On Wed, May 22, 2024 at 3:58 AM liuhongt <hongtao....@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 >