summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-07-31 17:58:14 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-07-31 17:58:14 +0000
commit654e130b6ec76c1a2910b2594cb403ecd2773af8 (patch)
tree79a53c08a138345e3cdd13b36940d3d1cf6f5917 /llvm/lib
parente430654fd85a04f04c93eab40ba7fe87d8657130 (diff)
downloadbcm5719-llvm-654e130b6ec76c1a2910b2594cb403ecd2773af8.tar.gz
bcm5719-llvm-654e130b6ec76c1a2910b2594cb403ecd2773af8.zip
New EH representation for MSVC compatibility
This introduces new instructions neccessary to implement MSVC-compatible exception handling support. Most of the middle-end and none of the back-end haven't been audited or updated to take them into account. Differential Revision: http://reviews.llvm.org/D11097 llvm-svn: 243766
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/IPA/InlineCost.cpp14
-rw-r--r--llvm/lib/Analysis/LoopInfo.cpp4
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp8
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp7
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp161
-rw-r--r--llvm/lib/AsmParser/LLParser.h9
-rw-r--r--llvm/lib/AsmParser/LLToken.h4
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp128
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp58
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp24
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h6
-rw-r--r--llvm/lib/CodeGen/TargetLoweringBase.cpp6
-rw-r--r--llvm/lib/IR/AsmWriter.cpp58
-rw-r--r--llvm/lib/IR/BasicBlock.cpp13
-rw-r--r--llvm/lib/IR/Instruction.cpp16
-rw-r--r--llvm/lib/IR/Instructions.cpp321
-rw-r--r--llvm/lib/IR/Verifier.cpp165
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp34
-rw-r--r--llvm/lib/Transforms/Scalar/ADCE.cpp4
-rw-r--r--llvm/lib/Transforms/Scalar/BDCE.cpp4
-rw-r--r--llvm/lib/Transforms/Scalar/JumpThreading.cpp3
-rw-r--r--llvm/lib/Transforms/Scalar/SCCP.cpp10
-rw-r--r--llvm/lib/Transforms/Utils/BasicBlockUtils.cpp11
-rw-r--r--llvm/lib/Transforms/Utils/InlineFunction.cpp145
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp5
-rw-r--r--llvm/lib/Transforms/Utils/LoopSimplify.cpp11
26 files changed, 1180 insertions, 49 deletions
diff --git a/llvm/lib/Analysis/IPA/InlineCost.cpp b/llvm/lib/Analysis/IPA/InlineCost.cpp
index 6d53b48832d..40bfac56719 100644
--- a/llvm/lib/Analysis/IPA/InlineCost.cpp
+++ b/llvm/lib/Analysis/IPA/InlineCost.cpp
@@ -156,6 +156,8 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
bool visitSwitchInst(SwitchInst &SI);
bool visitIndirectBrInst(IndirectBrInst &IBI);
bool visitResumeInst(ResumeInst &RI);
+ bool visitCleanupReturnInst(CleanupReturnInst &RI);
+ bool visitCatchReturnInst(CatchReturnInst &RI);
bool visitUnreachableInst(UnreachableInst &I);
public:
@@ -903,6 +905,18 @@ bool CallAnalyzer::visitResumeInst(ResumeInst &RI) {
return false;
}
+bool CallAnalyzer::visitCleanupReturnInst(CleanupReturnInst &CRI) {
+ // FIXME: It's not clear that a single instruction is an accurate model for
+ // the inline cost of a cleanupret instruction.
+ return false;
+}
+
+bool CallAnalyzer::visitCatchReturnInst(CatchReturnInst &CRI) {
+ // FIXME: It's not clear that a single instruction is an accurate model for
+ // the inline cost of a cleanupret instruction.
+ return false;
+}
+
bool CallAnalyzer::visitUnreachableInst(UnreachableInst &I) {
// FIXME: It might be reasonably to discount the cost of instructions leading
// to unreachable as they have the lowest possible impact on both runtime and
diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp
index bd0686075a9..1ad4fd893bc 100644
--- a/llvm/lib/Analysis/LoopInfo.cpp
+++ b/llvm/lib/Analysis/LoopInfo.cpp
@@ -102,8 +102,8 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
return false;
if (I->mayReadFromMemory())
return false;
- // The landingpad instruction is immobile.
- if (isa<LandingPadInst>(I))
+ // EH block instructions are immobile.
+ if (I->isEHPad())
return false;
// Determine the insertion point, unless one was given.
if (!InsertPt) {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 434a69e0820..b761a5c1b43 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3147,10 +3147,16 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
case Instruction::Switch:
case Instruction::Unreachable:
case Instruction::Fence:
- case Instruction::LandingPad:
case Instruction::AtomicRMW:
case Instruction::AtomicCmpXchg:
+ case Instruction::LandingPad:
case Instruction::Resume:
+ case Instruction::CatchPad:
+ case Instruction::CatchEndPad:
+ case Instruction::CatchRet:
+ case Instruction::CleanupPad:
+ case Instruction::CleanupRet:
+ case Instruction::TerminatePad:
return false; // Misc instructions which have effects
}
}
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 5c4bab734b2..be951f5c7d8 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -524,6 +524,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(undef);
KEYWORD(null);
KEYWORD(to);
+ KEYWORD(caller);
KEYWORD(tail);
KEYWORD(musttail);
KEYWORD(target);
@@ -749,6 +750,12 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(extractvalue, ExtractValue);
INSTKEYWORD(insertvalue, InsertValue);
INSTKEYWORD(landingpad, LandingPad);
+ INSTKEYWORD(cleanupret, CleanupRet);
+ INSTKEYWORD(catchret, CatchRet);
+ INSTKEYWORD(catchpad, CatchPad);
+ INSTKEYWORD(terminatepad, TerminatePad);
+ INSTKEYWORD(cleanuppad, CleanupPad);
+ INSTKEYWORD(catchendpad, CatchEndPad);
#undef INSTKEYWORD
#define DWKEYWORD(TYPE, TOKEN) \
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index f16921dea66..6c2cd08e580 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4532,6 +4532,12 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS);
case lltok::kw_invoke: return ParseInvoke(Inst, PFS);
case lltok::kw_resume: return ParseResume(Inst, PFS);
+ case lltok::kw_cleanupret: return ParseCleanupRet(Inst, PFS);
+ case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
+ case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
+ case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
+ case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
+ case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
case lltok::kw_sub:
@@ -4936,6 +4942,161 @@ bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) {
return false;
}
+bool LLParser::ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
+ PerFunctionState &PFS) {
+ if (ParseToken(lltok::lsquare, "expected '[' in cleanuppad"))
+ return true;
+
+ while (Lex.getKind() != lltok::rsquare) {
+ // If this isn't the first argument, we need a comma.
+ if (!Args.empty() &&
+ ParseToken(lltok::comma, "expected ',' in argument list"))
+ return true;
+
+ // Parse the argument.
+ LocTy ArgLoc;
+ Type *ArgTy = nullptr;
+ if (ParseType(ArgTy, ArgLoc))
+ return true;
+
+ Value *V;
+ if (ArgTy->isMetadataTy()) {
+ if (ParseMetadataAsValue(V, PFS))
+ return true;
+ } else {
+ if (ParseValue(ArgTy, V, PFS))
+ return true;
+ }
+ Args.push_back(V);
+ }
+
+ Lex.Lex(); // Lex the ']'.
+ return false;
+}
+
+/// ParseCleanupRet
+/// ::= 'cleanupret' ('void' | TypeAndValue) unwind ('to' 'caller' | TypeAndValue)
+bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
+ Type *RetTy = nullptr;
+ Value *RetVal = nullptr;
+ if (ParseType(RetTy, /*AllowVoid=*/true))
+ return true;
+
+ if (!RetTy->isVoidTy())
+ if (ParseValue(RetTy, RetVal, PFS))
+ return true;
+
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (Lex.getKind() == lltok::kw_to) {
+ Lex.Lex();
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in cleanupret"))
+ return true;
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ return true;
+ }
+ }
+
+ Inst = CleanupReturnInst::Create(Context, RetVal, UnwindBB);
+ return false;
+}
+
+/// ParseCatchRet
+/// ::= 'catchret' TypeAndValue
+bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
+ BasicBlock *BB;
+ if (ParseTypeAndBasicBlock(BB, PFS))
+ return true;
+
+ Inst = CatchReturnInst::Create(BB);
+ return false;
+}
+
+/// ParseCatchPad
+/// ::= 'catchpad' Type ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Type *RetType = nullptr;
+
+ SmallVector<Value *, 8> Args;
+ if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ return true;
+
+ BasicBlock *NormalBB, *UnwindBB;
+ if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
+ ParseTypeAndBasicBlock(NormalBB, PFS) ||
+ ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
+ ParseTypeAndBasicBlock(UnwindBB, PFS))
+ return true;
+
+ Inst = CatchPadInst::Create(RetType, NormalBB, UnwindBB, Args);
+ return false;
+}
+
+/// ParseTerminatePad
+/// ::= 'terminatepad' ParamList 'to' TypeAndValue
+bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
+ SmallVector<Value *, 8> Args;
+ if (ParseExceptionArgs(Args, PFS))
+ return true;
+
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (Lex.getKind() == lltok::kw_to) {
+ Lex.Lex();
+ if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
+ return true;
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ return true;
+ }
+ }
+
+ Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
+ return false;
+}
+
+/// ParseCleanupPad
+/// ::= 'cleanuppad' ParamList
+bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+ Type *RetType = nullptr;
+
+ SmallVector<Value *, 8> Args;
+ if (ParseType(RetType, /*AllowVoid=*/true) || ParseExceptionArgs(Args, PFS))
+ return true;
+
+ Inst = CleanupPadInst::Create(RetType, Args);
+ return false;
+}
+
+/// ParseCatchEndPad
+/// ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
+bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
+ if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+ return true;
+
+ BasicBlock *UnwindBB = nullptr;
+ if (Lex.getKind() == lltok::kw_to) {
+ Lex.Lex();
+ if (Lex.getKind() == lltok::kw_caller) {
+ Lex.Lex();
+ } else {
+ return true;
+ }
+ } else {
+ if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+ return true;
+ }
+ }
+
+ Inst = CatchEndPadInst::Create(Context, UnwindBB);
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Binary Operators.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index 6ef92c12b52..0c066f4b603 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -385,6 +385,9 @@ namespace llvm {
bool IsMustTailCall = false,
bool InVarArgsFunc = false);
+ bool ParseExceptionArgs(SmallVectorImpl<Value *> &Args,
+ PerFunctionState &PFS);
+
// Constant Parsing.
bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr);
bool ParseGlobalValue(Type *Ty, Constant *&V);
@@ -445,6 +448,12 @@ namespace llvm {
bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS);
bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS);
bool ParseResume(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
unsigned OperandType);
diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
index 691f085f0c9..19bf7e4e4c1 100644
--- a/llvm/lib/AsmParser/LLToken.h
+++ b/llvm/lib/AsmParser/LLToken.h
@@ -51,6 +51,7 @@ namespace lltok {
kw_zeroinitializer,
kw_undef, kw_null,
kw_to,
+ kw_caller,
kw_tail,
kw_musttail,
kw_target,
@@ -177,7 +178,8 @@ namespace lltok {
kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter,
kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
- kw_unreachable,
+ kw_unreachable, kw_cleanupret, kw_catchret, kw_catchpad,
+ kw_terminatepad, kw_cleanuppad, kw_catchendpad,
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
kw_getelementptr,
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index de91150c424..fea4c167ae3 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -3811,6 +3811,134 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
}
break;
}
+ // CLEANUPRET: [] or [ty,val] or [bb#] or [ty,val,bb#]
+ case bitc::FUNC_CODE_INST_CLEANUPRET: {
+ if (Record.size() < 2)
+ return error("Invalid record");
+ unsigned Idx = 0;
+ bool HasReturnValue = !!Record[Idx++];
+ bool HasUnwindDest = !!Record[Idx++];
+ Value *RetVal = nullptr;
+ BasicBlock *UnwindDest = nullptr;
+
+ if (HasReturnValue && getValueTypePair(Record, Idx, NextValueNo, RetVal))
+ return error("Invalid record");
+ if (HasUnwindDest) {
+ if (Idx == Record.size())
+ return error("Invalid record");
+ UnwindDest = getBasicBlock(Record[Idx++]);
+ if (!UnwindDest)
+ return error("Invalid record");
+ }
+
+ if (Record.size() != Idx)
+ return error("Invalid record");
+
+ I = CleanupReturnInst::Create(Context, RetVal, UnwindDest);
+ InstructionList.push_back(I);
+ break;
+ }
+ case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [bb#]
+ if (Record.size() != 1)
+ return error("Invalid record");
+ BasicBlock *BB = getBasicBlock(Record[0]);
+ if (!BB)
+ return error("Invalid record");
+ I = CatchReturnInst::Create(BB);
+ InstructionList.push_back(I);
+ break;
+ }
+ case bitc::FUNC_CODE_INST_CATCHPAD: { // CATCHPAD: [ty,bb#,bb#,num,(ty,val)*]
+ if (Record.size() < 4)
+ return error("Invalid record");
+ unsigned Idx = 0;
+ Type *Ty = getTypeByID(Record[Idx++]);
+ if (!Ty)
+ return error("Invalid record");
+ BasicBlock *NormalBB = getBasicBlock(Record[Idx++]);
+ if (!NormalBB)
+ return error("Invalid record");
+ BasicBlock *UnwindBB = getBasicBlock(Record[Idx++]);
+ if (!UnwindBB)
+ return error("Invalid record");
+ unsigned NumArgOperands = Record[Idx++];
+ SmallVector<Value *, 2> Args;
+ for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
+ Value *Val;
+ if (getValueTypePair(Record, Idx, NextValueNo, Val))
+ return error("Invalid record");
+ Args.push_back(Val);
+ }
+ if (Record.size() != Idx)
+ return error("Invalid record");
+
+ I = CatchPadInst::Create(Ty, NormalBB, UnwindBB, Args);
+ InstructionList.push_back(I);
+ break;
+ }
+ case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [bb#,num,(ty,val)*]
+ if (Record.size() < 1)
+ return error("Invalid record");
+ unsigned Idx = 0;
+ bool HasUnwindDest = !!Record[Idx++];
+ BasicBlock *UnwindDest = nullptr;
+ if (HasUnwindDest) {
+ if (Idx == Record.size())
+ return error("Invalid record");
+ UnwindDest = getBasicBlock(Record[Idx++]);
+ if (!UnwindDest)
+ return error("Invalid record");
+ }
+ unsigned NumArgOperands = Record[Idx++];
+ SmallVector<Value *, 2> Args;
+ for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
+ Value *Val;
+ if (getValueTypePair(Record, Idx, NextValueNo, Val))
+ return error("Invalid record");
+ Args.push_back(Val);
+ }
+ if (Record.size() != Idx)
+ return error("Invalid record");
+
+ I = TerminatePadInst::Create(Context, UnwindDest, Args);
+ InstructionList.push_back(I);
+ break;
+ }
+ case bitc::FUNC_CODE_INST_CLEANUPPAD: { // CLEANUPPAD: [ty, num,(ty,val)*]
+ if (Record.size() < 2)
+ return error("Invalid record");
+ unsigned Idx = 0;
+ Type *Ty = getTypeByID(Record[Idx++]);
+ if (!Ty)
+ return error("Invalid record");
+ unsigned NumArgOperands = Record[Idx++];
+ SmallVector<Value *, 2> Args;
+ for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
+ Value *Val;
+ if (getValueTypePair(Record, Idx, NextValueNo, Val))
+ return error("Invalid record");
+ Args.push_back(Val);
+ }
+ if (Record.size() != Idx)
+ return error("Invalid record");
+
+ I = CleanupPadInst::Create(Ty, Args);
+ InstructionList.push_back(I);
+ break;
+ }
+ case bitc::FUNC_CODE_INST_CATCHENDPAD: { // CATCHENDPADINST: [bb#] or []
+ if (Record.size() > 1)
+ return error("Invalid record");
+ BasicBlock *BB = nullptr;
+ if (Record.size() == 1) {
+ BB = getBasicBlock(Record[0]);
+ if (!BB)
+ return error("Invalid record");
+ }
+ I = CatchEndPadInst::Create(Context, BB);
+ InstructionList.push_back(I);
+ break;
+ }
case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
// Check magic
if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 31ae0141ef8..20e31d1a102 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1851,6 +1851,64 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Code = bitc::FUNC_CODE_INST_RESUME;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
break;
+ case Instruction::CleanupRet: {
+ Code = bitc::FUNC_CODE_INST_CLEANUPRET;
+ const auto &CRI = cast<CleanupReturnInst>(I);
+ Vals.push_back(CRI.hasReturnValue());
+ Vals.push_back(CRI.hasUnwindDest());
+ if (CRI.hasReturnValue())
+ PushValueAndType(CRI.getReturnValue(), InstID, Vals, VE);
+ if (CRI.hasUnwindDest())
+ Vals.push_back(VE.getValueID(CRI.getUnwindDest()));
+ break;
+ }
+ case Instruction::CatchRet: {
+ Code = bitc::FUNC_CODE_INST_CATCHRET;
+ const auto &CRI = cast<CatchReturnInst>(I);
+ Vals.push_back(VE.getValueID(CRI.getSuccessor()));
+ break;
+ }
+ case Instruction::CatchPad: {
+ Code = bitc::FUNC_CODE_INST_CATCHPAD;
+ const auto &CPI = cast<CatchPadInst>(I);
+ Vals.push_back(VE.getTypeID(CPI.getType()));
+ Vals.push_back(VE.getValueID(CPI.getNormalDest()));
+ Vals.push_back(VE.getValueID(CPI.getUnwindDest()));
+ unsigned NumArgOperands = CPI.getNumArgOperands();
+ Vals.push_back(NumArgOperands);
+ for (unsigned Op = 0; Op != NumArgOperands; ++Op)
+ PushValueAndType(CPI.getArgOperand(Op), InstID, Vals, VE);
+ break;
+ }
+ case Instruction::TerminatePad: {
+ Code = bitc::FUNC_CODE_INST_TERMINATEPAD;
+ const auto &TPI = cast<TerminatePadInst>(I);
+ Vals.push_back(TPI.hasUnwindDest());
+ if (TPI.hasUnwindDest())
+ Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
+ unsigned NumArgOperands = TPI.getNumArgOperands();
+ Vals.push_back(NumArgOperands);
+ for (unsigned Op = 0; Op != NumArgOperands; ++Op)
+ PushValueAndType(TPI.getArgOperand(Op), InstID, Vals, VE);
+ break;
+ }
+ case Instruction::CleanupPad: {
+ Code = bitc::FUNC_CODE_INST_CLEANUPPAD;
+ const auto &CPI = cast<CleanupPadInst>(I);
+ Vals.push_back(VE.getTypeID(CPI.getType()));
+ unsigned NumOperands = CPI.getNumOperands();
+ Vals.push_back(NumOperands);
+ for (unsigned Op = 0; Op != NumOperands; ++Op)
+ PushValueAndType(CPI.getOperand(Op), InstID, Vals, VE);
+ break;
+ }
+ case Instruction::CatchEndPad: {
+ Code = bitc::FUNC_CODE_INST_CATCHENDPAD;
+ const auto &CEPI = cast<CatchEndPadInst>(I);
+ if (CEPI.hasUnwindDest())
+ Vals.push_back(VE.getValueID(CEPI.getUnwindDest()));
+ break;
+ }
case Instruction::Unreachable:
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 22e1be94ef0..f15c95f4d5e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1158,6 +1158,30 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
llvm_unreachable("Can't get register for value!");
}
+void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
+ report_fatal_error("visitCleanupRet not yet implemented!");
+}
+
+void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
+ report_fatal_error("visitCatchEndPad not yet implemented!");
+}
+
+void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
+ report_fatal_error("visitCatchRet not yet implemented!");
+}
+
+void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
+ report_fatal_error("visitCatchPad not yet implemented!");
+}
+
+void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
+ report_fatal_error("visitTerminatePad not yet implemented!");
+}
+
+void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
+ report_fatal_error("visitCleanupPad not yet implemented!");
+}
+
void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
auto &DL = DAG.getDataLayout();
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 1b8cd5bb585..f71190d6375 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -735,6 +735,12 @@ private:
void visitSwitch(const SwitchInst &I);
void visitIndirectBr(const IndirectBrInst &I);
void visitUnreachable(const UnreachableInst &I);
+ void visitCleanupRet(const CleanupReturnInst &I);
+ void visitCatchEndPad(const CatchEndPadInst &I);
+ void visitCatchRet(const CatchReturnInst &I);
+ void visitCatchPad(const CatchPadInst &I);
+ void visitTerminatePad(const TerminatePadInst &TPI);
+ void visitCleanupPad(const CleanupPadInst &CPI);
uint32_t getEdgeWeight(const MachineBasicBlock *Src,
const MachineBasicBlock *Dst) const;
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index ee50ddd9fa0..0e10b2f2e11 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1571,6 +1571,12 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
case Invoke: return 0;
case Resume: return 0;
case Unreachable: return 0;
+ case CleanupRet: return 0;
+ case CatchEndPad: return 0;
+ case CatchRet: return 0;
+ case CatchPad: return 0;
+ case TerminatePad: return 0;
+ case CleanupPad: return 0;
case Add: return ISD::ADD;
case FAdd: return ISD::FADD;
case Sub: return ISD::SUB;
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 9018180ad75..e3905de6597 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2861,8 +2861,66 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(LPI->getClause(i), true);
}
+ } else if (const auto *CPI = dyn_cast<CatchPadInst>(&I)) {
+ Out << ' ';
+ TypePrinter.print(I.getType(), Out);
+
+ Out << " [";
+ for (unsigned Op = 0, NumOps = CPI->getNumArgOperands(); Op < NumOps;
+ ++Op) {
+ if (Op > 0)
+ Out << ", ";
+ writeOperand(CPI->getArgOperand(Op), /*PrintType=*/true);
+ }
+ Out << "] to ";
+ writeOperand(CPI->getNormalDest(), /*PrintType=*/true);
+ Out << " unwind ";
+ writeOperand(CPI->getUnwindDest(), /*PrintType=*/true);
+ } else if (const auto *TPI = dyn_cast<TerminatePadInst>(&I)) {
+ Out << " [";
+ for (unsigned Op = 0, NumOps = TPI->getNumArgOperands(); Op < NumOps;
+ ++Op) {
+ if (Op > 0)
+ Out << ", ";
+ writeOperand(TPI->getArgOperand(Op), /*PrintType=*/true);
+ }
+ Out << "] unwind ";
+ if (TPI->hasUnwindDest())
+ writeOperand(TPI->getUnwindDest(), /*PrintType=*/true);
+ else
+ Out << "to caller";
+ } else if (const auto *CPI = dyn_cast<CleanupPadInst>(&I)) {
+ Out << ' ';
+ TypePrinter.print(I.getType(), Out);
+
+ Out << " [";
+ for (unsigned Op = 0, NumOps = CPI->getNumOperands(); Op < NumOps; ++Op) {
+ if (Op > 0)
+ Out << ", ";
+ writeOperand(CPI->getOperand(Op), /*PrintType=*/true);
+ }
+ Out << "]";
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
+ } else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
+ if (CRI->hasReturnValue()) {
+ Out << ' ';
+ writeOperand(CRI->getReturnValue(), /*PrintType=*/true);
+ } else {
+ Out << " void";
+ }
+
+ Out << " unwind ";
+ if (CRI->hasUnwindDest())
+ writeOperand(CRI->getUnwindDest(), /*PrintType=*/true);
+ else
+ Out << "to caller";
+ } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(&I)) {
+ Out << " unwind ";
+ if (CEPI->hasUnwindDest())
+ writeOperand(CEPI->getUnwindDest(), /*PrintType=*/true);
+ else
+ Out << "to caller";
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
// Print the calling convention being used.
if (CI->getCallingConv() != CallingConv::C) {
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index 0a0449434a7..b5671a66f04 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -197,7 +197,7 @@ BasicBlock::iterator BasicBlock::getFirstInsertionPt() {
return end();
iterator InsertPt = FirstNonPHI;
- if (isa<LandingPadInst>(InsertPt)) ++InsertPt;
+ if (InsertPt->isEHPad()) ++InsertPt;
return InsertPt;
}
@@ -333,6 +333,17 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
}
}
+bool BasicBlock::canSplitPredecessors() const {
+ const Instruction *FirstNonPHI = getFirstNonPHI();
+ if (isa<LandingPadInst>(FirstNonPHI))
+ return true;
+ // This is perhaps a little conservative because constructs like
+ // CleanupBlockInst are pretty easy to split. However, SplitBlockPredecessors
+ // cannot handle such things just yet.
+ if (FirstNonPHI->isEHPad())
+ return false;
+ return true;
+}
/// This splits a basic block into two at the specified
/// instruction. Note that all instructions BEFORE the specified iterator stay
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index c57ba16cf6c..85173d96562 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -196,6 +196,11 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Invoke: return "invoke";
case Resume: return "resume";
case Unreachable: return "unreachable";
+ case CleanupRet: return "cleanupret";
+ case CatchEndPad: return "catchendpad";
+ case CatchRet: return "catchret";
+ case CatchPad: return "catchpad";
+ case TerminatePad: return "terminatepad";
// Standard binary operators...
case Add: return "add";
@@ -256,6 +261,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case ExtractValue: return "extractvalue";
case InsertValue: return "insertvalue";
case LandingPad: return "landingpad";
+ case CleanupPad: return "cleanuppad";
default: return "<Invalid operator> ";
}
@@ -407,6 +413,8 @@ bool Instruction::mayReadFromMemory() const {
case Instruction::Fence: // FIXME: refine definition of mayReadFromMemory
case Instruction::AtomicCmpXchg:
case Instruction::AtomicRMW:
+ case Instruction::CatchRet:
+ case Instruction::TerminatePad:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->doesNotAccessMemory();
@@ -427,6 +435,8 @@ bool Instruction::mayWriteToMemory() const {
case Instruction::VAArg:
case Instruction::AtomicCmpXchg:
case Instruction::AtomicRMW:
+ case Instruction::CatchRet:
+ case Instruction::TerminatePad:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->onlyReadsMemory();
@@ -455,6 +465,12 @@ bool Instruction::isAtomic() const {
bool Instruction::mayThrow() const {
if (const CallInst *CI = dyn_cast<CallInst>(this))
return !CI->doesNotThrow();
+ if (const auto *CRI = dyn_cast<CleanupReturnInst>(this))
+ return CRI->unwindsToCaller();
+ if (const auto *CEPI = dyn_cast<CatchEndPadInst>(this))
+ return CEPI->unwindsToCaller();
+ if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
+ return TPI->unwindsToCaller();
return isa<ResumeInst>(this);
}
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 86c921aeda8..701f92eb6ea 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -671,6 +671,303 @@ BasicBlock *ResumeInst::getSuccessorV(unsigned idx) const {
}
//===----------------------------------------------------------------------===//
+// CleanupReturnInst Implementation
+//===----------------------------------------------------------------------===//
+
+CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI)
+ : TerminatorInst(CRI.getType(), Instruction::CleanupRet,
+ OperandTraits<CleanupReturnInst>::op_end(this) -
+ CRI.getNumOperands(),
+ CRI.getNumOperands()) {
+ SubclassOptionalData = CRI.SubclassOptionalData;
+ if (Value *RetVal = CRI.getReturnValue())
+ setReturnValue(RetVal);
+ if (BasicBlock *UnwindDest = CRI.getUnwindDest())
+ setUnwindDest(UnwindDest);
+}
+
+void CleanupReturnInst::init(Value *RetVal, BasicBlock *UnwindBB) {
+ SubclassOptionalData = 0;
+ if (UnwindBB)
+ setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
+ if (RetVal)
+ setInstructionSubclassData(getSubclassDataFromInstruction() | 2);
+
+ if (UnwindBB)
+ setUnwindDest(UnwindBB);
+ if (RetVal)
+ setReturnValue(RetVal);
+}
+
+CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
+ BasicBlock *UnwindBB, unsigned Values,
+ Instruction *InsertBefore)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
+ OperandTraits<CleanupReturnInst>::op_end(this) - Values,
+ Values, InsertBefore) {
+ init(RetVal, UnwindBB);
+}
+
+CleanupReturnInst::CleanupReturnInst(LLVMContext &C, Value *RetVal,
+ BasicBlock *UnwindBB, unsigned Values,
+ BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::CleanupRet,
+ OperandTraits<CleanupReturnInst>::op_end(this) - Values,
+ Values, InsertAtEnd) {
+ init(RetVal, UnwindBB);
+}
+
+BasicBlock *CleanupReturnInst::getUnwindDest() const {
+ if (hasUnwindDest())
+ return cast<BasicBlock>(getOperand(getUnwindLabelOpIdx()));
+ return nullptr;
+}
+void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
+ assert(NewDest);
+ setOperand(getUnwindLabelOpIdx(), NewDest);
+}
+
+BasicBlock *CleanupReturnInst::getSuccessorV(unsigned Idx) const {
+ assert(Idx == 0);
+ return getUnwindDest();
+}
+unsigned CleanupReturnInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+void CleanupReturnInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
+ assert(Idx == 0);
+ setUnwindDest(B);
+}
+
+//===----------------------------------------------------------------------===//
+// CatchEndPadInst Implementation
+//===----------------------------------------------------------------------===//
+
+CatchEndPadInst::CatchEndPadInst(const CatchEndPadInst &CRI)
+ : TerminatorInst(CRI.getType(), Instruction::CatchEndPad,
+ OperandTraits<CatchEndPadInst>::op_end(this) -
+ CRI.getNumOperands(),
+ CRI.getNumOperands()) {
+ SubclassOptionalData = CRI.SubclassOptionalData;
+ if (BasicBlock *UnwindDest = CRI.getUnwindDest())
+ setUnwindDest(UnwindDest);
+}
+
+void CatchEndPadInst::init(BasicBlock *UnwindBB) {
+ SubclassOptionalData = 0;
+ if (UnwindBB) {
+ setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
+ setUnwindDest(UnwindBB);
+ }
+}
+
+CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
+ unsigned Values, Instruction *InsertBefore)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
+ OperandTraits<CatchEndPadInst>::op_end(this) - Values,
+ Values, InsertBefore) {
+ init(UnwindBB);
+}
+
+CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
+ unsigned Values, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
+ OperandTraits<CatchEndPadInst>::op_end(this) - Values,
+ Values, InsertAtEnd) {
+ init(UnwindBB);
+}
+
+BasicBlock *CatchEndPadInst::getSuccessorV(unsigned Idx) const {
+ assert(Idx == 0);
+ return getUnwindDest();
+}
+unsigned CatchEndPadInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+void CatchEndPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
+ assert(Idx == 0);
+ setUnwindDest(B);
+}
+
+//===----------------------------------------------------------------------===//
+// CatchReturnInst Implementation
+//===----------------------------------------------------------------------===//
+
+CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI)
+ : TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet,
+ OperandTraits<CatchReturnInst>::op_end(this) -
+ CRI.getNumOperands(),
+ CRI.getNumOperands()) {
+ Op<0>() = CRI.Op<0>();
+}
+
+CatchReturnInst::CatchReturnInst(BasicBlock *BB, Instruction *InsertBefore)
+ : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
+ OperandTraits<CatchReturnInst>::op_begin(this), 1,
+ InsertBefore) {
+ Op<0>() = BB;
+}
+
+CatchReturnInst::CatchReturnInst(BasicBlock *BB, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
+ OperandTraits<CatchReturnInst>::op_begin(this), 1,
+ InsertAtEnd) {
+ Op<0>() = BB;
+}
+
+BasicBlock *CatchReturnInst::getSuccessorV(unsigned Idx) const {
+ assert(Idx == 0);
+ return getSuccessor();
+}
+unsigned CatchReturnInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+void CatchReturnInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
+ assert(Idx == 0);
+ setSuccessor(B);
+}
+
+//===----------------------------------------------------------------------===//
+// CatchPadInst Implementation
+//===----------------------------------------------------------------------===//
+void CatchPadInst::init(BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, const Twine &NameStr) {
+ assert(getNumOperands() == 2 + Args.size() && "NumOperands not set up?");
+ Op<-2>() = IfNormal;
+ Op<-1>() = IfException;
+ std::copy(Args.begin(), Args.end(), op_begin());
+ setName(NameStr);
+}
+
+CatchPadInst::CatchPadInst(const CatchPadInst &CPI)
+ : TerminatorInst(CPI.getType(), Instruction::CatchPad,
+ OperandTraits<CatchPadInst>::op_end(this) -
+ CPI.getNumOperands(),
+ CPI.getNumOperands()) {
+ std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
+}
+
+CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
+ BasicBlock *IfException, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : TerminatorInst(RetTy, Instruction::CatchPad,
+ OperandTraits<CatchPadInst>::op_end(this) - Values,
+ Values, InsertBefore) {
+ init(IfNormal, IfException, Args, NameStr);
+}
+
+CatchPadInst::CatchPadInst(Type *RetTy, BasicBlock *IfNormal,
+ BasicBlock *IfException, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : TerminatorInst(RetTy, Instruction::CatchPad,
+ OperandTraits<CatchPadInst>::op_end(this) - Values,
+ Values, InsertAtEnd) {
+ init(IfNormal, IfException, Args, NameStr);
+}
+
+BasicBlock *CatchPadInst::getSuccessorV(unsigned Idx) const {
+ return getSuccessor(Idx);
+}
+unsigned CatchPadInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+void CatchPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
+ return setSuccessor(Idx, B);
+}
+
+//===----------------------------------------------------------------------===//
+// TerminatePadInst Implementation
+//===----------------------------------------------------------------------===//
+void TerminatePadInst::init(BasicBlock *BB, ArrayRef<Value *> Args,
+ const Twine &NameStr) {
+ SubclassOptionalData = 0;
+ if (BB)
+ setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
+ if (BB)
+ Op<-1>() = BB;
+ std::copy(Args.begin(), Args.end(), op_begin());
+ setName(NameStr);
+}
+
+TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI)
+ : TerminatorInst(TPI.getType(), Instruction::TerminatePad,
+ OperandTraits<TerminatePadInst>::op_end(this) -
+ TPI.getNumOperands(),
+ TPI.getNumOperands()) {
+ SubclassOptionalData = TPI.SubclassOptionalData;
+ std::copy(TPI.op_begin(), TPI.op_end(), op_begin());
+}
+
+TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr,
+ Instruction *InsertBefore)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
+ OperandTraits<TerminatePadInst>::op_end(this) - Values,
+ Values, InsertBefore) {
+ init(BB, Args, NameStr);
+}
+
+TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
+ OperandTraits<TerminatePadInst>::op_end(this) - Values,
+ Values, InsertAtEnd) {
+ init(BB, Args, NameStr);
+}
+
+BasicBlock *TerminatePadInst::getSuccessorV(unsigned Idx) const {
+ assert(Idx == 0);
+ return getUnwindDest();
+}
+unsigned TerminatePadInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+void TerminatePadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
+ assert(Idx == 0);
+ return setUnwindDest(B);
+}
+
+//===----------------------------------------------------------------------===//
+// CleanupPadInst Implementation
+//===----------------------------------------------------------------------===//
+void CleanupPadInst::init(ArrayRef<Value *> Args, const Twine &NameStr) {
+ assert(getNumOperands() == Args.size() && "NumOperands not set up?");
+ std::copy(Args.begin(), Args.end(), op_begin());
+ setName(NameStr);
+}
+
+CleanupPadInst::CleanupPadInst(const CleanupPadInst &CPI)
+ : Instruction(CPI.getType(), Instruction::CleanupPad,
+ OperandTraits<CleanupPadInst>::op_end(this) -
+ CPI.getNumOperands(),
+ CPI.getNumOperands()) {
+ std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
+}
+
+CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
+ const Twine &NameStr,
+ Instruction *InsertBefore)
+ : Instruction(RetTy, Instruction::CleanupPad,
+ OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
+ Args.size(), InsertBefore) {
+ init(Args, NameStr);
+}
+
+CleanupPadInst::CleanupPadInst(Type *RetTy, ArrayRef<Value *> Args,
+ const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : Instruction(RetTy, Instruction::CleanupPad,
+ OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
+ Args.size(), InsertAtEnd) {
+ init(Args, NameStr);
+}
+
+//===----------------------------------------------------------------------===//
// UnreachableInst Implementation
//===----------------------------------------------------------------------===//
@@ -3618,6 +3915,30 @@ InvokeInst *InvokeInst::cloneImpl() const {
ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
+CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
+ return new (getNumOperands()) CleanupReturnInst(*this);
+}
+
+CatchEndPadInst *CatchEndPadInst::cloneImpl() const {
+ return new (getNumOperands()) CatchEndPadInst(*this);
+}
+
+CatchReturnInst *CatchReturnInst::cloneImpl() const {
+ return new (1) CatchReturnInst(*this);
+}
+
+CatchPadInst *CatchPadInst::cloneImpl() const {
+ return new (getNumOperands()) CatchPadInst(*this);
+}
+
+TerminatePadInst *TerminatePadInst::cloneImpl() const {
+ return new (getNumOperands()) TerminatePadInst(*this);
+}
+
+CleanupPadInst *CleanupPadInst::cloneImpl() const {
+ return new (getNumOperands()) CleanupPadInst(*this);
+}
+
UnreachableInst *UnreachableInst::cloneImpl() const {
LLVMContext &Context = getContext();
return new UnreachableInst(Context);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 2135dafef8d..855456d0b2b 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -184,6 +184,15 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// \brief Track unresolved string-based type references.
SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs;
+ /// \brief The result type for a catchpad.
+ Type *CatchPadResultTy;
+
+ /// \brief The result type for a cleanuppad.
+ Type *CleanupPadResultTy;
+
+ /// \brief The result type for a landingpad.
+ Type *LandingPadResultTy;
+
/// \brief Whether we've seen a call to @llvm.localescape in this function
/// already.
bool SawFrameEscape;
@@ -194,7 +203,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
public:
explicit Verifier(raw_ostream &OS)
- : VerifierSupport(OS), Context(nullptr), SawFrameEscape(false) {}
+ : VerifierSupport(OS), Context(nullptr), CatchPadResultTy(nullptr),
+ CleanupPadResultTy(nullptr), LandingPadResultTy(nullptr),
+ SawFrameEscape(false) {}
bool verify(const Function &F) {
M = F.getParent();
@@ -228,6 +239,9 @@ public:
// FIXME: We strip const here because the inst visitor strips const.
visit(const_cast<Function &>(F));
InstsInThisBlock.clear();
+ CatchPadResultTy = nullptr;
+ CleanupPadResultTy = nullptr;
+ LandingPadResultTy = nullptr;
SawFrameEscape = false;
return !Broken;
@@ -379,6 +393,11 @@ private:
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
void visitLandingPadInst(LandingPadInst &LPI);
+ void visitCatchPadInst(CatchPadInst &CPI);
+ void visitCatchEndPadInst(CatchEndPadInst &CEPI);
+ void visitCleanupPadInst(CleanupPadInst &CPI);
+ void visitCleanupReturnInst(CleanupReturnInst &CRI);
+ void visitTerminatePadInst(TerminatePadInst &TPI);
void VerifyCallSite(CallSite CS);
void verifyMustTailCall(CallInst &CI);
@@ -2385,10 +2404,12 @@ void Verifier::visitCallInst(CallInst &CI) {
void Verifier::visitInvokeInst(InvokeInst &II) {
VerifyCallSite(&II);
- // Verify that there is a landingpad instruction as the first non-PHI
- // instruction of the 'unwind' destination.
- Assert(II.getUnwindDest()->isLandingPad(),
- "The unwind destination does not have a landingpad instruction!", &II);
+ // Verify that the first non-PHI instruction of the unwind destination is an
+ // exception handling instruction.
+ Assert(
+ II.getUnwindDest()->isEHPad(),
+ "The unwind destination does not have an exception handling instruction!",
+ &II);
visitTerminatorInst(II);
}
@@ -2774,6 +2795,14 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
&LPI);
}
+ if (!LandingPadResultTy)
+ LandingPadResultTy = LPI.getType();
+ else
+ Assert(LandingPadResultTy == LPI.getType(),
+ "The landingpad instruction should have a consistent result type "
+ "inside a function.",
+ &LPI);
+
Function *F = LPI.getParent()->getParent();
Assert(F->hasPersonalityFn(),
"LandingPadInst needs to be in a function with a personality.", &LPI);
@@ -2799,6 +2828,132 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
visitInstruction(LPI);
}
+void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
+ BasicBlock *BB = CPI.getParent();
+
+ if (!CatchPadResultTy)
+ CatchPadResultTy = CPI.getType();
+ else
+ Assert(CatchPadResultTy == CPI.getType(),
+ "The catchpad instruction should have a consistent result type "
+ "inside a function.",
+ &CPI);
+
+ Function *F = BB->getParent();
+ Assert(F->hasPersonalityFn(),
+ "CatchPadInst needs to be in a function with a personality.", &CPI);
+
+ // The catchpad instruction must be the first non-PHI instruction in the
+ // block.
+ Assert(BB->getFirstNonPHI() == &CPI,
+ "CatchPadInst not the first non-PHI instruction in the block.",
+ &CPI);
+
+ BasicBlock *UnwindDest = CPI.getUnwindDest();
+ Instruction *I = UnwindDest->getFirstNonPHI();
+ Assert(
+ isa<CatchPadInst>(I) || isa<CatchEndPadInst>(I),
+ "CatchPadInst must unwind to a CatchPadInst or a CatchEndPadInst.",
+ &CPI);
+
+ visitTerminatorInst(CPI);
+}
+
+void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) {
+ BasicBlock *BB = CEPI.getParent();
+
+ Function *F = BB->getParent();
+ Assert(F->hasPersonalityFn(),
+ "CatchEndPadInst needs to be in a function with a personality.",
+ &CEPI);
+
+ // The catchendpad instruction must be the first non-PHI instruction in the
+ // block.
+ Assert(BB->getFirstNonPHI() == &CEPI,
+ "CatchEndPadInst not the first non-PHI instruction in the block.",
+ &CEPI);
+
+ unsigned CatchPadsSeen = 0;
+ for (BasicBlock *PredBB : predecessors(BB))
+ if (isa<CatchPadInst>(PredBB->getTerminator()))
+ ++CatchPadsSeen;
+
+ Assert(CatchPadsSeen <= 1, "CatchEndPadInst must have no more than one "
+ "CatchPadInst predecessor.",
+ &CEPI);
+
+ if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) {
+ Instruction *I = UnwindDest->getFirstNonPHI();
+ Assert(
+ I->isEHPad() && !isa<LandingPadInst>(I),
+ "CatchEndPad must unwind to an EH block which is not a landingpad.",
+ &CEPI);
+ }
+
+ visitTerminatorInst(CEPI);
+}
+
+void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
+ BasicBlock *BB = CPI.getParent();
+
+ if (!CleanupPadResultTy)
+ CleanupPadResultTy = CPI.getType();
+ else
+ Assert(CleanupPadResultTy == CPI.getType(),
+ "The cleanuppad instruction should have a consistent result type "
+ "inside a function.",
+ &CPI);
+
+ Function *F = BB->getParent();
+ Assert(F->hasPersonalityFn(),
+ "CleanupPadInst needs to be in a function with a personality.", &CPI);
+
+ // The cleanuppad instruction must be the first non-PHI instruction in the
+ // block.
+ Assert(BB->getFirstNonPHI() == &CPI,
+ "CleanupPadInst not the first non-PHI instruction in the block.",
+ &CPI);
+
+ visitInstruction(CPI);
+}
+
+void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
+ if (BasicBlock *UnwindDest = CRI.getUnwindDest()) {
+ Instruction *I = UnwindDest->getFirstNonPHI();
+ Assert(I->isEHPad() && !isa<LandingPadInst>(I),
+ "CleanupReturnInst must unwind to an EH block which is not a "
+ "landingpad.",
+ &CRI);
+ }
+
+ visitTerminatorInst(CRI);
+}
+
+void Verifier::visitTerminatePadInst(TerminatePadInst &TPI) {
+ BasicBlock *BB = TPI.getParent();
+
+ Function *F = BB->getParent();
+ Assert(F->hasPersonalityFn(),
+ "TerminatePadInst needs to be in a function with a personality.",
+ &TPI);
+
+ // The terminatepad instruction must be the first non-PHI instruction in the
+ // block.
+ Assert(BB->getFirstNonPHI() == &TPI,
+ "TerminatePadInst not the first non-PHI instruction in the block.",
+ &TPI);
+
+ if (BasicBlock *UnwindDest = TPI.getUnwindDest()) {
+ Instruction *I = UnwindDest->getFirstNonPHI();
+ Assert(I->isEHPad() && !isa<LandingPadInst>(I),
+ "TerminatePadInst must unwind to an EH block which is not a "
+ "landingpad.",
+ &TPI);
+ }
+
+ visitTerminatorInst(TPI);
+}
+
void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
Instruction *Op = cast<Instruction>(I.getOperand(i));
// If the we have an invalid invoke, don't try to compute the dominance.
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 42c20339d5a..226876d407c 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2653,6 +2653,30 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
setOrigin(&I, getCleanOrigin());
}
+ void visitCleanupPadInst(CleanupPadInst &I) {
+ if (!I.getType()->isVoidTy()) {
+ setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
+ }
+ }
+
+ void visitCatchPad(CatchPadInst &I) {
+ if (!I.getType()->isVoidTy()) {
+ setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
+ }
+ }
+
+ void visitTerminatePad(TerminatePadInst &I) {
+ DEBUG(dbgs() << "TerminatePad: " << I << "\n");
+ // Nothing to do here.
+ }
+
+ void visitCatchEndPadInst(CatchEndPadInst &I) {
+ DEBUG(dbgs() << "CatchEndPad: " << I << "\n");
+ // Nothing to do here.
+ }
+
void visitGetElementPtrInst(GetElementPtrInst &I) {
handleShadowOr(I);
}
@@ -2696,6 +2720,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// Nothing to do here.
}
+ void visitCleanupReturnInst(CleanupReturnInst &CRI) {
+ DEBUG(dbgs() << "CleanupReturn: " << CRI << "\n");
+ // Nothing to do here.
+ }
+
+ void visitCatchReturnInst(CatchReturnInst &CRI) {
+ DEBUG(dbgs() << "CatchReturn: " << CRI << "\n");
+ // Nothing to do here.
+ }
+
void visitInstruction(Instruction &I) {
// Everything else: stop propagating and check for poisoned shadow.
if (ClDumpStrictInstructions)
diff --git a/llvm/lib/Transforms/Scalar/ADCE.cpp b/llvm/lib/Transforms/Scalar/ADCE.cpp
index d6fc9164158..824342ad7e3 100644
--- a/llvm/lib/Transforms/Scalar/ADCE.cpp
+++ b/llvm/lib/Transforms/Scalar/ADCE.cpp
@@ -58,8 +58,8 @@ bool ADCE::runOnFunction(Function& F) {
// Collect the set of "root" instructions that are known live.
for (Instruction &I : inst_range(F)) {
- if (isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
- isa<LandingPadInst>(I) || I.mayHaveSideEffects()) {
+ if (isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || I.isEHPad() ||
+ I.mayHaveSideEffects()) {
Alive.insert(&I);
Worklist.push_back(&I);
}
diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index 09c605e7673..7252db0a6cd 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -77,8 +77,8 @@ INITIALIZE_PASS_END(BDCE, "bdce", "Bit-Tracking Dead Code Elimination",
false, false)
static bool isAlwaysLive(Instruction *I) {
- return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) ||
- isa<LandingPadInst>(I) || I->mayHaveSideEffects();
+ return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || I->isEHPad() ||
+ I->mayHaveSideEffects();
}
void BDCE::determineLiveOperandBits(const Instruction *UserI,
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 1130d228acb..e845a7f586b 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -669,7 +669,8 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
// because now the condition in this block can be threaded through
// predecessors of our predecessor block.
if (BasicBlock *SinglePred = BB->getSinglePredecessor()) {
- if (SinglePred->getTerminator()->getNumSuccessors() == 1 &&
+ const TerminatorInst *TI = SinglePred->getTerminator();
+ if (!TI->isExceptional() && TI->getNumSuccessors() == 1 &&
SinglePred != BB && !hasAddressTakenAndUsed(BB)) {
// If SinglePred was a loop header, BB becomes one.
if (LoopHeaders.erase(SinglePred))
diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp
index 4d3a708fa20..c625b0f3362 100644
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp
@@ -539,9 +539,9 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
return;
}
- if (isa<InvokeInst>(TI)) {
- // Invoke instructions successors are always executable.
- Succs[0] = Succs[1] = true;
+ // Unwinding instructions successors are always executable.
+ if (TI.isExceptional()) {
+ Succs.assign(TI.getNumSuccessors(), true);
return;
}
@@ -605,8 +605,8 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
return BI->getSuccessor(CI->isZero()) == To;
}
- // Invoke instructions successors are always executable.
- if (isa<InvokeInst>(TI))
+ // Unwinding instructions successors are always executable.
+ if (TI->isExceptional())
return true;
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 74ca0a1aa18..1bf92e35abc 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -117,8 +117,9 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT,
// Don't break self-loops.
if (PredBB == BB) return false;
- // Don't break invokes.
- if (isa<InvokeInst>(PredBB->getTerminator())) return false;
+ // Don't break unwinding instructions.
+ if (PredBB->getTerminator()->isExceptional())
+ return false;
succ_iterator SI(succ_begin(PredBB)), SE(succ_end(PredBB));
BasicBlock *OnlySucc = BB;
@@ -283,7 +284,7 @@ llvm::SplitAllCriticalEdges(Function &F,
BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
DominatorTree *DT, LoopInfo *LI) {
BasicBlock::iterator SplitIt = SplitPt;
- while (isa<PHINode>(SplitIt) || isa<LandingPadInst>(SplitIt))
+ while (isa<PHINode>(SplitIt) || SplitIt->isEHPad())
++SplitIt;
BasicBlock *New = Old->splitBasicBlock(SplitIt, Old->getName()+".split");
@@ -474,6 +475,10 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix, DominatorTree *DT,
LoopInfo *LI, bool PreserveLCSSA) {
+ // Do not attempt to split that which cannot be split.
+ if (!BB->canSplitPredecessors())
+ return nullptr;
+
// For the landingpads we need to act a bit differently.
// Delegate this work to the SplitLandingPadPredecessors.
if (BB->isLandingPad()) {
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index c970a2d9e47..a7515bbf961 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -63,8 +63,8 @@ bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
}
namespace {
- /// A class for recording information about inlining through an invoke.
- class InvokeInliningInfo {
+ /// A class for recording information about inlining a landing pad.
+ class LandingPadInliningInfo {
BasicBlock *OuterResumeDest; ///< Destination of the invoke's unwind.
BasicBlock *InnerResumeDest; ///< Destination for the callee's resume.
LandingPadInst *CallerLPad; ///< LandingPadInst associated with the invoke.
@@ -72,7 +72,7 @@ namespace {
SmallVector<Value*, 8> UnwindDestPHIValues;
public:
- InvokeInliningInfo(InvokeInst *II)
+ LandingPadInliningInfo(InvokeInst *II)
: OuterResumeDest(II->getUnwindDest()), InnerResumeDest(nullptr),
CallerLPad(nullptr), InnerEHValuesPHI(nullptr) {
// If there are PHI nodes in the unwind destination block, we need to keep
@@ -124,7 +124,7 @@ namespace {
}
/// Get or create a target for the branch from ResumeInsts.
-BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
+BasicBlock *LandingPadInliningInfo::getInnerResumeDest() {
if (InnerResumeDest) return InnerResumeDest;
// Split the landing pad.
@@ -162,8 +162,8 @@ BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
/// When the landing pad block has only one predecessor, this is a simple
/// branch. When there is more than one predecessor, we need to split the
/// landing pad block after the landingpad instruction and jump to there.
-void InvokeInliningInfo::forwardResume(ResumeInst *RI,
- SmallPtrSetImpl<LandingPadInst*> &InlinedLPads) {
+void LandingPadInliningInfo::forwardResume(
+ ResumeInst *RI, SmallPtrSetImpl<LandingPadInst *> &InlinedLPads) {
BasicBlock *Dest = getInnerResumeDest();
BasicBlock *Src = RI->getParent();
@@ -182,8 +182,8 @@ void InvokeInliningInfo::forwardResume(ResumeInst *RI,
/// This function analyze BB to see if there are any calls, and if so,
/// it rewrites them to be invokes that jump to InvokeDest and fills in the PHI
/// nodes in that block with the values specified in InvokeDestPHIValues.
-static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
- InvokeInliningInfo &Invoke) {
+static BasicBlock *
+HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, BasicBlock *UnwindEdge) {
for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
Instruction *I = BBI++;
@@ -206,8 +206,7 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
// Create the new invoke instruction.
ImmutableCallSite CS(CI);
SmallVector<Value*, 8> InvokeArgs(CS.arg_begin(), CS.arg_end());
- InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split,
- Invoke.getOuterResumeDest(),
+ InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split, UnwindEdge,
InvokeArgs, CI->getName(), BB);
II->setDebugLoc(CI->getDebugLoc());
II->setCallingConv(CI->getCallingConv());
@@ -219,12 +218,9 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
// Delete the original call
Split->getInstList().pop_front();
-
- // Update any PHI nodes in the exceptional block to indicate that there is
- // now a new entry in them.
- Invoke.addIncomingPHIValuesFor(BB);
- return;
+ return BB;
}
+ return nullptr;
}
/// If we inlined an invoke site, we need to convert calls
@@ -233,8 +229,8 @@ static void HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
/// II is the invoke instruction being inlined. FirstNewBlock is the first
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
-static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
- ClonedCodeInfo &InlinedCodeInfo) {
+static void HandleInlinedLandingPad(InvokeInst *II, BasicBlock *FirstNewBlock,
+ ClonedCodeInfo &InlinedCodeInfo) {
BasicBlock *InvokeDest = II->getUnwindDest();
Function *Caller = FirstNewBlock->getParent();
@@ -242,7 +238,7 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
// The inlined code is currently at the end of the function, scan from the
// start of the inlined code to its end, checking for stuff we need to
// rewrite.
- InvokeInliningInfo Invoke(II);
+ LandingPadInliningInfo Invoke(II);
// Get all of the inlined landing pad instructions.
SmallPtrSet<LandingPadInst*, 16> InlinedLPads;
@@ -264,7 +260,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB){
if (InlinedCodeInfo.ContainsCalls)
- HandleCallsInBlockInlinedThroughInvoke(BB, Invoke);
+ if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
+ BB, Invoke.getOuterResumeDest()))
+ // Update any PHI nodes in the exceptional block to indicate that there
+ // is now a new entry in them.
+ Invoke.addIncomingPHIValuesFor(NewBB);
// Forward any resumes that are remaining here.
if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator()))
@@ -278,6 +278,102 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
InvokeDest->removePredecessor(II->getParent());
}
+/// If we inlined an invoke site, we need to convert calls
+/// in the body of the inlined function into invokes.
+///
+/// II is the invoke instruction being inlined. FirstNewBlock is the first
+/// block of the inlined code (the last block is the end of the function),
+/// and InlineCodeInfo is information about the code that got inlined.
+static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
+ ClonedCodeInfo &InlinedCodeInfo) {
+ BasicBlock *UnwindDest = II->getUnwindDest();
+ Function *Caller = FirstNewBlock->getParent();
+
+ assert(UnwindDest->getFirstNonPHI()->isEHPad() && "unexpected BasicBlock!");
+
+ // If there are PHI nodes in the unwind destination block, we need to keep
+ // track of which values came into them from the invoke before removing the
+ // edge from this block.
+ SmallVector<Value *, 8> UnwindDestPHIValues;
+ llvm::BasicBlock *InvokeBB = II->getParent();
+ for (Instruction &I : *UnwindDest) {
+ // Save the value to use for this edge.
+ PHINode *PHI = dyn_cast<PHINode>(&I);
+ if (!PHI)
+ break;
+ UnwindDestPHIValues.push_back(PHI->getIncomingValueForBlock(InvokeBB));
+ }
+
+ // Add incoming-PHI values to the unwind destination block for the given basic
+ // block, using the values for the original invoke's source block.
+ auto UpdatePHINodes = [&](BasicBlock *Src) {
+ BasicBlock::iterator I = UnwindDest->begin();
+ for (Value *V : UnwindDestPHIValues) {
+ PHINode *PHI = cast<PHINode>(I);
+ PHI->addIncoming(V, Src);
+ ++I;
+ }
+ };
+
+ // Forward EH terminator instructions to the caller's invoke destination.
+ // This is as simple as connect all the instructions which 'unwind to caller'
+ // to the invoke destination.
+ for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
+ ++BB) {
+ Instruction *I = BB->getFirstNonPHI();
+ if (I->isEHPad()) {
+ if (auto *CEPI = dyn_cast<CatchEndPadInst>(I)) {
+ if (CEPI->unwindsToCaller()) {
+ CatchEndPadInst::Create(CEPI->getContext(), UnwindDest, CEPI);
+ CEPI->eraseFromParent();
+ UpdatePHINodes(BB);
+ }
+ } else if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
+ if (TPI->unwindsToCaller()) {
+ SmallVector<Value *, 3> TerminatePadArgs;
+ for (Value *Operand : TPI->operands())
+ TerminatePadArgs.push_back(Operand);
+ TerminatePadInst::Create(TPI->getContext(), UnwindDest, TPI);
+ TPI->eraseFromParent();
+ UpdatePHINodes(BB);
+ }
+ } else if (auto *CPI = dyn_cast<CleanupPadInst>(I)) {
+ if (CPI->getNumOperands() == 0) {
+ CleanupPadInst::Create(CPI->getType(), {UnwindDest}, CPI->getName(),
+ CPI);
+ CPI->eraseFromParent();
+ }
+ } else {
+ assert(isa<CatchPadInst>(I));
+ }
+ }
+
+ if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) {
+ if (CRI->unwindsToCaller()) {
+ CleanupReturnInst::Create(CRI->getContext(), CRI->getReturnValue(),
+ UnwindDest, CRI);
+ CRI->eraseFromParent();
+ UpdatePHINodes(BB);
+ }
+ }
+ }
+
+ if (InlinedCodeInfo.ContainsCalls)
+ for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
+ ++BB)
+ if (BasicBlock *NewBB =
+ HandleCallsInBlockInlinedThroughInvoke(BB, UnwindDest))
+ // Update any PHI nodes in the exceptional block to indicate that there
+ // is now a new entry in them.
+ UpdatePHINodes(NewBB);
+
+ // Now that everything is happy, we have one final detail. The PHI nodes in
+ // the exception destination block still have entries due to the original
+ // invoke instruction. Eliminate these entries (which might even delete the
+ // PHI node) now.
+ UnwindDest->removePredecessor(InvokeBB);
+}
+
/// When inlining a function that contains noalias scope metadata,
/// this metadata needs to be cloned so that the inlined blocks
/// have different "unqiue scopes" at every call site. Were this not done, then
@@ -1204,8 +1300,15 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
// If we are inlining for an invoke instruction, we must make sure to rewrite
// any call instructions into invoke instructions.
- if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall))
- HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo);
+ if (auto *II = dyn_cast<InvokeInst>(TheCall)) {
+ BasicBlock *UnwindDest = II->getUnwindDest();
+ Instruction *FirstNonPHI = UnwindDest->getFirstNonPHI();
+ if (isa<LandingPadInst>(FirstNonPHI)) {
+ HandleInlinedLandingPad(II, FirstNewBlock, InlinedFunctionInfo);
+ } else {
+ HandleInlinedEHPad(II, FirstNewBlock, InlinedFunctionInfo);
+ }
+ }
// Handle any inlined musttail call sites. In order for a new call site to be
// musttail, the source of the clone and the inlined call site must have been
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 50ca6234d0b..71a55d495d5 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -283,8 +283,9 @@ bool llvm::isInstructionTriviallyDead(Instruction *I,
const TargetLibraryInfo *TLI) {
if (!I->use_empty() || isa<TerminatorInst>(I)) return false;
- // We don't want the landingpad instruction removed by anything this general.
- if (isa<LandingPadInst>(I))
+ // We don't want the landingpad-like instructions removed by anything this
+ // general.
+ if (I->isEHPad())
return false;
// We don't want debug info removed by anything this general, unless
diff --git a/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/llvm/lib/Transforms/Utils/LoopSimplify.cpp
index 11d7a21d3ce..1298011e78a 100644
--- a/llvm/lib/Transforms/Utils/LoopSimplify.cpp
+++ b/llvm/lib/Transforms/Utils/LoopSimplify.cpp
@@ -142,6 +142,8 @@ BasicBlock *llvm::InsertPreheaderForLoop(Loop *L, Pass *PP) {
BasicBlock *PreheaderBB;
PreheaderBB = SplitBlockPredecessors(Header, OutsideBlocks, ".preheader", DT,
LI, PreserveLCSSA);
+ if (!PreheaderBB)
+ return nullptr;
DEBUG(dbgs() << "LoopSimplify: Creating pre-header "
<< PreheaderBB->getName() << "\n");
@@ -178,6 +180,8 @@ static BasicBlock *rewriteLoopExitBlock(Loop *L, BasicBlock *Exit,
NewExitBB = SplitBlockPredecessors(Exit, LoopBlocks, ".loopexit", DT, LI,
PreserveLCSSA);
+ if (!NewExitBB)
+ return nullptr;
DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "
<< NewExitBB->getName() << "\n");
@@ -256,8 +260,10 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
return nullptr;
// The header is not a landing pad; preheader insertion should ensure this.
- assert(!L->getHeader()->isLandingPad() &&
- "Can't insert backedge to landing pad");
+ BasicBlock *Header = L->getHeader();
+ assert(!Header->isLandingPad() && "Can't insert backedge to landing pad");
+ if (!Header->canSplitPredecessors())
+ return nullptr;
PHINode *PN = findPHIToPartitionLoops(L, DT, AC);
if (!PN) return nullptr; // No known way to partition.
@@ -285,7 +291,6 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
bool PreserveLCSSA = PP->mustPreserveAnalysisID(LCSSAID);
- BasicBlock *Header = L->getHeader();
BasicBlock *NewBB = SplitBlockPredecessors(Header, OuterLoopPreds, ".outer",
DT, LI, PreserveLCSSA);
OpenPOWER on IntegriCloud