[polly] [Polly] Fix assertion in addUserAssumptions for unreachable blocks (PR #227311)

Karthika Devi C via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 05:11:32 PDT 2026


https://github.com/kartcq updated https://github.com/llvm/llvm-project/pull/227311

>From db803b743b2ae6bf2c47528b86ab1a25006fe473 Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Tue, 29 Sep 2026 06:09:50 -0700
Subject: [PATCH 1/4] [Polly] Fix assertion in addUserAssumptions for
 unreachable blocks

ScopBuilder::addUserAssumptions() crashes when an llvm.assume call
resides in a block that has no entry in InvalidDomainMap. This happens
when __builtin_unreachable() is converted to llvm.assume by earlier
passes, but Polly's buildDomainsWithBranchConstraints() skips the
block (e.g. due to an UnreachableInst terminator), leaving its
InvalidDomainMap entry uninitialized.
Skip such assumptions instead of asserting.

Fixes #226718
---
 polly/lib/Analysis/ScopBuilder.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index 9d48ba2f89248..63d3d56a82c46 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -1472,6 +1472,11 @@ void ScopBuilder::addUserAssumptions(
     SmallVector<isl_set *, 2> ConditionSets;
     auto *TI = InScop ? CI->getParent()->getTerminator() : nullptr;
     BasicBlock *BB = InScop ? CI->getParent() : R.getEntry();
+
+    // Skip assumptions in blocks with no computed domain (e.g. unreachable blocks).
+    if (!InvalidDomainMap.count(BB))
+      continue;
+
     auto *Dom = InScop ? isl_set_copy(scop->getDomainConditions(BB).get())
                        : isl_set_copy(scop->getContext().get());
     assert(Dom && "Cannot propagate a nullptr.");

>From e691033baaf12c4b833ebd03d204f393e000d40b Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Tue, 29 Sep 2026 19:20:36 +0530
Subject: [PATCH 2/4] Update Format

---
 polly/lib/Analysis/ScopBuilder.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index 63d3d56a82c46..6767280dc0790 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -980,7 +980,7 @@ bool ScopBuilder::buildDomainsWithBranchConstraints(
       isl::set CondSet = isl::manage(ConditionSets[u]);
       BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
 
-      // Skip blocks outside the region.
+      blocks outside the region.
       if (!scop->contains(SuccBB))
         continue;
 
@@ -1473,7 +1473,8 @@ void ScopBuilder::addUserAssumptions(
     auto *TI = InScop ? CI->getParent()->getTerminator() : nullptr;
     BasicBlock *BB = InScop ? CI->getParent() : R.getEntry();
 
-    // Skip assumptions in blocks with no computed domain (e.g. unreachable blocks).
+    // Skip assumptions in blocks with no computed domain (e.g. unreachable
+    // blocks).
     if (!InvalidDomainMap.count(BB))
       continue;
 

>From 2ef0f4c06fa2b319dad7b1729357d6aa223bf7b3 Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Tue, 29 Sep 2026 19:29:48 +0530
Subject: [PATCH 3/4] Update ScopBuilder.cpp

---
 polly/lib/Analysis/ScopBuilder.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index 6767280dc0790..de8b4380f8245 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -980,7 +980,7 @@ bool ScopBuilder::buildDomainsWithBranchConstraints(
       isl::set CondSet = isl::manage(ConditionSets[u]);
       BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
 
-      blocks outside the region.
+      // Skip blocks outside the region.
       if (!scop->contains(SuccBB))
         continue;
 

>From 65802a14d1255781afdbc7e305365e4a40ec788f Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Wed, 30 Sep 2026 05:04:41 -0700
Subject: [PATCH 4/4] Address review: clarify comment for non-affine
 subregions, add lit test

---
 polly/lib/Analysis/ScopBuilder.cpp            |  7 ++-
 .../assume_in_non_affine_subregion.ll         | 56 +++++++++++++++++++
 2 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 polly/test/ScopInfo/assume_in_non_affine_subregion.ll

diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index de8b4380f8245..a33a630c7bbdb 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -1473,8 +1473,11 @@ void ScopBuilder::addUserAssumptions(
     auto *TI = InScop ? CI->getParent()->getTerminator() : nullptr;
     BasicBlock *BB = InScop ? CI->getParent() : R.getEntry();
 
-    // Skip assumptions in blocks with no computed domain (e.g. unreachable
-    // blocks).
+    // Skip assumptions in blocks with no computed domain. This includes
+    // interior blocks of non-affine subregions (only the entry block has a
+    // domain) and unreachable blocks. We cannot use getDomainConditions here
+    // as it would return the region's domain for any block in a non-affine
+    // subregion, but the assumption may not actually execute.
     if (!InvalidDomainMap.count(BB))
       continue;
 
diff --git a/polly/test/ScopInfo/assume_in_non_affine_subregion.ll b/polly/test/ScopInfo/assume_in_non_affine_subregion.ll
new file mode 100644
index 0000000000000..09429980d0442
--- /dev/null
+++ b/polly/test/ScopInfo/assume_in_non_affine_subregion.ll
@@ -0,0 +1,56 @@
+; RUN: opt %loadNPMPolly '-passes=polly-custom<scops>' -polly-print-scops -disable-output < %s 2>&1 | FileCheck %s
+;
+; Verify that an llvm.assume inside an interior block of a non-affine
+; subregion does not cause an assertion failure in addUserAssumptions.
+; The assume's block has no InvalidDomainMap entry and must be skipped.
+;
+; https://github.com/llvm/llvm-project/issues/226718
+;
+;    void test(int *A, int *B, long n, int m) {
+;      for (long i = 0; i < n; i++) {
+;        A[i] = m;
+;        if (B[i]) {
+;          if (!(m == 0)) { __builtin_unreachable(); }
+;          B[i] = 1;
+;        }
+;      }
+;    }
+;
+; CHECK: Printing analysis
+; CHECK: Region: %for.body---%exit
+; CHECK: Statements {
+; CHECK: }
+
+define void @test(ptr %A, ptr %B, i64 %n, i32 %m) {
+entry:
+  %cmp = icmp sgt i64 %n, 0
+  br i1 %cmp, label %for.body.ph, label %exit
+
+for.body.ph:
+  %cmp2 = icmp eq i32 %m, 0
+  br label %for.body
+
+for.body:
+  %i = phi i64 [ 0, %for.body.ph ], [ %inc, %for.inc ]
+  %arrayidx.A = getelementptr inbounds i32, ptr %A, i64 %i
+  store i32 %m, ptr %arrayidx.A, align 4
+  %arrayidx.B = getelementptr inbounds i32, ptr %B, i64 %i
+  %val = load i32, ptr %arrayidx.B, align 4
+  %tobool = icmp eq i32 %val, 0
+  br i1 %tobool, label %for.inc, label %if.then
+
+if.then:
+  call void @llvm.assume(i1 %cmp2)
+  store i32 1, ptr %arrayidx.B, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nuw nsw i64 %i, 1
+  %exitcond = icmp eq i64 %inc, %n
+  br i1 %exitcond, label %exit, label %for.body
+
+exit:
+  ret void
+}
+
+declare void @llvm.assume(i1)



More information about the llvm-commits mailing list