mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
middle-end: extend the narrower shift amount before broadcasting it [PR 124250]
The comment above expand_vector_broadcast() states a precondition that the mode of op must be the element mode of vmode. But when expand_binop() called expand_vector_broadcast() to broadcast the shift amount, it only truncated the shift amount if it's too wide, but no action is performed if the shift amount is too narrow. PR middle-end/124250 PR target/123807 gcc/ * optabs.cc (expand_vector_broadcast): Add a checking assert to verify the precondition about the input modes. (expand_binop): Extend the shift amount if it's narrower than the element of the shifted vector. gcc/testsuite/ * gcc.c-torture/compile/pr124250.c: New test.
This commit is contained in:
@@ -428,9 +428,9 @@ force_expand_binop (machine_mode mode, optab binoptab,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Create a new vector value in VMODE with all elements set to OP. The
|
||||
mode of OP must be the element mode of VMODE. If OP is a constant,
|
||||
then the return value will be a constant. */
|
||||
/* Create a new vector value in VMODE with all elements set to OP. If OP
|
||||
is not a constant, the mode of it must be the element mode of VMODE.
|
||||
If OP is a constant, then the return value will be a constant. */
|
||||
|
||||
rtx
|
||||
expand_vector_broadcast (machine_mode vmode, rtx op)
|
||||
@@ -439,6 +439,8 @@ expand_vector_broadcast (machine_mode vmode, rtx op)
|
||||
rtvec vec;
|
||||
|
||||
gcc_checking_assert (VECTOR_MODE_P (vmode));
|
||||
gcc_checking_assert (CONST_INT_P (op)
|
||||
|| GET_MODE_INNER (vmode) == GET_MODE (op));
|
||||
|
||||
if (valid_for_const_vector_p (vmode, op))
|
||||
return gen_const_vec_duplicate (vmode, op);
|
||||
@@ -1629,15 +1631,25 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
|
||||
if (otheroptab
|
||||
&& (icode = optab_handler (otheroptab, mode)) != CODE_FOR_nothing)
|
||||
{
|
||||
/* The scalar may have been extended to be too wide. Truncate
|
||||
it back to the proper size to fit in the broadcast vector. */
|
||||
/* The scalar may be wider or narrower than the vector element.
|
||||
Truncate or extend it to the proper size to fit in the
|
||||
broadcast vector. */
|
||||
scalar_mode inner_mode = GET_MODE_INNER (mode);
|
||||
if (!CONST_INT_P (op1)
|
||||
&& (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (op1)))
|
||||
> GET_MODE_BITSIZE (inner_mode)))
|
||||
op1 = force_reg (inner_mode,
|
||||
simplify_gen_unary (TRUNCATE, inner_mode, op1,
|
||||
GET_MODE (op1)));
|
||||
if (!CONST_INT_P (op1))
|
||||
{
|
||||
auto mode1 = as_a <scalar_int_mode> (GET_MODE (op1));
|
||||
int size1 = GET_MODE_BITSIZE (mode1);
|
||||
int inner_size = GET_MODE_BITSIZE (inner_mode);
|
||||
|
||||
if (size1 != inner_size)
|
||||
{
|
||||
auto unary = size1 > inner_size ? TRUNCATE : ZERO_EXTEND;
|
||||
op1 = force_reg (inner_mode,
|
||||
simplify_gen_unary (unary, inner_mode,
|
||||
op1, mode1));
|
||||
}
|
||||
}
|
||||
|
||||
rtx vop1 = expand_vector_broadcast (mode, op1);
|
||||
if (vop1)
|
||||
{
|
||||
|
||||
8
gcc/testsuite/gcc.c-torture/compile/pr124250.c
Normal file
8
gcc/testsuite/gcc.c-torture/compile/pr124250.c
Normal file
@@ -0,0 +1,8 @@
|
||||
typedef long long v2i64 __attribute__ ((vector_size (16), aligned (16)));
|
||||
v2i64 a, b;
|
||||
|
||||
void
|
||||
test (int l)
|
||||
{
|
||||
a = b >> (-l);
|
||||
}
|
||||
Reference in New Issue
Block a user