/// Remove cached results for the children of @p R recursively.
void removeCachedResultsRecursively(const Region &R);
+ /// Check if @p S0 and @p S1 do contain multiple possibly aliasing pointers.
+ ///
+ /// @param S0 A expression to check.
+ /// @param S1 Another expression to check or nullptr.
+ /// @param Scope The loop/scope the expressions are checked in.
+ ///
+ /// @returns True, if multiple possibly aliasing pointers are used in @p S0
+ /// (and @p S1 if given).
+ bool involvesMultiplePtrs(const SCEV *S0, const SCEV *S1, Loop *Scope) const;
+
/// Add the region @p AR as over approximated sub-region in @p Context.
///
/// @param AR The non-affine subregion.
return true;
}
+bool ScopDetection::involvesMultiplePtrs(const SCEV *S0, const SCEV *S1,
+ Loop *Scope) const {
+ SetVector<Value *> Values;
+ findValues(S0, *SE, Values);
+ if (S1)
+ findValues(S1, *SE, Values);
+
+ SmallPtrSet<Value *, 8> PtrVals;
+ for (auto *V : Values) {
+ if (auto *P2I = dyn_cast<PtrToIntInst>(V))
+ V = P2I->getOperand(0);
+
+ if (!V->getType()->isPointerTy())
+ continue;
+
+ auto *PtrSCEV = SE->getSCEVAtScope(V, Scope);
+ if (isa<SCEVConstant>(PtrSCEV))
+ continue;
+
+ auto *BasePtr = dyn_cast<SCEVUnknown>(SE->getPointerBase(PtrSCEV));
+ if (!BasePtr)
+ return true;
+
+ auto *BasePtrVal = BasePtr->getValue();
+ if (PtrVals.insert(BasePtrVal).second) {
+ for (auto *PtrVal : PtrVals)
+ if (PtrVal != BasePtrVal && !AA->isNoAlias(PtrVal, BasePtrVal))
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool ScopDetection::isAffine(const SCEV *S, Loop *Scope,
DetectionContext &Context) const {
if (IsLoopBranch && L->isLoopLatch(&BB))
return false;
+ // Check for invalid usage of different pointers in one expression.
+ if (involvesMultiplePtrs(ConditionSCEV, nullptr, L))
+ return false;
+
if (isAffine(ConditionSCEV, L, Context))
return true;
const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
const SCEV *RHS = SE->getSCEVAtScope(ICmp->getOperand(1), L);
+ // Check for invalid usage of different pointers in one expression.
+ if (ICmp->isEquality() && involvesMultiplePtrs(LHS, nullptr, L) &&
+ involvesMultiplePtrs(RHS, nullptr, L))
+ return false;
+
+ // Check for invalid usage of different pointers in a relational comparison.
+ if (ICmp->isRelational() && involvesMultiplePtrs(LHS, RHS, L))
+ return false;
+
if (isAffine(LHS, L, Context) && isAffine(RHS, L, Context))
return true;