diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2023-09-20 09:46:19 -0400 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2023-09-20 13:03:14 -0400 |
commit | 0bd961634ad5561c205fa003ab5414578fa7dd54 (patch) | |
tree | 0085180c9694290f1af3d222bc351cef56c21973 | |
parent | 53d834a7fae3afffebb45a2d66908f705773a7fc (diff) | |
download | gcc-0bd961634ad5561c205fa003ab5414578fa7dd54.zip gcc-0bd961634ad5561c205fa003ab5414578fa7dd54.tar.gz gcc-0bd961634ad5561c205fa003ab5414578fa7dd54.tar.bz2 |
[frange] Remove special casing from unordered operators.
In coming up with testcases for the unordered folders, I realized that
we were already handling them correctly, even in the absence of my
work in this area lately.
All of the unordered fold_range() methods try to fold with the ordered
variants first, and if they return TRUE, we are guaranteed to be able
to fold, even in the presence of NANs. For example:
if (x_5 >= y_8)
if (x_5 __UNLE y_8)
On the true side of the first conditional we know that either x_5 < y_8
or that one or more operands is a NAN. Since UNLE_EXPR returns true
for precisely this scenario, we can fold as true.
This is handled in the fold_range() methods as follows:
if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
op2_no_nan, trio))
return false;
// The result is the same as the ordered version when the
// comparison is true or when the operands cannot be NANs.
if (!maybe_isnan (op1, op2) || r == range_true (type))
return true;
This code has been there since the last release, and makes the special
casing I am deleting obsolete. I have added tests to make sure we
keep track of this behavior.
gcc/ChangeLog:
* range-op-float.cc (foperator_unordered_ge::fold_range): Remove
special casing.
(foperator_unordered_gt::fold_range): Same.
(foperator_unordered_lt::fold_range): Same.
(foperator_unordered_le::fold_range): Same.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/vrp-float-relations-5.c: New test.
* gcc.dg/tree-ssa/vrp-float-relations-6.c: New test.
-rw-r--r-- | gcc/range-op-float.cc | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c | 54 |
3 files changed, 112 insertions, 16 deletions
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 399deee..0951bd3 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -1644,10 +1644,7 @@ public: const frange &op1, const frange &op2, relation_trio trio = TRIO_VARYING) const final override { - relation_kind rel = trio.op1_op2 (); - - if (op1.known_isnan () || op2.known_isnan () - || rel == VREL_LT) + if (op1.known_isnan () || op2.known_isnan ()) { r = range_true (type); return true; @@ -1759,10 +1756,7 @@ public: const frange &op1, const frange &op2, relation_trio trio = TRIO_VARYING) const final override { - relation_kind rel = trio.op1_op2 (); - - if (op1.known_isnan () || op2.known_isnan () - || rel == VREL_LE) + if (op1.known_isnan () || op2.known_isnan ()) { r = range_true (type); return true; @@ -1870,10 +1864,7 @@ public: const frange &op1, const frange &op2, relation_trio trio = TRIO_VARYING) const final override { - relation_kind rel = trio.op1_op2 (); - - if (op1.known_isnan () || op2.known_isnan () - || rel == VREL_GT) + if (op1.known_isnan () || op2.known_isnan ()) { r = range_true (type); return true; @@ -1985,10 +1976,7 @@ public: const frange &op1, const frange &op2, relation_trio trio = TRIO_VARYING) const final override { - relation_kind rel = trio.op1_op2 (); - - if (op1.known_isnan () || op2.known_isnan () - || rel == VREL_GE) + if (op1.known_isnan () || op2.known_isnan ()) { r = range_true (type); return true; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c new file mode 100644 index 0000000..2bd06c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c @@ -0,0 +1,54 @@ +// { dg-do compile } +// { dg-options "-O2 -fgimple -fdump-tree-evrp" } + +void link_error(); + +void __GIMPLE (ssa,startwith("evrp")) +foo1 (float x, float y) +{ + __BB(2): + if (x_4(D) <= y_5(D)) + goto __BB5; + else + goto __BB3; + + __BB(3): + // Relation at this point is VREL_GT. + if (x_4(D) __UNGE y_5(D)) + goto __BB5; + else + goto __BB4; + + __BB(4): + link_error (); + goto __BB5; + + __BB(5): + return; +} + +void __GIMPLE (ssa,startwith("evrp")) +foo2 (float x, float y) +{ + __BB(2): + if (x_4(D) <= y_5(D)) + goto __BB5; + else + goto __BB3; + + __BB(3): + // Relation at this point is VREL_GT. + if (x_4(D) __UNGT y_5(D)) + goto __BB5; + else + goto __BB4; + + __BB(4): + link_error (); + goto __BB5; + + __BB(5): + return; +} + +// { dg-final { scan-tree-dump-not "link_error" "evrp" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c new file mode 100644 index 0000000..a75ae5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c @@ -0,0 +1,54 @@ +// { dg-do compile } +// { dg-options "-O2 -fgimple -fdump-tree-evrp" } + +void link_error(); + +void __GIMPLE (ssa,startwith("evrp")) +foo1 (float x, float y) +{ + __BB(2): + if (x_4(D) >= y_5(D)) + goto __BB5; + else + goto __BB3; + + __BB(3): + // Relation at this point is VREL_LT. + if (x_4(D) __UNLT y_5(D)) + goto __BB5; + else + goto __BB4; + + __BB(4): + link_error (); + goto __BB5; + + __BB(5): + return; +} + +void __GIMPLE (ssa,startwith("evrp")) +foo2 (float x, float y) +{ + __BB(2): + if (x_4(D) >= y_5(D)) + goto __BB5; + else + goto __BB3; + + __BB(3): + // Relation at this point is VREL_LT. + if (x_4(D) __UNLE y_5(D)) + goto __BB5; + else + goto __BB4; + + __BB(4): + link_error (); + goto __BB5; + + __BB(5): + return; +} + +// { dg-final { scan-tree-dump-not "link_error" "evrp" } } |