blob: 10873cd8ed5d351fc17eb3c35cd718073b4da83d [file] [log] [blame]
Owen Anderson5e72db32007-07-11 00:46:18 +00001//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements a trivial dead store elimination that only considers
11// basic-block local redundant stores.
12//
13// FIXME: This should eventually be extended to be a post-dominator tree
14// traversal. Doing so would be pretty trivial.
15//
16//===----------------------------------------------------------------------===//
17
18#define DEBUG_TYPE "fdse"
19#include "llvm/Transforms/Scalar.h"
20#include "llvm/Function.h"
21#include "llvm/Instructions.h"
22#include "llvm/Pass.h"
23#include "llvm/ADT/SetVector.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include "llvm/ADT/Statistic.h"
26#include "llvm/Analysis/MemoryDependenceAnalysis.h"
27#include "llvm/Transforms/Utils/Local.h"
28#include "llvm/Support/Compiler.h"
29using namespace llvm;
30
31STATISTIC(NumFastStores, "Number of stores deleted");
32STATISTIC(NumFastOther , "Number of other instrs removed");
33
34namespace {
35 struct VISIBILITY_HIDDEN FDSE : public FunctionPass {
36 static char ID; // Pass identification, replacement for typeid
37 FDSE() : FunctionPass((intptr_t)&ID) {}
38
39 virtual bool runOnFunction(Function &F) {
40 bool Changed = false;
41 for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
42 Changed |= runOnBasicBlock(*I);
43 return Changed;
44 }
45
46 bool runOnBasicBlock(BasicBlock &BB);
47 void DeleteDeadInstructionChains(Instruction *I,
48 SetVector<Instruction*> &DeadInsts);
49
50 // getAnalysisUsage - We require post dominance frontiers (aka Control
51 // Dependence Graph)
52 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
53 AU.setPreservesCFG();
54 AU.addRequired<MemoryDependenceAnalysis>();
55 AU.addPreserved<MemoryDependenceAnalysis>();
56 }
57 };
58 char FDSE::ID = 0;
59 RegisterPass<FDSE> X("fdse", "Fast Dead Store Elimination");
60}
61
62FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); }
63
64bool FDSE::runOnBasicBlock(BasicBlock &BB) {
65 MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
66
67 DenseMap<Value*, StoreInst*> lastStore;
68 SetVector<Instruction*> possiblyDead;
69
70 bool MadeChange = false;
71
72 // Do a top-down walk on the BB
73 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
74 // If we find a store...
75 if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
76
77 // ... to a pointer that has been stored to before...
78 if (lastStore.count(S->getPointerOperand())) {
79 StoreInst* last = lastStore[S->getPointerOperand()];
80
81 // ... and no other memory dependencies are between them....
82 if (MD.getDependency(S) == last) {
83 // Remove it!
84 MD.removeInstruction(last);
85
86 // DCE instructions only used to calculate that store
87 if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
88 possiblyDead.insert(D);
89
90 last->eraseFromParent();
91 NumFastStores++;
92 MadeChange = true;
93 }
94 }
95
96 // Update our most-recent-store map
97 lastStore.insert(std::make_pair(S->getPointerOperand(), S));
98 }
99 }
100
101 // Do a trivial DCE
102 while (!possiblyDead.empty()) {
103 Instruction *I = possiblyDead.back();
104 possiblyDead.pop_back();
105 DeleteDeadInstructionChains(I, possiblyDead);
106 }
107
108 return MadeChange;
109}
110
111void FDSE::DeleteDeadInstructionChains(Instruction *I,
112 SetVector<Instruction*> &DeadInsts) {
113 // Instruction must be dead.
114 if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;
115
116 // Let the memory dependence know
117 getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);
118
119 // See if this made any operands dead. We do it this way in case the
120 // instruction uses the same operand twice. We don't want to delete a
121 // value then reference it.
122 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
123 if (Instruction *Op = dyn_cast<Instruction>(I->getOperand(i)))
124 DeadInsts.insert(Op); // Attempt to nuke it later.
125 I->setOperand(i, 0); // Drop from the operand list.
126 }
127
128 I->eraseFromParent();
129 ++NumFastOther;
130}