[llvm] r231386 - Replace llvm.frameallocate with llvm.frameescape

Reid Kleckner reid at kleckner.net
Thu Mar 5 10:26:35 PST 2015


Author: rnk
Date: Thu Mar  5 12:26:34 2015
New Revision: 231386

URL: http://llvm.org/viewvc/llvm-project?rev=231386&view=rev
Log:
Replace llvm.frameallocate with llvm.frameescape

Turns out it's pretty straightforward and simplifies the implementation.

Reviewers: andrew.w.kaylor

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

Added:
    llvm/trunk/test/CodeGen/X86/frameescape.ll
    llvm/trunk/test/Verifier/frameescape.ll
Removed:
    llvm/trunk/test/CodeGen/X86/frameallocate.ll
    llvm/trunk/test/Verifier/frameallocate.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/IR/CallSite.h
    llvm/trunk/include/llvm/IR/Intrinsics.td
    llvm/trunk/include/llvm/MC/MCContext.h
    llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/lib/MC/MCContext.cpp
    llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
    llvm/trunk/test/CodeGen/WinEH/cppeh-catch-all.ll
    llvm/trunk/test/CodeGen/WinEH/cppeh-catch-scalar.ll
    llvm/trunk/test/CodeGen/WinEH/cppeh-frame-vars.ll
    llvm/trunk/test/CodeGen/WinEH/cppeh-inalloca.ll
    llvm/trunk/test/CodeGen/WinEH/cppeh-min-unwind.ll
    llvm/trunk/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Thu Mar  5 12:26:34 2015
@@ -7614,7 +7614,7 @@ Note that calling this intrinsic does no
 other aggressive transformations, so the value returned may not be that
 of the obvious source-language caller.
 
-'``llvm.frameallocate``' and '``llvm.framerecover``' Intrinsics
+'``llvm.frameescape``' and '``llvm.framerecover``' Intrinsics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Syntax:
@@ -7622,24 +7622,23 @@ Syntax:
 
 ::
 
-      declare i8* @llvm.frameallocate(i32 %size)
-      declare i8* @llvm.framerecover(i8* %func, i8* %fp)
+      declare void @llvm.frameescape(...)
+      declare i8* @llvm.framerecover(i8* %func, i8* %fp, i32 %idx)
 
 Overview:
 """""""""
 
-The '``llvm.frameallocate``' intrinsic allocates stack memory at some fixed
-offset from the frame pointer, and the '``llvm.framerecover``'
-intrinsic applies that offset to a live frame pointer to recover the address of
-the allocation. The offset is computed during frame layout of the caller of
-``llvm.frameallocate``.
+The '``llvm.frameescape``' intrinsic escapes offsets of a collection of static
+allocas, and the '``llvm.framerecover``' intrinsic applies those offsets to a
+live frame pointer to recover the address of the allocation. The offset is
+computed during frame layout of the caller of ``llvm.frameescape``.
 
 Arguments:
 """"""""""
 
-The ``size`` argument to '``llvm.frameallocate``' must be a constant integer
-indicating the amount of stack memory to allocate. As with allocas, allocating
-zero bytes is legal, but the result is undefined.
+All arguments to '``llvm.frameescape``' must be pointers to static allocas or
+casts of static allocas. Each function can only call '``llvm.frameescape``'
+once, and it can only do so from the entry block.
 
 The ``func`` argument to '``llvm.framerecover``' must be a constant
 bitcasted pointer to a function defined in the current module. The code
@@ -7651,6 +7650,9 @@ pointer of a call frame that is currentl
 '``llvm.frameaddress``' is one way to produce such a value, but most platforms
 also expose the frame pointer through stack unwinding mechanisms.
 
