1 Star 0 Fork 132

wangding16/src-gcc

forked from src-openEuler/gcc 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch 36.36 KB
一键复制 编辑 原始数据 按行查看 历史
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
From 02313ab8cf7eb4defc1482ece48c07c2d8c77be9 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Thu, 6 May 2021 10:15:40 +0200
Subject: [PATCH 08/35] [Backport] phiopt: Optimize (x <=> y) cmp z [PR94589]
Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=ad96c867e173c1ebcfc201b201adac5095683a08
genericize_spaceship genericizes i <=> j to approximately
({ int c; if (i == j) c = 0; else if (i < j) c = -1; else c = 1; c; })
for strong ordering and
({ int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; c; })
for partial ordering.
The C++ standard supports then == or != comparisons of that against
strong/partial ordering enums, or </<=/==/!=/>/>= comparisons of <=> result
against literal 0.
In some cases we already optimize that but in many cases we keep performing
all the 2 or 3 comparisons, compute the spaceship value and then compare
that.
The following patch recognizes those patterns if the <=> operands are
integral types or floating point (the latter only for -ffast-math) and
optimizes it to the single comparison that is needed (plus adds debug stmts
if needed for the spaceship result).
There is one thing I'd like to address in a follow-up: the pr94589-2.C
testcase should be matching just 12 times each, but runs
into operator>=(partial_ordering, unspecified) being defined as
(_M_value&1)==_M_value
rather than _M_value>=0. When not honoring NaNs, the 2 case should be
unreachable and so (_M_value&1)==_M_value is then equivalent to _M_value>=0,
but is not a single use but two uses. I'll need to pattern match that case
specially.
2021-05-06 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/94589
* tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Call
spaceship_replacement.
(cond_only_block_p, spaceship_replacement): New functions.
* gcc.dg/pr94589-1.c: New test.
* gcc.dg/pr94589-2.c: New test.
* gcc.dg/pr94589-3.c: New test.
* gcc.dg/pr94589-4.c: New test.
* g++.dg/opt/pr94589-1.C: New test.
* g++.dg/opt/pr94589-2.C: New test.
* g++.dg/opt/pr94589-3.C: New test.
* g++.dg/opt/pr94589-4.C: New test.
---
gcc/testsuite/g++.dg/opt/pr94589-1.C | 33 +++
gcc/testsuite/g++.dg/opt/pr94589-2.C | 33 +++
gcc/testsuite/g++.dg/opt/pr94589-3.C | 84 ++++++
gcc/testsuite/g++.dg/opt/pr94589-4.C | 84 ++++++
gcc/testsuite/gcc.dg/pr94589-1.c | 35 +++
gcc/testsuite/gcc.dg/pr94589-2.c | 35 +++
gcc/testsuite/gcc.dg/pr94589-3.c | 97 ++++++
gcc/testsuite/gcc.dg/pr94589-4.c | 97 ++++++
gcc/tree-ssa-phiopt.c | 424 +++++++++++++++++++++++++++
9 files changed, 922 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-1.C
create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-2.C
create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-3.C
create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-4.C
create mode 100644 gcc/testsuite/gcc.dg/pr94589-1.c
create mode 100644 gcc/testsuite/gcc.dg/pr94589-2.c
create mode 100644 gcc/testsuite/gcc.dg/pr94589-3.c
create mode 100644 gcc/testsuite/gcc.dg/pr94589-4.c
diff --git a/gcc/testsuite/g++.dg/opt/pr94589-1.C b/gcc/testsuite/g++.dg/opt/pr94589-1.C
new file mode 100644
index 000000000..d1cc5050c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr94589-1.C
@@ -0,0 +1,33 @@
+// PR tree-optimization/94589
+// { dg-do compile { target c++20 } }
+// { dg-options "-O2 -g0 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 12 "optimized" } }
+// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[45]" 12 "optimized" } }
+
+#include <compare>
+
+#define A __attribute__((noipa))
+A bool f1 (int i, int j) { auto c = i <=> j; return c == 0; }
+A bool f2 (int i, int j) { auto c = i <=> j; return c != 0; }
+A bool f3 (int i, int j) { auto c = i <=> j; return c > 0; }
+A bool f4 (int i, int j) { auto c = i <=> j; return c < 0; }
+A bool f5 (int i, int j) { auto c = i <=> j; return c >= 0; }
+A bool f6 (int i, int j) { auto c = i <=> j; return c <= 0; }
+A bool f7 (int i, int j) { auto c = i <=> j; return c == std::strong_ordering::less; }
+A bool f8 (int i, int j) { auto c = i <=> j; return c != std::strong_ordering::less; }
+A bool f9 (int i, int j) { auto c = i <=> j; return c == std::strong_ordering::equal; }
+A bool f10 (int i, int j) { auto c = i <=> j; return c != std::strong_ordering::equal; }
+A bool f11 (int i, int j) { auto c = i <=> j; return c == std::strong_ordering::greater; }
+A bool f12 (int i, int j) { auto c = i <=> j; return c != std::strong_ordering::greater; }
+A bool f13 (int i) { auto c = i <=> 5; return c == 0; }
+A bool f14 (int i) { auto c = i <=> 5; return c != 0; }
+A bool f15 (int i) { auto c = i <=> 5; return c > 0; }
+A bool f16 (int i) { auto c = i <=> 5; return c < 0; }
+A bool f17 (int i) { auto c = i <=> 5; return c >= 0; }
+A bool f18 (int i) { auto c = i <=> 5; return c <= 0; }
+A bool f19 (int i) { auto c = i <=> 5; return c == std::strong_ordering::less; }
+A bool f20 (int i) { auto c = i <=> 5; return c != std::strong_ordering::less; }
+A bool f21 (int i) { auto c = i <=> 5; return c == std::strong_ordering::equal; }
+A bool f22 (int i) { auto c = i <=> 5; return c != std::strong_ordering::equal; }
+A bool f23 (int i) { auto c = i <=> 5; return c == std::strong_ordering::greater; }
+A bool f24 (int i) { auto c = i <=> 5; return c != std::strong_ordering::greater; }
diff --git a/gcc/testsuite/g++.dg/opt/pr94589-2.C b/gcc/testsuite/g++.dg/opt/pr94589-2.C
new file mode 100644
index 000000000..dda947e22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr94589-2.C
@@ -0,0 +1,33 @@
+// PR tree-optimization/94589
+// { dg-do compile { target c++20 } }
+// { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } }
+// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 5\\.0" 14 "optimized" } }
+
+#include <compare>
+
+#define A __attribute__((noipa))
+A bool f1 (double i, double j) { auto c = i <=> j; return c == 0; }
+A bool f2 (double i, double j) { auto c = i <=> j; return c != 0; }
+A bool f3 (double i, double j) { auto c = i <=> j; return c > 0; }
+A bool f4 (double i, double j) { auto c = i <=> j; return c < 0; }
+A bool f5 (double i, double j) { auto c = i <=> j; return c >= 0; }
+A bool f6 (double i, double j) { auto c = i <=> j; return c <= 0; }
+A bool f7 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::less; }
+A bool f8 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::less; }
+A bool f9 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::equivalent; }
+A bool f10 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::equivalent; }
+A bool f11 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::greater; }
+A bool f12 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::greater; }
+A bool f13 (double i) { auto c = i <=> 5.0; return c == 0; }
+A bool f14 (double i) { auto c = i <=> 5.0; return c != 0; }
+A bool f15 (double i) { auto c = i <=> 5.0; return c > 0; }
+A bool f16 (double i) { auto c = i <=> 5.0; return c < 0; }
+A bool f17 (double i) { auto c = i <=> 5.0; return c >= 0; }
+A bool f18 (double i) { auto c = i <=> 5.0; return c <= 0; }
+A bool f19 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::less; }
+A bool f20 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::less; }
+A bool f21 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::equivalent; }
+A bool f22 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::equivalent; }
+A bool f23 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::greater; }
+A bool f24 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::greater; }
diff --git a/gcc/testsuite/g++.dg/opt/pr94589-3.C b/gcc/testsuite/g++.dg/opt/pr94589-3.C
new file mode 100644
index 000000000..725b81f56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr94589-3.C
@@ -0,0 +1,84 @@
+// { dg-do run { target c++20 } }
+// { dg-options "-O2 -g" }
+
+#include "pr94589-1.C"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+ C (f1, 7, 8, false);
+ C (f1, 8, 8, true);
+ C (f1, 9, 8, false);
+ C (f2, 7, 8, true);
+ C (f2, 8, 8, false);
+ C (f2, 9, 8, true);
+ C (f3, 7, 8, false);
+ C (f3, 8, 8, false);
+ C (f3, 9, 8, true);
+ C (f4, 7, 8, true);
+ C (f4, 8, 8, false);
+ C (f4, 9, 8, false);
+ C (f5, 7, 8, false);
+ C (f5, 8, 8, true);
+ C (f5, 9, 8, true);
+ C (f6, 7, 8, true);
+ C (f6, 8, 8, true);
+ C (f6, 9, 8, false);
+ C (f7, 7, 8, true);
+ C (f7, 8, 8, false);
+ C (f7, 9, 8, false);
+ C (f8, 7, 8, false);
+ C (f8, 8, 8, true);
+ C (f8, 9, 8, true);
+ C (f9, 7, 8, false);
+ C (f9, 8, 8, true);
+ C (f9, 9, 8, false);
+ C (f10, 7, 8, true);
+ C (f10, 8, 8, false);
+ C (f10, 9, 8, true);
+ C (f11, 7, 8, false);
+ C (f11, 8, 8, false);
+ C (f11, 9, 8, true);
+ C (f12, 7, 8, true);
+ C (f12, 8, 8, true);
+ C (f12, 9, 8, false);
+ D (f13, 4, false);
+ D (f13, 5, true);
+ D (f13, 6, false);
+ D (f14, 4, true);
+ D (f14, 5, false);
+ D (f14, 6, true);
+ D (f15, 4, false);
+ D (f15, 5, false);
+ D (f15, 6, true);
+ D (f16, 4, true);
+ D (f16, 5, false);
+ D (f16, 6, false);
+ D (f17, 4, false);
+ D (f17, 5, true);
+ D (f17, 6, true);
+ D (f18, 4, true);
+ D (f18, 5, true);
+ D (f18, 6, false);
+ D (f19, 4, true);
+ D (f19, 5, false);
+ D (f19, 6, false);
+ D (f20, 4, false);
+ D (f20, 5, true);
+ D (f20, 6, true);
+ D (f21, 4, false);
+ D (f21, 5, true);
+ D (f21, 6, false);
+ D (f22, 4, true);
+ D (f22, 5, false);
+ D (f22, 6, true);
+ D (f23, 4, false);
+ D (f23, 5, false);
+ D (f23, 6, true);
+ D (f24, 4, true);
+ D (f24, 5, true);
+ D (f24, 6, false);
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr94589-4.C b/gcc/testsuite/g++.dg/opt/pr94589-4.C
new file mode 100644
index 000000000..256a45580
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr94589-4.C
@@ -0,0 +1,84 @@
+// { dg-do run { target c++20 } }
+// { dg-options "-O2 -g -ffast-math" }
+
+#include "pr94589-2.C"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+ C (f1, 7.0, 8.0, false);
+ C (f1, 8.0, 8.0, true);
+ C (f1, 9.0, 8.0, false);
+ C (f2, 7.0, 8.0, true);
+ C (f2, 8.0, 8.0, false);
+ C (f2, 9.0, 8.0, true);
+ C (f3, 7.0, 8.0, false);
+ C (f3, 8.0, 8.0, false);
+ C (f3, 9.0, 8.0, true);
+ C (f4, 7.0, 8.0, true);
+ C (f4, 8.0, 8.0, false);
+ C (f4, 9.0, 8.0, false);
+ C (f5, 7.0, 8.0, false);
+ C (f5, 8.0, 8.0, true);
+ C (f5, 9.0, 8.0, true);
+ C (f6, 7.0, 8.0, true);
+ C (f6, 8.0, 8.0, true);
+ C (f6, 9.0, 8.0, false);
+ C (f7, 7.0, 8.0, true);
+ C (f7, 8.0, 8.0, false);
+ C (f7, 9.0, 8.0, false);
+ C (f8, 7.0, 8.0, false);
+ C (f8, 8.0, 8.0, true);
+ C (f8, 9.0, 8.0, true);
+ C (f9, 7.0, 8.0, false);
+ C (f9, 8.0, 8.0, true);
+ C (f9, 9.0, 8.0, false);
+ C (f10, 7.0, 8.0, true);
+ C (f10, 8.0, 8.0, false);
+ C (f10, 9.0, 8.0, true);
+ C (f11, 7.0, 8.0, false);
+ C (f11, 8.0, 8.0, false);
+ C (f11, 9.0, 8.0, true);
+ C (f12, 7.0, 8.0, true);
+ C (f12, 8.0, 8.0, true);
+ C (f12, 9.0, 8.0, false);
+ D (f13, 4.0, false);
+ D (f13, 5.0, true);
+ D (f13, 6.0, false);
+ D (f14, 4.0, true);
+ D (f14, 5.0, false);
+ D (f14, 6.0, true);
+ D (f15, 4.0, false);
+ D (f15, 5.0, false);
+ D (f15, 6.0, true);
+ D (f16, 4.0, true);
+ D (f16, 5.0, false);
+ D (f16, 6.0, false);
+ D (f17, 4.0, false);
+ D (f17, 5.0, true);
+ D (f17, 6.0, true);
+ D (f18, 4.0, true);
+ D (f18, 5.0, true);
+ D (f18, 6.0, false);
+ D (f19, 4.0, true);
+ D (f19, 5.0, false);
+ D (f19, 6.0, false);
+ D (f20, 4.0, false);
+ D (f20, 5.0, true);
+ D (f20, 6.0, true);
+ D (f21, 4.0, false);
+ D (f21, 5.0, true);
+ D (f21, 6.0, false);
+ D (f22, 4.0, true);
+ D (f22, 5.0, false);
+ D (f22, 6.0, true);
+ D (f23, 4.0, false);
+ D (f23, 5.0, false);
+ D (f23, 6.0, true);
+ D (f24, 4.0, true);
+ D (f24, 5.0, true);
+ D (f24, 6.0, false);
+}
diff --git a/gcc/testsuite/gcc.dg/pr94589-1.c b/gcc/testsuite/gcc.dg/pr94589-1.c
new file mode 100644
index 000000000..de404ea82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94589-1.c
@@ -0,0 +1,35 @@
+/* PR tree-optimization/94589 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g0 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[45]" 14 "optimized" } } */
+
+#define A __attribute__((noipa))
+A int f1 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == 0; }
+A int f2 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != 0; }
+A int f3 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c > 0; }
+A int f4 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c < 0; }
+A int f5 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c >= 0; }
+A int f6 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c <= 0; }
+A int f7 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == -1; }
+A int f8 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != -1; }
+A int f9 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c > -1; }
+A int f10 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c <= -1; }
+A int f11 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == 1; }
+A int f12 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != 1; }
+A int f13 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c < 1; }
+A int f14 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c >= 1; }
+A int f15 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == 0; }
+A int f16 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != 0; }
+A int f17 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c > 0; }
+A int f18 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c < 0; }
+A int f19 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c >= 0; }
+A int f20 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c <= 0; }
+A int f21 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == -1; }
+A int f22 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != -1; }
+A int f23 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c > -1; }
+A int f24 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c <= -1; }
+A int f25 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == 1; }
+A int f26 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != 1; }
+A int f27 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c < 1; }
+A int f28 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c >= 1; }
diff --git a/gcc/testsuite/gcc.dg/pr94589-2.c b/gcc/testsuite/gcc.dg/pr94589-2.c
new file mode 100644
index 000000000..9481b764d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94589-2.c
@@ -0,0 +1,35 @@
+/* PR tree-optimization/94589 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 5\\.0" 14 "optimized" } } */
+
+#define A __attribute__((noipa))
+A int f1 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c == 0; }
+A int f2 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c != 0; }
+A int f3 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c > 0; }
+A int f4 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c < 0; }
+A int f5 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c >= 0; }
+A int f6 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c <= 0; }
+A int f7 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c == -1; }
+A int f8 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c != -1; }
+A int f9 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c > -1; }
+A int f10 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c <= -1; }
+A int f11 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c == 1; }
+A int f12 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c != 1; }
+A int f13 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c < 1; }
+A int f14 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c >= 1; }
+A int f15 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c == 0; }
+A int f16 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c != 0; }
+A int f17 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c > 0; }
+A int f18 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c < 0; }
+A int f19 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c >= 0; }
+A int f20 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c <= 0; }
+A int f21 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c == -1; }
+A int f22 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c != -1; }
+A int f23 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c > -1; }
+A int f24 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c <= -1; }
+A int f25 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c == 1; }
+A int f26 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c != 1; }
+A int f27 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c < 1; }
+A int f28 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c >= 1; }
diff --git a/gcc/testsuite/gcc.dg/pr94589-3.c b/gcc/testsuite/gcc.dg/pr94589-3.c
new file mode 100644
index 000000000..df82fab73
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94589-3.c
@@ -0,0 +1,97 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -g" } */
+
+#include "pr94589-1.c"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+ C (f1, 7, 8, 0);
+ C (f1, 8, 8, 1);
+ C (f1, 9, 8, 0);
+ C (f2, 7, 8, 1);
+ C (f2, 8, 8, 0);
+ C (f2, 9, 8, 1);
+ C (f3, 7, 8, 0);
+ C (f3, 8, 8, 0);
+ C (f3, 9, 8, 1);
+ C (f4, 7, 8, 1);
+ C (f4, 8, 8, 0);
+ C (f4, 9, 8, 0);
+ C (f5, 7, 8, 0);
+ C (f5, 8, 8, 1);
+ C (f5, 9, 8, 1);
+ C (f6, 7, 8, 1);
+ C (f6, 8, 8, 1);
+ C (f6, 9, 8, 0);
+ C (f7, 7, 8, 1);
+ C (f7, 8, 8, 0);
+ C (f7, 9, 8, 0);
+ C (f8, 7, 8, 0);
+ C (f8, 8, 8, 1);
+ C (f8, 9, 8, 1);
+ C (f9, 7, 8, 0);
+ C (f9, 8, 8, 1);
+ C (f9, 9, 8, 1);
+ C (f10, 7, 8, 1);
+ C (f10, 8, 8, 0);
+ C (f10, 9, 8, 0);
+ C (f11, 7, 8, 0);
+ C (f11, 8, 8, 0);
+ C (f11, 9, 8, 1);
+ C (f12, 7, 8, 1);
+ C (f12, 8, 8, 1);
+ C (f12, 9, 8, 0);
+ C (f13, 7, 8, 1);
+ C (f13, 8, 8, 1);
+ C (f13, 9, 8, 0);
+ C (f14, 7, 8, 0);
+ C (f14, 8, 8, 0);
+ C (f14, 9, 8, 1);
+ D (f15, 4, 0);
+ D (f15, 5, 1);
+ D (f15, 6, 0);
+ D (f16, 4, 1);
+ D (f16, 5, 0);
+ D (f16, 6, 1);
+ D (f17, 4, 0);
+ D (f17, 5, 0);
+ D (f17, 6, 1);
+ D (f18, 4, 1);
+ D (f18, 5, 0);
+ D (f18, 6, 0);
+ D (f19, 4, 0);
+ D (f19, 5, 1);
+ D (f19, 6, 1);
+ D (f20, 4, 1);
+ D (f20, 5, 1);
+ D (f20, 6, 0);
+ D (f21, 4, 1);
+ D (f21, 5, 0);
+ D (f21, 6, 0);
+ D (f22, 4, 0);
+ D (f22, 5, 1);
+ D (f22, 6, 1);
+ D (f23, 4, 0);
+ D (f23, 5, 1);
+ D (f23, 6, 1);
+ D (f24, 4, 1);
+ D (f24, 5, 0);
+ D (f24, 6, 0);
+ D (f25, 4, 0);
+ D (f25, 5, 0);
+ D (f25, 6, 1);
+ D (f26, 4, 1);
+ D (f26, 5, 1);
+ D (f26, 6, 0);
+ D (f27, 4, 1);
+ D (f27, 5, 1);
+ D (f27, 6, 0);
+ D (f28, 4, 0);
+ D (f28, 5, 0);
+ D (f28, 6, 1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr94589-4.c b/gcc/testsuite/gcc.dg/pr94589-4.c
new file mode 100644
index 000000000..b2557fb07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94589-4.c
@@ -0,0 +1,97 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -g -ffast-math" } */
+
+#include "pr94589-2.c"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+ C (f1, 7.0, 8.0, 0);
+ C (f1, 8.0, 8.0, 1);
+ C (f1, 9.0, 8.0, 0);
+ C (f2, 7.0, 8.0, 1);
+ C (f2, 8.0, 8.0, 0);
+ C (f2, 9.0, 8.0, 1);
+ C (f3, 7.0, 8.0, 0);
+ C (f3, 8.0, 8.0, 0);
+ C (f3, 9.0, 8.0, 1);
+ C (f4, 7.0, 8.0, 1);
+ C (f4, 8.0, 8.0, 0);
+ C (f4, 9.0, 8.0, 0);
+ C (f5, 7.0, 8.0, 0);
+ C (f5, 8.0, 8.0, 1);
+ C (f5, 9.0, 8.0, 1);
+ C (f6, 7.0, 8.0, 1);
+ C (f6, 8.0, 8.0, 1);
+ C (f6, 9.0, 8.0, 0);
+ C (f7, 7.0, 8.0, 1);
+ C (f7, 8.0, 8.0, 0);
+ C (f7, 9.0, 8.0, 0);
+ C (f8, 7.0, 8.0, 0);
+ C (f8, 8.0, 8.0, 1);
+ C (f8, 9.0, 8.0, 1);
+ C (f9, 7.0, 8.0, 0);
+ C (f9, 8.0, 8.0, 1);
+ C (f9, 9.0, 8.0, 1);
+ C (f10, 7.0, 8.0, 1);
+ C (f10, 8.0, 8.0, 0);
+ C (f10, 9.0, 8.0, 0);
+ C (f11, 7.0, 8.0, 0);
+ C (f11, 8.0, 8.0, 0);
+ C (f11, 9.0, 8.0, 1);
+ C (f12, 7.0, 8.0, 1);
+ C (f12, 8.0, 8.0, 1);
+ C (f12, 9.0, 8.0, 0);
+ C (f13, 7.0, 8.0, 1);
+ C (f13, 8.0, 8.0, 1);
+ C (f13, 9.0, 8.0, 0);
+ C (f14, 7.0, 8.0, 0);
+ C (f14, 8.0, 8.0, 0);
+ C (f14, 9.0, 8.0, 1);
+ D (f15, 4.0, 0);
+ D (f15, 5.0, 1);
+ D (f15, 6.0, 0);
+ D (f16, 4.0, 1);
+ D (f16, 5.0, 0);
+ D (f16, 6.0, 1);
+ D (f17, 4.0, 0);
+ D (f17, 5.0, 0);
+ D (f17, 6.0, 1);
+ D (f18, 4.0, 1);
+ D (f18, 5.0, 0);
+ D (f18, 6.0, 0);
+ D (f19, 4.0, 0);
+ D (f19, 5.0, 1);
+ D (f19, 6.0, 1);
+ D (f20, 4.0, 1);
+ D (f20, 5.0, 1);
+ D (f20, 6.0, 0);
+ D (f21, 4.0, 1);
+ D (f21, 5.0, 0);
+ D (f21, 6.0, 0);
+ D (f22, 4.0, 0);
+ D (f22, 5.0, 1);
+ D (f22, 6.0, 1);
+ D (f23, 4.0, 0);
+ D (f23, 5.0, 1);
+ D (f23, 6.0, 1);
+ D (f24, 4.0, 1);
+ D (f24, 5.0, 0);
+ D (f24, 6.0, 0);
+ D (f25, 4.0, 0);
+ D (f25, 5.0, 0);
+ D (f25, 6.0, 1);
+ D (f26, 4.0, 1);
+ D (f26, 5.0, 1);
+ D (f26, 6.0, 0);
+ D (f27, 4.0, 1);
+ D (f27, 5.0, 1);
+ D (f27, 6.0, 0);
+ D (f28, 4.0, 0);
+ D (f28, 5.0, 0);
+ D (f28, 6.0, 1);
+ return 0;
+}
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index b9cd07a60..fca32222f 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -63,6 +63,8 @@ static bool abs_replacement (basic_block, basic_block,
edge, edge, gimple *, tree, tree);
static bool xor_replacement (basic_block, basic_block,
edge, edge, gimple *, tree, tree);
+static bool spaceship_replacement (basic_block, basic_block,
+ edge, edge, gphi *, tree, tree);
static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
edge, edge, gimple *,
tree, tree);
@@ -361,6 +363,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
cfgchanged = true;
else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true;
+ else if (spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ cfgchanged = true;
}
}
@@ -1753,6 +1757,426 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
return true;
}
+/* Return true if the only executable statement in BB is a GIMPLE_COND. */
+
+static bool
+cond_only_block_p (basic_block bb)
+{
+ /* BB must have no executable statements. */
+ gimple_stmt_iterator gsi = gsi_after_labels (bb);
+ if (phi_nodes (bb))
+ return false;
+ while (!gsi_end_p (gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (is_gimple_debug (stmt))
+ ;
+ else if (gimple_code (stmt) == GIMPLE_NOP
+ || gimple_code (stmt) == GIMPLE_PREDICT
+ || gimple_code (stmt) == GIMPLE_COND)
+ ;
+ else
+ return false;
+ gsi_next (&gsi);
+ }
+ return true;
+}
+
+/* Attempt to optimize (x <=> y) cmp 0 and similar comparisons.
+ For strong ordering <=> try to match something like:
+ <bb 2> : // cond3_bb (== cond2_bb)
+ if (x_4(D) != y_5(D))
+ goto <bb 3>; [INV]
+ else
+ goto <bb 6>; [INV]
+
+ <bb 3> : // cond_bb
+ if (x_4(D) < y_5(D))
+ goto <bb 6>; [INV]
+ else
+ goto <bb 4>; [INV]
+
+ <bb 4> : // middle_bb
+
+ <bb 6> : // phi_bb
+ # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
+ _1 = iftmp.0_2 == 0;
+
+ and for partial ordering <=> something like:
+
+ <bb 2> : // cond3_bb
+ if (a_3(D) == b_5(D))
+ goto <bb 6>; [50.00%]
+ else
+ goto <bb 3>; [50.00%]
+
+ <bb 3> [local count: 536870913]: // cond2_bb
+ if (a_3(D) < b_5(D))
+ goto <bb 6>; [50.00%]
+ else
+ goto <bb 4>; [50.00%]
+
+ <bb 4> [local count: 268435456]: // cond_bb
+ if (a_3(D) > b_5(D))
+ goto <bb 6>; [50.00%]
+ else
+ goto <bb 5>; [50.00%]
+
+ <bb 5> [local count: 134217728]: // middle_bb
+
+ <bb 6> [local count: 1073741824]: // phi_bb
+ # SR.27_4 = PHI <0(2), -1(3), 1(4), 2(5)>
+ _2 = SR.27_4 > 0; */
+
+static bool
+spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
+ edge e0, edge e1, gphi *phi,
+ tree arg0, tree arg1)
+{
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (PHI_RESULT (phi)))
+ || TYPE_UNSIGNED (TREE_TYPE (PHI_RESULT (phi)))
+ || !tree_fits_shwi_p (arg0)
+ || !tree_fits_shwi_p (arg1)
+ || !IN_RANGE (tree_to_shwi (arg0), -1, 2)
+ || !IN_RANGE (tree_to_shwi (arg1), -1, 2))
+ return false;
+
+ basic_block phi_bb = gimple_bb (phi);
+ gcc_assert (phi_bb == e0->dest && phi_bb == e1->dest);
+ if (!IN_RANGE (EDGE_COUNT (phi_bb->preds), 3, 4))
+ return false;
+
+ use_operand_p use_p;
+ gimple *use_stmt;
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
+ return false;
+ if (!single_imm_use (PHI_RESULT (phi), &use_p, &use_stmt))
+ return false;
+ enum tree_code cmp;
+ tree lhs, rhs;
+ if (gimple_code (use_stmt) == GIMPLE_COND)
+ {
+ cmp = gimple_cond_code (use_stmt);
+ lhs = gimple_cond_lhs (use_stmt);
+ rhs = gimple_cond_rhs (use_stmt);
+ }
+ else if (is_gimple_assign (use_stmt))
+ {
+ if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
+ {
+ cmp = gimple_assign_rhs_code (use_stmt);
+ lhs = gimple_assign_rhs1 (use_stmt);
+ rhs = gimple_assign_rhs2 (use_stmt);
+ }
+ else if (gimple_assign_rhs_code (use_stmt) == COND_EXPR)
+ {
+ tree cond = gimple_assign_rhs1 (use_stmt);
+ if (!COMPARISON_CLASS_P (cond))
+ return false;
+ cmp = TREE_CODE (cond);
+ lhs = TREE_OPERAND (cond, 0);
+ rhs = TREE_OPERAND (cond, 1);
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+ switch (cmp)
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ break;
+ default:
+ return false;
+ }
+ if (lhs != PHI_RESULT (phi)
+ || !tree_fits_shwi_p (rhs)
+ || !IN_RANGE (tree_to_shwi (rhs), -1, 1))
+ return false;
+
+ if (!empty_block_p (middle_bb))
+ return false;
+
+ gcond *cond1 = as_a <gcond *> (last_stmt (cond_bb));
+ enum tree_code cmp1 = gimple_cond_code (cond1);
+ if (cmp1 != LT_EXPR && cmp1 != GT_EXPR)
+ return false;
+ tree lhs1 = gimple_cond_lhs (cond1);
+ tree rhs1 = gimple_cond_rhs (cond1);
+ /* The optimization may be unsafe due to NaNs. */
+ if (HONOR_NANS (TREE_TYPE (lhs1)))
+ return false;
+ if (TREE_CODE (lhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs1))
+ return false;
+ if (TREE_CODE (rhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
+ return false;
+
+ if (!single_pred_p (cond_bb) || !cond_only_block_p (cond_bb))
+ return false;
+
+ basic_block cond2_bb = single_pred (cond_bb);
+ if (EDGE_COUNT (cond2_bb->succs) != 2)
+ return false;
+ edge cond2_phi_edge;
+ if (EDGE_SUCC (cond2_bb, 0)->dest == cond_bb)
+ {
+ if (EDGE_SUCC (cond2_bb, 1)->dest != phi_bb)
+ return false;
+ cond2_phi_edge = EDGE_SUCC (cond2_bb, 1);
+ }
+ else if (EDGE_SUCC (cond2_bb, 0)->dest != phi_bb)
+ return false;
+ else
+ cond2_phi_edge = EDGE_SUCC (cond2_bb, 0);
+ tree arg2 = gimple_phi_arg_def (phi, cond2_phi_edge->dest_idx);
+ if (!tree_fits_shwi_p (arg2))
+ return false;
+ gimple *cond2 = last_stmt (cond2_bb);
+ if (cond2 == NULL || gimple_code (cond2) != GIMPLE_COND)
+ return false;
+ enum tree_code cmp2 = gimple_cond_code (cond2);
+ tree lhs2 = gimple_cond_lhs (cond2);
+ tree rhs2 = gimple_cond_rhs (cond2);
+ if (lhs2 == lhs1)
+ {
+ if (!operand_equal_p (rhs2, rhs1, 0))
+ return false;
+ }
+ else if (lhs2 == rhs1)
+ {
+ if (rhs2 != lhs1)
+ return false;
+ }
+ else
+ return false;
+
+ tree arg3 = arg2;
+ basic_block cond3_bb = cond2_bb;
+ edge cond3_phi_edge = cond2_phi_edge;
+ gimple *cond3 = cond2;
+ enum tree_code cmp3 = cmp2;
+ tree lhs3 = lhs2;
+ tree rhs3 = rhs2;
+ if (EDGE_COUNT (phi_bb->preds) == 4)
+ {
+ if (absu_hwi (tree_to_shwi (arg2)) != 1)
+ return false;
+ if (e1->flags & EDGE_TRUE_VALUE)
+ {
+ if (tree_to_shwi (arg0) != 2
+ || absu_hwi (tree_to_shwi (arg1)) != 1
+ || wi::to_widest (arg1) == wi::to_widest (arg2))
+ return false;
+ }
+ else if (tree_to_shwi (arg1) != 2
+ || absu_hwi (tree_to_shwi (arg0)) != 1
+ || wi::to_widest (arg0) == wi::to_widest (arg1))
+ return false;
+ if (cmp2 != LT_EXPR && cmp2 != GT_EXPR)
+ return false;
+ /* if (x < y) goto phi_bb; else fallthru;
+ if (x > y) goto phi_bb; else fallthru;
+ bbx:;
+ phi_bb:;
+ is ok, but if x and y are swapped in one of the comparisons,
+ or the comparisons are the same and operands not swapped,
+ or second goto phi_bb is not the true edge, it is not. */
+ if ((lhs2 == lhs1)
+ ^ (cmp2 == cmp1)
+ ^ ((e1->flags & EDGE_TRUE_VALUE) != 0))
+ return false;
+ if ((cond2_phi_edge->flags & EDGE_TRUE_VALUE) == 0)
+ return false;
+ if (!single_pred_p (cond2_bb) || !cond_only_block_p (cond2_bb))
+ return false;
+ cond3_bb = single_pred (cond2_bb);
+ if (EDGE_COUNT (cond2_bb->succs) != 2)
+ return false;
+ if (EDGE_SUCC (cond3_bb, 0)->dest == cond2_bb)
+ {
+ if (EDGE_SUCC (cond3_bb, 1)->dest != phi_bb)
+ return false;
+ cond3_phi_edge = EDGE_SUCC (cond3_bb, 1);
+ }
+ else if (EDGE_SUCC (cond3_bb, 0)->dest != phi_bb)
+ return false;
+ else
+ cond3_phi_edge = EDGE_SUCC (cond3_bb, 0);
+ arg3 = gimple_phi_arg_def (phi, cond3_phi_edge->dest_idx);
+ cond3 = last_stmt (cond3_bb);
+ if (cond3 == NULL || gimple_code (cond3) != GIMPLE_COND)
+ return false;
+ cmp3 = gimple_cond_code (cond3);
+ lhs3 = gimple_cond_lhs (cond3);
+ rhs3 = gimple_cond_rhs (cond3);
+ if (lhs3 == lhs1)
+ {
+ if (!operand_equal_p (rhs3, rhs1, 0))
+ return false;
+ }
+ else if (lhs3 == rhs1)
+ {
+ if (rhs3 != lhs1)
+ return false;
+ }
+ else
+ return false;
+ }
+ else if (absu_hwi (tree_to_shwi (arg0)) != 1
+ || absu_hwi (tree_to_shwi (arg1)) != 1
+ || wi::to_widest (arg0) == wi::to_widest (arg1))
+ return false;
+
+ if (!integer_zerop (arg3) || (cmp3 != EQ_EXPR && cmp3 != NE_EXPR))
+ return false;
+ if ((cond3_phi_edge->flags & (cmp3 == EQ_EXPR
+ ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) == 0)
+ return false;
+
+ /* lhs1 one_cmp rhs1 results in PHI_RESULT (phi) of 1. */
+ enum tree_code one_cmp;
+ if ((cmp1 == LT_EXPR)
+ ^ (!integer_onep ((e1->flags & EDGE_TRUE_VALUE) ? arg1 : arg0)))
+ one_cmp = LT_EXPR;
+ else
+ one_cmp = GT_EXPR;
+
+ enum tree_code res_cmp;
+ switch (cmp)
+ {
+ case EQ_EXPR:
+ if (integer_zerop (rhs))
+ res_cmp = EQ_EXPR;
+ else if (integer_minus_onep (rhs))
+ res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+ else if (integer_onep (rhs))
+ res_cmp = one_cmp;
+ else
+ return false;
+ break;
+ case NE_EXPR:
+ if (integer_zerop (rhs))
+ res_cmp = NE_EXPR;
+ else if (integer_minus_onep (rhs))
+ res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+ else if (integer_onep (rhs))
+ res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
+ else
+ return false;
+ break;
+ case LT_EXPR:
+ if (integer_onep (rhs))
+ res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
+ else if (integer_zerop (rhs))
+ res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+ else
+ return false;
+ break;
+ case LE_EXPR:
+ if (integer_zerop (rhs))
+ res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
+ else if (integer_minus_onep (rhs))
+ res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+ else
+ return false;
+ break;
+ case GT_EXPR:
+ if (integer_minus_onep (rhs))
+ res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+ else if (integer_zerop (rhs))
+ res_cmp = one_cmp;
+ else
+ return false;
+ break;
+ case GE_EXPR:
+ if (integer_zerop (rhs))
+ res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+ else if (integer_onep (rhs))
+ res_cmp = one_cmp;
+ else
+ return false;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (gimple_code (use_stmt) == GIMPLE_COND)
+ {
+ gcond *use_cond = as_a <gcond *> (use_stmt);
+ gimple_cond_set_code (use_cond, res_cmp);
+ gimple_cond_set_lhs (use_cond, lhs1);
+ gimple_cond_set_rhs (use_cond, rhs1);
+ }
+ else if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
+ {
+ gimple_assign_set_rhs_code (use_stmt, res_cmp);
+ gimple_assign_set_rhs1 (use_stmt, lhs1);
+ gimple_assign_set_rhs2 (use_stmt, rhs1);
+ }
+ else
+ {
+ tree cond = build2 (res_cmp, TREE_TYPE (gimple_assign_rhs1 (use_stmt)),
+ lhs1, rhs1);
+ gimple_assign_set_rhs1 (use_stmt, cond);
+ }
+ update_stmt (use_stmt);
+
+ if (MAY_HAVE_DEBUG_BIND_STMTS)
+ {
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ bool has_debug_uses = false;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, PHI_RESULT (phi))
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ gcc_assert (is_gimple_debug (use_stmt));
+ has_debug_uses = true;
+ break;
+ }
+
+ if (has_debug_uses)
+ {
+ /* If there are debug uses, emit something like:
+ # DEBUG D#1 => i_2(D) > j_3(D) ? 1 : -1
+ # DEBUG D#2 => i_2(D) == j_3(D) ? 0 : D#1
+ where > stands for the comparison that yielded 1
+ and replace debug uses of phi result with that D#2.
+ Ignore the value of 2, because if NaNs aren't expected,
+ all floating point numbers should be comparable. */
+ gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
+ tree type = TREE_TYPE (PHI_RESULT (phi));
+ tree temp1 = make_node (DEBUG_EXPR_DECL);
+ DECL_ARTIFICIAL (temp1) = 1;
+ TREE_TYPE (temp1) = type;
+ SET_DECL_MODE (temp1, TYPE_MODE (type));
+ tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
+ t = build3 (COND_EXPR, type, t, build_one_cst (type),
+ build_int_cst (type, -1));
+ gimple *g = gimple_build_debug_bind (temp1, t, phi);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ tree temp2 = make_node (DEBUG_EXPR_DECL);
+ DECL_ARTIFICIAL (temp2) = 1;
+ TREE_TYPE (temp2) = type;
+ SET_DECL_MODE (temp2, TYPE_MODE (type));
+ t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
+ t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
+ g = gimple_build_debug_bind (temp2, t, phi);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ replace_uses_by (PHI_RESULT (phi), temp2);
+ }
+ }
+
+ gimple_stmt_iterator psi = gsi_for_stmt (phi);
+ remove_phi_node (&psi, true);
+
+ return true;
+}
+
/* Convert
<bb 2>
--
2.27.0.windows.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wangding16/src-gcc.git
git@gitee.com:wangding16/src-gcc.git
wangding16
src-gcc
src-gcc
master

搜索帮助