<div dir="ltr">Hans,<div><br></div><div>It seems your change broke sanitizer-windows bot. Could you take a look?</div><div><br></div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-windows/builds/22232" class="cremed">http://lab.llvm.org:8011/builders/sanitizer-windows/builds/22232</a><br><br></div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-windows/builds/22232/steps/run%20tests/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-windows/builds/22232/steps/run%20tests/logs/stdio</a><br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, May 17, 2016 at 1:19 PM Hans Wennborg via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: hans<br>
Date: Tue May 17 15:13:29 2016<br>
New Revision: 269828<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=269828&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=269828&view=rev</a><br>
Log:<br>
X86: Avoid using _chkstk when lowering WIN_ALLOCA instructions<br>
<br>
This patch moves the expansion of WIN_ALLOCA pseudo-instructions<br>
into a separate pass that walks the CFG and lowers the instructions<br>
based on a conservative estimate of the offset between the stack<br>
pointer and the lowest accessed stack address.<br>
<br>
The goal is to reduce binary size and run-time costs by removing<br>
calls to _chkstk. While it doesn't fix all the code quality problems<br>
with inalloca calls, it's an incremental improvement for PR27076.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D20263" rel="noreferrer" target="_blank">http://reviews.llvm.org/D20263</a><br>
<br>
Added:<br>
    llvm/trunk/lib/Target/X86/X86WinAllocaExpander.cpp<br>
    llvm/trunk/test/CodeGen/X86/win-alloca-expander.ll<br>
Modified:<br>
    llvm/trunk/lib/Target/X86/CMakeLists.txt<br>
    llvm/trunk/lib/Target/X86/X86.h<br>
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp<br>
    llvm/trunk/lib/Target/X86/X86ISelLowering.h<br>
    llvm/trunk/lib/Target/X86/X86InstrCompiler.td<br>
    llvm/trunk/lib/Target/X86/X86InstrInfo.td<br>
    llvm/trunk/lib/Target/X86/X86MachineFunctionInfo.h<br>
    llvm/trunk/lib/Target/X86/X86TargetMachine.cpp<br>
    llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll<br>
    llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll<br>
    llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll<br>
    llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll<br>
    llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll<br>
    llvm/trunk/test/CodeGen/X86/inalloca.ll<br>
    llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll<br>
<br>
Modified: llvm/trunk/lib/Target/X86/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/CMakeLists.txt?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/CMakeLists.txt?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Target/X86/CMakeLists.txt Tue May 17 15:13:29 2016<br>
@@ -37,6 +37,7 @@ set(sources<br>
   X86WinEHState.cpp<br>
   X86OptimizeLEAs.cpp<br>
   X86FixupBWInsts.cpp<br>
+  X86WinAllocaExpander.cpp<br>
   )<br>
<br>
 add_llvm_target(X86CodeGen ${sources})<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.h?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.h?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86.h Tue May 17 15:13:29 2016<br>
@@ -59,6 +59,9 @@ FunctionPass *createX86FixupLEAs();<br>
 /// recalculations.<br>
 FunctionPass *createX86OptimizeLEAs();<br>
<br>
+/// Return a pass that expands WinAlloca pseudo-instructions.<br>
+FunctionPass *createX86WinAllocaExpander();<br>
+<br>
 /// Return a pass that optimizes the code-size of x86 call sequences. This is<br>
 /// done by replacing esp-relative movs with pushes.<br>
 FunctionPass *createX86CallFrameOptimization();<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue May 17 15:13:29 2016<br>
@@ -16563,14 +16563,9 @@ X86TargetLowering::LowerDYNAMIC_STACKALL<br>
     Result = DAG.getNode(X86ISD::SEG_ALLOCA, dl, SPTy, Chain,<br>
                                 DAG.getRegister(Vreg, SPTy));<br>
   } else {<br>
-    SDValue Flag;<br>
-    const unsigned Reg = (Subtarget.isTarget64BitLP64() ? X86::RAX : X86::EAX);<br>
-<br>
-    Chain = DAG.getCopyToReg(Chain, dl, Reg, Size, Flag);<br>
-    Flag = Chain.getValue(1);<br>
     SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);<br>
-<br>
-    Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Flag);<br>
+    Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Size);<br>
+    MF.getInfo<X86MachineFunctionInfo>()->setHasWinAlloca(true);<br>
<br>
     const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo();<br>
     unsigned SPReg = RegInfo->getStackRegister();<br>
@@ -23228,18 +23223,6 @@ X86TargetLowering::EmitLoweredSegAlloca(<br>
 }<br>
