Implement SimplifyCFG/InvokeEliminate.ll
authorChris Lattner <sabre@nondot.org>
Sun, 24 Aug 2003 18:36:16 +0000 (18:36 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 24 Aug 2003 18:36:16 +0000 (18:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8126 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SimplifyCFG.cpp

index ed0d45be26b826a3d3d30fd17f7cdb28f002c134..f47c8405186324113b16be6a27cc1fb5dbc20b25 100644 (file)
@@ -6,7 +6,10 @@
 
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Constant.h"
+#include "llvm/Intrinsics.h"
 #include "llvm/iPHINode.h"
+#include "llvm/iTerminators.h"
+#include "llvm/iOther.h"
 #include "llvm/Support/CFG.h"
 #include <algorithm>
 #include <functional>
@@ -87,12 +90,44 @@ static bool PropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) {
 // WARNING:  The entry node of a function may not be simplified.
 //
 bool SimplifyCFG(BasicBlock *BB) {
+  bool Changed = false;
   Function *M = BB->getParent();
 
   assert(BB && BB->getParent() && "Block not embedded in function!");
   assert(BB->getTerminator() && "Degenerate basic block encountered!");
   assert(&BB->getParent()->front() != BB && "Can't Simplify entry block!");
 
+  // Check to see if the first instruction in this block is just an
+  // 'llvm.unwind'.  If so, replace any invoke instructions which use this as an
+  // exception destination with call instructions.
+  //
+  if (CallInst *CI = dyn_cast<CallInst>(&BB->front()))
+    if (Function *F = CI->getCalledFunction())
+      if (F->getIntrinsicID() == LLVMIntrinsic::unwind) {
+        std::vector<BasicBlock*> Preds(pred_begin(BB), pred_end(BB));
+        while (!Preds.empty()) {
+          BasicBlock *Pred = Preds.back();
+          if (InvokeInst *II = dyn_cast<InvokeInst>(Pred->getTerminator()))
+            if (II->getExceptionalDest() == BB) {
+              // Insert a new branch instruction before the invoke, because this
+              // is now a fall through...
+              BranchInst *BI = new BranchInst(II->getNormalDest(), II);
+              Pred->getInstList().remove(II);   // Take out of symbol table
+              
+              // Insert the call now...
+              std::vector<Value*> Args(II->op_begin()+3, II->op_end());
+              CallInst *CI = new CallInst(II->getCalledValue(), Args,
+                                          II->getName(), BI);
+              // If the invoke produced a value, the Call now does instead
+              II->replaceAllUsesWith(CI);
+              delete II;
+              Changed = true;
+            }
+          
+          Preds.pop_back();
+        }
+      }
+
   // Remove basic blocks that have no predecessors... which are unreachable.
   if (pred_begin(BB) == pred_end(BB) &&
       !BB->hasConstantReferences()) {
@@ -123,7 +158,7 @@ bool SimplifyCFG(BasicBlock *BB) {
 
   // Check to see if we can constant propagate this terminator instruction
   // away...
-  bool Changed = ConstantFoldTerminator(BB);
+  Changed |= ConstantFoldTerminator(BB);
 
   // Check to see if this block has no non-phi instructions and only a single
   // successor.  If so, replace references to this basic block with references