blob: e344f55e823ee81647ce2f746d8ae715b8c571ad [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...
77 if (StoreInst* S = dyn_cast<StoreInst>(BBI)) {
Owen Andersonbf971aa2007-07-11 19:03:09 +000078 StoreInst*& last = lastStore[S->getPointerOperand()];
Owen Anderson5e72db32007-07-11 00:46:18 +000079
80 // ... to a pointer that has been stored to before...
Owen Andersonbf971aa2007-07-11 19:03:09 +000081 if (last) {
Owen Anderson5e72db32007-07-11 00:46:18 +000082
83 // ... and no other memory dependencies are between them....
84 if (MD.getDependency(S) == last) {
85 // Remove it!
86 MD.removeInstruction(last);
87
88 // DCE instructions only used to calculate that store
89 if (Instruction* D = dyn_cast<Instruction>(last->getOperand(0)))
90 possiblyDead.insert(D);
91
92 last->eraseFromParent();
93 NumFastStores++;
94 MadeChange = true;
95 }
96 }
97
98 // Update our most-recent-store map
Owen Andersonbf971aa2007-07-11 19:03:09 +000099 last = S;
Owen Anderson5e72db32007-07-11 00:46:18 +0000100 }
101 }
102
103 // Do a trivial DCE
104 while (!possiblyDead.empty()) {
105 Instruction *I = possiblyDead.back();
106 possiblyDead.pop_back();
107 DeleteDeadInstructionChains(I, possiblyDead);
108 }
109
110 return MadeChange;
111}
112
113void FDSE::DeleteDeadInstructionChains(Instruction *I,
114 SetVector<Instruction*> &DeadInsts) {
115 // Instruction must be dead.
116 if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;
117
118 // Let the memory dependence know
119 getAnalysis<MemoryDependenceAnalysis>().removeInstruction(I);
120
121 // See if this made any operands dead. We do it this way in case the
122 // instruction uses the same operand twice. We don't want to delete a
123 // value then reference it.
124 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
Owen Andersonbf971aa2007-07-11 19:03:09 +0000125 if (I->getOperand(i)->hasOneUse())
126 if (Instruction* Op = dyn_cast<Instruction>(I->getOperand(i)))
127 DeadInsts.insert(Op); // Attempt to nuke it later.
128
Owen Anderson5e72db32007-07-11 00:46:18 +0000129 I->setOperand(i, 0); // Drop from the operand list.
130 }
131
132 I->eraseFromParent();
133 ++NumFastOther;
134}