diff options
author | Vedant Kumar <vsk@apple.com> | 2018-12-07 03:01:54 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2018-12-07 03:01:54 +0000 |
commit | b2a6f8e505b105c733d931e1ed0513d7ea94f6c8 (patch) | |
tree | 1e58c4acf583de190493ad34ec95af79996ae95a /llvm/lib/Transforms/Utils | |
parent | 5fa736cc193968d59286e94b8b49e983d9e72384 (diff) | |
download | bcm5719-llvm-b2a6f8e505b105c733d931e1ed0513d7ea94f6c8.tar.gz bcm5719-llvm-b2a6f8e505b105c733d931e1ed0513d7ea94f6c8.zip |
[CodeExtractor] Store outputs at the first valid insertion point
When CodeExtractor outlines values which are used by the original
function, it must store those values in some in-out parameter. This
store instruction must not be inserted in between a PHI and an EH pad
instruction, as that results in invalid IR.
This fixes the following verifier failure seen while outlining within
ObjC methods with live exit values:
The unwind destination does not have an exception handling instruction!
%call35 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %exn.adjusted, i8* %1)
to label %invoke.cont34 unwind label %lpad33, !dbg !4183
The unwind destination does not have an exception handling instruction!
invoke void @objc_exception_throw(i8* %call35) #12
to label %invoke.cont36 unwind label %lpad33, !dbg !4184
LandingPadInst not the first non-PHI instruction in the block.
%3 = landingpad { i8*, i32 }
catch i8* null, !dbg !1411
rdar://46540815
llvm-svn: 348562
Diffstat (limited to 'llvm/lib/Transforms/Utils')
-rw-r--r-- | llvm/lib/Transforms/Utils/CodeExtractor.cpp | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index dbcee9e5755..a6b01107752 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -992,17 +992,15 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, continue; // Find proper insertion point. - Instruction *InsertPt; + BasicBlock::iterator InsertPt; // In case OutI is an invoke, we insert the store at the beginning in the // 'normal destination' BB. Otherwise we insert the store right after OutI. if (auto *InvokeI = dyn_cast<InvokeInst>(OutI)) - InsertPt = InvokeI->getNormalDest()->getFirstNonPHI(); + InsertPt = InvokeI->getNormalDest()->getFirstInsertionPt(); + else if (auto *Phi = dyn_cast<PHINode>(OutI)) + InsertPt = Phi->getParent()->getFirstInsertionPt(); else - InsertPt = OutI->getNextNode(); - - // Let's assume that there is no other guy interleave non-PHI in PHIs. - if (isa<PHINode>(InsertPt)) - InsertPt = InsertPt->getParent()->getFirstNonPHI(); + InsertPt = std::next(OutI->getIterator()); assert(OAI != newFunction->arg_end() && "Number of output arguments should match " @@ -1012,13 +1010,13 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context)); Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), FirstOut + i); GetElementPtrInst *GEP = GetElementPtrInst::Create( - StructArgTy, &*OAI, Idx, "gep_" + outputs[i]->getName(), InsertPt); - new StoreInst(outputs[i], GEP, InsertPt); + StructArgTy, &*OAI, Idx, "gep_" + outputs[i]->getName(), &*InsertPt); + new StoreInst(outputs[i], GEP, &*InsertPt); // Since there should be only one struct argument aggregating // all the output values, we shouldn't increment OAI, which always // points to the struct argument, in this case. } else { - new StoreInst(outputs[i], &*OAI, InsertPt); + new StoreInst(outputs[i], &*OAI, &*InsertPt); ++OAI; } } @@ -1379,8 +1377,10 @@ Function *CodeExtractor::extractCodeRegion() { if (doesNotReturn) newFunction->setDoesNotReturn(); - LLVM_DEBUG(if (verifyFunction(*newFunction)) - report_fatal_error("verification of newFunction failed!")); + LLVM_DEBUG(if (verifyFunction(*newFunction, &errs())) { + newFunction->dump(); + report_fatal_error("verification of newFunction failed!"); + }); LLVM_DEBUG(if (verifyFunction(*oldFunction)) report_fatal_error("verification of oldFunction failed!")); return newFunction; |