[llvm] r245238 - [WinEHPrepare] Replace unreasonable funclet terminators with unreachable

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 17 13:56:40 PDT 2015


Author: majnemer
Date: Mon Aug 17 15:56:39 2015
New Revision: 245238

URL: http://llvm.org/viewvc/llvm-project?rev=245238&view=rev
Log:
[WinEHPrepare] Replace unreasonable funclet terminators with unreachable

It is possible to be in a situation where more than one funclet token is
a valid SSA value.  If we see a terminator which exits a funclet which
doesn't use the funclet's token, replace it with unreachable.

Differential Revision: http://reviews.llvm.org/D12074

Modified:
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=245238&r1=245237&r2=245238&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Mon Aug 17 15:56:39 2015
@@ -3085,6 +3085,33 @@ bool WinEHPrepare::prepareExplicitEH(Fun
         RemapInstruction(&I, VMap, RF_IgnoreMissingEntries);
   }
 
+  // Remove implausible terminators and replace them with UnreachableInst.
+  for (auto &Funclet : FuncletBlocks) {
+    BasicBlock *FuncletPadBB = Funclet.first;
+    std::set<BasicBlock *> &BlocksInFunclet = Funclet.second;
+    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
+    auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
+    auto *CleanupPad = dyn_cast<CleanupPadInst>(FirstNonPHI);
+
+    for (BasicBlock *BB : BlocksInFunclet) {
+      TerminatorInst *TI = BB->getTerminator();
+      // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
+      bool IsUnreachableRet = isa<ReturnInst>(TI) && (CatchPad || CleanupPad);
+      // The token consumed by a CatchReturnInst must match the funclet token.
+      bool IsUnreachableCatchret = false;
+      if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
+        IsUnreachableCatchret = CRI->getReturnValue() != CatchPad;
+      // The token consumed by a CleanupPadInst must match the funclet token.
+      bool IsUnreachableCleanupret = false;
+      if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
+        IsUnreachableCleanupret = CRI->getReturnValue() != CleanupPad;
+      if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) {
+        new UnreachableInst(BB->getContext(), TI);
+        TI->eraseFromParent();
+      }
+    }
+  }
+
   // Clean-up some of the mess we made by removing useles PHI nodes, trivial
   // branches, etc.
   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
@@ -3094,9 +3121,6 @@ bool WinEHPrepare::prepareExplicitEH(Fun
     MergeBlockIntoPredecessor(BB);
   }
 
-  // TODO: Do something about cleanupblocks which branch to implausible
-  // cleanuprets.
-
   // We might have some unreachable blocks after cleaning up some impossible
   // control flow.
   removeUnreachableBlocks(F);
