[llvm-branch-commits] [mlir] [mlir][LLVM] Use a disjoint scope domain when inlining noalias (PR #218773)

Krzysztof Drewniak via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Aug 26 16:58:21 PDT 2026


https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/218773

>From c07395ecf88e64dc162878c7aabdb1ec7f42d44a Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Thu, 20 Aug 2026 22:54:40 +0000
Subject: [PATCH 1/2] [mlir][LLVM] Use a disjoint scope domain when inlining
 noalias

This matches recent changes to the LLVM inliner.

AI disclosure: Claude wrote the code, I wrote the commit message and
have done initial review.
---
 .../Transforms/InlinerInterfaceImpl.cpp       | 53 ++++++++++---------
 .../Dialect/LLVMIR/inlining-alias-scopes.mlir | 28 ++++------
 2 files changed, 38 insertions(+), 43 deletions(-)

diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
index df4ad5720972d..e44ab60644947 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
@@ -307,9 +307,12 @@ static void createNewAliasScopesFromNoAliasParameter(
     return;
 
   // Create a new domain for this specific inlining and a new scope for every
-  // noalias parameter.
+  // noalias parameter. The scopes are disjoint, since an access based on one
+  // noalias parameter can't reach memory an access based on another one
+  // reaches.
   auto functionDomain = LLVM::AliasScopeDomainAttr::get(
-      call->getContext(), cast<LLVM::CallOp>(call).getCalleeAttr().getAttr());
+      call->getContext(), cast<LLVM::CallOp>(call).getCalleeAttr().getAttr(),
+      /*disjointScopes=*/true);
   DenseMap<Value, LLVM::AliasScopeAttr> pointerScopes;
   for (LLVM::SSACopyOp copyOp : noAliasParams) {
     auto scope = LLVM::AliasScopeAttr::get(functionDomain);
@@ -367,21 +370,6 @@ static void createNewAliasScopesFromNoAliasParameter(
           }))
         return;
 
-      // Add all noalias parameter scopes to the noalias scope list that we are
-      // not based on.
-      SmallVector<Attribute> noAliasScopes;
-      for (LLVM::SSACopyOp noAlias : noAliasParams) {
-        if (basedOnPointers.contains(noAlias))
-          continue;
-
-        noAliasScopes.push_back(pointerScopes[noAlias]);
-      }
-
-      if (!noAliasScopes.empty())
-        aliasInterface.setNoAliasScopes(
-            concatArrayAttr(aliasInterface.getNoAliasScopesOrNull(),
-                            ArrayAttr::get(call->getContext(), noAliasScopes)));
-
       // Don't add alias scopes to call operations or operations that might
       // operate on pointers not based on any noalias parameter.
       // Since we add all scopes to an operation's noalias list that it
@@ -406,19 +394,34 @@ static void createNewAliasScopesFromNoAliasParameter(
       // Call operations are included in this list since we do not know whether
       // the callee accesses any memory besides the ones passed as its
       // arguments.
-      if (aliasesOtherKnownObject ||
-          isa<LLVM::CallOp>(aliasInterface.getOperation()))
-        return;
-
       SmallVector<Attribute> aliasScopes;
-      for (LLVM::SSACopyOp noAlias : noAliasParams)
-        if (basedOnPointers.contains(noAlias))
-          aliasScopes.push_back(pointerScopes[noAlias]);
+      if (!aliasesOtherKnownObject &&
+          !isa<LLVM::CallOp>(aliasInterface.getOperation()))
+        for (LLVM::SSACopyOp noAlias : noAliasParams)
+          if (basedOnPointers.contains(noAlias))
+            aliasScopes.push_back(pointerScopes[noAlias]);
 
-      if (!aliasScopes.empty())
+      if (!aliasScopes.empty()) {
         aliasInterface.setAliasScopes(
             concatArrayAttr(aliasInterface.getAliasScopesOrNull(),
                             ArrayAttr::get(call->getContext(), aliasScopes)));
+        return;
+      }
+
+      // Add all noalias parameter scopes to the noalias scope list that we are
+      // not based on.
+      SmallVector<Attribute> noAliasScopes;
+      for (LLVM::SSACopyOp noAlias : noAliasParams) {
+        if (basedOnPointers.contains(noAlias))
+          continue;
+
+        noAliasScopes.push_back(pointerScopes[noAlias]);
+      }
+
+      if (!noAliasScopes.empty())
+        aliasInterface.setNoAliasScopes(
+            concatArrayAttr(aliasInterface.getNoAliasScopesOrNull(),
+                            ArrayAttr::get(call->getContext(), noAliasScopes)));
     });
   }
 }
