[v2,2/2] aarch64: Fix bit-field alignment in param passing [PR105549]

Message ID 20221129134728.242212-2-christophe.lyon@arm.com
State Accepted
Headers
Series [v2,1/2] aarch64: fix warning emission for ABI break since GCC 9.1 |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Christophe Lyon Nov. 29, 2022, 1:47 p.m. UTC
  While working on enabling DFP for AArch64, I noticed new failures in
gcc.dg/compat/struct-layout-1.exp (t028) which were not actually
caused by DFP types handling. These tests are generated during 'make
check' and enabling DFP made generation different (not sure if new
non-DFP tests are generated, or if existing ones are generated
differently, the tests in question are huge and difficult to compare).

Anyway, I reduced the problem to what I attach at the end of the new
gcc.target/aarch64/aapcs64/va_arg-17.c test and rewrote it in the same
scheme as other va_arg* AArch64 tests.  Richard Sandiford further
reduced this to a non-vararg function, added as a second testcase.

This is a tough case mixing bit-fields and alignment, where
aarch64_function_arg_alignment did not follow what its descriptive
comment says: we want to use the natural alignment of the bit-field
type only if the user didn't reduce the alignment for the bit-field
itself.

The patch also adds a comment and assert that would help someone who
has to look at this area again.

The fix would be very small, except that this introduces a new ABI
break, and we have to warn about that.  Since this actually fixes a
problem introduced in GCC 9.1, we keep the old computation to detect
when we now behave differently.

This patch adds two new tests (va_arg-17.c and
pr105549.c). va_arg-17.c contains the reduced offending testcase from
struct-layout-1.exp for reference.  We update some tests introduced by
the previous patch, where parameters with bit-fields and packed
attribute now emit a different warning.

2022-11-28  Christophe Lyon  <christophe.lyon@arm.com>
	    Richard Sandiford  <richard.sandiford@arm.com>

	gcc/
	PR target/105549
	* config/aarch64/aarch64.cc (aarch64_function_arg_alignment):
	Check DECL_PACKED for bitfield.
	(aarch64_layout_arg): Warn when parameter passing ABI changes.
	(aarch64_function_arg_boundary): Do not warn here.
	(aarch64_gimplify_va_arg_expr): Warn when parameter passing ABI
	changes.

	gcc/testsuite/
	PR target/105549
	* gcc.target/aarch64/bitfield-abi-warning-align16-O2.c: Update.
	* gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c: Update.
	* gcc.target/aarch64/bitfield-abi-warning-align32-O2.c: Update.
	* gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c: Update.
	* gcc.target/aarch64/aapcs64/va_arg-17.c: New test.
	* gcc.target/aarch64/pr105549.c: New test.
---
 gcc/config/aarch64/aarch64.cc                 | 148 ++++++++++++++----
 .../gcc.target/aarch64/aapcs64/va_arg-17.c    | 105 +++++++++++++
 .../bitfield-abi-warning-align16-O2-extra.c   |  64 ++++----
 .../aarch64/bitfield-abi-warning-align16-O2.c |  48 +++---
 .../bitfield-abi-warning-align32-O2-extra.c   | 131 +++++++---------
 .../aarch64/bitfield-abi-warning-align32-O2.c | 141 ++++++++---------
 gcc/testsuite/gcc.target/aarch64/pr105549.c   |  12 ++
 7 files changed, 414 insertions(+), 235 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg-17.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr105549.c
  

Patch

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 3623df5bd94..a6d95dd85bf 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -7265,14 +7265,18 @@  aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode,
    bits.  The idea is to suppress any stronger alignment requested by
    the user and opt for the natural alignment (specified in AAPCS64 \S
    4.1).  ABI_BREAK is set to the old alignment if the alignment was
-   incorrectly calculated in versions of GCC prior to GCC-9.  This is
-   a helper function for local use only.  */
+   incorrectly calculated in versions of GCC prior to GCC-9.
+   ABI_BREAK_PACKED is set to the old alignment if it was incorrectly
+   calculated in versions between GCC-9 and GCC-13.  This is a helper
+   function for local use only.  */
 
 static unsigned int
 aarch64_function_arg_alignment (machine_mode mode, const_tree type,
-				unsigned int *abi_break)
+				unsigned int *abi_break,
+				unsigned int *abi_break_packed)
 {
   *abi_break = 0;
+  *abi_break_packed = 0;
   if (!type)
     return GET_MODE_ALIGNMENT (mode);
 
@@ -7288,6 +7292,7 @@  aarch64_function_arg_alignment (machine_mode mode, const_tree type,
     return TYPE_ALIGN (TREE_TYPE (type));
 
   unsigned int alignment = 0;
+  unsigned int bitfield_alignment_with_packed = 0;
   unsigned int bitfield_alignment = 0;
   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     if (TREE_CODE (field) == FIELD_DECL)
@@ -7307,11 +7312,30 @@  aarch64_function_arg_alignment (machine_mode mode, const_tree type,
 	   but gains 8-byte alignment and size thanks to "e".  */
 	alignment = std::max (alignment, DECL_ALIGN (field));
 	if (DECL_BIT_FIELD_TYPE (field))
-	  bitfield_alignment
-	    = std::max (bitfield_alignment,
-			TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)));
+	  {
+	    /* Take the bit-field type's alignment into account only
+	       if the user didn't reduce this field's alignment with
+	       the packed attribute.  */
+	    if (!DECL_PACKED (field))
+	      bitfield_alignment
+		= std::max (bitfield_alignment,
+			    TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)));
+
+	    /* Compute the alignment even if the bit-field is
+	       packed, so that we can emit a warning in case the
+	       alignment changed between GCC versions.  */
+	    bitfield_alignment_with_packed
+	      = std::max (bitfield_alignment_with_packed,
+			  TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)));
+	  }
       }
 
