public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
@ 2024-05-22  1:57 liuhongt
  2024-05-22  7:46 ` Richard Biener
  0 siblings, 1 reply; 6+ messages in thread
From: liuhongt @ 2024-05-22  1:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: jakub, pinskia

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.

Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}
Ok for trunk?

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.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/pr100927.c: New test.
---
 gcc/simplify-rtx.cc                      | 23 ++++++++++++++++----
 gcc/testsuite/gcc.target/i386/pr100927.c | 27 ++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr100927.c

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 53f54d1d392..b7a770dad60 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/gcc.target/i386/pr100927.c b/gcc/testsuite/gcc.target/i386/pr100927.c
new file mode 100644
index 00000000000..b137396c30f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr100927.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2 -ftrapping-math" } */
+/* { dg-final { scan-assembler-times "cvttps2dq" 3 } }  */
+
+#include <emmintrin.h>
+
+__m128i foo_ofr() {
+  const __m128i iv = _mm_set_epi32(0x4f000000, 0x4f000000, 0x4f000000, 0x4f000000);
+  const __m128  fv = _mm_castsi128_ps(iv);
+  const __m128i riv = _mm_cvttps_epi32(fv);
+  return riv;
+}
+
+__m128i foo_nan() {
+  const __m128i iv = _mm_set_epi32(0xff800001, 0xff800001, 0xff800001, 0xff800001);
+  const __m128  fv = _mm_castsi128_ps(iv);
+  const __m128i riv = _mm_cvttps_epi32(fv);
+  return riv;
+}
+
+__m128i foo_inf() {
+  const __m128i iv = _mm_set_epi32(0xff800000, 0xff800000, 0xff800000, 0xff800000);
+  const __m128  fv = _mm_castsi128_ps(iv);
+  const __m128i riv = _mm_cvttps_epi32(fv);
+  return riv;
+}
+
-- 
2.31.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
  2024-05-22  1:57 [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX liuhongt
@ 2024-05-22  7:46 ` Richard Biener
  2024-05-22  7:59   ` Jakub Jelinek
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Biener @ 2024-05-22  7:46 UTC (permalink / raw)
  To: liuhongt; +Cc: gcc-patches, jakub, pinskia

On Wed, May 22, 2024 at 3:58 AM liuhongt <hongtao.liu@intel.com> wrote:
>
> 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.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}
> Ok for trunk?

OK if there are no further comments today.

Thanks,
Richard.

> 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.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/i386/pr100927.c: New test.
> ---
>  gcc/simplify-rtx.cc                      | 23 ++++++++++++++++----
>  gcc/testsuite/gcc.target/i386/pr100927.c | 27 ++++++++++++++++++++++++
>  2 files changed, 46 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr100927.c
>
> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
> index 53f54d1d392..b7a770dad60 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/gcc.target/i386/pr100927.c b/gcc/testsuite/gcc.target/i386/pr100927.c
> new file mode 100644
> index 00000000000..b137396c30f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr100927.c
> @@ -0,0 +1,27 @@
> +/* { dg-do compile } */
> +/* { dg-options "-msse2 -O2 -ftrapping-math" } */
> +/* { dg-final { scan-assembler-times "cvttps2dq" 3 } }  */
> +
> +#include <emmintrin.h>
> +
> +__m128i foo_ofr() {
> +  const __m128i iv = _mm_set_epi32(0x4f000000, 0x4f000000, 0x4f000000, 0x4f000000);
> +  const __m128  fv = _mm_castsi128_ps(iv);
> +  const __m128i riv = _mm_cvttps_epi32(fv);
> +  return riv;
> +}
> +
> +__m128i foo_nan() {
> +  const __m128i iv = _mm_set_epi32(0xff800001, 0xff800001, 0xff800001, 0xff800001);
> +  const __m128  fv = _mm_castsi128_ps(iv);
> +  const __m128i riv = _mm_cvttps_epi32(fv);
> +  return riv;
> +}
> +
> +__m128i foo_inf() {
> +  const __m128i iv = _mm_set_epi32(0xff800000, 0xff800000, 0xff800000, 0xff800000);
> +  const __m128  fv = _mm_castsi128_ps(iv);
> +  const __m128i riv = _mm_cvttps_epi32(fv);
> +  return riv;
> +}
> +
> --
> 2.31.1
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
  2024-05-22  7:46 ` Richard Biener
@ 2024-05-22  7:59   ` Jakub Jelinek
  2024-05-23  5:11     ` Hongtao Liu
  0 siblings, 1 reply; 6+ messages in thread
From: Jakub Jelinek @ 2024-05-22  7:59 UTC (permalink / raw)
  To: Richard Biener, Joseph S. Myers; +Cc: liuhongt, gcc-patches, pinskia

On Wed, May 22, 2024 at 09:46:41AM +0200, Richard Biener wrote:
> On Wed, May 22, 2024 at 3:58 AM liuhongt <hongtao.liu@intel.com> wrote:
> >
> > 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.
> >
> > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}
> > Ok for trunk?
> 
> OK if there are no further comments today.

