blob: dd47a19058201943ea691f56d9a1cb9154f6fb0f [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"
Owen Andersonaa071722007-07-11 23:19:17 +000026#include "llvm/Analysis/AliasAnalysis.h"
Owen Anderson5e72db32007-07-11 00:46:18 +000027#include "llvm/Analysis/MemoryDependenceAnalysis.h"
Owen Andersonaa071722007-07-11 23:19:17 +000028#include "llvm/Target/TargetData.h"
Owen Anderson5e72db32007-07-11 00:46:18 +000029#include "llvm/Transforms/Utils/Local.h"
30#include "llvm/Support/Compiler.h"
31using namespace llvm;
32
33STATISTIC(NumFastStores, "Number of stores deleted");
34STATISTIC(NumFastOther , "Number of other instrs removed");
35
36namespace {
37 struct VISIBILITY_HIDDEN FDSE : public FunctionPass {
38 static char ID; // Pass identification, replacement for typeid
39 FDSE() : FunctionPass((intptr_t)&ID) {}
40
41 virtual bool runOnFunction(Function &F) {
42 bool Changed = false;
43 for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
44 Changed |= runOnBasicBlock(*I);
45 return Changed;
46 }
47
48 bool runOnBasicBlock(BasicBlock &BB);
Owen Andersonaa071722007-07-11 23:19:17 +000049 bool handleFreeWithNonTrivialDependency(FreeInst* F, StoreInst* dependency,
50 SetVector<Instruction*>& possiblyDead);
51 bool handleEndBlock(BasicBlock& BB, SetVector<Instruction*>& possiblyDead);
Owen Anderson5e72db32007-07-11 00:46:18 +000052 void DeleteDeadInstructionChains(Instruction *I,
53 SetVector<Instruction*> &DeadInsts);
54
55 // getAnalysisUsage - We require post dominance frontiers (aka Control
56 // Dependence Graph)
57 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
58 AU.setPreservesCFG();
Owen Andersonaa071722007-07-11 23:19:17 +000059 AU.addRequired<TargetData>();
60 AU.addRequired<AliasAnalysis>();
Owen Anderson5e72db32007-07-11 00:46:18 +000061 AU.addRequired<MemoryDependenceAnalysis>();
Owen Andersonaa071722007-07-11 23:19:17 +000062 AU.addPreserved<AliasAnalysis>();
Owen Anderson5e72db32007-07-11 00:46:18 +000063 AU.addPreserved<MemoryDependenceAnalysis>();
64 }
65 };
66 char FDSE::ID = 0;
67 RegisterPass<FDSE> X("fdse", "Fast Dead Store Elimination");
68}
69
70FunctionPass *llvm::createFastDeadStoreEliminationPass() { return new FDSE(); }
71
72bool FDSE::runOnBasicBlock(BasicBlock &BB) {
73 MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
74
Owen Andersonbf971aa2007-07-11 19:03:09 +000075 // Record the last-seen store to this pointer
Owen Anderson5e72db32007-07-11 00:46:18 +000076 DenseMap<Value*, StoreInst*> lastStore;
Owen Andersonbf971aa2007-07-11 19:03:09 +000077 // Record instructions possibly made dead by deleting a store
Owen Anderson5e72db32007-07-11 00:46:18 +000078 SetVector<Instruction*> possiblyDead;
79
80 bool MadeChange = false;
81
82 // Do a top-down walk on the BB
83 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
Owen Anderson14414702007-07-11 21:06:56 +000084 // If we find a store or a free...
Owen Andersone7201442007-07-11 20:38:34 +000085 if (isa<StoreInst>(BBI) || isa<FreeInst>(BBI)) {
86 Value* pointer = 0;
87 if (StoreInst* S = dyn_cast<StoreInst>(BBI))
88 pointer = S->getPointerOperand();
89 else if (FreeInst* F = dyn_cast<FreeInst>(BBI))
90 pointer = F->getPointerOperand();
91 assert(pointer && "Not a free or a store?");
92
93 StoreInst*& last = lastStore[pointer];
Owen Anderson5e72db32007-07-11 00:46:18 +000094
95 // ... to a pointer that has been stored to before...
Owen Andersonbf971aa2007-07-11 19:03:09 +000096 if (last) {
Owen Anderson5e72db32007-07-11 00:46:18 +000097
98 // ... and no other memory dependencies are between them....
Owen Andersone7201442007-07-11 20:38:34 +000099 if (MD.getDependency(BBI) == last) {
100
Owen Anderson5e72db32007-07-11 00:46:18 +0000101 // Remove it!
102 MD.removeInstruction(last);
103
104 // DCE instructions only used to calculate that store
105 if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
106 possiblyDead.insert(D);
107
108 last->eraseFromParent();
109 NumFastStores++;
110 MadeChange = true;
Owen Andersonaa071722007-07-11 23:19:17 +0000111
112 // If this is a free, check for a non-trivial dependency
113 } else if (FreeInst* F = dyn_cast<FreeInst>(BBI))
114 MadeChange |= handleFreeWithNonTrivialDependency(F, last, possiblyDead);
Owen Anderson5e72db32007-07-11 00:46:18 +0000115 }
116
117 // Update our most-recent-store map
Owen Andersone7201442007-07-11 20:38:34 +0000118 if (StoreInst* S = dyn_cast<StoreInst>(BBI))
119 last = S;
120 else
121 last = 0;
Owen Anderson5e72db32007-07-11 00:46:18 +0000122 }
123 }
124
125 // Do a trivial DCE
126 while (!possiblyDead.empty()) {
127 Instruction *I = possiblyDead.back();
128 possiblyDead.pop_back();
129 DeleteDeadInstructionChains(I, possiblyDead);
130 }
131
132 return MadeChange;
133}
134
Owen Andersonaa071722007-07-11 23:19:17 +0000135/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
136/// dependency is a store to a field of that structure
137bool FDSE::handleFreeWithNonTrivialDependency(FreeInst* F, StoreInst* dependency,
138 SetVector<Instruction*>& possiblyDead) {
139 TargetData &TD = getAnalysis<TargetData>();
140 AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
141 MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
142
143 Value* depPointer = dependency->getPointerOperand();
144 unsigned depPointerSize = TD.getTypeSize(dependency->getOperand(0)->getType());
145
146 // Check for aliasing
147 AliasAnalysis::AliasResult A = AA.alias(F->getPointerOperand(), ~0UL,
148 depPointer, depPointerSize);
149
150 if (A == AliasAnalysis::MustAlias) {
151 // Remove it!
152 MD.removeInstruction(dependency);
Owen Andersonaa071722007-07-11 23:19:17 +0000153
154 // DCE instructions only used to calculate that store
155 if (Instruction* D = dyn_cast<Instruction>(dependency->getOperand(0)))
156 possiblyDead.insert(D);
157
158 dependency->eraseFromParent();
159 NumFastStores++;
160 return true;
161 }
162
163 return false;
164}
165
Owen Anderson5e72db32007-07-11 00:46:18 +0000166void FDSE::DeleteDeadInstructionChains(Instruction *I,
167 SetVector<Instruction*> &DeadInsts) {
168 // Instruction must be dead.
169 if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;
170
171 // Let the memory dependence know
172 getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);
173
174 // See if this made any operands dead. We do it this way in case the
175 // instruction uses the same operand twice. We don't want to delete a
176 // value then reference it.
177 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
Owen Andersonbf971aa2007-07-11 19:03:09 +0000178 if (I->getOperand(i)->hasOneUse())
179 if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
180 DeadInsts.insert(Op); // Attempt to nuke it later.
181
Owen Anderson5e72db32007-07-11 00:46:18 +0000182 I->setOperand(i, 0); // Drop from the operand list.
183 }
184
185 I->eraseFromParent();
186 ++NumFastOther;
187}