Do not rewrite compare instruction using iv of a different stride if the new

stride may be rewritten using the stride of the compare instruction.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43367 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2007-10-25 22:45:20 +00:00
parent ca4571e79f
commit 5f8ebaa5c0

View File

@ -177,11 +177,17 @@ private:
void OptimizeIndvars(Loop *L); void OptimizeIndvars(Loop *L);
bool FindIVForUser(ICmpInst *Cond, IVStrideUse *&CondUse, bool FindIVForUser(ICmpInst *Cond, IVStrideUse *&CondUse,
const SCEVHandle *&CondStride); const SCEVHandle *&CondStride);
bool RequiresTypeConversion(const Type *Ty, const Type *NewTy);
unsigned CheckForIVReuse(bool, const SCEVHandle&, unsigned CheckForIVReuse(bool, const SCEVHandle&,
IVExpr&, const Type*, IVExpr&, const Type*,
const std::vector<BasedUser>& UsersToProcess); const std::vector<BasedUser>& UsersToProcess);
bool ValidStride(bool, int64_t, bool ValidStride(bool, int64_t,
const std::vector<BasedUser>& UsersToProcess); const std::vector<BasedUser>& UsersToProcess);
SCEVHandle CollectIVUsers(const SCEVHandle &Stride,
IVUsersOfOneStride &Uses,
Loop *L,
bool &AllUsesAreAddresses,
std::vector<BasedUser> &UsersToProcess);
void StrengthReduceStridedIVUsers(const SCEVHandle &Stride, void StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
IVUsersOfOneStride &Uses, IVUsersOfOneStride &Uses,
Loop *L, bool isOnlyStride); Loop *L, bool isOnlyStride);
@ -972,6 +978,19 @@ bool LoopStrengthReduce::ValidStride(bool HasBaseReg,
return true; return true;
} }
/// RequiresTypeConversion - Returns true if converting Ty to NewTy is not
/// a nop.
bool LoopStrengthReduce::RequiresTypeConversion(const Type *Ty,
const Type *NewTy) {
if (Ty == NewTy)
return false;
return (!Ty->canLosslesslyBitCastTo(NewTy) &&
!(isa<PointerType>(NewTy) &&
Ty->canLosslesslyBitCastTo(UIntPtrTy)) &&
!(isa<PointerType>(Ty) &&
NewTy->canLosslesslyBitCastTo(UIntPtrTy)));
}
/// CheckForIVReuse - Returns the multiple if the stride is the multiple /// CheckForIVReuse - Returns the multiple if the stride is the multiple
/// of a previous stride and it is a legal value for the target addressing /// of a previous stride and it is a legal value for the target addressing
/// mode scale component and optional base reg. This allows the users of /// mode scale component and optional base reg. This allows the users of
@ -1001,7 +1020,8 @@ unsigned LoopStrengthReduce::CheckForIVReuse(bool HasBaseReg,
IE = SI->second.IVs.end(); II != IE; ++II) IE = SI->second.IVs.end(); II != IE; ++II)
// FIXME: Only handle base == 0 for now. // FIXME: Only handle base == 0 for now.
// Only reuse previous IV if it would not require a type conversion. // Only reuse previous IV if it would not require a type conversion.
if (isZero(II->Base) && II->Base->getType() == Ty) { if (isZero(II->Base) &&
!RequiresTypeConversion(II->Base->getType(),Ty)) {
IV = *II; IV = *II;
return Scale; return Scale;
} }
@ -1030,23 +1050,16 @@ static bool isNonConstantNegative(const SCEVHandle &Expr) {
return SC->getValue()->getValue().isNegative(); return SC->getValue()->getValue().isNegative();
} }
/// StrengthReduceStridedIVUsers - Strength reduce all of the users of a single // CollectIVUsers - Transform our list of users and offsets to a bit more
/// stride of IV. All of the users may have different starting values, and this // complex table. In this new vector, each 'BasedUser' contains 'Base' the base
/// may not be the only stride (we know it is if isOnlyStride is true). // of the strided accessas well as the old information from Uses. We
void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride, // progressively move information from the Base field to the Imm field, until
// we eventually have the full access expression to rewrite the use.
SCEVHandle LoopStrengthReduce::CollectIVUsers(const SCEVHandle &Stride,
IVUsersOfOneStride &Uses, IVUsersOfOneStride &Uses,
Loop *L, Loop *L,
bool isOnlyStride) { bool &AllUsesAreAddresses,
// If all the users are moved to another stride, then there is nothing to do. std::vector<BasedUser> &UsersToProcess) {
if (Uses.Users.size() == 0)
return;
// Transform our list of users and offsets to a bit more complex table. In
// this new vector, each 'BasedUser' contains 'Base' the base of the
// strided accessas well as the old information from Uses. We progressively
// move information from the Base field to the Imm field, until we eventually
// have the full access expression to rewrite the use.
std::vector<BasedUser> UsersToProcess;
UsersToProcess.reserve(Uses.Users.size()); UsersToProcess.reserve(Uses.Users.size());
for (unsigned i = 0, e = Uses.Users.size(); i != e; ++i) { for (unsigned i = 0, e = Uses.Users.size(); i != e; ++i) {
UsersToProcess.push_back(BasedUser(Uses.Users[i], SE)); UsersToProcess.push_back(BasedUser(Uses.Users[i], SE));
@ -1070,17 +1083,6 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
SCEVHandle CommonExprs = SCEVHandle CommonExprs =
RemoveCommonExpressionsFromUseBases(UsersToProcess, SE); RemoveCommonExpressionsFromUseBases(UsersToProcess, SE);
// If we managed to find some expressions in common, we'll need to carry
// their value in a register and add it in for each use. This will take up
// a register operand, which potentially restricts what stride values are
// valid.
bool HaveCommonExprs = !isZero(CommonExprs);
// Keep track if every use in UsersToProcess is an address. If they all are,
// we may be able to rewrite the entire collection of them in terms of a
// smaller-stride IV.
bool AllUsesAreAddresses = true;
// Next, figure out what we can represent in the immediate fields of // Next, figure out what we can represent in the immediate fields of
// instructions. If we can represent anything there, move it to the imm // instructions. If we can represent anything there, move it to the imm
// fields of the BasedUsers. We do this so that it increases the commonality // fields of the BasedUsers. We do this so that it increases the commonality
@ -1136,6 +1138,40 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
} }
} }
return CommonExprs;
}
/// StrengthReduceStridedIVUsers - Strength reduce all of the users of a single
/// stride of IV. All of the users may have different starting values, and this
/// may not be the only stride (we know it is if isOnlyStride is true).
void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
IVUsersOfOneStride &Uses,
Loop *L,
bool isOnlyStride) {
// If all the users are moved to another stride, then there is nothing to do.
if (Uses.Users.size() == 0)
return;
// Keep track if every use in UsersToProcess is an address. If they all are,
// we may be able to rewrite the entire collection of them in terms of a
// smaller-stride IV.
bool AllUsesAreAddresses = true;
// Transform our list of users and offsets to a bit more complex table. In
// this new vector, each 'BasedUser' contains 'Base' the base of the
// strided accessas well as the old information from Uses. We progressively
// move information from the Base field to the Imm field, until we eventually
// have the full access expression to rewrite the use.
std::vector<BasedUser> UsersToProcess;
SCEVHandle CommonExprs = CollectIVUsers(Stride, Uses, L, AllUsesAreAddresses,
UsersToProcess);
// If we managed to find some expressions in common, we'll need to carry
// their value in a register and add it in for each use. This will take up
// a register operand, which potentially restricts what stride values are
// valid.
bool HaveCommonExprs = !isZero(CommonExprs);
// If all uses are addresses, check if it is possible to reuse an IV with a // If all uses are addresses, check if it is possible to reuse an IV with a
// stride that is a factor of this stride. And that the multiple is a number // stride that is a factor of this stride. And that the multiple is a number
// that can be encoded in the scale field of the target addressing mode. And // that can be encoded in the scale field of the target addressing mode. And
@ -1424,9 +1460,6 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond,
if (StrideOrder.size() < 2 || if (StrideOrder.size() < 2 ||
IVUsesByStride[*CondStride].Users.size() != 1) IVUsesByStride[*CondStride].Users.size() != 1)
return Cond; return Cond;
// FIXME: loosen this restriction?
if (!isa<SCEVConstant>(CondUse->Offset))
return Cond;
const SCEVConstant *SC = dyn_cast<SCEVConstant>(*CondStride); const SCEVConstant *SC = dyn_cast<SCEVConstant>(*CondStride);
if (!SC) return Cond; if (!SC) return Cond;
ConstantInt *C = dyn_cast<ConstantInt>(Cond->getOperand(1)); ConstantInt *C = dyn_cast<ConstantInt>(Cond->getOperand(1));
@ -1478,11 +1511,22 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond,
continue; continue;
} }
// FIXME: allow reuse of iv of a smaller type?
NewCmpTy = NewIncV->getType(); NewCmpTy = NewIncV->getType();
if (!CmpTy->canLosslesslyBitCastTo(NewCmpTy) && if (RequiresTypeConversion(CmpTy, NewCmpTy)) {
!(isa<PointerType>(NewCmpTy) && // FIXME: allow reuse of iv of a smaller type?
CmpTy->canLosslesslyBitCastTo(UIntPtrTy))) { NewCmpVal = CmpVal;
continue;
}
bool AllUsesAreAddresses = true;
std::vector<BasedUser> UsersToProcess;
SCEVHandle CommonExprs = CollectIVUsers(SI->first, SI->second, L,
AllUsesAreAddresses,
UsersToProcess);
// Avoid rewriting the compare instruction with an iv of new stride
// if it's likely the new stride uses will be rewritten using the
if (AllUsesAreAddresses &&
ValidStride(!isZero(CommonExprs), Scale, UsersToProcess)) {
NewCmpVal = CmpVal; NewCmpVal = CmpVal;
continue; continue;
} }