summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Transforms
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2018-12-07 03:01:54 +0000
committerVedant Kumar <vsk@apple.com>2018-12-07 03:01:54 +0000
commitb2a6f8e505b105c733d931e1ed0513d7ea94f6c8 (patch)
tree1e58c4acf583de190493ad34ec95af79996ae95a /llvm/unittests/Transforms
parent5fa736cc193968d59286e94b8b49e983d9e72384 (diff)
downloadbcm5719-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.cpp68
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
OpenPOWER on IntegriCloud