diff options
Diffstat (limited to 'lib/Transforms/Scalar/InstructionCombining.cpp')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 90 |
1 files changed, 54 insertions, 36 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 7c96c49..f635af3 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -56,6 +56,7 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/PatternMatch.h" +#include "llvm/Support/TargetFolder.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" @@ -186,7 +187,7 @@ namespace { /// Builder - This is an IRBuilder that automatically inserts new /// instructions into the worklist when they are created. - typedef IRBuilder<true, ConstantFolder, InstCombineIRInserter> BuilderTy; + typedef IRBuilder<true, TargetFolder, InstCombineIRInserter> BuilderTy; BuilderTy *Builder; static char ID; // Pass identification, replacement for typeid @@ -12675,16 +12676,19 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { /// many instructions are dead or constant). Additionally, if we find a branch /// whose condition is a known constant, we only visit the reachable successors. /// -static void AddReachableCodeToWorklist(BasicBlock *BB, +static bool AddReachableCodeToWorklist(BasicBlock *BB, SmallPtrSet<BasicBlock*, 64> &Visited, InstCombiner &IC, const TargetData *TD) { + bool MadeIRChange = false; SmallVector<BasicBlock*, 256> Worklist; Worklist.push_back(BB); std::vector<Instruction*> InstrsForInstCombineWorklist; InstrsForInstCombineWorklist.reserve(128); + SmallPtrSet<ConstantExpr*, 64> FoldedConstants; + while (!Worklist.empty()) { BB = Worklist.back(); Worklist.pop_back(); @@ -12704,14 +12708,38 @@ static void AddReachableCodeToWorklist(BasicBlock *BB, } // ConstantProp instruction if trivially constant. - if (Constant *C = ConstantFoldInstruction(Inst, BB->getContext(), TD)) { - DEBUG(errs() << "IC: ConstFold to: " << *C << " from: " - << *Inst << '\n'); - Inst->replaceAllUsesWith(C); - ++NumConstProp; - Inst->eraseFromParent(); - continue; + if (!Inst->use_empty() && isa<Constant>(Inst->getOperand(0))) + if (Constant *C = ConstantFoldInstruction(Inst, BB->getContext(), TD)) { + DEBUG(errs() << "IC: ConstFold to: " << *C << " from: " + << *Inst << '\n'); + Inst->replaceAllUsesWith(C); + ++NumConstProp; + Inst->eraseFromParent(); + continue; + } + + + + if (TD) { + // See if we can constant fold its operands. + for (User::op_iterator i = Inst->op_begin(), e = Inst->op_end(); + i != e; ++i) { + ConstantExpr *CE = dyn_cast<ConstantExpr>(i); + if (CE == 0) continue; + + // If we already folded this constant, don't try again. + if (!FoldedConstants.insert(CE)) + continue; + + Constant *NewC = + ConstantFoldConstantExpression(CE, BB->getContext(), TD); + if (NewC && NewC != CE) { + *i = NewC; + MadeIRChange = true; + } + } } + InstrsForInstCombineWorklist.push_back(Inst); } @@ -12753,11 +12781,12 @@ static void AddReachableCodeToWorklist(BasicBlock *BB, // some N^2 behavior in pathological cases. IC.Worklist.AddInitialGroup(&InstrsForInstCombineWorklist[0], InstrsForInstCombineWorklist.size()); + + return MadeIRChange; } bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { MadeIRChange = false; - TD = getAnalysisIfAvailable<TargetData>(); DEBUG(errs() << "\n\nINSTCOMBINE ITERATION #" << Iteration << " on " << F.getNameStr() << "\n"); @@ -12767,7 +12796,7 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { // the reachable instructions. Ignore blocks that are not reachable. Keep // track of which blocks we visit. SmallPtrSet<BasicBlock*, 64> Visited; - AddReachableCodeToWorklist(F.begin(), Visited, *this, TD); + MadeIRChange |= AddReachableCodeToWorklist(F.begin(), Visited, *this, TD); // Do a quick scan over the function. If we find any blocks that are // unreachable, remove any instructions inside of them. This prevents @@ -12786,7 +12815,6 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { MadeIRChange = true; } - // If I is not void type then replaceAllUsesWith undef. // This allows ValueHandlers and custom metadata to adjust itself. if (!I->getType()->isVoidTy()) @@ -12810,28 +12838,17 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { } // Instruction isn't dead, see if we can constant propagate it. - if (Constant *C = ConstantFoldInstruction(I, F.getContext(), TD)) { - DEBUG(errs() << "IC: ConstFold to: " << *C << " from: " << *I << '\n'); + if (!I->use_empty() && isa<Constant>(I->getOperand(0))) + if (Constant *C = ConstantFoldInstruction(I, F.getContext(), TD)) { + DEBUG(errs() << "IC: ConstFold to: " << *C << " from: " << *I << '\n'); - // Add operands to the worklist. - ReplaceInstUsesWith(*I, C); - ++NumConstProp; - EraseInstFromFunction(*I); - MadeIRChange = true; - continue; - } - - if (TD) { - // See if we can constant fold its operands. - for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(i)) - if (Constant *NewC = ConstantFoldConstantExpression(CE, - F.getContext(), TD)) - if (NewC != CE) { - *i = NewC; - MadeIRChange = true; - } - } + // Add operands to the worklist. + ReplaceInstUsesWith(*I, C); + ++NumConstProp; + EraseInstFromFunction(*I); + MadeIRChange = true; + continue; + } // See if we can trivially sink this instruction to a successor basic block. if (I->hasOneUse()) { @@ -12927,12 +12944,13 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { bool InstCombiner::runOnFunction(Function &F) { MustPreserveLCSSA = mustPreserveAnalysisID(LCSSAID); Context = &F.getContext(); - + TD = getAnalysisIfAvailable<TargetData>(); + /// Builder - This is an IRBuilder that automatically inserts new /// instructions into the worklist when they are created. - IRBuilder<true, ConstantFolder, InstCombineIRInserter> - TheBuilder(F.getContext(), ConstantFolder(F.getContext()), + IRBuilder<true, TargetFolder, InstCombineIRInserter> + TheBuilder(F.getContext(), TargetFolder(TD, F.getContext()), InstCombineIRInserter(Worklist)); Builder = &TheBuilder; |