blob: 82862f7b489734b2253053d9dae83faef366be45 [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) {
76 // If we find a store...
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
114 // Do a trivial DCE
115 while (!possiblyDead.empty()) {
116 Instruction *I = possiblyDead.back();
117 possiblyDead.pop_back();
118 DeleteDeadInstructionChains(I, possiblyDead);
119 }
120
121 return MadeChange;
122}
123
124void FDSE::DeleteDeadInstructionChains(Instruction *I,
125 SetVector<Instruction*> &DeadInsts) {
126 // Instruction must be dead.
127 if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;
128
129 // Let the memory dependence know
130 getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);
131
132 // See if this made any operands dead. We do it this way in case the
133 // instruction uses the same operand twice. We don't want to delete a
134 // value then reference it.
135 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
Owen Andersonbf971aa2007-07-11 19:03:09 +0000136 if (I->getOperand(i)->hasOneUse())
137 if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
138 DeadInsts.insert(Op); // Attempt to nuke it later.
139
Owen Anderson5e72db32007-07-11 00:46:18 +0000140 I->setOperand(i, 0); // Drop from the operand list.
141 }
142
143 I->eraseFromParent();
144 ++NumFastOther;
145}