Skip to content

Commit 78d00a1

Browse files
committed
[mlir][LLVM] Convert alias metadata to using attributes instead of ops
Using MLIR attributes instead of metadata has many advantages: * No indirection: Attributes can simply refer to each other seemlessly without having to use the indirection of `SymbolRefAttr`. This also gives us correctness by construction in a lot of places as well * Multithreading save: The Attribute infrastructure gives us thread-safety for free. Creating operations and inserting them into a block is not thread-safe. This is a major use case for e.g. the inliner in MLIR which runs in parallel * Easier to create: There is no need for a builder or a metadata region This patch therefore does exactly that. It leverages the new distinct attributes to create distinct alias domains and scopes in a deterministic and threadsafe manner. Differential Revision: https://reviews.llvm.org/D155159
1 parent afdb83b commit 78d00a1

File tree

17 files changed

+232
-306
lines changed

17 files changed

+232
-306
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,4 +562,92 @@ def LLVM_MemoryEffectsAttr : LLVM_Attr<"MemoryEffects", "memory_effects"> {
562562
let assemblyFormat = "`<` struct(params) `>`";
563563
}
564564

565+
//===----------------------------------------------------------------------===//
566+
// AliasScopeDomainAttr
567+
//===----------------------------------------------------------------------===//
568+
569+
def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain",
570+
"alias_scope_domain"> {
571+
let parameters = (ins
572+
"DistinctAttr":$id,
573+
OptionalParameter<"StringAttr">:$description
574+
);
575+
576+
let builders = [
577+
AttrBuilder<(ins CArg<"StringAttr", "{}">:$description), [{
578+
return $_get($_ctxt, DistinctAttr::create(UnitAttr::get($_ctxt)), description);
579+
}]>
580+
];
581+
582+
let summary = "LLVM dialect alias scope domain metadata";
583+
584+
let description = [{
585+
Defines a domain that may be associated with an alias scope.
586+
587+
See the following link for more details:
588+
https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
589+
}];
590+
591+
let assemblyFormat = "`<` struct(params) `>`";
592+
}
593+
594+
//===----------------------------------------------------------------------===//
595+
// AliasScopeAttr
596+
//===----------------------------------------------------------------------===//
597+
598+
def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> {
599+
let parameters = (ins
600+
"DistinctAttr":$id,
601+
"AliasScopeDomainAttr":$domain,
602+
OptionalParameter<"StringAttr">:$description
603+
);
604+
605+
let builders = [
606+
AttrBuilderWithInferredContext<(ins
607+
"AliasScopeDomainAttr":$domain,
608+
CArg<"StringAttr", "{}">:$description
609+
), [{
610+
MLIRContext *ctx = domain.getContext();
611+
return $_get(ctx, DistinctAttr::create(UnitAttr::get(ctx)), domain, description);
612+
}]>
613+
];
614+
615+
let description = [{
616+
Defines an alias scope that can be attached to a memory-accessing operation.
617+
Such scopes can be used in combination with `noalias` metadata to indicate
618+
that sets of memory-affecting operations in one scope do not alias with
619+
memory-affecting operations in another scope.
620+
621+
Example:
622+
```mlir
623+
#domain = #llvm.alias_scope_domain<id = distinct[1]<>, description = "Optional domain description">
624+
#scope1 = #llvm.alias_scope<id = distinct[2]<>, domain = #domain>
625+
#scope2 = #llvm.alias_scope<id = distinct[3]<>, domain = #domain, description = "Optional scope description">
626+
llvm.func @foo(%ptr1 : !llvm.ptr<i32>) {
627+
%c0 = llvm.mlir.constant(0 : i32) : i32
628+
%c4 = llvm.mlir.constant(4 : i32) : i32
629+
%1 = llvm.ptrtoint %ptr1 : !llvm.ptr<i32> to i32
630+
%2 = llvm.add %1, %c1 : i32
631+
%ptr2 = llvm.inttoptr %2 : i32 to !llvm.ptr<i32>
632+
llvm.store %c0, %ptr1 { alias_scopes = [#scope1], llvm.noalias = [#scope2] } : !llvm.ptr<i32>
633+
llvm.store %c4, %ptr2 { alias_scopes = [#scope2], llvm.noalias = [#scope1] } : !llvm.ptr<i32>
634+
llvm.return
635+
}
636+
```
637+
638+
See the following link for more details:
639+
https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
640+
}];
641+
642+
let summary = "LLVM dialect alias scope";
643+
644+
let assemblyFormat = "`<` struct(params) `>`";
645+
}
646+
647+
def LLVM_AliasScopeArrayAttr
648+
: TypedArrayAttrBase<LLVM_AliasScopeAttr,
649+
LLVM_AliasScopeAttr.summary # " array"> {
650+
let constBuilderCall = ?;
651+
}
652+
565653
#endif // LLVMIR_ATTRDEFS

mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,15 @@ def LLVM_MemsetOp : LLVM_ZeroResultIntrOp<"memset", [0, 2],
325325

326326
def LLVM_NoAliasScopeDeclOp
327327
: LLVM_ZeroResultIntrOp<"experimental.noalias.scope.decl"> {
328-
let arguments = (ins SymbolRefAttr:$scope);
328+
let arguments = (ins LLVM_AliasScopeAttr:$scope);
329329
string llvmBuilder = [{
330330
// Wrap the scope argument into a list since the LLVM IR intrinsic takes
331331
// a list containing exactly one scope rather than a scope itself.
332-
llvm::MDNode* node = moduleTranslation.getAliasScopes(op, {$scope});
332+
llvm::MDNode* node = moduleTranslation.getAliasScopes({$scope});
333333
builder.CreateNoAliasScopeDeclaration(node);
334334
}];
335335
string mlirBuilder = [{
336-
FailureOr<SmallVector<SymbolRefAttr>> scopeAttrs =
336+
FailureOr<SmallVector<LLVM::AliasScopeAttr>> scopeAttrs =
337337
moduleImport.matchAliasScopeAttrs(llvmOperands[0]);
338338
// Drop the intrinsic if the alias scope translation fails since the scope
339339
// is not used by an aliasing operation, such as a load or store, that is

mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ class LLVM_MemAccessOpBase<string mnemonic, list<Trait> traits = []> :
279279
DeclareOpInterfaceMethods<AliasAnalysisOpInterface>], traits)>,
280280
LLVM_MemOpPatterns {
281281
dag aliasAttrs = (ins OptionalAttr<SymbolRefArrayAttr>:$access_groups,
282-
OptionalAttr<SymbolRefArrayAttr>:$alias_scopes,
283-
OptionalAttr<SymbolRefArrayAttr>:$noalias_scopes,
282+
OptionalAttr<LLVM_AliasScopeArrayAttr>:$alias_scopes,
283+
OptionalAttr<LLVM_AliasScopeArrayAttr>:$noalias_scopes,
284284
OptionalAttr<SymbolRefArrayAttr>:$tbaa);
285285
}
286286

@@ -324,8 +324,8 @@ class LLVM_IntrOpBase<Dialect dialect, string opName, string enumName,
324324
(ins OptionalAttr<SymbolRefArrayAttr>:$access_groups),
325325
(ins )),
326326
!if(!gt(requiresAliasAnalysis, 0),
327-
(ins OptionalAttr<SymbolRefArrayAttr>:$alias_scopes,
328-
OptionalAttr<SymbolRefArrayAttr>:$noalias_scopes,
327+
(ins OptionalAttr<LLVM_AliasScopeArrayAttr>:$alias_scopes,
328+
OptionalAttr<LLVM_AliasScopeArrayAttr>:$noalias_scopes,
329329
OptionalAttr<SymbolRefArrayAttr>:$tbaa),
330330
(ins )));
331331
string resultPattern = !if(!gt(numResults, 1),

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,68 +1101,6 @@ def LLVM_MetadataOp : LLVM_Op<"metadata", [
11011101
let hasRegionVerifier = 1;
11021102
}
11031103

1104-
def LLVM_AliasScopeDomainMetadataOp : LLVM_Op<"alias_scope_domain", [
1105-
HasParent<"MetadataOp">, Symbol
1106-
]> {
1107-
let arguments = (ins
1108-
SymbolNameAttr:$sym_name,
1109-
OptionalAttr<StrAttr>:$description
1110-
);
1111-
let summary = "LLVM dialect alias.scope domain metadata.";
1112-
let description = [{
1113-
Defines a domain that may be associated with an alias scope.
1114-
1115-
See the following link for more details:
1116-
https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
1117-
}];
1118-
let assemblyFormat = "$sym_name attr-dict";
1119-
}
1120-
1121-
def LLVM_AliasScopeMetadataOp : LLVM_Op<"alias_scope", [
1122-
HasParent<"MetadataOp">, Symbol
1123-
]> {
1124-
let arguments = (ins
1125-
SymbolNameAttr:$sym_name,
1126-
FlatSymbolRefAttr:$domain,
1127-
OptionalAttr<StrAttr>:$description
1128-
);
1129-
let summary = "LLVM dialect alias.scope metadata.";
1130-
let description = [{
1131-
Defines an alias scope that can be attached to a memory-accessing operation.
1132-
Such scopes can be used in combination with `noalias` metadata to indicate
1133-
that sets of memory-affecting operations in one scope do not alias with
1134-
memory-affecting operations in another scope.
1135-
1136-
Example:
1137-
```mlir
1138-
module {
1139-
llvm.func @foo(%ptr1 : !llvm.ptr<i32>) {
1140-
%c0 = llvm.mlir.constant(0 : i32) : i32
1141-
%c4 = llvm.mlir.constant(4 : i32) : i32
1142-
%1 = llvm.ptrtoint %ptr1 : !llvm.ptr<i32> to i32
1143-
%2 = llvm.add %1, %c1 : i32
1144-
%ptr2 = llvm.inttoptr %2 : i32 to !llvm.ptr<i32>
1145-
llvm.store %c0, %ptr1 { alias_scopes = [@metadata::@scope1], llvm.noalias = [@metadata::@scope2] } : !llvm.ptr<i32>
1146-
llvm.store %c4, %ptr2 { alias_scopes = [@metadata::@scope2], llvm.noalias = [@metadata::@scope1] } : !llvm.ptr<i32>
1147-
llvm.return
1148-
}
1149-
1150-
llvm.metadata @metadata {
1151-
llvm.alias_scope_domain @unused_domain
1152-
llvm.alias_scope_domain @domain { description = "Optional domain description"}
1153-
llvm.alias_scope @scope1 { domain = @domain }
1154-
llvm.alias_scope @scope2 { domain = @domain, description = "Optional scope description" }
1155-
}
1156-
}
1157-
```
1158-
1159-
See the following link for more details:
1160-
https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
1161-
}];
1162-
let assemblyFormat = "$sym_name attr-dict";
1163-
let hasVerifier = 1;
1164-
}
1165-
11661104
def LLVM_AccessGroupMetadataOp : LLVM_Op<"access_group", [
11671105
HasParent<"MetadataOp">, Symbol
11681106
]> {

mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ class ModuleImport {
151151
/// Converts `value` to a label attribute. Asserts if the matching fails.
152152
DILabelAttr matchLabelAttr(llvm::Value *value);
153153

154-
/// Converts `value` to an array of symbol references pointing to alias scope
155-
/// operations, or returns failure if the conversion fails.
156-
FailureOr<SmallVector<SymbolRefAttr>>
154+
/// Converts `value` to an array of alias scopes or returns failure if the
155+
/// conversion fails.
156+
FailureOr<SmallVector<AliasScopeAttr>>
157157
matchAliasScopeAttrs(llvm::Value *value);
158158

159159
/// Translates the debug location.
@@ -202,10 +202,10 @@ class ModuleImport {
202202
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node,
203203
Location loc) const;
204204

205-
/// Returns the symbol references pointing to the alias scope operations that
206-
/// map to the alias scope nodes starting from the metadata `node`. Returns
207-
/// failure, if any of the symbol references cannot be found.
208-
FailureOr<SmallVector<SymbolRefAttr>>
205+
/// Returns the alias scope attributes that map to the alias scope nodes
206+
/// starting from the metadata `node`. Returns failure, if any of the
207+
/// attributes cannot be found.
208+
FailureOr<SmallVector<AliasScopeAttr>>
209209
lookupAliasScopeAttrs(const llvm::MDNode *node) const;
210210

211211
private:
@@ -349,9 +349,9 @@ class ModuleImport {
349349
/// operations for all operations that return no result. All operations that
350350
/// return a result have a valueMapping entry instead.
351351
DenseMap<llvm::Instruction *, Operation *> noResultOpMapping;
352-
/// Mapping between LLVM alias scope and domain metadata nodes and symbol
353-
/// references to the LLVM dialect operations corresponding to these nodes.
354-
DenseMap<const llvm::MDNode *, SymbolRefAttr> aliasScopeMapping;
352+
/// Mapping between LLVM alias scope and domain metadata nodes and
353+
/// attributes in the LLVM dialect corresponding to these nodes.
354+
DenseMap<const llvm::MDNode *, Attribute> aliasScopeMapping;
355355
/// Mapping between LLVM TBAA metadata nodes and symbol references to the LLVM
356356
/// dialect TBAA operations corresponding to these nodes.
357357
DenseMap<const llvm::MDNode *, SymbolRefAttr> tbaaMapping;

mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,13 @@ class ModuleTranslation {
122122
/// in these blocks.
123123
void forgetMapping(Region &region);
124124

125-
/// Returns the LLVM metadata corresponding to a symbol reference to an mlir
126-
/// LLVM dialect alias scope operation.
127-
llvm::MDNode *getAliasScope(Operation *op, SymbolRefAttr aliasScopeRef) const;
125+
/// Returns the LLVM metadata corresponding to a mlir LLVM dialect alias scope
126+
/// attribute.
127+
llvm::MDNode *getAliasScope(AliasScopeAttr aliasScopeAttr) const;
128128

129-
/// Returns the LLVM metadata corresponding to an array of symbol references
130-
/// to mlir LLVM dialect alias scope operations.
131-
llvm::MDNode *getAliasScopes(Operation *op,
132-
ArrayRef<SymbolRefAttr> aliasScopeRefs) const;
129+
/// Returns the LLVM metadata corresponding to an array of mlir LLVM dialect
130+
/// alias scope attributes.
131+
llvm::MDNode *getAliasScopes(ArrayRef<AliasScopeAttr> aliasScopeAttrs) const;
133132

134133
// Sets LLVM metadata for memory operations that are in a parallel loop.
135134
void setAccessGroupsMetadata(AccessGroupOpInterface op,
@@ -335,7 +334,7 @@ class ModuleTranslation {
335334

336335
/// Mapping from an alias scope metadata operation to its LLVM metadata.
337336
/// This map is populated on module entry.
338-
DenseMap<Operation *, llvm::MDNode *> aliasScopeMetadataMapping;
337+
DenseMap<Attribute, llvm::MDNode *> aliasScopeMetadataMapping;
339338

340339
/// Mapping from a tbaa metadata operation to its LLVM metadata.
341340
/// This map is populated on module entry.

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,21 +3084,6 @@ LogicalResult TBAATypeDescriptorOp::verify() {
30843084
return success();
30853085
}
30863086

3087-
//===----------------------------------------------------------------------===//
3088-
// AliasScopeMetadataOp
3089-
//===----------------------------------------------------------------------===//
3090-
3091-
LogicalResult AliasScopeMetadataOp::verify() {
3092-
Operation *domainOp = SymbolTable::lookupNearestSymbolFrom(
3093-
this->getOperation(), getDomainAttr());
3094-
if (!isa_and_nonnull<AliasScopeDomainMetadataOp>(domainOp)) {
3095-
return this->emitOpError()
3096-
<< "expected '" << getDomain()
3097-
<< "' to reference a domain operation in the same region";
3098-
}
3099-
return success();
3100-
}
3101-
31023087
//===----------------------------------------------------------------------===//
31033088
// OpAsmDialectInterface
31043089
//===----------------------------------------------------------------------===//
@@ -3109,8 +3094,9 @@ struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
31093094

31103095
AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
31113096
return TypeSwitch<Attribute, AliasResult>(attr)
3112-
.Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
3113-
DIDerivedTypeAttr, DIFileAttr, DILabelAttr, DILexicalBlockAttr,
3097+
.Case<AliasScopeAttr, AliasScopeDomainAttr, DIBasicTypeAttr,
3098+
DICompileUnitAttr, DICompositeTypeAttr, DIDerivedTypeAttr,
3099+
DIFileAttr, DILabelAttr, DILexicalBlockAttr,
31143100
DILexicalBlockFileAttr, DILocalVariableAttr, DINamespaceAttr,
31153101
DINullTypeAttr, DISubprogramAttr, DISubroutineTypeAttr,
31163102
LoopAnnotationAttr, LoopVectorizeAttr, LoopInterleaveAttr,

mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,6 @@ LogicalResult mlir::LLVM::detail::verifyAccessGroupOpInterface(Operation *op) {
100100
LogicalResult
101101
mlir::LLVM::detail::verifyAliasAnalysisOpInterface(Operation *op) {
102102
auto iface = cast<AliasAnalysisOpInterface>(op);
103-
if (failed(verifySymbolRefsPointTo<LLVM::AliasScopeMetadataOp>(
104-
iface, "alias scopes", iface.getAliasScopesOrNull())))
105-
return failure();
106-
if (failed(verifySymbolRefsPointTo<LLVM::AliasScopeMetadataOp>(
107-
iface, "noalias scopes", iface.getNoAliasScopesOrNull())))
108-
return failure();
109103
if (failed(verifySymbolRefsPointTo<LLVM::TBAATagOp>(
110104
iface, "tbaa tags", iface.getTBAATagsOrNull())))
111105
return failure();

mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,12 @@ static LogicalResult setLoopAttr(const llvm::MDNode *node, Operation *op,
191191
.Default([](auto) { return failure(); });
192192
}
193193

194-
/// Looks up all the symbol references pointing to the alias scope operations
195-
/// that map to the alias scope nodes starting from the alias scope metadata
196-
/// `node`, and attaches all of them to the imported operation if the lookups
197-
/// succeed. Returns failure otherwise.
194+
/// Looks up all the alias scope attributes that map to the alias scope nodes
195+
/// starting from the alias scope metadata `node`, and attaches all of them to
196+
/// the imported operation if the lookups succeed. Returns failure otherwise.
198197
static LogicalResult setAliasScopesAttr(const llvm::MDNode *node, Operation *op,
199198
LLVM::ModuleImport &moduleImport) {
200-
FailureOr<SmallVector<SymbolRefAttr>> aliasScopes =
199+
FailureOr<SmallVector<AliasScopeAttr>> aliasScopes =
201200
moduleImport.lookupAliasScopeAttrs(node);
202201
if (failed(aliasScopes))
203202
return failure();
@@ -207,8 +206,7 @@ static LogicalResult setAliasScopesAttr(const llvm::MDNode *node, Operation *op,
207206
return failure();
208207

209208
iface.setAliasScopes(ArrayAttr::get(
210-
iface.getContext(),
211-
SmallVector<Attribute>{aliasScopes->begin(), aliasScopes->end()}));
209+
iface.getContext(), llvm::to_vector_of<Attribute>(*aliasScopes)));
212210
return success();
213211
}
214212

@@ -219,7 +217,7 @@ static LogicalResult setAliasScopesAttr(const llvm::MDNode *node, Operation *op,
219217
static LogicalResult setNoaliasScopesAttr(const llvm::MDNode *node,
220218
Operation *op,
221219
LLVM::ModuleImport &moduleImport) {
222-
FailureOr<SmallVector<SymbolRefAttr>> noAliasScopes =
220+
FailureOr<SmallVector<AliasScopeAttr>> noAliasScopes =
223221
moduleImport.lookupAliasScopeAttrs(node);
224222
if (failed(noAliasScopes))
225223
return failure();
@@ -229,8 +227,7 @@ static LogicalResult setNoaliasScopesAttr(const llvm::MDNode *node,
229227
return failure();
230228

231229
iface.setNoAliasScopes(ArrayAttr::get(
232-
iface.getContext(),
233-
SmallVector<Attribute>{noAliasScopes->begin(), noAliasScopes->end()}));
230+
iface.getContext(), llvm::to_vector_of<Attribute>(*noAliasScopes)));
234231
return success();
235232
}
236233

0 commit comments

Comments
 (0)