[Mlir-commits] [mlir] 56d94a9 - [mlir][llvm] Add experimental alias scope decl intrinsic.

Tobias Gysi llvmlistbot at llvm.org
Wed Mar 22 02:26:20 PDT 2023


Author: Tobias Gysi
Date: 2023-03-22T10:21:09+01:00
New Revision: 56d94a90dbbf1845ec71cd749691c74c1dd8a3ef

URL: https://github.com/llvm/llvm-project/commit/56d94a90dbbf1845ec71cd749691c74c1dd8a3ef
DIFF: https://github.com/llvm/llvm-project/commit/56d94a90dbbf1845ec71cd749691c74c1dd8a3ef.diff

LOG: [mlir][llvm] Add experimental alias scope decl intrinsic.

The revision adds the llvm.experimental.noalias.scope.decl intrinsic
to the LLVM dialect and updates the import and export accordingly.

Reviewed By: Dinistro

Differential Revision: https://reviews.llvm.org/D146504

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
    mlir/include/mlir/Target/LLVMIR/ModuleImport.h
    mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
    mlir/lib/Target/LLVMIR/ModuleImport.cpp
    mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
    mlir/test/Dialect/LLVMIR/roundtrip.mlir
    mlir/test/Target/LLVMIR/Import/import-failure.ll
    mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll
    mlir/test/Target/LLVMIR/llvmir.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index 1b62ce0ca3e6e..391de1ffaa5dc 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -167,6 +167,31 @@ def LLVM_MemsetOp : LLVM_ZeroResultIntrOp<"memset", [0, 2], [],
   >];
 }
 
+def LLVM_NoAliasScopeDeclOp
+    : LLVM_ZeroResultIntrOp<"experimental.noalias.scope.decl"> {
+  let arguments = (ins SymbolRefAttr:$scope);
+  string llvmBuilder = [{
+    // Wrap the scope argument into a list since the LLVM IR intrinsic takes
+    // a list containing exactly one scope rather than a scope itself.
+    llvm::MDNode* node = moduleTranslation.getAliasScopes(op, {$scope});
+    builder.CreateNoAliasScopeDeclaration(node);
+  }];
+  string mlirBuilder = [{
+    FailureOr<SmallVector<SymbolRefAttr>> scopeAttrs =
+      moduleImport.matchAliasScopeAttrs(llvmOperands[0]);
+    // Drop the intrinsic if the alias scope translation fails since the scope
+    // is not used by an aliasing operation, such as a load or store, that is
+    // used to convert the alias scope metadata.
+    if (failed(scopeAttrs))
+      return success();
+    if (scopeAttrs->size() != 1)
+      return failure();
+    $_op = $_builder.create<LLVM::NoAliasScopeDeclOp>(
+      $_location, (*scopeAttrs)[0]);
+  }];
+  let assemblyFormat = "$scope attr-dict";
+}
+
 //===----------------------------------------------------------------------===//
 // Lifetime Markers
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index be4f6e5717b11..e1a94d6b80cc9 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -135,6 +135,11 @@ class ModuleImport {
   /// fails.
   DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value);
 
+  /// Converts `value` to an array of symbol references pointing to alias scope
+  /// operations, or returns failure if the conversion fails.
+  FailureOr<SmallVector<SymbolRefAttr>>
+  matchAliasScopeAttrs(llvm::Value *value);
+
   /// Translates the debug location.
   Location translateLoc(llvm::DILocation *loc);
 

