I've been investigating some (float)i == CST optimizations for match.pd, and noticed there's already a TODO comment in match.pd that's relatively easy to implement. When CST is a NaN, we only need to worry about exceptions with flag_trapping_math, and equality/inequality tests for sNaN only behave differently to qNaN with -fsignaling-nans. These issues are related to PR 57371 and PR 106805 in bugzilla.
This patch has been tested on x86_64-pc-linux-gnu with make bootstrap and make -k check, both with and without --target_board=unix{-m32} with no new failures. Ok for mainline? 2024-07-17 Roger Sayle <ro...@nextmovesoftware.com> gcc/ChangeLog * match.pd ((FTYPE) N CMP CST): Only worry about exceptions with flag_trapping_math, and about signaling NaNs with HONOR_SNANS. gcc/testsuite/ChangeLog * c-c++-common/pr57371-4.c: Update comment. * c-c++-common/pr57371-5.c: Add missing testcases from pr57371-4.c and update for -fno-singnaling-nans -fno-trapping-math. Thanks in advance, Roger --
diff --git a/gcc/match.pd b/gcc/match.pd index 7fff7b5..2ab3bb3 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6823,13 +6823,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) tree itype = TREE_TYPE (@0); format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1)))); const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1); - /* Be careful to preserve any potential exceptions due to - NaNs. qNaNs are ok in == or != context. - TODO: relax under -fno-trapping-math or - -fno-signaling-nans. */ - bool exception_p - = real_isnan (cst) && (cst->signalling - || (cmp != EQ_EXPR && cmp != NE_EXPR)); + /* Be careful to preserve any potential exceptions due to NaNs. + qNaNs are ok in == or != context. */ + bool exception_p = real_isnan (cst) + && flag_trapping_math + && ((cmp != EQ_EXPR && cmp != NE_EXPR) + || (cst->signalling + && HONOR_SNANS (TREE_TYPE (@1)))); } /* TODO: allow non-fitting itype and SNaNs when -fno-trapping-math. */ diff --git a/gcc/testsuite/c-c++-common/pr57371-4.c b/gcc/testsuite/c-c++-common/pr57371-4.c index f43f7c2..b0e539d 100644 --- a/gcc/testsuite/c-c++-common/pr57371-4.c +++ b/gcc/testsuite/c-c++-common/pr57371-4.c @@ -2,9 +2,7 @@ /* { dg-options "-O -fsignaling-nans -fdump-tree-original" } */ /* We can not get rid of comparison in tests below because of - pending NaN exceptions. - - TODO: avoid under -fno-trapping-math. */ + pending NaN exceptions. */ #define QNAN __builtin_nanf ("0") #define SNAN __builtin_nansf ("0") diff --git a/gcc/testsuite/c-c++-common/pr57371-5.c b/gcc/testsuite/c-c++-common/pr57371-5.c index 8e18b0a..77decbe 100644 --- a/gcc/testsuite/c-c++-common/pr57371-5.c +++ b/gcc/testsuite/c-c++-common/pr57371-5.c @@ -2,11 +2,10 @@ /* { dg-options "-O -fno-signaling-nans -fno-trapping-math -fdump-tree-original" } */ /* We can not get rid of comparison in tests below because of - pending NaN exceptions. - - TODO: avoid under -fno-trapping-math. */ + pending NaN exceptions. */ #define QNAN __builtin_nanf ("0") +#define SNAN __builtin_nansf ("0") void nonfinite(unsigned short x) { { @@ -34,6 +33,43 @@ void nonfinite(unsigned short x) { } { + volatile int nonfinite_5; + nonfinite_5 = (float) x > SNAN; + /* { dg-final { scan-tree-dump "nonfinite_5 = 0" "original" } } */ + } + + { + volatile int nonfinite_6; + nonfinite_6 = (float) x >= SNAN; + /* { dg-final { scan-tree-dump "nonfinite_6 = 0" "original" } } */ + } + + { + volatile int nonfinite_7; + nonfinite_7 = (float) x < SNAN; + /* { dg-final { scan-tree-dump "nonfinite_7 = 0" "original" } } */ + } + + { + volatile int nonfinite_8; + nonfinite_8 = (float) x <= SNAN; + /* { dg-final { scan-tree-dump "nonfinite_8 = 0" "original" } } */ + } + + { + volatile int nonfinite_9; + nonfinite_9 = (float) x == SNAN; + /* { dg-final { scan-tree-dump "nonfinite_9 = 0" "original" } } */ + } + + { + volatile int nonfinite_10; + nonfinite_10 = (float) x != SNAN; + /* { dg-final { scan-tree-dump "nonfinite_10 = 1" "original" } } * + */ + } + + { volatile int nonfinite_11; nonfinite_11 = (float) x == QNAN; /* { dg-final { scan-tree-dump "nonfinite_11 = 0" "original" } } */