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;
+}