[polly] Bound ISL operations during DeLICM scalar collapsing (PR #203073)
Shikhar Jain via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 28 08:44:07 PDT 2026
https://github.com/ShikharJ-Corp updated https://github.com/llvm/llvm-project/pull/203073
>From b0e54edd16d42bbfdb8039a17b00c6e950627c51 Mon Sep 17 00:00:00 2001
From: ShikharJain <shikharj at qti.qualcomm.com>
Date: Tue, 9 Jun 2026 20:45:38 -0700
Subject: [PATCH] Bound ISL operations during DeLICM scalar collapsing
The IslMaxOperationsGuard in DeLICM previously covered only the zone
analysis performed in computeZone(). The subsequent greedyCollapse()
-> collapseScalarsToStore() path calls computeScalarReachingOverwrite(),
which performs an unbounded ISL lexmin().
Share a single[already present], dormant IslMaxOperationsGuard
across both regions and arm it narrowly around each operation intensive
computation via IslQuotaScope, so the same operations budget
covers both computeZone() and the scalar collapsing.
When the quota is exceeded during scalar collapsing, bail out cleanly
alongwith incrementing DeLICMOutOfQuota.
Also added a unit test case.
Fixes: https://github.com/llvm/llvm-project/issues/202045
---
polly/lib/Transform/DeLICM.cpp | 41 ++++++++++---
.../test/DeLICM/outofquota-greedycollapse.ll | 59 +++++++++++++++++++
2 files changed, 93 insertions(+), 7 deletions(-)
create mode 100644 polly/test/DeLICM/outofquota-greedycollapse.ll
diff --git a/polly/lib/Transform/DeLICM.cpp b/polly/lib/Transform/DeLICM.cpp
index 4deace112f5b4..7b29cfe8feb29 100644
--- a/polly/lib/Transform/DeLICM.cpp
+++ b/polly/lib/Transform/DeLICM.cpp
@@ -40,7 +40,7 @@ cl::opt<int>
DelicmMaxOps("polly-delicm-max-ops",
cl::desc("Maximum number of isl operations to invest for "
"lifetime analysis; 0=no limit"),
- cl::init(1000000), cl::cat(PollyCategory));
+ cl::init(1500000), cl::cat(PollyCategory));
cl::opt<bool> DelicmOverapproximateWrites(
"polly-delicm-overapproximate-writes",
@@ -545,6 +545,13 @@ class DeLICMImpl final : public ZoneAlgorithm {
/// The number of PHIs mapped to some array element.
int NumberOfMappedPHIScalars = 0;
+ /// Shared ISL operations budget guarding the expensive zone analysis
+ /// (computeZone) and the scalar-to-store collapsing (greedyCollapse). It is
+ /// constructed dormant (AutoEnter=false) and armed narrowly around each
+ /// dangerous region via IslQuotaScope, so the same budget covers both
+ /// regions without ever nesting two armed scopes.
+ IslMaxOperationsGuard MaxOpGuard;
+
/// Determine whether two knowledges are conflicting with each other.
///
/// @see Knowledge::isConflicting
@@ -1024,9 +1031,27 @@ class DeLICMImpl final : public ZoneAlgorithm {
auto TargetAccRel = getAccessRelationFor(TargetStoreMA);
// { Zone[] -> DomTarget[] }
- // For each point in time, find the next target store instance.
- auto Target =
- computeScalarReachingOverwrite(Schedule, TargetDom, false, true);
+ // For each point in time, find the next target store instance. This can be
+ // expensive for SCoPs with many modular/quasi-affine constraints, so bound
+ // it with the shared ISL operations budget.
+ isl::map Target;
+ {
+ IslQuotaScope MaxOpScope = MaxOpGuard.enter();
+ Target = computeScalarReachingOverwrite(Schedule, TargetDom, false, true);
+
+ if (Target.is_null() || MaxOpScope.hasQuotaExceeded()) {
+ DeLICMOutOfQuota++;
+ POLLY_DEBUG(dbgs() << "DeLICM analysis exceeded max_operations during "
+ "scalar collapsing\n");
+ DebugLoc Begin, End;
+ getDebugLocations(getBBPairForRegion(&S->getRegion()), Begin, End);
+ OptimizationRemarkAnalysis R(DEBUG_TYPE, "OutOfQuota", Begin,
+ S->getEntry());
+ R << "maximal number of operations exceeded during scalar collapsing";
+ S->getFunction().getContext().diagnose(R);
+ return false;
+ }
+ }
// { Zone[] -> Element[] }
// Use the target store's write location as a suggestion to map scalars to.
@@ -1187,7 +1212,9 @@ class DeLICMImpl final : public ZoneAlgorithm {
}
public:
- DeLICMImpl(Scop *S, LoopInfo *LI) : ZoneAlgorithm("polly-delicm", S, LI) {}
+ DeLICMImpl(Scop *S, LoopInfo *LI)
+ : ZoneAlgorithm("polly-delicm", S, LI),
+ MaxOpGuard(IslCtx.get(), DelicmMaxOps, /*AutoEnter=*/false) {}
/// Calculate the lifetime (definition to last use) of every array element.
///
@@ -1200,14 +1227,14 @@ class DeLICMImpl final : public ZoneAlgorithm {
isl::union_map EltKnown, EltWritten;
{
- IslMaxOperationsGuard MaxOpGuard(IslCtx.get(), DelicmMaxOps);
-
+ IslQuotaScope MaxOpScope = MaxOpGuard.enter();
computeCommon();
EltUnused = computeLifetime();
EltKnown = computeKnown(true, false);
EltWritten = computeWritten();
}
+
DeLICMAnalyzed++;
if (EltUnused.is_null() || EltKnown.is_null() || EltWritten.is_null()) {
diff --git a/polly/test/DeLICM/outofquota-greedycollapse.ll b/polly/test/DeLICM/outofquota-greedycollapse.ll
new file mode 100644
index 0000000000000..b6eff5766cacd
--- /dev/null
+++ b/polly/test/DeLICM/outofquota-greedycollapse.ll
@@ -0,0 +1,59 @@
+; RUN: opt %loadNPMPolly '-passes=polly-custom<delicm>' -polly-process-unprofitable -pass-remarks-analysis=polly-delicm -polly-delicm-max-ops=1000000 -disable-output < %s 2>&1 | FileCheck %s
+
+; CHECK: maximal number of operations exceeded during scalar collapsing
+
+; ModuleID = '<stdin>'
+source_filename = "<stdin>"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
+target triple = "aarch64-unknown-linux-gnueabi"
+
+define void @ham(ptr %arg) {
+bb:
+ br label %bb1
+
+bb1: ; preds = %bb19, %bb
+ %phi = phi i64 [ 1, %bb ], [ %add, %bb19 ]
+ %trunc = trunc i64 %phi to i32
+ %and = and i32 %trunc, 1
+ %icmp = icmp eq i32 %and, 0
+ br i1 %icmp, label %bb4, label %bb2
+
+bb2: ; preds = %bb16, %bb13, %bb10, %bb7, %bb4, %bb1
+ %phi3 = phi i8 [ 1, %bb1 ], [ 0, %bb4 ], [ 1, %bb13 ], [ 0, %bb16 ], [ 0, %bb10 ], [ 1, %bb7 ]
+ %getelementptr = getelementptr i8, ptr %arg, i64 %phi
+ store i8 %phi3, ptr %getelementptr, align 1
+ br label %bb19
+
+bb4: ; preds = %bb1
+ %and5 = and i64 %phi, 254
+ %icmp6 = icmp eq i64 %and5, 0
+ br i1 %icmp6, label %bb7, label %bb2
+
+bb7: ; preds = %bb4
+ %and8 = and i32 %trunc, 256
+ %icmp9 = icmp eq i32 %and8, 0
+ br i1 %icmp9, label %bb10, label %bb2
+
+bb10: ; preds = %bb7
+ %and11 = and i64 %phi, 3584
+ %icmp12 = icmp eq i64 %and11, 0
+ br i1 %icmp12, label %bb13, label %bb2
+
+bb13: ; preds = %bb10
+ %and14 = and i32 %trunc, 8192
+ %icmp15 = icmp eq i32 %and14, 0
+ br i1 %icmp15, label %bb16, label %bb2
+
+bb16: ; preds = %bb13
+ %and17 = and i64 %phi, 49152
+ %icmp18 = icmp eq i64 %and17, 0
+ br i1 %icmp18, label %bb19, label %bb2
+
+bb19: ; preds = %bb16, %bb2
+ %add = add i64 %phi, 1
+ %icmp20 = icmp eq i64 %add, 65536
+ br i1 %icmp20, label %bb21, label %bb1
+
+bb21: ; preds = %bb19
+ ret void
+}
More information about the llvm-commits
mailing list