PR123447 reports an ICE on AArch64 with "-O2 -mstrict-align" in subreg
lowering when decomposing the following multiword store RTL:

(insn 12 11 13 2 (set (mem/c:XI (plus:DI (reg/f:DI 64 sfp)
                (const_int -96 [0xffffffffffffffa0])) [0  S64 A8])
        (reg:XI 103)) "a.c":14:6 4861 {*aarch64_movxi}

This RTL originates from expanding the following GIMPLE statement:

_1 = BIT_FIELD_REF <{ 9, -64497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 
256, 0>;

The operand is a constant _Decimal64 vector with BLKmode, so expand has
to materialize it in memory. The stack slot alignment is chosen via
get_object_alignment(), which historically only treated STRING_CST as a
possible unwrapped constant object (i.e. not under a CONST_DECL). As a
result, a VECTOR_CST falls back to 1-byte alignment, as indicated by A8
in the RTL dump above.

Later, subreg lowering attempts to decompose the RTL into DImode pieces.
With "-mstrict-align" enabled, simplify_gen_subreg() fails to construct
a valid subreg RTX for the pieces because the alignment is too small.
This eventually triggers an assertion failure.

This patch handles VECTOR_CST like STRING_CST in get_object_alignment(),
so that a reasonable alignment is derived from the vector constant's
type or its explicit alignment attribute.

Bootstrapped and tested on aarch64-linux-gnu and x86_64-linux-gnu.

gcc/ChangeLog:

        PR middle-end/123447
        * builtins.cc (get_object_alignment_2): Handle VECTOR_CST like
        STRING_CST.

gcc/testsuite/ChangeLog:

        PR middle-end/123447
        * gcc.dg/pr123447.c: New test.
---
 gcc/builtins.cc                 |  8 +++++---
 gcc/testsuite/gcc.dg/pr123447.c | 19 +++++++++++++++++++
 2 files changed, 24 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr123447.c

diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 28454c53777..9c39d0c5ee4 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -340,10 +340,12 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
            bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
        }
     }
-  else if (TREE_CODE (exp) == STRING_CST)
+  else if (TREE_CODE (exp) == STRING_CST
+          || TREE_CODE (exp) == VECTOR_CST)
     {
-      /* STRING_CST are the only constant objects we allow to be not
-         wrapped inside a CONST_DECL.  */
+      /* STRING_CST is a common constant object that appears unwrapped (not
+        under a CONST_DECL).  VECTOR_CST can appear unwrapped in some cases
+        (see PR123447).  */
       align = TYPE_ALIGN (TREE_TYPE (exp));
       if (CONSTANT_CLASS_P (exp))
        align = targetm.constant_alignment (exp, align);
diff --git a/gcc/testsuite/gcc.dg/pr123447.c b/gcc/testsuite/gcc.dg/pr123447.c
new file mode 100644
index 00000000000..b2ee1473758
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr123447.c
@@ -0,0 +1,19 @@
+/* PR middle-end/123447 */
+/* { dg-do compile { target aarch64*-*-* } } */
+/* { dg-options "-O2 -mstrict-align" } */
+
+typedef __attribute__((__vector_size__(32))) _Decimal64 D;
+typedef __attribute__((__vector_size__(64))) int V;
+typedef __attribute__((__vector_size__(64))) _Decimal64 D64;
+
+D d;
+
+void foo1 () {
+  D _4;
+  D64 _5;
+  V _1;
+  _1 = (V) { 9, -64497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+  _5 = (D64) _1;
+  _4 = __builtin_shufflevector (_5, _5, 0, 1, 2, 3);
+  d = _4;
+}
-- 
2.43.0

Reply via email to