// outlined but before the outlined code is pruned from the parent function.
DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks;
- // Map from outlined handler to call to llvm.frameaddress(1). Only used for
+ // Map from outlined handler to call to parent local address. Only used for
// 32-bit EH.
DenseMap<Function *, Value *> HandlerToParentFP;
BasicBlock *NextBB;
Constant *Selector;
if (isSelectorDispatch(BB, CatchHandler, Selector, NextBB)) {
- // Split the edge if there is a phi node. Returning from EH to a phi node
- // is just as impossible as having a phi after an indirectbr.
- if (isa<PHINode>(CatchHandler->begin())) {
+ // Split the edge if there are multiple predecessors. This creates a place
+ // where we can insert EH recovery code.
+ if (!CatchHandler->getSinglePredecessor()) {
DEBUG(dbgs() << "splitting EH return edge from " << BB->getName()
<< " to " << CatchHandler->getName() << '\n');
BBI = CatchHandler = SplitCriticalEdge(
// identifyEHBlocks() should have been called before this function.
assert(!NormalBlocks.empty());
+ // Try to avoid demoting EH pointer and selector values. They get in the way
+ // of our pattern matching.
+ SmallPtrSet<Instruction *, 10> EHVals;
+ for (BasicBlock &BB : F) {
+ LandingPadInst *LP = BB.getLandingPadInst();
+ if (!LP)
+ continue;
+ EHVals.insert(LP);
+ for (User *U : LP->users()) {
+ auto *EI = dyn_cast<ExtractValueInst>(U);
+ if (!EI)
+ continue;
+ EHVals.insert(EI);
+ for (User *U2 : EI->users()) {
+ if (auto *PN = dyn_cast<PHINode>(U2))
+ EHVals.insert(PN);
+ }
+ }
+ }
+
SetVector<Argument *> ArgsToDemote;
SetVector<Instruction *> InstrsToDemote;
for (BasicBlock &BB : F) {
continue;
}
+ // Don't demote EH values.
auto *OpI = cast<Instruction>(Op);
+ if (EHVals.count(OpI))
+ continue;
+
BasicBlock *OpBB = OpI->getParent();
// If a value is produced and consumed in the same BB, we don't need to
// demote it.
LPad->replaceAllUsesWith(UndefValue::get(LPad->getType()));
// Rewrite uses of the exception pointer to loads of an alloca.
- for (Instruction *E : SEHCodeUses) {
+ while (!SEHCodeUses.empty()) {
+ Instruction *E = SEHCodeUses.pop_back_val();
SmallVector<Use *, 4> Uses;
for (Use &U : E->uses())
Uses.push_back(&U);
auto *I = cast<Instruction>(U->getUser());
if (isa<ResumeInst>(I))
continue;
- LoadInst *LI;
if (auto *Phi = dyn_cast<PHINode>(I))
- LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false,
- Phi->getIncomingBlock(*U)->getTerminator());
+ SEHCodeUses.push_back(Phi);
else
- LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I);
- U->set(LI);
+ U->set(new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I));
}
E->replaceAllUsesWith(UndefValue::get(E->getType()));
E->eraseFromParent();
Builder.SetInsertPoint(Entry->getFirstInsertionPt());
Function *FrameEscapeFn =
- Intrinsic::getDeclaration(M, Intrinsic::frameescape);
+ Intrinsic::getDeclaration(M, Intrinsic::localescape);
Function *RecoverFrameFn =
- Intrinsic::getDeclaration(M, Intrinsic::framerecover);
+ Intrinsic::getDeclaration(M, Intrinsic::localrecover);
SmallVector<Value *, 8> AllocasToEscape;
- // Scan the entry block for an existing call to llvm.frameescape. We need to
+ // Scan the entry block for an existing call to llvm.localescape. We need to
// keep escaping those objects.
for (Instruction &I : F.front()) {
auto *II = dyn_cast<IntrinsicInst>(&I);
- if (II && II->getIntrinsicID() == Intrinsic::frameescape) {
+ if (II && II->getIntrinsicID() == Intrinsic::localescape) {
auto Args = II->arg_operands();
AllocasToEscape.append(Args.begin(), Args.end());
II->eraseFromParent();
}
// Finally, replace all of the temporary allocas for frame variables used in
- // the outlined handlers with calls to llvm.framerecover.
+ // the outlined handlers with calls to llvm.localrecover.
for (auto &VarInfoEntry : FrameVarInfo) {
Value *ParentVal = VarInfoEntry.first;
TinyPtrVector<AllocaInst *> &Allocas = VarInfoEntry.second;
llvm::Value *FP = HandlerToParentFP[HandlerFn];
assert(FP);
- // FIXME: Sink this framerecover into the blocks where it is used.
+ // FIXME: Sink this localrecover into the blocks where it is used.
Builder.SetInsertPoint(TempAlloca);
Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
Value *RecoverArgs[] = {
}
} // End for each FrameVarInfo entry.
- // Insert 'call void (...)* @llvm.frameescape(...)' at the end of the entry
+ // Insert 'call void (...)* @llvm.localescape(...)' at the end of the entry
// block.
Builder.SetInsertPoint(&F.getEntryBlock().back());
Builder.CreateCall(FrameEscapeFn, AllocasToEscape);
VMap[Extract] = SelectorValue;
}
-static bool isFrameAddressCall(const Value *V) {
- return match(const_cast<Value *>(V),
- m_Intrinsic<Intrinsic::frameaddress>(m_SpecificInt(0)));
+static bool isLocalAddressCall(const Value *V) {
+ return match(const_cast<Value *>(V), m_Intrinsic<Intrinsic::localaddress>());
}
CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction(
if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>()))
return handleTypeIdFor(VMap, Inst, NewBB);
- // When outlining llvm.frameaddress(i32 0), remap that to the second argument,
+ // When outlining llvm.localaddress(), remap that to the second argument,
// which is the FP of the parent.
- if (isFrameAddressCall(Inst)) {
+ if (isLocalAddressCall(Inst)) {
VMap[Inst] = ParentFP;
return CloningDirector::SkipInstruction;
}
// If we're asked to materialize a static alloca, we temporarily create an
// alloca in the outlined function and add this to the FrameVarInfo map. When
// all the outlining is complete, we'll replace these temporary allocas with
- // calls to llvm.framerecover.
+ // calls to llvm.localrecover.
if (auto *AV = dyn_cast<AllocaInst>(V)) {
assert(AV->isStaticAlloca() &&
"cannot materialize un-demoted dynamic alloca");
// of a catch parameter, add a sentinel to the multimap to indicate that it's
// used from another handler. This will prevent us from trying to sink the
// alloca into the handler and ensure that the catch parameter is present in
- // the call to llvm.frameescape.
+ // the call to llvm.localescape.
FrameVarInfo[V].push_back(getCatchObjectSentinel());
}
static CallSite matchOutlinedFinallyCall(BasicBlock *BB,
Instruction *MaybeCall) {
// Look for finally blocks that Clang has already outlined for us.
- // %fp = call i8* @llvm.frameaddress(i32 0)
+ // %fp = call i8* @llvm.localaddress()
// call void @"fin$parent"(iN 1, i8* %fp)
- if (isFrameAddressCall(MaybeCall) && MaybeCall != BB->getTerminator())
+ if (isLocalAddressCall(MaybeCall) && MaybeCall != BB->getTerminator())
MaybeCall = MaybeCall->getNextNode();
CallSite FinallyCall(MaybeCall);
if (!FinallyCall || FinallyCall.arg_size() != 2)
return CallSite();
if (!match(FinallyCall.getArgument(0), m_SpecificInt(1)))
return CallSite();
- if (!isFrameAddressCall(FinallyCall.getArgument(1)))
+ if (!isLocalAddressCall(FinallyCall.getArgument(1)))
return CallSite();
return FinallyCall;
}