On Wed, May 22, 2024 at 3:58 AM liuhongt <[email protected]> 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
>