+  /* Emit a warning if the alignment is different when taking the
+     'packed' attribute into account.  */
+  if (bitfield_alignment != bitfield_alignment_with_packed
+      && bitfield_alignment_with_packed > alignment)
+    *abi_break_packed = bitfield_alignment_with_packed;
+
   if (bitfield_alignment > alignment)
     {
       *abi_break = alignment;
@@ -7337,6 +7361,7 @@  aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
   bool allocate_ncrn, allocate_nvrn;
   HOST_WIDE_INT size;
   unsigned int abi_break;
+  unsigned int abi_break_packed;
 
   /* We need to do this once per argument.  */
   if (pcum->aapcs_arg_processed)
@@ -7348,9 +7373,57 @@  aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
        && (currently_expanding_function_start
 	   || currently_expanding_gimple_stmt));
 
+  /* There are several things to note here:
+
+     - Both the C and AAPCS64 interpretations of a type's alignment should
+       give a value that is no greater than the type's size.
+
+     - Types bigger than 16 bytes are passed indirectly.
+
+     - If an argument of type T is passed indirectly, TYPE and MODE describe
+       a pointer to T rather than T iself.
+
+     It follows that the AAPCS64 alignment of TYPE must be no greater
+     than 16 bytes.
+
+     Versions prior to GCC 9.1 ignored a bitfield's underlying type
+     and so could calculate an alignment that was too small.  If this
+     happened for TYPE then ABI_BREAK is this older, too-small alignment.
+
+     Although GCC 9.1 fixed that bug, it introduced a different one:
+     it would consider the alignment of a bitfield's underlying type even
+     if the field was packed (which should have the effect of overriding
+     the alignment of the underlying type).  This was fixed in GCC 13.1.
+
+     As a result of this bug, GCC 9 to GCC 12 could calculate an alignment
+     that was too big.  If this happened for TYPE, ABI_BREAK_PACKED is
+     this older, too-big alignment.
+
+     Also, the fact that GCC 9 to GCC 12 considered irrelevant
+     alignments meant they could calculate type alignments that were
+     bigger than the type's size, contrary to the assumption above.
+     The handling of register arguments was nevertheless (and justifiably)
+     written to follow the assumption that the alignment can never be
+     greater than the size.  The same was not true for stack arguments;
+     their alignment was instead handled by MIN bounds in
+     aarch64_function_arg_boundary.
+
+     The net effect is that, if GCC 9 to GCC 12 incorrectly calculated
+     an alignment of more than 16 bytes for TYPE then:
+
+     - If the argument was passed in registers, these GCC versions
+       would treat the alignment as though it was *less than* 16 bytes.
+
+     - If the argument was passed on the stack, these GCC versions
+       would treat the alignment as though it was *equal to* 16 bytes.
+
+     Both behaviors were wrong, but in different cases.  */
   unsigned int alignment
-    = aarch64_function_arg_alignment (mode, type, &abi_break);
-  gcc_assert (!alignment || abi_break < alignment);
+    = aarch64_function_arg_alignment (mode, type, &abi_break,
+				      &abi_break_packed);
+  gcc_assert (alignment <= 16 * BITS_PER_UNIT
+	      && (!alignment || abi_break < alignment)
+	      && (!abi_break_packed || alignment < abi_break_packed));
 
   pcum->aapcs_arg_processed = true;
 
