[polly] Isl ast gen compute out (PR #201859)

Shikhar Jain via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 24 08:50:23 PDT 2026


https://github.com/ShikharJ-Corp updated https://github.com/llvm/llvm-project/pull/201859

>From 182378bbc4b0ee4d0d5baf65f3acd99b50187fea Mon Sep 17 00:00:00 2001
From: ShikharJain <shikharj at qti.qualcomm.com>
Date: Wed, 10 Jun 2026 21:31:10 -0700
Subject: [PATCH 1/2] [Polly] Bound ISL operations during AST generation to
 prevent indefinite compile time

When -polly-process-unprofitable is used, this allows
SCoPs with complex iteration domains to reach ISL AST generation.
This patch applies IslMaxOperationsGuard around
isl_ast_build_node_from_schedule() in IslAst::init().
A new flag polly-astgen-computeout (default 3000000) controls
the limit.

Fixes:https://github.com/llvm/llvm-project/issues/201801
---
 polly/lib/CodeGen/IslAst.cpp              |  26 ++++-
 polly/test/IstAstInfo/AstGenComputeOut.ll | 110 ++++++++++++++++++++++
 2 files changed, 132 insertions(+), 4 deletions(-)
 create mode 100644 polly/test/IstAstInfo/AstGenComputeOut.ll

diff --git a/polly/lib/CodeGen/IslAst.cpp b/polly/lib/CodeGen/IslAst.cpp
index 0ea14ae2fc2e0..208722a701665 100644
--- a/polly/lib/CodeGen/IslAst.cpp
+++ b/polly/lib/CodeGen/IslAst.cpp
@@ -86,6 +86,11 @@ static cl::opt<bool>
                   cl::desc("Print the ISL abstract syntax tree"),
                   cl::cat(PollyCategory));
 
+static cl::opt<unsigned long>
+    AstGenComputeout("polly-astgen-computeout",
+                     cl::desc("Bound the AST generation by a maximal number of "
+                              "ISL operations [0 means un-bounded]"),
+                     cl::Hidden, cl::init(3000000), cl::cat(PollyCategory));
 STATISTIC(ScopsProcessed, "Number of SCoPs processed");
 STATISTIC(ScopsBeneficial, "Number of beneficial SCoPs");
 STATISTIC(BeneficialAffineLoops, "Number of beneficial affine loops");
@@ -545,10 +550,23 @@ void IslAst::init(const Dependences &D) {
   }
 
   RunCondition = buildRunCondition(S, isl::manage_copy(Build));
-
-  Root = isl::manage(
-      isl_ast_build_node_from_schedule(Build, S.getScheduleTree().release()));
-  walkAstForStatistics(Root);
+  // Apply IslMaxOperationsGuard on the api which starts the process of ASt gen
+  // from schedule tree. This is to avoid the timeout when the schedule tree is
+  // too big and complex.
+
+  {
+    IslMaxOperationsGuard MaxOpGuard(Ctx.get(), AstGenComputeout);
+    Root = isl::manage(
+        isl_ast_build_node_from_schedule(Build, S.getScheduleTree().release()));
+    if (MaxOpGuard.hasQuotaExceeded()) {
+      POLLY_DEBUG(
+          dbgs() << "AST generation for SCoP in function '"
+                 << S.getFunction().getName()
+                 << "' exceeded operation limit (operations). Skipping.\n");
+    }
+  }
+  if (!Root.is_null())
+    walkAstForStatistics(Root);
 
   isl_ast_build_free(Build);
 }