<br>
 MachineBasicBlock *<br>
-X86TargetLowering::EmitLoweredWinAlloca(MachineInstr *MI,<br>
-                                        MachineBasicBlock *BB) const {<br>
-  assert(!Subtarget.isTargetMachO());<br>
-  DebugLoc DL = MI->getDebugLoc();<br>
-  MachineInstr *ResumeMI = Subtarget.getFrameLowering()->emitStackProbe(<br>
-      *BB->getParent(), *BB, MI, DL, false);<br>
-  MachineBasicBlock *ResumeBB = ResumeMI->getParent();<br>
-  MI->eraseFromParent(); // The pseudo instruction is gone now.<br>
-  return ResumeBB;<br>
-}<br>
-<br>
-MachineBasicBlock *<br>
 X86TargetLowering::EmitLoweredCatchRet(MachineInstr *MI,<br>
                                        MachineBasicBlock *BB) const {<br>
   MachineFunction *MF = BB->getParent();<br>
@@ -23701,8 +23684,6 @@ X86TargetLowering::EmitInstrWithCustomIn<br>
   case X86::TLS_base_addr32:<br>
   case X86::TLS_base_addr64:<br>
     return EmitLoweredTLSAddr(MI, BB);<br>
-  case X86::WIN_ALLOCA:<br>
-    return EmitLoweredWinAlloca(MI, BB);<br>
   case X86::CATCHRET:<br>
     return EmitLoweredCatchRet(MI, BB);<br>
   case X86::CATCHPAD:<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Tue May 17 15:13:29 2016<br>
@@ -1162,9 +1162,6 @@ namespace llvm {<br>
     MachineBasicBlock *EmitLoweredAtomicFP(MachineInstr *I,<br>
                                            MachineBasicBlock *BB) const;<br>
<br>
-    MachineBasicBlock *EmitLoweredWinAlloca(MachineInstr *MI,<br>
-                                              MachineBasicBlock *BB) const;<br>
-<br>
     MachineBasicBlock *EmitLoweredCatchRet(MachineInstr *MI,<br>
                                            MachineBasicBlock *BB) const;<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrCompiler.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86InstrCompiler.td (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrCompiler.td Tue May 17 15:13:29 2016<br>
@@ -99,18 +99,6 @@ def VAARG_64 : I<0, Pseudo,<br>
                     (X86vaarg64 addr:$ap, imm:$size, imm:$mode, imm:$align)),<br>
                   (implicit EFLAGS)]>;<br>
<br>
-// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows<br>
-// targets.  These calls are needed to probe the stack when allocating more than<br>
-// 4k bytes in one go. Touching the stack at 4K increments is necessary to<br>
-// ensure that the guard pages used by the OS virtual memory manager are<br>
-// allocated in correct sequence.<br>
-// The main point of having separate instruction are extra unmodelled effects<br>
-// (compared to ordinary calls) like stack pointer change.<br>
-<br>
-let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in<br>
-  def WIN_ALLOCA : I<0, Pseudo, (outs), (ins),<br>
-                     "# dynamic stack allocation",<br>
-                     [(X86WinAlloca)]>;<br>
<br>
 // When using segmented stacks these are lowered into instructions which first<br>
 // check if the current stacklet has enough free memory. If it does, memory is<br>
@@ -132,6 +120,27 @@ def SEG_ALLOCA_64 : I<0, Pseudo, (outs G<br>
                     Requires<[In64BitMode]>;<br>
 }<br>
<br>
+// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows<br>
+// targets.  These calls are needed to probe the stack when allocating more than<br>
+// 4k bytes in one go. Touching the stack at 4K increments is necessary to<br>
+// ensure that the guard pages used by the OS virtual memory manager are<br>
+// allocated in correct sequence.<br>
+// The main point of having separate instruction are extra unmodelled effects<br>
+// (compared to ordinary calls) like stack pointer change.<br>
+<br>
+let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in<br>
+def WIN_ALLOCA_32 : I<0, Pseudo, (outs), (ins GR32:$size),<br>
+                     "# dynamic stack allocation",<br>
+                     [(X86WinAlloca GR32:$size)]>,<br>
+                     Requires<[NotLP64]>;<br>
+<br>
+let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in<br>
+def WIN_ALLOCA_64 : I<0, Pseudo, (outs), (ins GR64:$size),<br>
+                     "# dynamic stack allocation",<br>
+                     [(X86WinAlloca GR64:$size)]>,<br>
+                     Requires<[In64BitMode]>;<br>
+<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // EH Pseudo Instructions<br>
 //<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Tue May 17 15:13:29 2016<br>
@@ -112,6 +112,8 @@ def SDT_X86TLSBASEADDR : SDTypeProfile<0<br>
<br>
 def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>;<br>
<br>
+def SDT_X86WIN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;<br>
+<br>
 def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;<br>
<br>
 def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>;<br>
@@ -273,8 +275,8 @@ def X86bextr  : SDNode<"X86ISD::BEXTR",<br>
<br>
 def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>;<br>
<br>
-def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDTX86Void,<br>
-                          [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;<br>
+def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA,<br>
+                          [SDNPHasChain, SDNPOutGlue]>;<br>
<br>
 def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA,<br>
                           [SDNPHasChain]>;<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86MachineFunctionInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MachineFunctionInfo.h?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MachineFunctionInfo.h?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86MachineFunctionInfo.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86MachineFunctionInfo.h Tue May 17 15:13:29 2016<br>
@@ -98,6 +98,9 @@ class X86MachineFunctionInfo : public Ma<br>
   /// True if this function uses the red zone.<br>
   bool UsesRedZone = false;<br>
<br>
+  /// True if this function has WIN_ALLOCA instructions.<br>
+  bool HasWinAlloca = false;<br>
+<br>
 private:<br>
   /// ForwardedMustTailRegParms - A list of virtual and physical registers<br>
   /// that must be forwarded to every musttail call.<br>
@@ -172,6 +175,9 @@ public:<br>
<br>
   bool getUsesRedZone() const { return UsesRedZone; }<br>
   void setUsesRedZone(bool V) { UsesRedZone = V; }<br>
+<br>
+  bool hasWinAlloca() const { return HasWinAlloca; }<br>
+  void setHasWinAlloca(bool v) { HasWinAlloca = v; }<br>
 };<br>
<br>
 } // End llvm namespace<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Tue May 17 15:13:29 2016<br>