@@ -3215,6 +3239,12 @@ void WinEHPrepare::insertPHIStore(
 void WinEHPrepare::demoteNonlocalUses(Value *V,
                                       std::set<BasicBlock *> &ColorsForBB,
                                       Function &F) {
+  // Tokens can only be used non-locally due to control flow involving
+  // unreachable edges.  Don't try to demote the token usage, we'll simply
+  // delete the cloned user later.
+  if (isa<CatchPadInst>(V) || isa<CleanupPadInst>(V))
+    return;
+
   DenseMap<BasicBlock *, Value *> Loads;
   AllocaInst *SpillSlot = nullptr;
   for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;) {

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll?rev=245238&r1=245237&r2=245238&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll Mon Aug 17 15:56:39 2015
@@ -36,14 +36,14 @@ merge:
   ; CHECK: merge:
   ; CHECK-NOT: = phi
   %phi = phi i32 [ %x, %left ], [ %y, %right ]
-  catchpad void [] to label %catch unwind label %catchend
+  %cp = catchpad token [] to label %catch unwind label %catchend
 
 catch:
   ; CHECK: catch:
   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
   ; CHECK-NEXT: call void @h(i32 [[Reload]])
   call void @h(i32 %phi)
-  catchret void to label %exit
+  catchret token %cp to label %exit
 
 catchend:
   catchendpad unwind to caller
@@ -75,9 +75,9 @@ right:
 merge.inner:
   ; CHECK: merge.inner:
   ; CHECK-NOT: = phi
-  ; CHECK: catchpad void
+  ; CHECK: catchpad token
   %x = phi i32 [ 1, %left ], [ 2, %right ]
-  catchpad void [] to label %catch.inner unwind label %catchend.inner
+  %cpinner = catchpad token [] to label %catch.inner unwind label %catchend.inner
 
 catch.inner:
   ; Need just one store here because only %y is affected
@@ -89,16 +89,16 @@ catch.inner:
           to label %catchret.inner unwind label %merge.outer
 
 catchret.inner:
-  catchret void to label %exit
+  catchret token %cpinner to label %exit
 catchend.inner:
   catchendpad unwind label %merge.outer
 
 merge.outer:
   ; CHECK: merge.outer:
   ; CHECK-NOT: = phi
-  ; CHECK: catchpad void
+  ; CHECK: [[CatchPad:%[^ ]+]] = catchpad token
   %y = phi i32 [ %x, %catchend.inner ], [ %z, %catch.inner ]
-  catchpad void [] to label %catch.outer unwind label %catchend.outer
+  %cpouter = catchpad token [] to label %catch.outer unwind label %catchend.outer
 
 catchend.outer:
   catchendpad unwind to caller
@@ -109,10 +109,10 @@ catch.outer:
   ; CHECK: catch.outer:
   ; CHECK-DAG: load i32, i32* [[Slot1]]
   ; CHECK-DAG: load i32, i32* [[Slot2]]
-  ; CHECK: catchret void to label
+  ; CHECK: catchret token [[CatchPad]] to label
   call void @h(i32 %x)
   call void @h(i32 %y)
-  catchret void to label %exit
+  catchret token %cpouter to label %exit
 
 exit:
   ret void
@@ -131,7 +131,7 @@ entry:
           to label %exit unwind label %catchpad
 
 catchpad:
-  catchpad void [] to label %catch unwind label %catchend
+  %cp = catchpad token [] to label %catch unwind label %catchend
 
 catch:
   ; Need to reload %B here
@@ -152,7 +152,7 @@ merge:
   ; CHECK:   %phi = phi i32 [ [[ReloadX]], %left ]
   %phi = phi i32 [ %x, %left ], [ 42, %right ]
   call void @h(i32 %phi)
-  catchret void to label %exit
+  catchret token %cp to label %exit
 
 catchend:
   catchendpad unwind to caller
@@ -188,11 +188,11 @@ right:
           to label %join unwind label %catchpad.inner
 catchpad.inner:
    ; CHECK: catchpad.inner:
-   ; CHECK-NEXT: catchpad void
+   ; CHECK-NEXT: catchpad token
    %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
-   catchpad void [] to label %catch.inner unwind label %catchend.inner
+   %cp1 = catchpad token [] to label %catch.inner unwind label %catchend.inner
 catch.inner:
-   catchret void to label %join
+   catchret token %cp1 to label %join
 catchend.inner:
    catchendpad unwind label  %catchpad.outer
 join:
@@ -205,15 +205,15 @@ join:
            to label %exit unwind label %catchpad.outer
 catchpad.outer:
    ; CHECK: catchpad.outer:
-   ; CHECK-NEXT: catchpad void
+   ; CHECK-NEXT: catchpad token
    %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ]
-   catchpad void [] to label %catch.outer unwind label %catchend.outer
+   %cp2 = catchpad token [] to label %catch.outer unwind label %catchend.outer
 catch.outer:
    ; CHECK: catch.outer:
    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
    ; CHECK:   call void @h(i32 [[Reload]])
    call void @h(i32 %phi.outer)
-   catchret void to label %exit
+   catchret token %cp2 to label %exit
 catchend.outer:
    catchendpad unwind to caller
 exit:
@@ -241,10 +241,10 @@ invoke.cont:
 cleanup:
   ; cleanup phi can be loaded at cleanup entry
   ; CHECK: cleanup:
-  ; CHECK-NEXT: cleanuppad void
+  ; CHECK-NEXT: cleanuppad token
   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
-  cleanuppad void []
+  %cp = cleanuppad token []
   %b = call i1 @i()
   br i1 %b, label %left, label %right
 
@@ -264,8 +264,8 @@ merge:
   ; need store for %phi.catch
   ; CHECK:      merge:
   ; CHECK-NEXT:   store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
-  ; CHECK-NEXT:   cleanupret void
-  cleanupret void unwind label %catchpad
+  ; CHECK-NEXT:   cleanupret token
+  cleanupret token %cp unwind label %catchpad
 
 invoke.cont2:
   ; need store for %phi.catch
@@ -277,16 +277,16 @@ invoke.cont2:
 
 catchpad:
   ; CHECK: catchpad:
-  ; CHECK-NEXT: catchpad void
+  ; CHECK-NEXT: catchpad token
   %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
-  catchpad void [] to label %catch unwind label %catchend
+  %cp2 = catchpad token [] to label %catch unwind label %catchend
 
 catch:
   ; CHECK: catch:
   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
   ; CHECK:   call void @h(i32 [[CatchReload]]
   call void @h(i32 %phi.catch)
-  catchret void to label %exit
+  catchret token %cp2 to label %exit
 
 catchend:
   catchendpad unwind to caller
@@ -310,8 +310,8 @@ entry:
   ; CHECK: store i32 %x, i32* [[SpillSlot:%[^ ]+]]
   ; CHECK: br label %loop
 to_caller:
-  cleanuppad void []
-  cleanupret void unwind to caller
+  %cp1 = cleanuppad token []
+  cleanupret token %cp1 unwind to caller
 loop:
   invoke void @f()
           to label %loop unwind label %cleanup
@@ -319,9 +319,9 @@ cleanup:
   ; CHECK: cleanup:
   ; CHECK:   [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]]
   ; CHECK:   call void @h(i32 [[Load]])
-  cleanuppad void []
+  %cp2 = cleanuppad token []
   call void @h(i32 %x)
-  cleanupret void unwind to caller
+  cleanupret token %cp2 unwind to caller
 }
 
 ; CHECK-LABEL: @test7(
@@ -343,9 +343,9 @@ invoke.cont:
 catchpad:
   ; %x phi should be eliminated
   ; CHECK: catchpad:
-  ; CHECK-NEXT: catchpad void
+  ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad token
   %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
-  catchpad void [] to label %catch unwind label %catchend
+  %cp = catchpad token [] to label %catch unwind label %catchend
 catch:
   %b = call i1 @i()
   br i1 %b, label %left, label %right
@@ -353,8 +353,8 @@ left:
   ; Edge from %left to %join needs to be split so that
   ; the load of %x can be inserted *after* the catchret
   ; CHECK: left:
-  ; CHECK-NEXT: catchret void to label %[[SplitLeft:[^ ]+]]
-  catchret void to label %join
+  ; CHECK-NEXT: catchret token %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
+  catchret token %cp to label %join
   ; CHECK: [[SplitLeft]]:
   ; CHECK:   [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
   ; CHECK:   br label %join
@@ -363,9 +363,9 @@ right:
   ; the load of %y can be inserted *after* the catchret
   ; CHECK: right:
   ; CHECK:   store i32 %y, i32* [[SlotY:%[^ ]+]]
-  ; CHECK:   catchret void to label %[[SplitRight:[^ ]+]]
+  ; CHECK:   catchret token %[[CatchPad]] to label %[[SplitRight:[^ ]+]]
   %y = call i32 @g()
-  catchret void to label %join
+  catchret token %cp to label %join
   ; CHECK: [[SplitRight]]:
   ; CHECK:   [[LoadY:%[^ ]+]] = load i32, i32* [[SlotY]]
   ; CHECK:   br label %join
@@ -380,3 +380,32 @@ join:
 exit:
   ret void
 }
+
+; CHECK-LABEL: @test8(
+define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry:
+  invoke void @f()
+          to label %done unwind label %cleanup1
+  invoke void @f()
+          to label %done unwind label %cleanup2
+
+done:
+  ret void
+
+cleanup1:
+  ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad token
+  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: cleanupret token [[CleanupPad1]]
+  %cp0 = cleanuppad token []
+  br label %cleanupexit
+
+cleanup2:
+  ; CHECK: cleanuppad token
+  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: unreachable
+  %cp1 = cleanuppad token []
+  br label %cleanupexit
+
+cleanupexit:
+  call void @f()
+  cleanupret token %cp0 unwind label %cleanup2
+}




More information about the llvm-commits mailing list