From: Loeka Rogge <[email protected]>
V2HI vectors, explicitly or auto-generated, could be stored in memory wrongly
due to endianness. For example in the following c code stores to the struct
are SLP vectorized, causing them to be stored in the wrong order:
> struct S {short a; short b;};
> s.a = 520;
> s.b = -1;
in the split2 pass the following register set:
> (const_vector:V2HI [
> (const_int 520 [0x208])
> (const_int -1 [0xffffffffffffffff])
> ])) "smallTest.c":16:9 484 {*movv2hi_insn}
is converted to:
> (const_int -65016 [0xffffffffffff0208])) "smallTest.c":16:9 3 {*movsi_insn}
and is then loaded into the struct. For big-endian this is wrong because
the most significant bytes are written first in memory, storing -1 instead of
520 in s.a .
This patch swaps the 2 values in this step if the target is big-endian.
The added test creates a vector of 2 shorts and verifies the order when
it is passed in a register or in memory.
Regtested for arc and big-endian arc.
gcc/ChangeLog:
* config/arc/simdext.md: Change order for movv2hi for big-endian.
gcc/testsuite/ChangeLog:
* gcc.target/arc/movv2hi-be.c: New test.
Signed-off-by: Loeka Rogge <[email protected]>
---
gcc/config/arc/simdext.md | 11 ++++----
gcc/testsuite/gcc.target/arc/movv2hi-be.c | 32 +++++++++++++++++++++++
2 files changed, 38 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/arc/movv2hi-be.c
diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
index a53b2ba737..94ea0884b7 100644
--- a/gcc/config/arc/simdext.md
+++ b/gcc/config/arc/simdext.md
@@ -1438,11 +1438,12 @@
"reload_completed && GET_CODE (operands[1]) == CONST_VECTOR"
[(set (match_dup 0) (match_dup 2))]
{
- HOST_WIDE_INT intval = INTVAL (XVECEXP (operands[1], 0, 1)) << 16;
- intval |= INTVAL (XVECEXP (operands[1], 0, 0)) & 0xFFFF;
-
- operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
- operands[2] = GEN_INT (trunc_int_for_mode (intval, SImode));
+ int hi = !TARGET_BIG_ENDIAN;
+ int lo = !hi;
+ HOST_WIDE_INT intval = INTVAL (XVECEXP (operands[1], 0, hi)) << 16;
+ intval |= INTVAL (XVECEXP (operands[1], 0, lo)) & 0xFFFF;
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+ operands[2] = GEN_INT (trunc_int_for_mode (intval, SImode));
}
[(set_attr "type" "move,move,load,store")
(set_attr "predicable" "yes,yes,no,no")
diff --git a/gcc/testsuite/gcc.target/arc/movv2hi-be.c
b/gcc/testsuite/gcc.target/arc/movv2hi-be.c
new file mode 100644
index 0000000000..7d4b8e2e5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/movv2hi-be.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+typedef short v2hi __attribute__((vector_size(4)));
+
+__attribute__((noinline)) void foo3(short a)
+{
+ if (a != 520)
+ {
+ __builtin_abort();
+ }
+}
+
+__attribute__((noinline)) void foo2(v2hi v)
+{
+ foo3(v[0]);
+}
+
+__attribute__((noinline)) void foo(v2hi *v)
+{
+ foo2(*v);
+}
+
+int main (void)
+{
+ v2hi v;
+ v[0] = 520;
+ v[1] = -1;
+ foo(&v);
+ foo2(v);
+ return 0;
+}
--
2.43.0