[llvm] r251061 - [SimplifyCFG] Extend SimplifyResume to handle phi of trivial landing pad.

Chen Li via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 22 13:48:39 PDT 2015


Author: chenli
Date: Thu Oct 22 15:48:38 2015
New Revision: 251061

URL: http://llvm.org/viewvc/llvm-project?rev=251061&view=rev
Log:
[SimplifyCFG] Extend SimplifyResume to handle phi of trivial landing pad.

Summary: Currently SimplifyResume can convert an invoke instruction to a call instruction if its landing pad is trivial. In practice we could have several invoke instructions with trivial landing pads and share a common rethrow block, and in the common rethrow block, all the landing pads join to a phi node. The patch extends SimplifyResume to check the phi of landing pad and their incoming blocks. If any of them is trivial, remove it from the phi node and convert the invoke instruction to a call instruction.  

Reviewers: hfinkel, reames

Subscribers: llvm-commits

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

Modified:
    llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=251061&r1=251060&r2=251061&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Thu Oct 22 15:48:38 2015
@@ -2905,26 +2905,80 @@ bool SimplifyCFGOpt::SimplifyResume(Resu
   // exception then zap the landing pad, turning its invokes into calls.
   BasicBlock *BB = RI->getParent();
   LandingPadInst *LPInst = dyn_cast<LandingPadInst>(BB->getFirstNonPHI());
-  if (RI->getValue() != LPInst)
-    // Not a landing pad, or the resume is not unwinding the exception that
-    // caused control to branch here.
+
+  // If RI->getValue() is a landing pad, check if the first instruction is
+  // the same landing pad that caused control to branch here. If RI->getValue
+  // is a phi of landing pad, check its predecessor blocks to see if any of
+  // them contains a trivial landing pad.
+  if (RI->getValue() != LPInst && !isa<PHINode>(RI->getValue()))
     return false;
 
-  // Check that there are no other instructions except for debug intrinsics.
-  BasicBlock::iterator I = LPInst->getIterator(), E = RI->getIterator();
+  // Check that there are no other instructions except for debug intrinsics
+  // between the landing pad (or phi of landing pad) and resume instruction.
+  BasicBlock::iterator I = cast<Instruction>(RI->getValue()), E = RI;
   while (++I != E)
     if (!isa<DbgInfoIntrinsic>(I))
       return false;
 
+  SmallVector<BasicBlock *, 4> TrivialUnwindBlocks;
+  if (RI->getValue() == LPInst) {
+    // Landing pad is in current block, which has already been checked.
+    TrivialUnwindBlocks.push_back(BB);
+  } else {
+    // Check incoming blocks to see if any of them are trivial.
+    auto *PhiLPInst = cast<PHINode>(RI->getValue());
+    for (unsigned i = 0; i < PhiLPInst->getNumIncomingValues(); i++) {
+      auto *IncomingBB = PhiLPInst->getIncomingBlock(i);
+      auto *IncomingValue = PhiLPInst->getIncomingValue(i);
+
+      auto *LandingPad =
+          dyn_cast<LandingPadInst>(IncomingBB->getFirstNonPHI());
+      // Not the landing pad that caused the control to branch here.
+      if (IncomingValue != LandingPad)
+        continue;
+
+      bool isTrivial = true;
+
+      I = IncomingBB->getFirstNonPHI();
+      E = IncomingBB->getTerminator();
+      while (++I != E)
+        if (!isa<DbgInfoIntrinsic>(I)) {
+          isTrivial = false;
+          break;
+        }
+
+      if (isTrivial)
+        TrivialUnwindBlocks.push_back(IncomingBB);
+    }
+  }
+
   // Turn all invokes that unwind here into calls and delete the basic block.
-  for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE;) {
-    BasicBlock *Pred = *PI++;
-    removeUnwindEdge(Pred);
+  for (auto *TrivialBB : TrivialUnwindBlocks) {
+    if (isa<PHINode>(RI->getValue())) {
+      // Blocks that will be deleted should also be removed
+      // from the phi node.
+      BB->removePredecessor(TrivialBB, true);
+    }
+
+    for (pred_iterator PI = pred_begin(TrivialBB), PE = pred_end(TrivialBB);
+         PI != PE;) {
+      BasicBlock *Pred = *PI++;
+      removeUnwindEdge(Pred);
+    }
+
+    // The landingpad is now unreachable.  Zap it.
+    if (TrivialBB == BB)
+      BB = nullptr;
+    TrivialBB->eraseFromParent();
+  }
+
+  // Delete the resume block if all its predecessors have been deleted, and we
+  // haven't already deleted it above when deleting the landing pad blocks.
+  if (BB && pred_begin(BB) == pred_end(BB)) {
+    BB->eraseFromParent();
   }
 
-  // The landingpad is now unreachable.  Zap it.
-  BB->eraseFromParent();
-  return true;
+  return TrivialUnwindBlocks.size() != 0;
 }
 
 bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) {

Modified: llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll?rev=251061&r1=251060&r2=251061&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll Thu Oct 22 15:48:38 2015
@@ -17,4 +17,46 @@ Rethrow:
         resume { i8*, i32 } %exn
 }
 
+declare i64 @dummy1()
+declare i64 @dummy2()
+
+; This testcase checks to see if simplifycfg pass can convert two invoke 
+; instructions to call instructions if they share a common trivial unwind
+; block.
+define i64 @test2(i1 %cond) personality i32 (...)* @__gxx_personality_v0 {
+entry:
+; CHECK-LABEL: @test2(
+; CHECK: %call1 = call i64 @dummy1()
+; CHECK: %call2 = call i64 @dummy2()
+; CHECK-NOT: resume { i8*, i32 } %lp
+  br i1 %cond, label %br1, label %br2
+
+br1:
+  %call1 = invoke i64 @dummy1()
+          to label %invoke.cont unwind label %lpad1
+          
+br2: 
+  %call2 = invoke i64 @dummy2()
+          to label %invoke.cont unwind label %lpad2
+          
+invoke.cont:
+  %c = phi i64 [%call1, %br1], [%call2, %br2]
+  ret i64 %c 
+  
+  
+lpad1:
+  %0 = landingpad { i8*, i32 }
+          cleanup
+  br label %rethrow 
+
+lpad2:
+  %1 = landingpad { i8*, i32 }
+          cleanup
+  br label %rethrow
+
+rethrow:
+  %lp = phi { i8*, i32 } [%0, %lpad1], [%1, %lpad2]
+  resume { i8*, i32 } %lp
+}
+
 declare i32 @__gxx_personality_v0(...)




More information about the llvm-commits mailing list