As I wrote in the PR, I don't think this is the right fix for the PR,
the simplify-rtx.cc change is the right thing to do, the C standard
in F.4 says that the out of range conversions to integers should raise
exceptions, but still says that the resulting value in those cases is
unspecified.
So, for the C part we should verify that with -ftrapping-math we don't
constant fold it and cover it both by pure C and perhaps backend specific
testcases which just search asm for the conversion instructions
or even runtime test which tests that the exceptions are triggered,
verify that we don't fold it either during GIMPLE opts or RTL opts
(dunno whether they can be folded in e.g. C constant initializers or not).

And then on the backend side, it should stop using FIX/UNSIGNED_FIX RTLs
in patterns which are used for the intrinsics (and keep using them in
patterns used for C scalar/vector conversions), because even with
-fno-trapping-math the intrinsics should have the documented behavior,
particular result value, while in C they are clearly unspecified and
FIX/UNSIGNED_FIX folding even with the patch chooses some particular values
which don't match those (sure, they are like that because of Java, but am
not sure it is the right time to change what we do in those cases say
by providing a target hook to pick a different value).

The provided testcase tests the values though, so I think is inappropriate
for this patch.

	Jakub


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
  2024-05-22  7:59   ` Jakub Jelinek
@ 2024-05-23  5:11     ` Hongtao Liu
  2024-05-27  1:08       ` liuhongt
  0 siblings, 1 reply; 6+ messages in thread
From: Hongtao Liu @ 2024-05-23  5:11 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Biener, Joseph S. Myers, liuhongt, gcc-patches, pinskia

On Wed, May 22, 2024 at 3:59 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Wed, May 22, 2024 at 09:46:41AM +0200, Richard Biener wrote:
> > On Wed, May 22, 2024 at 3:58 AM liuhongt <hongtao.liu@intel.com> wrote:
> > >
> > > 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.
> > >
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}
> > > Ok for trunk?
> >
> > OK if there are no further comments today.
>
> As I wrote in the PR, I don't think this is the right fix for the PR,
> the simplify-rtx.cc change is the right thing to do, the C standard
> in F.4 says that the out of range conversions to integers should raise
> exceptions, but still says that the resulting value in those cases is
> unspecified.
> So, for the C part we should verify that with -ftrapping-math we don't
> constant fold it and cover it both by pure C and perhaps backend specific
> testcases which just search asm for the conversion instructions
> or even runtime test which tests that the exceptions are triggered,
> verify that we don't fold it either during GIMPLE opts or RTL opts
> (dunno whether they can be folded in e.g. C constant initializers or not).
>
There're lots of warnings for Wconversion that rely on gimple fold,
lots of new failures after the patch below.
Should we also add -fno-trapping-math to those testcases?

-  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;
 }


g++: c-c++-common/Wconversion-1.c  -std=gnu++14  (test for warnings, line 13)

g++: c-c++-common/Wconversion-1.c  -std=gnu++17  (test for warnings, line 13)

g++: c-c++-common/Wconversion-1.c  -std=gnu++20  (test for warnings, line 13)

g++: c-c++-common/Wconversion-1.c  -std=gnu++98  (test for warnings, line 13)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 26)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 30)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 34)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 39)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 43)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 47)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 51)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 55)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14  (test for
warnings, line 59)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++14 execution test

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 26)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 30)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 34)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 39)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 43)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 47)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 51)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 55)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17  (test for
warnings, line 59)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++17 execution test

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 26)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 30)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 34)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 39)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 43)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 47)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 51)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 55)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20  (test for
warnings, line 59)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++20 execution test

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 26)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 30)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 34)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 39)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 43)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 47)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 51)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 55)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98  (test for
warnings, line 59)

g++: c-c++-common/dfp/convert-int-saturate.c  -std=c++98 execution test

g++: g++.dg/ubsan/pr63956.C    (test for errors, line 159)

g++: g++.dg/ubsan/pr63956.C   (test for excess errors)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 100)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 101)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 102)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 110)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 111)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 33)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 34)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 86)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 87)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 88)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 89)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 90)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 91)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 92)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 93)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 95)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 96)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 97)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 98)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++14  (test for
warnings, line 99)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 100)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 101)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 102)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 110)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 111)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 33)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 34)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 86)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 87)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 88)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 89)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 90)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 91)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 92)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 93)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 95)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 96)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 97)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 98)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++17  (test for
warnings, line 99)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 100)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 101)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 102)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 110)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 111)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 33)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 34)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 86)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 87)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 88)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 89)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 90)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 91)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 92)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 93)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 95)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 96)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 97)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 98)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++20  (test for
warnings, line 99)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 100)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 101)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 102)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 110)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 111)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 33)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 34)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 86)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 87)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 88)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 89)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 90)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 91)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 92)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 93)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 95)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 96)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 97)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 98)

g++: g++.dg/warn/Wconversion-real-integer.C  -std=gnu++98  (test for
warnings, line 99)

gcc: c-c++-common/Wconversion-1.c  -Wc++-compat   (test for warnings, line 13)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 26)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 30)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 34)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 39)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 43)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 47)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 51)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 55)

gcc: c-c++-common/dfp/convert-int-saturate.c  (test for warnings, line 59)

gcc: c-c++-common/dfp/convert-int-saturate.c execution test

gcc: gcc.c-torture/execute/20031003-1.c   -O0  execution test

gcc: gcc.c-torture/execute/20031003-1.c   -O1  execution test

gcc: gcc.c-torture/execute/20031003-1.c   -O2  execution test

gcc: gcc.c-torture/execute/20031003-1.c   -O2 -flto
-fno-use-linker-plugin -flto-partition=none  execution test

gcc: gcc.c-torture/execute/20031003-1.c   -O2 -flto
-fuse-linker-plugin -fno-fat-lto-objects  execution test

gcc: gcc.c-torture/execute/20031003-1.c   -O3 -g  execution test

gcc: gcc.c-torture/execute/20031003-1.c   -Os  execution test

gcc: gcc.dg/Wconversion-complex-c99.c  (test for warnings, line 118)

gcc: gcc.dg/Wconversion-complex-c99.c  (test for warnings, line 119)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 100)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 101)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 102)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 103)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 111)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 112)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 34)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 35)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 87)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 88)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 89)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 90)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 91)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 92)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 93)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 94)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 96)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 97)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 98)

gcc: gcc.dg/Wconversion-real-integer.c  (test for warnings, line 99)

gcc: gcc.dg/c90-const-expr-11.c  (test for warnings, line 23)

gcc: gcc.dg/c90-const-expr-11.c constant at line 24 (test for errors, line 23)

gcc: gcc.dg/overflow-warn-8.c  (test for warnings, line 10)
>
>         Jakub
>


-- 
BR,
Hongtao

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
  2024-05-23  5:11     ` Hongtao Liu