@@ -7488,19 +7561,29 @@  aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
       /* C.8 if the argument has an alignment of 16 then the NGRN is
 	 rounded up to the next even number.  */
       if (nregs == 2
-	  && ncrn % 2
+	  && ncrn % 2)
+	{
+	  /* Emit a warning if the alignment changed when taking the
+	     'packed' attribute into account.  */
+	  if (warn_pcs_change
+	      && abi_break_packed
+	      && ((abi_break_packed == 16 * BITS_PER_UNIT)
+		  != (alignment == 16 * BITS_PER_UNIT)))
+	    inform (input_location, "parameter passing for argument of type "
+		    "%qT changed in GCC 13.1", type);
+
 	  /* The == 16 * BITS_PER_UNIT instead of >= 16 * BITS_PER_UNIT
 	     comparison is there because for > 16 * BITS_PER_UNIT
 	     alignment nregs should be > 2 and therefore it should be
 	     passed by reference rather than value.  */
-	  && (aarch64_function_arg_alignment (mode, type, &abi_break)
-	      == 16 * BITS_PER_UNIT))
-	{
-	  if (warn_pcs_change && abi_break)
-	    inform (input_location, "parameter passing for argument of type "
-		    "%qT changed in GCC 9.1", type);
-	  ++ncrn;
-	  gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
+	  if (alignment == 16 * BITS_PER_UNIT)
+	    {
+	      if (warn_pcs_change && abi_break)
+		inform (input_location, "parameter passing for argument of type "
+			"%qT changed in GCC 9.1", type);
+	      ++ncrn;
+	      gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
+	    }
 	}
 
       /* If an argument with an SVE mode needs to be shifted up to the
@@ -7553,8 +7636,14 @@  aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 on_stack:
   pcum->aapcs_stack_words = size / UNITS_PER_WORD;
 
-  if (aarch64_function_arg_alignment (mode, type, &abi_break)
-      == 16 * BITS_PER_UNIT)
+  if (warn_pcs_change
+      && abi_break_packed
+      && ((abi_break_packed >= 16 * BITS_PER_UNIT)
+	  != (alignment >= 16 * BITS_PER_UNIT)))
+    inform (input_location, "parameter passing for argument of type "
+	    "%qT changed in GCC 13.1", type);
+
+  if (alignment == 16 * BITS_PER_UNIT)
     {
       int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD);
       if (pcum->aapcs_stack_size != new_size)
@@ -7676,16 +7765,13 @@  static unsigned int
 aarch64_function_arg_boundary (machine_mode mode, const_tree type)
 {
   unsigned int abi_break;
+  unsigned int abi_break_packed;
   unsigned int alignment = aarch64_function_arg_alignment (mode, type,
-							   &abi_break);
+							   &abi_break,
+							   &abi_break_packed);
+  /* We rely on aarch64_layout_arg and aarch64_gimplify_va_arg_expr
+     to emit warnings about ABI incompatibility.  */
   alignment = MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
-  if (abi_break && warn_psabi)
-    {
-      abi_break = MIN (MAX (abi_break, PARM_BOUNDARY), STACK_BOUNDARY);
-      if (alignment != abi_break)
-	inform (input_location, "parameter passing for argument of type "
-		"%qT changed in GCC 9.1", type);
-    }
   return alignment;
 }
 
@@ -19544,8 +19630,10 @@  aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   size = int_size_in_bytes (type);
 
   unsigned int abi_break;
+  unsigned int abi_break_packed;
   align
-    = aarch64_function_arg_alignment (mode, type, &abi_break) / BITS_PER_UNIT;
+    = aarch64_function_arg_alignment (mode, type, &abi_break, &abi_break_packed)
+    / BITS_PER_UNIT;
 
   dw_align = false;
   adjust = 0;
@@ -19588,6 +19676,10 @@  aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
       rsize = ROUND_UP (size, UNITS_PER_WORD);
       nregs = rsize / UNITS_PER_WORD;
 
+      if (align <= 8 && abi_break_packed && warn_psabi)
+	inform (input_location, "parameter passing for argument of type "
+		"%qT changed in GCC 13.1", type);
+
       if (align > 8)
 	{
 	  if (abi_break && warn_psabi)
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg-17.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg-17.c
new file mode 100644
index 00000000000..24895c3ab48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg-17.c
@@ -0,0 +1,105 @@ 
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test covers a corner case where a composite type parameter fits in one
+   register: we do not need a double-word alignment when accessing it in the
+   va_arg stack area.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg-17.c"
+#include "type-def.h"
+
+enum E6 { e6_0, e6_1, e6_2, e6_3, e6_65533 = 65533, e6_65534, e6_65535 };
+typedef enum E6 Tal16E6 __attribute__((aligned (16)));
+typedef unsigned int Tuint;
+
+int fails;
+
+union S2844 {
+  Tuint a:((((10) - 1) & 31) + 1);
+  Tal16E6 __attribute__((aligned (2), packed)) b:31;
+  struct{}c[0];
+} ;
+union S2844 s2844;
+union S2844 a2844[5];
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  memset (&s2844, '\0', sizeof (s2844));
+  memset (a2844, '\0', sizeof (a2844));
+  s2844.a = 799U;
+  a2844[2].a = 586U;
+}
+
+#include "abitest.h"
+#else
+  ARG       (int          , 1        , W0 , LAST_NAMED_ARG_ID)
+  DOTS
+  ANON_PROMOTED  (float   , 1.0f, double, 1.0, D0, 1)
+  ANON      (union S2844  , s2844    , X1 , 2)
+  ANON      (long long    , 2LL      , X2 , 3)
+  ANON      (union  S2844 , a2844[2] , X3 , 4)
+  LAST_ANON (union  S2844 , a2844[2] , X4 , 5)
+#endif
+
+#if 0
+  /* This test is derived from a case generated by struct-layout-1.exp:  */
+
+enum E6 { e6_0, e6_1, e6_2, e6_3, e6_65533 = 65533, e6_65534, e6_65535 };
+typedef enum E6 Tal16E6 __attribute__((aligned (16)));
+typedef unsigned int Tuint;
+
+int fails;
+
+union S2844 {
+  Tuint a:((((10) - 1) & 31) + 1);
+  Tal16E6 __attribute__((aligned (2), packed)) b:31;
+  struct{}c[0];
+} ;
+union S2844 s2844;
+union S2844 a2844[5];
+
+typedef __builtin_va_list __gnuc_va_list;
+typedef __gnuc_va_list va_list;
+
+void check2844va (int z, ...) {
+  union S2844 arg, *p;
+  va_list ap;
+
+  __builtin_va_start(ap,z);
+  if (__builtin_va_arg(ap,double) != 1.0)
+    printf ("fail %d.%d\n", 2844, 0), ++fails;
+
+  p = &s2844;
+  arg = __builtin_va_arg(ap,union S2844);  /* This would fail.  */
+  if (p->a != arg.a)
+    printf ("fail %d.%d\n", 2844, 1), ++fails;
+
+  if (__builtin_va_arg(ap,long long) != 3LL)
+    printf ("fail %d.%d\n", 2844, 2), ++fails;
+
+  p = &a2844[2];
+  arg = __builtin_va_arg(ap,union S2844);  /* This would fail.  */
+  if (p->a != arg.a)
+    printf ("fail %d.%d\n", 2844, 3), ++fails;
+
+  arg = __builtin_va_arg(ap,union S2844);  /* This would fail.  */
+  if (p->a != arg.a)
+    printf ("fail %d.%d\n", 2844, 4), ++fails;
+
+  __builtin_va_end(ap);
+}
+
+int main (void) {
+  int i, j;
+  memset (&s2844, '\0', sizeof (s2844));
+  memset (a2844, '\0', sizeof (a2844));
+  s2844.a = 799U;
+  a2844[2].a = 586U;
+  check2844va (1, 1.0, s2844, 2LL, a2844[2], a2844[2]);
+  exit (fails != 0);
+}
+#endif /* 0 */
diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c
index 3e38cac149d..f248a129509 100644
--- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c
+++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c
@@ -7,9 +7,9 @@ 
 #include "bitfield-abi-warning.h"
 
 /* In f1, f2, f4, f8, f16, f16p (and stdarg versions):  */
