forked from OSchip/llvm-project
SLPVectorizer: Speedup isConsecutive (that checks if two addresses are consecutive in memory) by checking for additional patterns that don't need to go through SCEV.
llvm-svn: 186563
This commit is contained in:
parent
1860763c76
commit
7d7036b8c6
|
@ -989,26 +989,45 @@ bool BoUpSLP::isConsecutiveAccess(Value *A, Value *B) {
|
||||||
// uses the other pointer.
|
// uses the other pointer.
|
||||||
GetElementPtrInst *GepA = dyn_cast<GetElementPtrInst>(PtrA);
|
GetElementPtrInst *GepA = dyn_cast<GetElementPtrInst>(PtrA);
|
||||||
GetElementPtrInst *GepB = dyn_cast<GetElementPtrInst>(PtrB);
|
GetElementPtrInst *GepB = dyn_cast<GetElementPtrInst>(PtrB);
|
||||||
if (GepA && GepB && GepA->getPointerOperand() == GepB->getPointerOperand()) {
|
|
||||||
unsigned BW = DL->getPointerSizeInBits(ASA);
|
|
||||||
APInt OffsetA(BW, 0) ,OffsetB(BW, 0);
|
|
||||||
|
|
||||||
|
unsigned BW = DL->getPointerSizeInBits(ASA);
|
||||||
|
Type *Ty = cast<PointerType>(PtrA->getType())->getElementType();
|
||||||
|
int64_t Sz = DL->getTypeStoreSize(Ty);
|
||||||
|
|
||||||
|
// If both pointers are GEPs:
|
||||||
|
if (GepA && GepB) {
|
||||||
|
// Check that they have the same base pointer.
|
||||||
|
if (GepA->getPointerOperand() != GepB->getPointerOperand())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if the geps use a constant offset.
|
||||||
|
APInt OffsetA(BW, 0) ,OffsetB(BW, 0);
|
||||||
if (GepA->accumulateConstantOffset(*DL, OffsetA) &&
|
if (GepA->accumulateConstantOffset(*DL, OffsetA) &&
|
||||||
GepB->accumulateConstantOffset(*DL, OffsetB)) {
|
GepB->accumulateConstantOffset(*DL, OffsetB))
|
||||||
Type *Ty = cast<PointerType>(PtrA->getType())->getElementType();
|
|
||||||
int64_t Sz = DL->getTypeStoreSize(Ty);
|
|
||||||
return ((OffsetB.getSExtValue() - OffsetA.getSExtValue()) == Sz);
|
return ((OffsetB.getSExtValue() - OffsetA.getSExtValue()) == Sz);
|
||||||
|
|
||||||
|
// Try to strip the geps. This makes SCEV faster.
|
||||||
|
if (GepA->getNumIndices() == 1 && GepB->getNumIndices() == 1) {
|
||||||
|
PtrA = GepA->getOperand(1);
|
||||||
|
PtrB = GepB->getOperand(1);
|
||||||
|
Sz = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if PtrA is the base and PtrB is a constant offset.
|
||||||
|
if (GepB && GepB->getPointerOperand() == PtrA) {
|
||||||
|
APInt Offset(BW, 0);
|
||||||
|
if (GepB->accumulateConstantOffset(*DL, Offset))
|
||||||
|
return Offset.getZExtValue() == DL->getTypeStoreSize(Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GepA can't use PtrB as a base pointer.
|
||||||
|
if (GepA && GepA->getPointerOperand() == PtrB)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Calculate the distance.
|
// Calculate the distance.
|
||||||
const SCEV *PtrSCEVA = SE->getSCEV(PtrA);
|
const SCEV *PtrSCEVA = SE->getSCEV(PtrA);
|
||||||
const SCEV *PtrSCEVB = SE->getSCEV(PtrB);
|
const SCEV *PtrSCEVB = SE->getSCEV(PtrB);
|
||||||
Type *Ty = cast<PointerType>(PtrA->getType())->getElementType();
|
|
||||||
// The instructions are consecutive if the size of the first load/store is
|
|
||||||
// the same as the offset.
|
|
||||||
int64_t Sz = DL->getTypeStoreSize(Ty);
|
|
||||||
|
|
||||||
const SCEV *C = SE->getConstant(PtrSCEVA->getType(), Sz);
|
const SCEV *C = SE->getConstant(PtrSCEVA->getType(), Sz);
|
||||||
const SCEV *X = SE->getAddExpr(PtrSCEVA, C);
|
const SCEV *X = SE->getAddExpr(PtrSCEVA, C);
|
||||||
return X == PtrSCEVB;
|
return X == PtrSCEVB;
|
||||||
|
|
Loading…
Reference in New Issue