On Tue, Jul 28, 2026 at 9:02 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?
>
> 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))
IN_RANGE ?
> + {
> + emit_move_insn (target, target);
> + return;
> + }
OK for the x86 part with the above macro - even a comment is not
needed for self-documented code.
Thanks,
Uros.