@ 2024-05-27  1:08       ` liuhongt
  2024-06-04 14:27         ` Jeff Law
  0 siblings, 1 reply; 6+ messages in thread
From: liuhongt @ 2024-05-27  1:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: jakub

Update in V2:
Guard constant folding for overflow value in
fold_convert_const_int_from_real with flag_trapping_math.
Add -fno-trapping-math to related testcases which warn for overflow
in conversion from floating point to integer.

Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
Ok for trunk?

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.
---
 gcc/fold-const.cc                             | 13 +++++++-
 gcc/simplify-rtx.cc                           | 23 +++++++++++---
 gcc/testsuite/c-c++-common/Wconversion-1.c    |  2 +-
 .../c-c++-common/dfp/convert-int-saturate.c   |  1 +
 gcc/testsuite/g++.dg/ubsan/pr63956.C          |  7 ++++-
 .../g++.dg/warn/Wconversion-real-integer.C    |  2 +-
 .../gcc.c-torture/execute/20031003-1.c        |  2 ++
 .../gcc.dg/Wconversion-complex-c99.c          |  2 +-
 .../gcc.dg/Wconversion-real-integer.c         |  2 +-
 gcc/testsuite/gcc.dg/c90-const-expr-11.c      |  2 +-
 gcc/testsuite/gcc.dg/overflow-warn-8.c        |  1 +
 gcc/testsuite/gcc.dg/pr100927.c               | 31 +++++++++++++++++++
 12 files changed, 77 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr100927.c

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 7b268964acc..0ba01984630 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 53f54d1d392..b7a770dad60 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 81f9498d07c..9d874d19548 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 2d01f99468b..6b362c2aa95 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 6fd0b4f893e..9c15dbd8d54 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 3b6d1f3c437..d6332140b14 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 5d39d799e50..5e6f5089fc6 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 e8bc9db237d..69281c7d71e 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 92e6987d9ec..ca6007f4fe8 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 a2720c47bf4..65aab10a129 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 e76bcac5e07..75bfa74f3dc 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 00000000000..ea0e627befa
--- /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;
+}
-- 
2.31.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX.
  2024-05-27  1:08       ` liuhongt
@ 2024-06-04 14:27         ` Jeff Law
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff Law @ 2024-06-04 14:27 UTC (permalink / raw)
  To: liuhongt, gcc-patches; +Cc: jakub



On 5/26/24 7:08 PM, liuhongt wrote:
> Update in V2:
> Guard constant folding for overflow value in
> fold_convert_const_int_from_real with flag_trapping_math.
> Add -fno-trapping-math to related testcases which warn for overflow
> in conversion from floating point to integer.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
> Ok for trunk?
> 
> 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.
OK.  Thanks.

jeff



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-06-04 14:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-22  1:57 [PATCH] Don't simplify NAN/INF or out-of-range constant for FIX/UNSIGNED_FIX liuhongt
2024-05-22  7:46 ` Richard Biener
2024-05-22  7:59   ` Jakub Jelinek
2024-05-23  5:11     ` Hongtao Liu
2024-05-27  1:08       ` liuhongt
2024-06-04 14:27         ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).