[Mlir-commits] [mlir] d25e91d - Support alias.scope and noalias metadata
Alex Zinenko
llvmlistbot at llvm.org
Tue Aug 24 11:43:08 PDT 2021
Author: Tyler Augustine
Date: 2021-08-24T20:42:59+02:00
New Revision: d25e91d7f61acc9f6fdfa908a45f9127fe4f13a2
URL: https://github.com/llvm/llvm-project/commit/d25e91d7f61acc9f6fdfa908a45f9127fe4f13a2
DIFF: https://github.com/llvm/llvm-project/commit/d25e91d7f61acc9f6fdfa908a45f9127fe4f13a2.diff
LOG: Support alias.scope and noalias metadata
Introduces new Ops to represent 1. alias.scope metadata in LLVM, and 2. domains for these scopes. These correspond to the metadata described in https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata. Lists of scopes are modeled the same way as access groups - as an ArrayAttr on the Op (added in https://reviews.llvm.org/D97944).
Lowering 'noalias' attributes on function parameters is already supported. However, lowering `noalias` metadata on individual Ops is not, which is added in this change. LLVM uses the same keyword for these, but this change introduces a separate attribute name 'noalias_scopes' to represent this distinct concept.
Reviewed By: mehdi_amini
Differential Revision: https://reviews.llvm.org/D107870
Added:
Modified:
mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Dialect/LLVMIR/invalid.mlir
mlir/test/Target/LLVMIR/llvmir.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
index 29ebdcd987117..a0508697ec8f8 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
@@ -32,6 +32,8 @@ def LLVM_Dialect : Dialect {
static StringRef getDataLayoutAttrName() { return "llvm.data_layout"; }
static StringRef getAlignAttrName() { return "llvm.align"; }
static StringRef getNoAliasAttrName() { return "llvm.noalias"; }
+ static StringRef getNoAliasScopesAttrName() { return "noalias_scopes"; }
+ static StringRef getAliasScopesAttrName() { return "alias_scopes"; }
static StringRef getLoopAttrName() { return "llvm.loop"; }
static StringRef getParallelAccessAttrName() { return "parallel_access"; }
static StringRef getLoopOptionsAttrName() { return "options"; }
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 2b05ae1858146..8505f6f437170 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -286,6 +286,10 @@ class MemoryOpWithAlignmentAndAttributes : MemoryOpWithAlignmentBase {
code setAccessGroupsMetadataCode = [{
moduleTranslation.setAccessGroupsMetadata(op, inst);
}];
+
+ code setAliasScopeMetadataCode = [{
+ moduleTranslation.setAliasScopeMetadata(op, inst);
+ }];
}
// Memory-related operations.
@@ -329,13 +333,19 @@ def LLVM_GEPOp
def LLVM_LoadOp : LLVM_Op<"load">, MemoryOpWithAlignmentAndAttributes {
let arguments = (ins LLVM_PointerTo<LLVM_LoadableType>:$addr,
OptionalAttr<SymbolRefArrayAttr>:$access_groups,
+ OptionalAttr<SymbolRefArrayAttr>:$alias_scopes,
+ OptionalAttr<SymbolRefArrayAttr>:$noalias_scopes,
OptionalAttr<I64Attr>:$alignment, UnitAttr:$volatile_,
UnitAttr:$nontemporal);
let results = (outs LLVM_LoadableType:$res);
string llvmBuilder = [{
auto *inst = builder.CreateLoad(
$addr->getType()->getPointerElementType(), $addr, $volatile_);
- }] # setAlignmentCode # setNonTemporalMetadataCode # setAccessGroupsMetadataCode # [{
+ }] # setAlignmentCode
+ # setNonTemporalMetadataCode
+ # setAccessGroupsMetadataCode
+ # setAliasScopeMetadataCode
+ # [{
$res = inst;
}];
let builders = [
@@ -357,11 +367,16 @@ def LLVM_StoreOp : LLVM_Op<"store">, MemoryOpWithAlignmentAndAttributes {
let arguments = (ins LLVM_LoadableType:$value,
LLVM_PointerTo<LLVM_LoadableType>:$addr,
OptionalAttr<SymbolRefArrayAttr>:$access_groups,
+ OptionalAttr<SymbolRefArrayAttr>:$alias_scopes,
+ OptionalAttr<SymbolRefArrayAttr>:$noalias_scopes,
OptionalAttr<I64Attr>:$alignment, UnitAttr:$volatile_,
UnitAttr:$nontemporal);
string llvmBuilder = [{
auto *inst = builder.CreateStore($value, $addr, $volatile_);
- }] # setAlignmentCode # setNonTemporalMetadataCode # setAccessGroupsMetadataCode;
+ }] # setAlignmentCode
+ # setNonTemporalMetadataCode
+ # setAccessGroupsMetadataCode
+ # setAliasScopeMetadataCode;
let builders = [
OpBuilder<(ins "Value":$value, "Value":$addr,
CArg<"unsigned", "0">:$alignment, CArg<"bool", "false">:$isVolatile,
@@ -876,8 +891,7 @@ def LLVM_MetadataOp : LLVM_Op<"metadata", [
);
let summary = "LLVM dialect metadata.";
let description = [{
- llvm.metadata op defines one or more metadata nodes. Currently the
- llvm.access_group metadata op is supported.
+ llvm.metadata op defines one or more metadata nodes.
Example:
llvm.metadata @metadata {
@@ -890,6 +904,66 @@ def LLVM_MetadataOp : LLVM_Op<"metadata", [
let assemblyFormat = "$sym_name attr-dict-with-keyword $body";
}
+def LLVM_AliasScopeDomainMetadataOp : LLVM_Op<"alias_scope_domain", [
+ HasParent<"MetadataOp">, Symbol
+]> {
+ let arguments = (ins
+ SymbolNameAttr:$sym_name,
+ OptionalAttr<StrAttr>:$description
+ );
+ let summary = "LLVM dialect alias.scope domain metadata.";
+ let description = [{
+ Defines a domain that may be associated with an alias scope.
+
+ See the following link for more details:
+ https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
+ }];
+ let assemblyFormat = "$sym_name attr-dict";
+}
+
+def LLVM_AliasScopeMetadataOp : LLVM_Op<"alias_scope", [
+ HasParent<"MetadataOp">, Symbol
+]> {
+ let arguments = (ins
+ SymbolNameAttr:$sym_name,
+ FlatSymbolRefAttr:$domain,
+ OptionalAttr<StrAttr>:$description
+ );
+ let summary = "LLVM dialect alias.scope metadata.";
+ let description = [{
+ Defines an alias scope that can be attached to a memory-accessing operation.
+ Such scopes can be used in combination with `noalias` metadata to indicate
+ that sets of memory-affecting operations in one scope do not alias with
+ memory-affecting operations in another scope.
+
+ Example:
+ module {
+ llvm.func @foo(%ptr1 : !llvm.ptr<i32>) {
+ %c0 = llvm.mlir.constant(0 : i32) : i32
+ %c4 = llvm.mlir.constant(4 : i32) : i32
+ %1 = llvm.ptrtoint %ptr1 : !llvm.ptr<i32> to i32
+ %2 = llvm.add %1, %c1 : i32
+ %ptr2 = llvm.inttoptr %2 : i32 to !llvm.ptr<i32>
+ llvm.store %c0, %ptr1 { alias_scopes = [@metadata::@scope1], llvm.noalias = [@metadata::@scope2] } : !llvm.ptr<i32>
+ llvm.store %c4, %ptr2 { alias_scopes = [@metadata::@scope2], llvm.noalias = [@metadata::@scope1] } : !llvm.ptr<i32>
+ llvm.return
+ }
+
+ llvm.metadata @metadata {
+ llvm.alias_scope_domain @unused_domain
+ llvm.alias_scope_domain @domain { description = "Optional domain description"}
+ llvm.alias_scope @scope1 { domain = @domain }
+ llvm.alias_scope @scope2 { domain = @domain, description = "Optional scope description" }
+ llvm.return
+ }
+ }
+
+ See the following link for more details:
+ https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
+ }];
+ let assemblyFormat = "$sym_name attr-dict";
+}
+
def LLVM_AccessGroupMetadataOp : LLVM_Op<"access_group", [
HasParent<"MetadataOp">, Symbol
]> {
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index f8c8ff8debe8b..6df772d8e68b1 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -115,6 +115,11 @@ class ModuleTranslation {
llvm::MDNode *getAccessGroup(Operation &opInst,
SymbolRefAttr accessGroupRef) const;
+ /// Returns the LLVM metadata corresponding to a reference to an mlir LLVM
+ /// dialect alias scope operation
+ llvm::MDNode *getAliasScope(Operation &opInst,
+ SymbolRefAttr aliasScopeRef) const;
+
/// Returns the LLVM metadata corresponding to a llvm loop's codegen
/// options attribute.
llvm::MDNode *lookupLoopOptionsMetadata(Attribute options) const {
@@ -131,6 +136,9 @@ class ModuleTranslation {
// Sets LLVM metadata for memory operations that are in a parallel loop.
void setAccessGroupsMetadata(Operation *op, llvm::Instruction *inst);
+ // Sets LLVM metadata for memory operations that have alias scope information.
+ void setAliasScopeMetadata(Operation *op, llvm::Instruction *inst);
+
/// Converts the type from MLIR LLVM dialect to LLVM.
llvm::Type *convertType(Type type);
@@ -268,6 +276,10 @@ class ModuleTranslation {
/// metadata nodes.
LogicalResult createAccessGroupMetadata();
+ /// Process alias.scope LLVM Metadata operations and create LLVM
+ /// metadata nodes for them and their domains.
+ LogicalResult createAliasScopeMetadata();
+
/// Translates dialect attributes attached to the given operation.
LogicalResult convertDialectAttributes(Operation *op);
@@ -300,7 +312,7 @@ class ModuleTranslation {
/// values after all operations are converted.
DenseMap<Operation *, llvm::Instruction *> branchMapping;
- /// Mapping from an access group metadata optation to its LLVM metadata.
+ /// Mapping from an access group metadata operation to its LLVM metadata.
/// This map is populated on module entry and is used to annotate loops (as
/// identified via their branches) and contained memory accesses.
DenseMap<Operation *, llvm::MDNode *> accessGroupMetadataMapping;
@@ -310,6 +322,10 @@ class ModuleTranslation {
/// attribute.
DenseMap<Attribute, llvm::MDNode *> loopOptionsMetadataMapping;
+ /// Mapping from an access scope metadata operation to its LLVM metadata.
+ /// This map is populated on module entry.
+ DenseMap<Operation *, llvm::MDNode *> aliasScopeMetadataMapping;
+
/// Stack of user-specified state elements, useful when translating operations
/// with regions.
SmallVector<std::unique_ptr<StackFrame>> stack;
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index ca66e7f08af97..7a8ff8fbdb317 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -335,32 +335,76 @@ SwitchOp::getMutableSuccessorOperands(unsigned index) {
// Builder, printer and parser for for LLVM::LoadOp.
//===----------------------------------------------------------------------===//
-static LogicalResult verifyAccessGroups(Operation *op) {
- if (Attribute attribute =
- op->getAttr(LLVMDialect::getAccessGroupsAttrName())) {
+LogicalResult verifySymbolAttribute(
+ Operation *op, StringRef attributeName,
+ std::function<LogicalResult(Operation *, SymbolRefAttr)> verifySymbolType) {
+ if (Attribute attribute = op->getAttr(attributeName)) {
// The attribute is already verified to be a symbol ref array attribute via
// a constraint in the operation definition.
- for (SymbolRefAttr accessGroupRef :
+ for (SymbolRefAttr symbolRef :
attribute.cast<ArrayAttr>().getAsRange<SymbolRefAttr>()) {
- StringRef metadataName = accessGroupRef.getRootReference();
+ StringRef metadataName = symbolRef.getRootReference();
+ StringRef symbolName = symbolRef.getLeafReference();
+ // We want @metadata::@symbol, not just @symbol
+ if (metadataName == symbolName) {
+ return op->emitOpError() << "expected '" << symbolRef
+ << "' to specify a fully qualified reference";
+ }
auto metadataOp = SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
op->getParentOp(), metadataName);
if (!metadataOp)
- return op->emitOpError() << "expected '" << accessGroupRef
- << "' to reference a metadata op";
- StringRef accessGroupName = accessGroupRef.getLeafReference();
- Operation *accessGroupOp =
- SymbolTable::lookupNearestSymbolFrom(metadataOp, accessGroupName);
- if (!accessGroupOp)
- return op->emitOpError() << "expected '" << accessGroupRef
- << "' to reference an access_group op";
+ return op->emitOpError()
+ << "expected '" << symbolRef << "' to reference a metadata op";
+ Operation *symbolOp =
+ SymbolTable::lookupNearestSymbolFrom(metadataOp, symbolName);
+ if (!symbolOp)
+ return op->emitOpError()
+ << "expected '" << symbolRef << "' to be a valid reference";
+ if (failed(verifySymbolType(symbolOp, symbolRef))) {
+ return failure();
+ }
}
}
return success();
}
+// Verifies that metadata ops are wired up properly.
+template <typename OpTy>
+static LogicalResult verifyOpMetadata(Operation *op, StringRef attributeName) {
+ auto verifySymbolType = [op](Operation *symbolOp,
+ SymbolRefAttr symbolRef) -> LogicalResult {
+ if (!isa<OpTy>(symbolOp)) {
+ return op->emitOpError()
+ << "expected '" << symbolRef << "' to resolve to a "
+ << OpTy::getOperationName();
+ }
+ return success();
+ };
+
+ return verifySymbolAttribute(op, attributeName, verifySymbolType);
+}
+
+static LogicalResult verifyMemoryOpMetadata(Operation *op) {
+ // access_groups
+ if (failed(verifyOpMetadata<LLVM::AccessGroupMetadataOp>(
+ op, LLVMDialect::getAccessGroupsAttrName())))
+ return failure();
+
+ // alias_scopes
+ if (failed(verifyOpMetadata<LLVM::AliasScopeMetadataOp>(
+ op, LLVMDialect::getAliasScopesAttrName())))
+ return failure();
+
+ // noalias_scopes
+ if (failed(verifyOpMetadata<LLVM::AliasScopeMetadataOp>(
+ op, LLVMDialect::getNoAliasScopesAttrName())))
+ return failure();
+
+ return success();
+}
+
static LogicalResult verify(LoadOp op) {
- return verifyAccessGroups(op.getOperation());
+ return verifyMemoryOpMetadata(op.getOperation());
}
void LoadOp::build(OpBuilder &builder, OperationState &result, Type t,
@@ -422,7 +466,7 @@ static ParseResult parseLoadOp(OpAsmParser &parser, OperationState &result) {
//===----------------------------------------------------------------------===//
static LogicalResult verify(StoreOp op) {
- return verifyAccessGroups(op.getOperation());
+ return verifyMemoryOpMetadata(op.getOperation());
}
void StoreOp::build(OpBuilder &builder, OperationState &result, Value value,
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index f078ded04ec7f..0c3839ae9b8c2 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -774,6 +774,78 @@ void ModuleTranslation::setAccessGroupsMetadata(Operation *op,
}
}
+LogicalResult ModuleTranslation::createAliasScopeMetadata() {
+ mlirModule->walk([&](LLVM::MetadataOp metadatas) {
+ // Create the domains first, so they can be reference below in the scopes.
+ DenseMap<Operation *, llvm::MDNode *> aliasScopeDomainMetadataMapping;
+ metadatas.walk([&](LLVM::AliasScopeDomainMetadataOp op) {
+ llvm::LLVMContext &ctx = llvmModule->getContext();
+ llvm::SmallVector<llvm::Metadata *, 2> operands;
+ operands.push_back({}); // Placeholder for self-reference
+ if (Optional<StringRef> description = op.description())
+ operands.push_back(llvm::MDString::get(ctx, description.getValue()));
+ llvm::MDNode *domain = llvm::MDNode::get(ctx, operands);
+ domain->replaceOperandWith(0, domain); // Self-reference for uniqueness
+ aliasScopeDomainMetadataMapping.insert({op, domain});
+ });
+
+ // Now create the scopes, referencing the domains created above.
+ metadatas.walk([&](LLVM::AliasScopeMetadataOp op) {
+ llvm::LLVMContext &ctx = llvmModule->getContext();
+ assert(isa<LLVM::MetadataOp>(op->getParentOp()));
+ auto metadataOp = dyn_cast<LLVM::MetadataOp>(op->getParentOp());
+ Operation *domainOp =
+ SymbolTable::lookupNearestSymbolFrom(metadataOp, op.domainAttr());
+ llvm::MDNode *domain = aliasScopeDomainMetadataMapping.lookup(domainOp);
+ assert(domain && "Scope's domain should already be valid");
+ llvm::SmallVector<llvm::Metadata *, 3> operands;
+ operands.push_back({}); // Placeholder for self-reference
+ operands.push_back(domain);
+ if (Optional<StringRef> description = op.description())
+ operands.push_back(llvm::MDString::get(ctx, description.getValue()));
+ llvm::MDNode *scope = llvm::MDNode::get(ctx, operands);
+ scope->replaceOperandWith(0, scope); // Self-reference for uniqueness
+ aliasScopeMetadataMapping.insert({op, scope});
+ });
+ });
+ return success();
+}
+
+llvm::MDNode *
+ModuleTranslation::getAliasScope(Operation &opInst,
+ SymbolRefAttr aliasScopeRef) const {
+ StringRef metadataName = aliasScopeRef.getRootReference();
+ StringRef scopeName = aliasScopeRef.getLeafReference();
+ auto metadataOp = SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
+ opInst.getParentOp(), metadataName);
+ Operation *aliasScopeOp =
+ SymbolTable::lookupNearestSymbolFrom(metadataOp, scopeName);
+ return aliasScopeMetadataMapping.lookup(aliasScopeOp);
+}
+
+void ModuleTranslation::setAliasScopeMetadata(Operation *op,
+ llvm::Instruction *inst) {
+ auto populateScopeMetadata = [this, op, inst](StringRef attrName,
+ StringRef llvmMetadataName) {
+ auto scopes = op->getAttrOfType<ArrayAttr>(attrName);
+ if (!scopes || scopes.empty())
+ return;
+ llvm::Module *module = inst->getModule();
+ SmallVector<llvm::Metadata *> scopeMDs;
+ for (SymbolRefAttr scopeRef : scopes.getAsRange<SymbolRefAttr>())
+ scopeMDs.push_back(getAliasScope(*op, scopeRef));
+ llvm::MDNode *unionMD = nullptr;
+ if (scopeMDs.size() == 1)
+ unionMD = llvm::cast<llvm::MDNode>(scopeMDs.front());
+ else if (scopeMDs.size() >= 2)
+ unionMD = llvm::MDNode::get(module->getContext(), scopeMDs);
+ inst->setMetadata(module->getMDKindID(llvmMetadataName), unionMD);
+ };
+
+ populateScopeMetadata(LLVMDialect::getAliasScopesAttrName(), "alias.scope");
+ populateScopeMetadata(LLVMDialect::getNoAliasScopesAttrName(), "noalias");
+}
+
llvm::Type *ModuleTranslation::convertType(Type type) {
return typeTranslator.translateType(type);
}
@@ -842,6 +914,8 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
return nullptr;
if (failed(translator.createAccessGroupMetadata()))
return nullptr;
+ if (failed(translator.createAliasScopeMetadata()))
+ return nullptr;
if (failed(translator.convertFunctions()))
return nullptr;
if (llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index 22fe88d7df415..c80be74ce9002 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -909,7 +909,7 @@ module {
module {
llvm.func @accessGroups(%arg0 : !llvm.ptr<i32>) {
- // expected-error at below {{expected '@func1' to reference a metadata op}}
+ // expected-error at below {{expected '@func1' to specify a fully qualified reference}}
%0 = llvm.load %arg0 { "access_groups" = [@func1] } : !llvm.ptr<i32>
llvm.return
}
@@ -922,11 +922,87 @@ module {
module {
llvm.func @accessGroups(%arg0 : !llvm.ptr<i32>) {
- // expected-error at below {{expected '@metadata' to reference an access_group op}}
- %0 = llvm.load %arg0 { "access_groups" = [@metadata] } : !llvm.ptr<i32>
+ // expected-error at below {{expected '@accessGroups::@group1' to reference a metadata op}}
+ %0 = llvm.load %arg0 { "access_groups" = [@accessGroups::@group1] } : !llvm.ptr<i32>
+ llvm.return
+ }
+ llvm.metadata @metadata {
+ llvm.return
+ }
+}
+
+// -----
+
+module {
+ llvm.func @accessGroups(%arg0 : !llvm.ptr<i32>) {
+ // expected-error at below {{expected '@metadata::@group1' to be a valid reference}}
+ %0 = llvm.load %arg0 { "access_groups" = [@metadata::@group1] } : !llvm.ptr<i32>
+ llvm.return
+ }
+ llvm.metadata @metadata {
+ llvm.return
+ }
+}
+
+// -----
+
+module {
+ llvm.func @accessGroups(%arg0 : !llvm.ptr<i32>) {
+ // expected-error at below {{expected '@metadata::@scope' to resolve to a llvm.access_group}}
+ %0 = llvm.load %arg0 { "access_groups" = [@metadata::@scope] } : !llvm.ptr<i32>
+ llvm.return
+ }
+ llvm.metadata @metadata {
+ llvm.alias_scope_domain @domain
+ llvm.alias_scope @scope { domain = @domain }
+ llvm.return
+ }
+}
+
+// -----
+
+module {
+ llvm.func @accessGroups(%arg0 : !llvm.ptr<i32>) {
+ // expected-error at below {{attribute 'alias_scopes' failed to satisfy constraint: symbol ref array attribute}}
+ %0 = llvm.load %arg0 { "alias_scopes" = "test" } : !llvm.ptr<i32>
+ llvm.return
+ }
+}
+
+// -----
+
+module {
+ llvm.func @accessGroups(%arg0 : !llvm.ptr<i32>) {
+ // expected-error at below {{attribute 'noalias_scopes' failed to satisfy constraint: symbol ref array attribute}}
+ %0 = llvm.load %arg0 { "noalias_scopes" = "test" } : !llvm.ptr<i32>
+ llvm.return
+ }
+}
+
+// -----
+
+module {
+ llvm.func @aliasScope(%arg0 : !llvm.ptr<i32>) {
+ // expected-error at below {{expected '@metadata::@group' to resolve to a llvm.alias_scope}}
+ %0 = llvm.load %arg0 { "alias_scopes" = [@metadata::@group] } : !llvm.ptr<i32>
+ llvm.return
+ }
+ llvm.metadata @metadata {
+ llvm.access_group @group
+ llvm.return
+ }
+}
+
+// -----
+
+module {
+ llvm.func @aliasScope(%arg0 : !llvm.ptr<i32>) {
+ // expected-error at below {{expected '@metadata::@group' to resolve to a llvm.alias_scope}}
+ %0 = llvm.load %arg0 { "noalias_scopes" = [@metadata::@group] } : !llvm.ptr<i32>
llvm.return
}
llvm.metadata @metadata {
+ llvm.access_group @group
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index aa1c934c7bf21..e6795e5199b26 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -1594,3 +1594,39 @@ module {
// CHECK: ![[PIPELINE_DISABLE_NODE]] = !{!"llvm.loop.pipeline.disable", i1 true}
// CHECK: ![[II_NODE]] = !{!"llvm.loop.pipeline.initiationinterval", i32 2}
// CHECK: ![[ACCESS_GROUPS_NODE]] = !{![[GROUP_NODE1]], ![[GROUP_NODE2]]}
+
+// -----
+
+module {
+ llvm.func @aliasScope(%arg1 : !llvm.ptr<i32>, %arg2 : !llvm.ptr<i32>, %arg3 : !llvm.ptr<i32>) {
+ %0 = llvm.mlir.constant(0 : i32) : i32
+ llvm.store %0, %arg1 { alias_scopes = [@metadata::@scope1], noalias_scopes = [@metadata::@scope2, @metadata::@scope3] } : !llvm.ptr<i32>
+ llvm.store %0, %arg2 { alias_scopes = [@metadata::@scope2], noalias_scopes = [@metadata::@scope1, @metadata::@scope3] } : !llvm.ptr<i32>
+ %1 = llvm.load %arg3 { alias_scopes = [@metadata::@scope3], noalias_scopes = [@metadata::@scope1, @metadata::@scope2] } : !llvm.ptr<i32>
+ 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 }
+ llvm.return
+ }
+}
+
+// Function
+// CHECK-LABEL: aliasScope
+// CHECK: store {{.*}}, !alias.scope ![[SCOPE1:[0-9]+]], !noalias ![[SCOPES23:[0-9]+]]
+// CHECK: store {{.*}}, !alias.scope ![[SCOPE2:[0-9]+]], !noalias ![[SCOPES13:[0-9]+]]
+// CHECK: load {{.*}}, !alias.scope ![[SCOPE3:[0-9]+]], !noalias ![[SCOPES12:[0-9]+]]
+
+// Metadata
+// CHECK-DAG: ![[DOMAIN:[0-9]+]] = distinct !{![[DOMAIN]], !"The domain"}
+// CHECK-DAG: ![[SCOPE1]] = distinct !{![[SCOPE1]], ![[DOMAIN]], !"The first scope"}
+// CHECK-DAG: ![[SCOPE2]] = distinct !{![[SCOPE2]], ![[DOMAIN]]}
+// CHECK-DAG: ![[SCOPE3]] = distinct !{![[SCOPE3]], ![[DOMAIN]]}
+// CHECK-DAG: ![[SCOPES12]] = !{![[SCOPE1]], ![[SCOPE2]]}
+// CHECK-DAG: ![[SCOPES13]] = !{![[SCOPE1]], ![[SCOPE3]]}
+// CHECK-DAG: ![[SCOPES23]] = !{![[SCOPE2]], ![[SCOPE3]]}
+
More information about the Mlir-commits
mailing list