[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