INITIALIZE_PASS_BEGIN(DependenceAnalysis, "da",
"Dependence Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(DependenceAnalysis, "da",
"Dependence Analysis", true, true)
bool DependenceAnalysis::runOnFunction(Function &F) {
this->F = &F;
- AA = &getAnalysis<AliasAnalysis>();
- SE = &getAnalysis<ScalarEvolution>();
+ AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
+ SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
return false;
}
void DependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
- AU.addRequiredTransitive<AliasAnalysis>();
- AU.addRequiredTransitive<ScalarEvolution>();
+ AU.addRequiredTransitive<AAResultsWrapperPass>();
+ AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
AU.addRequiredTransitive<LoopInfoWrapperPass>();
}
: Dependence(Source, Destination), Levels(CommonLevels),
LoopIndependent(PossiblyLoopIndependent) {
Consistent = true;
- DV = CommonLevels ? new DVEntry[CommonLevels] : nullptr;
+ if (CommonLevels)
+ DV = make_unique<DVEntry[]>(CommonLevels);
}
// The rest are simple getters that hide the implementation.
void DependenceAnalysis::Constraint::setDistance(const SCEV *D,
const Loop *CurLoop) {
Kind = Distance;
- A = SE->getConstant(D->getType(), 1);
+ A = SE->getOne(D->getType());
B = SE->getNegativeSCEV(A);
C = SE->getNegativeSCEV(D);
AssociatedLoop = CurLoop;
if (!C1B2_C2B1 || !C1A2_C2A1 ||
!A1B2_A2B1 || !A2B1_A1B2)
return false;
- APInt Xtop = C1B2_C2B1->getValue()->getValue();
- APInt Xbot = A1B2_A2B1->getValue()->getValue();
- APInt Ytop = C1A2_C2A1->getValue()->getValue();
- APInt Ybot = A2B1_A1B2->getValue()->getValue();
+ APInt Xtop = C1B2_C2B1->getAPInt();
+ APInt Xbot = A1B2_A2B1->getAPInt();
+ APInt Ytop = C1A2_C2A1->getAPInt();
+ APInt Ybot = A2B1_A1B2->getAPInt();
DEBUG(dbgs() << "\t\tXtop = " << Xtop << "\n");
DEBUG(dbgs() << "\t\tXbot = " << Xbot << "\n");
DEBUG(dbgs() << "\t\tYtop = " << Ytop << "\n");
}
if (const SCEVConstant *CUB =
collectConstantUpperBound(X->getAssociatedLoop(), Prod1->getType())) {
- APInt UpperBound = CUB->getValue()->getValue();
+ APInt UpperBound = CUB->getAPInt();
DEBUG(dbgs() << "\t\tupper bound = " << UpperBound << "\n");
if (Xq.sgt(UpperBound) || Yq.sgt(UpperBound)) {
X->setEmpty();
OS << "!\n";
}
-static AliasAnalysis::AliasResult underlyingObjectsAlias(AliasAnalysis *AA,
- const DataLayout &DL,
- const Value *A,
- const Value *B) {
+static AliasResult underlyingObjectsAlias(AliasAnalysis *AA,
+ const DataLayout &DL, const Value *A,
+ const Value *B) {
const Value *AObj = GetUnderlyingObject(A, DL);
const Value *BObj = GetUnderlyingObject(B, DL);
- return AA->alias(AObj, AA->getTypeStoreSize(AObj->getType()),
- BObj, AA->getTypeStoreSize(BObj->getType()));
+ return AA->alias(AObj, DL.getTypeStoreSize(AObj->getType()),
+ BObj, DL.getTypeStoreSize(BObj->getType()));
}
}
}
-void DependenceAnalysis::unifySubscriptType(Subscript *Pair) {
- const SCEV *Src = Pair->Src;
- const SCEV *Dst = Pair->Dst;
- IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
- IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
- if (SrcTy == nullptr || DstTy == nullptr) {
- assert(SrcTy == DstTy && "This function only unify integer types and "
- "expect Src and Dst share the same type "
- "otherwise.");
- return;
+void DependenceAnalysis::unifySubscriptType(ArrayRef<Subscript *> Pairs) {
+
+ unsigned widestWidthSeen = 0;
+ Type *widestType;
+
+ // Go through each pair and find the widest bit to which we need
+ // to extend all of them.
+ for (unsigned i = 0; i < Pairs.size(); i++) {
+ const SCEV *Src = Pairs[i]->Src;
+ const SCEV *Dst = Pairs[i]->Dst;
+ IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
+ IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
+ if (SrcTy == nullptr || DstTy == nullptr) {
+ assert(SrcTy == DstTy && "This function only unify integer types and "
+ "expect Src and Dst share the same type "
+ "otherwise.");
+ continue;
+ }
+ if (SrcTy->getBitWidth() > widestWidthSeen) {
+ widestWidthSeen = SrcTy->getBitWidth();
+ widestType = SrcTy;
+ }
+ if (DstTy->getBitWidth() > widestWidthSeen) {
+ widestWidthSeen = DstTy->getBitWidth();
+ widestType = DstTy;
+ }
}
- if (SrcTy->getBitWidth() > DstTy->getBitWidth()) {
- // Sign-extend Dst to typeof(Src) if typeof(Src) is wider than typeof(Dst).
- Pair->Dst = SE->getSignExtendExpr(Dst, SrcTy);
- } else if (SrcTy->getBitWidth() < DstTy->getBitWidth()) {
- // Sign-extend Src to typeof(Dst) if typeof(Dst) is wider than typeof(Src).
- Pair->Src = SE->getSignExtendExpr(Src, DstTy);
+
+
+ assert(widestWidthSeen > 0);
+
+ // Now extend each pair to the widest seen.
+ for (unsigned i = 0; i < Pairs.size(); i++) {
+ const SCEV *Src = Pairs[i]->Src;
+ const SCEV *Dst = Pairs[i]->Dst;
+ IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
+ IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
+ if (SrcTy == nullptr || DstTy == nullptr) {
+ assert(SrcTy == DstTy && "This function only unify integer types and "
+ "expect Src and Dst share the same type "
+ "otherwise.");
+ continue;
+ }
+ if (SrcTy->getBitWidth() < widestWidthSeen)
+ // Sign-extend Src to widestType
+ Pairs[i]->Src = SE->getSignExtendExpr(Src, widestType);
+ if (DstTy->getBitWidth() < widestWidthSeen) {
+ // Sign-extend Dst to widestType
+ Pairs[i]->Dst = SE->getSignExtendExpr(Dst, widestType);
+ }
}
}
return isLoopInvariant(Src, LoopNest);
const SCEV *Start = AddRec->getStart();
const SCEV *Step = AddRec->getStepRecurrence(*SE);
+ const SCEV *UB = SE->getBackedgeTakenCount(AddRec->getLoop());
+ if (!isa<SCEVCouldNotCompute>(UB)) {
+ if (SE->getTypeSizeInBits(Start->getType()) <
+ SE->getTypeSizeInBits(UB->getType())) {
+ if (!AddRec->getNoWrapFlags())
+ return false;
+ }
+ }
if (!isLoopInvariant(Step, LoopNest))
return false;
Loops.set(mapSrcLoop(AddRec->getLoop()));
return isLoopInvariant(Dst, LoopNest);
const SCEV *Start = AddRec->getStart();
const SCEV *Step = AddRec->getStepRecurrence(*SE);
+ const SCEV *UB = SE->getBackedgeTakenCount(AddRec->getLoop());
+ if (!isa<SCEVCouldNotCompute>(UB)) {
+ if (SE->getTypeSizeInBits(Start->getType()) <
+ SE->getTypeSizeInBits(UB->getType())) {
+ if (!AddRec->getNoWrapFlags())
+ return false;
+ }
+ }
if (!isLoopInvariant(Step, LoopNest))
return false;
Loops.set(mapDstLoop(AddRec->getLoop()));
// All subscripts are all the same type.
// Loop bound may be smaller (e.g., a char).
// Should zero extend loop bound, since it's always >= 0.
-// This routine collects upper bound and extends if needed.
+// This routine collects upper bound and extends or truncates if needed.
+// Truncating is safe when subscripts are known not to wrap. Cases without
+// nowrap flags should have been rejected earlier.
// Return null if no bound available.
const SCEV *DependenceAnalysis::collectUpperBound(const Loop *L,
Type *T) const {
if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
const SCEV *UB = SE->getBackedgeTakenCount(L);
- return SE->getNoopOrZeroExtend(UB, T);
+ return SE->getTruncateOrZeroExtend(UB, T);
}
return nullptr;
}
// Can we compute distance?
if (isa<SCEVConstant>(Delta) && isa<SCEVConstant>(Coeff)) {
- APInt ConstDelta = cast<SCEVConstant>(Delta)->getValue()->getValue();
- APInt ConstCoeff = cast<SCEVConstant>(Coeff)->getValue()->getValue();
+ APInt ConstDelta = cast<SCEVConstant>(Delta)->getAPInt();
+ APInt ConstCoeff = cast<SCEVConstant>(Coeff)->getAPInt();
APInt Distance = ConstDelta; // these need to be initialized
APInt Remainder = ConstDelta;
APInt::sdivrem(ConstDelta, ConstCoeff, Distance, Remainder);
assert(SE->isKnownPositive(ConstCoeff) && "ConstCoeff should be positive");
// compute SplitIter for use by DependenceAnalysis::getSplitIteration()
- SplitIter =
- SE->getUDivExpr(SE->getSMaxExpr(SE->getConstant(Delta->getType(), 0),
- Delta),
- SE->getMulExpr(SE->getConstant(Delta->getType(), 2),
- ConstCoeff));
+ SplitIter = SE->getUDivExpr(
+ SE->getSMaxExpr(SE->getZero(Delta->getType()), Delta),
+ SE->getMulExpr(SE->getConstant(Delta->getType(), 2), ConstCoeff));
DEBUG(dbgs() << "\t Split iter = " << *SplitIter << "\n");
const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
return true;
}
Result.DV[Level].Splitable = false;
- Result.DV[Level].Distance = SE->getConstant(Delta->getType(), 0);
+ Result.DV[Level].Distance = SE->getZero(Delta->getType());
return false;
}
}
// check that Coeff divides Delta
- APInt APDelta = ConstDelta->getValue()->getValue();
- APInt APCoeff = ConstCoeff->getValue()->getValue();
+ APInt APDelta = ConstDelta->getAPInt();
+ APInt APCoeff = ConstCoeff->getAPInt();
APInt Distance = APDelta; // these need to be initialzed
APInt Remainder = APDelta;
APInt::sdivrem(APDelta, APCoeff, Distance, Remainder);
// find gcd
APInt G, X, Y;
- APInt AM = ConstSrcCoeff->getValue()->getValue();
- APInt BM = ConstDstCoeff->getValue()->getValue();
+ APInt AM = ConstSrcCoeff->getAPInt();
+ APInt BM = ConstDstCoeff->getAPInt();
unsigned Bits = AM.getBitWidth();
- if (findGCD(Bits, AM, BM, ConstDelta->getValue()->getValue(), G, X, Y)) {
+ if (findGCD(Bits, AM, BM, ConstDelta->getAPInt(), G, X, Y)) {
// gcd doesn't divide Delta, no dependence
++ExactSIVindependence;
++ExactSIVsuccesses;
// UM is perhaps unavailable, let's check
if (const SCEVConstant *CUB =
collectConstantUpperBound(CurLoop, Delta->getType())) {
- UM = CUB->getValue()->getValue();
+ UM = CUB->getAPInt();
DEBUG(dbgs() << "\t UM = " << UM << "\n");
UMvalid = true;
}
static
bool isRemainderZero(const SCEVConstant *Dividend,
const SCEVConstant *Divisor) {
- APInt ConstDividend = Dividend->getValue()->getValue();
- APInt ConstDivisor = Divisor->getValue()->getValue();
+ APInt ConstDividend = Dividend->getAPInt();
+ APInt ConstDivisor = Divisor->getAPInt();
return ConstDividend.srem(ConstDivisor) == 0;
}
Level--;
Result.Consistent = false;
const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
- NewConstraint.setLine(SE->getConstant(Delta->getType(), 0),
- DstCoeff, Delta, CurLoop);
+ NewConstraint.setLine(SE->getZero(Delta->getType()), DstCoeff, Delta,
+ CurLoop);
DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
if (isKnownPredicate(CmpInst::ICMP_EQ, SrcConst, DstConst)) {
if (Level < CommonLevels) {
Level--;
Result.Consistent = false;
const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
- NewConstraint.setLine(SrcCoeff, SE->getConstant(Delta->getType(), 0),
- Delta, CurLoop);
+ NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->getType()), Delta,
+ CurLoop);
DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
if (isKnownPredicate(CmpInst::ICMP_EQ, DstConst, SrcConst)) {
if (Level < CommonLevels) {
// find gcd
APInt G, X, Y;
- APInt AM = ConstSrcCoeff->getValue()->getValue();
- APInt BM = ConstDstCoeff->getValue()->getValue();
+ APInt AM = ConstSrcCoeff->getAPInt();
+ APInt BM = ConstDstCoeff->getAPInt();
unsigned Bits = AM.getBitWidth();
- if (findGCD(Bits, AM, BM, ConstDelta->getValue()->getValue(), G, X, Y)) {
+ if (findGCD(Bits, AM, BM, ConstDelta->getAPInt(), G, X, Y)) {
// gcd doesn't divide Delta, no dependence
++ExactRDIVindependence;
return true;
// SrcUM is perhaps unavailable, let's check
if (const SCEVConstant *UpperBound =
collectConstantUpperBound(SrcLoop, Delta->getType())) {
- SrcUM = UpperBound->getValue()->getValue();
+ SrcUM = UpperBound->getAPInt();
DEBUG(dbgs() << "\t SrcUM = " << SrcUM << "\n");
SrcUMvalid = true;
}
// UM is perhaps unavailable, let's check
if (const SCEVConstant *UpperBound =
collectConstantUpperBound(DstLoop, Delta->getType())) {
- DstUM = UpperBound->getValue()->getValue();
+ DstUM = UpperBound->getAPInt();
DEBUG(dbgs() << "\t DstUM = " << DstUM << "\n");
DstUMvalid = true;
}
Constant = getConstantPart(Product);
if (!Constant)
return false;
- APInt ConstCoeff = Constant->getValue()->getValue();
+ APInt ConstCoeff = Constant->getAPInt();
RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
Coefficients = AddRec->getStart();
}
Constant = getConstantPart(Product);
if (!Constant)
return false;
- APInt ConstCoeff = Constant->getValue()->getValue();
+ APInt ConstCoeff = Constant->getAPInt();
RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
Coefficients = AddRec->getStart();
}
const SCEVConstant *ConstOp = getConstantPart(Product);
if (!ConstOp)
return false;
- APInt ConstOpValue = ConstOp->getValue()->getValue();
+ APInt ConstOpValue = ConstOp->getAPInt();
ExtraGCD = APIntOps::GreatestCommonDivisor(ExtraGCD,
ConstOpValue.abs());
}
}
if (!Constant)
return false;
- APInt ConstDelta = cast<SCEVConstant>(Constant)->getValue()->getValue();
+ APInt ConstDelta = cast<SCEVConstant>(Constant)->getAPInt();
DEBUG(dbgs() << " ConstDelta = " << ConstDelta << "\n");
if (ConstDelta == 0)
return false;
Constant = getConstantPart(Product);
else
Constant = cast<SCEVConstant>(Coeff);
- APInt ConstCoeff = Constant->getValue()->getValue();
+ APInt ConstCoeff = Constant->getAPInt();
RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
}
Inner = AddRec->getStart();
Constant = getConstantPart(Product);
else
Constant = cast<SCEVConstant>(Coeff);
- APInt ConstCoeff = Constant->getValue()->getValue();
+ APInt ConstCoeff = Constant->getAPInt();
RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
}
Inner = AddRec->getStart();
// or constant, in which case we give up on this direction.
continue;
}
- APInt ConstCoeff = Constant->getValue()->getValue();
+ APInt ConstCoeff = Constant->getAPInt();
RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
DEBUG(dbgs() << "\tRunningGCD = " << RunningGCD << "\n");
if (RunningGCD != 0) {
// If the difference is 0, we won't need to know the number of iterations.
if (isKnownPredicate(CmpInst::ICMP_EQ, A[K].NegPart, B[K].PosPart))
Bound[K].Lower[Dependence::DVEntry::ALL] =
- SE->getConstant(A[K].Coeff->getType(), 0);
+ SE->getZero(A[K].Coeff->getType());
if (isKnownPredicate(CmpInst::ICMP_EQ, A[K].PosPart, B[K].NegPart))
Bound[K].Upper[Dependence::DVEntry::ALL] =
- SE->getConstant(A[K].Coeff->getType(), 0);
+ SE->getZero(A[K].Coeff->getType());
}
}
Bound[K].Lower[Dependence::DVEntry::LT] = nullptr; // Default value = -infinity.
Bound[K].Upper[Dependence::DVEntry::LT] = nullptr; // Default value = +infinity.
if (Bound[K].Iterations) {
- const SCEV *Iter_1 =
- SE->getMinusSCEV(Bound[K].Iterations,
- SE->getConstant(Bound[K].Iterations->getType(), 1));
+ const SCEV *Iter_1 = SE->getMinusSCEV(
+ Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
const SCEV *NegPart =
getNegativePart(SE->getMinusSCEV(A[K].NegPart, B[K].Coeff));
Bound[K].Lower[Dependence::DVEntry::LT] =
Bound[K].Lower[Dependence::DVEntry::GT] = nullptr; // Default value = -infinity.
Bound[K].Upper[Dependence::DVEntry::GT] = nullptr; // Default value = +infinity.
if (Bound[K].Iterations) {
- const SCEV *Iter_1 =
- SE->getMinusSCEV(Bound[K].Iterations,
- SE->getConstant(Bound[K].Iterations->getType(), 1));
+ const SCEV *Iter_1 = SE->getMinusSCEV(
+ Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
const SCEV *NegPart =
getNegativePart(SE->getMinusSCEV(A[K].Coeff, B[K].PosPart));
Bound[K].Lower[Dependence::DVEntry::GT] =
// X^+ = max(X, 0)
const SCEV *DependenceAnalysis::getPositivePart(const SCEV *X) const {
- return SE->getSMaxExpr(X, SE->getConstant(X->getType(), 0));
+ return SE->getSMaxExpr(X, SE->getZero(X->getType()));
}
// X^- = min(X, 0)
const SCEV *DependenceAnalysis::getNegativePart(const SCEV *X) const {
- return SE->getSMinExpr(X, SE->getConstant(X->getType(), 0));
+ return SE->getSMinExpr(X, SE->getZero(X->getType()));
}
DependenceAnalysis::collectCoeffInfo(const SCEV *Subscript,
bool SrcFlag,
const SCEV *&Constant) const {
- const SCEV *Zero = SE->getConstant(Subscript->getType(), 0);
+ const SCEV *Zero = SE->getZero(Subscript->getType());
CoefficientInfo *CI = new CoefficientInfo[MaxLevels + 1];
for (unsigned K = 1; K <= MaxLevels; ++K) {
CI[K].Coeff = Zero;
// return the coefficient (the step)
// corresponding to the specified loop.
// If there isn't one, return 0.
-// For example, given a*i + b*j + c*k, zeroing the coefficient
+// For example, given a*i + b*j + c*k, finding the coefficient
// corresponding to the j loop would yield b.
const SCEV *DependenceAnalysis::findCoefficient(const SCEV *Expr,
const Loop *TargetLoop) const {
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Expr);
if (!AddRec)
- return SE->getConstant(Expr->getType(), 0);
+ return SE->getZero(Expr->getType());
if (AddRec->getLoop() == TargetLoop)
return AddRec->getStepRecurrence(*SE);
return findCoefficient(AddRec->getStart(), TargetLoop);
const SCEVConstant *Bconst = dyn_cast<SCEVConstant>(B);
const SCEVConstant *Cconst = dyn_cast<SCEVConstant>(C);
if (!Bconst || !Cconst) return false;
- APInt Beta = Bconst->getValue()->getValue();
- APInt Charlie = Cconst->getValue()->getValue();
+ APInt Beta = Bconst->getAPInt();
+ APInt Charlie = Cconst->getAPInt();
APInt CdivB = Charlie.sdiv(Beta);
assert(Charlie.srem(Beta) == 0 && "C should be evenly divisible by B");
const SCEV *AP_K = findCoefficient(Dst, CurLoop);
const SCEVConstant *Aconst = dyn_cast<SCEVConstant>(A);
const SCEVConstant *Cconst = dyn_cast<SCEVConstant>(C);
if (!Aconst || !Cconst) return false;
- APInt Alpha = Aconst->getValue()->getValue();
- APInt Charlie = Cconst->getValue()->getValue();
+ APInt Alpha = Aconst->getAPInt();
+ APInt Charlie = Cconst->getAPInt();
APInt CdivA = Charlie.sdiv(Alpha);
assert(Charlie.srem(Alpha) == 0 && "C should be evenly divisible by A");
const SCEV *A_K = findCoefficient(Src, CurLoop);
const SCEVConstant *Aconst = dyn_cast<SCEVConstant>(A);
const SCEVConstant *Cconst = dyn_cast<SCEVConstant>(C);
if (!Aconst || !Cconst) return false;
- APInt Alpha = Aconst->getValue()->getValue();
- APInt Charlie = Cconst->getValue()->getValue();
+ APInt Alpha = Aconst->getAPInt();
+ APInt Charlie = Cconst->getAPInt();
APInt CdivA = Charlie.sdiv(Alpha);
assert(Charlie.srem(Alpha) == 0 && "C should be evenly divisible by A");
const SCEV *A_K = findCoefficient(Src, CurLoop);
/// source and destination array references are recurrences on a nested loop,
/// this function flattens the nested recurrences into separate recurrences
/// for each loop level.
-bool DependenceAnalysis::tryDelinearize(const SCEV *SrcSCEV,
- const SCEV *DstSCEV,
- SmallVectorImpl<Subscript> &Pair,
- const SCEV *ElementSize) {
+bool DependenceAnalysis::tryDelinearize(Instruction *Src,
+ Instruction *Dst,
+ SmallVectorImpl<Subscript> &Pair)
+{
+ Value *SrcPtr = getPointerOperand(Src);
+ Value *DstPtr = getPointerOperand(Dst);
+
+ Loop *SrcLoop = LI->getLoopFor(Src->getParent());
+ Loop *DstLoop = LI->getLoopFor(Dst->getParent());
+
+ // Below code mimics the code in Delinearization.cpp
+ const SCEV *SrcAccessFn =
+ SE->getSCEVAtScope(SrcPtr, SrcLoop);
+ const SCEV *DstAccessFn =
+ SE->getSCEVAtScope(DstPtr, DstLoop);
+
const SCEVUnknown *SrcBase =
- dyn_cast<SCEVUnknown>(SE->getPointerBase(SrcSCEV));
+ dyn_cast<SCEVUnknown>(SE->getPointerBase(SrcAccessFn));
const SCEVUnknown *DstBase =
- dyn_cast<SCEVUnknown>(SE->getPointerBase(DstSCEV));
+ dyn_cast<SCEVUnknown>(SE->getPointerBase(DstAccessFn));
if (!SrcBase || !DstBase || SrcBase != DstBase)
return false;
- SrcSCEV = SE->getMinusSCEV(SrcSCEV, SrcBase);
- DstSCEV = SE->getMinusSCEV(DstSCEV, DstBase);
+ const SCEV *ElementSize = SE->getElementSize(Src);
+ if (ElementSize != SE->getElementSize(Dst))
+ return false;
+
+ const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
+ const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
const SCEVAddRecExpr *SrcAR = dyn_cast<SCEVAddRecExpr>(SrcSCEV);
const SCEVAddRecExpr *DstAR = dyn_cast<SCEVAddRecExpr>(DstSCEV);
// First step: collect parametric terms in both array references.
SmallVector<const SCEV *, 4> Terms;
- SrcAR->collectParametricTerms(*SE, Terms);
- DstAR->collectParametricTerms(*SE, Terms);
+ SE->collectParametricTerms(SrcAR, Terms);
+ SE->collectParametricTerms(DstAR, Terms);
// Second step: find subscript sizes.
SmallVector<const SCEV *, 4> Sizes;
// Third step: compute the access functions for each subscript.
SmallVector<const SCEV *, 4> SrcSubscripts, DstSubscripts;
- SrcAR->computeAccessFunctions(*SE, SrcSubscripts, Sizes);
- DstAR->computeAccessFunctions(*SE, DstSubscripts, Sizes);
+ SE->computeAccessFunctions(SrcAR, SrcSubscripts, Sizes);
+ SE->computeAccessFunctions(DstAR, DstSubscripts, Sizes);
// Fail when there is only a subscript: that's a linearized access function.
if (SrcSubscripts.size() < 2 || DstSubscripts.size() < 2 ||
}
#endif
-
// depends -
// Returns NULL if there is no dependence.
// Otherwise, return a Dependence with as many details as possible.
switch (underlyingObjectsAlias(AA, F->getParent()->getDataLayout(), DstPtr,
SrcPtr)) {
- case AliasAnalysis::MayAlias:
- case AliasAnalysis::PartialAlias:
+ case MayAlias:
+ case PartialAlias:
// cannot analyse objects if we don't understand their aliasing.
DEBUG(dbgs() << "can't analyze may or partial alias\n");
return make_unique<Dependence>(Src, Dst);
- case AliasAnalysis::NoAlias:
+ case NoAlias:
// If the objects noalias, they are distinct, accesses are independent.
DEBUG(dbgs() << "no alias\n");
return nullptr;
- case AliasAnalysis::MustAlias:
+ case MustAlias:
break; // The underlying objects alias; test accesses for dependence.
}
DEBUG(dbgs() << " SrcPtrSCEV = " << *SrcPtrSCEV << "\n");
DEBUG(dbgs() << " DstPtrSCEV = " << *DstPtrSCEV << "\n");
- UsefulGEP =
- isLoopInvariant(SrcPtrSCEV, LI->getLoopFor(Src->getParent())) &&
- isLoopInvariant(DstPtrSCEV, LI->getLoopFor(Dst->getParent()));
+ UsefulGEP = isLoopInvariant(SrcPtrSCEV, LI->getLoopFor(Src->getParent())) &&
+ isLoopInvariant(DstPtrSCEV, LI->getLoopFor(Dst->getParent())) &&
+ (SrcGEP->getNumOperands() == DstGEP->getNumOperands());
}
unsigned Pairs = UsefulGEP ? SrcGEP->idx_end() - SrcGEP->idx_begin() : 1;
SmallVector<Subscript, 4> Pair(Pairs);
Pair[0].Dst = DstSCEV;
}
- if (Delinearize && Pairs == 1 && CommonLevels > 1 &&
- tryDelinearize(Pair[0].Src, Pair[0].Dst, Pair, SE->getElementSize(Src))) {
- DEBUG(dbgs() << " delinerized GEP\n");
- Pairs = Pair.size();
+ if (Delinearize && CommonLevels > 1) {
+ if (tryDelinearize(Src, Dst, Pair)) {
+ DEBUG(dbgs() << " delinerized GEP\n");
+ Pairs = Pair.size();
+ }
}
for (unsigned P = 0; P < Pairs; ++P) {
SmallBitVector Sivs(Pairs);
SmallBitVector Mivs(Pairs);
SmallBitVector ConstrainedLevels(MaxLevels + 1);
+ SmallVector<Subscript *, 4> PairsInGroup;
for (int SJ = Group.find_first(); SJ >= 0; SJ = Group.find_next(SJ)) {
DEBUG(dbgs() << SJ << " ");
if (Pair[SJ].Classification == Subscript::SIV)
Sivs.set(SJ);
else
Mivs.set(SJ);
+ PairsInGroup.push_back(&Pair[SJ]);
}
+ unifySubscriptType(PairsInGroup);
DEBUG(dbgs() << "}\n");
while (Sivs.any()) {
bool Changed = false;
DEBUG(dbgs() << " updating\n");
for (int SJ = ConstrainedLevels.find_first(); SJ >= 0;
SJ = ConstrainedLevels.find_next(SJ)) {
+ if (SJ > (int)CommonLevels)
+ break;
updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
if (Result.DV[SJ - 1].Direction == Dependence::DVEntry::NONE)
return nullptr;
return nullptr;
}
- auto Final = make_unique<FullDependence>(Result);
- Result.DV = nullptr;
- return std::move(Final);
+ return make_unique<FullDependence>(std::move(Result));
}
Value *SrcPtr = getPointerOperand(Src);
Value *DstPtr = getPointerOperand(Dst);
assert(underlyingObjectsAlias(AA, F->getParent()->getDataLayout(), DstPtr,
- SrcPtr) == AliasAnalysis::MustAlias);
+ SrcPtr) == MustAlias);
// establish loop nesting levels
establishNestingLevels(Src, Dst);
SrcGEP->getPointerOperandType() == DstGEP->getPointerOperandType()) {
const SCEV *SrcPtrSCEV = SE->getSCEV(SrcGEP->getPointerOperand());
const SCEV *DstPtrSCEV = SE->getSCEV(DstGEP->getPointerOperand());
- UsefulGEP =
- isLoopInvariant(SrcPtrSCEV, LI->getLoopFor(Src->getParent())) &&
- isLoopInvariant(DstPtrSCEV, LI->getLoopFor(Dst->getParent()));
+ UsefulGEP = isLoopInvariant(SrcPtrSCEV, LI->getLoopFor(Src->getParent())) &&
+ isLoopInvariant(DstPtrSCEV, LI->getLoopFor(Dst->getParent())) &&
+ (SrcGEP->getNumOperands() == DstGEP->getNumOperands());
}
unsigned Pairs = UsefulGEP ? SrcGEP->idx_end() - SrcGEP->idx_begin() : 1;
SmallVector<Subscript, 4> Pair(Pairs);
Pair[0].Dst = DstSCEV;
}
- if (Delinearize && Pairs == 1 && CommonLevels > 1 &&
- tryDelinearize(Pair[0].Src, Pair[0].Dst, Pair, SE->getElementSize(Src))) {
- DEBUG(dbgs() << " delinerized GEP\n");
- Pairs = Pair.size();
+ if (Delinearize && CommonLevels > 1) {
+ if (tryDelinearize(Src, Dst, Pair)) {
+ DEBUG(dbgs() << " delinerized GEP\n");
+ Pairs = Pair.size();
+ }
}
for (unsigned P = 0; P < Pairs; ++P) {