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 <[email protected]> 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 <[email protected]> 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)) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