+The ``idx`` argument to '``llvm.framerecover``' indicates which alloca passed to
+'``llvm.frameescape``' to recover. It is zero-indexed.
+
 Semantics:
 """"""""""
 

Modified: llvm/trunk/include/llvm/IR/CallSite.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/CallSite.h (original)
+++ llvm/trunk/include/llvm/IR/CallSite.h Thu Mar  5 12:26:34 2015
@@ -151,7 +151,12 @@ public:
   IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); }
   bool arg_empty() const { return arg_end() == arg_begin(); }
   unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
-  
+
+  /// arg_operands - iteration adapter for range-for loops.
+  iterator_range<IterTy> arg_operands() const {
+    return iterator_range<User::const_op_iterator>(arg_begin(), arg_eng());
+  }
+
   /// getType - Return the type of the instruction that generated this call site
   ///
   Type *getType() const { return (*this)->getType(); }

Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
+++ llvm/trunk/include/llvm/IR/Intrinsics.td Thu Mar  5 12:26:34 2015
@@ -261,10 +261,10 @@ def int_gcwrite : Intrinsic<[],
 //
 def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
 def int_frameaddress  : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
-def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
+def int_frameescape : Intrinsic<[], [llvm_vararg_ty]>;
 def int_framerecover : Intrinsic<[llvm_ptr_ty],
-                                             [llvm_ptr_ty, llvm_ptr_ty],
-                                             [IntrNoMem]>;
+                                 [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty],
+                                 [IntrNoMem]>;
 def int_read_register  : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
                                    [IntrNoMem], "llvm.read_register">;
 def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty],

Modified: llvm/trunk/include/llvm/MC/MCContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCContext.h?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCContext.h (original)
+++ llvm/trunk/include/llvm/MC/MCContext.h Thu Mar  5 12:26:34 2015
@@ -238,7 +238,7 @@ namespace llvm {
 
     MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);
 
-    MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName);
+    MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx);
 
     /// LookupSymbol - Get the symbol for \p Name, or null.
     MCSymbol *LookupSymbol(StringRef Name) const;

Modified: llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp (original)
+++ llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp Thu Mar  5 12:26:34 2015
@@ -810,17 +810,6 @@ void PEI::replaceFrameIndices(MachineBas
         continue;
       }
 
-      // Frame allocations are target independent. Simply swap the index with
-      // the offset.
-      if (MI->getOpcode() == TargetOpcode::FRAME_ALLOC) {
-        assert(TFI->hasFP(Fn) && "frame alloc requires FP");
-        MachineOperand &FI = MI->getOperand(i);
-        unsigned Reg;
-        int FrameOffset = TFI->getFrameIndexReference(Fn, FI.getIndex(), Reg);
-        FI.ChangeToImmediate(FrameOffset);
-        continue;
-      }
-
       // Some instructions (e.g. inline asm instructions) can have
       // multiple frame indices and/or cause eliminateFrameIndex
       // to insert more than one instruction. We need the register

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Thu Mar  5 12:26:34 2015
@@ -5618,45 +5618,47 @@ SelectionDAGBuilder::visitIntrinsicCall(
   case Intrinsic::instrprof_increment:
     llvm_unreachable("instrprof failed to lower an increment");
 
-  case Intrinsic::frameallocate: {
+  case Intrinsic::frameescape: {
     MachineFunction &MF = DAG.getMachineFunction();
     const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo();
 
-    // Do the allocation and map it as a normal value.
-    // FIXME: Maybe we should add this to the alloca map so that we don't have
-    // to register allocate it?
-    uint64_t Size = cast<ConstantInt>(I.getArgOperand(0))->getZExtValue();
-    int Alloc = MF.getFrameInfo()->CreateFrameAllocation(Size);
-    MVT PtrVT = TLI.getPointerTy(0);
-    SDValue FIVal = DAG.getFrameIndex(Alloc, PtrVT);
-    setValue(&I, FIVal);
-
-    // Directly emit a FRAME_ALLOC machine instr. Label assignment emission is
-    // the same on all targets.
-    MCSymbol *FrameAllocSym =
-        MF.getMMI().getContext().getOrCreateFrameAllocSymbol(MF.getName());
-    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, dl,
-            TII->get(TargetOpcode::FRAME_ALLOC))
-        .addSym(FrameAllocSym)
-        .addFrameIndex(Alloc);
+    // Directly emit some FRAME_ALLOC machine instrs. Label assignment emission
+    // is the same on all targets.
+    for (unsigned Idx = 0, E = I.getNumArgOperands(); Idx < E; ++Idx) {
+      AllocaInst *Slot =
+          cast<AllocaInst>(I.getArgOperand(Idx)->stripPointerCasts());
+      assert(FuncInfo.StaticAllocaMap.count(Slot) &&
+             "can only escape static allocas");
+      int FI = FuncInfo.StaticAllocaMap[Slot];
+      MCSymbol *FrameAllocSym =
+          MF.getMMI().getContext().getOrCreateFrameAllocSymbol(MF.getName(),
+                                                               Idx);
+      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, dl,
+              TII->get(TargetOpcode::FRAME_ALLOC))
+          .addSym(FrameAllocSym)
+          .addFrameIndex(FI);
+    }
 
     return nullptr;
   }
 
   case Intrinsic::framerecover: {
-    // i8* @llvm.framerecover(i8* %fn, i8* %fp)
+    // i8* @llvm.framerecover(i8* %fn, i8* %fp, i32 %idx)
     MachineFunction &MF = DAG.getMachineFunction();
     MVT PtrVT = TLI.getPointerTy(0);
 
     // Get the symbol that defines the frame offset.
-    Function *Fn = cast<Function>(I.getArgOperand(0)->stripPointerCasts());
+    auto *Fn = cast<Function>(I.getArgOperand(0)->stripPointerCasts());
+    auto *Idx = cast<ConstantInt>(I.getArgOperand(2));
+    unsigned IdxVal = unsigned(Idx->getLimitedValue(INT_MAX));
     MCSymbol *FrameAllocSym =
-        MF.getMMI().getContext().getOrCreateFrameAllocSymbol(Fn->getName());
+        MF.getMMI().getContext().getOrCreateFrameAllocSymbol(Fn->getName(),
+                                                             IdxVal);
 
     // Create a TargetExternalSymbol for the label to avoid any target lowering
     // that would make this PC relative.
     StringRef Name = FrameAllocSym->getName();
-    assert(Name.size() == strlen(Name.data()) && "not null terminated");
+    assert(Name.data()[Name.size()] == '\0' && "not null terminated");
     SDValue OffsetSym = DAG.getTargetExternalSymbol(Name.data(), PtrVT);
     SDValue OffsetVal =
         DAG.getNode(ISD::FRAME_ALLOC_RECOVER, sdl, PtrVT, OffsetSym);

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Thu Mar  5 12:26:34 2015
@@ -36,17 +36,12 @@ using namespace llvm::PatternMatch;
 
 namespace {
 
-struct HandlerAllocas {
-  TinyPtrVector<AllocaInst *> Allocas;
-  int ParentFrameAllocationIndex;
-};
-
 // This map is used to model frame variable usage during outlining, to
 // construct a structure type to hold the frame variables in a frame
 // allocation block, and to remap the frame variable allocas (including
 // spill locations as needed) to GEPs that get the variable from the
 // frame allocation structure.
-typedef MapVector<Value *, HandlerAllocas> FrameVarInfoMap;
+typedef MapVector<Value *, TinyPtrVector<AllocaInst *>> FrameVarInfoMap;
 
 class WinEHPrepare : public FunctionPass {
   std::unique_ptr<FunctionPass> DwarfPrepare;
@@ -73,7 +68,7 @@ private:
                             SmallVectorImpl<LandingPadInst *> &LPads);
   bool outlineHandler(HandlerType CatchOrCleanup, Function *SrcFn,
                       Constant *SelectorType, LandingPadInst *LPad,
-                      CallInst *&EHAlloc, FrameVarInfoMap &VarInfo);
+                      FrameVarInfoMap &VarInfo);
 };
 
 class WinEHFrameVariableMaterializer : public ValueMaterializer {
@@ -236,7 +231,6 @@ bool WinEHPrepare::prepareCPPEHHandlers(
   // outlined catch and cleanup handlers.  They will be populated as the
   // handlers are outlined.
   FrameVarInfoMap FrameVarInfo;
-  SmallVector<CallInst *, 4> HandlerAllocs;
 
   bool HandlersOutlined = false;
 
@@ -263,15 +257,10 @@ bool WinEHPrepare::prepareCPPEHHandlers(
       if (LPad->isCatch(Idx)) {
         // Create a new instance of the handler data structure in the
         // HandlerData vector.
-        CallInst *EHAlloc = nullptr;
         bool Outlined = outlineHandler(Catch, &F, LPad->getClause(Idx), LPad,
-                                       EHAlloc, FrameVarInfo);
+                                       FrameVarInfo);
         if (Outlined) {
           HandlersOutlined = true;
-          // These values must be resolved after all handlers have been
-          // outlined.
-          if (EHAlloc)
-            HandlerAllocs.push_back(EHAlloc);
         }
       } // End if (isCatch)
     }   // End for each clause
@@ -283,14 +272,10 @@ bool WinEHPrepare::prepareCPPEHHandlers(
     //        multiple landing pads.  Those cases will be supported later
     //        when landing pad block analysis is added.
     if (LPad->isCleanup()) {
-      CallInst *EHAlloc = nullptr;
       bool Outlined =
-          outlineHandler(Cleanup, &F, nullptr, LPad, EHAlloc, FrameVarInfo);
+          outlineHandler(Cleanup, &F, nullptr, LPad, FrameVarInfo);
       if (Outlined) {
         HandlersOutlined = true;
-        // This value must be resolved after all handlers have been outlined.
-        if (EHAlloc)
-          HandlerAllocs.push_back(EHAlloc);
       }
     }
   } // End for each landingpad
@@ -306,103 +291,27 @@ bool WinEHPrepare::prepareCPPEHHandlers(
   //        that looks for allocas with no uses in the parent function.
   //        That will only happen after the pruning is implemented.
 
-  // Remap the frame variables.
-  SmallVector<Type *, 2> StructTys;
-  StructTys.push_back(Type::getInt32Ty(F.getContext()));   // EH state
-  StructTys.push_back(Type::getInt8PtrTy(F.getContext())); // EH object
-
-  // Start the index at two since we always have the above fields at 0 and 1.
-  int Idx = 2;
-
-  // FIXME: Sort the FrameVarInfo vector by the ParentAlloca size and alignment
-  //        and add padding as necessary to provide the proper alignment.
-
-  // Map the alloca instructions to the corresponding index in the
-  // frame allocation structure.  If any alloca is used only in a single
-  // handler and is not used in the parent frame after outlining, it will
-  // be assigned an index of -1, meaning the handler can keep its
-  // "temporary" alloca and the original alloca can be erased from the
-  // parent function.  If we later encounter this alloca in a second
-  // handler, we will assign it a place in the frame allocation structure
-  // at that time.  Since the instruction replacement doesn't happen until
-  // all the entries in the HandlerData have been processed this isn't a
-  // problem.
-  for (auto &VarInfoEntry : FrameVarInfo) {
-    Value *ParentVal = VarInfoEntry.first;
-    HandlerAllocas &AllocaInfo = VarInfoEntry.second;
-
-    if (auto *ParentAlloca = dyn_cast<AllocaInst>(ParentVal)) {
-      // If the instruction still has uses in the parent function or if it is
-      // referenced by more than one handler, add it to the frame allocation
-      // structure.
-      if (ParentAlloca->getNumUses() != 0 || AllocaInfo.Allocas.size() > 1) {
-        Type *VarTy = ParentAlloca->getAllocatedType();
-        StructTys.push_back(VarTy);
-        AllocaInfo.ParentFrameAllocationIndex = Idx++;
-      } else {
-        // If the variable is not used in the parent frame and it is only used
-        // in one handler, the alloca can be removed from the parent frame
-        // and the handler will keep its "temporary" alloca to define the value.
-        // An element index of -1 is used to indicate this condition.
-        AllocaInfo.ParentFrameAllocationIndex = -1;
-      }
-    } else {
-      // FIXME: Sink non-alloca values into the handler if they have no other
-      //        uses in the parent function after outlining and are only used in
-      //        one handler.
-      Type *VarTy = ParentVal->getType();
-      StructTys.push_back(VarTy);
-      AllocaInfo.ParentFrameAllocationIndex = Idx++;
-    }
-  }
-
-  // Having filled the StructTys vector and assigned an index to each element,
-  // we can now create the structure.
-  StructType *EHDataStructTy = StructType::create(
-      F.getContext(), StructTys, "struct." + F.getName().str() + ".ehdata");
-  IRBuilder<> Builder(F.getParent()->getContext());
-
-  // Create a frame allocation.
   Module *M = F.getParent();
   LLVMContext &Context = M->getContext();
   BasicBlock *Entry = &F.getEntryBlock();
+  IRBuilder<> Builder(F.getParent()->getContext());
   Builder.SetInsertPoint(Entry->getFirstInsertionPt());
-  Function *FrameAllocFn =
-      Intrinsic::getDeclaration(M, Intrinsic::frameallocate);
-  uint64_t EHAllocSize = M->getDataLayout().getTypeAllocSize(EHDataStructTy);
-  Value *FrameAllocArgs[] = {
-      ConstantInt::get(Type::getInt32Ty(Context), EHAllocSize)};
-  CallInst *FrameAlloc =
-      Builder.CreateCall(FrameAllocFn, FrameAllocArgs, "frame.alloc");
-
-  Value *FrameEHData = Builder.CreateBitCast(
-      FrameAlloc, EHDataStructTy->getPointerTo(), "eh.data");
-
-  // Now visit each handler that is using the structure and bitcast its EHAlloc
-  // value to be a pointer to the frame alloc structure.
-  DenseMap<Function *, Value *> EHDataMap;
-  for (CallInst *EHAlloc : HandlerAllocs) {
-    // The EHAlloc has no uses at this time, so we need to just insert the
-    // cast before the next instruction. There is always a next instruction.
-    BasicBlock::iterator II = EHAlloc;
-    ++II;
-    Builder.SetInsertPoint(cast<Instruction>(II));
-    Value *EHData = Builder.CreateBitCast(
-        EHAlloc, EHDataStructTy->getPointerTo(), "eh.data");
-    EHDataMap[EHAlloc->getParent()->getParent()] = EHData;
-  }
+
+  Function *FrameEscapeFn =
+      Intrinsic::getDeclaration(M, Intrinsic::frameescape);
+  Function *RecoverFrameFn =
+      Intrinsic::getDeclaration(M, Intrinsic::framerecover);
+  Type *Int8PtrType = Type::getInt8PtrTy(Context);
+  Type *Int32Type = Type::getInt32Ty(Context);
 
   // Finally, replace all of the temporary allocas for frame variables used in
-  // the outlined handlers and the original frame allocas with GEP instructions
-  // that get the equivalent pointer from the frame allocation struct.
-  Instruction *FrameEHDataInst = cast<Instruction>(FrameEHData);
-  BasicBlock::iterator II = FrameEHDataInst;
-  ++II;
+  // the outlined handlers with calls to llvm.framerecover.
+  BasicBlock::iterator II = Entry->getFirstInsertionPt();
   Instruction *AllocaInsertPt = II;
+  SmallVector<Value *, 8> AllocasToEscape;
   for (auto &VarInfoEntry : FrameVarInfo) {
     Value *ParentVal = VarInfoEntry.first;
-    HandlerAllocas &AllocaInfo = VarInfoEntry.second;
-    int Idx = AllocaInfo.ParentFrameAllocationIndex;
+    TinyPtrVector<AllocaInst *> &Allocas = VarInfoEntry.second;
 
     // If the mapped value isn't already an alloca, we need to spill it if it
     // is a computed value or copy it if it is an argument.
@@ -430,48 +339,51 @@ bool WinEHPrepare::prepareCPPEHHandlers(
       }
     }
 
-    // If we have an index of -1 for this instruction, it means it isn't used
-    // outside of this handler.  In that case, we just keep the "temporary"
-    // alloca in the handler and erase the original alloca from the parent.
-    if (Idx == -1) {
+    // If the parent alloca is no longer used and only one of the handlers used
+    // it, erase the parent and leave the copy in the outlined handler.
+    if (ParentAlloca->getNumUses() == 0 && Allocas.size() == 1) {
       ParentAlloca->eraseFromParent();
-    } else {
-      // Otherwise, we replace the parent alloca and all outlined allocas
-      // which map to it with GEP instructions.
-
-      // First replace the original alloca.
-      Builder.SetInsertPoint(ParentAlloca);
-      Builder.SetCurrentDebugLocation(ParentAlloca->getDebugLoc());
-      Value *ElementPtr =
-          Builder.CreateConstInBoundsGEP2_32(FrameEHData, 0, Idx);
-      ParentAlloca->replaceAllUsesWith(ElementPtr);
-      ParentAlloca->removeFromParent();
-      ElementPtr->takeName(ParentAlloca);
-      if (ParentAlloca == AllocaInsertPt)
-        AllocaInsertPt = dyn_cast<Instruction>(ElementPtr);
-      delete ParentAlloca;
-
-      // Next replace all outlined allocas that are mapped to it.
-      for (AllocaInst *TempAlloca : AllocaInfo.Allocas) {
-        Value *EHData = EHDataMap[TempAlloca->getParent()->getParent()];
-        // FIXME: Sink this GEP into the blocks where it is used.
-        Builder.SetInsertPoint(TempAlloca);
-        Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
-        ElementPtr = Builder.CreateConstInBoundsGEP2_32(EHData, 0, Idx);
-        TempAlloca->replaceAllUsesWith(ElementPtr);
-        TempAlloca->removeFromParent();
-        ElementPtr->takeName(TempAlloca);
-        delete TempAlloca;
+      continue;
+    }
+
+    // Add this alloca to the list of things to escape.
+    AllocasToEscape.push_back(ParentAlloca);
+
+    // Next replace all outlined allocas that are mapped to it.
+    for (AllocaInst *TempAlloca : Allocas) {
+      Function *HandlerFn = TempAlloca->getParent()->getParent();
+      // FIXME: Sink this GEP into the blocks where it is used.
+      Builder.SetInsertPoint(TempAlloca);
+      Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
+      Value *RecoverArgs[] = {
+          Builder.CreateBitCast(&F, Int8PtrType, ""),
+          &(HandlerFn->getArgumentList().back()),
+          llvm::ConstantInt::get(Int32Type, AllocasToEscape.size() - 1)};
+      Value *RecoveredAlloca =
+          Builder.CreateCall(RecoverFrameFn, RecoverArgs);
+      // Add a pointer bitcast if the alloca wasn't an i8.
+      if (RecoveredAlloca->getType() != TempAlloca->getType()) {
+        RecoveredAlloca->setName(Twine(TempAlloca->getName()) + ".i8");
+        RecoveredAlloca =
+            Builder.CreateBitCast(RecoveredAlloca, TempAlloca->getType());
       }
-    } // end else of if (Idx == -1)
+      TempAlloca->replaceAllUsesWith(RecoveredAlloca);
+      TempAlloca->removeFromParent();
+      RecoveredAlloca->takeName(TempAlloca);
+      delete TempAlloca;
+    }
   }   // End for each FrameVarInfo entry.
 
+  // Insert 'call void (...)* @llvm.frameescape(...)' at the end of the entry
+  // block.
+  Builder.SetInsertPoint(&F.getEntryBlock().back());
+  Builder.CreateCall(FrameEscapeFn, AllocasToEscape);
+
   return HandlersOutlined;
 }
 
 bool WinEHPrepare::outlineHandler(HandlerType CatchOrCleanup, Function *SrcFn,
                                   Constant *SelectorType, LandingPadInst *LPad,
-                                  CallInst *&EHAlloc,
                                   FrameVarInfoMap &VarInfo) {
   Module *M = SrcFn->getParent();
   LLVMContext &Context = M->getContext();
@@ -500,23 +412,6 @@ bool WinEHPrepare::outlineHandler(Handle
   Builder.SetInsertPoint(Entry);
   Builder.SetCurrentDebugLocation(LPad->getDebugLoc());
 
-  // The outlined handler will be called with the parent's frame pointer as
-  // its second argument. To enable the handler to access variables from
-  // the parent frame, we use that pointer to get locate a special block
-  // of memory that was allocated using llvm.eh.allocateframe for this
-  // purpose.  During the outlining process we will determine which frame
-  // variables are used in handlers and create a structure that maps these
-  // variables into the frame allocation block.
-  //
-  // The frame allocation block also contains an exception state variable
-  // used by the runtime and a pointer to the exception object pointer
-  // which will be filled in by the runtime for use in the handler.
-  Function *RecoverFrameFn =
-      Intrinsic::getDeclaration(M, Intrinsic::framerecover);
-  Value *RecoverArgs[] = {Builder.CreateBitCast(SrcFn, Int8PtrType, ""),
-                          &(Handler->getArgumentList().back())};
-  EHAlloc = Builder.CreateCall(RecoverFrameFn, RecoverArgs, "eh.alloc");
-
   std::unique_ptr<WinEHCloningDirectorBase> Director;
 
   if (CatchOrCleanup == Catch) {
@@ -765,7 +660,7 @@ Value *WinEHFrameVariableMaterializer::m
   if (auto *AV = dyn_cast<AllocaInst>(V)) {
     AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone());
     Builder.Insert(NewAlloca, AV->getName());
-    FrameVarInfo[AV].Allocas.push_back(NewAlloca);
+    FrameVarInfo[AV].push_back(NewAlloca);
     return NewAlloca;
   }
 
@@ -776,7 +671,7 @@ Value *WinEHFrameVariableMaterializer::m
   if (isa<Instruction>(V) || isa<Argument>(V)) {
     AllocaInst *NewAlloca =
         Builder.CreateAlloca(V->getType(), nullptr, "eh.temp.alloca");
-    FrameVarInfo[V].Allocas.push_back(NewAlloca);
+    FrameVarInfo[V].push_back(NewAlloca);
     LoadInst *NewLoad = Builder.CreateLoad(NewAlloca, V->getName() + ".reload");
     return NewLoad;
   }

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Thu Mar  5 12:26:34 2015
@@ -198,14 +198,18 @@ class Verifier : public InstVisitor<Veri
   /// personality function.
   const Value *PersonalityFn;
 
-  /// \brief Whether we've seen a call to @llvm.frameallocate in this function
+  /// \brief Whether we've seen a call to @llvm.frameescape in this function
   /// already.
-  bool SawFrameAllocate;
+  bool SawFrameEscape;
+
+  /// Stores the count of how many objects were passed to llvm.frameescape for a
+  /// given function and the largest index passed to llvm.framerecover.
+  DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
 
 public:
   explicit Verifier(raw_ostream &OS = dbgs())
       : VerifierSupport(OS), Context(nullptr), PersonalityFn(nullptr),
-        SawFrameAllocate(false) {}
+        SawFrameEscape(false) {}
 
   bool verify(const Function &F) {
     M = F.getParent();
@@ -240,7 +244,7 @@ public:
     visit(const_cast<Function &>(F));
     InstsInThisBlock.clear();
     PersonalityFn = nullptr;
-    SawFrameAllocate = false;
+    SawFrameEscape = false;
 
     return !Broken;
   }
@@ -259,6 +263,10 @@ public:
         visitFunction(*I);
     }
 
+    // Now that we've visited every function, verify that we never asked to
+    // recover a frame index that wasn't escaped.
+    verifyFrameRecoverIndices();
+
     for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
          I != E; ++I)
       visitGlobalVariable(*I);
@@ -373,6 +381,7 @@ private:
 
   void VerifyConstantExprBitcastType(const ConstantExpr *CE);
   void VerifyStatepoint(ImmutableCallSite CS);
+  void verifyFrameRecoverIndices();
 };
 class DebugInfoVerifier : public VerifierSupport {
 public:
@@ -1266,6 +1275,20 @@ void Verifier::VerifyStatepoint(Immutabl
   // about.  See example statepoint.ll in the verifier subdirectory
 }
 
+void Verifier::verifyFrameRecoverIndices() {
+  llvm::errs() << "verifyFrameRecoverIndices\n";
+  for (auto &Counts : FrameEscapeInfo) {
+    Function *F = Counts.first;
+    unsigned EscapedObjectCount = Counts.second.first;
+    unsigned MaxRecoveredIndex = Counts.second.second;
+    Assert1(MaxRecoveredIndex <= EscapedObjectCount,
+            "all indices passed to llvm.framerecover must be less than the "
+            "number of arguments passed ot llvm.frameescape in the parent "
+            "function",
+            F);
+  }
+}
+
 // visitFunction - Verify that a function is ok.
 //
 void Verifier::visitFunction(const Function &F) {
@@ -2859,15 +2882,19 @@ void Verifier::visitIntrinsicFunctionCal
             "llvm.invariant.end parameter #2 must be a constant integer", &CI);
     break;
 
-  case Intrinsic::frameallocate: {
+  case Intrinsic::frameescape: {
     BasicBlock *BB = CI.getParent();
     Assert1(BB == &BB->getParent()->front(),
-            "llvm.frameallocate used outside of entry block", &CI);
-    Assert1(!SawFrameAllocate,
-            "multiple calls to llvm.frameallocate in one function", &CI);
-    SawFrameAllocate = true;
-    Assert1(isa<ConstantInt>(CI.getArgOperand(0)),
-            "llvm.frameallocate argument must be constant integer size", &CI);
+            "llvm.frameescape used outside of entry block", &CI);
+    Assert1(!SawFrameEscape,
+            "multiple calls to llvm.frameescape in one function", &CI);
+    for (Value *Arg : CI.arg_operands()) {
+      auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts());
+      Assert1(AI && AI->isStaticAlloca(),
+              "llvm.frameescape only accepts static allocas", &CI);
+    }
+    FrameEscapeInfo[BB->getParent()].first = CI.getNumArgOperands();
+    SawFrameEscape = true;
     break;
   }
   case Intrinsic::framerecover: {
@@ -2875,6 +2902,12 @@ void Verifier::visitIntrinsicFunctionCal
     Function *Fn = dyn_cast<Function>(FnArg);
     Assert1(Fn && !Fn->isDeclaration(), "llvm.framerecover first "
             "argument must be function defined in this module", &CI);
+    auto *IdxArg = dyn_cast<ConstantInt>(CI.getArgOperand(2));
+    Assert1(IdxArg, "idx argument of llvm.framerecover must be a constant int",
+            &CI);
+    auto &Entry = FrameEscapeInfo[Fn];
+    Entry.second = unsigned(
+        std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1));
     break;
   }
 

Modified: llvm/trunk/lib/MC/MCContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCContext.cpp (original)
+++ llvm/trunk/lib/MC/MCContext.cpp Thu Mar  5 12:26:34 2015
@@ -131,9 +131,10 @@ MCSymbol *MCContext::getOrCreateSectionS
   return Sym;
 }
 
-MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName) {
-  return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
-                           "frameallocation_" + FuncName);
+MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName,
+                                                 unsigned Idx) {
+  return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + FuncName +
+                           "$frame_escape_" + Twine(Idx));
 }
 
 MCSymbol *MCContext::CreateSymbol(StringRef Name) {

Modified: llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp Thu Mar  5 12:26:34 2015
@@ -496,6 +496,25 @@ X86RegisterInfo::eliminateFrameIndex(Mac
   else
     BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr);
 
+  // FRAME_ALLOC uses a single offset, with no register. It only works in the
+  // simple FP case, and doesn't work with stack realignment. On 32-bit, the
+  // offset is from the traditional base pointer location.  On 64-bit, the
+  // offset is from the SP at the end of the prologue, not the FP location. This
+  // matches the behavior of llvm.frameaddress.
+  if (Opc == TargetOpcode::FRAME_ALLOC) {
+    assert(TFI->hasFP(MF) && "frame alloc requires FP");
+    MachineOperand &FI = MI.getOperand(FIOperandNum);
+    const MachineFrameInfo *MFI = MF.getFrameInfo();
+    int Offset = MFI->getObjectOffset(FrameIndex) - TFI->getOffsetOfLocalArea();
+    bool IsWinEH = MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
+    if (IsWinEH)
+      Offset += MFI->getStackSize();
+    else
+      Offset += SlotSize;
+    FI.ChangeToImmediate(Offset);
+    return;
+  }
+
   // For LEA64_32r when BasePtr is 32-bits (X32) we can use full-size 64-bit
   // register as source operand, semantic is the same and destination is
   // 32-bits. It saves one byte per lea in code since 0x67 prefix is avoided.

Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-catch-all.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-catch-all.ll?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/cppeh-catch-all.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/cppeh-catch-all.ll Thu Mar  5 12:26:34 2015
@@ -54,8 +54,6 @@ try.cont:
 
 ; CHECK: define internal i8* @_Z4testv.catch(i8*, i8*) {
 ; CHECK: entry:
-; CHECK:   %eh.alloc = call i8* @llvm.framerecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1)
-; CHECK:   %eh.data = bitcast i8* %eh.alloc to %struct._Z4testv.ehdata*
 ; CHECK:   call void @_Z16handle_exceptionv()
 ; CHECK:   ret i8* blockaddress(@_Z4testv, %try.cont)
 ; CHECK: }

Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-catch-scalar.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-catch-scalar.ll?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/cppeh-catch-scalar.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/cppeh-catch-scalar.ll Thu Mar  5 12:26:34 2015
@@ -18,20 +18,17 @@
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-windows-msvc"
 
-; This is the structure that will get created for the frame allocation.
-; CHECK: %struct._Z4testv.ehdata = type { i32, i8*, i32 }
-
 @_ZTIi = external constant i8*
 
 ; The function entry will be rewritten like this.
 ; CHECK: define void @_Z4testv() #0 {
 ; CHECK: entry:
-; CHECK:   %frame.alloc = call i8* @llvm.frameallocate(i32 24)
-; CHECK:   %eh.data = bitcast i8* %frame.alloc to %struct._Z4testv.ehdata*
 ; CHECK:   %exn.slot = alloca i8*
 ; CHECK:   %ehselector.slot = alloca i32
-; CHECK-NOT:  %i = alloca i32, align 4
-; CHECK:  %i = getelementptr inbounds %struct._Z4testv.ehdata, %struct._Z4testv.ehdata* %eh.data, i32 0, i32 2
+; CHECK:   %i = alloca i32, align 4
+; CHECK:   call void (...)* @llvm.frameescape(i32* %i)
+; CHECK:   invoke void @_Z9may_throwv()
+; CHECK:           to label %invoke.cont unwind label %lpad
 
 ; Function Attrs: uwtable
 define void @_Z4testv() #0 {
@@ -85,9 +82,8 @@ eh.resume:
 
 ; CHECK: define internal i8* @_Z4testv.catch(i8*, i8*) {
 ; CHECK: entry:
-; CHECK:   %eh.alloc = call i8* @llvm.framerecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1)
-; CHECK:   %eh.data = bitcast i8* %eh.alloc to %struct._Z4testv.ehdata*
-; CHECK:   %i = getelementptr inbounds %struct._Z4testv.ehdata, %struct._Z4testv.ehdata* %eh.data, i32 0, i32 2
+; CHECK:   %i.i81 = call i8* @llvm.framerecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 0)
+; CHECK:   %i = bitcast i8* %i.i81 to i32*
 ; CHECK:   %tmp7 = load i32, i32* %i, align 4
 ; CHECK:   call void @_Z10handle_inti(i32 %tmp7)
 ; CHECK:   ret i8* blockaddress(@_Z4testv, %try.cont)

Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-frame-vars.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-frame-vars.ll?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/cppeh-frame-vars.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/cppeh-frame-vars.ll Thu Mar  5 12:26:34 2015
@@ -41,9 +41,6 @@ target triple = "x86_64-pc-windows-msvc"
 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
 %struct.SomeData = type { i32, i32 }
 
-; This structure should be declared for the frame allocation block.
-; CHECK: %"struct.\01?test@@YAXXZ.ehdata" = type { i32, i8*, i32, i32, [10 x i32], i32, %struct.SomeData }
-
 $"\01??_R0H at 8" = comdat any
 
 @"\01??_7type_info@@6B@" = external constant i8*
@@ -52,19 +49,19 @@ $"\01??_R0H at 8" = comdat any
 ; The function entry should be rewritten like this.
 ; CHECK: define void @"\01?test@@YAXXZ"() #0 {
 ; CHECK: entry:
-; CHECK:   %frame.alloc = call i8* @llvm.frameallocate(i32 80)
-; CHECK:   %eh.data = bitcast i8* %frame.alloc to %"struct.\01?test@@YAXXZ.ehdata"*
-; CHECK-NOT:  %NumExceptions = alloca i32, align 4
-; CHECK:   %NumExceptions = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 3
-; CHECK-NOT:  %ExceptionVal = alloca [10 x i32], align 16
-; CHECK:   %ExceptionVal = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 4
-; CHECK-NOT:  %Data = alloca %struct.SomeData, align 4
-; CHECK:   %Data = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 6
-; CHECK:   %i = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 5
+; CHECK:   %NumExceptions = alloca i32, align 4
+; CHECK:   %ExceptionVal = alloca [10 x i32], align 16
+; CHECK:   %Data = alloca %struct.SomeData, align 4
+; CHECK:   %i = alloca i32, align 4
 ; CHECK:   %exn.slot = alloca i8*
 ; CHECK:   %ehselector.slot = alloca i32
-; CHECK-NOT:  %e = alloca i32, align 4
-; CHECK:   %e = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 2
+; CHECK:   %e = alloca i32, align 4
+; CHECK:   store i32 0, i32* %NumExceptions, align 4
+; CHECK:   %tmp = bitcast %struct.SomeData* %Data to i8*
+; CHECK:   call void @llvm.memset(i8* %tmp, i8 0, i64 8, i32 4, i1 false)
+; CHECK:   store i32 0, i32* %i, align 4
+; CHECK:   call void (...)* @llvm.frameescape(i32* %e, i32* %NumExceptions, [10 x i32]* %ExceptionVal, i32* %i, %struct.SomeData* %Data)
+; CHECK:   br label %for.cond
 
 ; Function Attrs: uwtable
 define void @"\01?test@@YAXXZ"() #0 {
@@ -179,13 +176,16 @@ eh.resume:
 ; The following catch handler should be outlined.
 ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) {
 ; CHECK: entry:
-; CHECK:   %eh.alloc = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1)
-; CHECK:   %eh.data = bitcast i8* %eh.alloc to %"struct.\01?test@@YAXXZ.ehdata"*
-; CHECK:   %e = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 2
-; CHECK:   %NumExceptions = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 3
-; CHECK:   %ExceptionVal = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 4
-; CHECK:   %i = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 5
-; CHECK:   %Data = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 6
+; CHECK:   %e.i81 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0)
+; CHECK:   %e = bitcast i8* %e.i81 to i32*
+; CHECK:   %NumExceptions.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1)
+; CHECK:   %NumExceptions = bitcast i8* %NumExceptions.i8 to i32*
+; CHECK:   %ExceptionVal.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2)
+; CHECK:   %ExceptionVal = bitcast i8* %ExceptionVal.i8 to [10 x i32]*
+; CHECK:   %i.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 3)
+; CHECK:   %i = bitcast i8* %i.i8 to i32*
+; CHECK:   %Data.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 4)
+; CHECK:   %Data = bitcast i8* %Data.i8 to %struct.SomeData*
 ; CHECK:   %tmp11 = load i32, i32* %e, align 4
 ; CHECK:   %tmp12 = load i32, i32* %NumExceptions, align 4
 ; CHECK:   %idxprom = sext i32 %tmp12 to i64

Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-inalloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-inalloca.ll?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/cppeh-inalloca.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/cppeh-inalloca.ll Thu Mar  5 12:26:34 2015
@@ -38,18 +38,15 @@ $"\01??_R0H at 8" = comdat any
 ; The function entry should be rewritten like this.
 ; CHECK: define i32 @"\01?test@@YAHUA@@@Z"(<{ %struct.A }>* inalloca) #0 {
 ; CHECK: entry:
-; CHECK:   %frame.alloc = call i8* @llvm.frameallocate(i32 24)
-; CHECK:   %eh.data = bitcast i8* %frame.alloc to %"struct.\01?test@@YAHUA@@@Z.ehdata"*
-; CHECK:   %.tmp.reg2mem = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 3
+; CHECK:   %.tmp.reg2mem = alloca <{ %struct.A }>*
 ; CHECK:   %.tmp = select i1 true, <{ %struct.A }>* %0, <{ %struct.A }>* undef
 ; CHECK:   store <{ %struct.A }>* %.tmp, <{ %struct.A }>** %.tmp.reg2mem
-; CHECK-NOT:  %retval = alloca i32, align 4
-; CHECK:   %retval = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 4
+; CHECK:   %retval = alloca i32, align 4
 ; CHECK:   %exn.slot = alloca i8*
 ; CHECK:   %ehselector.slot = alloca i32
-; CHECK-NOT:  %e = alloca i32, align 4
-; CHECK:   %e = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 2
-; CHECK:   %cleanup.dest.slot = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 5
+; CHECK:   %e = alloca i32, align 4
+; CHECK:   %cleanup.dest.slot = alloca i32
+; CHECK:   call void (...)* @llvm.frameescape(i32* %e, <{ %struct.A }>** %.tmp.reg2mem, i32* %retval, i32* %cleanup.dest.slot)
 ; CHECK:   invoke void @"\01?may_throw@@YAXXZ"()
 ; CHECK:           to label %invoke.cont unwind label %lpad
 
@@ -132,13 +129,16 @@ eh.resume:
 ; The following catch handler should be outlined.
 ; CHECK: define internal i8* @"\01?test@@YAHUA@@@Z.catch"(i8*, i8*) {
 ; CHECK: entry:
-; CHECK:   %eh.alloc = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1)
-; CHECK:   %eh.data = bitcast i8* %eh.alloc to %"struct.\01?test@@YAHUA@@@Z.ehdata"*
-; CHECK:   %e = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 2
-; CHECK:   %eh.temp.alloca = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 3
+; CHECK:   %e.i81 = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 0)
+; CHECK:   %e = bitcast i8* %e.i81 to i32*
+; CHECK:   %eh.temp.alloca.i8 = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 1)
+; CHECK:   %eh.temp.alloca = bitcast i8* %eh.temp.alloca.i8 to <{ %struct.A }>**
 ; CHECK:   %.reload = load <{ %struct.A }>*, <{ %struct.A }>** %eh.temp.alloca
-; CHECK:   %retval = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 4
-; CHECK:   %cleanup.dest.slot = getelementptr inbounds %"struct.\01?test@@YAHUA@@@Z.ehdata", %"struct.\01?test@@YAHUA@@@Z.ehdata"* %eh.data, i32 0, i32 5
+; CHECK:   %retval.i8 = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 2)
+; CHECK:   %retval = bitcast i8* %retval.i8 to i32*
+; CHECK:   %cleanup.dest.slot.i8 = call i8* @llvm.framerecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 3)
+; CHECK:   %cleanup.dest.slot = bitcast i8* %cleanup.dest.slot.i8 to i32*
+; CHECK:   %e.i8 = bitcast i32* %e to i8*
 ; CHECK:   %a = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %.reload, i32 0, i32 0
 ; CHECK:   %a1 = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 0
 ; CHECK:   %tmp8 = load i32, i32* %a1, align 4
@@ -149,7 +149,6 @@ eh.resume:
 ; CHECK:   ret i8* blockaddress(@"\01?test@@YAHUA@@@Z", %cleanup)
 ; CHECK: }
 
-
 declare void @"\01?may_throw@@YAXXZ"() #0
 
 declare i32 @__CxxFrameHandler3(...)

Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-min-unwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-min-unwind.ll?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/cppeh-min-unwind.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/cppeh-min-unwind.ll Thu Mar  5 12:26:34 2015
@@ -18,18 +18,16 @@
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-windows-msvc"
 
-; This structure should be created for the frame allocation.
-; CHECK: %struct._Z4testv.ehdata = type { i32, i8*, %class.SomeClass }
-
 %class.SomeClass = type { [28 x i32] }
 
 ; The function entry should be rewritten like this.
 ; CHECK: define void @_Z4testv() #0 {
 ; CHECK: entry:
-; CHECK:   %frame.alloc = call i8* @llvm.frameallocate(i32 128)
-; CHECK:   %eh.data = bitcast i8* %frame.alloc to %struct._Z4testv.ehdata*
-; CHECK-NOT:  %obj = alloca %class.SomeClass, align 4
-; CHECK:   %obj = getelementptr inbounds %struct._Z4testv.ehdata, %struct._Z4testv.ehdata* %eh.data, i32 0, i32 2
+; CHECK:   %obj = alloca %class.SomeClass, align 4
+; CHECK:   call void @_ZN9SomeClassC1Ev(%class.SomeClass* %obj)
+; CHECK:   call void (...)* @llvm.frameescape(%class.SomeClass* %obj)
+; CHECK:   invoke void @_Z9may_throwv()
+; CHECK:           to label %invoke.cont unwind label %lpad
 
 ; Function Attrs: uwtable
 define void @_Z4testv() #0 {
@@ -66,9 +64,8 @@ eh.resume:
 ; This cleanup handler should be outlined.
 ; CHECK: define internal void @_Z4testv.cleanup(i8*, i8*) {
 ; CHECK: entry:
-; CHECK:   %eh.alloc = call i8* @llvm.framerecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1)
-; CHECK:   %eh.data = bitcast i8* %eh.alloc to %struct._Z4testv.ehdata*
-; CHECK:   %obj = getelementptr inbounds %struct._Z4testv.ehdata, %struct._Z4testv.ehdata* %eh.data, i32 0, i32 2
+; CHECK:   %obj.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 0)
+; CHECK:   %obj = bitcast i8* %obj.i8 to %class.SomeClass*
 ; CHECK:   call void @_ZN9SomeClassD1Ev(%class.SomeClass* %obj)
 ; CHECK:   ret void
 ; CHECK: }

Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll?rev=231386&r1=231385&r2=231386&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll Thu Mar  5 12:26:34 2015
@@ -50,32 +50,28 @@ $"\01??_R0H at 8" = comdat any
 @"\01??_7type_info@@6B@" = external constant i8*
 @"\01??_R0H at 8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
 
-; This structure should be declared for the frame allocation block.
-; CHECK: %"struct.\01?test@@YAXXZ.ehdata" = type { i32, i8*, i32, i32, [10 x i32], i32, i32*, i32* }
-
 ; The function entry should be rewritten like this.
 ; CHECK: define void @"\01?test@@YAXXZ"() #0 {
 ; CHECK: entry:
-; CHECK:  %frame.alloc = call i8* @llvm.frameallocate(i32 88)
-; CHECK:  %eh.data = bitcast i8* %frame.alloc to %"struct.\01?test@@YAXXZ.ehdata"*
-; CHECK-NOT:  %ExceptionVal = alloca [10 x i32], align 16
-; CHECK:  %NumExceptions.020.reg2mem = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 3
-; CHECK:  %i.019.reg2mem = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 5
-; CHECK:  %ExceptionVal = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 4
-; CHECK:  %Data = alloca i64, align 8
-; CHECK:  %tmpcast = bitcast i64* %Data to %struct.SomeData*
-; CHECK:  %0 = bitcast [10 x i32]* %ExceptionVal to i8*
-; CHECK:  call void @llvm.lifetime.start(i64 40, i8* %0) #1
-; CHECK:  store i64 0, i64* %Data, align 8
-; CHECK:  %a.reg2mem = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 6
-; CHECK:  %a = bitcast i64* %Data to i32*
-; CHECK:  store i32* %a, i32** %a.reg2mem
-; CHECK:  %b.reg2mem = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 7
-; CHECK:  %b = getelementptr inbounds %struct.SomeData, %struct.SomeData* %tmpcast, i64 0, i32 1
-; CHECK:  store i32* %b, i32** %b.reg2mem
-; CHECK:  store i32 0, i32* %NumExceptions.020.reg2mem
-; CHECK:  store i32 0, i32* %i.019.reg2mem
-; CHECK:  br label %for.body
+; CHECK:   %NumExceptions.020.reg2mem = alloca i32
+; CHECK:   %i.019.reg2mem = alloca i32
+; CHECK:   %e = alloca i32, align 4
+; CHECK:   %ExceptionVal = alloca [10 x i32], align 16
+; CHECK:   %Data = alloca i64, align 8
+; CHECK:   %tmpcast = bitcast i64* %Data to %struct.SomeData*
+; CHECK:   %0 = bitcast [10 x i32]* %ExceptionVal to i8*
+; CHECK:   call void @llvm.lifetime.start(i64 40, i8* %0) #1
+; CHECK:   store i64 0, i64* %Data, align 8
+; CHECK:   %a.reg2mem = alloca i32*
+; CHECK:   %a = bitcast i64* %Data to i32*
+; CHECK:   store i32* %a, i32** %a.reg2mem
+; CHECK:   %b.reg2mem = alloca i32*
+; CHECK:   %b = getelementptr inbounds %struct.SomeData, %struct.SomeData* %tmpcast, i64 0, i32 1
+; CHECK:   store i32* %b, i32** %b.reg2mem
+; CHECK:   store i32 0, i32* %NumExceptions.020.reg2mem
+; CHECK:   store i32 0, i32* %i.019.reg2mem
+; CHECK:   call void (...)* @llvm.frameescape(i32* %e, i32* %NumExceptions.020.reg2mem, [10 x i32]* %ExceptionVal, i32* %i.019.reg2mem, i32** %a.reg2mem, i32** %b.reg2mem)
+; CHECK:   br label %for.body
 
 ; Function Attrs: uwtable
 define void @"\01?test@@YAXXZ"() #0 {
@@ -187,17 +183,21 @@ eh.resume:
 ; The following catch handler should be outlined.
 ; CHECK: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) {
 ; CHECK: entry:
-; CHECK:   %eh.alloc = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1)
-; CHECK:   %eh.data = bitcast i8* %eh.alloc to %"struct.\01?test@@YAXXZ.ehdata"*
-; CHECK:   %e = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 2
-; CHECK:   %eh.temp.alloca = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 3
+; CHECK:   %e.i84 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0)
+; CHECK:   %e = bitcast i8* %e.i84 to i32*
+; CHECK:   %eh.temp.alloca.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1)
+; CHECK:   %eh.temp.alloca = bitcast i8* %eh.temp.alloca.i8 to i32*
 ; CHECK:   %NumExceptions.020.reload = load i32, i32* %eh.temp.alloca
-; CHECK:   %ExceptionVal = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 4
-; CHECK:   %eh.temp.alloca1 = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 5
+; CHECK:   %ExceptionVal.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2)
+; CHECK:   %ExceptionVal = bitcast i8* %ExceptionVal.i8 to [10 x i32]*
+; CHECK:   %eh.temp.alloca1.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 3)
+; CHECK:   %eh.temp.alloca1 = bitcast i8* %eh.temp.alloca1.i8 to i32*
 ; CHECK:   %i.019.reload = load i32, i32* %eh.temp.alloca1
-; CHECK:   %eh.temp.alloca2 = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 6
+; CHECK:   %eh.temp.alloca2.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 4)
+; CHECK:   %eh.temp.alloca2 = bitcast i8* %eh.temp.alloca2.i8 to i32**
 ; CHECK:   %a.reload = load i32*, i32** %eh.temp.alloca2
-; CHECK:   %eh.temp.alloca3 = getelementptr inbounds %"struct.\01?test@@YAXXZ.ehdata", %"struct.\01?test@@YAXXZ.ehdata"* %eh.data, i32 0, i32 7
+; CHECK:   %eh.temp.alloca3.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 5)
+; CHECK:   %eh.temp.alloca3 = bitcast i8* %eh.temp.alloca3.i8 to i32**
 ; CHECK:   %b.reload = load i32*, i32** %eh.temp.alloca3
 ; CHECK:   %e.i8 = bitcast i32* %e to i8*
 ; CHECK:   %tmp8 = load i32, i32* %e, align 4, !tbaa !7

Removed: llvm/trunk/test/CodeGen/X86/frameallocate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/frameallocate.ll?rev=231385&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/frameallocate.ll (original)
+++ llvm/trunk/test/CodeGen/X86/frameallocate.ll (removed)
@@ -1,43 +0,0 @@
-; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
-
-declare i8* @llvm.frameallocate(i32)
-declare i8* @llvm.frameaddress(i32)
-declare i8* @llvm.framerecover(i8*, i8*)
-declare i32 @printf(i8*, ...)
-
- at str = internal constant [10 x i8] c"asdf: %d\0A\00"
-
-define void @print_framealloc_from_fp(i8* %fp) {
-  %alloc = call i8* @llvm.framerecover(i8* bitcast (void(i32*, i32*)* @alloc_func to i8*), i8* %fp)
-  %alloc_i32 = bitcast i8* %alloc to i32*
-  %r = load i32, i32* %alloc_i32
-  call i32 (i8*, ...)* @printf(i8* getelementptr ([10 x i8]* @str, i32 0, i32 0), i32 %r)
-  ret void
-}
-
-; CHECK-LABEL: print_framealloc_from_fp:
-; CHECK: movabsq $.Lframeallocation_alloc_func, %[[offs:[a-z]+]]
-; CHECK: movl (%rcx,%[[offs]]), %edx
-; CHECK: leaq {{.*}}(%rip), %rcx
-; CHECK: callq printf
-; CHECK: retq
-
-define void @alloc_func(i32* %s, i32* %d) {
-  %alloc = call i8* @llvm.frameallocate(i32 16)
-  %alloc_i32 = bitcast i8* %alloc to i32*
-  store i32 42, i32* %alloc_i32
-  %fp = call i8* @llvm.frameaddress(i32 0)
-  call void @print_framealloc_from_fp(i8* %fp)
-  ret void
-}
-
-; CHECK-LABEL: alloc_func:
-; CHECK: subq    $48, %rsp
-; CHECK: .seh_stackalloc 48
-; CHECK: leaq    48(%rsp), %rbp
-; CHECK: .seh_setframe 5, 48
-; CHECK: .Lframeallocation_alloc_func = -[[offs:[0-9]+]]
-; CHECK: movl $42, -[[offs]](%rbp)
-; CHECK: leaq    -48(%rbp), %rcx
-; CHECK: callq print_framealloc_from_fp
-; CHECK: retq

Added: llvm/trunk/test/CodeGen/X86/frameescape.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/frameescape.ll?rev=231386&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/frameescape.ll (added)
+++ llvm/trunk/test/CodeGen/X86/frameescape.ll Thu Mar  5 12:26:34 2015
@@ -0,0 +1,63 @@
+; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
+
+declare void @llvm.frameescape(...)
+declare i8* @llvm.frameaddress(i32)
+declare i8* @llvm.framerecover(i8*, i8*, i32)
+declare i32 @printf(i8*, ...)
+
+ at str = internal constant [10 x i8] c"asdf: %d\0A\00"
+
+define void @print_framealloc_from_fp(i8* %fp) {
+  %a.i8 = call i8* @llvm.framerecover(i8* bitcast (void()* @alloc_func to i8*), i8* %fp, i32 0)
+  %a = bitcast i8* %a.i8 to i32*
+  %a.val = load i32, i32* %a
+  call i32 (i8*, ...)* @printf(i8* getelementptr ([10 x i8]* @str, i32 0, i32 0), i32 %a.val)
+  %b.i8 = call i8* @llvm.framerecover(i8* bitcast (void()* @alloc_func to i8*), i8* %fp, i32 1)
+  %b = bitcast i8* %b.i8 to i32*
+  %b.val = load i32, i32* %b
+  call i32 (i8*, ...)* @printf(i8* getelementptr ([10 x i8]* @str, i32 0, i32 0), i32 %b.val)
+  ret void
+}
+
+; CHECK-LABEL: print_framealloc_from_fp:
+; CHECK: movq %rcx, %[[parent_fp:[a-z]+]]
+; CHECK: movabsq $.Lalloc_func$frame_escape_0, %[[offs:[a-z]+]]
+; CHECK: movl (%[[parent_fp]],%[[offs]]), %edx
+; CHECK: leaq {{.*}}(%rip), %[[str:[a-z]+]]
+; CHECK: movq %[[str]], %rcx
+; CHECK: callq printf
+; CHECK: movabsq $.Lalloc_func$frame_escape_1, %[[offs:[a-z]+]]
+; CHECK: movl (%[[parent_fp]],%[[offs]]), %edx
+; CHECK: movq %[[str]], %rcx
+; CHECK: callq printf
+; CHECK: retq
+
+define void @alloc_func() {
+  %a = alloca i32
+  %b = alloca i32
+  call void (...)* @llvm.frameescape(i32* %a, i32* %b)
+  store i32 42, i32* %a
+  store i32 13, i32* %b
+  %fp = call i8* @llvm.frameaddress(i32 0)
+  call void @print_framealloc_from_fp(i8* %fp)
+  ret void
+}
+
+; CHECK-LABEL: alloc_func:
+; CHECK: subq    $48, %rsp
+; CHECK: .seh_stackalloc 48
+; CHECK: leaq    48(%rsp), %rbp
+; CHECK: .seh_setframe 5, 48
+; CHECK: .Lalloc_func$frame_escape_0 = 44
+; CHECK: .Lalloc_func$frame_escape_1 = 40
+; CHECK: movl $42, -4(%rbp)
+; CHECK: movl $13, -8(%rbp)
+; CHECK: leaq    -48(%rbp), %rcx
+; CHECK: callq print_framealloc_from_fp
+; CHECK: retq
+
+; Helper to make this a complete program so it can be compiled and tested.
+define i32 @main() {
+  call void @alloc_func()
+  ret i32 0
+}

Removed: llvm/trunk/test/Verifier/frameallocate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/frameallocate.ll?rev=231385&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/frameallocate.ll (original)
+++ llvm/trunk/test/Verifier/frameallocate.ll (removed)
@@ -1,48 +0,0 @@
-; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
-
-declare i8* @llvm.frameallocate(i32)
-declare i8* @llvm.framerecover(i8*, i8*)
-
-define internal void @f() {
-  call i8* @llvm.frameallocate(i32 4)
-  call i8* @llvm.frameallocate(i32 4)
-  ret void
-}
-; CHECK: multiple calls to llvm.frameallocate in one function
-
-define internal void @f_a(i32 %n) {
-  call i8* @llvm.frameallocate(i32 %n)
-  ret void
-}
-; CHECK: llvm.frameallocate argument must be constant integer size
-
-define internal void @g() {
-entry:
-  br label %not_entry
-not_entry:
-  call i8* @llvm.frameallocate(i32 4)
-  ret void
-}
-; CHECK: llvm.frameallocate used outside of entry block
-
-define internal void @h() {
-  call i8* @llvm.framerecover(i8* null, i8* null)
-  ret void
-}
-; CHECK: llvm.framerecover first argument must be function defined in this module
-
- at global = constant i8 0
-
-declare void @declaration()
-
-define internal void @i() {
-  call i8* @llvm.framerecover(i8* @global, i8* null)
-  ret void
-}
-; CHECK: llvm.framerecover first argument must be function defined in this module
-
-define internal void @j() {
-  call i8* @llvm.framerecover(i8* bitcast(void()* @declaration to i8*), i8* null)
-  ret void
-}
-; CHECK: llvm.framerecover first argument must be function defined in this module

Added: llvm/trunk/test/Verifier/frameescape.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/frameescape.ll?rev=231386&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/frameescape.ll (added)
+++ llvm/trunk/test/Verifier/frameescape.ll Thu Mar  5 12:26:34 2015
@@ -0,0 +1,69 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @llvm.frameescape(...)
+declare i8* @llvm.framerecover(i8*, i8*, i32)
+
+define internal void @f() {
+  %a = alloca i8
+  call void (...)* @llvm.frameescape(i8* %a)
+  call void (...)* @llvm.frameescape(i8* %a)
+  ret void
+}
+; CHECK: multiple calls to llvm.frameescape in one function
+
+define internal void @g() {
+entry:
+  %a = alloca i8
+  br label %not_entry
+not_entry:
+  call void (...)* @llvm.frameescape(i8* %a)
+  ret void
+}
+; CHECK: llvm.frameescape used outside of entry block
+
+define internal void @h() {
+  call i8* @llvm.framerecover(i8* null, i8* null, i32 0)
+  ret void
+}
+; CHECK: llvm.framerecover first argument must be function defined in this module
+
+ at global = constant i8 0
+
+declare void @declaration()
+
+define internal void @i() {
+  call i8* @llvm.framerecover(i8* @global, i8* null, i32 0)
+  ret void
+}
+; CHECK: llvm.framerecover first argument must be function defined in this module
+
+define internal void @j() {
+  call i8* @llvm.framerecover(i8* bitcast(void()* @declaration to i8*), i8* null, i32 0)
+  ret void
+}
+; CHECK: llvm.framerecover first argument must be function defined in this module
+
+define internal void @k(i32 %n) {
+  call i8* @llvm.framerecover(i8* bitcast(void()* @f to i8*), i8* null, i32 %n)
+  ret void
+}
+; CHECK: idx argument of llvm.framerecover must be a constant int
+
+define internal void @l(i8* %b) {
+  %a = alloca i8
+  call void (...)* @llvm.frameescape(i8* %a, i8* %b)
+  ret void
+}
+; CHECK: llvm.frameescape only accepts static allocas
+
+define internal void @m() {
+  %a = alloca i8
+  call void (...)* @llvm.frameescape(i8* %a)
+  ret void
+}
+
+define internal void @n(i8* %fp) {
+  call i8* @llvm.framerecover(i8* bitcast(void ()* @m to i8*), i8* %fp, i32 1)
+  ret void
+}
+; CHECK: all indices passed to llvm.framerecover must be less than the number of arguments passed ot llvm.frameescape in the parent function





More information about the llvm-commits mailing list