diff --git a/polly/test/IstAstInfo/AstGenComputeOut.ll b/polly/test/IstAstInfo/AstGenComputeOut.ll
new file mode 100644
index 0000000000000..d846849f24c93
--- /dev/null
+++ b/polly/test/IstAstInfo/AstGenComputeOut.ll
@@ -0,0 +1,110 @@
+; RUN: opt %s -passes='polly-custom<ast>' -polly-process-unprofitable \
+; RUN:   -polly-astgen-computeout=1000000 -debug-only=polly-ast \
+; RUN:   -disable-output 2>&1 | FileCheck %s
+
+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 @InitializeZeroMasks(i32 %0) {
+entry:
+  br label %if.end
+
+if.end:                                           ; preds = %for.inc18, %entry
+  %indvars.iv = phi i64 [ 1, %entry ], [ %indvars.iv.next, %for.inc18 ]
+  br i1 true, label %if.end.1, label %for.end
+
+if.end.1:                                         ; preds = %if.end
+  %tobool.not.14 = icmp eq i32 %0, 0
+  br i1 %tobool.not.14, label %if.end.14, label %for.end
+
+if.end.14:                                        ; preds = %if.end.1
+  %1 = trunc i64 %indvars.iv to i32
+  %and.15 = and i32 %1, 1
+  %tobool.not.15 = icmp eq i32 %and.15, 0
+  br i1 %tobool.not.15, label %if.end14, label %for.end
+
+for.end:                                          ; preds = %if.end.14, %if.end.1, %if.end
+  %j.0119.lcssa = phi i8 [ 0, %if.end.1 ], [ 1, %if.end ], [ 0, %if.end.14 ]
+  br label %if.then10
+
+if.then10:                                        ; preds = %if.end14.13, %if.end14.12, %if.end14.11, %if.end14.10, %if.end14.9, %if.end14.8, %if.end14.7, %if.end14.6, %if.end14.5, %if.end14.4, %if.end14.3, %if.end14.2, %if.end14, %for.end
+  %j.1121.lcssa.neg = phi i8 [ 1, %for.end ], [ 0, %if.end14 ], [ 0, %if.end14.13 ], [ 0, %if.end14.2 ], [ 0, %if.end14.3 ], [ 0, %if.end14.4 ], [ 0, %if.end14.5 ], [ 0, %if.end14.6 ], [ 0, %if.end14.7 ], [ 0, %if.end14.8 ], [ 0, %if.end14.9 ], [ 0, %if.end14.10 ], [ 0, %if.end14.11 ], [ 0, %if.end14.12 ]
+  store i8 0, ptr null, align 1
+  br label %for.inc18
+
+if.end14:                                         ; preds = %if.end.14
+  %and8.1 = and i32 %1, 2
+  %tobool9.not.1 = icmp eq i32 %and8.1, 0
+  %and8.2 = and i32 %1, 4
+  %tobool9.not.2 = icmp eq i32 %and8.2, 0
+  %or.cond = and i1 %tobool9.not.1, %tobool9.not.2
+  br i1 %or.cond, label %if.end14.2, label %if.then10
+
+if.end14.2:                                       ; preds = %if.end14
+  %and8.3 = and i32 %1, 8
+  %tobool9.not.3 = icmp eq i32 %and8.3, 0
+  br i1 %tobool9.not.3, label %if.end14.3, label %if.then10
+
+if.end14.3:                                       ; preds = %if.end14.2
+  %and8.4 = and i32 %1, 16
+  %tobool9.not.4 = icmp eq i32 %and8.4, 0
+  br i1 %tobool9.not.4, label %if.end14.4, label %if.then10
+
+if.end14.4:                                       ; preds = %if.end14.3
+  %and8.5 = and i32 %1, 32
+  %tobool9.not.5 = icmp eq i32 %and8.5, 0
+  br i1 %tobool9.not.5, label %if.end14.5, label %if.then10
+
+if.end14.5:                                       ; preds = %if.end14.4
+  %and8.6 = and i32 %1, 64
+  %tobool9.not.6 = icmp eq i32 %and8.6, 0
+  br i1 %tobool9.not.6, label %if.end14.6, label %if.then10
+
+if.end14.6:                                       ; preds = %if.end14.5
+  %and8.7 = and i32 %1, 128
+  %tobool9.not.7 = icmp eq i32 %and8.7, 0
+  br i1 %tobool9.not.7, label %if.end14.7, label %if.then10
+
+if.end14.7:                                       ; preds = %if.end14.6
+  %and8.8 = and i32 %1, 256
+  %tobool9.not.8 = icmp eq i32 %and8.8, 0
+  br i1 %tobool9.not.8, label %if.end14.8, label %if.then10
+
+if.end14.8:                                       ; preds = %if.end14.7
+  %and8.9 = and i32 %1, 512
+  %tobool9.not.9 = icmp eq i32 %and8.9, 0
+  br i1 %tobool9.not.9, label %if.end14.9, label %if.then10
+
+if.end14.9:                                       ; preds = %if.end14.8
+  %and8.10 = and i32 %1, 1024
+  %tobool9.not.10 = icmp eq i32 %and8.10, 0
+  br i1 %tobool9.not.10, label %if.end14.10, label %if.then10
+
+if.end14.10:                                      ; preds = %if.end14.9
+  %and8.11 = and i32 %1, 2048
+  %tobool9.not.11 = icmp eq i32 %and8.11, 0
+  br i1 %tobool9.not.11, label %if.end14.11, label %if.then10
+
+if.end14.11:                                      ; preds = %if.end14.10
+  %and8.12 = and i32 %1, 4096
+  %tobool9.not.12 = icmp eq i32 %and8.12, 0
+  br i1 %tobool9.not.12, label %if.end14.12, label %if.then10
+
+if.end14.12:                                      ; preds = %if.end14.11
+  %and8.13 = and i32 %1, 8192
+  %tobool9.not.13 = icmp eq i32 %and8.13, 0
+  br i1 %tobool9.not.13, label %if.end14.13, label %if.then10
+
+if.end14.13:                                      ; preds = %if.end14.12
+  br i1 false, label %for.inc18, label %if.then10
+
+for.inc18:                                        ; preds = %if.end14.13, %if.then10
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %exitcond.not = icmp eq i64 %indvars.iv, 65536
+  br i1 %exitcond.not, label %for.end20, label %if.end
+
+for.end20:                                        ; preds = %for.inc18
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}

>From ecff189d03e0f4e722abaf50a41d97a773a7ec93 Mon Sep 17 00:00:00 2001
From: Shikhar Jain <shikharj at qti.qualcomm.com>
Date: Wed, 24 Jun 2026 21:20:13 +0530
Subject: [PATCH 2/2] Update polly/lib/CodeGen/IslAst.cpp

Co-authored-by: Michael Kruse <github at meinersbur.de>
---
 polly/lib/CodeGen/IslAst.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/polly/lib/CodeGen/IslAst.cpp b/polly/lib/CodeGen/IslAst.cpp
index 208722a701665..ed8dc2ff4c25b 100644
--- a/polly/lib/CodeGen/IslAst.cpp
+++ b/polly/lib/CodeGen/IslAst.cpp
@@ -550,7 +550,7 @@ void IslAst::init(const Dependences &D) {
   }
 
   RunCondition = buildRunCondition(S, isl::manage_copy(Build));
-  // Apply IslMaxOperationsGuard on the api which starts the process of ASt gen
+  // Apply IslMaxOperationsGuard on the API which starts the process of AST gen
   // from schedule tree. This is to avoid the timeout when the schedule tree is
   // too big and complex.
 



More information about the llvm-commits mailing list