bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const { Region &CurRegion = Context.CurRegion; for (const SCEVUnknown *BasePointer : Context.NonAffineAccesses) { Value *BaseValue = BasePointer->getValue(); ArrayShape *Shape = new ArrayShape(BasePointer); bool BasePtrHasNonAffine = false; // First step: collect parametric terms in all array references. SmallVector<const SCEV *, 4> Terms; for (const auto &Pair : Context.Accesses[BasePointer]) { const SCEVAddRecExpr *AccessFunction = dyn_cast<SCEVAddRecExpr>(Pair.second); if (AccessFunction) AccessFunction->collectParametricTerms(*SE, Terms); } // Second step: find array shape. SE->findArrayDimensions(Terms, Shape->DelinearizedSizes, Context.ElementSize[BasePointer]); // No array shape derived. if (Shape->DelinearizedSizes.empty()) { if (AllowNonAffine) continue; for (const auto &Pair : Context.Accesses[BasePointer]) { const Instruction *Insn = Pair.first; const SCEV *AF = Pair.second; if (!isAffineExpr(&CurRegion, AF, *SE, BaseValue)) { invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF, Insn, BaseValue); if (!KeepGoing) return false; } } continue; } // Third step: compute the access functions for each subscript. // // We first store the resulting memory accesses in TempMemoryAccesses. Only // if the access functions for all memory accesses have been successfully // delinearized we continue. Otherwise, we either report a failure or, if // non-affine accesses are allowed, we drop the information. In case the // information is dropped the memory accesses need to be overapproximated // when translated to a polyhedral representation. MapInsnToMemAcc TempMemoryAccesses; for (const auto &Pair : Context.Accesses[BasePointer]) { const Instruction *Insn = Pair.first; const SCEVAddRecExpr *AF = dyn_cast<SCEVAddRecExpr>(Pair.second); bool IsNonAffine = false; MemAcc *Acc = new MemAcc(Insn, Shape); TempMemoryAccesses.insert({Insn, Acc}); if (!AF) { if (isAffineExpr(&CurRegion, Pair.second, *SE, BaseValue)) Acc->DelinearizedSubscripts.push_back(Pair.second); else IsNonAffine = true; } else { AF->computeAccessFunctions(*SE, Acc->DelinearizedSubscripts, Shape->DelinearizedSizes); if (Acc->DelinearizedSubscripts.size() == 0) IsNonAffine = true; for (const SCEV *S : Acc->DelinearizedSubscripts) if (!isAffineExpr(&CurRegion, S, *SE, BaseValue)) IsNonAffine = true; } // (Possibly) report non affine access if (IsNonAffine) { BasePtrHasNonAffine = true; if (!AllowNonAffine) invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, Pair.second, Insn, BaseValue); if (!KeepGoing && !AllowNonAffine) return false; } } if (!BasePtrHasNonAffine) InsnToMemAcc.insert(TempMemoryAccesses.begin(), TempMemoryAccesses.end()); } return true; }