]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Correct x86: Call ix86_access_stack_p only for larger alignment
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 3 Apr 2026 07:55:17 +0000 (15:55 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 7 Apr 2026 21:22:57 +0000 (05:22 +0800)
commit f511bf93f947199a9f9099fee87b7052e5515fb9
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sun Mar 29 14:30:28 2026 -0700

    x86: Call ix86_access_stack_p only for larger alignment

has 2 issues:

1. It didn't exclude memory with SYMBOLIC_CONST when checking for stack
access.
2. It replaced:

  HARD_REG_SET hard_stack_slot_access = stack_slot_access;
  ...
      bool symbolic_const_load_p = false;

      if (!TEST_HARD_REG_BIT (hard_stack_slot_access, regno))
...
        symbolic_const_load_p = true;
      ...

      if (!symbolic_const_load_p
          || ix86_access_stack_p...)
call ix86_update_stack_alignment.

with

      if (ix86_need_alignment_p...
          && ix86_access_stack_p...)
call ix86_update_stack_alignment.

Since ix86_access_stack_p excludes registers on hard_stack_slot_access,
stack alignment isn't updated for registers on hard_stack_slot_access.
Instead, we should do

      if (ix86_need_alignment_p...
          && (TEST_HARD_REG_BIT (hard_stack_slot_access, regno)
              || ix86_access_stack_p...))
        call ix86_update_stack_alignment.

The compile times of PR target/124165 and PR target/124684 test are
unchanged.

      if (ix86_need_alignment_p...
          && (TEST_HARD_REG_BIT (hard_stack_slot_access, regno)
      || ix86_access_stack_p...))
call ix86_update_stack_alignment.

gcc/

PR target/124759
PR target/124789
* config/i386/i386.cc (ix86_need_alignment_p_2): New function.
Exclude memory with SYMBOLIC_CONST.
(ix86_need_alignment_p_1): Call ix86_need_alignment_p_2.
(ix86_find_max_used_stack_alignment): Restore
hard_stack_slot_access handling.

gcc/testsuite/

PR target/124759
PR target/124789
* gcc.target/i386/pr124759.c: New test.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
gcc/config/i386/i386.cc
gcc/testsuite/gcc.target/i386/pr124759.c [new file with mode: 0644]

index f4d0f6239433ba1a2f7d00a348908b928726610d..9d1a2af70647f3f7a778180a72bcf224ea43b46f 100644 (file)
@@ -8781,6 +8781,29 @@ ix86_access_stack_p (unsigned int regno, basic_block bb,
   return false;
 }
 
+/* Return true if OP isn't a memory operand with SYMBOLIC_CONST and
+   needs alignment > ALIGNMENT.  */
+
+static bool
+ix86_need_alignment_p_2 (const_rtx op, unsigned int alignment)
+{
+  bool need_alignment = MEM_ALIGN (op) > alignment;
+  tree mem_expr = MEM_EXPR (op);
+  if (!mem_expr)
+    return need_alignment;
+
+  tree var = get_base_address (mem_expr);
+  if (!VAR_P (var) || !DECL_RTL_SET_P (var))
+    return need_alignment;
+
+  rtx x = DECL_RTL (var);
+  if (!MEM_P (x))
+    return need_alignment;
+
+  x = XEXP (x, 0);
+  return !SYMBOLIC_CONST (x) && need_alignment;
+}
+
 /* Return true if SET needs alignment > ALIGNMENT.  */
 
 static bool
@@ -8789,7 +8812,7 @@ ix86_need_alignment_p_1 (rtx set, unsigned int alignment)
   rtx dest = SET_DEST (set);
 
   if (MEM_P (dest))
-    return MEM_ALIGN (dest) > alignment;
+    return ix86_need_alignment_p_2 (dest, alignment);
 
   const_rtx src = SET_SRC (set);
 
@@ -8799,7 +8822,7 @@ ix86_need_alignment_p_1 (rtx set, unsigned int alignment)
       auto op = *iter;
 
       if (MEM_P (op))
-       return MEM_ALIGN (op) > alignment;
+       return ix86_need_alignment_p_2 (op, alignment);
     }
 
   return false;
@@ -8890,6 +8913,9 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
       bitmap_set_bit (worklist, HARD_FRAME_POINTER_REGNUM);
     }
 
+  /* Registers on HARD_STACK_SLOT_ACCESS always access stack.  */
+  HARD_REG_SET hard_stack_slot_access = stack_slot_access;
+
   calculate_dominance_info (CDI_DOMINATORS);
 
   unsigned int regno;
@@ -8926,10 +8952,12 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
          /* Call ix86_access_stack_p only if INSN needs alignment >
             STACK_ALIGNMENT.  */
          if (ix86_need_alignment_p (insn, stack_alignment)
-             && ix86_access_stack_p (regno, BLOCK_FOR_INSN (insn),
-                                     set_up_by_prologue, prologue_used,
-                                     reg_dominate_bbs_known,
-                                     reg_dominate_bbs))
+             && (TEST_HARD_REG_BIT (hard_stack_slot_access, regno)
+                 || ix86_access_stack_p (regno, BLOCK_FOR_INSN (insn),
+                                         set_up_by_prologue,
+                                         prologue_used,
+                                         reg_dominate_bbs_known,
+                                         reg_dominate_bbs)))
            {
              /* Update stack alignment if REGNO is used for stack
                 access.  */
diff --git a/gcc/testsuite/gcc.target/i386/pr124759.c b/gcc/testsuite/gcc.target/i386/pr124759.c
new file mode 100644 (file)
index 0000000..b5a86b7
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do run { target avx_runtime } } */
+/* { dg-options "-fhardened -O3 -mavx" } */
+
+struct a {
+  unsigned long long b;
+  unsigned long long c;
+  int d;
+  char e;
+  int f;
+} g;
+int h = 1, i, j;
+long long k, l, n;
+int m[1]={};
+short o;
+static inline short p(short q, short r) { return q + r; }
+int main() {
+  for (; h < 3; h = p(h, 1))
+    if (h) {
+      k |= 4;
+      struct a s = {8, 2, 2, 4, 15};
+      for (int n = 0; n != 54; n++)
+        if (m[l])
+          if (i)
+            o = 0;
+      g = s;
+      j &= 4073709551610LL;
+    }
+  return 0;
+}