[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
Chris Lattner
lattner at cs.uiuc.edu
Thu Aug 4 10:40:41 PDT 2005
Changes in directory llvm/lib/Transforms/Scalar:
LoopStrengthReduce.cpp updated: 1.30 -> 1.31
---
Log message:
Refactor this code substantially with the following improvements:
1. We only analyze instructions once, guaranteed
2. AnalyzeGetElementPtrUsers has been ripped apart and replaced with
something much simpler.
The next step is to handle expressions that are not all indvar+loop-invariant
values (e.g. handling indvar+loopvariant).
---
Diffs of the changes: (+38 -138)
LoopStrengthReduce.cpp | 176 ++++++++++---------------------------------------
1 files changed, 38 insertions(+), 138 deletions(-)
Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.30 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.31
--- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.30 Wed Aug 3 20:19:13 2005
+++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Thu Aug 4 12:40:30 2005
@@ -138,9 +138,10 @@
Value *getCastedVersionOf(Value *V);
private:
void runOnLoop(Loop *L);
- bool AddUsersIfInteresting(Instruction *I, Loop *L);
- void AnalyzeGetElementPtrUsers(GetElementPtrInst *GEP, Instruction *I,
- Loop *L);
+ bool AddUsersIfInteresting(Instruction *I, Loop *L,
+ std::set<Instruction*> &Processed);
+ SCEVHandle GetExpressionSCEV(Instruction *E, Loop *L);
+
void StrengthReduceStridedIVUsers(Value *Stride, IVUsersOfOneStride &Uses,
Loop *L, bool isOnlyStride);
@@ -234,48 +235,24 @@
return false;
}
-
-/// GetAdjustedIndex - Adjust the specified GEP sequential type index to match
-/// the size of the pointer type, and scale it by the type size.
-static SCEVHandle GetAdjustedIndex(const SCEVHandle &Idx, uint64_t TySize,
- const Type *UIntPtrTy) {
- SCEVHandle Result = Idx;
- if (Result->getType()->getUnsignedVersion() != UIntPtrTy) {
- if (UIntPtrTy->getPrimitiveSize() < Result->getType()->getPrimitiveSize())
- Result = SCEVTruncateExpr::get(Result, UIntPtrTy);
- else
- Result = SCEVZeroExtendExpr::get(Result, UIntPtrTy);
- }
-
- // This index is scaled by the type size being indexed.
- if (TySize != 1)
- Result = SCEVMulExpr::get(Result,
- SCEVConstant::get(ConstantUInt::get(UIntPtrTy,
- TySize)));
- return Result;
-}
-
-
-/// AnalyzeGetElementPtrUsers - Analyze all of the users of the specified
-/// getelementptr instruction, adding them to the IVUsesByStride table. Note
-/// that we only want to analyze a getelementptr instruction once, and it can
-/// have multiple operands that are uses of the indvar (e.g. A[i][i]). Because
-/// of this, we only process a GEP instruction if its first recurrent operand is
-/// "op", otherwise we will either have already processed it or we will sometime
-/// later.
-void LoopStrengthReduce::AnalyzeGetElementPtrUsers(GetElementPtrInst *GEP,
- Instruction *Op, Loop *L) {
+/// GetExpressionSCEV - Compute and return the SCEV for the specified
+/// instruction.
+SCEVHandle LoopStrengthReduce::GetExpressionSCEV(Instruction *Exp, Loop *L) {
+ GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Exp);
+ if (!GEP)
+ return SE->getSCEV(Exp);
+
// Analyze all of the subscripts of this getelementptr instruction, looking
// for uses that are determined by the trip count of L. First, skip all
// operands the are not dependent on the IV.
// Build up the base expression. Insert an LLVM cast of the pointer to
// uintptr_t first.
- SCEVHandle Base = SCEVUnknown::get(getCastedVersionOf(GEP->getOperand(0)));
+ SCEVHandle GEPVal = SCEVUnknown::get(getCastedVersionOf(GEP->getOperand(0)));
gep_type_iterator GTI = gep_type_begin(GEP);
- unsigned i = 1;
- for (; GEP->getOperand(i) != Op; ++i, ++GTI) {
+
+ for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
// If this is a use of a recurrence that we can analyze, and it comes before
// Op does in the GEP operand list, we will handle this when we process this
// operand.
@@ -283,104 +260,37 @@
const StructLayout *SL = TD->getStructLayout(STy);
unsigned Idx = cast<ConstantUInt>(GEP->getOperand(i))->getValue();
uint64_t Offset = SL->MemberOffsets[Idx];
- Base = SCEVAddExpr::get(Base, SCEVUnknown::getIntegerSCEV(Offset,
- UIntPtrTy));
+ GEPVal = SCEVAddExpr::get(GEPVal,
+ SCEVUnknown::getIntegerSCEV(Offset, UIntPtrTy));
} else {
- SCEVHandle Idx = SE->getSCEV(GEP->getOperand(i));
-
- // If this operand is reducible, and it's not the one we are looking at
- // currently, do not process the GEP at this time.
- if (CanReduceSCEV(Idx, L))
- return;
- Base = SCEVAddExpr::get(Base, GetAdjustedIndex(Idx,
- TD->getTypeSize(GTI.getIndexedType()), UIntPtrTy));
+ SCEVHandle Idx = SE->getSCEV(getCastedVersionOf(GEP->getOperand(i)));
+ uint64_t TypeSize = TD->getTypeSize(GTI.getIndexedType());
+ if (TypeSize != 1)
+ Idx = SCEVMulExpr::get(Idx,
+ SCEVConstant::get(ConstantUInt::get(UIntPtrTy,
+ TypeSize)));
+ GEPVal = SCEVAddExpr::get(GEPVal, Idx);
}
}
- // Get the index, convert it to intptr_t.
- SCEVHandle GEPIndexExpr =
- GetAdjustedIndex(SE->getSCEV(Op), TD->getTypeSize(GTI.getIndexedType()),
- UIntPtrTy);
-
- // Process all remaining subscripts in the GEP instruction.
- for (++i, ++GTI; i != GEP->getNumOperands(); ++i, ++GTI)
- if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
- const StructLayout *SL = TD->getStructLayout(STy);
- unsigned Idx = cast<ConstantUInt>(GEP->getOperand(i))->getValue();
- uint64_t Offset = SL->MemberOffsets[Idx];
- Base = SCEVAddExpr::get(Base, SCEVUnknown::getIntegerSCEV(Offset,
- UIntPtrTy));
- } else {
- SCEVHandle Idx = SE->getSCEV(GEP->getOperand(i));
- if (CanReduceSCEV(Idx, L)) { // Another IV subscript
- GEPIndexExpr = SCEVAddExpr::get(GEPIndexExpr,
- GetAdjustedIndex(Idx, TD->getTypeSize(GTI.getIndexedType()),
- UIntPtrTy));
- assert(CanReduceSCEV(GEPIndexExpr, L) &&
- "Cannot reduce the sum of two reducible SCEV's??");
- } else {
- Base = SCEVAddExpr::get(Base, GetAdjustedIndex(Idx,
- TD->getTypeSize(GTI.getIndexedType()), UIntPtrTy));
- }
- }
-
- assert(CanReduceSCEV(GEPIndexExpr, L) && "Non reducible idx??");
-
- // FIXME: If the base is not loop invariant, we currently cannot emit this.
- if (!Base->isLoopInvariant(L)) {
- DEBUG(std::cerr << "IGNORING GEP due to non-invariant base: "
- << *Base << "\n");
- return;
- }
-
- Base = SCEVAddExpr::get(Base, cast<SCEVAddRecExpr>(GEPIndexExpr)->getStart());
- SCEVHandle Stride = cast<SCEVAddRecExpr>(GEPIndexExpr)->getOperand(1);
-
- DEBUG(std::cerr << "GEP BASE : " << *Base << "\n");
- DEBUG(std::cerr << "GEP STRIDE: " << *Stride << "\n");
-
- Value *Step = 0; // Step of ISE.
- if (SCEVConstant *SC = dyn_cast<SCEVConstant>(Stride))
- /// Always get the step value as an unsigned value.
- Step = ConstantExpr::getCast(SC->getValue(),
- SC->getValue()->getType()->getUnsignedVersion());
- else
- Step = cast<SCEVUnknown>(Stride)->getValue();
- assert(Step->getType()->isUnsigned() && "Bad step value!");
-
-
- // Now that we know the base and stride contributed by the GEP instruction,
- // process all users.
- for (Value::use_iterator UI = GEP->use_begin(), E = GEP->use_end();
- UI != E; ++UI) {
- Instruction *User = cast<Instruction>(*UI);
-
- // Do not infinitely recurse on PHI nodes.
- if (isa<PHINode>(User) && User->getParent() == L->getHeader())
- continue;
-
- // If this is an instruction defined in a nested loop, or outside this loop,
- // don't mess with it.
- if (LI->getLoopFor(User->getParent()) != L)
- continue;
-
- DEBUG(std::cerr << "FOUND USER: " << *User
- << " OF STRIDE: " << *Step << " BASE = " << *Base << "\n");
-
- // Okay, we found a user that we cannot reduce. Analyze the instruction
- // and decide what to do with it.
- IVUsesByStride[Step].addUser(Base, User, GEP);
- }
+ //assert(CanReduceSCEV(GEPVal, L) && "Cannot reduce this use of IV?");
+ return GEPVal;
}
/// AddUsersIfInteresting - Inspect the specified instruction. If it is a
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
/// return true. Otherwise, return false.
-bool LoopStrengthReduce::AddUsersIfInteresting(Instruction *I, Loop *L) {
+bool LoopStrengthReduce::AddUsersIfInteresting(Instruction *I, Loop *L,
+ std::set<Instruction*> &Processed) {
if (I->getType() == Type::VoidTy) return false;
- SCEVHandle ISE = SE->getSCEV(I);
- if (!CanReduceSCEV(ISE, L)) return false;
-
+ if (!Processed.insert(I).second)
+ return true; // Instruction already handled.
+
+ SCEVHandle ISE = GetExpressionSCEV(I, L);
+ if (!CanReduceSCEV(ISE, L))
+ return false; // Non-analyzable expression, e.g. a rem instr.
+
+ // NOT SAFE with generalized EXPRS
SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(ISE);
SCEVHandle Start = AR->getStart();
@@ -395,8 +305,6 @@
Step = cast<SCEVUnknown>(AR->getOperand(1))->getValue();
assert(Step->getType()->isUnsigned() && "Bad step value!");
- std::set<GetElementPtrInst*> AnalyzedGEPs;
-
for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;++UI){
Instruction *User = cast<Instruction>(*UI);
@@ -413,16 +321,7 @@
// Okay, we found a user that we cannot reduce. Analyze the instruction
// and decide what to do with it.
IVUsesByStride[Step].addUser(Start, User, I);
- continue;
- }
-
- // Next, see if this user is analyzable itself!
- if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
- // If this is a getelementptr instruction, figure out what linear
- // expression of induction variable is actually being used.
- if (AnalyzedGEPs.insert(GEP).second) // Not already analyzed?
- AnalyzeGetElementPtrUsers(GEP, I, L);
- } else if (!AddUsersIfInteresting(User, L)) {
+ } else if (!AddUsersIfInteresting(User, L, Processed)) {
DEBUG(std::cerr << "FOUND USER: " << *User
<< " OF SCEV: " << *ISE << "\n");
@@ -655,8 +554,9 @@
// Next, find all uses of induction variables in this loop, and catagorize
// them by stride. Start by finding all of the PHI nodes in the header for
// this loop. If they are induction variables, inspect their uses.
+ std::set<Instruction*> Processed; // Don't reprocess instructions.
for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I)
- AddUsersIfInteresting(I, L);
+ AddUsersIfInteresting(I, L, Processed);
// If we have nothing to do, return.
//if (IVUsesByStride.empty()) return;
More information about the llvm-commits
mailing list