diff mbox series

[committed] simplify-rtx: Fix vec_select index check

Message ID mpt5yt88gp6.fsf@arm.com
State Committed
Headers show
Series [committed] simplify-rtx: Fix vec_select index check | expand

Commit Message

Richard Sandiford Nov. 4, 2021, 8:31 a.m. UTC
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.

Tested on aarch64-linux-gnu and aarch64_be-elf.  Applied as obvious.

Richard


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.
---
 gcc/simplify-rtx.c                            | 12 +++---
 .../gcc.dg/rtl/aarch64/big-endian-cse-1.c     | 42 +++++++++++++++++++
 2 files changed, 48 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c
diff mbox series

Patch

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index aac5693f548..9038affa036 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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;
-
-  machine_mode imode = GET_MODE_INNER (GET_MODE (op));
+  scalar_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)
diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c b/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c
new file mode 100644
index 00000000000..1559a489f25
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c
@@ -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,} } } */