classify_argument classified V1TImode as a single SSE eightbyte, so
aggregates containing a V1TImode member were passed and returned with
only the low 8 bytes.  Classify it as SSE + SSEUP like the other
16-byte vector modes.

PR target/128625

gcc/ChangeLog:

* config/i386/i386.cc (classify_argument): Classify E_V1TImode
as X86_64_SSE_CLASS followed by X86_64_SSEUP_CLASS.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr128625.c: New test.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Uros.
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index ad34cfeda02..8943da8b068 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -2701,10 +2701,10 @@ classify_argument (machine_mode mode, const_tree type,
     case E_V8BFmode:
     case E_V2DFmode:
     case E_V2DImode:
+    case E_V1TImode:
       classes[0] = X86_64_SSE_CLASS;
       classes[1] = X86_64_SSEUP_CLASS;
       return 2;
-    case E_V1TImode:
     case E_V1DImode:
     case E_V2SFmode:
     case E_V2SImode:
diff --git a/gcc/testsuite/gcc.target/i386/pr128625.c 
b/gcc/testsuite/gcc.target/i386/pr128625.c
new file mode 100644
index 00000000000..43640341b09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr128625.c
@@ -0,0 +1,32 @@
+/* PR target/128625 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O2" } */
+
+typedef __int128 V __attribute__((vector_size (16)));
+struct S { V m; };
+
+__attribute__((noipa)) int
+f (struct S s)
+{
+  return s.m[0] >> 64;
+}
+
+__attribute__((noipa)) struct S
+g (__int128 x)
+{
+  struct S s = { { x } };
+  return s;
+}
+
+int
+main ()
+{
+  __int128 x = ((__int128) 0x1234 << 64) | 0x5678;
+  struct S s = { { x } };
+  if (f (s) != 0x1234)
+    __builtin_abort ();
+  s = g (x);
+  if (s.m[0] != x)
+    __builtin_abort ();
+  return 0;
+}

Reply via email to