[gcc r15-11437] i386: Fix ICE on out of bounds vector elt access [PR126446]
Jakub Jelinek via Gcc-cvs <[email protected]> Sat, 1 Aug 2026 10:16:32 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:34932e9e078c180c4d552d910ff8c97be9ed8050 commit r15-11437-g34932e9e078c180c4d552d910ff8c97be9ed8050 Author: Jakub Jelinek <[email protected]> Date: Wed Jul 29 10:15:11 2026 +0200 i386: Fix ICE on out of bounds vector elt access [PR126446] 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 fixes it 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. gimple-isel.cc will be changed incrementally. 2026-07-29 Jakub Jelinek <[email protected]> PR target/126446 * 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. Reviewed-by: Uros Bizjak <[email protected]> (cherry picked from commit 1bc2fdc4f4cbe1b68237f49f211473c56d8a44a3) Diff: --- gcc/config/i386/i386-expand.cc | 5 +++++ gcc/testsuite/gcc.target/i386/avx2-pr126446.c | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index c13eff64a001..78d30974bf95 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -17891,6 +17891,11 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt) machine_mode mmode = VOIDmode; rtx (*gen_blendm) (rtx, rtx, rtx, rtx); + if (!IN_RANGE (elt, 0, GET_MODE_NUNITS (mode))) + { + emit_move_insn (target, target); + return; + } switch (mode) { case E_V2SImode: diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr126446.c b/gcc/testsuite/gcc.target/i386/avx2-pr126446.c new file mode 100644 index 000000000000..4af8cfd283c7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx2-pr126446.c @@ -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]; +}