diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2023-08-23 12:23:49 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2023-08-25 10:29:48 +0200 |
commit | 66be6ed81f369573824f1a8f5a3538a63472292f (patch) | |
tree | fd91217e8bc980cecf387c312d8d98dcaef15ce6 /gcc/ordered-hash-map-tests.cc | |
parent | a739bac402ea5a583e43dbd01c14ebaff317c885 (diff) | |
download | gcc-66be6ed81f369573824f1a8f5a3538a63472292f.zip gcc-66be6ed81f369573824f1a8f5a3538a63472292f.tar.gz gcc-66be6ed81f369573824f1a8f5a3538a63472292f.tar.bz2 |
[frange] Relax floating point relational folding.
This patch implements a new frelop_early_resolve() that handles the
NAN special cases instead of calling into the integer version which
can break for some combinations. Relaxing FP conditional folding in
this matter allows ranger to do a better job resulting in more
threading opportunities, among other things.
In auditing ranger versus DOM scoped tables I've noticed we are too
cautious when folding floating point conditionals involving
relationals. We refuse to fold anything if there is the possibility
of a NAN, but this is overly restrictive.
For example:
if (x_5 != y_8)
if (x_5 != y_8)
link_error ();
In range-ops, we fail to fold the second conditional because
frelop_early_resolve bails on anything that may have a NAN, but in the
above case the possibility of a NAN is inconsequential.
However, there are some cases where we must be careful, because a NAN
can complicate matters:
if (x_5 == x_5)
...
Here the operands to EQ_EXPR are the same so we get VREL_EQ as the
relation. However, we can't fold the conditional unless we know x_5
cannot be a NAN.
On the other hand, we can fold the second conditional here:
if (x_5 == x_5)
if (x_5 > x_5)
Because on the TRUE side of the first conditional we are guaranteed to
be free of NANs.
This patch is basically an inline of the integer version of
relop_early_resolve() with special casing for floats.
The main thing to keep in mind is that the relation coming into a
range-op entry may have a NAN, and for that one must look at the
operands. This makes the relations akin to unordered comparisons,
making VREL_LT behave like VREL_UNLT would.
The tricky corner cases are VREL_EQ and VREL_NE, as discussed above.
Apart from these that are special cased, the relation table for
intersect should work fine for returning a FALSE, even with NANs. The
union table, not so much and is documented in the code.
This allows us to add some optimizations for the unordered operators.
For example, a relation of VREL_LT on entry to an operator allows us
to fold an UNLT_EXPR as true, even with NANs because in this case
VREL_LT is really VREL_UNLT which maps perfectly.
BTW, we batted some ideas on how to get this work, and it seems this
is the cleaner route with the special cases nestled in the operators
themselves. Another idea is to add unordered relations, but that
would require bloating the various tables adding spots for VREL_UNEQ,
VREL_UNLT, etc, plus adding relations for VREL_UNORDERED so the
intersects work correctly. I'm not wed to either one, and we can
certainly revisit this if it becomes burdensome to maintain (or to get
right).
gcc/ChangeLog:
* range-op-float.cc (frelop_early_resolve): Rewrite for better NAN
handling.
(operator_not_equal::fold_range): Adjust for relations.
(operator_lt::fold_range): Same.
(operator_gt::fold_range): Same.
(foperator_unordered_equal::fold_range): Same.
(foperator_unordered_lt::fold_range): Same.
(foperator_unordered_le::fold_range): Same.
(foperator_unordered_gt::fold_range): Same.
(foperator_unordered_ge::fold_range): Same.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/vrp-float-12.c: New test.
Diffstat (limited to 'gcc/ordered-hash-map-tests.cc')
0 files changed, 0 insertions, 0 deletions