mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-11 10:25:41 +00:00
Generalize the ChangeCompareStride code, in preparation for
handling non-constant strides. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65363 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -2133,15 +2133,12 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond,
|
|||||||
return Cond;
|
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));
|
|
||||||
if (!C) return Cond;
|
|
||||||
|
|
||||||
ICmpInst::Predicate Predicate = Cond->getPredicate();
|
ICmpInst::Predicate Predicate = Cond->getPredicate();
|
||||||
int64_t CmpSSInt = SC->getValue()->getSExtValue();
|
int64_t CmpSSInt = SC->getValue()->getSExtValue();
|
||||||
int64_t CmpVal = C->getValue().getSExtValue();
|
unsigned BitWidth = (*CondStride)->getBitWidth();
|
||||||
unsigned BitWidth = C->getValue().getBitWidth();
|
|
||||||
uint64_t SignBit = 1ULL << (BitWidth-1);
|
uint64_t SignBit = 1ULL << (BitWidth-1);
|
||||||
const Type *CmpTy = C->getType();
|
const Type *CmpTy = Cond->getOperand(0)->getType();
|
||||||
const Type *NewCmpTy = NULL;
|
const Type *NewCmpTy = NULL;
|
||||||
unsigned TyBits = CmpTy->getPrimitiveSizeInBits();
|
unsigned TyBits = CmpTy->getPrimitiveSizeInBits();
|
||||||
unsigned NewTyBits = 0;
|
unsigned NewTyBits = 0;
|
||||||
@@ -2149,102 +2146,112 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond,
|
|||||||
Value *NewCmpLHS = NULL;
|
Value *NewCmpLHS = NULL;
|
||||||
Value *NewCmpRHS = NULL;
|
Value *NewCmpRHS = NULL;
|
||||||
int64_t Scale = 1;
|
int64_t Scale = 1;
|
||||||
|
SCEVHandle NewOffset = SE->getIntegerSCEV(0, UIntPtrTy);
|
||||||
// Check stride constant and the comparision constant signs to detect
|
|
||||||
// overflow.
|
|
||||||
if ((CmpVal & SignBit) != (CmpSSInt & SignBit))
|
|
||||||
return Cond;
|
|
||||||
|
|
||||||
// Look for a suitable stride / iv as replacement.
|
|
||||||
std::stable_sort(StrideOrder.begin(), StrideOrder.end(), StrideCompare());
|
std::stable_sort(StrideOrder.begin(), StrideOrder.end(), StrideCompare());
|
||||||
for (unsigned i = 0, e = StrideOrder.size(); i != e; ++i) {
|
|
||||||
std::map<SCEVHandle, IVUsersOfOneStride>::iterator SI =
|
|
||||||
IVUsesByStride.find(StrideOrder[i]);
|
|
||||||
if (!isa<SCEVConstant>(SI->first))
|
|
||||||
continue;
|
|
||||||
int64_t SSInt = cast<SCEVConstant>(SI->first)->getValue()->getSExtValue();
|
|
||||||
if (abs(SSInt) <= abs(CmpSSInt) || (SSInt % CmpSSInt) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Scale = SSInt / CmpSSInt;
|
if (ConstantInt *C = dyn_cast<ConstantInt>(Cond->getOperand(1))) {
|
||||||
int64_t NewCmpVal = CmpVal * Scale;
|
int64_t CmpVal = C->getValue().getSExtValue();
|
||||||
APInt Mul = APInt(BitWidth, NewCmpVal);
|
|
||||||
// Check for overflow.
|
|
||||||
if (Mul.getSExtValue() != NewCmpVal)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Watch out for overflow.
|
// Check stride constant and the comparision constant signs to detect
|
||||||
if (ICmpInst::isSignedPredicate(Predicate) &&
|
// overflow.
|
||||||
(CmpVal & SignBit) != (NewCmpVal & SignBit))
|
if ((CmpVal & SignBit) != (CmpSSInt & SignBit))
|
||||||
continue;
|
return Cond;
|
||||||
|
|
||||||
if (NewCmpVal == CmpVal)
|
// Look for a suitable stride / iv as replacement.
|
||||||
continue;
|
for (unsigned i = 0, e = StrideOrder.size(); i != e; ++i) {
|
||||||
// Pick the best iv to use trying to avoid a cast.
|
std::map<SCEVHandle, IVUsersOfOneStride>::iterator SI =
|
||||||
NewCmpLHS = NULL;
|
IVUsesByStride.find(StrideOrder[i]);
|
||||||
for (std::vector<IVStrideUse>::iterator UI = SI->second.Users.begin(),
|
if (!isa<SCEVConstant>(SI->first))
|
||||||
E = SI->second.Users.end(); UI != E; ++UI) {
|
|
||||||
NewCmpLHS = UI->OperandValToReplace;
|
|
||||||
if (NewCmpLHS->getType() == CmpTy)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!NewCmpLHS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
NewCmpTy = NewCmpLHS->getType();
|
|
||||||
NewTyBits = isa<PointerType>(NewCmpTy)
|
|
||||||
? UIntPtrTy->getPrimitiveSizeInBits()
|
|
||||||
: NewCmpTy->getPrimitiveSizeInBits();
|
|
||||||
if (RequiresTypeConversion(NewCmpTy, CmpTy)) {
|
|
||||||
// Check if it is possible to rewrite it using
|
|
||||||
// an iv / stride of a smaller integer type.
|
|
||||||
bool TruncOk = false;
|
|
||||||
if (NewCmpTy->isInteger()) {
|
|
||||||
unsigned Bits = NewTyBits;
|
|
||||||
if (ICmpInst::isSignedPredicate(Predicate))
|
|
||||||
--Bits;
|
|
||||||
uint64_t Mask = (1ULL << Bits) - 1;
|
|
||||||
if (((uint64_t)NewCmpVal & Mask) == (uint64_t)NewCmpVal)
|
|
||||||
TruncOk = true;
|
|
||||||
}
|
|
||||||
if (!TruncOk)
|
|
||||||
continue;
|
continue;
|
||||||
|
int64_t SSInt = cast<SCEVConstant>(SI->first)->getValue()->getSExtValue();
|
||||||
|
if (abs(SSInt) <= abs(CmpSSInt) || (SSInt % CmpSSInt) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Scale = SSInt / CmpSSInt;
|
||||||
|
int64_t NewCmpVal = CmpVal * Scale;
|
||||||
|
APInt Mul = APInt(BitWidth, NewCmpVal);
|
||||||
|
// Check for overflow.
|
||||||
|
if (Mul.getSExtValue() != NewCmpVal)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Watch out for overflow.
|
||||||
|
if (ICmpInst::isSignedPredicate(Predicate) &&
|
||||||
|
(CmpVal & SignBit) != (NewCmpVal & SignBit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (NewCmpVal == CmpVal)
|
||||||
|
continue;
|
||||||
|
// Pick the best iv to use trying to avoid a cast.
|
||||||
|
NewCmpLHS = NULL;
|
||||||
|
for (std::vector<IVStrideUse>::iterator UI = SI->second.Users.begin(),
|
||||||
|
E = SI->second.Users.end(); UI != E; ++UI) {
|
||||||
|
NewCmpLHS = UI->OperandValToReplace;
|
||||||
|
if (NewCmpLHS->getType() == CmpTy)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!NewCmpLHS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NewCmpTy = NewCmpLHS->getType();
|
||||||
|
NewTyBits = isa<PointerType>(NewCmpTy)
|
||||||
|
? UIntPtrTy->getPrimitiveSizeInBits()
|
||||||
|
: NewCmpTy->getPrimitiveSizeInBits();
|
||||||
|
if (RequiresTypeConversion(NewCmpTy, CmpTy)) {
|
||||||
|
// Check if it is possible to rewrite it using
|
||||||
|
// an iv / stride of a smaller integer type.
|
||||||
|
bool TruncOk = false;
|
||||||
|
if (NewCmpTy->isInteger()) {
|
||||||
|
unsigned Bits = NewTyBits;
|
||||||
|
if (ICmpInst::isSignedPredicate(Predicate))
|
||||||
|
--Bits;
|
||||||
|
uint64_t Mask = (1ULL << Bits) - 1;
|
||||||
|
if (((uint64_t)NewCmpVal & Mask) == (uint64_t)NewCmpVal)
|
||||||
|
TruncOk = true;
|
||||||
|
}
|
||||||
|
if (!TruncOk)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't rewrite if use offset is non-constant and the new type is
|
||||||
|
// of a different type.
|
||||||
|
// FIXME: too conservative?
|
||||||
|
if (NewTyBits != TyBits && !isa<SCEVConstant>(CondUse->Offset))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool AllUsesAreAddresses = true;
|
||||||
|
bool AllUsesAreOutsideLoop = true;
|
||||||
|
std::vector<BasedUser> UsersToProcess;
|
||||||
|
SCEVHandle CommonExprs = CollectIVUsers(SI->first, SI->second, L,
|
||||||
|
AllUsesAreAddresses,
|
||||||
|
AllUsesAreOutsideLoop,
|
||||||
|
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
|
||||||
|
// stride of the compare instruction.
|
||||||
|
if (AllUsesAreAddresses &&
|
||||||
|
ValidStride(!CommonExprs->isZero(), Scale, UsersToProcess))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If scale is negative, use swapped predicate unless it's testing
|
||||||
|
// for equality.
|
||||||
|
if (Scale < 0 && !Cond->isEquality())
|
||||||
|
Predicate = ICmpInst::getSwappedPredicate(Predicate);
|
||||||
|
|
||||||
|
NewStride = &StrideOrder[i];
|
||||||
|
if (!isa<PointerType>(NewCmpTy))
|
||||||
|
NewCmpRHS = ConstantInt::get(NewCmpTy, NewCmpVal);
|
||||||
|
else {
|
||||||
|
NewCmpRHS = ConstantInt::get(UIntPtrTy, NewCmpVal);
|
||||||
|
NewCmpRHS = SCEVExpander::InsertCastOfTo(Instruction::IntToPtr,
|
||||||
|
NewCmpRHS, NewCmpTy);
|
||||||
|
}
|
||||||
|
NewOffset = TyBits == NewTyBits
|
||||||
|
? SE->getMulExpr(CondUse->Offset,
|
||||||
|
SE->getConstant(ConstantInt::get(CmpTy, Scale)))
|
||||||
|
: SE->getConstant(ConstantInt::get(NewCmpTy,
|
||||||
|
cast<SCEVConstant>(CondUse->Offset)->getValue()->getSExtValue()*Scale));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't rewrite if use offset is non-constant and the new type is
|
|
||||||
// of a different type.
|
|
||||||
// FIXME: too conservative?
|
|
||||||
if (NewTyBits != TyBits && !isa<SCEVConstant>(CondUse->Offset))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bool AllUsesAreAddresses = true;
|
|
||||||
bool AllUsesAreOutsideLoop = true;
|
|
||||||
std::vector<BasedUser> UsersToProcess;
|
|
||||||
SCEVHandle CommonExprs = CollectIVUsers(SI->first, SI->second, L,
|
|
||||||
AllUsesAreAddresses,
|
|
||||||
AllUsesAreOutsideLoop,
|
|
||||||
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
|
|
||||||
// stride of the compare instruction.
|
|
||||||
if (AllUsesAreAddresses &&
|
|
||||||
ValidStride(!CommonExprs->isZero(), Scale, UsersToProcess))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If scale is negative, use swapped predicate unless it's testing
|
|
||||||
// for equality.
|
|
||||||
if (Scale < 0 && !Cond->isEquality())
|
|
||||||
Predicate = ICmpInst::getSwappedPredicate(Predicate);
|
|
||||||
|
|
||||||
NewStride = &StrideOrder[i];
|
|
||||||
if (!isa<PointerType>(NewCmpTy))
|
|
||||||
NewCmpRHS = ConstantInt::get(NewCmpTy, NewCmpVal);
|
|
||||||
else {
|
|
||||||
NewCmpRHS = ConstantInt::get(UIntPtrTy, NewCmpVal);
|
|
||||||
NewCmpRHS = SCEVExpander::InsertCastOfTo(Instruction::IntToPtr,
|
|
||||||
NewCmpRHS, NewCmpTy);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forgo this transformation if it the increment happens to be
|
// Forgo this transformation if it the increment happens to be
|
||||||
@@ -2275,11 +2282,6 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond,
|
|||||||
OldCond->eraseFromParent();
|
OldCond->eraseFromParent();
|
||||||
|
|
||||||
IVUsesByStride[*CondStride].Users.pop_back();
|
IVUsesByStride[*CondStride].Users.pop_back();
|
||||||
SCEVHandle NewOffset = TyBits == NewTyBits
|
|
||||||
? SE->getMulExpr(CondUse->Offset,
|
|
||||||
SE->getConstant(ConstantInt::get(CmpTy, Scale)))
|
|
||||||
: SE->getConstant(ConstantInt::get(NewCmpTy,
|
|
||||||
cast<SCEVConstant>(CondUse->Offset)->getValue()->getSExtValue()*Scale));
|
|
||||||
IVUsesByStride[*NewStride].addUser(NewOffset, Cond, NewCmpLHS);
|
IVUsesByStride[*NewStride].addUser(NewOffset, Cond, NewCmpLHS);
|
||||||
CondUse = &IVUsesByStride[*NewStride].Users.back();
|
CondUse = &IVUsesByStride[*NewStride].Users.back();
|
||||||
CondStride = NewStride;
|
CondStride = NewStride;
|
||||||
|
Reference in New Issue
Block a user