[llvm] r262370 - [X86] Elide references to _chkstk for dynamic allocas

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 1 11:20:24 PST 2016


Author: majnemer
Date: Tue Mar  1 13:20:23 2016
New Revision: 262370

URL: http://llvm.org/viewvc/llvm-project?rev=262370&view=rev
Log:
[X86] Elide references to _chkstk for dynamic allocas

The _chkstk function is called by the compiler to probe the stack in an
order consistent with Windows' expectations.  However, it is possible to
elide the call to _chkstk and manually adjust the stack pointer if we
can prove that the allocation is fixed size and smaller than the probe
size.

This shrinks chrome.dll, chrome_child.dll and chrome.exe by a
cummulative ~133 KB.

Differential Revision: http://reviews.llvm.org/D17679

Modified:
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll
    llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll
    llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll
    llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll
    llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll
    llvm/trunk/test/CodeGen/X86/inalloca.ll
    llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Mar  1 13:20:23 2016
@@ -16366,9 +16366,8 @@ SDValue
 X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
                                            SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
+  const Function *F = MF.getFunction();
   bool SplitStack = MF.shouldSplitStack();
-  bool Lower = (Subtarget.isOSWindows() && !Subtarget.isTargetMachO()) ||
-               SplitStack;
   SDLoc dl(Op);
 
   // Get the inputs.
@@ -16382,21 +16381,45 @@ X86TargetLowering::LowerDYNAMIC_STACKALL
   // pointer when other instructions are using the stack.
   Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, dl, true), dl);
 
+  const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
   bool Is64Bit = Subtarget.is64Bit();
   MVT SPTy = getPointerTy(DAG.getDataLayout());
 
+  bool CheckStack = SplitStack;
+  if (!CheckStack && Subtarget.isOSWindows() && !Subtarget.isTargetMachO()) {
+    // The Windows ABI requires us to probe the stack for allocations beyond
+    // the probe size.
+    if (auto *SizeC = dyn_cast<ConstantSDNode>(Size)) {
+      // Try to elide the probe if we can prove that this dynamic allocation is
+      // smaller than the probe size.
+      unsigned StackProbeSize = 4096;
+      if (F->hasFnAttribute("stack-probe-size"))
+        F->getFnAttribute("stack-probe-size")
+            .getValueAsString()
+            .getAsInteger(0, StackProbeSize);
+      unsigned AlignedAlloc = SizeC->getZExtValue();
+      // Round the dynamic alloca's size up to it's alignment.
+      if (Align)
+        AlignedAlloc = alignTo(AlignedAlloc, Align);
+
+      // If the aligned allocation is smaller than the probe size, then we don't
+      // need to probe the stack.
+      CheckStack = AlignedAlloc >= StackProbeSize;
+    } else {
+      // We cannot tell how big this dynamic alloca will be, probe the stack.
+      CheckStack = true;
+    }
+  }
+
   SDValue Result;
-  if (!Lower) {
+  if (!CheckStack) {
     const TargetLowering &TLI = DAG.getTargetLoweringInfo();
     unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
     assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
                     " not tell us which reg is the stack pointer!");
-    EVT VT = Node->getValueType(0);
-    SDValue Tmp3 = Node->getOperand(2);
 
     SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
     Chain = SP.getValue(1);
-    unsigned Align = cast<ConstantSDNode>(Tmp3)->getZExtValue();
     const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();
     unsigned StackAlign = TFI.getStackAlignment();
     Result = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
@@ -16410,8 +16433,6 @@ X86TargetLowering::LowerDYNAMIC_STACKALL
     if (Is64Bit) {
       // The 64 bit implementation of segmented stacks needs to clobber both r10
       // r11. This makes it impossible to use it along with nested parameters.
-      const Function *F = MF.getFunction();
-
       for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
            I != E; ++I)
         if (I->hasNestAttr())
@@ -16434,7 +16455,6 @@ X86TargetLowering::LowerDYNAMIC_STACKALL
 
     Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Flag);
 
-    const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
     unsigned SPReg = RegInfo->getStackRegister();
     SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, SPTy);
     Chain = SP.getValue(1);

Modified: llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll (original)
+++ llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll Tue Mar  1 13:20:23 2016
@@ -38,8 +38,9 @@ ehcleanup:
 ; CHECK: pushl %ebp
 ; CHECK: movl %esp, %ebp
 ; CHECK: subl ${{[0-9]+}}, %esp
