Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 35741b0

Browse files
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@348562 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 2b0c69e commit 35741b0

File tree

2 files changed

+80
-12
lines changed

2 files changed

+80
-12
lines changed

lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -992,17 +992,15 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
992992
continue;
993993

994994
// Find proper insertion point.
995-
Instruction *InsertPt;
995+
BasicBlock::iterator InsertPt;
996996
// In case OutI is an invoke, we insert the store at the beginning in the
997997
// 'normal destination' BB. Otherwise we insert the store right after OutI.
998998
if (auto *InvokeI = dyn_cast<InvokeInst>(OutI))
999-
InsertPt = InvokeI->getNormalDest()->getFirstNonPHI();
999+
InsertPt = InvokeI->getNormalDest()->getFirstInsertionPt();
1000+
else if (auto *Phi = dyn_cast<PHINode>(OutI))
1001+
InsertPt = Phi->getParent()->getFirstInsertionPt();
10001002
else
1001-
InsertPt = OutI->getNextNode();
1002-
1003-
// Let's assume that there is no other guy interleave non-PHI in PHIs.
1004-
if (isa<PHINode>(InsertPt))
1005-
InsertPt = InsertPt->getParent()->getFirstNonPHI();
1003+
InsertPt = std::next(OutI->getIterator());
10061004

10071005
assert(OAI != newFunction->arg_end() &&
10081006
"Number of output arguments should match "
@@ -1012,13 +1010,13 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
10121010
Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context));
10131011
Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), FirstOut + i);
10141012
GetElementPtrInst *GEP = GetElementPtrInst::Create(
1015-
StructArgTy, &*OAI, Idx, "gep_" + outputs[i]->getName(), InsertPt);
1016-
new StoreInst(outputs[i], GEP, InsertPt);
1013+
StructArgTy, &*OAI, Idx, "gep_" + outputs[i]->getName(), &*InsertPt);
1014+
new StoreInst(outputs[i], GEP, &*InsertPt);
10171015
// Since there should be only one struct argument aggregating
10181016
// all the output values, we shouldn't increment OAI, which always
10191017
// points to the struct argument, in this case.
10201018
} else {
1021-
new StoreInst(outputs[i], &*OAI, InsertPt);
1019+
new StoreInst(outputs[i], &*OAI, &*InsertPt);
10221020
++OAI;
10231021
}
10241022
}
@@ -1379,8 +1377,10 @@ Function *CodeExtractor::extractCodeRegion() {
13791377
if (doesNotReturn)
13801378
newFunction->setDoesNotReturn();
13811379

1382-
LLVM_DEBUG(if (verifyFunction(*newFunction))
1383-
report_fatal_error("verification of newFunction failed!"));
1380+
LLVM_DEBUG(if (verifyFunction(*newFunction, &errs())) {
1381+
newFunction->dump();
1382+
report_fatal_error("verification of newFunction failed!");
1383+
});
13841384
LLVM_DEBUG(if (verifyFunction(*oldFunction))
13851385
report_fatal_error("verification of oldFunction failed!"));
13861386
return newFunction;

unittests/Transforms/Utils/CodeExtractorTest.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,72 @@ TEST(CodeExtractor, ExitPHIOnePredFromRegion) {
127127
EXPECT_FALSE(verifyFunction(*Outlined));
128128
EXPECT_FALSE(verifyFunction(*Func));
129129
}
130+
131+
TEST(CodeExtractor, StoreOutputInvokeResultAfterEHPad) {
132+
LLVMContext Ctx;
133+
SMDiagnostic Err;
134+
std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
135+
declare i8 @hoge()
136+
137+
define i32 @foo() personality i8* null {
138+
entry:
139+
%call = invoke i8 @hoge()
140+
to label %invoke.cont unwind label %lpad
141+
142+
invoke.cont: ; preds = %entry
143+
unreachable
144+
145+
lpad: ; preds = %entry
146+
%0 = landingpad { i8*, i32 }
147+
catch i8* null
148+
br i1 undef, label %catch, label %finally.catchall
149+
150+
catch: ; preds = %lpad
151+
%call2 = invoke i8 @hoge()
152+
to label %invoke.cont2 unwind label %lpad2
153+
154+
invoke.cont2: ; preds = %catch
155+
%call3 = invoke i8 @hoge()
156+
to label %invoke.cont3 unwind label %lpad2
157+
158+
invoke.cont3: ; preds = %invoke.cont2
159+
unreachable
160+
161+
lpad2: ; preds = %invoke.cont2, %catch
162+
%ex.1 = phi i8* [ undef, %invoke.cont2 ], [ null, %catch ]
163+
%1 = landingpad { i8*, i32 }
164+
catch i8* null
165+
br label %finally.catchall
166+
167+
finally.catchall: ; preds = %lpad33, %lpad
168+
%ex.2 = phi i8* [ %ex.1, %lpad2 ], [ null, %lpad ]
169+
unreachable
170+
}
171+
)invalid", Err, Ctx));
172+
173+
if (!M) {
174+
Err.print("unit", errs());
175+
exit(1);
176+
}
177+
178+
Function *Func = M->getFunction("foo");
179+
EXPECT_FALSE(verifyFunction(*Func, &errs()));
180+
181+
SmallVector<BasicBlock *, 2> ExtractedBlocks{
182+
getBlockByName(Func, "catch"),
183+
getBlockByName(Func, "invoke.cont2"),
184+
getBlockByName(Func, "invoke.cont3"),
185+
getBlockByName(Func, "lpad2")
186+
};
187+
188+
DominatorTree DT(*Func);
189+
CodeExtractor CE(ExtractedBlocks, &DT);
190+
EXPECT_TRUE(CE.isEligible());
191+
192+
Function *Outlined = CE.extractCodeRegion();
193+
EXPECT_TRUE(Outlined);
194+
EXPECT_FALSE(verifyFunction(*Outlined, &errs()));
195+
EXPECT_FALSE(verifyFunction(*Func, &errs()));
196+
}
197+
130198
} // end anonymous namespace

0 commit comments

Comments
 (0)