simplify-rtx: Fix vec_select index check
Vector lane indices follow memory (array) order, so lane 0 corresponds to the high element rather than the low element on big-endian targets. This was causing quite a few execution failures on aarch64_be, such as gcc.c-torture/execute/pr47538.c. gcc/ * simplify-rtx.c (simplify_context::simplify_gen_vec_select): Assert that the operand has a vector mode. Use subreg_lowpart_offset to test whether an index corresponds to the low part. gcc/testsuite/ * gcc.dg/rtl/aarch64/big-endian-cse-1.c: New test.
This commit is contained in:
parent
95318d469f
commit
518f865f4b
|
@ -7622,15 +7622,15 @@ simplify_context::lowpart_subreg (machine_mode outer_mode, rtx expr,
|
|||
|
||||
/* Generate RTX to select element at INDEX out of vector OP. */
|
||||
|
||||
rtx simplify_context::simplify_gen_vec_select (rtx op, unsigned int index)
|
||||
rtx
|
||||
simplify_context::simplify_gen_vec_select (rtx op, unsigned int index)
|
||||
{
|
||||
gcc_assert (VECTOR_MODE_P (GET_MODE (op)));
|
||||
|
||||
if (!VECTOR_MODE_P (GET_MODE (op)))
|
||||
return NULL_RTX;
|
||||
scalar_mode imode = GET_MODE_INNER (GET_MODE (op));
|
||||
|
||||
machine_mode imode = GET_MODE_INNER (GET_MODE (op));
|
||||
|
||||
if (index == 0)
|
||||
if (known_eq (index * GET_MODE_SIZE (imode),
|
||||
subreg_lowpart_offset (imode, GET_MODE (op))))
|
||||
{
|
||||
rtx res = lowpart_subreg (imode, op, GET_MODE (op));
|
||||
if (res)
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* { dg-do compile { target aarch64*-*-* } } */
|
||||
/* { dg-require-effective-target lp64 } */
|
||||
/* { dg-options "-O3 -mbig-endian" } */
|
||||
|
||||
void __RTL (startwith ("vregs")) foo (void *ptr1, void *ptr2)
|
||||
{
|
||||
(function "foo"
|
||||
(param "ptr1"
|
||||
(DECL_RTL (reg/v:DI <0> [ ptr1 ]))
|
||||
(DECL_RTL_INCOMING (reg:DI x0 [ ptr1 ]))
|
||||
) ;; param "ptr1"
|
||||
(param "ptr2"
|
||||
(DECL_RTL (reg/v:DI <1> [ ptr2 ]))
|
||||
(DECL_RTL_INCOMING (reg:DI x1 [ ptr2 ]))
|
||||
) ;; param "ptr2"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
|
||||
(insn 4 (set (reg:DI <0>) (reg:DI x0)))
|
||||
(insn 5 (set (reg:DI <1>) (reg:DI x1)))
|
||||
(insn 6 (set (reg:V2SI <2>)
|
||||
(const_vector:V2SI [(const_int 1)
|
||||
(const_int 0)])) (nil))
|
||||
(insn 7 (set (mem:V2SI (reg:DI <0>) [1 ptr1+0 S8 A8])
|
||||
(reg:V2SI <2>)))
|
||||
(insn 8 (set (reg:V4SI <3>)
|
||||
(const_vector:V4SI [(const_int 1)
|
||||
(const_int 1)
|
||||
(const_int 1)
|
||||
(const_int 1)])) (nil))
|
||||
(insn 9 (set (reg:SI <4>) (subreg:SI (reg:V4SI <3>) 12))
|
||||
(expr_list:REG_EQUAL (const_int 1) (nil)))
|
||||
(insn 10 (set (mem:SI (reg:DI <1>) [1 ptr2+0 S4 A4])
|
||||
(reg:SI <4>)))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not {\tstr\twzr,} } } */
|
Loading…
Reference in New Issue