diff options
-rw-r--r-- | lib/Transforms/Utils/BasicBlockUtils.cpp | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index aea0b94..20a4714 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -7,7 +7,9 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Function.h" -#include "llvm/Instruction.h" +#include "llvm/iTerminators.h" +#include "llvm/Constant.h" +#include "llvm/Type.h" #include <algorithm> // ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) @@ -50,11 +52,56 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL, } // ReplaceInstWithInst - Replace the instruction specified by From with the -// instruction specified by To. Note that this is slower than providing an -// iterator directly, because the basic block containing From must be searched -// for the instruction. +// instruction specified by To. // void ReplaceInstWithInst(Instruction *From, Instruction *To) { BasicBlock::iterator BI(From); ReplaceInstWithInst(From->getParent()->getInstList(), BI, To); } + +// RemoveSuccessor - Change the specified terminator instruction such that its +// successor #SuccNum no longer exists. Because this reduces the outgoing +// degree of the current basic block, the actual terminator instruction itself +// may have to be changed. In the case where the last successor of the block is +// deleted, a return instruction is inserted in its place which can cause a +// suprising change in program behavior if it is not expected. +// +void RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum) { + assert(SuccNum < TI->getNumSuccessors() && + "Trying to remove a nonexistant successor!"); + + // If our old successor block contains any PHI nodes, remove the entry in the + // PHI nodes that comes from this branch... + // + BasicBlock *BB = TI->getParent(); + TI->getSuccessor(SuccNum)->removePredecessor(BB); + + TerminatorInst *NewTI = 0; + switch (TI->getOpcode()) { + case Instruction::Br: + // If this is a conditional branch... convert to unconditional branch. + if (TI->getNumSuccessors() == 2) { + cast<BranchInst>(TI)->setUnconditionalDest(TI->getSuccessor(1-SuccNum)); + } else { // Otherwise convert to a return instruction... + Value *RetVal = 0; + + // Create a value to return... if the function doesn't return null... + if (BB->getParent()->getReturnType() != Type::VoidTy) + RetVal = Constant::getNullValue(BB->getParent()->getReturnType()); + + // Create the return... + NewTI = new ReturnInst(RetVal); + } + break; + + case Instruction::Invoke: // Should convert to call + case Instruction::Switch: // Should remove entry + default: + case Instruction::Ret: // Cannot happen, has no successors! + assert(0 && "Unhandled terminator instruction type in RemoveSuccessor!"); + abort(); + } + + if (NewTI) // If it's a different instruction, replace. + ReplaceInstWithInst(TI, NewTI); +} |