[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
Tue Aug 25 21:38:47 PDT 2026


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

>From f50a689134a1b391655125be0d3201e8a40be3c1 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] [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 a1b2a6adbfc9d..e301da5338ca6 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
@@ -309,9 +309,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);
@@ -369,21 +372,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
@@ -408,19 +396,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 6b369c5012105..a4363b432d4a3 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) {
@@ -257,7 +255,7 @@ llvm.func @missing_noalias_on_one_ptr(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2:
 
 // -----
 
-// 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]]{{(,.*)?}}>
 
@@ -284,7 +282,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]]{{(,.*)?}}>
 
@@ -313,7 +311,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]]{{(,.*)?}}>
 
@@ -338,7 +336,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
@@ -367,7 +364,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]]{{(,.*)?}}>
 
@@ -399,7 +396,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]]{{(,.*)?}}>
 
@@ -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]]{{(,.*)?}}>
 
@@ -455,10 +452,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
@@ -470,13 +465,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
@@ -484,7 +476,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)
@@ -511,7 +503,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)



More information about the llvm-branch-commits mailing list