-/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 12 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 12 } } */
 /* In fp, f1p, f2p, f4p, f8p (and stdarg versions):  */
-/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 } } */
 
 /* Bitfield parameter in registers.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} "" { target *-*-* } 47 } f1 */
@@ -17,11 +17,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} "" { target *-*-* } 49 } f4 */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} "" { target *-*-* } 50 } f8 */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 53 }  fp */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 54 } f1p */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 55 } f2p */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 56 } f4p */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 57 } f8p */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 53 }  fp */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 54 } f1p */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 55 } f2p */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 56 } f4p */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 57 } f8p */
 
 /* Bitfield call argument in registers.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} ""  { target *-*-* } 60 } g1 */
@@ -29,11 +29,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} ""  { target *-*-* } 62 } g4 */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} ""  { target *-*-* } 63 } g8 */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 66 }  gp */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 67 } g1p */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 68 } g2p */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 69 } g4p */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 70 } g8p */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 66 }  gp */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 67 } g1p */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 68 } g2p */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 69 } g4p */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 70 } g8p */
 
 
 /* Bitfield parameter in stack.  */
@@ -42,11 +42,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} "" { target *-*-* } 76 } f4_stack */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} "" { target *-*-* } 77 } f8_stack */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 80 }  fp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 81 } f1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 82 } f2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 83 } f4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 84 } f8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 80 }  fp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 81 } f1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 82 } f2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 83 } f4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 84 } f8p_stack */
 
 /* Bitfield call argument in stack.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} ""  { target *-*-* } 87 } g1_stack */
@@ -54,11 +54,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} ""  { target *-*-* } 89 } g4_stack */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} ""  { target *-*-* } 90 } g8_stack */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 93 }  gp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 94 } g1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 95 } g2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 96 } g4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 97 } g8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 93 }  gp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 94 } g1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 95 } g2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 96 } g4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 97 } g8p_stack */
 
 
 /* Bitfield parameter in stdarg.  */
@@ -67,11 +67,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} "" { target *-*-* } 103 } f4_stdarg */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} "" { target *-*-* } 104 } f8_stdarg */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 107 }  fp_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 108 } f1p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 109 } f2p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 110 } f4p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 111 } f8p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 107 }  fp_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 108 } f1p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 109 } f2p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 110 } f4p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 111 } f8p_stdarg */
 
 /* Bitfield call argument in stdarg.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} ""  { target *-*-* } 114 } g1_stdarg */
@@ -79,8 +79,8 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} ""  { target *-*-* } 116 } g4_stdarg */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} ""  { target *-*-* } 117 } g8_stdarg */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 120 }  gp_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 121 } g1p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 122 } g2p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 123 } g4p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 124 } g8p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 120 }  gp_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 121 } g1p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 122 } g2p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 123 } g4p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 124 } g8p_stdarg */
diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c
index 39c5f9228ee..268c7aa90cb 100644
--- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c
+++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c
@@ -7,9 +7,9 @@ 
 #include "bitfield-abi-warning.h"
 
 /* In f1, f2, f4, f8, f16, f16p (and stdarg versions):  */
