[llvm] X86: Mark flag clobbers dead in stack probe expansion (PR #227682)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 05:19:48 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/227682
Co-authored-by: Claude Opus 5 <noreply at anthropic.com>
>From 3be71d79627283ec1a1befb65ed0f4c0202c2c0b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 29 Sep 2026 01:51:58 +0200
Subject: [PATCH] X86: Mark flag clobbers dead in stack probe expansion
Co-authored-by: Claude Opus 5 <noreply at anthropic.com>
---
llvm/lib/Target/X86/X86FrameLowering.cpp | 36 ++--
.../CodeGen/X86/stack-probe-call-dead-defs.ll | 118 +++++++++++
.../X86/stack-probe-inline-dead-eflags.ll | 196 ++++++++++++++++++
3 files changed, 338 insertions(+), 12 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/stack-probe-call-dead-defs.ll
create mode 100644 llvm/test/CodeGen/X86/stack-probe-inline-dead-eflags.ll
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index a25aba6d0afe0..11edf771a5232 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -942,7 +942,8 @@ void X86FrameLowering::emitStackProbeInlineGenericLoop(
BuildMI(MBB, MBBI, DL, TII.get(SUBOpc), FinalStackProbed)
.addReg(FinalStackProbed)
.addImm(BoundOffset)
- .setMIFlag(MachineInstr::FrameSetup);
+ .setMIFlag(MachineInstr::FrameSetup)
+ .setOperandDead(3); // implicit-def $eflags
} else if (Uses64BitFramePtr) {
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), FinalStackProbed)
.addImm(-BoundOffset)
@@ -950,7 +951,8 @@ void X86FrameLowering::emitStackProbeInlineGenericLoop(
BuildMI(MBB, MBBI, DL, TII.get(X86::ADD64rr), FinalStackProbed)
.addReg(FinalStackProbed)
.addReg(StackPtr)
- .setMIFlag(MachineInstr::FrameSetup);
+ .setMIFlag(MachineInstr::FrameSetup)
+ .setOperandDead(3); // implicit-def $eflags
} else {
llvm_unreachable("Offset too large for 32-bit stack pointer");
}
@@ -1151,7 +1153,8 @@ void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
// to zero if so.
BuildMI(&MBB, DL, TII.get(X86::XOR64rr), ZeroReg)
.addReg(ZeroReg, RegState::Undef)
- .addReg(ZeroReg, RegState::Undef);
+ .addReg(ZeroReg, RegState::Undef)
+ .setOperandDead(3); // implicit-def $eflags
BuildMI(&MBB, DL, TII.get(X86::MOV64rr), CopyReg).addReg(X86::RSP);
BuildMI(&MBB, DL, TII.get(X86::SUB64rr), TestReg)
.addReg(CopyReg)
@@ -1185,7 +1188,8 @@ void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
RoundMBB->addLiveIn(FinalReg);
BuildMI(RoundMBB, DL, TII.get(X86::AND64ri32), RoundedReg)
.addReg(FinalReg)
- .addImm(PageMask);
+ .addImm(PageMask)
+ .setOperandDead(3); // implicit-def $eflags
BuildMI(RoundMBB, DL, TII.get(X86::JMP_1)).addMBB(LoopMBB);
// LimitReg now holds the current stack limit, RoundedReg page-rounded
@@ -1240,7 +1244,8 @@ void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
// the stack pointer for real.
BuildMI(*ContinueMBB, ContinueMBBI, DL, TII.get(X86::SUB64rr), X86::RSP)
.addReg(X86::RSP)
- .addReg(SizeReg);
+ .addReg(SizeReg)
+ .setOperandDead(3); // implicit-def $eflags
// Add the control flow edges we need.
MBB.addSuccessor(ContinueMBB);
@@ -1313,14 +1318,18 @@ void X86FrameLowering::emitStackProbeCall(
unsigned AX = Uses64BitFramePtr ? X86::RAX : X86::EAX;
unsigned SP = Uses64BitFramePtr ? X86::RSP : X86::ESP;
+ bool EmitSPSub = STI.isTargetWin64() || !STI.isOSWindows();
+
CI.addReg(AX, RegState::Implicit)
.addReg(SP, RegState::Implicit)
- .addReg(AX, RegState::Define | RegState::Implicit)
+ .addReg(AX, RegState::Define | RegState::Implicit |
+ getDeadRegState(!EmitSPSub))
.addReg(SP, RegState::Define | RegState::Implicit)
- .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
+ .addReg(X86::EFLAGS,
+ RegState::Define | RegState::Implicit | RegState::Dead);
MachineInstr *ModInst = CI;
- if (STI.isTargetWin64() || !STI.isOSWindows()) {
+ if (EmitSPSub) {
// MSVC x32's _chkstk and cygwin/mingw's _alloca adjust %esp themselves.
// MSVC x64's __chkstk and cygwin/mingw's ___chkstk_ms do not adjust %rsp
// themselves. They also does not clobber %rax so we can reuse it when
@@ -1330,14 +1339,15 @@ void X86FrameLowering::emitStackProbeCall(
ModInst =
BuildMI(MBB, MBBI, DL, TII.get(getSUBrrOpcode(Uses64BitFramePtr)), SP)
.addReg(SP)
- .addReg(AX);
+ .addReg(AX)
+ .setOperandDead(3); // implicit-def $eflags
}
// DebugInfo variable locations -- if there's an instruction number for the
// allocation (i.e., DYN_ALLOC_*), substitute it for the instruction that
// modifies SP.
if (InstrNum) {
- if (STI.isTargetWin64() || !STI.isOSWindows()) {
+ if (EmitSPSub) {
// Label destination operand of the subtract.
MF.makeDebugValueSubstitution(*InstrNum,
{ModInst->getDebugInstrNum(), 0});
@@ -1466,7 +1476,8 @@ void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
BuildMI(headMBB, DL, TII.get(SUBOpc), StackPtr)
.addReg(StackPtr)
.addImm(StackProbeSize)
- .setMIFlag(MachineInstr::FrameSetup);
+ .setMIFlag(MachineInstr::FrameSetup)
+ .setOperandDead(3); // implicit-def $eflags
BuildMI(headMBB, DL,
TII.get(Uses64BitFramePtr ? X86::CMP64rr : X86::CMP32rr))
@@ -1496,7 +1507,8 @@ void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
BuildMI(bodyMBB, DL, TII.get(SUBOpc), StackPtr)
.addReg(StackPtr)
.addImm(StackProbeSize)
- .setMIFlag(MachineInstr::FrameSetup);
+ .setMIFlag(MachineInstr::FrameSetup)
+ .setOperandDead(3); // implicit-def $eflags
// cmp with stack pointer bound
BuildMI(bodyMBB, DL,
diff --git a/llvm/test/CodeGen/X86/stack-probe-call-dead-defs.ll b/llvm/test/CodeGen/X86/stack-probe-call-dead-defs.ll
new file mode 100644
index 0000000000000..c3f22b08cd298
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-probe-call-dead-defs.ll
@@ -0,0 +1,118 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=i686-pc-windows-msvc -stop-after=prolog-epilog -o - %s | FileCheck %s --check-prefix=X86
+; RUN: llc -mtriple=x86_64-pc-windows-msvc -stop-after=prolog-epilog -o - %s | FileCheck %s --check-prefix=X64
+; RUN: llc -mtriple=x86_64-linux-gnu -stop-after=prolog-epilog -o - %s | FileCheck %s --check-prefix=LINUX
+
+; The probe call's flag clobber is dead, as is its scratch register def when
+; the probe adjusts the stack pointer itself.
+
+define void @dyn_alloca(i64 %n) "probe-stack"="__chkstk" {
+ ; X86-LABEL: name: dyn_alloca
+ ; X86: bb.0 (%ir-block.0):
+ ; X86-NEXT: frame-setup PUSH32r killed $ebp, implicit-def $esp, implicit $esp
+ ; X86-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8
+ ; X86-NEXT: frame-setup CFI_INSTRUCTION offset $ebp, -8
+ ; X86-NEXT: $ebp = frame-setup MOV32rr $esp
+ ; X86-NEXT: frame-setup CFI_INSTRUCTION def_cfa_register $ebp
+ ; X86-NEXT: renamable $eax = MOV32rm $ebp, 1, $noreg, 8, $noreg :: (load (s32) from %fixed-stack.2)
+ ; X86-NEXT: renamable $eax = ADD32ri killed renamable $eax, 3, implicit-def dead $eflags
+ ; X86-NEXT: renamable $eax = AND32ri killed renamable $eax, -4, implicit-def dead $eflags
+ ; X86-NEXT: CALLpcrel32 &__chkstk, implicit $esp, implicit $ssp, implicit $eax, implicit $esp, implicit-def dead $eax, implicit-def $esp, implicit-def dead $eflags
+ ; X86-NEXT: renamable $eax = COPY $esp
+ ; X86-NEXT: PUSH32r killed renamable $eax, implicit-def $esp, implicit $esp :: (store (s32) into stack)
+ ; X86-NEXT: CALLpcrel32 @use, csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp
+ ; X86-NEXT: $esp = MOV32rr $ebp
+ ; X86-NEXT: $ebp = frame-destroy POP32r implicit-def $esp, implicit $esp
+ ; X86-NEXT: RET 0
+ ;
+ ; X64-LABEL: name: dyn_alloca
+ ; X64: bb.0 (%ir-block.0):
+ ; X64-NEXT: liveins: $rcx
+ ; X64-NEXT: {{ $}}
+ ; X64-NEXT: frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+ ; X64-NEXT: frame-setup SEH_PushReg 52
+ ; X64-NEXT: $rbp = MOV64rr $rsp
+ ; X64-NEXT: frame-setup SEH_SetFrame 52, 0
+ ; X64-NEXT: frame-setup SEH_EndPrologue
+ ; X64-NEXT: renamable $rax = LEA64r killed renamable $rcx, 1, $noreg, 15, $noreg
+ ; X64-NEXT: renamable $rax = AND64ri32 killed renamable $rax, -16, implicit-def dead $eflags
+ ; X64-NEXT: CALL64pcrel32 &__chkstk, implicit $rsp, implicit $ssp, implicit $rax, implicit $rsp, implicit-def $rax, implicit-def $rsp, implicit-def dead $eflags
+ ; X64-NEXT: $rsp = SUB64rr $rsp, $rax, implicit-def dead $eflags
+ ; X64-NEXT: renamable $rcx = COPY $rsp
+ ; X64-NEXT: $rsp = SUB64ri32 $rsp, 32, implicit-def dead $eflags
+ ; X64-NEXT: CALL64pcrel32 @use, csr_win64, implicit $rsp, implicit $ssp, implicit $rcx, implicit-def $rsp, implicit-def $ssp
+ ; X64-NEXT: SEH_BeginEpilogue
+ ; X64-NEXT: $rsp = MOV64rr $rbp
+ ; X64-NEXT: $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
+ ; X64-NEXT: SEH_EndEpilogue
+ ; X64-NEXT: RET 0
+ ;
+ ; LINUX-LABEL: name: dyn_alloca
+ ; LINUX: bb.0 (%ir-block.0):
+ ; LINUX-NEXT: liveins: $rdi
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION offset $rbp, -16
+ ; LINUX-NEXT: $rbp = frame-setup MOV64rr $rsp
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION def_cfa_register $rbp
+ ; LINUX-NEXT: renamable $rax = LEA64r killed renamable $rdi, 1, $noreg, 15, $noreg
+ ; LINUX-NEXT: renamable $rax = AND64ri32 killed renamable $rax, -16, implicit-def dead $eflags
+ ; LINUX-NEXT: CALL64pcrel32 &__chkstk, implicit $rsp, implicit $ssp, implicit $rax, implicit $rsp, implicit-def $rax, implicit-def $rsp, implicit-def dead $eflags
+ ; LINUX-NEXT: $rsp = SUB64rr $rsp, $rax, implicit-def dead $eflags
+ ; LINUX-NEXT: renamable $rdi = COPY $rsp
+ ; LINUX-NEXT: CALL64pcrel32 target-flags(x86-plt) @use, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
+ ; LINUX-NEXT: $rsp = MOV64rr $rbp
+ ; LINUX-NEXT: $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
+ ; LINUX-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $rsp, 8
+ ; LINUX-NEXT: RET 0
+ %a = alloca i8, i64 %n
+ call void @use(ptr %a)
+ ret void
+}
+
+define void @large_frame() "probe-stack"="__chkstk" {
+ ; X86-LABEL: name: large_frame
+ ; X86: bb.0 (%ir-block.0):
+ ; X86-NEXT: $eax = frame-setup MOV32ri 40000
+ ; X86-NEXT: frame-setup CALLpcrel32 &__chkstk, implicit $esp, implicit $ssp, implicit $eax, implicit $esp, implicit-def dead $eax, implicit-def $esp, implicit-def dead $eflags
+ ; X86-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 40004
+ ; X86-NEXT: $eax = MOV32rr $esp
+ ; X86-NEXT: PUSH32r killed renamable $eax, implicit-def $esp, implicit $esp :: (store (s32) into stack)
+ ; X86-NEXT: CFI_INSTRUCTION adjust_cfa_offset 4
+ ; X86-NEXT: CALLpcrel32 @use, csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp
+ ; X86-NEXT: $esp = ADD32ri $esp, 40004, implicit-def dead $eflags
+ ; X86-NEXT: CFI_INSTRUCTION adjust_cfa_offset -40004
+ ; X86-NEXT: RET 0
+ ;
+ ; X64-LABEL: name: large_frame
+ ; X64: bb.0 (%ir-block.0):
+ ; X64-NEXT: $rax = frame-setup MOV32ri64 40040
+ ; X64-NEXT: frame-setup CALL64pcrel32 &__chkstk, implicit $rsp, implicit $ssp, implicit $rax, implicit $rsp, implicit-def $rax, implicit-def $rsp, implicit-def dead $eflags
+ ; X64-NEXT: $rsp = frame-setup SUB64rr $rsp, $rax, implicit-def dead $eflags
+ ; X64-NEXT: frame-setup SEH_StackAlloc 40040
+ ; X64-NEXT: frame-setup SEH_EndPrologue
+ ; X64-NEXT: renamable $rcx = LEA64r $rsp, 1, $noreg, 40, $noreg
+ ; X64-NEXT: CALL64pcrel32 @use, csr_win64, implicit $rsp, implicit $ssp, implicit $rcx, implicit-def $rsp, implicit-def $ssp
+ ; X64-NEXT: SEH_BeginEpilogue
+ ; X64-NEXT: $rsp = frame-destroy ADD64ri32 $rsp, 40040, implicit-def dead $eflags
+ ; X64-NEXT: SEH_EndEpilogue
+ ; X64-NEXT: RET 0
+ ;
+ ; LINUX-LABEL: name: large_frame
+ ; LINUX: bb.0 (%ir-block.0):
+ ; LINUX-NEXT: $rax = frame-setup MOV32ri64 40008
+ ; LINUX-NEXT: frame-setup CALL64pcrel32 &__chkstk, implicit $rsp, implicit $ssp, implicit $rax, implicit $rsp, implicit-def $rax, implicit-def $rsp, implicit-def dead $eflags
+ ; LINUX-NEXT: $rsp = frame-setup SUB64rr $rsp, $rax, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 40016
+ ; LINUX-NEXT: renamable $rdi = LEA64r $rsp, 1, $noreg, 8, $noreg
+ ; LINUX-NEXT: CALL64pcrel32 target-flags(x86-plt) @use, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
+ ; LINUX-NEXT: $rsp = frame-destroy ADD64ri32 $rsp, 40008, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 8
+ ; LINUX-NEXT: RET 0
+ %a = alloca [40000 x i8]
+ call void @use(ptr %a)
+ ret void
+}
+
+declare void @use(ptr)
diff --git a/llvm/test/CodeGen/X86/stack-probe-inline-dead-eflags.ll b/llvm/test/CodeGen/X86/stack-probe-inline-dead-eflags.ll
new file mode 100644
index 0000000000000..0ba152445f1cd
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-probe-inline-dead-eflags.ll
@@ -0,0 +1,196 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=x86_64-linux-gnu -stop-after=prolog-epilog -o - %s | FileCheck %s --check-prefix=LINUX
+; RUN: llc -mtriple=x86_64-pc-win32-coreclr -stop-after=prolog-epilog -o - %s | FileCheck %s --check-prefix=CORECLR
+
+; The flag clobbers of the inline probe sequences are dead.
+
+define void @large_frame() "probe-stack"="inline-asm" {
+ ; LINUX-LABEL: name: large_frame
+ ; LINUX: bb.0 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.1(0x80000000)
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: $r11 = frame-setup COPY $rsp
+ ; LINUX-NEXT: $r11 = frame-setup SUB64ri32 $r11, 36864, implicit-def dead $eflags
+ ; LINUX-NEXT: CFI_INSTRUCTION def_cfa_register $r11
+ ; LINUX-NEXT: CFI_INSTRUCTION adjust_cfa_offset 36864
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.1 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; LINUX-NEXT: liveins: $r11
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: $rsp = frame-setup SUB64ri32 $rsp, 4096, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-setup MOV64mi32 $rsp, 1, $noreg, 0, $noreg, 0
+ ; LINUX-NEXT: frame-setup CMP64rr $rsp, $r11, implicit-def $eflags
+ ; LINUX-NEXT: frame-setup JCC_1 %bb.1, 5, implicit $eflags
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.2 (%ir-block.0):
+ ; LINUX-NEXT: $rsp = frame-setup SUB64ri32 $rsp, 3144, implicit-def dead $eflags
+ ; LINUX-NEXT: CFI_INSTRUCTION def_cfa_register $rsp
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 40016
+ ; LINUX-NEXT: renamable $rdi = LEA64r $rsp, 1, $noreg, 8, $noreg
+ ; LINUX-NEXT: CALL64pcrel32 target-flags(x86-plt) @use, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
+ ; LINUX-NEXT: $rsp = frame-destroy ADD64ri32 $rsp, 40008, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 8
+ ; LINUX-NEXT: RET 0
+ ;
+ ; CORECLR-LABEL: name: large_frame
+ ; CORECLR: bb.0 (%ir-block.0):
+ ; CORECLR-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rax = frame-setup MOV32ri64 40040
+ ; CORECLR-NEXT: $rcx = frame-setup XOR64rr undef $rcx, undef $rcx, implicit-def dead $eflags
+ ; CORECLR-NEXT: $rdx = frame-setup MOV64rr $rsp
+ ; CORECLR-NEXT: $rdx = frame-setup SUB64rr $rdx, $rax, implicit-def $eflags
+ ; CORECLR-NEXT: $rdx = frame-setup CMOV64rr $rdx, $rcx, 2, implicit $eflags
+ ; CORECLR-NEXT: $rcx = frame-setup MOV64rm $noreg, 1, $noreg, 16, $gs
+ ; CORECLR-NEXT: frame-setup CMP64rr $rdx, $rcx, implicit-def $eflags
+ ; CORECLR-NEXT: frame-setup JCC_1 %bb.3, 3, implicit $eflags
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: bb.1 (%ir-block.0):
+ ; CORECLR-NEXT: successors: %bb.2(0x80000000)
+ ; CORECLR-NEXT: liveins: $rdx
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rdx = frame-setup AND64ri32 $rdx, -4096, implicit-def dead $eflags
+ ; CORECLR-NEXT: frame-setup JMP_1 %bb.2
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: bb.2 (%ir-block.0):
+ ; CORECLR-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
+ ; CORECLR-NEXT: liveins: $rcx, $rdx
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rcx = frame-setup LEA64r $rcx, 1, $noreg, -4096, $noreg
+ ; CORECLR-NEXT: frame-setup MOV8mi $rcx, 1, $noreg, 0, $noreg, 0
+ ; CORECLR-NEXT: frame-setup CMP64rr $rdx, $rcx, implicit-def $eflags
+ ; CORECLR-NEXT: frame-setup JCC_1 %bb.2, 5, implicit $eflags
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: bb.3 (%ir-block.0):
+ ; CORECLR-NEXT: liveins: $rax
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rsp = frame-setup SUB64rr $rsp, $rax, implicit-def dead $eflags
+ ; CORECLR-NEXT: frame-setup SEH_StackAlloc 40040
+ ; CORECLR-NEXT: frame-setup SEH_EndPrologue
+ ; CORECLR-NEXT: renamable $rcx = LEA64r $rsp, 1, $noreg, 40, $noreg
+ ; CORECLR-NEXT: CALL64pcrel32 @use, csr_win64, implicit $rsp, implicit $ssp, implicit $rcx, implicit-def $rsp, implicit-def $ssp
+ ; CORECLR-NEXT: SEH_BeginEpilogue
+ ; CORECLR-NEXT: $rsp = frame-destroy ADD64ri32 $rsp, 40040, implicit-def dead $eflags
+ ; CORECLR-NEXT: SEH_EndEpilogue
+ ; CORECLR-NEXT: RET 0
+ %a = alloca [40000 x i8]
+ call void @use(ptr %a)
+ ret void
+}
+
+define void @large_frame_align() "probe-stack"="inline-asm" {
+ ; LINUX-LABEL: name: large_frame_align
+ ; LINUX: bb.1 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.2(0x40000000), %bb.0(0x40000000)
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION offset $rbp, -16
+ ; LINUX-NEXT: $rbp = frame-setup MOV64rr $rsp
+ ; LINUX-NEXT: frame-setup CFI_INSTRUCTION def_cfa_register $rbp
+ ; LINUX-NEXT: $r11 = frame-setup COPY $rsp
+ ; LINUX-NEXT: $r11 = frame-setup AND64ri32 $r11, -4096, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-setup CMP64rr $r11, $rsp, implicit-def $eflags
+ ; LINUX-NEXT: frame-setup JCC_1 %bb.0, 4, implicit $eflags
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.2 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.3(0x40000000), %bb.4(0x40000000)
+ ; LINUX-NEXT: liveins: $r11
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: $rsp = frame-setup SUB64ri32 $rsp, 4096, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-setup CMP64rr $rsp, $r11, implicit-def $eflags
+ ; LINUX-NEXT: frame-setup JCC_1 %bb.4, 2, implicit $eflags
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.3 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.3(0x40000000), %bb.4(0x40000000)
+ ; LINUX-NEXT: liveins: $r11
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: frame-setup MOV64mi32 $rsp, 1, $noreg, 0, $noreg, 0
+ ; LINUX-NEXT: $rsp = frame-setup SUB64ri32 $rsp, 4096, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-setup CMP64rr $r11, $rsp, implicit-def $eflags
+ ; LINUX-NEXT: frame-setup JCC_1 %bb.3, 2, implicit $eflags
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.4 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.0(0x80000000)
+ ; LINUX-NEXT: liveins: $r11
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: $rsp = frame-setup COPY $r11
+ ; LINUX-NEXT: frame-setup MOV64mi32 $rsp, 1, $noreg, 0, $noreg, 0
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.0 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.5(0x80000000)
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: $r11 = frame-setup COPY $rsp
+ ; LINUX-NEXT: $r11 = frame-setup SUB64ri32 $r11, 40960, implicit-def dead $eflags
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.5 (%ir-block.0):
+ ; LINUX-NEXT: successors: %bb.5(0x40000000), %bb.6(0x40000000)
+ ; LINUX-NEXT: liveins: $r11
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: $rsp = frame-setup SUB64ri32 $rsp, 4096, implicit-def dead $eflags
+ ; LINUX-NEXT: frame-setup MOV64mi32 $rsp, 1, $noreg, 0, $noreg, 0
+ ; LINUX-NEXT: frame-setup CMP64rr $rsp, $r11, implicit-def $eflags
+ ; LINUX-NEXT: frame-setup JCC_1 %bb.5, 5, implicit $eflags
+ ; LINUX-NEXT: {{ $}}
+ ; LINUX-NEXT: bb.6 (%ir-block.0):
+ ; LINUX-NEXT: $rdi = MOV64rr $rsp
+ ; LINUX-NEXT: CALL64pcrel32 target-flags(x86-plt) @use, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
+ ; LINUX-NEXT: $rsp = MOV64rr $rbp
+ ; LINUX-NEXT: $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
+ ; LINUX-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $rsp, 8
+ ; LINUX-NEXT: RET 0
+ ;
+ ; CORECLR-LABEL: name: large_frame_align
+ ; CORECLR: bb.0 (%ir-block.0):
+ ; CORECLR-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp
+ ; CORECLR-NEXT: frame-setup SEH_PushReg 52
+ ; CORECLR-NEXT: $rax = frame-setup MOV32ri64 45040
+ ; CORECLR-NEXT: $rcx = frame-setup XOR64rr undef $rcx, undef $rcx, implicit-def dead $eflags
+ ; CORECLR-NEXT: $rdx = frame-setup MOV64rr $rsp
+ ; CORECLR-NEXT: $rdx = frame-setup SUB64rr $rdx, $rax, implicit-def $eflags
+ ; CORECLR-NEXT: $rdx = frame-setup CMOV64rr $rdx, $rcx, 2, implicit $eflags
+ ; CORECLR-NEXT: $rcx = frame-setup MOV64rm $noreg, 1, $noreg, 16, $gs
+ ; CORECLR-NEXT: frame-setup CMP64rr $rdx, $rcx, implicit-def $eflags
+ ; CORECLR-NEXT: frame-setup JCC_1 %bb.3, 3, implicit $eflags
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: bb.1 (%ir-block.0):
+ ; CORECLR-NEXT: successors: %bb.2(0x80000000)
+ ; CORECLR-NEXT: liveins: $rdx
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rdx = frame-setup AND64ri32 $rdx, -4096, implicit-def dead $eflags
+ ; CORECLR-NEXT: frame-setup JMP_1 %bb.2
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: bb.2 (%ir-block.0):
+ ; CORECLR-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
+ ; CORECLR-NEXT: liveins: $rcx, $rdx
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rcx = frame-setup LEA64r $rcx, 1, $noreg, -4096, $noreg
+ ; CORECLR-NEXT: frame-setup MOV8mi $rcx, 1, $noreg, 0, $noreg, 0
+ ; CORECLR-NEXT: frame-setup CMP64rr $rdx, $rcx, implicit-def $eflags
+ ; CORECLR-NEXT: frame-setup JCC_1 %bb.2, 5, implicit $eflags
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: bb.3 (%ir-block.0):
+ ; CORECLR-NEXT: liveins: $rax
+ ; CORECLR-NEXT: {{ $}}
+ ; CORECLR-NEXT: $rsp = frame-setup SUB64rr $rsp, $rax, implicit-def dead $eflags
+ ; CORECLR-NEXT: frame-setup SEH_StackAlloc 45040
+ ; CORECLR-NEXT: $rbp = LEA64r $rsp, 1, $noreg, 128, $noreg
+ ; CORECLR-NEXT: frame-setup SEH_SetFrame 52, 128
+ ; CORECLR-NEXT: frame-setup SEH_EndPrologue
+ ; CORECLR-NEXT: $rsp = frame-setup AND64ri32 $rsp, -4096, implicit-def dead $eflags
+ ; CORECLR-NEXT: renamable $rcx = LEA64r $rsp, 1, $noreg, 4096, $noreg
+ ; CORECLR-NEXT: CALL64pcrel32 @use, csr_win64, implicit $rsp, implicit $ssp, implicit $rcx, implicit-def $rsp, implicit-def $ssp
+ ; CORECLR-NEXT: SEH_BeginEpilogue
+ ; CORECLR-NEXT: $rsp = LEA64r $rbp, 1, $noreg, 44912, $noreg
+ ; CORECLR-NEXT: $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp
+ ; CORECLR-NEXT: SEH_EndEpilogue
+ ; CORECLR-NEXT: RET 0
+ %a = alloca [40000 x i8], align 4096
+ call void @use(ptr %a)
+ ret void
+}
+
+declare void @use(ptr)
More information about the llvm-commits
mailing list