https://gcc.gnu.org/g:7b29e31e693953a306b2bd0db7b2975ceed7e44c

commit r16-7109-g7b29e31e693953a306b2bd0db7b2975ceed7e44c
Author: Pengfei Li <[email protected]>
Date:   Mon Jan 26 16:09:42 2026 +0000

    expand: Increase stack slot alignment for STRICT_ALIGNMENT targets 
[PR123447]
    
    PR123447 reports an ICE on AArch64 with "-O2 -mstrict-align" in subreg
    lowering while 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. Current get_object_alignment() returns a
    1-byte guaranteed alignment for this VECTOR_CST, as indicated by A8 in
    the RTL dump above. However, with "-mstrict-align" enabled, later subreg
    lowering pass expects at least 64-bit alignment when it constructs a new
    RTX to decompose the store into pieces. Because the original alignment
    is too small, simplify_gen_subreg() returns NULL_RTX and an assertion is
    hit.
    
    This patch increases the stack slot alignment for STRICT_ALIGNMENT
    targets, when the operand is forced into memory. The increased alignment
    is capped by MAX_SUPPORTED_STACK_ALIGNMENT so it won't be too large.
    
    Bootstrapped and tested on aarch64-linux-gnu and x86_64-linux-gnu.
    
    gcc/ChangeLog:
    
            PR middle-end/123447
            * expr.cc (expand_expr_real_1): Increase stack slot alignment
            for STRICT_ALIGNMENT targets.
    
    gcc/testsuite/ChangeLog:
    
            PR middle-end/123447
            * gcc.dg/pr123447.c: New test.

Diff:
---
 gcc/expr.cc                     | 21 +++++++++++++++++----
 gcc/testsuite/gcc.dg/pr123447.c | 19 +++++++++++++++++++
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index b6d593d09a2d..d3dad6c8041c 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -12336,13 +12336,26 @@ expand_expr_real_1 (tree exp, rtx target, 
machine_mode tmode,
           and need be, put it there.  */
        else if (CONSTANT_P (op0) || (!MEM_P (op0) && must_force_mem))
          {
+           machine_mode tem_mode = TYPE_MODE (TREE_TYPE (tem));
            poly_int64 size;
            if (!poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (tem)), &size))
              size = max_int_size_in_bytes (TREE_TYPE (tem));
-           memloc = assign_stack_local (TYPE_MODE (TREE_TYPE (tem)), size,
-                                        TREE_CODE (tem) == SSA_NAME
-                                        ? TYPE_ALIGN (TREE_TYPE (tem))
-                                        : get_object_alignment (tem));
+           unsigned int align = TREE_CODE (tem) == SSA_NAME
+                                ? TYPE_ALIGN (TREE_TYPE (tem))
+                                : get_object_alignment (tem);
+           if (STRICT_ALIGNMENT)
+             {
+               /* For STRICT_ALIGNMENT targets, when we force the operand to
+                  memory, we may need to increase the alignment to meet the
+                  expectation in later RTL lowering passes.  The increased
+                  alignment is capped by MAX_SUPPORTED_STACK_ALIGNMENT.  */
+               if (tem_mode != BLKmode)
+                 align = MAX (align, GET_MODE_ALIGNMENT (tem_mode));
+               else
+                 align = MAX (align, TYPE_ALIGN (TREE_TYPE (tem)));
+               align = MIN (align, (unsigned) MAX_SUPPORTED_STACK_ALIGNMENT);
+             }
+           memloc = assign_stack_local (tem_mode, size, align);
            emit_move_insn (memloc, op0);
            op0 = memloc;
            clear_mem_expr = true;
diff --git a/gcc/testsuite/gcc.dg/pr123447.c b/gcc/testsuite/gcc.dg/pr123447.c
new file mode 100644
index 000000000000..b2ee1473758f
--- /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;
+}

Reply via email to