[gcc r13-10446] isel: Fix ICE on out of bounds vector elt access [PR126446]

Jakub Jelinek via Gcc-cvs <[email protected]> Sat, 1 Aug 2026 10:58:32 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:8e3bbd704424d72cde1efcd3d6d34250e188541f

commit r13-10446-g8e3bbd704424d72cde1efcd3d6d34250e188541f
Author: Jakub Jelinek <[email protected]>
Date:   Wed Jul 29 23:34:54 2026 +0200

    isel: Fix ICE on out of bounds vector elt access [PR126446]
    
    The isel pass has a check for out of bounds constant index before
    optimizing into .VEC_SET, but it does it using
          // if index is a constant, then check the bounds
          poly_uint64 idx_poly;
          if (poly_int_tree_p (idx, &idx_poly))
            {
              poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (view_op0));
              if (known_gt (idx_poly, nelts))
                return false;
            }
    In the testcase below, idx is INTEGER_CST with long long type and
    negative value, that doesn't fit into poly_uint64, so we happily convert
    it into .VEC_SET.
    
    Furthermore, the known_gt check looks wrong, already idx_poly known_eq
    to nelts is too large and out of bounds for .VEC_SET.
    
    This patch fixes that by punting if !poly_int_tree_p (idx, &idx_poly)
    and poly_int_tree_p (idx), so when it is INTEGER_CST or POLY_INT_CST
    which doesn't fit into poly_uint64 (so likely negative), and
    uses known_ge instead of known_gt.
    
    2026-07-29  Jakub Jelinek  <[email protected]>
    
            PR target/126446
            * gimple-isel.cc (gimple_expand_vec_set_extract_expr): Punt if
            idx doesn't fit into poly_uint64 but is poly_int_tree_p.  Use
            known_ge rather than known_gt for out of bounds check.  Formatting
            fixes.
    
    Reviewed-by: Richard Biener <[email protected]>
    (cherry picked from commit a7ba10ac1e027349a655ee4572abf34c1b9c1db1)

Diff:
---
 gcc/gimple-isel.cc | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index f7eabeca6475..0534c02396ed 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -69,10 +69,11 @@ gimple_expand_vec_set_expr (struct function *fun, gimple_stmt_iterator *gsi)
 
   tree val = gimple_assign_rhs1 (stmt);
   tree op0 = TREE_OPERAND (lhs, 0);
-  if (TREE_CODE (op0) == VIEW_CONVERT_EXPR && DECL_P (TREE_OPERAND (op0, 0))
+  if (TREE_CODE (op0) == VIEW_CONVERT_EXPR
+      && DECL_P (TREE_OPERAND (op0, 0))
       && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
-      && TYPE_MODE (TREE_TYPE (lhs))
-	   == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0)))))
+      && (TYPE_MODE (TREE_TYPE (lhs))
+	  == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0))))))
     {
       tree pos = TREE_OPERAND (lhs, 1);
       tree view_op0 = TREE_OPERAND (op0, 0);
@@ -82,9 +83,13 @@ gimple_expand_vec_set_expr (struct function *fun, gimple_stmt_iterator *gsi)
       if (poly_int_tree_p (pos, &idx_poly))
 	{
 	  poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (view_op0));
-	  if (known_gt (idx_poly, nelts))
+	  if (known_ge (idx_poly, nelts))
 	    return false;
 	}
+      else if (poly_int_tree_p (pos))
+	// if idx doesn't fit into poly_uint64, but is constant, it
+	// must be out of bounds
+	return false;
       machine_mode outermode = TYPE_MODE (TREE_TYPE (view_op0));
       if ((auto_var_in_fn_p (view_op0, fun->decl)
 	   || (VAR_P (view_op0) && DECL_HARD_REGISTER (view_op0)))