--- /dev/null
+// PR tree-optimization/94589
+// { dg-do compile { target c++20 } }
+// { dg-require-effective-target inf }
+// { dg-options "-O2 -g0 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|>|>=) \[ij]_\[0-9]+\\(D\\)" 8 "optimized" } }
+// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|>|>=) 5\\.0" 8 "optimized" } }
+
+#include <compare>
+
+#define A __attribute__((noipa))
+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 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 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 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; }
--- /dev/null
+// { dg-do run { target c++20 } }
+// { dg-require-effective-target inf }
+// { dg-options "-O2 -g" }
+
+#include "pr94589-5.C"
+
+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 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 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 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 f25 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::unordered; }
+A bool f26 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::unordered; }
+A bool f27 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::unordered; }
+A bool f28 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::unordered; }
+
+#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 (f1, __builtin_nan (""), 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 (f2, __builtin_nan (""), 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 (f3, __builtin_nan (""), 8.0, false);
+ C (f4, 7.0, 8.0, true);
+ C (f4, 8.0, 8.0, false);
+ C (f4, 9.0, 8.0, false);
+ C (f4, __builtin_nan (""), 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 (f5, __builtin_nan (""), 8.0, false);
+ C (f6, 7.0, 8.0, true);
+ C (f6, 8.0, 8.0, true);
+ C (f6, 9.0, 8.0, false);
+ C (f6, __builtin_nan (""), 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 (f7, __builtin_nan (""), 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 (f8, __builtin_nan (""), 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 (f9, __builtin_nan (""), 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 (f10, __builtin_nan (""), 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 (f11, __builtin_nan (""), 8.0, false);
+ C (f12, 7.0, 8.0, true);
+ C (f12, 8.0, 8.0, true);
+ C (f12, 9.0, 8.0, false);
+ C (f12, __builtin_nan (""), 8.0, true);
+ D (f13, 4.0, false);
+ D (f13, 5.0, true);
+ D (f13, 6.0, false);
+ D (f13, __builtin_nan (""), false);
+ D (f14, 4.0, true);
+ D (f14, 5.0, false);
+ D (f14, 6.0, true);
+ D (f14, __builtin_nan (""), true);
+ D (f15, 4.0, false);
+ D (f15, 5.0, false);
+ D (f15, 6.0, true);
+ D (f15, __builtin_nan (""), false);
+ D (f16, 4.0, true);
+ D (f16, 5.0, false);
+ D (f16, 6.0, false);
+ D (f16, __builtin_nan (""), false);
+ D (f17, 4.0, false);
+ D (f17, 5.0, true);
+ D (f17, 6.0, true);
+ D (f17, __builtin_nan (""), false);
+ D (f18, 4.0, true);
+ D (f18, 5.0, true);
+ D (f18, 6.0, false);
+ D (f18, __builtin_nan (""), false);
+ D (f19, 4.0, true);
+ D (f19, 5.0, false);
+ D (f19, 6.0, false);
+ D (f19, __builtin_nan (""), false);
+ D (f20, 4.0, false);
+ D (f20, 5.0, true);
+ D (f20, 6.0, true);
+ D (f20, __builtin_nan (""), true);
+ D (f21, 4.0, false);
+ D (f21, 5.0, true);
+ D (f21, 6.0, false);
+ D (f21, __builtin_nan (""), false);
+ D (f22, 4.0, true);
+ D (f22, 5.0, false);
+ D (f22, 6.0, true);
+ D (f22, __builtin_nan (""), true);
+ D (f23, 4.0, false);
+ D (f23, 5.0, false);
+ D (f23, 6.0, true);
+ D (f23, __builtin_nan (""), false);
+ D (f24, 4.0, true);
+ D (f24, 5.0, true);
+ D (f24, 6.0, false);
+ D (f24, __builtin_nan (""), true);
+ C (f25, 7.0, 8.0, false);
+ C (f25, 8.0, 8.0, false);
+ C (f25, 9.0, 8.0, false);
+ C (f25, __builtin_nan (""), 8.0, true);
+ C (f26, 7.0, 8.0, true);
+ C (f26, 8.0, 8.0, true);
+ C (f26, 9.0, 8.0, true);
+ C (f26, __builtin_nan (""), 8.0, false);
+ D (f27, 4.0, false);
+ D (f27, 5.0, false);
+ D (f27, 6.0, false);
+ D (f27, __builtin_nan (""), true);
+ D (f28, 4.0, true);
+ D (f28, 5.0, true);
+ D (f28, 6.0, true);
+ D (f28, __builtin_nan (""), false);
+}
--- /dev/null
+/* PR tree-optimization/94589 */
+/* { dg-do compile { target inf } } */
+/* { 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\\) (?:<|<=|>|>=) 5\\.0" 14 "optimized" } } */
+
+#define A __attribute__((noipa))
+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 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; }
+A int f29 (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) == 0; }
+A int f30 (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) != 0; }
+A int f31 (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) == 0; }
+A int f32 (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) != 0; }
--- /dev/null
+/* { dg-do run { target inf } } */
+/* { dg-options "-O2 -g" } */
+
+#include "pr94589-5.c"
+
+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 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; }
+
+#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 (f1, __builtin_nan (""), 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 (f2, __builtin_nan (""), 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 (f3, __builtin_nan (""), 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 (f4, __builtin_nan (""), 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 (f5, __builtin_nan (""), 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 (f6, __builtin_nan (""), 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 (f7, __builtin_nan (""), 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 (f8, __builtin_nan (""), 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 (f9, __builtin_nan (""), 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 (f10, __builtin_nan (""), 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 (f11, __builtin_nan (""), 8.0, 0);
+ C (f12, 7.0, 8.0, 1);
+ C (f12, 8.0, 8.0, 1);
+ C (f12, 9.0, 8.0, 0);
+ C (f12, __builtin_nan (""), 8.0, 1);
+ C (f13, 7.0, 8.0, 1);
+ C (f13, 8.0, 8.0, 1);
+ C (f13, 9.0, 8.0, 0);
+ C (f13, __builtin_nan (""), 8.0, 0);
+ C (f14, 7.0, 8.0, 0);
+ C (f14, 8.0, 8.0, 0);
+ C (f14, 9.0, 8.0, 1);
+ C (f14, __builtin_nan (""), 8.0, 1);
+ D (f15, 4.0, 0);
+ D (f15, 5.0, 1);
+ D (f15, 6.0, 0);
+ D (f15, __builtin_nan (""), 0);
+ D (f16, 4.0, 1);
+ D (f16, 5.0, 0);
+ D (f16, 6.0, 1);
+ D (f16, __builtin_nan (""), 1);
+ D (f17, 4.0, 0);
+ D (f17, 5.0, 0);
+ D (f17, 6.0, 1);
+ D (f17, __builtin_nan (""), 1);
+ D (f18, 4.0, 1);
+ D (f18, 5.0, 0);
+ D (f18, 6.0, 0);
+ D (f18, __builtin_nan (""), 0);
+ D (f19, 4.0, 0);
+ D (f19, 5.0, 1);
+ D (f19, 6.0, 1);
+ D (f19, __builtin_nan (""), 1);
+ D (f20, 4.0, 1);
+ D (f20, 5.0, 1);
+ D (f20, 6.0, 0);
+ D (f20, __builtin_nan (""), 0);
+ D (f21, 4.0, 1);
+ D (f21, 5.0, 0);
+ D (f21, 6.0, 0);
+ D (f21, __builtin_nan (""), 0);
+ D (f22, 4.0, 0);
+ D (f22, 5.0, 1);
+ D (f22, 6.0, 1);
+ D (f22, __builtin_nan (""), 1);
+ D (f23, 4.0, 0);
+ D (f23, 5.0, 1);
+ D (f23, 6.0, 1);
+ D (f23, __builtin_nan (""), 1);
+ D (f24, 4.0, 1);
+ D (f24, 5.0, 0);
+ D (f24, 6.0, 0);
+ D (f24, __builtin_nan (""), 0);
+ D (f25, 4.0, 0);
+ D (f25, 5.0, 0);
+ D (f25, 6.0, 1);
+ D (f25, __builtin_nan (""), 0);
+ D (f26, 4.0, 1);
+ D (f26, 5.0, 1);
+ D (f26, 6.0, 0);
+ D (f26, __builtin_nan (""), 1);
+ D (f27, 4.0, 1);
+ D (f27, 5.0, 1);
+ D (f27, 6.0, 0);
+ D (f27, __builtin_nan (""), 0);
+ D (f28, 4.0, 0);
+ D (f28, 5.0, 0);
+ D (f28, 6.0, 1);
+ D (f28, __builtin_nan (""), 1);
+ C (f29, 7.0, 8.0, 0);
+ C (f29, 8.0, 8.0, 1);
+ C (f29, 9.0, 8.0, 1);
+ C (f29, __builtin_nan (""), 8.0, 0);
+ C (f30, 7.0, 8.0, 1);
+ C (f30, 8.0, 8.0, 0);
+ C (f30, 9.0, 8.0, 0);
+ C (f30, __builtin_nan (""), 8.0, 1);
+ D (f31, 4.0, 0);
+ D (f31, 5.0, 1);
+ D (f31, 6.0, 1);
+ D (f31, __builtin_nan (""), 0);
+ D (f32, 4.0, 1);
+ D (f32, 5.0, 0);
+ D (f32, 6.0, 0);
+ D (f32, __builtin_nan (""), 1);
+ return 0;
+}
}
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))
{
if (absu_hwi (tree_to_shwi (arg2)) != 1)
return false;
+ if ((cond2_phi_edge->flags & EDGE_FALSE_VALUE)
+ && HONOR_NANS (TREE_TYPE (lhs1)))
+ return false;
if (e1->flags & EDGE_TRUE_VALUE)
{
if (tree_to_shwi (arg0) != 2
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 the true and false edges are swapped, it is not. */
+ or the true and false edges are swapped, it is not.
+ For HONOR_NANS, the edge flags are irrelevant and the comparisons
+ must be different for non-swapped operands and same for swapped
+ operands. */
if ((lhs2 == lhs1)
- ^ (((cond2_phi_edge->flags
- & ((cmp2 == LT_EXPR || cmp2 == LE_EXPR)
- ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0)
- != ((e1->flags
- & ((cmp1 == LT_EXPR || cmp1 == LE_EXPR)
- ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0)))
+ ^ (HONOR_NANS (TREE_TYPE (lhs1))
+ ? ((cmp2 == LT_EXPR || cmp2 == LE_EXPR)
+ != (cmp1 == LT_EXPR || cmp1 == LE_EXPR))
+ : (((cond2_phi_edge->flags
+ & ((cmp2 == LT_EXPR || cmp2 == LE_EXPR)
+ ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0)
+ != ((e1->flags
+ & ((cmp1 == LT_EXPR || cmp1 == LE_EXPR)
+ ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0))))
return false;
if (!single_pred_p (cond2_bb) || !cond_only_block_p (cond2_bb))
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))
+ || wi::to_widest (arg0) == wi::to_widest (arg1)
+ || HONOR_NANS (TREE_TYPE (lhs1)))
return false;
if (!integer_zerop (arg3) || (cmp3 != EQ_EXPR && cmp3 != NE_EXPR))
one_cmp = GT_EXPR;
enum tree_code res_cmp;
+ bool negate_p = false;
switch (cmp)
{
case EQ_EXPR:
- if (integer_zerop (rhs))
+ if (integer_zerop (rhs) && !HONOR_NANS (TREE_TYPE (lhs1)))
res_cmp = EQ_EXPR;
else if (integer_minus_onep (rhs))
res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
return false;
break;
case NE_EXPR:
- if (integer_zerop (rhs))
+ if (integer_zerop (rhs) && !HONOR_NANS (TREE_TYPE (lhs1)))
res_cmp = NE_EXPR;
else if (integer_minus_onep (rhs))
res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
else
return false;
+ if (HONOR_NANS (TREE_TYPE (lhs1)))
+ negate_p = true;
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;
+ {
+ if (HONOR_NANS (TREE_TYPE (lhs1)) && orig_use_lhs)
+ negate_p = true;
+ res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+ }
else
return false;
break;
res_cmp = one_cmp;
else
return false;
+ if (HONOR_NANS (TREE_TYPE (lhs1)))
+ negate_p = true;
break;
case GE_EXPR:
if (integer_zerop (rhs))
- res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+ {
+ if (HONOR_NANS (TREE_TYPE (lhs1)) && !orig_use_lhs)
+ negate_p = true;
+ res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+ }
else if (integer_onep (rhs))
- res_cmp = one_cmp;
+ {
+ if (HONOR_NANS (TREE_TYPE (lhs1)))
+ negate_p = true;
+ res_cmp = one_cmp;
+ }
else
return false;
break;
gcc_unreachable ();
}
+ tree clhs1 = lhs1, crhs1 = rhs1;
+ if (negate_p)
+ {
+ if (cfun->can_throw_non_call_exceptions)
+ return false;
+ res_cmp = invert_tree_comparison (res_cmp, false);
+ clhs1 = make_ssa_name (boolean_type_node);
+ gimple *g = gimple_build_assign (clhs1, res_cmp, lhs1, rhs1);
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ crhs1 = boolean_false_node;
+ res_cmp = EQ_EXPR;
+ }
+
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);
+ gimple_cond_set_lhs (use_cond, clhs1);
+ gimple_cond_set_rhs (use_cond, crhs1);
}
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);
+ gimple_assign_set_rhs1 (use_stmt, clhs1);
+ gimple_assign_set_rhs2 (use_stmt, crhs1);
}
else
{
tree cond = build2 (res_cmp, TREE_TYPE (gimple_assign_rhs1 (use_stmt)),
- lhs1, rhs1);
+ clhs1, crhs1);
gimple_assign_set_rhs1 (use_stmt, cond);
}
update_stmt (use_stmt);
# 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. */
+ Ignore the value of 2 if !HONOR_NANS, because if NaNs
+ aren't expected, all floating point numbers should be
+ comparable. If HONOR_NANS, emit something like:
+ # DEBUG D#1 => i_2(D) < j_3(D) ? -1 : 2
+ # DEBUG D#2 => i_2(D) > j_3(D) ? 1 : D#1
+ # DEBUG D#3 => i_2(D) == j_3(D) ? 0 : D#2
+ instead. */
gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
tree type = TREE_TYPE (phires);
+ tree minus_one = build_int_cst (type, -1);
+ if (HONOR_NANS (TREE_TYPE (lhs1)))
+ {
+ tree temp3 = build_debug_expr_decl (type);
+ tree t = build2 (one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR,
+ boolean_type_node, lhs1, rhs2);
+ t = build3 (COND_EXPR, type, t, minus_one,
+ build_int_cst (type, 2));
+ gimple *g = gimple_build_debug_bind (temp3, t, phi);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ minus_one = temp3;
+ }
tree temp1 = build_debug_expr_decl (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));
+ minus_one);
gimple *g = gimple_build_debug_bind (temp1, t, phi);
gsi_insert_before (&gsi, g, GSI_SAME_STMT);
tree temp2 = build_debug_expr_decl (type);
replace_uses_by (phires, temp2);
if (orig_use_lhs)
{
- if (has_cast_debug_uses)
+ if (has_cast_debug_uses
+ || (HONOR_NANS (TREE_TYPE (lhs1)) && !is_cast))
{
tree temp3 = make_node (DEBUG_EXPR_DECL);
DECL_ARTIFICIAL (temp3) = 1;
TREE_TYPE (temp3) = TREE_TYPE (orig_use_lhs);
SET_DECL_MODE (temp3, TYPE_MODE (type));
- t = fold_convert (TREE_TYPE (temp3), temp2);
+ if (has_cast_debug_uses)
+ t = fold_convert (TREE_TYPE (temp3), temp2);
+ else
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (temp3),
+ temp2, build_int_cst (TREE_TYPE (temp3),
+ ~1));
g = gimple_build_debug_bind (temp3, t, phi);
gsi_insert_before (&gsi, g, GSI_SAME_STMT);
replace_uses_by (orig_use_lhs, temp3);