-/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 12 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 12 } } */
 /* In fp, f1p, f2p, f4p, f8p (and stdarg versions):  */
-/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 } } */
 
 /* Bitfield parameter in registers.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} "" { target *-*-* } 47 } f1 */
@@ -17,15 +17,9 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} "" { target *-*-* } 49 } f4 */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} "" { target *-*-* } 50 } f8 */
 
-/* No change in parameter passing in GCC 9.1 for lines 53-57 (fp, f1p, f2p,
-   f4p, f8p) (because the argument fits in a single register).  Should not
-   warn, but aarch64_function_arg_boundary would need to take the argument size
-   into account as well as whether it's passed via registers or the stack.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 53 }  fp */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 54 } f1p */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 55 } f2p */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 56 } f4p */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 57 } f8p */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 53-57 (fp,
+   f1p, f2p, f4p, f8p) because the argument fits in a single register.
+   No warning expected.  */
 
 /* Bitfield call argument in registers.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} ""  { target *-*-* } 60 } g1 */
@@ -43,11 +37,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} "" { target *-*-* } 76 } f4_stack */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} "" { target *-*-* } 77 } f8_stack */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 80 }  fp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 81 } f1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 82 } f2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 83 } f4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 84 } f8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 80 }  fp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 81 } f1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 82 } f2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 83 } f4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 84 } f8p_stack */
 
 /* Bitfield call argument in stack.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} ""  { target *-*-* } 87 } g1_stack */
@@ -55,11 +49,11 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} ""  { target *-*-* } 89 } g4_stack */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} ""  { target *-*-* } 90 } g8_stack */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 93 }  gp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 94 } g1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 95 } g2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 96 } g4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 97 } g8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 93 }  gp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 94 } g1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 95 } g2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 96 } g4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 97 } g8p_stack */
 
 
 /* Bitfield parameter in stdarg.  */
@@ -68,14 +62,14 @@ 
 /* { dg-note {parameter passing for argument of type 'struct S4' changed in GCC 9.1} "" { target *-*-* } 103 } f4_stdarg */
 /* { dg-note {parameter passing for argument of type 'struct S8' changed in GCC 9.1} "" { target *-*-* } 104 } f8_stdarg */
 
-/* Parameter passing for these should not have changed in GCC 9.1 (PR 105549).
+/* FIXME Parameter passing for these should not have changed in GCC 9.1 (PR 105549).
    Fortunately we warn. Note the discrepancy with lines 120-124 below: we warn
    in the callee, but not in the caller.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1} "" { target *-*-* } 107 }  fp_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 108 } f1p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 109 } f2p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 110 } f4p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 111 } f8p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1} "" { target *-*-* } 107 }  fp_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 108 } f1p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 109 } f2p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 110 } f4p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 111 } f8p_stdarg */
 
 /* Bitfield call argument in stdarg.  */
 /* { dg-note {parameter passing for argument of type 'struct S1' changed in GCC 9.1} ""  { target *-*-* } 114 } g1_stdarg */
diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c
index 70671ceda09..a8a50b35e8e 100644
--- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c
+++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c
@@ -11,109 +11,96 @@ 
 /* { dg-final { scan-assembler-times "ldr\tx0, \\\[x1\\\]" 10 } } */
 
 /* In fp, f1p, f2p, f4p, f8p (and stdarg versions):  */
-/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 } } */
 
 /* In f16p (and stdarg version):  */
-/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 2 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 2 } } */
 
-/* In f1_stack, f2_stack, f4_stack, f8_stack, f16_stack, f8p_stack:  */
-/* { dg-final { scan-assembler-times "ldr\tx\[0-9\]+, \\\[sp, 8\\\]" 6 { xfail *-*-* } } } */
-
-/* In fp_stack, f1p_stack:  */
-/* { dg-final { scan-assembler-times "ldrb\tw0, \\\[sp, 8\\\]" 2 { xfail *-*-* } } } */
-
-/* In f2p_stack:  */
-/* { dg-final { scan-assembler-times "ldrh\tw0, \\\[sp, 8\\\]" 1 { xfail *-*-* } } } */
-
-/* In f4p_stack:  */
-/* { dg-final { scan-assembler-times "ldr\tw0, \\\[sp, 8\\\]" 1 { xfail *-*-* } } } */
+/* In f1_stack, f2_stack, f4_stack, f8_stack, f16_stack, fp_stack,
+   f1p_stack, f2p_stack, f4p_stack, f8p_stack:  */
+/* { dg-final { scan-assembler-times "ldr\tx\[0-9\]+, \\\[sp, 8\\\]" 10 } } */
 
 /* In f16p_stack:  */
-/* { dg-final { scan-assembler-times "ldr\tx0, \\\[sp, 16\\\]" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "ldr\tx\[0-9\]+, \\\[sp, 16\\\]" 1 } } */
 
 /* Bitfield parameter in registers.  */
-/* No change in parameter passing in GCC 9.1 for lines 47-51 (f1, f2, f4, f8, f16)
-   because the overall alignment is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 47-51 (f1,
+   f2, f4, f8, f16) because the overall alignment is > 16.  No warning
+   expected.  */
 