-; CHECK: movl $8, %eax
-; CHECK: calll __chkstk
+; CHECK: movl %esp, %[[tmp_sp1:.*]]
+; CHECK: leal -8(%[[tmp_sp1]]), %[[tmp_sp2:.*]]
+; CHECK: %[[tmp_sp2]], %esp
 ; CHECK: calll "??0A@@QAE at XZ"
 ; CHECK: calll "??0A@@QAE at XZ"
 ; CHECK: calll _takes_two

Modified: llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll (original)
+++ llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll Tue Mar  1 13:20:23 2016
@@ -15,5 +15,8 @@ define void @bar() {
   ret void
 }
 ; CHECK-LABEL: _bar:
-; CHECK: calll __chkstk
+; CHECK: movl %esp, %ebp
+; CHECK: movl %esp, %[[sp_tmp:.*]]
+; CHECK: addl $-4, %[[sp_tmp]]
+; CHECK: movl %[[sp_tmp]], %esp
 ; CHECK: retl

Modified: llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll (original)
+++ llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll Tue Mar  1 13:20:23 2016
@@ -10,13 +10,14 @@ declare void @Foo_ctor(%Foo* %this)
 
 define void @g() {
 entry:
+; CHECK: movl    %esp, %ebp
   %args = alloca inalloca %frame
   %c = getelementptr %frame, %frame* %args, i32 0, i32 2
-; CHECK: movl    $20, %eax
-; CHECK: calll   __chkstk
-; CHECK: movl %esp,
+; CHECK: movl    %esp, %[[tmp_sp1:.*]]
+; CHECK: leal    -20(%[[tmp_sp1]]), %[[tmp_sp2:.*]]
+; CHECK: movl    %[[tmp_sp2]], %esp
   call void @Foo_ctor(%Foo* %c)
-; CHECK: leal 12(%{{.*}}),
+; CHECK: leal -8(%[[tmp_sp1]]),
 ; CHECK-NEXT: pushl
 ; CHECK-NEXT: calll _Foo_ctor
 ; CHECK: addl $4, %esp

Modified: llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll (original)
+++ llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll Tue Mar  1 13:20:23 2016
@@ -12,6 +12,7 @@ declare void @plus(%Iter* sret, %Iter*,
 declare void @reverse(%frame.reverse* inalloca align 4)
 
 define i32 @main() personality i32 (...)* @pers {
+; CHECK: movl    %esp, %ebp
   %temp.lvalue = alloca %Iter
   br label %blah
 
@@ -21,9 +22,10 @@ blah:
   %beg = getelementptr %frame.reverse, %frame.reverse* %rev_args, i32 0, i32 0
   %end = getelementptr %frame.reverse, %frame.reverse* %rev_args, i32 0, i32 1
 
-; CHECK:  calll   __chkstk
-; CHECK:  movl %esp, %[[beg:[^ ]*]]
-; CHECK:  leal 12(%[[beg]]), %[[end:[^ ]*]]
+; CHECK:  movl %esp, %[[end:.*]]
+; CHECK:  leal -24(%[[end]]), %[[beg:.*]]
+; CHECK:  movl %[[beg]], %esp
+; CHECK:  addl $-12, %[[end]]
 
   call void @begin(%Iter* sret %temp.lvalue)
 ; CHECK:  calll _begin

Modified: llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll (original)
+++ llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll Tue Mar  1 13:20:23 2016
@@ -7,16 +7,16 @@ declare x86_stdcallcc void @i(i32 %a)
 
 define void @g() {
 ; CHECK-LABEL: _g:
+; CHECK: movl    %esp, %ebp
   %b = alloca inalloca %Foo
-; CHECK: movl    $8, %eax
-; CHECK: calll   __chkstk
+; CHECK: movl    %esp, %[[tmp_sp:.*]]
+; CHECK: leal    -8(%[[tmp_sp]]), %esp
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1
   store i32 13, i32* %f1
   store i32 42, i32* %f2
-; CHECK: movl %esp, %eax
-; CHECK: movl    $13, (%eax)
-; CHECK: movl    $42, 4(%eax)
+; CHECK: movl    $13, -8(%[[tmp_sp]])
+; CHECK: movl    $42, -4(%[[tmp_sp]])
   call x86_stdcallcc void @f(%Foo* inalloca %b)
 ; CHECK: calll   _f at 8
 ; CHECK-NOT: %esp

Modified: llvm/trunk/test/CodeGen/X86/inalloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inalloca.ll (original)
+++ llvm/trunk/test/CodeGen/X86/inalloca.ll Tue Mar  1 13:20:23 2016
@@ -7,16 +7,16 @@ declare void @f(%Foo* inalloca %b)
 define void @a() {
 ; CHECK-LABEL: _a:
 entry:
+; CHECK: movl    %esp, %ebp
   %b = alloca inalloca %Foo
-; CHECK: movl    $8, %eax
-; CHECK: calll   __chkstk
+; CHECK: movl    %esp, %[[tmp_sp:.*]]
+; CHECK: leal    -8(%[[tmp_sp]]), %esp
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1
   store i32 13, i32* %f1
   store i32 42, i32* %f2
-; CHECK: movl %esp, %eax
-; CHECK: movl    $13, (%eax)
-; CHECK: movl    $42, 4(%eax)
+; CHECK: movl    $13, -8(%[[tmp_sp]])
+; CHECK: movl    $42, -4(%[[tmp_sp]])
   call void @f(%Foo* inalloca %b)
 ; CHECK: calll   _f
   ret void
@@ -27,16 +27,16 @@ declare void @inreg_with_inalloca(i32 in
 define void @b() {
 ; CHECK-LABEL: _b:
 entry:
+; CHECK: movl    %esp, %ebp
   %b = alloca inalloca %Foo
-; CHECK: movl    $8, %eax
-; CHECK: calll   __chkstk
+; CHECK: movl    %esp, %[[tmp_sp:.*]]
+; CHECK: leal    -8(%[[tmp_sp]]), %esp
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1
   store i32 13, i32* %f1
   store i32 42, i32* %f2
-; CHECK: movl %esp, %eax
-; CHECK: movl    $13, (%eax)
-; CHECK: movl    $42, 4(%eax)
+; CHECK: movl    $13, -8(%[[tmp_sp]])
+; CHECK: movl    $42, -4(%[[tmp_sp]])
   call void @inreg_with_inalloca(i32 inreg 1, %Foo* inalloca %b)
 ; CHECK: movl    $1, %eax
 ; CHECK: calll   _inreg_with_inalloca
@@ -48,16 +48,16 @@ declare x86_thiscallcc void @thiscall_wi
 define void @c() {
 ; CHECK-LABEL: _c:
 entry:
+; CHECK: movl    %esp, %ebp
   %b = alloca inalloca %Foo
-; CHECK: movl    $8, %eax
-; CHECK: calll   __chkstk
+; CHECK: movl    %esp, %[[tmp_sp:.*]]
+; CHECK: leal    -8(%[[tmp_sp]]), %esp
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1
   store i32 13, i32* %f1
   store i32 42, i32* %f2
-; CHECK: movl %esp, %eax
-; CHECK-DAG: movl    $13, (%eax)
-; CHECK-DAG: movl    $42, 4(%eax)
+; CHECK-DAG: movl    $13, -8(%[[tmp_sp]])
+; CHECK-DAG: movl    $42, -4(%[[tmp_sp]])
   call x86_thiscallcc void @thiscall_with_inalloca(i8* null, %Foo* inalloca %b)
 ; CHECK-DAG: xorl    %ecx, %ecx
 ; CHECK: calll   _thiscall_with_inalloca

Modified: llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll?rev=262370&r1=262369&r2=262370&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll (original)
+++ llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll Tue Mar  1 13:20:23 2016
@@ -9,7 +9,7 @@ target triple = "i686-pc-windows-msvc18.
 
 %struct.S = type { [12 x i8] }
 
-define x86_thiscallcc void @call_inalloca(i1 %x) {
+define x86_thiscallcc void @call_inalloca(i1 %x) "stack-probe-size"="12" {
 entry:
   %argmem = alloca inalloca <{ %struct.S }>, align 4
   %argidx1 = getelementptr inbounds <{ %struct.S }>, <{ %struct.S }>* %argmem, i32 0, i32 0, i32 0, i32 0




More information about the llvm-commits mailing list