[PR106967] frange: revamp relational operators for NANs.
authorAldy Hernandez <aldyh@redhat.com>
Tue, 20 Sep 2022 14:19:14 +0000 (16:19 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Wed, 21 Sep 2022 09:06:57 +0000 (11:06 +0200)
commitd2278da1c3cb7bf8b3d96c86dbef2982bf4cc54a
treebc0bd39f8caa2202ec73ca9e4bf8cd4655c2c4b3
parentce8aed75a38b468490ecab4c318e3eb08d468608
[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.
gcc/range-op-float.cc
gcc/testsuite/gcc.dg/tree-ssa/pr106967.c [new file with mode: 0644]