[PR106967] frange: revamp relational operators for NANs.
Since NANs can be inserted by other passes even for -ffinite-math-only,
we can't depend on the flag to determine if a NAN is a possiblity.
Instead, we must explicitly check for them.
In the case of -ffinite-math-only, paths leading up to a NAN are
undefined and can be considered unreachable. I have audited all the
relational code and made sure we're handling the known NAN case before
anything else, setting undefined when appropriate.
In the process, I revamped all the relational code handling NANs to
correctly notice paths that are unreachable.
The basic structure for ordered relational operators (except != of
course) is this:
If either operand is a known NAN, return FALSE.
The true side of a relop when one operand is a NAN is
unreachable.
On the false side of a relop when one operand is a NAN, we
know nothing about the other operand.
Regstrapped on x86-64 and ppc64le Linux.
lapack testing on x86-64 with and without -ffinite-math-only.
PR tree-optimization/106967
gcc/ChangeLog:
* range-op-float.cc (foperator_equal::fold_range): Adjust for NAN.
(foperator_equal::op1_range): Same.
(foperator_not_equal::fold_range): Same.
(foperator_not_equal::op1_range): Same.
(foperator_lt::fold_range): Same.
(foperator_lt::op1_range): Same.
(foperator_lt::op2_range): Same.
(foperator_le::fold_range): Same.
(foperator_le::op1_range): Same.
(foperator_le::op2_range): Same.
(foperator_gt::fold_range): Same.
(foperator_gt::op1_range): Same.
(foperator_gt::op2_range): Same.
(foperator_ge::fold_range): Same.
(foperator_ge::op1_range): Same.
(foperator_ge::op2_range): Same.
(foperator_unordered::op1_range): Same.
(foperator_ordered::fold_range): Same.
(foperator_ordered::op1_range): Same.
(build_le): Assert that we don't have a NAN.
(build_lt): Same.
(build_gt): Same.
(build_ge): Same.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/pr106967.c: New test.