@@ -266,6 +266,7 @@ void X86PassConfig::addPreRegAlloc() {<br>
     addPass(createX86OptimizeLEAs());<br>
<br>
   addPass(createX86CallFrameOptimization());<br>
+  addPass(createX86WinAllocaExpander());<br>
 }<br>
<br>
 void X86PassConfig::addPostRegAlloc() {<br>
<br>
Added: llvm/trunk/lib/Target/X86/X86WinAllocaExpander.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86WinAllocaExpander.cpp?rev=269828&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86WinAllocaExpander.cpp?rev=269828&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86WinAllocaExpander.cpp (added)<br>
+++ llvm/trunk/lib/Target/X86/X86WinAllocaExpander.cpp Tue May 17 15:13:29 2016<br>
@@ -0,0 +1,294 @@<br>
+//===----- X86WinAllocaExpander.cpp - Expand WinAlloca pseudo instruction -===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file defines a pass that expands WinAlloca pseudo-instructions.<br>
+//<br>
+// It performs a conservative analysis to determine whether each allocation<br>
+// falls within a region of the stack that is safe to use, or whether stack<br>
+// probes must be emitted.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "X86.h"<br>
+#include "X86InstrBuilder.h"<br>
+#include "X86InstrInfo.h"<br>
+#include "X86MachineFunctionInfo.h"<br>
+#include "X86Subtarget.h"<br>
+#include "llvm/ADT/PostOrderIterator.h"<br>
+#include "llvm/CodeGen/MachineFunctionPass.h"<br>
+#include "llvm/CodeGen/MachineInstrBuilder.h"<br>
+#include "llvm/CodeGen/MachineRegisterInfo.h"<br>
+#include "llvm/CodeGen/Passes.h"<br>
+#include "llvm/IR/Function.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include "llvm/Target/TargetInstrInfo.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace {<br>
+<br>
+class X86WinAllocaExpander : public MachineFunctionPass {<br>
+public:<br>
+  X86WinAllocaExpander() : MachineFunctionPass(ID) {}<br>
+<br>
+  bool runOnMachineFunction(MachineFunction &MF) override;<br>
+<br>
+private:<br>
+  /// Strategies for lowering a WinAlloca.<br>
+  enum Lowering { TouchAndSub, Sub, Probe };<br>
+<br>
+  /// Deterministic-order map from WinAlloca instruction to desired lowering.<br>
+  typedef MapVector<MachineInstr*, Lowering> LoweringMap;<br>
+<br>
+  /// Compute which lowering to use for each WinAlloca instruction.<br>
+  void computeLowerings(MachineFunction &MF, LoweringMap& Lowerings);<br>
+<br>
+  /// Get the appropriate lowering based on current offset and amount.<br>
+  Lowering getLowering(int64_t CurrentOffset, int64_t AllocaAmount);<br>
+<br>
+  /// Lower a WinAlloca instruction.<br>
+  void lower(MachineInstr* MI, Lowering L);<br>
+<br>
+  MachineRegisterInfo *MRI;<br>
+  const X86Subtarget *STI;<br>
+  const TargetInstrInfo *TII;<br>
+  const X86RegisterInfo *TRI;<br>
+  unsigned StackPtr;<br>
+  unsigned SlotSize;<br>
+  int64_t StackProbeSize;<br>
+<br>
+  const char *getPassName() const override { return "X86 WinAlloca Expander"; }<br>
+  static char ID;<br>
+};<br>
+<br>
+char X86WinAllocaExpander::ID = 0;<br>
+<br>
+} // end anonymous namespace<br>
+<br>
+FunctionPass *llvm::createX86WinAllocaExpander() {<br>
+  return new X86WinAllocaExpander();<br>
+}<br>
+<br>
+/// Return the allocation amount for a WinAlloca instruction, or -1 if unknown.<br>
+static int64_t getWinAllocaAmount(MachineInstr *MI, MachineRegisterInfo *MRI) {<br>
+  assert(MI->getOpcode() == X86::WIN_ALLOCA_32 ||<br>
+         MI->getOpcode() == X86::WIN_ALLOCA_64);<br>
+  assert(MI->getOperand(0).isReg());<br>
+<br>
+  unsigned AmountReg = MI->getOperand(0).getReg();<br>
+  MachineInstr *Def = MRI->getUniqueVRegDef(AmountReg);<br>
+<br>
+  // Look through copies.<br>
+  while (Def && Def->isCopy() && Def->getOperand(1).isReg())<br>
+    Def = MRI->getUniqueVRegDef(Def->getOperand(1).getReg());<br>
+<br>
+  if (!Def ||<br>
+      (Def->getOpcode() != X86::MOV32ri && Def->getOpcode() != X86::MOV64ri) ||<br>
+      !Def->getOperand(1).isImm())<br>
+    return -1;<br>
+<br>
+  return Def->getOperand(1).getImm();<br>
+}<br>
+<br>
+X86WinAllocaExpander::Lowering<br>
+X86WinAllocaExpander::getLowering(int64_t CurrentOffset,<br>
+                                  int64_t AllocaAmount) {<br>
+  // For a non-constant amount or a large amount, we have to probe.<br>
+  if (AllocaAmount < 0 || AllocaAmount > StackProbeSize)<br>
+    return Probe;<br>
+<br>
+  // If it fits within the safe region of the stack, just subtract.<br>
+  if (CurrentOffset + AllocaAmount <= StackProbeSize)<br>
+    return Sub;<br>
+<br>
+  // Otherwise, touch the current tip of the stack, then subtract.<br>
+  return TouchAndSub;<br>
+}<br>
+<br>
+static bool isPushPop(const MachineInstr &MI) {<br>
+  switch (MI.getOpcode()) {<br>
+  case X86::PUSH32i8:<br>
+  case X86::PUSH32r:<br>
+  case X86::PUSH32rmm:<br>
+  case X86::PUSH32rmr:<br>
+  case X86::PUSHi32:<br>
+  case X86::PUSH64i8:<br>
+  case X86::PUSH64r:<br>
+  case X86::PUSH64rmm:<br>
+  case X86::PUSH64rmr:<br>
+  case X86::PUSH64i32:<br>
+  case X86::POP32r:<br>
+  case X86::POP64r:<br>
+    return true;<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+void X86WinAllocaExpander::computeLowerings(MachineFunction &MF,<br>
+                                            LoweringMap &Lowerings) {<br>
+  // Do a one-pass reverse post-order walk of the CFG to conservatively estimate<br>
+  // the offset between the stack pointer and the lowest touched part of the<br>
+  // stack, and use that to decide how to lower each WinAlloca instruction.<br>
+<br>
+  // Initialize OutOffset[B], the stack offset at exit from B, to something big.<br>
+  DenseMap<MachineBasicBlock *, int64_t> OutOffset;<br>
+  for (MachineBasicBlock &MBB : MF)<br>
+    OutOffset[&MBB] = INT32_MAX;<br>
+<br>
+  // Note: we don't know the offset at the start of the entry block since the<br>
+  // prologue hasn't been inserted yet, and how much that will adjust the stack<br>
+  // pointer depends on register spills, which have not been computed yet.<br>
+<br>
+  // Compute the reverse post-order.<br>
+  ReversePostOrderTraversal<MachineFunction*> RPO(&MF);<br>
+<br>
+  for (MachineBasicBlock *MBB : RPO) {<br>
+    int64_t Offset = -1;<br>
+    for (MachineBasicBlock *Pred : MBB->predecessors())<br>
+      Offset = std::max(Offset, OutOffset[Pred]);<br>
+    if (Offset == -1) Offset = INT32_MAX;<br>
+<br>
+    for (MachineInstr &MI : *MBB) {<br>
+      if (MI.getOpcode() == X86::WIN_ALLOCA_32 ||<br>
+          MI.getOpcode() == X86::WIN_ALLOCA_64) {<br>
+        // A WinAlloca moves StackPtr, and potentially touches it.<br>
+        int64_t Amount = getWinAllocaAmount(&MI, MRI);<br>
+        Lowering L = getLowering(Offset, Amount);<br>
+        Lowerings[&MI] = L;<br>
+        switch (L) {<br>
+        case Sub:<br>
+          Offset += Amount;<br>
+          break;<br>
+        case TouchAndSub:<br>
+          Offset = Amount;<br>
+          break;<br>
+        case Probe:<br>
+          Offset = 0;<br>
+          break;<br>
+        }<br>
+      } else if (MI.isCall() || isPushPop(MI)) {<br>
+        // Calls, pushes and pops touch the tip of the stack.<br>
+        Offset = 0;<br>
+      } else if (MI.getOpcode() == X86::ADJCALLSTACKUP32 ||<br>
+                 MI.getOpcode() == X86::ADJCALLSTACKUP64) {<br>
+        Offset -= MI.getOperand(0).getImm();<br>
+      } else if (MI.getOpcode() == X86::ADJCALLSTACKDOWN32 ||<br>
+                 MI.getOpcode() == X86::ADJCALLSTACKDOWN64) {<br>
+        Offset += MI.getOperand(0).getImm();<br>
+      } else if (MI.modifiesRegister(StackPtr, TRI)) {<br>
+        // Any other modification of SP means we've lost track of it.<br>
+        Offset = INT32_MAX;<br>
+      }<br>
+    }<br>
+<br>
+    OutOffset[MBB] = Offset;<br>
+  }<br>
+}<br>
+<br>
+static unsigned getSubOpcode(bool Is64Bit, int64_t Amount) {<br>
+  if (Is64Bit)<br>
+    return isInt<8>(Amount) ? X86::SUB64ri8 : X86::SUB64ri32;<br>
+  return isInt<8>(Amount) ? X86::SUB32ri8 : X86::SUB32ri;<br>
+}<br>
+<br>
+void X86WinAllocaExpander::lower(MachineInstr* MI, Lowering L) {<br>
+  DebugLoc DL = MI->getDebugLoc();<br>
+  MachineBasicBlock *MBB = MI->getParent();<br>
+  MachineBasicBlock::iterator I = *MI;<br>
+<br>
+  int64_t Amount = getWinAllocaAmount(MI, MRI);<br>
+  if (Amount == 0) {<br>
+    MI->eraseFromParent();<br>
+    return;<br>
+  }<br>
+<br>
+  bool Is64Bit = STI->is64Bit();<br>
+  assert(SlotSize == 4 || SlotSize == 8);<br>
+  unsigned RegA = (SlotSize == 8) ? X86::RAX : X86::EAX;<br>
+<br>
+  switch (L) {<br>
+  case TouchAndSub:<br>
+    assert(Amount >= SlotSize);<br>
+<br>
+    // Use a push to touch the top of the stack.<br>
+    BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::PUSH64r : X86::PUSH32r))<br>
+        .addReg(RegA, RegState::Undef);<br>
+    Amount -= SlotSize;<br>
+    if (!Amount)<br>
+      break;<br>
+<br>
+    // Fall through to make any remaining adjustment.<br>
+  case Sub:<br>
+    assert(Amount > 0);<br>
+    if (Amount == SlotSize) {<br>
+      // Use push to save size.<br>
+      BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::PUSH64r : X86::PUSH32r))<br>
+          .addReg(RegA, RegState::Undef);<br>
+    } else {<br>
+      // Sub.<br>
+      BuildMI(*MBB, I, DL, TII->get(getSubOpcode(Is64Bit, Amount)), StackPtr)<br>
+          .addReg(StackPtr)<br>
+          .addImm(Amount);<br>
+    }<br>
+    break;<br>
+  case Probe:<br>
+    // The probe lowering expects the amount in RAX/EAX.<br>
+    BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegA)<br>
+        .addReg(MI->getOperand(0).getReg());<br>
+<br>
+    // Do the probe.<br>
+    STI->getFrameLowering()->emitStackProbe(*MBB->getParent(), *MBB, MI, DL,<br>
+                                            /*InPrologue=*/false);<br>
+    break;<br>
+  }<br>
+<br>
+  unsigned AmountReg = MI->getOperand(0).getReg();<br>
+  MI->eraseFromParent();<br>
+<br>
+  // Delete the definition of AmountReg, possibly walking a chain of copies.<br>
+  for (;;) {<br>
+    if (!MRI->use_empty(AmountReg))<br>
+      break;<br>
+    MachineInstr *AmountDef = MRI->getUniqueVRegDef(AmountReg);<br>
+    if (!AmountDef)<br>
+      break;<br>
+    if (AmountDef->isCopy() && AmountDef->getOperand(1).isReg())<br>
+      AmountReg = AmountDef->getOperand(1).isReg();<br>
+    AmountDef->eraseFromParent();<br>
+    break;<br>
+  }<br>
+}<br>
+<br>
+bool X86WinAllocaExpander::runOnMachineFunction(MachineFunction &MF) {<br>
+  if (!MF.getInfo<X86MachineFunctionInfo>()->hasWinAlloca())<br>
+    return false;<br>
+<br>
+  MRI = &MF.getRegInfo();<br>
+  STI = &MF.getSubtarget<X86Subtarget>();<br>
+  TII = STI->getInstrInfo();<br>
+  TRI = STI->getRegisterInfo();<br>
+  StackPtr = TRI->getStackRegister();<br>
+  SlotSize = TRI->getSlotSize();<br>
+<br>
+  StackProbeSize = 4096;<br>
+  if (MF.getFunction()->hasFnAttribute("stack-probe-size")) {<br>
+    MF.getFunction()<br>
+        ->getFnAttribute("stack-probe-size")<br>
+        .getValueAsString()<br>
+        .getAsInteger(0, StackProbeSize);<br>
+  }<br>
+<br>
+  LoweringMap Lowerings;<br>
+  computeLowerings(MF, Lowerings);<br>
+  for (auto &P : Lowerings)<br>
+    lower(P.first, P.second);<br>
+<br>
+  return true;<br>
+}<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll Tue May 17 15:13:29 2016<br>
@@ -38,8 +38,8 @@ ehcleanup:<br>
 ; CHECK: pushl %ebp<br>
 ; CHECK: movl %esp, %ebp<br>
 ; CHECK: subl ${{[0-9]+}}, %esp<br>