diff  --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 67091257a3cf9..a04e285af580e 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -122,9 +122,14 @@ class ModuleTranslation {
   void forgetMapping(Region &region);
 
   /// Returns the LLVM metadata corresponding to a symbol reference to an mlir
-  /// LLVM dialect alias scope operation
+  /// LLVM dialect alias scope operation.
   llvm::MDNode *getAliasScope(Operation *op, SymbolRefAttr aliasScopeRef) const;
 
+  /// Returns the LLVM metadata corresponding to an array of symbol references
+  /// to mlir LLVM dialect alias scope operations.
+  llvm::MDNode *getAliasScopes(Operation *op,
+                               ArrayRef<SymbolRefAttr> aliasScopeRefs) const;
+
   // Sets LLVM metadata for memory operations that are in a parallel loop.
   void setAccessGroupsMetadata(AccessGroupOpInterface op,
                                llvm::Instruction *inst);

diff  --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index a45768726bc43..d3ac7dcc17554 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1215,6 +1215,13 @@ DILocalVariableAttr ModuleImport::matchLocalVariableAttr(llvm::Value *value) {
   return debugImporter->translate(node);
 }
 
+FailureOr<SmallVector<SymbolRefAttr>>
+ModuleImport::matchAliasScopeAttrs(llvm::Value *value) {
+  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
+  auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
+  return lookupAliasScopeAttrs(node);
+}
+
 Location ModuleImport::translateLoc(llvm::DILocation *loc) {
   return debugImporter->translateLoc(loc);
 }

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index ca5fb7dda3841..7159aa49540ef 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1065,16 +1065,22 @@ ModuleTranslation::getAliasScope(Operation *op,
   return aliasScopeMetadataMapping.lookup(aliasScopeOp);
 }
 
+llvm::MDNode *ModuleTranslation::getAliasScopes(
+    Operation *op, ArrayRef<SymbolRefAttr> aliasScopeRefs) const {
+  SmallVector<llvm::Metadata *> nodes;
+  nodes.reserve(aliasScopeRefs.size());
+  for (SymbolRefAttr aliasScopeRef : aliasScopeRefs)
+    nodes.push_back(getAliasScope(op, aliasScopeRef));
+  return llvm::MDNode::get(getLLVMContext(), nodes);
+}
+
 void ModuleTranslation::setAliasScopeMetadata(AliasAnalysisOpInterface op,
                                               llvm::Instruction *inst) {
-  auto populateScopeMetadata = [&](ArrayAttr scopeRefs, unsigned kind) {
-    if (!scopeRefs || scopeRefs.empty())
+  auto populateScopeMetadata = [&](ArrayAttr aliasScopeRefs, unsigned kind) {
+    if (!aliasScopeRefs || aliasScopeRefs.empty())
       return;
-    llvm::Module *module = inst->getModule();
-    SmallVector<llvm::Metadata *> scopeMDs;
-    for (SymbolRefAttr scopeRef : scopeRefs.getAsRange<SymbolRefAttr>())
-      scopeMDs.push_back(getAliasScope(op, scopeRef));
-    llvm::MDNode *node = llvm::MDNode::get(module->getContext(), scopeMDs);
+    llvm::MDNode *node = getAliasScopes(
+        op, llvm::to_vector(aliasScopeRefs.getAsRange<SymbolRefAttr>()));
     inst->setMetadata(kind, node);
   };
 

diff  --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index c9db19b409e25..9147027c9d4b2 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -596,3 +596,15 @@ llvm.func @stackrestore_opaque_pointers(%arg0: !llvm.ptr)  {
   llvm.intr.stackrestore %arg0 : !llvm.ptr
   llvm.return
 }
+
+// CHECK-LABEL: @experimental_noalias_scope_decl
+llvm.func @experimental_noalias_scope_decl() {
+  // CHECK: llvm.intr.experimental.noalias.scope.decl @metadata::@scope
+  llvm.intr.experimental.noalias.scope.decl @metadata::@scope
+  llvm.return
+}
+
+llvm.metadata @metadata {
+  llvm.alias_scope_domain @domain {description = "The domain"}
+  llvm.alias_scope @scope {domain = @domain, description = "The first scope"}
+}

diff  --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 16f2cf2b6283c..b330f654d3d51 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -322,3 +322,18 @@ bb2:
 }
 
 !0 = !{!"function_entry_count", i64 42}
+
+; // -----
+
+; CHECK:      import-failure.ll
+; CHECK-SAME: warning: dropped instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
+define void @unused_scope() {
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  ret void
+}
+
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+!0 = !{!1}
+!1 = !{!1, !2}
+!2 = distinct !{!2, !"The domain"}

diff  --git a/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll b/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll
index a9ed8e9ee556f..eb74b0ab880bb 100644
--- a/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll
+++ b/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll
@@ -62,27 +62,34 @@ define void @two_domains(ptr %arg1) {
 
 ; // -----
 
+; CHECK: llvm.metadata @__llvm_global_metadata {
+; CHECK:   llvm.alias_scope_domain @[[DOMAIN:.*]] {description = "The domain"}
+; CHECK:   llvm.alias_scope @[[$SCOPE:.*]] {domain = @[[DOMAIN]]}
+; CHECK: }
+
 ; CHECK-LABEL: llvm.func @supported_ops
 define void @supported_ops(ptr %arg1, float %arg2, i32 %arg3, i32 %arg4) {
-  ; CHECK: llvm.load {{.*}}alias_scopes =
-  %1 = load i32, ptr %arg1, !alias.scope !3
-  ; CHECK: llvm.store {{.*}}alias_scopes =
-  store i32 %1, ptr %arg1, !alias.scope !3
-  ; CHECK: llvm.atomicrmw {{.*}}alias_scopes =
-  %2 = atomicrmw fmax ptr %arg1, float %arg2 acquire, !alias.scope !3
-  ; CHECK: llvm.cmpxchg {{.*}}alias_scopes =
-  %3 = cmpxchg ptr %arg1, i32 %arg3, i32 %arg4 monotonic seq_cst, !alias.scope !3
-  ; CHECK: "llvm.intr.memcpy"{{.*}}alias_scopes =
-  call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg1, i32 4, i1 false), !alias.scope !3
-  ; CHECK: "llvm.intr.memset"{{.*}}alias_scopes =
-  call void @llvm.memset.p0.i32(ptr %arg1, i8 42, i32 4, i1 false), !alias.scope !3
+  ; CHECK: llvm.intr.experimental.noalias.scope.decl @__llvm_global_metadata::@[[$SCOPE]]
+  call void @llvm.experimental.noalias.scope.decl(metadata !2)
+  ; CHECK: llvm.load {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+  %1 = load i32, ptr %arg1, !alias.scope !2
+  ; CHECK: llvm.store {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+  store i32 %1, ptr %arg1, !alias.scope !2
+  ; CHECK: llvm.atomicrmw {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+  %2 = atomicrmw fmax ptr %arg1, float %arg2 acquire, !alias.scope !2
+  ; CHECK: llvm.cmpxchg {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+  %3 = cmpxchg ptr %arg1, i32 %arg3, i32 %arg4 monotonic seq_cst, !alias.scope !2
+  ; CHECK: "llvm.intr.memcpy"{{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+  call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg1, i32 4, i1 false), !alias.scope !2
+  ; CHECK: "llvm.intr.memset"{{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+  call void @llvm.memset.p0.i32(ptr %arg1, i8 42, i32 4, i1 false), !alias.scope !2
   ret void
 }
 
+declare void @llvm.experimental.noalias.scope.decl(metadata)
 declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
 declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
 
 !0 = distinct !{!0, !"The domain"}
-!1 = distinct !{!1}
-!2 = !{!2, !0}
-!3 = !{!2}
+!1 = !{!1, !0}
+!2 = !{!1}

diff  --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index ce65ff995709c..46120cb348296 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2016,38 +2016,41 @@ llvm.func @switch_weights(%arg0: i32) -> i32 {
 
 // -----
 
-module {
-  llvm.func @aliasScope(%arg1 : !llvm.ptr) {
-      %0 = llvm.mlir.constant(0 : i32) : i32
-      llvm.store %0, %arg1 {alias_scopes = [@metadata::@scope1], noalias_scopes = [@metadata::@scope2, @metadata::@scope3]} : i32, !llvm.ptr
-      %1 = llvm.load %arg1 {alias_scopes = [@metadata::@scope2], noalias_scopes = [@metadata::@scope1, @metadata::@scope3]} : !llvm.ptr -> i32
-      %2 = llvm.atomicrmw add %arg1, %0 monotonic {alias_scopes = [@metadata::@scope3], noalias_scopes = [@metadata::@scope1, @metadata::@scope2]} : !llvm.ptr, i32
-      %3 = llvm.cmpxchg %arg1, %1, %2 acq_rel monotonic {alias_scopes = [@metadata::@scope3]} : !llvm.ptr, i32
-      %4 = llvm.mlir.constant(0 : i1) : i1
-      %5 = llvm.mlir.constant(42 : i8) : i8
-      "llvm.intr.memcpy"(%arg1, %arg1, %0, %4) {alias_scopes = [@metadata::@scope3]} : (!llvm.ptr, !llvm.ptr, i32, i1) -> ()
-      "llvm.intr.memset"(%arg1, %5, %0, %4) {noalias_scopes = [@metadata::@scope3]} : (!llvm.ptr, i8, i32, i1) -> ()
-      llvm.return
-  }
-
-  llvm.metadata @metadata {
-    llvm.alias_scope_domain @domain {description = "The domain"}
-    llvm.alias_scope @scope1 {domain = @domain, description = "The first scope"}
-    llvm.alias_scope @scope2 {domain = @domain}
-    llvm.alias_scope @scope3 {domain = @domain}
-  }
-}
-
-// Function
 // CHECK-LABEL: aliasScope
-// CHECK:  store {{.*}}, !alias.scope ![[SCOPES1:[0-9]+]], !noalias ![[SCOPES23:[0-9]+]]
-// CHECK:  load {{.*}}, !alias.scope ![[SCOPES2:[0-9]+]], !noalias ![[SCOPES13:[0-9]+]]
-// CHECK:  atomicrmw {{.*}}, !alias.scope ![[SCOPES3:[0-9]+]], !noalias ![[SCOPES12:[0-9]+]]
-// CHECK:  cmpxchg {{.*}}, !alias.scope ![[SCOPES3]]
-// CHECK:  llvm.memcpy{{.*}}, !alias.scope ![[SCOPES3]]
-// CHECK:  llvm.memset{{.*}}, !noalias ![[SCOPES3]]
-
-// Metadata
+llvm.func @aliasScope(%arg1 : !llvm.ptr) {
+  %0 = llvm.mlir.constant(0 : i32) : i32
+  // CHECK:  call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPES1:[0-9]+]])
+  llvm.intr.experimental.noalias.scope.decl @metadata::@scope1
+  // CHECK:  store {{.*}}, !alias.scope ![[SCOPES1]], !noalias ![[SCOPES23:[0-9]+]]
+  llvm.store %0, %arg1 {alias_scopes = [@metadata::@scope1], noalias_scopes = [@metadata::@scope2, @metadata::@scope3]} : i32, !llvm.ptr
+  // CHECK:  load {{.*}}, !alias.scope ![[SCOPES2:[0-9]+]], !noalias ![[SCOPES13:[0-9]+]]
+  %1 = llvm.load %arg1 {alias_scopes = [@metadata::@scope2], noalias_scopes = [@metadata::@scope1, @metadata::@scope3]} : !llvm.ptr -> i32
+  // CHECK:  atomicrmw {{.*}}, !alias.scope ![[SCOPES3:[0-9]+]], !noalias ![[SCOPES12:[0-9]+]]
+  %2 = llvm.atomicrmw add %arg1, %0 monotonic {alias_scopes = [@metadata::@scope3], noalias_scopes = [@metadata::@scope1, @metadata::@scope2]} : !llvm.ptr, i32
+  // CHECK:  cmpxchg {{.*}}, !alias.scope ![[SCOPES3]]
+  %3 = llvm.cmpxchg %arg1, %1, %2 acq_rel monotonic {alias_scopes = [@metadata::@scope3]} : !llvm.ptr, i32
+  %4 = llvm.mlir.constant(0 : i1) : i1
+  %5 = llvm.mlir.constant(42 : i8) : i8
+  // CHECK:  llvm.memcpy{{.*}}, !alias.scope ![[SCOPES3]]
+  "llvm.intr.memcpy"(%arg1, %arg1, %0, %4) {alias_scopes = [@metadata::@scope3]} : (!llvm.ptr, !llvm.ptr, i32, i1) -> ()
+  // CHECK:  llvm.memset{{.*}}, !noalias ![[SCOPES3]]
+  "llvm.intr.memset"(%arg1, %5, %0, %4) {noalias_scopes = [@metadata::@scope3]} : (!llvm.ptr, i8, i32, i1) -> ()
+  llvm.return
+}
+
+llvm.metadata @metadata {
+  llvm.alias_scope_domain @domain {description = "The domain"}
+  llvm.alias_scope @scope1 {domain = @domain, description = "The first scope"}
+  llvm.alias_scope @scope2 {domain = @domain}
+  llvm.alias_scope @scope3 {domain = @domain}
+}
+
+// Check the intrinsic declarations.
+// CHECK-DAG: declare void @llvm.experimental.noalias.scope.decl(metadata)
+// CHECK-DAG: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
+// CHECK-DAG: declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
+
+// Check the translated metadata.
 // CHECK-DAG: ![[DOMAIN:[0-9]+]] = distinct !{![[DOMAIN]], !"The domain"}
 // CHECK-DAG: ![[SCOPE1:[0-9]+]] = distinct !{![[SCOPE1]], ![[DOMAIN]], !"The first scope"}
 // CHECK-DAG: ![[SCOPE2:[0-9]+]] = distinct !{![[SCOPE2]], ![[DOMAIN]]}
@@ -2059,7 +2062,6 @@ module {
 // CHECK-DAG: ![[SCOPES13]] = !{![[SCOPE1]], ![[SCOPE3]]}
 // CHECK-DAG: ![[SCOPES23]] = !{![[SCOPE2]], ![[SCOPE3]]}
 
-
 // -----
 
 // It is okay to have repeated successors if they have no arguments.


        


More information about the Mlir-commits mailing list