forked from OSchip/llvm-project
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). llvm-svn: 22649
This commit is contained in:
parent
5adb830b30
commit
eaf24725b2
|
@ -138,9 +138,10 @@ namespace {
|
||||||
Value *getCastedVersionOf(Value *V);
|
Value *getCastedVersionOf(Value *V);
|
||||||
private:
|
private:
|
||||||
void runOnLoop(Loop *L);
|
void runOnLoop(Loop *L);
|
||||||
bool AddUsersIfInteresting(Instruction *I, Loop *L);
|
bool AddUsersIfInteresting(Instruction *I, Loop *L,
|
||||||
void AnalyzeGetElementPtrUsers(GetElementPtrInst *GEP, Instruction *I,
|
std::set<Instruction*> &Processed);
|
||||||
Loop *L);
|
SCEVHandle GetExpressionSCEV(Instruction *E, Loop *L);
|
||||||
|
|
||||||
|
|
||||||
void StrengthReduceStridedIVUsers(Value *Stride, IVUsersOfOneStride &Uses,
|
void StrengthReduceStridedIVUsers(Value *Stride, IVUsersOfOneStride &Uses,
|
||||||
Loop *L, bool isOnlyStride);
|
Loop *L, bool isOnlyStride);
|
||||||
|
@ -234,48 +235,24 @@ static bool CanReduceSCEV(const SCEVHandle &SH, Loop *L) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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);
|
||||||
|
|
||||||
/// 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) {
|
|
||||||
// Analyze all of the subscripts of this getelementptr instruction, looking
|
// Analyze all of the subscripts of this getelementptr instruction, looking
|
||||||
// for uses that are determined by the trip count of L. First, skip all
|
// for uses that are determined by the trip count of L. First, skip all
|
||||||
// operands the are not dependent on the IV.
|
// operands the are not dependent on the IV.
|
||||||
|
|
||||||
// Build up the base expression. Insert an LLVM cast of the pointer to
|
// Build up the base expression. Insert an LLVM cast of the pointer to
|
||||||
// uintptr_t first.
|
// 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);
|
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
|
// 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
|
// Op does in the GEP operand list, we will handle this when we process this
|
||||||
// operand.
|
// operand.
|
||||||
|
@ -283,104 +260,37 @@ void LoopStrengthReduce::AnalyzeGetElementPtrUsers(GetElementPtrInst *GEP,
|
||||||
const StructLayout *SL = TD->getStructLayout(STy);
|
const StructLayout *SL = TD->getStructLayout(STy);
|
||||||
unsigned Idx = cast<ConstantUInt>(GEP->getOperand(i))->getValue();
|
unsigned Idx = cast<ConstantUInt>(GEP->getOperand(i))->getValue();
|
||||||
uint64_t Offset = SL->MemberOffsets[Idx];
|
uint64_t Offset = SL->MemberOffsets[Idx];
|
||||||
Base = SCEVAddExpr::get(Base, SCEVUnknown::getIntegerSCEV(Offset,
|
GEPVal = SCEVAddExpr::get(GEPVal,
|
||||||
UIntPtrTy));
|
SCEVUnknown::getIntegerSCEV(Offset, UIntPtrTy));
|
||||||
} else {
|
} else {
|
||||||
SCEVHandle Idx = SE->getSCEV(GEP->getOperand(i));
|
SCEVHandle Idx = SE->getSCEV(getCastedVersionOf(GEP->getOperand(i)));
|
||||||
|
uint64_t TypeSize = TD->getTypeSize(GTI.getIndexedType());
|
||||||
// If this operand is reducible, and it's not the one we are looking at
|
if (TypeSize != 1)
|
||||||
// currently, do not process the GEP at this time.
|
Idx = SCEVMulExpr::get(Idx,
|
||||||
if (CanReduceSCEV(Idx, L))
|
SCEVConstant::get(ConstantUInt::get(UIntPtrTy,
|
||||||
return;
|
TypeSize)));
|
||||||
Base = SCEVAddExpr::get(Base, GetAdjustedIndex(Idx,
|
GEPVal = SCEVAddExpr::get(GEPVal, Idx);
|
||||||
TD->getTypeSize(GTI.getIndexedType()), UIntPtrTy));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the index, convert it to intptr_t.
|
//assert(CanReduceSCEV(GEPVal, L) && "Cannot reduce this use of IV?");
|
||||||
SCEVHandle GEPIndexExpr =
|
return GEPVal;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AddUsersIfInteresting - Inspect the specified instruction. If it is a
|
/// AddUsersIfInteresting - Inspect the specified instruction. If it is a
|
||||||
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
|
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
|
||||||
/// return true. Otherwise, return false.
|
/// 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;
|
if (I->getType() == Type::VoidTy) return false;
|
||||||
SCEVHandle ISE = SE->getSCEV(I);
|
if (!Processed.insert(I).second)
|
||||||
if (!CanReduceSCEV(ISE, L)) return false;
|
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);
|
SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(ISE);
|
||||||
SCEVHandle Start = AR->getStart();
|
SCEVHandle Start = AR->getStart();
|
||||||
|
|
||||||
|
@ -395,8 +305,6 @@ bool LoopStrengthReduce::AddUsersIfInteresting(Instruction *I, Loop *L) {
|
||||||
Step = cast<SCEVUnknown>(AR->getOperand(1))->getValue();
|
Step = cast<SCEVUnknown>(AR->getOperand(1))->getValue();
|
||||||
assert(Step->getType()->isUnsigned() && "Bad step value!");
|
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){
|
for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;++UI){
|
||||||
Instruction *User = cast<Instruction>(*UI);
|
Instruction *User = cast<Instruction>(*UI);
|
||||||
|
|
||||||
|
@ -413,16 +321,7 @@ bool LoopStrengthReduce::AddUsersIfInteresting(Instruction *I, Loop *L) {
|
||||||
// Okay, we found a user that we cannot reduce. Analyze the instruction
|
// Okay, we found a user that we cannot reduce. Analyze the instruction
|
||||||
// and decide what to do with it.
|
// and decide what to do with it.
|
||||||
IVUsesByStride[Step].addUser(Start, User, I);
|
IVUsesByStride[Step].addUser(Start, User, I);
|
||||||
continue;
|
} else if (!AddUsersIfInteresting(User, L, Processed)) {
|
||||||
}
|
|
||||||
|
|
||||||
// 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)) {
|
|
||||||
DEBUG(std::cerr << "FOUND USER: " << *User
|
DEBUG(std::cerr << "FOUND USER: " << *User
|
||||||
<< " OF SCEV: " << *ISE << "\n");
|
<< " OF SCEV: " << *ISE << "\n");
|
||||||
|
|
||||||
|
@ -655,8 +554,9 @@ void LoopStrengthReduce::runOnLoop(Loop *L) {
|
||||||
// Next, find all uses of induction variables in this loop, and catagorize
|
// 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
|
// 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.
|
// 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)
|
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 we have nothing to do, return.
|
||||||
//if (IVUsesByStride.empty()) return;
|
//if (IVUsesByStride.empty()) return;
|
||||||
|
|
Loading…
Reference in New Issue