From 704489d52e8a2e9f62b478b8a3d3612bfe03bfc5 Mon Sep 17 00:00:00 2001 From: Andrew Kaylor Date: Mon, 23 Nov 2015 19:51:41 +0000 Subject: [PATCH] [WinEH] Fix a case where GVN could incorrectly PRE a load into an EH pad. Differential Revision: http://reviews.llvm.org/D14842 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253908 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/GVN.cpp | 10 +++++++ test/Transforms/GVN/pre-load.ll | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 1f9630ed511..3e5f5360372 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/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/test/Transforms/GVN/pre-load.ll b/test/Transforms/GVN/pre-load.ll index 24221d540f2..c165a5a4932 100644 --- a/test/Transforms/GVN/pre-load.ll +++ b/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 +} -- 2.34.1