-/* No change in parameter passing in GCC 9.1 for lines 53-57 (fp, f1p, f2p,
-   f4p, f8p) because the argument fits in a single register.  Should not warn,
-   but aarch64_function_arg_boundary would need to take the argument size into
-   account as well as whether it's passed via registers or the stack.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}  "" { target *-*-* } 53 } fp */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 54 } f1p */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 55 } f2p */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 56 } f4p */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 57 } f8p */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 53-57 (fp,
+   f1p, f2p, f4p, f8p) because the alignment that GCC 9.1 calculated for the
+   underlying type was 32 bytes (above the maximum expected of 16).  */
 
-/* Changed in GCC 9.1, but we fail to emit a warning since GCC 11 (was OK with GCC 9).  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { xfail *-*-* } 58 } f16p */
+/* Changed again in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 13.1} "" { target *-*-* } 58 } f16p */
 
 
 /* Bitfield call argument in registers.  */
-/* No change in parameter passing in GCC 9.1 for lines 60-64 (g1, g2, g4, g8, g16)
-   because the overall alignment is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 60-64 (g1,
+   g2, g4, g8, g16) because the overall alignment is > 16.  No warning
+   expected.  */
 
-/* No change in parameter passing in GCC 9.1 for lines 66-70 (gp, g1p, g2p,
-   g4p, g8p), no warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 66-70 (gp,
+   g1p, g2p, g4p, g8p), no warning expected.  */
 
-/* Changed in GCC 9.1, but we fail to emit a warning.  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { xfail *-*-* } 71 } g16p */
+/* Changed again in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 13.1} "" { target *-*-* } 71 } g16p */
 
 
 /* Bitfield parameter in stack.  */
-/* No change in parameter passing in GCC 9.1 for lines 74-78 (f1_stack,
-   f2_stack, f4_stack, f8_stack, f16_stack) because the overall alignment is >
-   16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 74-78
+   (f1_stack, f2_stack, f4_stack, f8_stack, f16_stack) because the overall
+   alignment is > 16.  No warning expected.  */
 
-/* Changed in GCC 9.1.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}  "" { target *-*-* } 80 } fp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 81 } f1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 82 } f2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 83 } f4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 84 } f8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1}  "" { target *-*-* } 80 } fp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 81 } f1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 82 } f2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 83 } f4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 84 } f8p_stack */
 
-/* No change in parameter passing in GCC 9.1 for line 85 (f16p_stack) because
-   the overall alignment is >= 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for line 85
+   (f16p_stack).  No warning expected.  */
 
 
 /* Bitfield call argument in stack.  */
-/* No change in parameter passing in GCC 9.1 for lines 87-91 (g1_stack,
-   g2_stack, g4_stack, g8_stack, g16_stack) because the overall alignment is >
-   16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC13.1 for lines 87-91
+   (g1_stack, g2_stack, g4_stack, g8_stack, g16_stack) because the overall
+   alignment is > 16.  No warning expected.  */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}  "" { target *-*-* } 93 } gp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 94 } g1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 95 } g2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 96 } g4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 97 } g8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1}  "" { target *-*-* } 93 } gp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 94 } g1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 95 } g2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 96 } g4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 97 } g8p_stack */
 
 
-/* No change in parameter passing in GCC 9.1 for line 98 (g16p_stack).  No
-   warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for line 98
+   (g16p_stack).  No warning expected.  */
 
 
 /* Bitfield parameter in stdarg.  */
-/* No change in parameter passing in GCC 9.1 for lines 101-105 (f1_stdarg,
-   f2_stdarg, f4_stdarg, f8_stdarg, f16_stdarg) because the overall alignment
-   is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 101-105
+   (f1_stdarg, f2_stdarg, f4_stdarg, f8_stdarg, f16_stdarg) because the overall
+   alignment is > 16.  No warning expected.  */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}   "" { target *-*-* } 107 } fp_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1}  "" { target *-*-* } 108 } f1p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1}  "" { target *-*-* } 109 } f2p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1}  "" { target *-*-* } 110 } f4p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1}  "" { target *-*-* } 111 } f8p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1}   "" { target *-*-* } 107 } fp_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1}  "" { target *-*-* } 108 } f1p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1}  "" { target *-*-* } 109 } f2p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1}  "" { target *-*-* } 110 } f4p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1}  "" { target *-*-* } 111 } f8p_stdarg */
 
-/* No change in parameter passing in GCC 9.1 for line 112 (f16p_stdarg).
-   Should not warn.  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { target *-*-* } 112 } f16p_stdarg */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for line 112 (f16p_stdarg).
+   No warning expected.  */
 
 /* Bitfield call argument in stdarg.  */
-/* No change in parameter passing in GCC 9.1 for lines 114-118 (g1_stdarg,
-   g2_stdarg, g4_stdarg, g8_stdarg, g16_stdarg) because the overall alignment
-   is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 114-118
+   (g1_stdarg, g2_stdarg, g4_stdarg, g8_stdarg, g16_stdarg) because the overall
+   alignment is > 16.  No warning expected.  */
 
