blob: cd85b7caef7da8aa0d6d80ac159c9c81dc917506 [file] [log] [blame]
Owen Anderson5e72db32007-07-11 00:46:18 +00001//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Owen Andersonbf971aa2007-07-11 19:03:09 +00005// This file was developed by Owen Anderson and is distributed under
Owen Anderson5e72db32007-07-11 00:46:18 +00006// 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
Owen Andersonbf971aa2007-07-11 19:03:09 +000067 // Record the last-seen store to this pointer
Owen Anderson5e72db32007-07-11 00:46:18 +000068 DenseMap<Value*, StoreInst*> lastStore;
Owen Andersonbf971aa2007-07-11 19:03:09 +000069 // Record instructions possibly made dead by deleting a store
Owen Anderson5e72db32007-07-11 00:46:18 +000070 SetVector<Instruction*> possiblyDead;
71
72 bool MadeChange = false;
73
74 // Do a top-down walk on the BB
75 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
Owen Anderson14414702007-07-11 21:06:56 +000076 // If we find a store or a free...
Owen Andersone7201442007-07-11 20:38:34 +000077 if (isa<StoreInst>(BBI) || isa<FreeInst>(BBI)) {
78 Value* pointer = 0;
79 if (StoreInst* S = dyn_cast<StoreInst>(BBI))
80 pointer = S->getPointerOperand();
81 else if (FreeInst* F = dyn_cast<FreeInst>(BBI))
82 pointer = F->getPointerOperand();
83 assert(pointer && "Not a free or a store?");
84
85 StoreInst*& last = lastStore[pointer];
Owen Anderson5e72db32007-07-11 00:46:18 +000086
87 // ... to a pointer that has been stored to before...
Owen Andersonbf971aa2007-07-11 19:03:09 +000088 if (last) {
Owen Anderson5e72db32007-07-11 00:46:18 +000089
90 // ... and no other memory dependencies are between them....
Owen Andersone7201442007-07-11 20:38:34 +000091 if (MD.getDependency(BBI) == last) {
92
Owen Anderson5e72db32007-07-11 00:46:18 +000093 // Remove it!
94 MD.removeInstruction(last);
95
96 // DCE instructions only used to calculate that store
97 if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
98 possiblyDead.insert(D);
99
100 last->eraseFromParent();
101 NumFastStores++;
102 MadeChange = true;
103 }
104 }
105
106 // Update our most-recent-store map
Owen Andersone7201442007-07-11 20:38:34 +0000107 if (StoreInst* S = dyn_cast<StoreInst>(BBI))
108 last = S;
109 else
110 last = 0;
Owen Anderson5e72db32007-07-11 00:46:18 +0000111 }
112 }
113
Owen Anderson14414702007-07-11 21:06:56 +0000114 // If this block ends in a return, unwind, unreachable, and eventually
115 // tailcall, then all allocas are dead at its end.
116 if (BB.getTerminator()->getNumSuccessors() == 0) {
117 // Pointers alloca'd in this function are dead in the end block
118 SmallPtrSet<AllocaInst*, 4> deadPointers;
119
120 // Find all of the alloca'd pointers in the entry block
121 BasicBlock *Entry = BB.getParent()->begin();
122 for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I)
123 if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
124 deadPointers.insert(AI);
125
126 // Scan the basic block backwards
127 for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
128 --BBI;
129
130 if (deadPointers.empty())
131 break;
132
133 // If we find a store whose pointer is dead...
134 if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
135 if (deadPointers.count(S->getPointerOperand())){
136 // Remove it!
137 MD.removeInstruction(S);
138
139 // DCE instructions only used to calculate that store
140 if (Instruction* D = dyn_cast<Instruction>(S->getOperand(0)))
141 possiblyDead.insert(D);
142
143 BBI++;
144 S->eraseFromParent();
145 NumFastStores++;
146 MadeChange = true;
147 }
148
149 // If we encounter a use of the pointer, it is no longer considered dead
150 } else if (LoadInst* L = dyn_cast<LoadInst>(BBI)) {
151 deadPointers.erase(L->getPointerOperand());
152 } else if (VAArgInst* V = dyn_cast<VAArgInst>(BBI)) {
153 deadPointers.erase(V->getOperand(0));
154 }
155 }
156 }
157
Owen Anderson5e72db32007-07-11 00:46:18 +0000158 // Do a trivial DCE
159 while (!possiblyDead.empty()) {
160 Instruction *I = possiblyDead.back();
161 possiblyDead.pop_back();
162 DeleteDeadInstructionChains(I, possiblyDead);
163 }
164
165 return MadeChange;
166}
167
168void FDSE::DeleteDeadInstructionChains(Instruction *I,
169 SetVector<Instruction*> &DeadInsts) {
170 // Instruction must be dead.
171 if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;
172
173 // Let the memory dependence know
174 getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);
175
176 // See if this made any operands dead. We do it this way in case the
177 // instruction uses the same operand twice. We don't want to delete a
178 // value then reference it.
179 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
Owen Andersonbf971aa2007-07-11 19:03:09 +0000180 if (I->getOperand(i)->hasOneUse())
181 if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
182 DeadInsts.insert(Op); // Attempt to nuke it later.
183
Owen Anderson5e72db32007-07-11 00:46:18 +0000184 I->setOperand(i, 0); // Drop from the operand list.
185 }
186
187 I->eraseFromParent();
188 ++NumFastOther;
189}