blob: 3b719df4f6e33314729260cb658c57738641d3f4 [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
Owen Anderson9baaaa52007-07-24 00:17:04 +000018#define DEBUG_TYPE "rle"
Owen Anderson6aba7212007-07-23 21:48:08 +000019#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 {
Owen Anderson9baaaa52007-07-24 00:17:04 +000033 struct VISIBILITY_HIDDEN RLE : public FunctionPass {
Owen Anderson6aba7212007-07-23 21:48:08 +000034 static char ID; // Pass identification, replacement for typeid
Owen Anderson9baaaa52007-07-24 00:17:04 +000035 RLE() : FunctionPass((intptr_t)&ID) {}
Owen Anderson6aba7212007-07-23 21:48:08 +000036
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 };
Owen Anderson9baaaa52007-07-24 00:17:04 +000054 char RLE::ID = 0;
55 RegisterPass<RLE> X("rle", "Redundant Load Elimination");
Owen Anderson6aba7212007-07-23 21:48:08 +000056}
57
Owen Anderson9baaaa52007-07-24 00:17:04 +000058FunctionPass *llvm::createRedundantLoadEliminationPass() { return new RLE(); }
Owen Anderson6aba7212007-07-23 21:48:08 +000059
Owen Anderson9baaaa52007-07-24 00:17:04 +000060bool RLE::runOnBasicBlock(BasicBlock &BB) {
Owen Anderson6aba7212007-07-23 21:48:08 +000061 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
Chris Lattner27406942007-08-02 16:53:43 +000069 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end();
70 BBI != BBE; ++BBI) {
Owen Anderson6aba7212007-07-23 21:48:08 +000071 // If we find a store or a free...
72 if (LoadInst* L = dyn_cast<LoadInst>(BBI)) {
Owen Anderson5e68f0c2007-07-23 22:05:54 +000073 // We can't delete volatile loads
74 if (L->isVolatile()) {
75 lastLoad[L->getPointerOperand()] = L;
76 continue;
77 }
78
Owen Anderson6aba7212007-07-23 21:48:08 +000079 Value* pointer = L->getPointerOperand();
80 LoadInst*& last = lastLoad[pointer];
81
82 // ... to a pointer that has been loaded from before...
Owen Anderson9b1cc8c2007-08-09 04:42:44 +000083 Instruction* dep = MD.getDependency(BBI);
Owen Anderson6aba7212007-07-23 21:48:08 +000084 bool deletedLoad = false;
85
86 while (dep != MemoryDependenceAnalysis::None &&
87 dep != MemoryDependenceAnalysis::NonLocal &&
88 (isa<LoadInst>(dep) || isa<StoreInst>(dep))) {
89 // ... that depends on a store ...
90 if (StoreInst* S = dyn_cast<StoreInst>(dep)) {
91 if (S->getPointerOperand() == pointer) {
92 // Remove it!
93 MD.removeInstruction(BBI);
94
95 BBI--;
96 L->replaceAllUsesWith(S->getOperand(0));
97 L->eraseFromParent();
98 NumFastLoads++;
99 deletedLoad = true;
100 MadeChange = true;
101 }
102
103 // Whether we removed it or not, we can't
104 // go any further
105 break;
106 } else if (!last) {
107 // If we don't depend on a store, and we haven't
108 // been loaded before, bail.
109 break;
110 } else if (dep == last) {
111 // Remove it!
112 MD.removeInstruction(BBI);
113
114 BBI--;
115 L->replaceAllUsesWith(last);
116 L->eraseFromParent();
117 deletedLoad = true;
118 NumFastLoads++;
119 MadeChange = true;
120
121 break;
122 } else {
Owen Anderson9b1cc8c2007-08-09 04:42:44 +0000123 dep = MD.getDependency(BBI, dep);
Owen Anderson6aba7212007-07-23 21:48:08 +0000124 }
125 }
126
127 if (!deletedLoad)
128 last = L;
129 }
130 }
131
132 return MadeChange;
133}
134
135