-/* No change in parameter passing in GCC 9.1 for lines 120-124 (gp_stdarg,
-   g1p_stdarg, g2p_stdarg, g4p_stdarg, g8p_stdarg), no warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 120-124
+   (gp_stdarg, g1p_stdarg, g2p_stdarg, g4p_stdarg, g8p_stdarg), no warning
+   expected.  */
 
-/* Changed in GCC 9.1, but we fail to emit a warning.  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { xfail *-*-* } 125 } g16p_stdarg */
+/* Changed again in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 13.1} "" { target *-*-* } 125 } g16p_stdarg */
diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c
index 81797acc0d4..e872de3dbe0 100644
--- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c
+++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c
@@ -10,115 +10,104 @@ 
 /* { dg-final { scan-assembler-times "ldr\tx0, \\\[x1\\\]" 10 } } */
 
 /* In fp, f1p, f2p, f4p, f8p (and stdarg versions):  */
-/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w1, 1" 10 } } */
 
 /* In f16p (and stdarg version):  */
-/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 2 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "and\tw0, w2, 1" 2 } } */
 
 /* In f1_stack, f2_stack, f4_stack, f8_stack, f16_stack, f8p_stack:  */
-/* { dg-final { scan-assembler-times "ldr\tx\[0-9\]+, \\\[sp, 8\\\]" 6 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "ldr\tx\[0-9\]+, \\\[sp, 8\\\]" 6 } } */
 
 /* In fp_stack, f1p_stack:  */
-/* { dg-final { scan-assembler-times "ldrb\tw0, \\\[sp, 8\\\]" 2 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "ldrb\tw0, \\\[sp, 8\\\]" 2 } } */
 
 /* In f2p_stack:  */
-/* { dg-final { scan-assembler-times "ldrh\tw0, \\\[sp, 8\\\]" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "ldrh\tw0, \\\[sp, 8\\\]" 1 } } */
 
 /* In f4p_stack:  */
-/* { dg-final { scan-assembler-times "ldr\tw0, \\\[sp, 8\\\]" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "ldr\tw0, \\\[sp, 8\\\]" 1 } } */
 
 /* In f16p_stack:  */
-/* { dg-final { scan-assembler-times "ldr\tx0, \\\[sp, 16\\\]" 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "ldr\tx0, \\\[sp, 16\\\]" 1 } } */
 
 /* Bitfield parameter in registers.  */
-/* No change in parameter passing in GCC 9.1 for lines 47-51 (f1, f2, f4, f8, f16)
-   because the overall alignment is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 47-51 (f1,
+   f2, f4, f8, f16) because the overall alignment is > 16.  No warning
+   expected.  */
 
-/* No change in parameter passing in GCC 9.1 for lines 53-57 (fp, f1p, f2p,
-   f4p, f8p) because the argument fits in a single register.  Should not warn,
-   but aarch64_function_arg_boundary would need to take the argument size into
-   account as well as whether it's passed via registers or the stack.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}  "" { target *-*-* } 53 } fp */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 54 } f1p */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 55 } f2p */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 56 } f4p */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 57 } f8p */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 53-57 (fp,
+   f1p, f2p, f4p, f8p) because the argument fits in a single register.
+   No warning expected.  */
 
-/* Changed in GCC 9.1, but we fail to emit a warning since GCC 11 (was OK with GCC 9).  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { xfail *-*-* } 58 } f16p */
+/* Changes in GCC 13.1, we restore the same codegen as before GCC 9.1 .  */
+/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 13.1} "" { target *-*-* } 58 } f16p */
 
 
 /* Bitfield call argument in registers.  */
-/* No change in parameter passing in GCC 9.1 for lines 60-64 (g1, g2, g4, g8, g16)
-   because the overall alignment is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 60-64 (g1,
+   g2, g4, g8, g16) because the overall alignment is > 16.  No warning
+   expected.  */
 
-/* No change in parameter passing in GCC 9.1 for lines 66-70 (gp, g1p, g2p,
-   g4p, g8p), no warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 66-70 (gp,
+   g1p, g2p, g4p, g8p), no warning expected.  */
 
-/* Changed in GCC 9.1, but we fail to emit a warning.  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { xfail *-*-* } 71 } g16p */
+/* Changed in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 13.1} "" { target *-*-* } 71 } g16p */
 
 
 /* Bitfield parameter in stack.  */
-/* No change in parameter passing in GCC 9.1 for lines 74-78 (f1_stack,
-   f2_stack, f4_stack, f8_stack, f16_stack) because the overall alignment is >
-   16.  No warning expected.  */
-
-/* No change in parameter passing in GCC 9.1 for lines 80-84 (fp_stack,
-   f1p_stack, f2p_stack, f4p_stack, f8p_stack) because the argument fits in a
-   single register.  Should not warn, but aarch64_function_arg_boundary would
-   need to take the argument size into account as well as whether it's passed
-   via registers or the stack.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}  "" { target *-*-* } 80 } fp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 81 } f1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 82 } f2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 83 } f4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 84 } f8p_stack */
-
-/* No change in parameter passing in GCC 9.1 for line 85 (f16p_stack) because
-   the overall alignment is >= 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 74-78
+   (f1_stack, f2_stack, f4_stack, f8_stack, f16_stack) because the overall
+   alignment is > 16.  No warning expected.  */
+
+/* Changed in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1}  "" { target *-*-* } 80 } fp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 81 } f1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 82 } f2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 83 } f4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 84 } f8p_stack */
+
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for line 85
+   (f16p_stack).  No warning expected.  */
 
 /* Bitfield call argument in stack.  */
