[gcc r17-2960] PR tree-optimization/126242: Check range is defined to avoid ICE.
Roger Sayle via Gcc-cvs <[email protected]> Tue, 4 Aug 2026 20:07:21 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:d6073a20f86a9012ce1284a752e32ac5ec9e2132 commit r17-2960-gd6073a20f86a9012ce1284a752e32ac5ec9e2132 Author: Roger Sayle <[email protected]> Date: Tue Aug 4 21:03:20 2026 +0100 PR tree-optimization/126242: Check range is defined to avoid ICE. Here's the latest revision of my patch to resolve PR 126242 (and 126325), incorporating Richard Biener's feedback to simplify the logic, eliminating itype_ok and always using calling gimple_match_range_of_expr. This version also resolves PR tree-optimization/126325 introduced/exposed by the same change, checking that when transforming (float)x < C into x < (int)C that (int)C is exactly representable, i.e. that (float)(int)C == C. This patch resolves PR tree-opt/126242, an unanticipated interaction between the two recent (float)i == 1.0 patches to match.pd. The issue is that value range information is getting queried in circumstances (on paths) where we've failed to initialize the range and/or ranger has failed to bound the value. The correction below fixes this in two ways: initialize the range information in more cases, and check that the range has been successfully initialized before using it. The motivation/benefit for the first approach is seen in the example: unsigned char t = x & 63; return (float)t > 100.0; Previously, because unsigned char can be safely represented in a float we'd use the bounds [0,255], and transform this to t > 100. Obviously, there's benefit in using ranger to reduce the range to [0,63], even when the integer type fits the floating point type, allowing the above expression to be simplified even further to false. 2026-08-04 Roger Sayle <[email protected]> Richard Biener <[email protected]> gcc/ChangeLog PR tree-optimization/126242 PR tree-optimization/126325 * match.pd ((FTYPE) N CMP CST): Always attempt to initialize value range information. Check undefined_p before using range bounds. Check that icst_val hasn't overflowed, i.e. that (FTYPE)ICST == CST, before transforming to integer comparison. gcc/testsuite/ChangeLog PR tree-optimization/126242 PR tree-optimization/126325 * gcc.dg/pr126325.c: New test case. * gfortran.dg/pr126242.f90: New reduced test case. * gfortran.dg/pr41928-2.f90: Also compile pr41928.f90 with -Ofast. Diff: --- gcc/match.pd | 19 ++- gcc/testsuite/gcc.dg/pr126325.c | 19 +++ gcc/testsuite/gfortran.dg/pr126242.f90 | 5 + gcc/testsuite/gfortran.dg/pr41928-2.f90 | 263 ++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+), 6 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 344883d6ea4c..d5160d87e304 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -7844,10 +7844,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (with { tree itype = TREE_TYPE (@0); - signop isign = TYPE_SIGN (itype); format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1)))); - bool itype_ok = fmt.can_represent_integral_type_p (itype); - bool value_ok = itype_ok; + bool value_ok = fmt.can_represent_integral_type_p (itype); const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1); /* Be careful to preserve any potential exceptions due to NaNs. qNaNs are ok in == or != context. */ @@ -7858,8 +7856,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && HONOR_SNANS (TREE_TYPE (@1)))); #if GIMPLE int_range_max vr; - if (!value_ok - && gimple_match_range_of_expr (vr, @0, @2)) + if (gimple_match_range_of_expr (vr, @0, @2)) value_ok = fmt.can_represent_range_value_p (&vr); #endif /* Conversion may raise FPE_INEXACT with -ftrapping-math. */ @@ -7874,7 +7871,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) wide_int imin_val = wi::min_value (itype); wide_int imax_val = wi::max_value (itype); #if GIMPLE - if (!itype_ok) + if (!vr.undefined_p ()) { imin_val = vr.lower_bound (); imax_val = vr.upper_bound (); @@ -7897,6 +7894,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) bool overflow_p = false; wide_int icst_val = real_to_integer (&icst, &overflow_p, TYPE_PRECISION (itype)); + /* Double check that icst is representable in itype. */ + if (isign == SIGNED && !overflow_p) + { + REAL_VALUE_TYPE check; + real_from_integer (&check, fmt, icst_val, isign); + if (!real_identical (&check, &icst)) + overflow_p = true; + } } (switch /* Optimize cases when CST is outside of ITYPE's range. */ @@ -7915,12 +7920,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Remove cast if CST is an integer representable by ITYPE, and it is safe to do so. */ (if (cst_int_p + && !overflow_p && fold_cmp_float_cst_p (imin_val, imax_val, cmp, &icst, fmt, icst_val, isign)) (cmp @0 { wide_int_to_tree (itype, icst_val); }) ) /* Otherwise replace with sensible integer constant. */ (if (!cst_int_p + && !overflow_p && fold_cmp_float_cst_p (imin_val, imax_val, icmp, &icst, fmt, icst_val, isign)) (icmp @0 { wide_int_to_tree (itype, icst_val); }))))))))) diff --git a/gcc/testsuite/gcc.dg/pr126325.c b/gcc/testsuite/gcc.dg/pr126325.c new file mode 100644 index 000000000000..57b7317a8566 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr126325.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -fdump-tree-optimized" } */ + +/* It is incorrect to simplify these comparisons to true (or false), + even with -Ofast. */ + +int f (int i) +{ + return (float)i < 2147483648.0f; /* = 2^31 (INT_MAX + 1) */ +} + +int g (unsigned int i) +{ + return (float)i < 4294967296.0f; /* = 2^32 (UINT_MAX + 1) */ +} + +/* { dg-final { scan-tree-dump-not "return 0" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return 1" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "e\\+9" 2 "optimized" } } */ diff --git a/gcc/testsuite/gfortran.dg/pr126242.f90 b/gcc/testsuite/gfortran.dg/pr126242.f90 new file mode 100644 index 000000000000..293c9bfe2fce --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr126242.f90 @@ -0,0 +1,5 @@ +! { dg-do compile } +! { dg-options "-Ofast -w" } +DO bx=2,lb +END DO +END diff --git a/gcc/testsuite/gfortran.dg/pr41928-2.f90 b/gcc/testsuite/gfortran.dg/pr41928-2.f90 new file mode 100644 index 000000000000..d96857afd8d0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr41928-2.f90 @@ -0,0 +1,263 @@ +! { dg-do compile } +! { dg-options "-Ofast -w" } +MODULE kinds + INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND ( 14, 200 ) + INTEGER, DIMENSION(:), ALLOCATABLE :: nco,ncoset,nso,nsoset + INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: co,coset +END MODULE kinds +MODULE ai_moments + USE kinds +CONTAINS + SUBROUTINE cossin(la_max,npgfa,zeta,rpgfa,la_min,& + lb_max,npgfb,zetb,rpgfb,lb_min,& + rac,rbc,kvec,cosab,sinab) + REAL(KIND=dp), DIMENSION(ncoset(la_max),& + ncoset(lb_max)) :: sc, ss + DO ipgf=1,npgfa + DO jpgf=1,npgfb + IF (la_max > 0) THEN + DO la=2,la_max + DO ax=2,la + DO ay=0,la-ax + sc(coset(ax,ay,az),1) = rap(1)*sc(coset(ax-1,ay,az),1) +& + f2 * kvec(1)*ss(coset(ax-1,ay,az),1) + ss(coset(ax,ay,az),1) = rap(1)*ss(coset(ax-1,ay,az),1) +& + f2 * kvec(1)*sc(coset(ax-1,ay,az),1) + END DO + END DO + END DO + IF (lb_max > 0) THEN + DO lb=2,lb_max + ss(1,coset(0,0,lb)) = rbp(3)*ss(1,coset(0,0,lb-1)) +& + f2 * kvec(3)*sc(1,coset(0,0,lb-1)) + DO bx=2,lb + DO by=0,lb-bx + ss(1,coset(bx,by,bz)) = rbp(1)*ss(1,coset(bx-1,by,bz)) +& + f2 * kvec(1)*sc(1,coset(bx-1,by,bz)) + END DO + END DO + END DO + END IF + END IF + DO j=ncoset(lb_min-1)+1,ncoset(lb_max) + END DO + END DO + END DO + END SUBROUTINE cossin + SUBROUTINE moment(la_max,npgfa,zeta,rpgfa,la_min,& + lb_max,npgfb,zetb,rpgfb,& + lc_max,rac,rbc,mab) + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: zeta, rpgfa + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: zetb, rpgfb + REAL(KIND=dp), DIMENSION(:, :, :), & + INTENT(INOUT) :: mab + REAL(KIND=dp), DIMENSION(3) :: rab, rap, rbp, rpc + REAL(KIND=dp), DIMENSION(ncoset(la_max),& + ncoset(lb_max), ncoset(lc_max)) :: s + DO ipgf=1,npgfa + DO jpgf=1,npgfb + IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN + DO k=1, ncoset(lc_max)-1 + DO j=nb+1,nb+ncoset(lb_max) + DO i=na+1,na+ncoset(la_max) + mab(i,j,k) = 0.0_dp + END DO + END DO + END DO + END IF + rpc = zetp*(zeta(ipgf)*rac+zetb(jpgf)*rbc) + DO l=2, ncoset(lc_max) + lx = indco(1,l) + l2 = 0 + IF ( lz > 0 ) THEN + IF ( lz > 1 ) l2 = coset(lx,ly,lz-2) + ELSE IF ( ly > 0 ) THEN + IF ( ly > 1 ) l2 = coset(lx,ly-2,lz) + IF ( lx > 1 ) l2 = coset(lx-2,ly,lz) + END IF + s(1,1,l) = rpc(i)*s(1,1,l1) + IF ( l2 > 0 ) s(1,1,l) = s(1,1,l) + f2*REAL(ni,dp)*s(1,1,l2) + END DO + DO l = 1, ncoset(lc_max) + IF ( lx > 0 ) THEN + lx1 = coset(lx-1,ly,lz) + END IF + IF ( ly > 0 ) THEN + ly1 = coset(lx,ly-1,lz) + END IF + IF (la_max > 0) THEN + DO la=2,la_max + IF ( lz1 > 0 ) s(coset(0,0,la),1,l) = s(coset(0,0,la),1,l) + & + f2z*s(coset(0,0,la-1),1,lz1) + IF ( ly1 > 0 ) s(coset(0,1,az),1,l) = s(coset(0,1,az),1,l) + & + f2y*s(coset(0,0,az),1,ly1) + DO ay=2,la + s(coset(0,ay,az),1,l) = rap(2)*s(coset(0,ay-1,az),1,l) +& + f2*REAL(ay-1,dp)*s(coset(0,ay-2,az),1,l) + IF ( ly1 > 0 ) s(coset(0,ay,az),1,l) = s(coset(0,ay,az),1,l) + & + f2y*s(coset(0,ay-1,az),1,ly1) + END DO + DO ay=0,la-1 + IF ( lx1 > 0 ) s(coset(1,ay,az),1,l) = s(coset(1,ay,az),1,l) + & + f2x*s(coset(0,ay,az),1,lx1) + END DO + DO ax=2,la + DO ay=0,la-ax + s(coset(ax,ay,az),1,l) = rap(1)*s(coset(ax-1,ay,az),1,l) +& + f3*s(coset(ax-2,ay,az),1,l) + IF ( lx1 > 0 ) s(coset(ax,ay,az),1,l) = s(coset(ax,ay,az),1,l) + & + f2x*s(coset(ax-1,ay,az),1,lx1) + END DO + END DO + END DO + IF (lb_max > 0) THEN + DO j=2,ncoset(lb_max) + DO i=1,ncoset(la_max) + s(i,j,l) = 0.0_dp + END DO + END DO + DO la=la_start,la_max-1 + DO ax=0,la + DO ay=0,la-ax + s(coset(ax,ay,az),2,l) = s(coset(ax+1,ay,az),1,l) -& + rab(1)*s(coset(ax,ay,az),1,l) + s(coset(ax,ay,az),4,l) = s(coset(ax,ay,az+1),1,l) -& + rab(3)*s(coset(ax,ay,az),1,l) + END DO + END DO + END DO + DO ax=0,la_max + DO ay=0,la_max-ax + IF (ax == 0) THEN + s(coset(ax,ay,az),2,l) = rbp(1)*s(coset(ax,ay,az),1,l) + ELSE + s(coset(ax,ay,az),2,l) = rbp(1)*s(coset(ax,ay,az),1,l) +& + fx*s(coset(ax-1,ay,az),1,l) + END IF + IF (lx1 > 0) s(coset(ax,ay,az),2,l) = s(coset(ax,ay,az),2,l) +& + f2x*s(coset(ax,ay,az),1,lx1) + IF (ay == 0) THEN + s(coset(ax,ay,az),3,l) = rbp(2)*s(coset(ax,ay,az),1,l) + ELSE + s(coset(ax,ay,az),3,l) = rbp(2)*s(coset(ax,ay,az),1,l) +& + fy*s(coset(ax,ay-1,az),1,l) + END IF + IF (ly1 > 0) s(coset(ax,ay,az),3,l) = s(coset(ax,ay,az),3,l) +& + f2y*s(coset(ax,ay,az),1,ly1) + IF (az == 0) THEN + s(coset(ax,ay,az),4,l) = rbp(3)*s(coset(ax,ay,az),1,l) + ELSE + s(coset(ax,ay,az),4,l) = rbp(3)*s(coset(ax,ay,az),1,l) +& + fz*s(coset(ax,ay,az-1),1,l) + END IF + IF (lz1 > 0) s(coset(ax,ay,az),4,l) = s(coset(ax,ay,az),4,l) +& + f2z*s(coset(ax,ay,az),1,lz1) + END DO + END DO + DO lb=2,lb_max + DO la=la_start,la_max-1 + DO ax=0,la + DO ay=0,la-ax + s(coset(ax,ay,az),coset(0,0,lb),l) =& + rab(3)*s(coset(ax,ay,az),coset(0,0,lb-1),l) + DO bx=1,lb + DO by=0,lb-bx + s(coset(ax,ay,az),coset(bx,by,bz),l) =& + rab(1)*s(coset(ax,ay,az),coset(bx-1,by,bz),l) + END DO + END DO + END DO + END DO + END DO + DO ax=0,la_max + DO ay=0,la_max-ax + IF (az == 0) THEN + s(coset(ax,ay,az),coset(0,0,lb),l) =& + rbp(3)*s(coset(ax,ay,az),coset(0,0,lb-1),l) +& + f3*s(coset(ax,ay,az),coset(0,0,lb-2),l) + END IF + IF (lz1 > 0) s(coset(ax,ay,az),coset(0,0,lb),l) =& + f2z*s(coset(ax,ay,az),coset(0,0,lb-1),lz1) + IF (ay == 0) THEN + IF (ly1 > 0) s(coset(ax,ay,az),coset(0,1,bz),l) =& + f2y*s(coset(ax,ay,az),coset(0,0,bz),ly1) + DO by=2,lb + s(coset(ax,ay,az),coset(0,by,bz),l) =& + f3*s(coset(ax,ay,az),coset(0,by-2,bz),l) + IF (ly1 > 0) s(coset(ax,ay,az),coset(0,by,bz),l) =& + f2y*s(coset(ax,ay,az),coset(0,by-1,bz),ly1) + END DO + s(coset(ax,ay,az),coset(0,1,bz),l) =& + fy*s(coset(ax,ay-1,az),coset(0,0,bz),l) + END IF + IF (ax == 0) THEN + DO by=0,lb-1 + IF (lx1 > 0) s(coset(ax,ay,az),coset(1,by,bz),l) =& + f2x*s(coset(ax,ay,az),coset(0,by,bz),lx1) + END DO + DO bx=2,lb + DO by=0,lb-bx + s(coset(ax,ay,az),coset(bx,by,bz),l) =& + f3*s(coset(ax,ay,az),coset(bx-2,by,bz),l) + IF (lx1 > 0) s(coset(ax,ay,az),coset(bx,by,bz),l) =& + f2x*s(coset(ax,ay,az),coset(bx-1,by,bz),lx1) + END DO + END DO + DO by=0,lb-1 + IF (lx1 > 0) s(coset(ax,ay,az),coset(1,by,bz),l) =& + f2x*s(coset(ax,ay,az),coset(0,by,bz),lx1) + END DO + DO bx=2,lb + DO by=0,lb-bx + s(coset(ax,ay,az),coset(bx,by,bz),l) =& + f3*s(coset(ax,ay,az),coset(bx-2,by,bz),l) + IF (lx1 > 0) s(coset(ax,ay,az),coset(bx,by,bz),l) =& + f2x*s(coset(ax,ay,az),coset(bx-1,by,bz),lx1) + END DO + END DO + END IF + END DO + END DO + END DO + END IF + IF (lb_max > 0) THEN + DO lb=2,lb_max + IF (lz1 > 0) s(1,coset(0,0,lb),l) = s(1,coset(0,0,lb),l) +& + f2z*s(1,coset(0,0,lb-1),lz1) + IF (ly1 > 0) s(1,coset(0,1,bz),l) = s(1,coset(0,1,bz),l) +& + f2y*s(1,coset(0,0,bz),ly1) + DO by=2,lb + s(1,coset(0,by,bz),l) = rbp(2)*s(1,coset(0,by-1,bz),l) +& + f2*REAL(by-1,dp)*s(1,coset(0,by-2,bz),l) + IF (lx1 > 0) s(1,coset(1,by,bz),l) = s(1,coset(1,by,bz),l) +& + f2x*s(1,coset(0,by,bz),lx1) + END DO + DO bx=2,lb + DO by=0,lb-bx + IF (lx1 > 0) s(1,coset(bx,by,bz),l) = s(1,coset(bx,by,bz),l) +& + f2x*s(1,coset(bx-1,by,bz),lx1) + END DO + END DO + END DO + END IF + END IF + END DO + DO k=2,ncoset(lc_max) + DO j=1,ncoset(lb_max) + END DO + END DO + END DO + END DO + END SUBROUTINE moment + SUBROUTINE diff_momop(la_max,npgfa,zeta,rpgfa,la_min,& + order,rac,rbc,difmab,mab_ext) + REAL(KIND=dp), DIMENSION(:, :, :), & + OPTIONAL, POINTER :: mab_ext + REAL(KIND=dp), ALLOCATABLE, & + DIMENSION(:, :, :) :: difmab_tmp + DO imom = 1,ncoset(order)-1 + CALL adbdr(la_max,npgfa,rpgfa,la_min,& + difmab_tmp(:,:,2), difmab_tmp(:,:,3)) + END DO + END SUBROUTINE diff_momop +END MODULE ai_moments