diff options
author | liuhongt <hongtao.liu@intel.com> | 2024-05-21 16:57:17 +0800 |
---|---|---|
committer | liuhongt <hongtao.liu@intel.com> | 2024-06-05 12:08:35 +0800 |
commit | b05288d1f1e4b632eddf8830b4369d4659f6c2ff (patch) | |
tree | b8f475d6293176e73e9d1894bb3dcf08e4ffee20 | |
parent | 4638e508aa814d4aa2e204c3ab041c6a56aad2bd (diff) | |
download | gcc-b05288d1f1e4b632eddf8830b4369d4659f6c2ff.zip gcc-b05288d1f1e4b632eddf8830b4369d4659f6c2ff.tar.gz gcc-b05288d1f1e4b632eddf8830b4369d4659f6c2ff.tar.bz2 |
Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
According to IEEE standard, for conversions from floating point to
integer. When a NaN or infinite operand cannot be represented in the
destination format and this cannot otherwise be indicated, the invalid
operation exception shall be signaled. When a numeric operand would
convert to an integer outside the range of the destination format, the
invalid operation exception shall be signaled if this situation cannot
otherwise be indicated.
The patch prevent simplication of the conversion from floating point
to integer for NAN/INF/out-of-range constant when flag_trapping_math.
gcc/ChangeLog:
PR rtl-optimization/100927
PR rtl-optimization/115161
PR rtl-optimization/115115
* simplify-rtx.cc (simplify_const_unary_operation): Prevent
simplication of FIX/UNSIGNED_FIX for NAN/INF/out-of-range
constant when flag_trapping_math.
* fold-const.cc (fold_convert_const_int_from_real): Don't fold
for overflow value when_trapping_math.
gcc/testsuite/ChangeLog:
* gcc.dg/pr100927.c: New test.
* c-c++-common/Wconversion-1.c: Add -fno-trapping-math.
* c-c++-common/dfp/convert-int-saturate.c: Ditto.
* g++.dg/ubsan/pr63956.C: Ditto.
* g++.dg/warn/Wconversion-real-integer.C: Ditto.
* gcc.c-torture/execute/20031003-1.c: Ditto.
* gcc.dg/Wconversion-complex-c99.c: Ditto.
* gcc.dg/Wconversion-real-integer.c: Ditto.
* gcc.dg/c90-const-expr-11.c: Ditto.
* gcc.dg/overflow-warn-8.c: Ditto.
-rw-r--r-- | gcc/fold-const.cc | 13 | ||||
-rw-r--r-- | gcc/simplify-rtx.cc | 23 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/Wconversion-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/pr63956.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20031003-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wconversion-complex-c99.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wconversion-real-integer.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c90-const-expr-11.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/overflow-warn-8.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr100927.c | 31 |
12 files changed, 77 insertions, 11 deletions
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 92b048c..710d697 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -2246,7 +2246,18 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg if (! overflow) val = real_to_integer (&r, &overflow, TYPE_PRECISION (type)); - t = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (arg1)); + /* According to IEEE standard, for conversions from floating point to + integer. When a NaN or infinite operand cannot be represented in the + destination format and this cannot otherwise be indicated, the invalid + operation exception shall be signaled. When a numeric operand would + convert to an integer outside the range of the destination format, the + invalid operation exception shall be signaled if this situation cannot + otherwise be indicated. */ + if (!flag_trapping_math || !overflow) + t = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (arg1)); + else + t = NULL_TREE; + return t; } diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 5caf1df..f6b4d73 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -2256,14 +2256,25 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, switch (code) { case FIX: + /* According to IEEE standard, for conversions from floating point to + integer. When a NaN or infinite operand cannot be represented in + the destination format and this cannot otherwise be indicated, the + invalid operation exception shall be signaled. When a numeric + operand would convert to an integer outside the range of the + destination format, the invalid operation exception shall be + signaled if this situation cannot otherwise be indicated. */ if (REAL_VALUE_ISNAN (*x)) - return const0_rtx; + return flag_trapping_math ? NULL_RTX : const0_rtx; + + if (REAL_VALUE_ISINF (*x) && flag_trapping_math) + return NULL_RTX; /* Test against the signed upper bound. */ wmax = wi::max_value (width, SIGNED); real_from_integer (&t, VOIDmode, wmax, SIGNED); if (real_less (&t, x)) - return immed_wide_int_const (wmax, mode); + return (flag_trapping_math + ? NULL_RTX : immed_wide_int_const (wmax, mode)); /* Test against the signed lower bound. */ wmin = wi::min_value (width, SIGNED); @@ -2276,13 +2287,17 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, case UNSIGNED_FIX: if (REAL_VALUE_ISNAN (*x) || REAL_VALUE_NEGATIVE (*x)) - return const0_rtx; + return flag_trapping_math ? NULL_RTX : const0_rtx; + + if (REAL_VALUE_ISINF (*x) && flag_trapping_math) + return NULL_RTX; /* Test against the unsigned upper bound. */ wmax = wi::max_value (width, UNSIGNED); real_from_integer (&t, VOIDmode, wmax, UNSIGNED); if (real_less (&t, x)) - return immed_wide_int_const (wmax, mode); + return (flag_trapping_math + ? NULL_RTX : immed_wide_int_const (wmax, mode)); return immed_wide_int_const (real_to_integer (x, &fail, width), mode); diff --git a/gcc/testsuite/c-c++-common/Wconversion-1.c b/gcc/testsuite/c-c++-common/Wconversion-1.c index 81f9498..9d874d1 100644 --- a/gcc/testsuite/c-c++-common/Wconversion-1.c +++ b/gcc/testsuite/c-c++-common/Wconversion-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Wconversion" } */ +/* { dg-options "-Wconversion -fno-trapping-math" } */ typedef char T; diff --git a/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c b/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c index 2d01f99..6b362c2 100644 --- a/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c +++ b/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c @@ -2,6 +2,7 @@ C99 6.3.1.4(1a) New. Test integer saturation. */ +/* { dg-options "-fno-trapping-math" } */ #ifndef __STDC_WANT_DEC_FP__ #define __STDC_WANT_DEC_FP__ 1 #endif diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C index 6fd0b4f..9c15dbd 100644 --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C @@ -1,6 +1,6 @@ // PR sanitizer/63956 // { dg-do compile } -// { dg-options "-std=c++14 -fsanitize=undefined,float-divide-by-zero,float-cast-overflow" } +// { dg-options "-std=c++14 -fsanitize=undefined,float-divide-by-zero" } #define SA(X) static_assert((X),#X) #define INT_MIN (-__INT_MAX__ - 1) @@ -162,8 +162,13 @@ fn11 (double d) return i * 2; } +void +__attribute__((optimize("no-trapping-math"))) +foo () +{ constexpr int r1 = fn11 (3.4); constexpr int r2 = fn11 (__builtin_inf ()); // { dg-message "in .constexpr. expansion of " } +} constexpr int fn12 (int i) diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C index 3b6d1f3..d6332140 100644 --- a/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C +++ b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C @@ -3,7 +3,7 @@ gcc/testsuite/gcc.dg/Wconversion-real-integer.c */ /* { dg-do compile } -/* { dg-options "-Wconversion -ftrack-macro-expansion=0" } */ +/* { dg-options "-Wconversion -ftrack-macro-expansion=0 -fno-trapping-math" } */ /* { dg-require-effective-target int32plus } */ #include <limits.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/20031003-1.c b/gcc/testsuite/gcc.c-torture/execute/20031003-1.c index 5d39d79..5e6f508 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20031003-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20031003-1.c @@ -1,5 +1,7 @@ /* PR optimization/9325 */ +/* { dg-additional-options "-fno-trapping-math" } */ + #include <limits.h> extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c b/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c index e8bc9db..69281c7 100644 --- a/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c +++ b/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c @@ -6,7 +6,7 @@ /* { dg-do compile } */ /* { dg-skip-if "doubles are floats,ints are 16bits" { "avr-*-*" } } */ -/* { dg-options " -std=c99 -pedantic -Wconversion " } */ +/* { dg-options " -std=c99 -pedantic -Wconversion -fno-trapping-math" } */ /* { dg-require-effective-target int32plus } */ /* { dg-require-effective-target double64plus } */ diff --git a/gcc/testsuite/gcc.dg/Wconversion-real-integer.c b/gcc/testsuite/gcc.dg/Wconversion-real-integer.c index 92e6987..ca6007f 100644 --- a/gcc/testsuite/gcc.dg/Wconversion-real-integer.c +++ b/gcc/testsuite/gcc.dg/Wconversion-real-integer.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-skip-if "doubles are floats,ints are 16bits" { "avr-*-*" } } */ -/* { dg-options "-std=c99 -Wconversion" } */ +/* { dg-options "-std=c99 -Wconversion -fno-trapping-math" } */ /* { dg-require-effective-target int32plus } */ /* { dg-require-effective-target double64plus } */ #include <limits.h> diff --git a/gcc/testsuite/gcc.dg/c90-const-expr-11.c b/gcc/testsuite/gcc.dg/c90-const-expr-11.c index a2720c4..65aab10 100644 --- a/gcc/testsuite/gcc.dg/c90-const-expr-11.c +++ b/gcc/testsuite/gcc.dg/c90-const-expr-11.c @@ -2,7 +2,7 @@ constant expressions. */ /* Origin: Joseph Myers <joseph@codesourcery.com> */ /* { dg-do compile } */ -/* { dg-options "-std=iso9899:1990 -pedantic-errors -O2" } */ +/* { dg-options "-std=iso9899:1990 -pedantic-errors -O2 -fno-trapping-math" } */ #include <float.h> #include <limits.h> diff --git a/gcc/testsuite/gcc.dg/overflow-warn-8.c b/gcc/testsuite/gcc.dg/overflow-warn-8.c index e76bcac..75bfa74 100644 --- a/gcc/testsuite/gcc.dg/overflow-warn-8.c +++ b/gcc/testsuite/gcc.dg/overflow-warn-8.c @@ -1,5 +1,6 @@ #include <limits.h> +/* { dg-options " -fno-trapping-math" } */ void foo (int j) { int i1 = (int)(double)1.0 + INT_MAX; /* { dg-warning "integer overflow" } */ diff --git a/gcc/testsuite/gcc.dg/pr100927.c b/gcc/testsuite/gcc.dg/pr100927.c new file mode 100644 index 0000000..ea0e627 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr100927.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftrapping-math -fdump-tree-optimized -fdump-rtl-final" } */ +/* { dg-final { scan-tree-dump-times {(?n)= \(int\)} 3 "optimized" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)\(fix:SI} 3 "final" } } */ + +int +foo_ofr () +{ + union {float a; + int b;}c; + c.b = 0x4f000000; + return (int)c.a; +} + +int +foo_inf () +{ + union {float a; + int b;}c; + c.b = 0xff800000; + return (int)c.a; +} + +int +foo_nan () +{ + union {float a; + int b;}c; + c.b = 0xff800001; + return (int)c.a; +} |