On Tue, Jul 28, 2026 at 12:03 PM Jakub Jelinek <[email protected]> wrote: > > Hi! > > The following testcase ICEs on x86_64. > 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. > > And another problem is that the x86 backend isn't trying to be careful > and handle out of bounds elt gracefully (I think it could still in theory > happen, if GIMPLE lets it through but e.g. something during expansion > figures out the index is constant or whatever). > > The following patch does 2 things (both are enough to avoid the ICE). > One is to also punt if idx is clearly negative (doesn't fit into > poly_uint64 but fits into poly_int64). > And the second fix is in the backend to avoid triggering UB at compile > time by doing HOST_WIDE_INT_1U << elt etc. when elt is negative or too > large. In order to avoid ICE, we need to emit something, so I emit > a no-op move, out of bounds vector set shouldn't change anything in > the target. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
The gimple-isel parts are ok. > > Now that I look at the patch, I think the if (known_gt (idx_poly, nelts)) > above is wrong as well, I think it should be > if (known_ge (idx_poly, nelts)) > because vector set is out of bounds even when accessing nelts index. > If you agree, I can post an incremental patch. > > 2026-07-28 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 fits into poly_int64. > * config/i386/i386-expand.cc (ix86_expand_vector_set): If elt is > out of bounds, emit a no-op move. > > * gcc.target/i386/avx2-pr126446.c: New test. > > --- gcc/gimple-isel.cc.jj 2026-07-22 09:42:52.010559350 +0200 > +++ gcc/gimple-isel.cc 2026-07-28 13:07:46.663422172 +0200 > @@ -96,10 +96,11 @@ gimple_expand_vec_set_extract_expr (stru > return false; > > tree op0 = TREE_OPERAND (ref, 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 (ref)) > - == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0))))) > + && (TYPE_MODE (TREE_TYPE (ref)) > + == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0)))))) > { > tree pos = TREE_OPERAND (ref, 1); > > @@ -114,6 +115,10 @@ gimple_expand_vec_set_extract_expr (stru > if (known_gt (idx_poly, nelts)) > return false; > } > + else if (tree_fits_poly_int64_p (idx)) > + // if idx doesn't fit into poly_uint64, but fits into poly_int64, > + // it must be negative > + return false; > machine_mode outermode = TYPE_MODE (TREE_TYPE (view_op0)); > machine_mode extract_mode = TYPE_MODE (TREE_TYPE (ref)); > > --- gcc/config/i386/i386-expand.cc.jj 2026-07-24 11:52:32.590640836 +0200 > +++ gcc/config/i386/i386-expand.cc 2026-07-28 13:04:52.711678590 +0200 > @@ -19157,6 +19157,11 @@ ix86_expand_vector_set (bool mmx_ok, rtx > machine_mode mmode = VOIDmode; > rtx (*gen_blendm) (rtx, rtx, rtx, rtx); > > + if (elt < 0 || elt >= GET_MODE_NUNITS (mode)) > + { > + emit_move_insn (target, target); > + return; > + } > if (TARGET_SSE4_1 && mode == V4SImode && val == const0_rtx) > { > emit_insn (gen_sse4_1_insertps_v4si_zero (target, target, > --- gcc/testsuite/gcc.target/i386/avx2-pr126446.c.jj 2026-07-28 > 13:15:10.373701905 +0200 > +++ gcc/testsuite/gcc.target/i386/avx2-pr126446.c 2026-07-28 > 13:14:54.663904357 +0200 > @@ -0,0 +1,14 @@ > +/* PR target/126446 */ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -mavx2" } */ > + > +typedef signed char V __attribute__((vector_size (16))); > + > +signed char > +foo () > +{ > + V b = {}; > + long long c = ~2878966870562407444LL; > + b[c] = 1; > + return b[0]; > +} > > Jakub >