-/* No change in parameter passing in GCC 9.1 for lines 87-91 (g1_stack,
-   g2_stack, g4_stack, g8_stack, g16_stack) because the overall alignment is >
-   16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 87-91
+   (g1_stack, g2_stack, g4_stack, g8_stack, g16_stack) because the overall
+   alignment is > 16.  No warning expected.  */
 
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}  "" { target *-*-* } 93 } gp_stack */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1} "" { target *-*-* } 94 } g1p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1} "" { target *-*-* } 95 } g2p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1} "" { target *-*-* } 96 } g4p_stack */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1} "" { target *-*-* } 97 } g8p_stack */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1}  "" { target *-*-* } 93 } gp_stack */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1} "" { target *-*-* } 94 } g1p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1} "" { target *-*-* } 95 } g2p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1} "" { target *-*-* } 96 } g4p_stack */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1} "" { target *-*-* } 97 } g8p_stack */
 
 
-/* No change in parameter passing in GCC 9.1 for line 98 (g16p_stack).  No
-   warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for line 98
+   (g16p_stack).  No warning expected.  */
 
 
 /* Bitfield parameter in stdarg.  */
-/* No change in parameter passing in GCC 9.1 for lines 101-105 (f1_stdarg,
-   f2_stdarg, f4_stdarg, f8_stdarg, f16_stdarg) because the overall alignment
-   is > 16.  No warning expected.  */
-
-/* Parameter passing for these should not have changed in GCC 9.1 (PR 105549).
-   Fortunately we warn. Note the discrepancy with lines 120-124 below: we warn
-   in the callee, but not in the caller.  */
-/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 9.1}   "" { target *-*-* } 107 } fp_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 9.1}  "" { target *-*-* } 108 } f1p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 9.1}  "" { target *-*-* } 109 } f2p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 9.1}  "" { target *-*-* } 110 } f4p_stdarg */
-/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 9.1}  "" { target *-*-* } 111 } f8p_stdarg */
-
-/* No change in parameter passing in GCC 9.1 for line 112 (f16p_stdarg).
-   Should not warn.  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { target *-*-* } 112 } f16p_stdarg */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 101-105
+   (f1_stdarg, f2_stdarg, f4_stdarg, f8_stdarg, f16_stdarg) because the overall
+   alignment is > 16.  No warning expected.  */
+
+/* Changed in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct Sp' changed in GCC 13.1}   "" { target *-*-* } 107 } fp_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S1p' changed in GCC 13.1}  "" { target *-*-* } 108 } f1p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S2p' changed in GCC 13.1}  "" { target *-*-* } 109 } f2p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S4p' changed in GCC 13.1}  "" { target *-*-* } 110 } f4p_stdarg */
+/* { dg-note {parameter passing for argument of type 'struct S8p' changed in GCC 13.1}  "" { target *-*-* } 111 } f8p_stdarg */
+
+/* No change for line 112 (f16p_stdarg), no warning.  */
 
 /* Bitfield call argument in stdarg.  */
-/* No change in parameter passing in GCC 9.1 for lines 114-118 (g1_stdarg,
-   g2_stdarg, g4_stdarg, g8_stdarg, g16_stdarg) because the overall alignment
-   is > 16.  No warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 114-118
+   (g1_stdarg, g2_stdarg, g4_stdarg, g8_stdarg, g16_stdarg) because the overall
+   alignment is > 16.  No warning expected.  */
 
-/* No change in parameter passing in GCC 9.1 for lines 120-124 (gp_stdarg,
-   g1p_stdarg, g2p_stdarg, g4p_stdarg, g8p_stdarg), no warning expected.  */
+/* No change in parameter passing in GCC 9.1 nor GCC 13.1 for lines 120-124
+   (gp_stdarg, g1p_stdarg, g2p_stdarg, g4p_stdarg, g8p_stdarg), no warning
+   expected.  */
 
-/* Changed in GCC 9.1, but we fail to emit a warning.  */
-/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 9.1} "" { xfail *-*-* } 125 } g16p_stdarg */
+/* Changed in GCC 13.1.  */
+/* { dg-note {parameter passing for argument of type 'struct S16p' changed in GCC 13.1} "" { target *-*-* } 125 } g16p_stdarg */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr105549.c b/gcc/testsuite/gcc.target/aarch64/pr105549.c
new file mode 100644
index 00000000000..55a91ed6bc4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr105549.c
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-save-temps" } */
+
+enum e { E1 };
+typedef enum e e __attribute__((aligned(16)));
+union u {
+    __attribute__((aligned(2), packed)) e a : 1;
+    int x[4];
+};
+union u g(int a, union u u2) { return u2; }
+
+/* { dg-final { scan-assembler "stp\tx1, x2, \\\[sp, 8\\\]" } } */