blob: 001f834b5f0bdb80ef28b76ff857abc0a6484912 [file] [log] [blame]
Owen Anderson6aba7212007-07-23 21:48:08 +00001//===- FastDLE.cpp - Fast Dead Load Elimination ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Owen Anderson 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 load elimination that only considers
11// basic-block local redundant load.
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 "fdle"
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/SmallPtrSet.h"
24#include "llvm/ADT/Statistic.h"
25#include "llvm/Analysis/MemoryDependenceAnalysis.h"
26#include "llvm/Transforms/Utils/Local.h"
27#include "llvm/Support/Compiler.h"
28using namespace llvm;
29
30STATISTIC(NumFastLoads, "Number of loads deleted");
31
32namespace {
33 struct VISIBILITY_HIDDEN FDLE : public FunctionPass {
34 static char ID; // Pass identification, replacement for typeid
35 FDLE() : FunctionPass((intptr_t)&ID) {}
36
37 virtual bool runOnFunction(Function &F) {
38 bool Changed = false;
39 for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
40 Changed |= runOnBasicBlock(*I);
41 return Changed;
42 }
43
44 bool runOnBasicBlock(BasicBlock &BB);
45
46 // getAnalysisUsage - We require post dominance frontiers (aka Control
47 // Dependence Graph)
48 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
49 AU.setPreservesCFG();
50 AU.addRequired<MemoryDependenceAnalysis>();
51 AU.addPreserved<MemoryDependenceAnalysis>();
52 }
53 };
54 char FDLE::ID = 0;
55 RegisterPass<FDLE> X("fdle", "Fast Dead Load Elimination");
56}
57
58FunctionPass *llvm::createFastDeadLoadEliminationPass() { return new FDLE(); }
59
60bool FDLE::runOnBasicBlock(BasicBlock &BB) {
61 MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
62
63 // Record the last-seen load from this pointer
64 DenseMap<Value*, LoadInst*> lastLoad;
65
66 bool MadeChange = false;
67
68 // Do a top-down walk on the BB
69 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ++BBI) {
70 // If we find a store or a free...
71 if (LoadInst* L = dyn_cast<LoadInst>(BBI)) {
72 Value* pointer = L->getPointerOperand();
73 LoadInst*& last = lastLoad[pointer];
74
75 // ... to a pointer that has been loaded from before...
76 Instruction* dep = MD.getDependency(BBI);
77 bool deletedLoad = false;
78
79 while (dep != MemoryDependenceAnalysis::None &&
80 dep != MemoryDependenceAnalysis::NonLocal &&
81 (isa<LoadInst>(dep) || isa<StoreInst>(dep))) {
82 // ... that depends on a store ...
83 if (StoreInst* S = dyn_cast<StoreInst>(dep)) {
84 if (S->getPointerOperand() == pointer) {
85 // Remove it!
86 MD.removeInstruction(BBI);
87
88 BBI--;
89 L->replaceAllUsesWith(S->getOperand(0));
90 L->eraseFromParent();
91 NumFastLoads++;
92 deletedLoad = true;
93 MadeChange = true;
94 }
95
96 // Whether we removed it or not, we can't
97 // go any further
98 break;
99 } else if (!last) {
100 // If we don't depend on a store, and we haven't
101 // been loaded before, bail.
102 break;
103 } else if (dep == last) {
104 // Remove it!
105 MD.removeInstruction(BBI);
106
107 BBI--;
108 L->replaceAllUsesWith(last);
109 L->eraseFromParent();
110 deletedLoad = true;
111 NumFastLoads++;
112 MadeChange = true;
113
114 break;
115 } else {
116 dep = MD.getDependency(BBI, dep);
117 }
118 }
119
120 if (!deletedLoad)
121 last = L;
122 }
123 }
124
125 return MadeChange;
126}
127
128