]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
authorliuhongt <hongtao.liu@intel.com>
Tue, 21 May 2024 08:57:17 +0000 (16:57 +0800)
committerliuhongt <hongtao.liu@intel.com>
Wed, 5 Jun 2024 04:08:35 +0000 (12:08 +0800)
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.

12 files changed:
gcc/fold-const.cc
gcc/simplify-rtx.cc
gcc/testsuite/c-c++-common/Wconversion-1.c
gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c
gcc/testsuite/g++.dg/ubsan/pr63956.C
gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C
gcc/testsuite/gcc.c-torture/execute/20031003-1.c
gcc/testsuite/gcc.dg/Wconversion-complex-c99.c
gcc/testsuite/gcc.dg/Wconversion-real-integer.c
gcc/testsuite/gcc.dg/c90-const-expr-11.c
gcc/testsuite/gcc.dg/overflow-warn-8.c
gcc/testsuite/gcc.dg/pr100927.c [new file with mode: 0644]

index 92b048c307e291446c5de521ae9b6f8b710682e9..710d697c0217c784b34f9f9f7b00b1945369076a 100644 (file)
@@ -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;
 }
 
index 5caf1dfd957fe1a5f5d7264d5e69a523a748be2f..f6b4d73b593c21fb7cc0c09aec0da2b3f86ad302 100644 (file)
@@ -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);
index 81f9498d07c658bca6902dd256a997f288a4343c..9d874d195481d192efa70538590a1eb9d49e991d 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-Wconversion" } */
+/* { dg-options "-Wconversion -fno-trapping-math" } */
 
 typedef char T;
 
index 2d01f99468bfb47f4e36dc4fd2bfe59d32f3e28e..6b362c2aa9595212b6df0c0940b24a59006e314a 100644 (file)
@@ -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
index 6fd0b4f893ec954c57c755fbe1f7ae72a21204c6..9c15dbd8d540c492a7a469386832590444220269 100644 (file)
@@ -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)
index 3b6d1f3c437c0af837f7906c1f11e3e05c71fd19..d6332140b140ac0a5bd8fb21ce63b75a995826a0 100644 (file)
@@ -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>
 
index 5d39d799e50447d610368d561eb959595f5a8f50..5e6f5089fc64b56423d269fc7834b3e995aa0d6d 100644 (file)
@@ -1,5 +1,7 @@
 /* PR optimization/9325  */
 
+/* { dg-additional-options "-fno-trapping-math" } */
+
 #include <limits.h>
 
 extern void abort (void);
index e8bc9db237d10d32e5e596dc2031f04808753519..69281c7d71eebe029b25eaf65b4d555bb0962cf4 100644 (file)
@@ -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 } */
 
index 92e6987d9ec3c2884c1d1105a94dcafc9cdff787..ca6007f4fe8c418d604b1e26aed8f7dc5d777511 100644 (file)
@@ -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>
index a2720c47bf4c0c00ce4ae310d58b02f74a3dc358..65aab10a129ff22e6d946d322918b638672e7ad4 100644 (file)
@@ -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>
index e76bcac5e0789e8d087d8cb8431dd248542fd37f..75bfa74f3dc42ade3509505c47bb21d8df427858 100644 (file)
@@ -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 (file)
index 0000000..ea0e627
--- /dev/null
@@ -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;
+}