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

Commit c89bf67

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 (cherry picked from commit 35741b0)
1 parent 662f9f5 commit c89bf67

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
@@ -991,17 +991,15 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
991991
continue;
992992

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

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

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

unittests/Transforms/Utils/CodeExtractor.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)