[llvm] [X86] Don't discard over-16 stack alignment for 32-bit interrupt handlers (PR #225366)

Timur Golubovich via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 04:11:11 PDT 2026


https://github.com/timurgol007 created https://github.com/llvm/llvm-project/pull/225366

calculateMaxStackAlign assigned Align(16) instead of taking the maximum, so an alloca with align 64 in a 32-bit handler got andl $-16 and landed only 16-byte aligned, even though PEI had laid the frame out for 64. With AVX512 the compiler then emits vmovaps to that object, which faults.

>From 5a9d3a6949a9efeda4c7f7ca64a4ce1c4a0997a6 Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Wed, 16 Sep 2026 15:39:48 +0200
Subject: [PATCH] [X86] Don't discard over-16 stack alignment for 32-bit
 interrupt handlers

calculateMaxStackAlign assigned Align(16) instead of taking the maximum, so
an alloca with align 64 in a 32-bit handler got andl $-16 and landed only
16-byte aligned, even though PEI had laid the frame out for 64. With AVX512
the compiler then emits vmovaps to that object, which faults.
---
 llvm/lib/Target/X86/X86FrameLowering.cpp  |  9 +++------
 llvm/test/CodeGen/X86/x86-interrupt_cc.ll | 12 ++++++------
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index fad665e31bbe5..5b9251917a634 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -1351,12 +1351,9 @@ X86FrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const {
       MaxAlign = Align(SlotSize);
   }
 
-  if (!Is64Bit && MF.getFunction().getCallingConv() == CallingConv::X86_INTR) {
-    if (HasRealign)
-      MaxAlign = (MaxAlign > 16) ? MaxAlign : Align(16);
-    else
-      MaxAlign = Align(16);
-  }
+  if (!Is64Bit && MF.getFunction().getCallingConv() == CallingConv::X86_INTR)
+    MaxAlign = std::max(MaxAlign, Align(16));
+
   return MaxAlign.value();
 }
 
diff --git a/llvm/test/CodeGen/X86/x86-interrupt_cc.ll b/llvm/test/CodeGen/X86/x86-interrupt_cc.ll
index ff40a3404d5ef..c6777d18f898a 100644
--- a/llvm/test/CodeGen/X86/x86-interrupt_cc.ll
+++ b/llvm/test/CodeGen/X86/x86-interrupt_cc.ll
@@ -514,9 +514,9 @@ define x86_intrcc void @foo(ptr byval(i8) %frame) {
 ; CHECK32-KNL-NEXT:    pushl %edx ## encoding: [0x52]
 ; CHECK32-KNL-NEXT:    pushl %ecx ## encoding: [0x51]
 ; CHECK32-KNL-NEXT:    pushl %eax ## encoding: [0x50]
-; CHECK32-KNL-NEXT:    andl $-16, %esp ## encoding: [0x83,0xe4,0xf0]
-; CHECK32-KNL-NEXT:    subl $560, %esp ## encoding: [0x81,0xec,0x30,0x02,0x00,0x00]
-; CHECK32-KNL-NEXT:    ## imm = 0x230
+; CHECK32-KNL-NEXT:    andl $-64, %esp ## encoding: [0x83,0xe4,0xc0]
+; CHECK32-KNL-NEXT:    subl $576, %esp ## encoding: [0x81,0xec,0x40,0x02,0x00,0x00]
+; CHECK32-KNL-NEXT:    ## imm = 0x240
 ; CHECK32-KNL-NEXT:    kmovw %k7, {{[-0-9]+}}(%e{{[sb]}}p) ## 2-byte Spill
 ; CHECK32-KNL-NEXT:    ## encoding: [0xc5,0xf8,0x91,0x7d,0xf2]
 ; CHECK32-KNL-NEXT:    kmovw %k6, {{[-0-9]+}}(%e{{[sb]}}p) ## 2-byte Spill
@@ -620,9 +620,9 @@ define x86_intrcc void @foo(ptr byval(i8) %frame) {
 ; CHECK32-SKX-NEXT:    pushl %edx ## encoding: [0x52]
 ; CHECK32-SKX-NEXT:    pushl %ecx ## encoding: [0x51]
 ; CHECK32-SKX-NEXT:    pushl %eax ## encoding: [0x50]
-; CHECK32-SKX-NEXT:    andl $-16, %esp ## encoding: [0x83,0xe4,0xf0]
-; CHECK32-SKX-NEXT:    subl $624, %esp ## encoding: [0x81,0xec,0x70,0x02,0x00,0x00]
-; CHECK32-SKX-NEXT:    ## imm = 0x270
+; CHECK32-SKX-NEXT:    andl $-64, %esp ## encoding: [0x83,0xe4,0xc0]
+; CHECK32-SKX-NEXT:    subl $640, %esp ## encoding: [0x81,0xec,0x80,0x02,0x00,0x00]
+; CHECK32-SKX-NEXT:    ## imm = 0x280
 ; CHECK32-SKX-NEXT:    kmovq %k7, {{[-0-9]+}}(%e{{[sb]}}p) ## 8-byte Spill
 ; CHECK32-SKX-NEXT:    ## encoding: [0xc4,0xe1,0xf8,0x91,0x7d,0xe8]
 ; CHECK32-SKX-NEXT:    kmovq %k6, {{[-0-9]+}}(%e{{[sb]}}p) ## 8-byte Spill



More information about the llvm-commits mailing list