diff --git a/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir b/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir
index 0259b4456c3c9..2c8b8428a36c0 100644
--- a/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir
+++ b/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir
@@ -208,7 +208,7 @@ llvm.func @caller(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -223,10 +223,8 @@ llvm.func @foo(%arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.ptr {llvm.noalias})
 // CHECK-LABEL: llvm.func @bar
 // CHECK: llvm.load
 // CHECK-SAME: alias_scopes = [#[[$ARG1_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG0_SCOPE]]]
 // CHECK: llvm.store
 // CHECK-SAME: alias_scopes = [#[[$ARG0_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG1_SCOPE]]]
 llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
   llvm.call @foo(%arg0, %arg2) : (!llvm.ptr, !llvm.ptr) -> ()
   llvm.return
@@ -234,7 +232,7 @@ llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
 llvm.func @foo(%arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.ptr) {
@@ -292,7 +290,7 @@ llvm.func @clone_disjoint_domain(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llv
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -319,7 +317,7 @@ llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -348,7 +346,7 @@ llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -373,7 +371,6 @@ llvm.func @region_branch(%arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.ptr {llvm
 // CHECK-LABEL: llvm.func @region_branch_inlining
 // CHECK: llvm.store
 // CHECK-SAME: alias_scopes = [#[[$ARG0_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG1_SCOPE]]]
 llvm.func @region_branch_inlining(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
   llvm.call @region_branch(%arg0, %arg2) : (!llvm.ptr, !llvm.ptr) -> ()
   llvm.return
@@ -402,7 +399,7 @@ llvm.func @missing_region_branch_inlining(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %a
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -434,7 +431,7 @@ llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -469,7 +466,7 @@ llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG0_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 // CHECK-DAG: #[[$ARG1_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
@@ -490,10 +487,8 @@ llvm.func @supported_operations(%arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.pt
 // CHECK-LABEL: llvm.func @bar
 // CHECK: llvm.store
 // CHECK-SAME: alias_scopes = [#[[$ARG1_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG0_SCOPE]]]
 // CHECK: llvm.load
 // CHECK-SAME: alias_scopes = [#[[$ARG1_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG0_SCOPE]]]
 // CHECK: "llvm.intr.memcpy"
 // CHECK-SAME: alias_scopes = [#[[$ARG0_SCOPE]], #[[$ARG1_SCOPE]]]
 // CHECK-NOT: noalias_scopes
@@ -505,13 +500,10 @@ llvm.func @supported_operations(%arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.pt
 // CHECK-NOT: noalias_scopes
 // CHECK: "llvm.intr.memset"
 // CHECK-SAME: alias_scopes = [#[[$ARG0_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG1_SCOPE]]]
 // CHECK: llvm.cmpxchg
 // CHECK-SAME: alias_scopes = [#[[$ARG0_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG1_SCOPE]]]
 // CHECK: llvm.atomicrmw
 // CHECK-SAME: alias_scopes = [#[[$ARG0_SCOPE]]]
-// CHECK-SAME: noalias_scopes = [#[[$ARG1_SCOPE]]]
 llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
   llvm.call @supported_operations(%arg0, %arg2) : (!llvm.ptr, !llvm.ptr) -> ()
   llvm.return
@@ -519,7 +511,7 @@ llvm.func @bar(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
 llvm.func @foo(%arg: i32)
@@ -546,7 +538,7 @@ llvm.func @noalias_with_region(%arg0: !llvm.ptr) {
 
 // -----
 
-// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}>
+// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}disjointScopes = true{{.*}}>
 // CHECK-DAG: #[[$ARG_SCOPE:.*]] = #llvm.alias_scope<id = {{.*}}, domain = #[[DOMAIN]]{{(,.*)?}}>
 
 llvm.func @foo(%arg: i32)

>From c20482116cf70d565175e0cc215ebe3d41b88fee Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Wed, 26 Aug 2026 19:03:44 +0000
Subject: [PATCH 2/2] Update comment

---
 mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
index e44ab60644947..61ffbd2eb725e 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
@@ -408,8 +408,8 @@ static void createNewAliasScopesFromNoAliasParameter(
         return;
       }
 
-      // Add all noalias parameter scopes to the noalias scope list that we are
-      // not based on.
+      // Mark all the noalias arguments as noalias with this operation if its
+      // scope is something unrelated.
       SmallVector<Attribute> noAliasScopes;
       for (LLVM::SSACopyOp noAlias : noAliasParams) {
         if (basedOnPointers.contains(noAlias))



More information about the llvm-branch-commits mailing list