-; CHECK: movl $8, %eax<br>
-; CHECK: calll __chkstk<br>
+; CHECK: pushl %eax<br>
+; CHECK: pushl %eax<br>
 ; CHECK: calll "??0A@@QAE@XZ"<br>
 ; CHECK: calll "??0A@@QAE@XZ"<br>
 ; CHECK: calll _takes_two<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/dynamic-alloca-in-entry.ll Tue May 17 15:13:29 2016<br>
@@ -15,5 +15,5 @@ define void @bar() {<br>
   ret void<br>
 }<br>
 ; CHECK-LABEL: _bar:<br>
-; CHECK: calll __chkstk<br>
+; CHECK: pushl %eax<br>
 ; CHECK: retl<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/inalloca-ctor.ll Tue May 17 15:13:29 2016<br>
@@ -12,8 +12,8 @@ define void @g() {<br>
 entry:<br>
   %args = alloca inalloca %frame<br>
   %c = getelementptr %frame, %frame* %args, i32 0, i32 2<br>
-; CHECK: movl    $20, %eax<br>
-; CHECK: calll   __chkstk<br>
+; CHECK: pushl   %eax<br>
+; CHECK: subl    $16, %esp<br>
 ; CHECK: movl %esp,<br>
   call void @Foo_ctor(%Foo* %c)<br>
 ; CHECK: leal 12(%{{.*}}),<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/inalloca-invoke.ll Tue May 17 15:13:29 2016<br>
@@ -21,7 +21,8 @@ blah:<br>
   %beg = getelementptr %frame.reverse, %frame.reverse* %rev_args, i32 0, i32 0<br>
   %end = getelementptr %frame.reverse, %frame.reverse* %rev_args, i32 0, i32 1<br>
<br>
-; CHECK:  calll   __chkstk<br>
+; CHECK:  pushl   %eax<br>
+; CHECK:  subl    $20, %esp<br>
 ; CHECK:  movl %esp, %[[beg:[^ ]*]]<br>
 ; CHECK:  leal 12(%[[beg]]), %[[end:[^ ]*]]<br>
<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/inalloca-stdcall.ll Tue May 17 15:13:29 2016<br>
@@ -8,8 +8,8 @@ declare x86_stdcallcc void @i(i32 %a)<br>
 define void @g() {<br>
 ; CHECK-LABEL: _g:<br>
   %b = alloca inalloca %Foo<br>
-; CHECK: movl    $8, %eax<br>
-; CHECK: calll   __chkstk<br>
+; CHECK: pushl   %eax<br>
+; CHECK: pushl   %eax<br>
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0<br>
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1<br>
   store i32 13, i32* %f1<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/inalloca.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inalloca.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/inalloca.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/inalloca.ll Tue May 17 15:13:29 2016<br>
@@ -8,8 +8,8 @@ define void @a() {<br>
 ; CHECK-LABEL: _a:<br>
 entry:<br>
   %b = alloca inalloca %Foo<br>
-; CHECK: movl    $8, %eax<br>
-; CHECK: calll   __chkstk<br>
+; CHECK: pushl   %eax<br>
+; CHECK: pushl   %eax<br>
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0<br>
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1<br>
   store i32 13, i32* %f1<br>
@@ -28,8 +28,8 @@ define void @b() {<br>
 ; CHECK-LABEL: _b:<br>
 entry:<br>
   %b = alloca inalloca %Foo<br>
-; CHECK: movl    $8, %eax<br>
-; CHECK: calll   __chkstk<br>
+; CHECK: pushl   %eax<br>
+; CHECK: pushl   %eax<br>
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0<br>
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1<br>
   store i32 13, i32* %f1<br>
@@ -49,8 +49,8 @@ define void @c() {<br>
 ; CHECK-LABEL: _c:<br>
 entry:<br>
   %b = alloca inalloca %Foo<br>
-; CHECK: movl    $8, %eax<br>
-; CHECK: calll   __chkstk<br>
+; CHECK: pushl   %eax<br>
+; CHECK: pushl   %eax<br>
   %f1 = getelementptr %Foo, %Foo* %b, i32 0, i32 0<br>
   %f2 = getelementptr %Foo, %Foo* %b, i32 0, i32 1<br>
   store i32 13, i32* %f1<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll?rev=269828&r1=269827&r2=269828&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll?rev=269828&r1=269827&r2=269828&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/shrink-wrap-chkstk.ll Tue May 17 15:13:29 2016<br>
@@ -7,7 +7,7 @@<br>
 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"<br>
 target triple = "i686-pc-windows-msvc18.0.0"<br>
<br>
-%struct.S = type { [12 x i8] }<br>
+%struct.S = type { [8192 x i8] }<br>
<br>
 define x86_thiscallcc void @call_inalloca(i1 %x) {<br>
 entry:<br>
@@ -29,7 +29,7 @@ bb2:<br>
 ; CHECK-LABEL: _call_inalloca: # @call_inalloca<br>
 ; CHECK: pushl %ebp<br>
 ; CHECK: movl %esp, %ebp<br>
-; CHECK: movl $12, %eax<br>
+; CHECK: movl $8192, %eax<br>
 ; CHECK: calll __chkstk<br>
 ; CHECK: calll _inalloca_params<br>
 ; CHECK: movl %ebp, %esp<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/win-alloca-expander.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-alloca-expander.ll?rev=269828&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-alloca-expander.ll?rev=269828&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/win-alloca-expander.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/win-alloca-expander.ll Tue May 17 15:13:29 2016<br>
@@ -0,0 +1,153 @@<br>
+; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s<br>
+<br>
+%struct.S = type { [1024 x i8] }<br>
+%struct.T = type { [3000 x i8] }<br>
+%struct.U = type { [10000 x i8] }<br>
+<br>
+define void @basics() {<br>
+; CHECK-LABEL: basics:<br>
+entry:<br>
+  br label %bb1<br>
+<br>
+; Allocation move sizes should have been removed.<br>
+; CHECK-NOT: movl $1024<br>
+; CHECK-NOT: movl $3000<br>
+<br>
+bb1:<br>
+  %p0 = alloca %struct.S<br>
+; The allocation is small enough not to require stack probing, but the %esp<br>
+; offset after the prologue is not known, so the stack must be touched before<br>
+; the pointer is adjusted.<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $1020, %esp<br>
+<br>
+  %saved_stack = tail call i8* @llvm.stacksave()<br>
+<br>
+  %p1 = alloca %struct.S<br>
+; We know the %esp offset from above, so there is no need to touch the stack<br>
+; before adjusting it.<br>
+; CHECK: subl $1024, %esp<br>
+<br>
+  %p2 = alloca %struct.T<br>
+; The offset is now 2048 bytes, so allocating a T must touch the stack again.<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $2996, %esp<br>
+<br>
+  call void @f(%struct.S* %p0)<br>
+; CHECK: calll<br>
+<br>
+  %p3 = alloca %struct.T<br>
+; The call above touched the stack, so there is room for a T object.<br>
+; CHECK: subl $3000, %esp<br>
+<br>
+  %p4 = alloca %struct.U<br>
+; The U object is large enough to require stack probing.<br>
+; CHECK: movl $10000, %eax<br>
+; CHECK: calll __chkstk<br>
+<br>
+  %p5 = alloca %struct.T<br>
+; The stack probing above touched the tip of the stack, so there's room for a T.<br>
+; CHECK: subl $3000, %esp<br>
+<br>
+  call void @llvm.stackrestore(i8* %saved_stack)<br>
+  %p6 = alloca %struct.S<br>
+; The stack restore means we lose track of the stack pointer and must probe.<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $1020, %esp<br>
+<br>
+; Use the pointers so they're not optimized away.<br>
+  call void @f(%struct.S* %p1)<br>
+  call void @g(%struct.T* %p2)<br>
+  call void @g(%struct.T* %p3)<br>
+  call void @h(%struct.U* %p4)<br>
+  call void @g(%struct.T* %p5)<br>
+  ret void<br>
+}<br>
+<br>
+define void @loop() {<br>
+; CHECK-LABEL: loop:<br>
+entry:<br>
+  br label %bb1<br>
+<br>
+bb1:<br>
+  %p1 = alloca %struct.S<br>
+; The entry offset is unknown; touch-and-sub.<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $1020, %esp<br>
+  br label %loop1<br>
+<br>
+loop1:<br>
+  %i1 = phi i32 [ 10, %bb1 ], [ %dec1, %loop1 ]<br>
+  %p2 = alloca %struct.S<br>
+; We know the incoming offset from bb1, but from the back-edge, we assume the<br>
+; worst, and therefore touch-and-sub to allocate.<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $1020, %esp<br>
+  %dec1 = sub i32 %i1, 1<br>
+  %cmp1 = icmp sgt i32 %i1, 0<br>
+  br i1 %cmp1, label %loop1, label %end<br>
+; CHECK: decl<br>
+; CHECK: jg<br>
+<br>
+end:<br>
+  call void @f(%struct.S* %p1)<br>
+  call void @f(%struct.S* %p2)<br>
+  ret void<br>
+}<br>
+<br>
+define void @probe_size_attribute() "stack-probe-size"="512" {<br>
+; CHECK-LABEL: probe_size_attribute:<br>
+entry:<br>
+  br label %bb1<br>
+<br>
+bb1:<br>
+  %p0 = alloca %struct.S<br>
+; The allocation would be small enough not to require probing, if it wasn't<br>
+; for the stack-probe-size attribute.<br>
+; CHECK: movl $1024, %eax<br>
+; CHECK: calll __chkstk<br>
+  call void @f(%struct.S* %p0)<br>
+  ret void<br>
+}<br>
+<br>
+define void @cfg(i1 %x, i1 %y) {<br>
+; Test that the blocks are analyzed in the correct order.<br>
+; CHECK-LABEL: cfg:<br>
+entry:<br>
+  br i1 %x, label %bb1, label %bb2<br>
+<br>
+bb1:<br>
+  %p1 = alloca %struct.S<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $1020, %esp<br>
+  br label %bb3<br>
+bb2:<br>
+  %p2 = alloca %struct.T<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $2996, %esp<br>
+  br label %bb3<br>
+<br>
+bb3:<br>
+  br i1 %y, label %bb4, label %bb5<br>
+<br>
+bb4:<br>
+  %p4 = alloca %struct.S<br>
+; CHECK: subl $1024, %esp<br>
+  call void @f(%struct.S* %p4)<br>
+  ret void<br>
+<br>
+bb5:<br>
+  %p5 = alloca %struct.T<br>
+; CHECK: pushl %eax<br>
+; CHECK: subl $2996, %esp<br>
+  call void @g(%struct.T* %p5)<br>
+  ret void<br>
+}<br>
+<br>
+<br>
+declare void @f(%struct.S*)<br>
+declare void @g(%struct.T*)<br>
+declare void @h(%struct.U*)<br>
+<br>
+declare i8* @llvm.stacksave()<br>
+declare void @llvm.stackrestore(i8*)<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><div dir="ltr">-- <br></div>Mike<br>Sent from phone