[WinEH] Fix a case where GVN could incorrectly PRE a load into an EH pad.
authorAndrew Kaylor <andrew.kaylor@intel.com>
Mon, 23 Nov 2015 19:51:41 +0000 (19:51 +0000)
committerAndrew Kaylor <andrew.kaylor@intel.com>
Mon, 23 Nov 2015 19:51:41 +0000 (19:51 +0000)
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
test/Transforms/GVN/pre-load.ll

index 1f9630ed511409274bc4babbfc61ec8a42b697d0..3e5f53603720915e2a2bbf09f2c6ec7185b38979 100644 (file)
@@ -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;
     }
index 24221d540f22ca675c772a9b938ad738e73fffca..c165a5a49325c7823ba25b23a9d343f72de11757 100644 (file)
@@ -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
+}