Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//===- LoopStrengthReduce.cpp - Strength Reduce GEPs in Loops -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs a strength reduction on array references inside loops that
// have as one or more of their components the loop induction variable. This is
// accomplished by creating a new Value to hold the initial value of the array
// access for the first iteration, and then creating a new GEP instruction in
// the loop to increment the value by the appropriate amount.
//
// There are currently several deficiencies in the implementation, marked with
// FIXME in the code.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/Statistic.h"
#include <set>
using namespace llvm;
namespace {
Statistic<> NumReduced ("loop-reduce", "Number of GEPs strength reduced");
class LoopStrengthReduce : public FunctionPass {
LoopInfo *LI;
DominatorSet *DS;
bool Changed;
public:
virtual bool runOnFunction(Function &) {
LI = &getAnalysis<LoopInfo>();
DS = &getAnalysis<DominatorSet>();
Changed = false;
for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I)
runOnLoop(*I);
return Changed;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
Jeff Cohen
committed
AU.addRequiredID(LoopSimplifyID);
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
AU.addRequired<LoopInfo>();
AU.addRequired<DominatorSet>();
}
private:
void runOnLoop(Loop *L);
void strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
Instruction *InsertBefore,
std::set<Instruction*> &DeadInsts);
void DeleteTriviallyDeadInstructions(std::set<Instruction*> &Insts);
};
RegisterOpt<LoopStrengthReduce> X("loop-reduce",
"Strength Reduce GEP Uses of Ind. Vars");
}
FunctionPass *llvm::createLoopStrengthReducePass() {
return new LoopStrengthReduce();
}
/// DeleteTriviallyDeadInstructions - If any of the instructions is the
/// specified set are trivially dead, delete them and see if this makes any of
/// their operands subsequently dead.
void LoopStrengthReduce::
DeleteTriviallyDeadInstructions(std::set<Instruction*> &Insts) {
while (!Insts.empty()) {
Instruction *I = *Insts.begin();
Insts.erase(Insts.begin());
if (isInstructionTriviallyDead(I)) {
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
if (Instruction *U = dyn_cast<Instruction>(I->getOperand(i)))
Insts.insert(U);
I->getParent()->getInstList().erase(I);
Changed = true;
}
}
}
void LoopStrengthReduce::strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
Instruction *InsertBefore,
std::set<Instruction*> &DeadInsts) {
// We will strength reduce the GEP by splitting it into two parts. The first
// is a GEP to hold the initial value of the non-strength-reduced GEP upon
// entering the loop, which we will insert at the end of the loop preheader.
// The second is a GEP to hold the incremented value of the initial GEP.
// The LoopIndVarSimplify pass guarantees that loop counts start at zero, so
// we will replace the indvar with a constant zero value to create the first
// GEP.
//
// We currently only handle GEP instructions that consist of zero or more
// constants and one instance of the canonical induction variable.
Jeff Cohen
committed
unsigned indvar = 0;
std::vector<Value *> pre_op_vector;
std::vector<Value *> inc_op_vector;
Value *CanonicalIndVar = L->getCanonicalInductionVariable();
Jeff Cohen
committed
BasicBlock *Header = L->getHeader();
for (unsigned op = 1, e = GEPI->getNumOperands(); op != e; ++op) {
Value *operand = GEPI->getOperand(op);
if (operand == CanonicalIndVar) {
// FIXME: use getCanonicalInductionVariableIncrement to choose between
// one and neg one maybe? We need to support int *foo = GEP base, -1
const Type *Ty = CanonicalIndVar->getType();
pre_op_vector.push_back(Constant::getNullValue(Ty));
inc_op_vector.push_back(ConstantInt::get(Ty, 1));
Jeff Cohen
committed
indvar = op;
break;
} else if (isa<Constant>(operand)) {
pre_op_vector.push_back(operand);
Jeff Cohen
committed
} else if (Instruction *inst = dyn_cast<Instruction>(operand)) {
if (!DS->dominates(inst, Header->begin()))
return;
pre_op_vector.push_back(operand);
} else
return;
}
Jeff Cohen
committed
assert(indvar > 0 && "Indvar used by GEP not found in operand list");
Jeff Cohen
committed
// Ensure the pointer base is loop invariant. While strength reduction
// makes sense even if the pointer changed on every iteration, there is no
// realistic way of handling it unless GEPs were completely decomposed into
// their constituent operations so we have explicit multiplications to work
// with.
if (Instruction *GepPtrOp = dyn_cast<Instruction>(GEPI->getOperand(0)))
if (!DS->dominates(GepPtrOp, Header->begin()))
return;
// If all operands of the GEP we are going to insert into the preheader
// are constants, generate a GEP ConstantExpr instead.
//
// If there is only one operand after the initial non-constant one, we know
// that it was the induction variable, and has been replaced by a constant
// null value. In this case, replace the GEP with a use of pointer directly.
BasicBlock *Preheader = L->getLoopPreheader();
Value *PreGEP;
if (isa<Constant>(GEPI->getOperand(0))) {
Constant *C = dyn_cast<Constant>(GEPI->getOperand(0));
PreGEP = ConstantExpr::getGetElementPtr(C, pre_op_vector);
} else if (pre_op_vector.size() == 1) {
PreGEP = GEPI->getOperand(0);
} else {
PreGEP = new GetElementPtrInst(GEPI->getOperand(0),
Jeff Cohen
committed
pre_op_vector, GEPI->getName()+".pre",
Preheader->getTerminator());
}
// The next step of the strength reduction is to create a PHI that will choose
// between the initial GEP we created and inserted into the preheader, and
// the incremented GEP that we will create below and insert into the loop body
PHINode *NewPHI = new PHINode(PreGEP->getType(),
GEPI->getName()+".str", InsertBefore);
NewPHI->addIncoming(PreGEP, Preheader);
Jeff Cohen
committed
// Now, create the GEP instruction to increment by one the value selected by
// the PHI instruction we just created above, and add it as the second
// incoming Value/BasicBlock pair to the PHINode. It is inserted before the
// increment of the canonical induction variable.
Instruction *IncrInst =
const_cast<Instruction*>(L->getCanonicalInductionVariableIncrement());
GetElementPtrInst *StrGEP = new GetElementPtrInst(NewPHI, inc_op_vector,
GEPI->getName()+".inc",
IncrInst);
NewPHI->addIncoming(StrGEP, IncrInst->getParent());
Jeff Cohen
committed
if (GEPI->getNumOperands() - 1 == indvar) {
// If there were no operands following the induction variable, replace all
// uses of the old GEP instruction with the new PHI.
GEPI->replaceAllUsesWith(NewPHI);
} else {
// Create a new GEP instruction using the new PHI as the base. The
// operands of the original GEP past the induction variable become
// operands of this new GEP.
std::vector<Value *> op_vector;
const Type *Ty = CanonicalIndVar->getType();
op_vector.push_back(Constant::getNullValue(Ty));
for (unsigned op = indvar + 1; op < GEPI->getNumOperands(); op++)
op_vector.push_back(GEPI->getOperand(op));
GetElementPtrInst *newGEP = new GetElementPtrInst(NewPHI, op_vector,
GEPI->getName() + ".lsr",
GEPI);
GEPI->replaceAllUsesWith(newGEP);
}
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
// The old GEP is now dead.
DeadInsts.insert(GEPI);
++NumReduced;
}
void LoopStrengthReduce::runOnLoop(Loop *L) {
// First step, transform all loops nesting inside of this loop.
for (LoopInfo::iterator I = L->begin(), E = L->end(); I != E; ++I)
runOnLoop(*I);
// Next, get the first PHINode since it is guaranteed to be the canonical
// induction variable for the loop by the preceding IndVarSimplify pass.
PHINode *PN = L->getCanonicalInductionVariable();
if (0 == PN)
return;
// Insert secondary PHI nodes after the canonical induction variable's PHI
// for the strength reduced pointers that we will be creating.
Instruction *InsertBefore = PN->getNext();
// FIXME: Need to use SCEV to detect GEP uses of the indvar, since indvars
// pass creates code like this, which we can't currently detect:
// %tmp.1 = sub uint 2000, %indvar
// %tmp.8 = getelementptr int* %y, uint %tmp.1
// Strength reduce all GEPs in the Loop
std::set<Instruction*> DeadInsts;
for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
UI != UE; ++UI)
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI))
strengthReduceGEP(GEPI, L, InsertBefore, DeadInsts);
// Clean up after ourselves
if (!DeadInsts.empty()) {
DeleteTriviallyDeadInstructions(DeadInsts);
// At this point, we know that we have killed one or more GEP instructions.
// It is worth checking to see if the cann indvar is also dead, so that we
// can remove it as well. The requirements for the cann indvar to be
// considered dead are:
// 1. the cann indvar has one use
// 2. the use is an add instruction
// 3. the add has one use
// 4. the add is used by the cann indvar
// If all four cases above are true, then we can remove both the add and
// the cann indvar.
if (PN->hasOneUse()) {
BinaryOperator *BO = dyn_cast<BinaryOperator>(*(PN->use_begin()));
if (BO && BO->getOpcode() == Instruction::Add)
if (BO->hasOneUse()) {
PHINode *PotentialIndvar = dyn_cast<PHINode>(*(BO->use_begin()));
if (PotentialIndvar && PN == PotentialIndvar) {
PN->dropAllReferences();
DeadInsts.insert(BO);
DeadInsts.insert(PN);
DeleteTriviallyDeadInstructions(DeadInsts);
}
}
}
}
}