[llvm] [polly] [delinearize] remove all uses of GEP instructions (PR #156215)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 30 17:06:04 PDT 2025
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff origin/main HEAD --extensions h,cpp -- llvm/include/llvm/Analysis/Delinearization.h llvm/lib/Analysis/Delinearization.cpp llvm/lib/Analysis/DependenceAnalysis.cpp llvm/lib/Analysis/LoopCacheAnalysis.cpp polly/include/polly/ScopInfo.h polly/lib/Analysis/ScopBuilder.cpp polly/lib/Analysis/ScopInfo.cpp
``````````
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/llvm/include/llvm/Analysis/Delinearization.h b/llvm/include/llvm/Analysis/Delinearization.h
index 2eda019ab..549901424 100644
--- a/llvm/include/llvm/Analysis/Delinearization.h
+++ b/llvm/include/llvm/Analysis/Delinearization.h
@@ -146,14 +146,14 @@ bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr,
/// Compute access functions for each subscript in a delinearized array access.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr,
- SmallVectorImpl<const SCEV *> &Subscripts,
- SmallVectorImpl<const SCEV *> &Sizes,
- const SCEV *ElementSize);
+ SmallVectorImpl<const SCEV *> &Subscripts,
+ SmallVectorImpl<const SCEV *> &Sizes,
+ const SCEV *ElementSize);
/// Backward compatibility wrapper for computeAccessFunctions.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr,
- SmallVectorImpl<const SCEV *> &Subscripts,
- SmallVectorImpl<const SCEV *> &Sizes);
+ SmallVectorImpl<const SCEV *> &Subscripts,
+ SmallVectorImpl<const SCEV *> &Sizes);
/// Implementation of fixed size array delinearization. Try to delinearize
/// access function for a fixed size multi-dimensional array, by deriving
diff --git a/llvm/lib/Analysis/Delinearization.cpp b/llvm/lib/Analysis/Delinearization.cpp
index 873060d5f..55ecaac2e 100644
--- a/llvm/lib/Analysis/Delinearization.cpp
+++ b/llvm/lib/Analysis/Delinearization.cpp
@@ -447,26 +447,31 @@ extractArrayInfoFromAllocaOrGlobal(ScalarEvolution &SE, Value *BasePtr,
// Clear output vector.
Sizes.clear();
- LLVM_DEBUG(dbgs() << "extractArrayInfoFromAllocaOrGlobal called with BasePtr: " << *BasePtr << "\n");
+ LLVM_DEBUG(
+ dbgs() << "extractArrayInfoFromAllocaOrGlobal called with BasePtr: "
+ << *BasePtr << "\n");
// Distinguish between simple array accesses and complex pointer arithmetic.
- // Only apply array_info extraction to direct array accesses to avoid incorrect
- // delinearization of complex pointer arithmetic patterns.
+ // Only apply array_info extraction to direct array accesses to avoid
+ // incorrect delinearization of complex pointer arithmetic patterns.
if (auto *GEP = dyn_cast<GetElementPtrInst>(BasePtr)) {
- // Check if this is a simple array access pattern: GEP [N x T]* @array, 0, idx
- // This represents direct indexing like array[i], which should use array dimensions.
+ // Check if this is a simple array access pattern: GEP [N x T]* @array, 0,
+ // idx This represents direct indexing like array[i], which should use array
+ // dimensions.
if (GEP->getNumIndices() == 2) {
auto *FirstIdx = dyn_cast<ConstantInt>(GEP->getOperand(1));
if (FirstIdx && FirstIdx->isZero()) {
- // Simple array access: extract dimensions from the underlying array type
+ // Simple array access: extract dimensions from the underlying array
+ // type
Value *Source = GEP->getPointerOperand()->stripPointerCasts();
- return extractArrayInfoFromAllocaOrGlobal(SE, Source, Sizes, ElementSize);
+ return extractArrayInfoFromAllocaOrGlobal(SE, Source, Sizes,
+ ElementSize);
}
}
- // Complex GEPs like (&array[offset])[index] represent pointer arithmetic, not
- // simple array indexing. These should be handled by parametric delinearization
- // to preserve the linearized byte-offset semantics rather than treating them
- // as multidimensional array accesses.
+ // Complex GEPs like (&array[offset])[index] represent pointer arithmetic,
+ // not simple array indexing. These should be handled by parametric
+ // delinearization to preserve the linearized byte-offset semantics rather
+ // than treating them as multidimensional array accesses.
return false;
}
@@ -545,12 +550,14 @@ bool llvm::delinearizeUsingArrayInfo(ScalarEvolution &SE, const SCEV *AccessFn,
return false;
// Validate dimension consistency: subscripts should match array dimensions
- // (Sizes includes element size as last element, so array dimensions = Sizes.size() - 1)
+ // (Sizes includes element size as last element, so array dimensions =
+ // Sizes.size() - 1)
unsigned ArrayDims = Sizes.size() - 1;
if (Subscripts.size() != ArrayDims) {
- LLVM_DEBUG(dbgs() << "delinearizeUsingArrayInfo: Dimension mismatch - "
- << Subscripts.size() << " subscripts for " << ArrayDims
- << " array dimensions. Falling back to parametric method.\n");
+ LLVM_DEBUG(
+ dbgs() << "delinearizeUsingArrayInfo: Dimension mismatch - "
+ << Subscripts.size() << " subscripts for " << ArrayDims
+ << " array dimensions. Falling back to parametric method.\n");
return false;
}
@@ -882,8 +889,7 @@ void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
// Do not analyze memory accesses outside loops.
if (!L)
continue;
- const SCEV *AccessFn =
- SE->getSCEVAtScope(getPointerOperand(&Inst), L);
+ const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
O << "\n";
O << "Inst:" << Inst << "\n";
@@ -901,7 +907,7 @@ void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
Sizes.clear();
const SCEVUnknown *BasePointer =
- dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
+ dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
// Fail to delinearize if we cannot find the base pointer.
if (!BasePointer)
continue;
diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index e9feb14b5..d07090b22 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -1478,27 +1478,31 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) {
const SCEVUnknown *BasePointer =
dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
- // Get or create the ScopArrayInfo and mark it as using array_info delinearization.
- LLVM_DEBUG(dbgs() << "buildAccessMultiDimFixed: BasePointer=" << *BasePointer->getValue() << "\n");
- auto *SAI = scop->getOrCreateScopArrayInfo(BasePointer->getValue(), ElementType,
- Sizes, MemoryKind::Array);
+ // Get or create the ScopArrayInfo and mark it as using array_info
+ // delinearization.
+ LLVM_DEBUG(dbgs() << "buildAccessMultiDimFixed: BasePointer="
+ << *BasePointer->getValue() << "\n");
+ auto *SAI = scop->getOrCreateScopArrayInfo(
+ BasePointer->getValue(), ElementType, Sizes, MemoryKind::Array);
SAI->setUsedArrayInfoDelinearization(true);
LLVM_DEBUG({
- dbgs() << "buildAccessMultiDimFixed for " << BasePointer->getValue()->getName()
- << ": Subscripts=[";
+ dbgs() << "buildAccessMultiDimFixed for "
+ << BasePointer->getValue()->getName() << ": Subscripts=[";
for (unsigned i = 0; i < Subscripts.size(); i++) {
- if (i > 0) dbgs() << ", ";
+ if (i > 0)
+ dbgs() << ", ";
dbgs() << *Subscripts[i];
}
dbgs() << "], Sizes=[";
for (unsigned i = 0; i < Sizes.size(); i++) {
- if (i > 0) dbgs() << ", ";
+ if (i > 0)
+ dbgs() << ", ";
dbgs() << *Sizes[i];
}
dbgs() << "]\n";
});
-
+
addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
true, Subscripts, Sizes, Val);
return true;
@@ -2306,8 +2310,9 @@ void ScopBuilder::updateAccessDimensionality() {
if (Array->getNumberOfDimensions() != 1)
continue;
- // Skip divisibility optimization for arrays delinearized using array_info,
- // as they produce proper array indices rather than byte offsets.
+ // Skip divisibility optimization for arrays delinearized using
+ // array_info, as they produce proper array indices rather than byte
+ // offsets.
if (Array->usedArrayInfoDelinearization())
continue;
@@ -2582,25 +2587,30 @@ bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA,
if (Valid) {
// Finally, check if they are no other instructions accessing this memory.
- // For multidimensional arrays with known bounds, be less strict about overlaps
- // to preserve reduction detection for legitimate array reduction patterns.
+ // For multidimensional arrays with known bounds, be less strict about
+ // overlaps to preserve reduction detection for legitimate array reduction
+ // patterns.
isl::map AllAccsRel = LoadAccs.unite(StoreAccs);
AllAccsRel = AllAccsRel.intersect_domain(Domain);
isl::set AllAccs = AllAccsRel.range();
-
- bool hasOtherAccesses = hasIntersectingAccesses(AllAccs, LoadMA, StoreMA, Domain, MemAccs);
-
- // For arrays delinearized with array_info (multidimensional with known bounds),
- // allow reductions even if there might be overlapping accesses from other reductions
- // in the same statement, as these represent legitimate reduction patterns.
+
+ bool hasOtherAccesses =
+ hasIntersectingAccesses(AllAccs, LoadMA, StoreMA, Domain, MemAccs);
+
+ // For arrays delinearized with array_info (multidimensional with known
+ // bounds), allow reductions even if there might be overlapping accesses
+ // from other reductions in the same statement, as these represent
+ // legitimate reduction patterns.
auto *SAI = LoadMA->getScopArrayInfo();
- if (hasOtherAccesses && SAI->usedArrayInfoDelinearization() && SAI->getNumberOfDimensions() > 1) {
- POLLY_DEBUG(dbgs() << " == Allowing potential overlap for multidimensional array reduction\n");
+ if (hasOtherAccesses && SAI->usedArrayInfoDelinearization() &&
+ SAI->getNumberOfDimensions() > 1) {
+ POLLY_DEBUG(dbgs() << " == Allowing potential overlap for "
+ "multidimensional array reduction\n");
Valid = true;
} else {
Valid = !hasOtherAccesses;
}
-
+
POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "not " : "")
<< "accessed by other instructions!\n");
}
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 419ece58c..92edf858e 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -447,18 +447,20 @@ void MemoryAccess::updateDimensionality() {
unsigned DimsArray = unsignedFromIslSize(ArraySpace.dim(isl::dim::set));
unsigned DimsAccess = unsignedFromIslSize(AccessSpace.dim(isl::dim::set));
-
- LLVM_DEBUG(dbgs() << "updateDimensionality: DimsArray=" << DimsArray
- << ", DimsAccess=" << DimsAccess
- << " for array " << SAI->getName() << "\n");
-
+
+ LLVM_DEBUG(dbgs() << "updateDimensionality: DimsArray=" << DimsArray
+ << ", DimsAccess=" << DimsAccess << " for array "
+ << SAI->getName() << "\n");
+
if (DimsArray < DimsAccess) {
- LLVM_DEBUG(dbgs() << "ERROR: DimsArray < DimsAccess - assertion would fail!\n");
+ LLVM_DEBUG(
+ dbgs() << "ERROR: DimsArray < DimsAccess - assertion would fail!\n");
return; // Graceful failure instead of assertion
}
unsigned DimsMissing = DimsArray - DimsAccess;
-
- LLVM_DEBUG(dbgs() << "updateDimensionality: Computing DimsMissing=" << DimsMissing << "\n");
+
+ LLVM_DEBUG(dbgs() << "updateDimensionality: Computing DimsMissing="
+ << DimsMissing << "\n");
auto *BB = getStatement()->getEntryBlock();
auto &DL = BB->getModule()->getDataLayout();
@@ -511,17 +513,18 @@ void MemoryAccess::updateDimensionality() {
// An access ((float *)A)[i] to an array char *A is modeled as
// {[i] -> A[o] : 4 i <= o <= 4 i + 3
if (ElemBytes > ArrayElemSize) {
- LLVM_DEBUG(dbgs() << "updateDimensionality: ElemBytes=" << ElemBytes
+ LLVM_DEBUG(dbgs() << "updateDimensionality: ElemBytes=" << ElemBytes
<< " > ArrayElemSize=" << ArrayElemSize << "\n");
-
+
if (ElemBytes % ArrayElemSize != 0) {
- LLVM_DEBUG(dbgs() << "ERROR: Loaded element size not multiple of canonical element size!\n");
+ LLVM_DEBUG(dbgs() << "ERROR: Loaded element size not multiple of "
+ "canonical element size!\n");
return; // Graceful failure instead of assertion
}
-
+
if (DimsArray < 1) {
LLVM_DEBUG(dbgs() << "ERROR: DimsArray < 1!\n");
- return; // Graceful failure instead of assertion
+ return; // Graceful failure instead of assertion
}
isl::map Map = isl::map::from_domain_and_range(
isl::set::universe(ArraySpace), isl::set::universe(ArraySpace));
@@ -547,8 +550,9 @@ void MemoryAccess::updateDimensionality() {
Map = Map.add_constraint(C);
AccessRelation = AccessRelation.apply_range(Map);
}
-
- LLVM_DEBUG(dbgs() << "updateDimensionality: Completed successfully for array " << SAI->getName() << "\n");
+
+ LLVM_DEBUG(dbgs() << "updateDimensionality: Completed successfully for array "
+ << SAI->getName() << "\n");
}
std::string
@@ -870,10 +874,11 @@ void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) {
isl::space Space = isl::space(Ctx, 0, Statement->getNumIterators(), 0);
AccessRelation = isl::map::universe(Space);
- LLVM_DEBUG(dbgs() << "buildAccessRelation for " << BaseAddr->getName()
+ LLVM_DEBUG(dbgs() << "buildAccessRelation for " << BaseAddr->getName()
<< ": Processing " << Subscripts.size() << " subscripts\n");
for (int i = 0, Size = Subscripts.size(); i < Size; ++i) {
- LLVM_DEBUG(dbgs() << " Subscripts[" << i << "] = " << *Subscripts[i] << "\n");
+ LLVM_DEBUG(dbgs() << " Subscripts[" << i << "] = " << *Subscripts[i]
+ << "\n");
isl::pw_aff Affine = getPwAff(Subscripts[i]);
isl::map SubscriptMap = isl::map::from_pw_aff(Affine);
AccessRelation = AccessRelation.flat_range_product(SubscriptMap);
``````````
</details>
https://github.com/llvm/llvm-project/pull/156215
More information about the llvm-commits
mailing list