diff mbox series

aarch64: Remove alignment assertions [PR109661]

Message ID mptmt2bf69o.fsf@arm.com
State New
Headers show
Series aarch64: Remove alignment assertions [PR109661] | expand

Commit Message

Richard Sandiford May 11, 2023, 11:37 a.m. UTC
The trunk patch for this PR corrected the ABI for enums that have
a defined underlying type.  We shouldn't change the ABI on the branches
though, so this patch just removes the assertions that highlighed
the problem.

I think the same approach makes sense longer-term: keep the assertions
at maximum strength in trunk, and in any new branches that get cut.
Then, if the assertions trip an ABI problem, fix the problem in trunk
and remove the assertions from active branches.

The tests are the same as for the trunk version, but with all Wpsabi
message and expected output checks removed.

Tested on aarch64-linux-gnu & pushed to GCC 13.  I'll do a similar
patch for GCC 12.

Richard


gcc/
	PR target/109661
	* config/aarch64/aarch64.cc (aarch64_function_arg_alignment): Remove
	assertion.
	(aarch64_layout_arg): Likewise.

gcc/testsuite/
	PR target/109661
	* g++.target/aarch64/pr109661-1.C: New test.
	* g++.target/aarch64/pr109661-2.C: Likewise.
	* g++.target/aarch64/pr109661-3.C: Likewise.
	* g++.target/aarch64/pr109661-4.C: Likewise.
	* gcc.target/aarch64/pr109661-1.c: Likewise.
---
 gcc/config/aarch64/aarch64.cc                 |   5 -
 gcc/testsuite/g++.target/aarch64/pr109661-1.C | 122 +++++++++++++++++
 gcc/testsuite/g++.target/aarch64/pr109661-2.C | 123 ++++++++++++++++++
 gcc/testsuite/g++.target/aarch64/pr109661-3.C | 123 ++++++++++++++++++
 gcc/testsuite/g++.target/aarch64/pr109661-4.C | 123 ++++++++++++++++++
 gcc/testsuite/gcc.target/aarch64/pr109661-1.c |   5 +
 6 files changed, 496 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr109661-1.C
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr109661-2.C
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr109661-3.C
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr109661-4.C
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr109661-1.c
diff mbox series

Patch

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 0f04ab9fba0..f5db5379543 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -7495,7 +7495,6 @@  aarch64_function_arg_alignment (machine_mode mode, const_tree type,
 	  gcc_assert (known_eq (POINTER_SIZE, GET_MODE_BITSIZE (mode)));
 	  return POINTER_SIZE;
 	}
-      gcc_assert (!TYPE_USER_ALIGN (type));
       return TYPE_ALIGN (type);
     }
 
@@ -7714,10 +7713,6 @@  aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
     = aarch64_function_arg_alignment (mode, type, &abi_break,
 				      &abi_break_packed);
 
-  gcc_assert ((allocate_nvrn || alignment <= 16 * BITS_PER_UNIT)
-	      && (!alignment || abi_break < alignment)
-	      && (!abi_break_packed || alignment < abi_break_packed));
-
   /* allocate_ncrn may be false-positive, but allocate_nvrn is quite reliable.
      The following code thus handles passing by SIMD/FP registers first.  */
 
diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-1.C b/gcc/testsuite/g++.target/aarch64/pr109661-1.C
new file mode 100644
index 00000000000..c579834358b
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr109661-1.C
@@ -0,0 +1,122 @@ 
+/* { dg-options "-O2 -Wpsabi" } */
+
+#include <stdarg.h>
+
+#define ALIGN
+
+typedef __uint128_t u128_4 __attribute__((aligned(4)));
+typedef __uint128_t u128_8 __attribute__((aligned(8)));
+typedef __uint128_t u128_16 __attribute__((aligned(16)));
+typedef __uint128_t u128_32 __attribute__((aligned(32)));
+typedef __uint128_t u128;
+
+typedef __UINT64_TYPE__ u64_4 __attribute__((aligned(4)));
+typedef __UINT64_TYPE__ u64_8 __attribute__((aligned(8)));
+typedef __UINT64_TYPE__ u64_16 __attribute__((aligned(16)));
+typedef __UINT64_TYPE__ u64_32 __attribute__((aligned(32)));
+typedef __UINT64_TYPE__ u64;
+
+enum class ALIGN e128_4 : u128_4 { A };
+enum class ALIGN e128_8 : u128_8 { A };
+enum class ALIGN e128_16 : u128_16 { A };
+enum class ALIGN e128_32 : u128_32 { A };
+enum class ALIGN e128 : u128 { A };
+
+enum class ALIGN e64_4 : u64_4 { A };
+enum class ALIGN e64_8 : u64_8 { A };
+enum class ALIGN e64_16 : u64_16 { A };
+enum class ALIGN e64_32 : u64_32 { A };
+enum class ALIGN e64 : u64 { A };
+
+extern "C" {
+
+e128_4 reg_e128_4 (int x, e128_4 y) { return y; }
+
+e128_8 reg_e128_8 (int x, e128_8 y) { return y; }
+
+e128_16 reg_e128_16 (int x, e128_16 y) { return y; }
+
+e128_32 reg_e128_32 (int x, e128_32 y) { return y; }
+
+e128 reg_e128 (int x, e128 y) { return y; }
+
+e64_4 reg_e64_4 (int x, e64_4 y) { return y; }
+
+e64_8 reg_e64_8 (int x, e64_8 y) { return y; }
+
+e64_16 reg_e64_16 (int x, e64_16 y) { return y; }
+
+e64_32 reg_e64_32 (int x, e64_32 y) { return y; }
+
+e64 reg_e64 (int x, e64 y) { return y; }
+
+e128_4 stack_e128_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_4 y) { return y; }
+
+e128_8 stack_e128_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_8 y) { return y; }
+
+e128_16 stack_e128_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_16 y) { return y; }
+
+e128_32 stack_e128_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_32 y) { return y; }
+
+e128 stack_e128 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128 y) { return y; }
+
+e64_4 stack_e64_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_4 y) { return y; }
+
+e64_8 stack_e64_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_8 y) { return y; }
+
+e64_16 stack_e64_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_16 y) { return y; }
+
+e64_32 stack_e64_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_32 y) { return y; }
+
+e64 stack_e64 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64 y) { return y; }
+
+void callee (int n, ...);
+
+void
+caller ()
+{
+  callee (1, e128_4::A);
+  callee (1, e128_8::A);
+  callee (1, e128_16::A);
+  callee (1, e128_32::A);
+  callee (1, e128::A);
+
+  callee (1, e64_4::A);
+  callee (1, e64_8::A);
+  callee (1, e64_16::A);
+  callee (1, e64_32::A);
+  callee (1, e64::A);
+
+#define LOTS 1, 2, 3, 4, 5, 6, 7, 8, 9
+
+  callee (LOTS, e128_4::A);
+  callee (LOTS, e128_8::A);
+  callee (LOTS, e128_16::A);
+  callee (LOTS, e128_32::A);
+  callee (LOTS, e128::A);
+
+  callee (LOTS, e64_4::A);
+  callee (LOTS, e64_8::A);
+  callee (LOTS, e64_16::A);
+  callee (LOTS, e64_32::A);
+  callee (LOTS, e64::A);
+}
+
+void
+va (volatile void *ptr, ...)
+{
+  va_list ap;
+  va_start (ap, ptr);
+  *(volatile e128_4 *) ptr = va_arg (ap, e128_4);
+  *(volatile e128_8 *) ptr = va_arg (ap, e128_8);
+  *(volatile e128_16 *) ptr = va_arg (ap, e128_16);
+  *(volatile e128_32 *) ptr = va_arg (ap, e128_32);
+  *(volatile e128 *) ptr = va_arg (ap, e128);
+  *(volatile e64_4 *) ptr = va_arg (ap, e64_4);
+  *(volatile e64_8 *) ptr = va_arg (ap, e64_8);
+  *(volatile e64_16 *) ptr = va_arg (ap, e64_16);
+  *(volatile e64_32 *) ptr = va_arg (ap, e64_32);
+  *(volatile e64 *) ptr = va_arg (ap, e64);
+}
+
+}
diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-2.C b/gcc/testsuite/g++.target/aarch64/pr109661-2.C
new file mode 100644
index 00000000000..570335a0667
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr109661-2.C
@@ -0,0 +1,123 @@ 
+/* { dg-options "-O2 -Wpsabi" } */
+
+
+#include <stdarg.h>
+
+#define ALIGN __attribute__((aligned(8)))
+
+typedef __uint128_t u128_4 __attribute__((aligned(4)));
+typedef __uint128_t u128_8 __attribute__((aligned(8)));
+typedef __uint128_t u128_16 __attribute__((aligned(16)));
+typedef __uint128_t u128_32 __attribute__((aligned(32)));
+typedef __uint128_t u128;
+
+typedef __UINT64_TYPE__ u64_4 __attribute__((aligned(4)));
+typedef __UINT64_TYPE__ u64_8 __attribute__((aligned(8)));
+typedef __UINT64_TYPE__ u64_16 __attribute__((aligned(16)));
+typedef __UINT64_TYPE__ u64_32 __attribute__((aligned(32)));
+typedef __UINT64_TYPE__ u64;
+
+enum class ALIGN e128_4 : u128_4 { A };
+enum class ALIGN e128_8 : u128_8 { A };
+enum class ALIGN e128_16 : u128_16 { A };
+enum class ALIGN e128_32 : u128_32 { A };
+enum class ALIGN e128 : u128 { A };
+
+enum class ALIGN e64_4 : u64_4 { A };
+enum class ALIGN e64_8 : u64_8 { A };
+enum class ALIGN e64_16 : u64_16 { A };
+enum class ALIGN e64_32 : u64_32 { A };
+enum class ALIGN e64 : u64 { A };
+
+extern "C" {
+
+e128_4 reg_e128_4 (int x, e128_4 y) { return y; }
+
+e128_8 reg_e128_8 (int x, e128_8 y) { return y; }
+
+e128_16 reg_e128_16 (int x, e128_16 y) { return y; }
+
+e128_32 reg_e128_32 (int x, e128_32 y) { return y; }
+
+e128 reg_e128 (int x, e128 y) { return y; }
+
+e64_4 reg_e64_4 (int x, e64_4 y) { return y; }
+
+e64_8 reg_e64_8 (int x, e64_8 y) { return y; }
+
+e64_16 reg_e64_16 (int x, e64_16 y) { return y; }
+
+e64_32 reg_e64_32 (int x, e64_32 y) { return y; }
+
+e64 reg_e64 (int x, e64 y) { return y; }
+
+e128_4 stack_e128_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_4 y) { return y; }
+
+e128_8 stack_e128_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_8 y) { return y; }
+
+e128_16 stack_e128_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_16 y) { return y; }
+
+e128_32 stack_e128_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_32 y) { return y; }
+
+e128 stack_e128 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128 y) { return y; }
+
+e64_4 stack_e64_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_4 y) { return y; }
+
+e64_8 stack_e64_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_8 y) { return y; }
+
+e64_16 stack_e64_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_16 y) { return y; }
+
+e64_32 stack_e64_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_32 y) { return y; }
+
+e64 stack_e64 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64 y) { return y; }
+
+void callee (int n, ...);
+
+void
+caller ()
+{
+  callee (1, e128_4::A);
+  callee (1, e128_8::A);
+  callee (1, e128_16::A);
+  callee (1, e128_32::A);
+  callee (1, e128::A);
+
+  callee (1, e64_4::A);
+  callee (1, e64_8::A);
+  callee (1, e64_16::A);
+  callee (1, e64_32::A);
+  callee (1, e64::A);
+
+#define LOTS 1, 2, 3, 4, 5, 6, 7, 8, 9
+
+  callee (LOTS, e128_4::A);
+  callee (LOTS, e128_8::A);
+  callee (LOTS, e128_16::A);
+  callee (LOTS, e128_32::A);
+  callee (LOTS, e128::A);
+
+  callee (LOTS, e64_4::A);
+  callee (LOTS, e64_8::A);
+  callee (LOTS, e64_16::A);
+  callee (LOTS, e64_32::A);
+  callee (LOTS, e64::A);
+}
+
+void
+va (volatile void *ptr, ...)
+{
+  va_list ap;
+  va_start (ap, ptr);
+  *(volatile e128_4 *) ptr = va_arg (ap, e128_4);
+  *(volatile e128_8 *) ptr = va_arg (ap, e128_8);
+  *(volatile e128_16 *) ptr = va_arg (ap, e128_16);
+  *(volatile e128_32 *) ptr = va_arg (ap, e128_32);
+  *(volatile e128 *) ptr = va_arg (ap, e128);
+  *(volatile e64_4 *) ptr = va_arg (ap, e64_4);
+  *(volatile e64_8 *) ptr = va_arg (ap, e64_8);
+  *(volatile e64_16 *) ptr = va_arg (ap, e64_16);
+  *(volatile e64_32 *) ptr = va_arg (ap, e64_32);
+  *(volatile e64 *) ptr = va_arg (ap, e64);
+}
+
+}
diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-3.C b/gcc/testsuite/g++.target/aarch64/pr109661-3.C
new file mode 100644
index 00000000000..fe06868e55a
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr109661-3.C
@@ -0,0 +1,123 @@ 
+/* { dg-options "-O2 -Wpsabi" } */
+
+
+#include <stdarg.h>
+
+#define ALIGN __attribute__((aligned(16)))
+
+typedef __uint128_t u128_4 __attribute__((aligned(4)));
+typedef __uint128_t u128_8 __attribute__((aligned(8)));
+typedef __uint128_t u128_16 __attribute__((aligned(16)));
+typedef __uint128_t u128_32 __attribute__((aligned(32)));
+typedef __uint128_t u128;
+
+typedef __UINT64_TYPE__ u64_4 __attribute__((aligned(4)));
+typedef __UINT64_TYPE__ u64_8 __attribute__((aligned(8)));
+typedef __UINT64_TYPE__ u64_16 __attribute__((aligned(16)));
+typedef __UINT64_TYPE__ u64_32 __attribute__((aligned(32)));
+typedef __UINT64_TYPE__ u64;
+
+enum class ALIGN e128_4 : u128_4 { A };
+enum class ALIGN e128_8 : u128_8 { A };
+enum class ALIGN e128_16 : u128_16 { A };
+enum class ALIGN e128_32 : u128_32 { A };
+enum class ALIGN e128 : u128 { A };
+
+enum class ALIGN e64_4 : u64_4 { A };
+enum class ALIGN e64_8 : u64_8 { A };
+enum class ALIGN e64_16 : u64_16 { A };
+enum class ALIGN e64_32 : u64_32 { A };
+enum class ALIGN e64 : u64 { A };
+
+extern "C" {
+
+e128_4 reg_e128_4 (int x, e128_4 y) { return y; }
+
+e128_8 reg_e128_8 (int x, e128_8 y) { return y; }
+
+e128_16 reg_e128_16 (int x, e128_16 y) { return y; }
+
+e128_32 reg_e128_32 (int x, e128_32 y) { return y; }
+
+e128 reg_e128 (int x, e128 y) { return y; }
+
+e64_4 reg_e64_4 (int x, e64_4 y) { return y; }
+
+e64_8 reg_e64_8 (int x, e64_8 y) { return y; }
+
+e64_16 reg_e64_16 (int x, e64_16 y) { return y; }
+
+e64_32 reg_e64_32 (int x, e64_32 y) { return y; }
+
+e64 reg_e64 (int x, e64 y) { return y; }
+
+e128_4 stack_e128_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_4 y) { return y; }
+
+e128_8 stack_e128_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_8 y) { return y; }
+
+e128_16 stack_e128_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_16 y) { return y; }
+
+e128_32 stack_e128_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_32 y) { return y; }
+
+e128 stack_e128 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128 y) { return y; }
+
+e64_4 stack_e64_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_4 y) { return y; }
+
+e64_8 stack_e64_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_8 y) { return y; }
+
+e64_16 stack_e64_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_16 y) { return y; }
+
+e64_32 stack_e64_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_32 y) { return y; }
+
+e64 stack_e64 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64 y) { return y; }
+
+void callee (int n, ...);
+
+void
+caller ()
+{
+  callee (1, e128_4::A);
+  callee (1, e128_8::A);
+  callee (1, e128_16::A);
+  callee (1, e128_32::A);
+  callee (1, e128::A);
+
+  callee (1, e64_4::A);
+  callee (1, e64_8::A);
+  callee (1, e64_16::A);
+  callee (1, e64_32::A);
+  callee (1, e64::A);
+
+#define LOTS 1, 2, 3, 4, 5, 6, 7, 8, 9
+
+  callee (LOTS, e128_4::A);
+  callee (LOTS, e128_8::A);
+  callee (LOTS, e128_16::A);
+  callee (LOTS, e128_32::A);
+  callee (LOTS, e128::A);
+
+  callee (LOTS, e64_4::A);
+  callee (LOTS, e64_8::A);
+  callee (LOTS, e64_16::A);
+  callee (LOTS, e64_32::A);
+  callee (LOTS, e64::A);
+}
+
+void
+va (volatile void *ptr, ...)
+{
+  va_list ap;
+  va_start (ap, ptr);
+  *(volatile e128_4 *) ptr = va_arg (ap, e128_4);
+  *(volatile e128_8 *) ptr = va_arg (ap, e128_8);
+  *(volatile e128_16 *) ptr = va_arg (ap, e128_16);
+  *(volatile e128_32 *) ptr = va_arg (ap, e128_32);
+  *(volatile e128 *) ptr = va_arg (ap, e128);
+  *(volatile e64_4 *) ptr = va_arg (ap, e64_4);
+  *(volatile e64_8 *) ptr = va_arg (ap, e64_8);
+  *(volatile e64_16 *) ptr = va_arg (ap, e64_16);
+  *(volatile e64_32 *) ptr = va_arg (ap, e64_32);
+  *(volatile e64 *) ptr = va_arg (ap, e64);
+}
+
+}
diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-4.C b/gcc/testsuite/g++.target/aarch64/pr109661-4.C
new file mode 100644
index 00000000000..6f451ec1028
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr109661-4.C
@@ -0,0 +1,123 @@ 
+/* { dg-options "-O2 -Wpsabi" } */
+
+
+#include <stdarg.h>
+
+#define ALIGN __attribute__((aligned(32)))
+
+typedef __uint128_t u128_4 __attribute__((aligned(4)));
+typedef __uint128_t u128_8 __attribute__((aligned(8)));
+typedef __uint128_t u128_16 __attribute__((aligned(16)));
+typedef __uint128_t u128_32 __attribute__((aligned(32)));
+typedef __uint128_t u128;
+
+typedef __UINT64_TYPE__ u64_4 __attribute__((aligned(4)));
+typedef __UINT64_TYPE__ u64_8 __attribute__((aligned(8)));
+typedef __UINT64_TYPE__ u64_16 __attribute__((aligned(16)));
+typedef __UINT64_TYPE__ u64_32 __attribute__((aligned(32)));
+typedef __UINT64_TYPE__ u64;
+
+enum class ALIGN e128_4 : u128_4 { A };
+enum class ALIGN e128_8 : u128_8 { A };
+enum class ALIGN e128_16 : u128_16 { A };
+enum class ALIGN e128_32 : u128_32 { A };
+enum class ALIGN e128 : u128 { A };
+
+enum class ALIGN e64_4 : u64_4 { A };
+enum class ALIGN e64_8 : u64_8 { A };
+enum class ALIGN e64_16 : u64_16 { A };
+enum class ALIGN e64_32 : u64_32 { A };
+enum class ALIGN e64 : u64 { A };
+
+extern "C" {
+
+e128_4 reg_e128_4 (int x, e128_4 y) { return y; }
+
+e128_8 reg_e128_8 (int x, e128_8 y) { return y; }
+
+e128_16 reg_e128_16 (int x, e128_16 y) { return y; }
+
+e128_32 reg_e128_32 (int x, e128_32 y) { return y; }
+
+e128 reg_e128 (int x, e128 y) { return y; }
+
+e64_4 reg_e64_4 (int x, e64_4 y) { return y; }
+
+e64_8 reg_e64_8 (int x, e64_8 y) { return y; }
+
+e64_16 reg_e64_16 (int x, e64_16 y) { return y; }
+
+e64_32 reg_e64_32 (int x, e64_32 y) { return y; }
+
+e64 reg_e64 (int x, e64 y) { return y; }
+
+e128_4 stack_e128_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_4 y) { return y; }
+
+e128_8 stack_e128_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_8 y) { return y; }
+
+e128_16 stack_e128_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_16 y) { return y; }
+
+e128_32 stack_e128_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128_32 y) { return y; }
+
+e128 stack_e128 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e128 y) { return y; }
+
+e64_4 stack_e64_4 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_4 y) { return y; }
+
+e64_8 stack_e64_8 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_8 y) { return y; }
+
+e64_16 stack_e64_16 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_16 y) { return y; }
+
+e64_32 stack_e64_32 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64_32 y) { return y; }
+
+e64 stack_e64 (u128 x0, u128 x2, u128 x4, u128 x6, int x, e64 y) { return y; }
+
+void callee (int n, ...);
+
+void
+caller ()
+{
+  callee (1, e128_4::A);
+  callee (1, e128_8::A);
+  callee (1, e128_16::A);
+  callee (1, e128_32::A);
+  callee (1, e128::A);
+
+  callee (1, e64_4::A);
+  callee (1, e64_8::A);
+  callee (1, e64_16::A);
+  callee (1, e64_32::A);
+  callee (1, e64::A);
+
+#define LOTS 1, 2, 3, 4, 5, 6, 7, 8, 9
+
+  callee (LOTS, e128_4::A);
+  callee (LOTS, e128_8::A);
+  callee (LOTS, e128_16::A);
+  callee (LOTS, e128_32::A);
+  callee (LOTS, e128::A);
+
+  callee (LOTS, e64_4::A);
+  callee (LOTS, e64_8::A);
+  callee (LOTS, e64_16::A);
+  callee (LOTS, e64_32::A);
+  callee (LOTS, e64::A);
+}
+
+void
+va (volatile void *ptr, ...)
+{
+  va_list ap;
+  va_start (ap, ptr);
+  *(volatile e128_4 *) ptr = va_arg (ap, e128_4);
+  *(volatile e128_8 *) ptr = va_arg (ap, e128_8);
+  *(volatile e128_16 *) ptr = va_arg (ap, e128_16);
+  *(volatile e128_32 *) ptr = va_arg (ap, e128_32);
+  *(volatile e128 *) ptr = va_arg (ap, e128);
+  *(volatile e64_4 *) ptr = va_arg (ap, e64_4);
+  *(volatile e64_8 *) ptr = va_arg (ap, e64_8);
+  *(volatile e64_16 *) ptr = va_arg (ap, e64_16);
+  *(volatile e64_32 *) ptr = va_arg (ap, e64_32);
+  *(volatile e64 *) ptr = va_arg (ap, e64);
+}
+
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr109661-1.c b/gcc/testsuite/gcc.target/aarch64/pr109661-1.c
new file mode 100644
index 00000000000..04109170b37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr109661-1.c
@@ -0,0 +1,5 @@ 
+/* { dg-options "-O2 -Wpsabi" } */
+
+enum __attribute__((aligned(16))) e { E };
+
+enum e test (int x, enum e y) { return y; }