summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-05-10 19:00:36 +0000
committerChris Lattner <sabre@nondot.org>2006-05-10 19:00:36 +0000
commita36ee4ea34ce3c31a474e9d5bcf03eacb1f57fa5 (patch)
treeb07db4b7fa66358ee6748668d546caa78f369c29 /llvm/lib/Transforms
parent1a0e0c1c9e2be5ca5d8e1dbc5b6819f7cb473161 (diff)
downloadbcm5719-llvm-a36ee4ea34ce3c31a474e9d5bcf03eacb1f57fa5.tar.gz
bcm5719-llvm-a36ee4ea34ce3c31a474e9d5bcf03eacb1f57fa5.zip
Two changes:
1. Implement InstCombine/deadcode.ll by not adding instructions in unreachable blocks (due to constants in conditional branches/switches) to the worklist. This causes them to be deleted before instcombine starts up, leading to better optimization. 2. In the prepass over instructions, do trivial constprop/dce as we go. This has the effect of improving the effectiveness of #1. In addition, it *significantly* speeds up instcombine on test cases with large amounts of constant folding code (for example, that produced by code specialization or partial evaluation). In one example, it speeds up instcombine from 0.0589s to 0.0224s with a release build (a 2.6x speedup). llvm-svn: 28215
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp79
1 files changed, 72 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index e617114a903..aabc3e558dd 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -48,7 +48,6 @@
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PatternMatch.h"
-#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
@@ -7318,17 +7317,83 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
return true;
}
+
+/// AddReachableCodeToWorklist - Walk the function in depth-first order, adding
+/// all reachable code to the worklist.
+///
+/// This has a couple of tricks to make the code faster and more powerful. In
+/// particular, we constant fold and DCE instructions as we go, to avoid adding
+/// them to the worklist (this significantly speeds up instcombine on code where
+/// 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,
+ std::set<BasicBlock*> &Visited,
+ std::vector<Instruction*> &WorkList) {
+ // We have now visited this block! If we've already been here, bail out.
+ if (!Visited.insert(BB).second) return;
+
+ for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
+ Instruction *Inst = BBI++;
+
+ // DCE instruction if trivially dead.
+ if (isInstructionTriviallyDead(Inst)) {
+ ++NumDeadInst;
+ DEBUG(std::cerr << "IC: DCE: " << *Inst);
+ Inst->eraseFromParent();
+ continue;
+ }
+
+ // ConstantProp instruction if trivially constant.
+ if (Constant *C = ConstantFoldInstruction(Inst)) {
+ DEBUG(std::cerr << "IC: ConstFold to: " << *C << " from: " << *Inst);
+ Inst->replaceAllUsesWith(C);
+ ++NumConstProp;
+ Inst->eraseFromParent();
+ continue;
+ }
+
+ WorkList.push_back(Inst);
+ }
+
+ // Recursively visit successors. If this is a branch or switch on a constant,
+ // only visit the reachable successor.
+ TerminatorInst *TI = BB->getTerminator();
+ if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+ if (BI->isConditional() && isa<ConstantBool>(BI->getCondition())) {
+ bool CondVal = cast<ConstantBool>(BI->getCondition())->getValue();
+ AddReachableCodeToWorklist(BI->getSuccessor(!CondVal), Visited, WorkList);
+ return;
+ }
+ } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
+ if (ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition())) {
+ // See if this is an explicit destination.
+ for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i)
+ if (SI->getCaseValue(i) == Cond) {
+ AddReachableCodeToWorklist(SI->getSuccessor(i), Visited, WorkList);
+ return;
+ }
+
+ // Otherwise it is the default destination.
+ AddReachableCodeToWorklist(SI->getSuccessor(0), Visited, WorkList);
+ return;
+ }
+ }
+
+ for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
+ AddReachableCodeToWorklist(TI->getSuccessor(i), Visited, WorkList);
+}
+
bool InstCombiner::runOnFunction(Function &F) {
bool Changed = false;
TD = &getAnalysis<TargetData>();
{
- // Populate the worklist with the reachable instructions.
+ // Do a depth-first traversal of the function, populate the worklist with
+ // the reachable instructions. Ignore blocks that are not reachable. Keep
+ // track of which blocks we visit.
std::set<BasicBlock*> Visited;
- for (df_ext_iterator<BasicBlock*> BB = df_ext_begin(&F.front(), Visited),
- E = df_ext_end(&F.front(), Visited); BB != E; ++BB)
- for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
- WorkList.push_back(I);
+ AddReachableCodeToWorklist(F.begin(), Visited, WorkList);
// Do a quick scan over the function. If we find any blocks that are
// unreachable, remove any instructions inside of them. This prevents
@@ -7397,7 +7462,7 @@ bool InstCombiner::runOnFunction(Function &F) {
ReplaceInstUsesWith(*I, C);
++NumConstProp;
- I->getParent()->getInstList().erase(I);
+ I->eraseFromParent();
removeFromWorkList(I);
continue;
}
OpenPOWER on IntegriCloud