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/unittests/Transforms | |
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/unittests/Transforms')
-rw-r--r-- | llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp b/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp index 42448fd8fd0..7e3512f56f3 100644 --- a/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp +++ b/llvm/unittests/Transforms/Utils/CodeExtractorTest.cpp @@ -127,4 +127,72 @@ TEST(CodeExtractor, ExitPHIOnePredFromRegion) { EXPECT_FALSE(verifyFunction(*Outlined)); EXPECT_FALSE(verifyFunction(*Func)); } + +TEST(CodeExtractor, StoreOutputInvokeResultAfterEHPad) { + LLVMContext Ctx; + SMDiagnostic Err; + std::unique_ptr<Module> M(parseAssemblyString(R"invalid( + declare i8 @hoge() + + define i32 @foo() personality i8* null { + entry: + %call = invoke i8 @hoge() + to label %invoke.cont unwind label %lpad + + invoke.cont: ; preds = %entry + unreachable + + lpad: ; preds = %entry + %0 = landingpad { i8*, i32 } + catch i8* null + br i1 undef, label %catch, label %finally.catchall + + catch: ; preds = %lpad + %call2 = invoke i8 @hoge() + to label %invoke.cont2 unwind label %lpad2 + + invoke.cont2: ; preds = %catch + %call3 = invoke i8 @hoge() + to label %invoke.cont3 unwind label %lpad2 + + invoke.cont3: ; preds = %invoke.cont2 + unreachable + + lpad2: ; preds = %invoke.cont2, %catch + %ex.1 = phi i8* [ undef, %invoke.cont2 ], [ null, %catch ] + %1 = landingpad { i8*, i32 } + catch i8* null + br label %finally.catchall + + finally.catchall: ; preds = %lpad33, %lpad + %ex.2 = phi i8* [ %ex.1, %lpad2 ], [ null, %lpad ] + unreachable + } + )invalid", Err, Ctx)); + + if (!M) { + Err.print("unit", errs()); + exit(1); + } + + Function *Func = M->getFunction("foo"); + EXPECT_FALSE(verifyFunction(*Func, &errs())); + + SmallVector<BasicBlock *, 2> ExtractedBlocks{ + getBlockByName(Func, "catch"), + getBlockByName(Func, "invoke.cont2"), + getBlockByName(Func, "invoke.cont3"), + getBlockByName(Func, "lpad2") + }; + + DominatorTree DT(*Func); + CodeExtractor CE(ExtractedBlocks, &DT); + EXPECT_TRUE(CE.isEligible()); + + Function *Outlined = CE.extractCodeRegion(); + EXPECT_TRUE(Outlined); + EXPECT_FALSE(verifyFunction(*Outlined, &errs())); + EXPECT_FALSE(verifyFunction(*Func, &errs())); +} + } // end anonymous namespace |