diff options
author | Andrew Kaylor <andrew.kaylor@intel.com> | 2015-11-23 19:51:41 +0000 |
---|---|---|
committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2015-11-23 19:51:41 +0000 |
commit | 0615a0e65dd1da8941eda4db8d2d65ea02f40976 (patch) | |
tree | 95ede5940e885076b19800ca9fa4afacc106fd18 | |
parent | d200b27f08f9a2c00a6937eaeb610df1490fa805 (diff) | |
download | bcm5719-llvm-0615a0e65dd1da8941eda4db8d2d65ea02f40976.tar.gz bcm5719-llvm-0615a0e65dd1da8941eda4db8d2d65ea02f40976.zip |
[WinEH] Fix a case where GVN could incorrectly PRE a load into an EH pad.
Differential Revision: http://reviews.llvm.org/D14842
llvm-svn: 253908
-rw-r--r-- | llvm/lib/Transforms/Scalar/GVN.cpp | 10 | ||||
-rw-r--r-- | llvm/test/Transforms/GVN/pre-load.ll | 47 |
2 files changed, 57 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 1f9630ed511..3e5f5360372 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1555,6 +1555,16 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock, for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB); PI != E; ++PI) { BasicBlock *Pred = *PI; + + // If any predecessor block is an EH pad that does not allow non-PHI + // instructions before the terminator, we can't PRE the load. + if (Pred->getTerminator()->isEHPad()) { + DEBUG(dbgs() + << "COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '" + << Pred->getName() << "': " << *LI << '\n'); + return false; + } + if (IsValueFullyAvailableInBlock(Pred, FullyAvailableBlocks, 0)) { continue; } diff --git a/llvm/test/Transforms/GVN/pre-load.ll b/llvm/test/Transforms/GVN/pre-load.ll index 24221d540f2..c165a5a4932 100644 --- a/llvm/test/Transforms/GVN/pre-load.ll +++ b/llvm/test/Transforms/GVN/pre-load.ll @@ -389,3 +389,50 @@ block5: ; CHECK: block4: ; CHECK-NEXT: phi i32 } + +declare void @f() +declare void @g(i32) +declare i32 @__CxxFrameHandler3(...) + +; Test that loads aren't PRE'd into EH pads. +define void @test12(i32* %p) personality i32 (...)* @__CxxFrameHandler3 { +; CHECK-LABEL: @test12( +block1: + invoke void @f() + to label %block2 unwind label %catch + +block2: + invoke void @f() + to label %block3 unwind label %cleanup + +block3: + ret void + +catch: + %c = catchpad [] + to label %catch.dispatch unwind label %catchend + +catch.dispatch: + catchret %c to label %block2 + +; CHECK: catchend: +; CHECK-NOT: load +; CHECK-NEXT: catchendpad +catchend: + catchendpad unwind label %cleanup2 + +cleanup: + %c1 = cleanuppad [] + store i32 0, i32* %p + cleanupret %c1 unwind label %cleanup2 + +; CHECK: cleanup2: +; CHECK-NOT: phi +; CHECK-NEXT: %c2 = cleanuppad [] +; CHECK-NEXT: %NOTPRE = load i32, i32* %p +cleanup2: + %c2 = cleanuppad [] + %NOTPRE = load i32, i32* %p + call void @g(i32 %NOTPRE) + cleanupret %c2 unwind to caller +} |