diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 356b86fdbb0..9e37d96f59e 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -43,12 +43,13 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstIterator.h" #include "llvm/Support/InstVisitor.h" #include "llvm/Support/PatternMatch.h" -#include "llvm/Support/Debug.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" #include using namespace llvm; using namespace llvm::PatternMatch; @@ -57,6 +58,7 @@ namespace { Statistic<> NumCombined ("instcombine", "Number of insts combined"); Statistic<> NumConstProp("instcombine", "Number of constant folds"); Statistic<> NumDeadInst ("instcombine", "Number of dead inst eliminated"); + Statistic<> NumSunkInst ("instcombine", "Number of instructions sunk"); class InstCombiner : public FunctionPass, public InstVisitor { @@ -4189,6 +4191,32 @@ void InstCombiner::removeFromWorkList(Instruction *I) { WorkList.end()); } + +/// TryToSinkInstruction - Try to move the specified instruction from its +/// current block into the beginning of DestBlock, which can only happen if it's +/// safe to move the instruction past all of the instructions between it and the +/// end of its block. +static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { + assert(I->hasOneUse() && "Invariants didn't hold!"); + + // Cannot move control-flow-involving instructions. + if (isa(I) || isa(I) || isa(I)) return false; + + // Do not sink alloca instructions out of the entry block. + if (isa(I) && I->getParent() == &DestBlock->getParent()->front()) + return false; + + if (isa(I)) return false; + + BasicBlock::iterator InsertPos = DestBlock->begin(); + while (isa(InsertPos)) ++InsertPos; + + BasicBlock *SrcBlock = I->getParent(); + DestBlock->getInstList().splice(InsertPos, SrcBlock->getInstList(), I); + ++NumSunkInst; + return true; +} + bool InstCombiner::runOnFunction(Function &F) { bool Changed = false; TD = &getAnalysis(); @@ -4246,6 +4274,29 @@ bool InstCombiner::runOnFunction(Function &F) { continue; } + // See if we can trivially sink this instruction to a successor basic block. + if (I->hasOneUse()) { + BasicBlock *BB = I->getParent(); + BasicBlock *UserParent = cast(I->use_back())->getParent(); + if (UserParent != BB) { + bool UserIsSuccessor = false; + // See if the user is one of our successors. + for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) + if (*SI == UserParent) { + UserIsSuccessor = true; + break; + } + + // If the user is one of our immediate successors, and if that successor + // only has us as a predecessors (we'd have to split the critical edge + // otherwise), we can keep going. + if (UserIsSuccessor && !isa(I->use_back()) && + next(pred_begin(UserParent)) == pred_end(UserParent)) + // Okay, the CFG is simple enough, try to sink this instruction. + Changed |= TryToSinkInstruction(I, UserParent); + } + } + // Now that we have an instruction, try combining it to simplify it... if (Instruction *Result = visit(*I)) { ++NumCombined;