https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128129

liu zhenyu <lzy20000419 at outlook dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
      Known to work|                            |7.5.0
      Known to fail|                            |10.5.0, 11.5.0, 12.5.0,
                   |                            |13.4.0, 14.2.0, 14.4.0,
                   |                            |15.3.0, 16.2.0, 17.0,
                   |                            |8.5.0, 9.5.0

--- Comment #1 from liu zhenyu <lzy20000419 at outlook dot com> ---
I looked at where this goes wrong. ifcombine calls maybe_fold_and_comparisons
for (v == 0) && (a != b), where v is a PHI of two a < b. and_comparisons_1
takes the invert path, and and_var_with_comparison rewrites !v & (a != b) as
!(v | (a == b)). or_comparisons_1 folds v | (a == b) to a <= b, which is right.
Then canonicalize_bool negates it:

gcc/gimple-fold.cc:6569 (14.2), :7246 (trunk):

        return fold_build2 (invert_tree_comparison (TREE_CODE (expr), false),

honor_nans is hard-coded to false, so !(a <= b) becomes a > b instead of a u>
b. The same hard-coded false is used for code2 in and_var_with_comparison (14.2
:6731, trunk :7408) and or_var_with_comparison (14.2 :7208, trunk :9381). With
-fno-trapping-math, for example, !(a<b) && a<=b becomes a u== b.

Suggested fix: pass HONOR_NANS (TREE_OPERAND (expr, 0)) (or of op2a for code2)
in these three places, and return NULL_TREE when invert_tree_comparison returns
ERROR_MARK. I tested this on 14.2: the testcase passes at -O1/-O2/-O3, and a
512-function NaN compare test I have shows no differences against -O0, with and
without -fno-trapping-math. Valid folds such as !(a<b) && a<=b to a == b are
still done.

Reply via email to