diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -562,4 +562,92 @@ let assemblyFormat = "`<` struct(params) `>`"; } +//===----------------------------------------------------------------------===// +// AliasScopeDomainAttr +//===----------------------------------------------------------------------===// + +def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain", + "alias_scope_domain"> { + let parameters = (ins + "DistinctAttr":$id, + OptionalParameter<"StringAttr">:$description + ); + + let builders = [ + AttrBuilder<(ins CArg<"StringAttr", "{}">:$description), [{ + return $_get($_ctxt, DistinctAttr::create(UnitAttr::get($_ctxt)), 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 = "`<` struct(params) `>`"; +} + +//===----------------------------------------------------------------------===// +// AliasScopeAttr +//===----------------------------------------------------------------------===// + +def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> { + let parameters = (ins + "DistinctAttr":$id, + "AliasScopeDomainAttr":$domain, + OptionalParameter<"StringAttr">:$description + ); + + let builders = [ + AttrBuilderWithInferredContext<(ins + "AliasScopeDomainAttr":$domain, + CArg<"StringAttr", "{}">:$description + ), [{ + MLIRContext *ctx = domain.getContext(); + return $_get(ctx, DistinctAttr::create(UnitAttr::get(ctx)), domain, description); + }]> + ]; + + 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: + ```mlir + #domain = #llvm.alias_scope_domain, description = "Optional domain description"> + #scope1 = #llvm.alias_scope, domain = #domain> + #scope2 = #llvm.alias_scope, domain = #domain, description = "Optional scope description"> + llvm.func @foo(%ptr1 : !llvm.ptr) { + %c0 = llvm.mlir.constant(0 : i32) : i32 + %c4 = llvm.mlir.constant(4 : i32) : i32 + %1 = llvm.ptrtoint %ptr1 : !llvm.ptr to i32 + %2 = llvm.add %1, %c1 : i32 + %ptr2 = llvm.inttoptr %2 : i32 to !llvm.ptr + llvm.store %c0, %ptr1 { alias_scopes = [#scope1], llvm.noalias = [#scope2] } : !llvm.ptr + llvm.store %c4, %ptr2 { alias_scopes = [#scope2], llvm.noalias = [#scope1] } : !llvm.ptr + llvm.return + } + ``` + + See the following link for more details: + https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata + }]; + + let summary = "LLVM dialect alias scope"; + + let assemblyFormat = "`<` struct(params) `>`"; +} + +def LLVM_AliasScopeArrayAttr + : TypedArrayAttrBase { + let constBuilderCall = ?; +} + #endif // LLVMIR_ATTRDEFS diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -325,15 +325,15 @@ def LLVM_NoAliasScopeDeclOp : LLVM_ZeroResultIntrOp<"experimental.noalias.scope.decl"> { - let arguments = (ins SymbolRefAttr:$scope); + let arguments = (ins LLVM_AliasScopeAttr:$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}); + llvm::MDNode* node = moduleTranslation.getAliasScopes({$scope}); builder.CreateNoAliasScopeDeclaration(node); }]; string mlirBuilder = [{ - FailureOr> scopeAttrs = + FailureOr> 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 diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -279,8 +279,8 @@ DeclareOpInterfaceMethods], traits)>, LLVM_MemOpPatterns { dag aliasAttrs = (ins OptionalAttr:$access_groups, - OptionalAttr:$alias_scopes, - OptionalAttr:$noalias_scopes, + OptionalAttr:$alias_scopes, + OptionalAttr:$noalias_scopes, OptionalAttr:$tbaa); } @@ -324,8 +324,8 @@ (ins OptionalAttr:$access_groups), (ins )), !if(!gt(requiresAliasAnalysis, 0), - (ins OptionalAttr:$alias_scopes, - OptionalAttr:$noalias_scopes, + (ins OptionalAttr:$alias_scopes, + OptionalAttr:$noalias_scopes, OptionalAttr:$tbaa), (ins ))); string resultPattern = !if(!gt(numResults, 1), diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -1101,68 +1101,6 @@ let hasRegionVerifier = 1; } -def LLVM_AliasScopeDomainMetadataOp : LLVM_Op<"alias_scope_domain", [ - HasParent<"MetadataOp">, Symbol -]> { - let arguments = (ins - SymbolNameAttr:$sym_name, - OptionalAttr:$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:$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: - ```mlir - module { - llvm.func @foo(%ptr1 : !llvm.ptr) { - %c0 = llvm.mlir.constant(0 : i32) : i32 - %c4 = llvm.mlir.constant(4 : i32) : i32 - %1 = llvm.ptrtoint %ptr1 : !llvm.ptr to i32 - %2 = llvm.add %1, %c1 : i32 - %ptr2 = llvm.inttoptr %2 : i32 to !llvm.ptr - llvm.store %c0, %ptr1 { alias_scopes = [@metadata::@scope1], llvm.noalias = [@metadata::@scope2] } : !llvm.ptr - llvm.store %c4, %ptr2 { alias_scopes = [@metadata::@scope2], llvm.noalias = [@metadata::@scope1] } : !llvm.ptr - 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" } - } - } - ``` - - See the following link for more details: - https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata - }]; - let assemblyFormat = "$sym_name attr-dict"; - let hasVerifier = 1; -} - def LLVM_AccessGroupMetadataOp : LLVM_Op<"access_group", [ HasParent<"MetadataOp">, Symbol ]> { diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -151,9 +151,9 @@ /// Converts `value` to a label attribute. Asserts if the matching fails. DILabelAttr matchLabelAttr(llvm::Value *value); - /// Converts `value` to an array of symbol references pointing to alias scope - /// operations, or returns failure if the conversion fails. - FailureOr> + /// Converts `value` to an array of alias scopes or returns failure if the + /// conversion fails. + FailureOr> matchAliasScopeAttrs(llvm::Value *value); /// Translates the debug location. @@ -202,10 +202,10 @@ LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const; - /// Returns the symbol references pointing to the alias scope operations that - /// map to the alias scope nodes starting from the metadata `node`. Returns - /// failure, if any of the symbol references cannot be found. - FailureOr> + /// Returns the alias scope attributes that map to the alias scope nodes + /// starting from the metadata `node`. Returns failure, if any of the + /// attributes cannot be found. + FailureOr> lookupAliasScopeAttrs(const llvm::MDNode *node) const; private: @@ -349,9 +349,9 @@ /// operations for all operations that return no result. All operations that /// return a result have a valueMapping entry instead. DenseMap noResultOpMapping; - /// Mapping between LLVM alias scope and domain metadata nodes and symbol - /// references to the LLVM dialect operations corresponding to these nodes. - DenseMap aliasScopeMapping; + /// Mapping between LLVM alias scope and domain metadata nodes and + /// attributes in the LLVM dialect corresponding to these nodes. + DenseMap aliasScopeMapping; /// Mapping between LLVM TBAA metadata nodes and symbol references to the LLVM /// dialect TBAA operations corresponding to these nodes. DenseMap tbaaMapping; diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -122,14 +122,13 @@ /// in these blocks. void forgetMapping(Region ®ion); - /// Returns the LLVM metadata corresponding to a symbol reference to an mlir - /// LLVM dialect alias scope operation. - llvm::MDNode *getAliasScope(Operation *op, SymbolRefAttr aliasScopeRef) const; + /// Returns the LLVM metadata corresponding to a mlir LLVM dialect alias scope + /// attribute. + llvm::MDNode *getAliasScope(AliasScopeAttr aliasScopeAttr) 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 aliasScopeRefs) const; + /// Returns the LLVM metadata corresponding to an array of mlir LLVM dialect + /// alias scope attributes. + llvm::MDNode *getAliasScopes(ArrayRef aliasScopeAttrs) const; // Sets LLVM metadata for memory operations that are in a parallel loop. void setAccessGroupsMetadata(AccessGroupOpInterface op, @@ -335,7 +334,7 @@ /// Mapping from an alias scope metadata operation to its LLVM metadata. /// This map is populated on module entry. - DenseMap aliasScopeMetadataMapping; + DenseMap aliasScopeMetadataMapping; /// Mapping from a tbaa metadata operation to its LLVM metadata. /// This map is populated on module entry. diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -3084,21 +3084,6 @@ return success(); } -//===----------------------------------------------------------------------===// -// AliasScopeMetadataOp -//===----------------------------------------------------------------------===// - -LogicalResult AliasScopeMetadataOp::verify() { - Operation *domainOp = SymbolTable::lookupNearestSymbolFrom( - this->getOperation(), getDomainAttr()); - if (!isa_and_nonnull(domainOp)) { - return this->emitOpError() - << "expected '" << getDomain() - << "' to reference a domain operation in the same region"; - } - return success(); -} - //===----------------------------------------------------------------------===// // OpAsmDialectInterface //===----------------------------------------------------------------------===// @@ -3109,8 +3094,9 @@ AliasResult getAlias(Attribute attr, raw_ostream &os) const override { return TypeSwitch(attr) - .Case(op); - if (failed(verifySymbolRefsPointTo( - iface, "alias scopes", iface.getAliasScopesOrNull()))) - return failure(); - if (failed(verifySymbolRefsPointTo( - iface, "noalias scopes", iface.getNoAliasScopesOrNull()))) - return failure(); if (failed(verifySymbolRefsPointTo( iface, "tbaa tags", iface.getTBAATagsOrNull()))) return failure(); diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp @@ -191,13 +191,12 @@ .Default([](auto) { return failure(); }); } -/// Looks up all the symbol references pointing to the alias scope operations -/// that map to the alias scope nodes starting from the alias scope metadata -/// `node`, and attaches all of them to the imported operation if the lookups -/// succeed. Returns failure otherwise. +/// Looks up all the alias scope attributes that map to the alias scope nodes +/// starting from the alias scope metadata `node`, and attaches all of them to +/// the imported operation if the lookups succeed. Returns failure otherwise. static LogicalResult setAliasScopesAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) { - FailureOr> aliasScopes = + FailureOr> aliasScopes = moduleImport.lookupAliasScopeAttrs(node); if (failed(aliasScopes)) return failure(); @@ -207,8 +206,7 @@ return failure(); iface.setAliasScopes(ArrayAttr::get( - iface.getContext(), - SmallVector{aliasScopes->begin(), aliasScopes->end()})); + iface.getContext(), llvm::to_vector_of(*aliasScopes))); return success(); } @@ -219,7 +217,7 @@ static LogicalResult setNoaliasScopesAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) { - FailureOr> noAliasScopes = + FailureOr> noAliasScopes = moduleImport.lookupAliasScopeAttrs(node); if (failed(noAliasScopes)) return failure(); @@ -229,8 +227,7 @@ return failure(); iface.setNoAliasScopes(ArrayAttr::get( - iface.getContext(), - SmallVector{noAliasScopes->begin(), noAliasScopes->end()})); + iface.getContext(), llvm::to_vector_of(*noAliasScopes))); return success(); } diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -454,14 +454,14 @@ return idx >= node->getNumOperands() || isa(node->getOperand(idx)); }; - // Helper that creates an alias scope domain operation. + // Helper that creates an alias scope domain attribute. auto createAliasScopeDomainOp = [&](const llvm::MDNode *aliasDomain) { StringAttr description = nullptr; if (aliasDomain->getNumOperands() >= 2) if (auto *operand = dyn_cast(aliasDomain->getOperand(1))) description = builder.getStringAttr(operand->getString()); - std::string name = llvm::formatv("domain_{0}", aliasScopeMapping.size()); - return builder.create(loc, name, description); + return builder.getAttr( + DistinctAttr::create(builder.getUnitAttr()), description); }; // Collect the alias scopes and domains to translate them. @@ -484,49 +484,34 @@ if (aliasScopeMapping.contains(scope)) continue; - // Set the insertion point to the end of the global metadata operation. - MetadataOp metadataOp = getGlobalMetadataOp(); - StringAttr metadataOpName = - SymbolTable::getSymbolName(getGlobalMetadataOp()); - OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPointToEnd(&metadataOp.getBody().back()); - // Convert the domain metadata node if it has not been translated before. auto it = aliasScopeMapping.find(aliasScope.getDomain()); if (it == aliasScopeMapping.end()) { auto aliasScopeDomainOp = createAliasScopeDomainOp(domain); - auto symbolRef = SymbolRefAttr::get( - builder.getContext(), metadataOpName, - FlatSymbolRefAttr::get(builder.getContext(), - aliasScopeDomainOp.getSymName())); - it = aliasScopeMapping.try_emplace(domain, symbolRef).first; + it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first; } // Convert the scope metadata node if it has not been converted before. StringAttr description = nullptr; if (!aliasScope.getName().empty()) description = builder.getStringAttr(aliasScope.getName()); - std::string name = llvm::formatv("scope_{0}", aliasScopeMapping.size()); - auto aliasScopeOp = builder.create( - loc, name, it->getSecond().getLeafReference().getValue(), - description); - auto symbolRef = - SymbolRefAttr::get(builder.getContext(), metadataOpName, - FlatSymbolRefAttr::get(builder.getContext(), - aliasScopeOp.getSymName())); - aliasScopeMapping.try_emplace(aliasScope.getNode(), symbolRef); + auto aliasScopeOp = builder.getAttr( + DistinctAttr::create(builder.getUnitAttr()), + cast(it->second), description); + aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp); } } return success(); } -FailureOr> +FailureOr> ModuleImport::lookupAliasScopeAttrs(const llvm::MDNode *node) const { - SmallVector aliasScopes; + SmallVector aliasScopes; aliasScopes.reserve(node->getNumOperands()); for (const llvm::MDOperand &operand : node->operands()) { auto *node = cast(operand.get()); - aliasScopes.push_back(aliasScopeMapping.lookup(node)); + aliasScopes.push_back( + dyn_cast_or_null(aliasScopeMapping.lookup(node))); } // Return failure if one of the alias scope lookups failed. if (llvm::is_contained(aliasScopes, nullptr)) @@ -1261,7 +1246,7 @@ return debugImporter->translate(node); } -FailureOr> +FailureOr> ModuleImport::matchAliasScopeAttrs(llvm::Value *value) { auto *nodeAsVal = cast(value); auto *node = cast(nodeAsVal->getMetadata()); diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -22,6 +22,7 @@ #include "mlir/Dialect/LLVMIR/Transforms/LegalizeForExport.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/Dialect/OpenMP/OpenMPInterfaces.h" +#include "mlir/IR/AttrTypeSubElements.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" @@ -1093,60 +1094,56 @@ } LogicalResult ModuleTranslation::createAliasScopeMetadata() { - mlirModule->walk([&](LLVM::MetadataOp metadatas) { - // Create the domains first, so they can be reference below in the scopes. - DenseMap aliasScopeDomainMetadataMapping; - metadatas.walk([&](LLVM::AliasScopeDomainMetadataOp op) { - llvm::LLVMContext &ctx = llvmModule->getContext(); - llvm::SmallVector operands; - operands.push_back({}); // Placeholder for self-reference - if (std::optional description = op.getDescription()) - operands.push_back(llvm::MDString::get(ctx, *description)); - 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(op->getParentOp())); - auto metadataOp = dyn_cast(op->getParentOp()); - Operation *domainOp = - SymbolTable::lookupNearestSymbolFrom(metadataOp, op.getDomainAttr()); - llvm::MDNode *domain = aliasScopeDomainMetadataMapping.lookup(domainOp); - assert(domain && "Scope's domain should already be valid"); - llvm::SmallVector operands; - operands.push_back({}); // Placeholder for self-reference - operands.push_back(domain); - if (std::optional description = op.getDescription()) - operands.push_back(llvm::MDString::get(ctx, *description)); - llvm::MDNode *scope = llvm::MDNode::get(ctx, operands); - scope->replaceOperandWith(0, scope); // Self-reference for uniqueness - aliasScopeMetadataMapping.insert({op, scope}); - }); + DenseMap aliasScopeDomainMetadataMapping; + + AttrTypeWalker walker; + walker.addWalk([&](LLVM::AliasScopeDomainAttr op) { + llvm::LLVMContext &ctx = llvmModule->getContext(); + llvm::SmallVector operands; + operands.push_back({}); // Placeholder for self-reference + if (StringAttr description = op.getDescription()) + operands.push_back(llvm::MDString::get(ctx, description)); + llvm::MDNode *domain = llvm::MDNode::get(ctx, operands); + domain->replaceOperandWith(0, domain); // Self-reference for uniqueness + aliasScopeDomainMetadataMapping.insert({op, domain}); }); + + walker.addWalk([&](LLVM::AliasScopeAttr op) { + llvm::LLVMContext &ctx = llvmModule->getContext(); + llvm::MDNode *domain = + aliasScopeDomainMetadataMapping.lookup(op.getDomain()); + assert(domain && "Scope's domain should already be valid"); + llvm::SmallVector operands; + operands.push_back({}); // Placeholder for self-reference + operands.push_back(domain); + if (StringAttr description = op.getDescription()) + operands.push_back(llvm::MDString::get(ctx, description)); + llvm::MDNode *scope = llvm::MDNode::get(ctx, operands); + scope->replaceOperandWith(0, scope); // Self-reference for uniqueness + aliasScopeMetadataMapping.insert({op, scope}); + }); + + mlirModule->walk([&](AliasAnalysisOpInterface op) { + if (auto aliasScopes = op.getAliasScopesOrNull()) + walker.walk(aliasScopes); + if (auto noAliasScopes = op.getNoAliasScopesOrNull()) + walker.walk(noAliasScopes); + }); + return success(); } llvm::MDNode * -ModuleTranslation::getAliasScope(Operation *op, - SymbolRefAttr aliasScopeRef) const { - StringAttr metadataName = aliasScopeRef.getRootReference(); - StringAttr scopeName = aliasScopeRef.getLeafReference(); - auto metadataOp = SymbolTable::lookupNearestSymbolFrom( - op->getParentOp(), metadataName); - Operation *aliasScopeOp = - SymbolTable::lookupNearestSymbolFrom(metadataOp, scopeName); - return aliasScopeMetadataMapping.lookup(aliasScopeOp); +ModuleTranslation::getAliasScope(AliasScopeAttr aliasScopeAttr) const { + return aliasScopeMetadataMapping.lookup(aliasScopeAttr); } llvm::MDNode *ModuleTranslation::getAliasScopes( - Operation *op, ArrayRef aliasScopeRefs) const { + ArrayRef aliasScopeAttrs) const { SmallVector nodes; - nodes.reserve(aliasScopeRefs.size()); - for (SymbolRefAttr aliasScopeRef : aliasScopeRefs) - nodes.push_back(getAliasScope(op, aliasScopeRef)); + nodes.reserve(aliasScopeAttrs.size()); + for (AliasScopeAttr aliasScopeRef : aliasScopeAttrs) + nodes.push_back(getAliasScope(aliasScopeRef)); return llvm::MDNode::get(getLLVMContext(), nodes); } @@ -1156,7 +1153,7 @@ if (!aliasScopeRefs || aliasScopeRefs.empty()) return; llvm::MDNode *node = getAliasScopes( - op, llvm::to_vector(aliasScopeRefs.getAsRange())); + llvm::to_vector(aliasScopeRefs.getAsRange())); inst->setMetadata(kind, node); }; diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -982,8 +982,7 @@ llvm.return } llvm.metadata @metadata { - llvm.alias_scope_domain @domain - llvm.alias_scope @scope { domain = @domain } + llvm.func @scope() } } @@ -991,7 +990,7 @@ module { llvm.func @aliasScope(%arg0 : !llvm.ptr, %arg1 : i32, %arg2 : i32) { - // expected-error@below {{attribute 'alias_scopes' failed to satisfy constraint: symbol ref array attribute}} + // expected-error@below {{attribute 'alias_scopes' failed to satisfy constraint: LLVM dialect alias scope array}} %0 = llvm.cmpxchg %arg0, %arg1, %arg2 acq_rel monotonic { "alias_scopes" = "test" } : !llvm.ptr, i32 llvm.return } @@ -1001,7 +1000,7 @@ module { llvm.func @noAliasScopes(%arg0 : !llvm.ptr) { - // expected-error@below {{attribute 'noalias_scopes' failed to satisfy constraint: symbol ref array attribute}} + // expected-error@below {{attribute 'noalias_scopes' failed to satisfy constraint: LLVM dialect alias scope array}} %0 = llvm.load %arg0 { "noalias_scopes" = "test" } : !llvm.ptr -> i32 llvm.return } @@ -1009,54 +1008,6 @@ // ----- -module { - llvm.func @aliasScope(%arg0 : i32, %arg1 : !llvm.ptr) { - // expected-error@below {{expected '@metadata::@group' to resolve to a llvm.alias_scope}} - llvm.store %arg0, %arg1 { "alias_scopes" = [@metadata::@group] } : i32, !llvm.ptr - llvm.return - } - llvm.metadata @metadata { - llvm.access_group @group - } -} - -// ----- - -module { - llvm.func @aliasScope(%arg0 : !llvm.ptr, %arg1 : f32) { - // expected-error@below {{expected '@metadata::@group' to resolve to a llvm.alias_scope}} - %0 = llvm.atomicrmw fadd %arg0, %arg1 monotonic { "noalias_scopes" = [@metadata::@group] } : !llvm.ptr, f32 - llvm.return - } - llvm.metadata @metadata { - llvm.access_group @group - } -} - -// ----- - -module { - llvm.metadata @metadata { - llvm.access_group @group - // expected-error@below {{expected 'group' to reference a domain operation in the same region}} - llvm.alias_scope @scope { domain = @group } - } -} - -// ----- - -module { - llvm.metadata @metadata { - // expected-error@below {{expected 'domain' to reference a domain operation in the same region}} - llvm.alias_scope @scope { domain = @domain } - } - llvm.metadata @other_metadata { - llvm.alias_scope_domain @domain - } -} - -// ----- - llvm.func @wmmaLoadOp_invalid_mem_space(%arg0: !llvm.ptr<5>, %arg1: i32) { // expected-error@+1 {{'nvvm.wmma.load' op expected source pointer in memory space 0, 1, 3}} %0 = nvvm.wmma.load %arg0, %arg1 diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -566,14 +566,12 @@ llvm.return } +#alias_scope_domain = #llvm.alias_scope_domain, description = "The domain"> +#alias_scope = #llvm.alias_scope, domain = #alias_scope_domain, description = "The domain"> + // 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 + // CHECK: llvm.intr.experimental.noalias.scope.decl #{{.*}} + llvm.intr.experimental.noalias.scope.decl #alias_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/metadata-alias-scopes.ll b/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll --- a/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll +++ b/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll @@ -1,25 +1,23 @@ ; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s -; CHECK: llvm.metadata @__llvm_global_metadata { -; CHECK: llvm.alias_scope_domain @[[DOMAIN:.*]] {description = "The domain"} -; CHECK: llvm.alias_scope @[[$SCOPE0:.*]] {description = "The first scope", domain = @[[DOMAIN]]} -; CHECK: llvm.alias_scope @[[$SCOPE1:.*]] {domain = @[[DOMAIN]]} -; CHECK: llvm.alias_scope @[[$SCOPE2:.*]] {domain = @[[DOMAIN]]} -; CHECK: } +; CHECK: #[[DOMAIN:.*]] = #llvm.alias_scope_domain +; CHECK: #[[$SCOPE0:.*]] = #llvm.alias_scope +; CHECK: #[[$SCOPE1:.*]] = #llvm.alias_scope +; CHECK: #[[$SCOPE2:.*]] = #llvm.alias_scope ; CHECK-LABEL: llvm.func @alias_scope define void @alias_scope(ptr %arg1) { ; CHECK: llvm.load - ; CHECK-SAME: alias_scopes = [@__llvm_global_metadata::@[[$SCOPE0]]] - ; CHECK-SAME: noalias_scopes = [@__llvm_global_metadata::@[[$SCOPE1]], @__llvm_global_metadata::@[[$SCOPE2]]] + ; CHECK-SAME: alias_scopes = [#[[$SCOPE0]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE1]], #[[$SCOPE2]]] %1 = load i32, ptr %arg1, !alias.scope !4, !noalias !7 ; CHECK: llvm.load - ; CHECK-SAME: alias_scopes = [@__llvm_global_metadata::@[[$SCOPE1]]] - ; CHECK-SAME: noalias_scopes = [@__llvm_global_metadata::@[[$SCOPE0]], @__llvm_global_metadata::@[[$SCOPE2]]] + ; CHECK-SAME: alias_scopes = [#[[$SCOPE1]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE0]], #[[$SCOPE2]]] %2 = load i32, ptr %arg1, !alias.scope !5, !noalias !8 ; CHECK: llvm.load - ; CHECK-SAME: alias_scopes = [@__llvm_global_metadata::@[[$SCOPE2]]] - ; CHECK-SAME: noalias_scopes = [@__llvm_global_metadata::@[[$SCOPE0]], @__llvm_global_metadata::@[[$SCOPE1]]] + ; CHECK-SAME: alias_scopes = [#[[$SCOPE2]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE0]], #[[$SCOPE1]]] %3 = load i32, ptr %arg1, !alias.scope !6, !noalias !9 ret void } @@ -37,18 +35,16 @@ ; // ----- -; CHECK: llvm.metadata @__llvm_global_metadata { -; CHECK: llvm.alias_scope_domain @[[DOMAIN0:.*]] {description = "The domain"} -; CHECK: llvm.alias_scope @[[$SCOPE0:.*]] {domain = @[[DOMAIN0]]} -; CHECK: llvm.alias_scope_domain @[[DOMAIN1:.*]] -; CHECK: llvm.alias_scope @[[$SCOPE1:.*]] {domain = @[[DOMAIN1]]} -; CHECK: } +; CHECK: #[[DOMAIN0:.*]] = #llvm.alias_scope_domain +; CHECK: #[[DOMAIN1:.*]] = #llvm.alias_scope_domain +; CHECK: #[[$SCOPE0:.*]] = #llvm.alias_scope +; CHECK: #[[$SCOPE1:.*]] = #llvm.alias_scope ; CHECK-LABEL: llvm.func @two_domains define void @two_domains(ptr %arg1) { ; CHECK: llvm.load - ; CHECK-SAME: alias_scopes = [@__llvm_global_metadata::@[[$SCOPE0]]] - ; CHECK-SAME: noalias_scopes = [@__llvm_global_metadata::@[[$SCOPE1]]] + ; CHECK-SAME: alias_scopes = [#[[$SCOPE0]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE1]]] %1 = load i32, ptr %arg1, !alias.scope !4, !noalias !5 ret void } @@ -62,30 +58,28 @@ ; // ----- -; CHECK: llvm.metadata @__llvm_global_metadata { -; CHECK: llvm.alias_scope_domain @[[DOMAIN:.*]] {description = "The domain"} -; CHECK: llvm.alias_scope @[[$SCOPE:.*]] {domain = @[[DOMAIN]]} -; CHECK: } +; CHECK: #[[DOMAIN:.*]] = #llvm.alias_scope_domain +; CHECK: #[[$SCOPE:.*]] = #llvm.alias_scope ; CHECK-LABEL: llvm.func @supported_ops define void @supported_ops(ptr %arg1, float %arg2, i32 %arg3, i32 %arg4) { - ; CHECK: llvm.intr.experimental.noalias.scope.decl @__llvm_global_metadata::@[[$SCOPE]] + ; CHECK: llvm.intr.experimental.noalias.scope.decl #[[$SCOPE]] call void @llvm.experimental.noalias.scope.decl(metadata !2) - ; CHECK: llvm.load {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]] + ; CHECK: llvm.load {{.*}}alias_scopes = [#[[$SCOPE]]] %1 = load i32, ptr %arg1, !alias.scope !2 - ; CHECK: llvm.store {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]] + ; CHECK: llvm.store {{.*}}alias_scopes = [#[[$SCOPE]]] store i32 %1, ptr %arg1, !alias.scope !2 - ; CHECK: llvm.atomicrmw {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]] + ; CHECK: llvm.atomicrmw {{.*}}alias_scopes = [#[[$SCOPE]]] %2 = atomicrmw fmax ptr %arg1, float %arg2 acquire, !alias.scope !2 - ; CHECK: llvm.cmpxchg {{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]] + ; CHECK: llvm.cmpxchg {{.*}}alias_scopes = [#[[$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]]] + ; CHECK: "llvm.intr.memcpy"{{.*}}alias_scopes = [#[[$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]]] + ; CHECK: "llvm.intr.memset"{{.*}}alias_scopes = [#[[$SCOPE]]] call void @llvm.memset.p0.i32(ptr %arg1, i8 42, i32 4, i1 false), !alias.scope !2 - ; CHECK: llvm.call{{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]] + ; CHECK: llvm.call{{.*}}alias_scopes = [#[[$SCOPE]]] call void @foo(ptr %arg1), !alias.scope !2 - ; CHECK: llvm.call{{.*}}noalias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]] + ; CHECK: llvm.call{{.*}}noalias_scopes = [#[[$SCOPE]]] call void @foo(ptr %arg1), !noalias !2 ret void } diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2080,38 +2080,36 @@ llvm.func @foo(%arg0: !llvm.ptr) +#alias_scope_domain = #llvm.alias_scope_domain, description = "The domain"> +#alias_scope1 = #llvm.alias_scope, domain = #alias_scope_domain, description = "The first scope"> +#alias_scope2 = #llvm.alias_scope, domain = #alias_scope_domain> +#alias_scope3 = #llvm.alias_scope, domain = #alias_scope_domain> + // CHECK-LABEL: aliasScope 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 + llvm.intr.experimental.noalias.scope.decl #alias_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 + llvm.store %0, %arg1 {alias_scopes = [#alias_scope1], noalias_scopes = [#alias_scope2, #alias_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 + %1 = llvm.load %arg1 {alias_scopes = [#alias_scope2], noalias_scopes = [#alias_scope1, #alias_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 + %2 = llvm.atomicrmw add %arg1, %0 monotonic {alias_scopes = [#alias_scope3], noalias_scopes = [#alias_scope1, #alias_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 + %3 = llvm.cmpxchg %arg1, %1, %2 acq_rel monotonic {alias_scopes = [#alias_scope3]} : !llvm.ptr, i32 %5 = llvm.mlir.constant(42 : i8) : i8 // CHECK: llvm.memcpy{{.*}}, !alias.scope ![[SCOPES3]] - "llvm.intr.memcpy"(%arg1, %arg1, %0) <{isVolatile = false}> {alias_scopes = [@metadata::@scope3]} : (!llvm.ptr, !llvm.ptr, i32) -> () + "llvm.intr.memcpy"(%arg1, %arg1, %0) <{isVolatile = false}> {alias_scopes = [#alias_scope3]} : (!llvm.ptr, !llvm.ptr, i32) -> () // CHECK: llvm.memset{{.*}}, !noalias ![[SCOPES3]] - "llvm.intr.memset"(%arg1, %5, %0) <{isVolatile = false}> {noalias_scopes = [@metadata::@scope3]} : (!llvm.ptr, i8, i32) -> () + "llvm.intr.memset"(%arg1, %5, %0) <{isVolatile = false}> {noalias_scopes = [#alias_scope3]} : (!llvm.ptr, i8, i32) -> () // CHECK: call void @foo({{.*}} !alias.scope ![[SCOPES3]] - llvm.call @foo(%arg1) {alias_scopes = [@metadata::@scope3]} : (!llvm.ptr) -> () + llvm.call @foo(%arg1) {alias_scopes = [#alias_scope3]} : (!llvm.ptr) -> () // CHECK: call void @foo({{.*}} !noalias ![[SCOPES3]] - llvm.call @foo(%arg1) {noalias_scopes = [@metadata::@scope3]} : (!llvm.ptr) -> () + llvm.call @foo(%arg1) {noalias_scopes = [#alias_scope3]} : (!llvm.ptr) -> () 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) diff --git a/mlir/test/mlir-tblgen/llvm-intrinsics.td b/mlir/test/mlir-tblgen/llvm-intrinsics.td --- a/mlir/test/mlir-tblgen/llvm-intrinsics.td +++ b/mlir/test/mlir-tblgen/llvm-intrinsics.td @@ -72,8 +72,8 @@ // It implements the alias analysis interface. // ALIAS: 1> // It has alias scopes, noalias, and tbaa. -// ALIAS: OptionalAttr:$alias_scopes -// ALIAS: OptionalAttr:$noalias_scopes +// ALIAS: OptionalAttr:$alias_scopes +// ALIAS: OptionalAttr:$noalias_scopes // ALIAS: OptionalAttr:$tbaa //---------------------------------------------------------------------------// diff --git a/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp --- a/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp +++ b/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp @@ -219,8 +219,9 @@ if (requiresAccessGroup) operands.push_back("OptionalAttr:$access_groups"); if (requiresAliasAnalysis) { - operands.push_back("OptionalAttr:$alias_scopes"); - operands.push_back("OptionalAttr:$noalias_scopes"); + operands.push_back("OptionalAttr:$alias_scopes"); + operands.push_back( + "OptionalAttr:$noalias_scopes"); operands.push_back("OptionalAttr:$tbaa"); }