https://gcc.gnu.org/g:d7ff7435b47c5fb3b17fed14d3624176b121be64

commit r16-4962-gd7ff7435b47c5fb3b17fed14d3624176b121be64
Author: Loeka Rogge <[email protected]>
Date:   Wed Oct 29 06:57:55 2025 -0700

    arc: Fix wrong vector ordering on big-endian architecture
    
    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(movv2hi_insn): 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]>

Diff:
---
 gcc/config/arc/simdext.md                 | 14 +++++++++-----
 gcc/testsuite/gcc.target/arc/movv2hi-be.c | 32 +++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
index a53b2ba737e4..53e0c83a9246 100644
--- a/gcc/config/arc/simdext.md
+++ b/gcc/config/arc/simdext.md
@@ -1438,11 +1438,15 @@
   "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 ? 0 : 1;
+    int lo = TARGET_BIG_ENDIAN ? 1 : 0;
+    HOST_WIDE_INT hi_val = INTVAL (XVECEXP (operands[1], 0, hi));
+    HOST_WIDE_INT lo_val = INTVAL (XVECEXP (operands[1], 0, lo));
+    hi_val = zext_hwi (hi_val, 16);
+    lo_val = zext_hwi (lo_val, 16);
+    HOST_WIDE_INT intval = lo_val | (hi_val << 16);
+    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 000000000000..7d4b8e2e5c12
--- /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;
+}

Reply via email to