Skip to content

Commit 023dbba

Browse files
committed
[MLIR] Enable import of non self referential alias scopes
1 parent 6192faf commit 023dbba

File tree

6 files changed

+143
-12
lines changed

6 files changed

+143
-12
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ def LLVM_MemoryEffectsAttr : LLVM_Attr<"MemoryEffects", "memory_effects"> {
825825
def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain",
826826
"alias_scope_domain"> {
827827
let parameters = (ins
828-
"DistinctAttr":$id,
828+
"Attribute":$id,
829829
OptionalParameter<"StringAttr">:$description
830830
);
831831

@@ -853,7 +853,7 @@ def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain",
853853

854854
def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> {
855855
let parameters = (ins
856-
"DistinctAttr":$id,
856+
"Attribute":$id,
857857
"AliasScopeDomainAttr":$domain,
858858
OptionalParameter<"StringAttr">:$description
859859
);
@@ -891,6 +891,8 @@ def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> {
891891
}
892892
```
893893

894+
The first attribute can either be a DistinctAttribute or a StringAttribute.
895+
894896
See the following link for more details:
895897
https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
896898
}];

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,11 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
427427
return node->getNumOperands() != 0 &&
428428
node == dyn_cast<llvm::MDNode>(node->getOperand(0));
429429
};
430+
auto verifySelfRefOrString = [](const llvm::MDNode *node) {
431+
return node->getNumOperands() != 0 &&
432+
(node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
433+
isa<llvm::MDString>(node->getOperand(0)));
434+
};
430435
// Helper that verifies the given operand is a string or does not exist.
431436
auto verifyDescription = [](const llvm::MDNode *node, unsigned idx) {
432437
return idx >= node->getNumOperands() ||
@@ -438,8 +443,14 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
438443
if (aliasDomain->getNumOperands() >= 2)
439444
if (auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
440445
description = builder.getStringAttr(operand->getString());
441-
return builder.getAttr<AliasScopeDomainAttr>(
442-
DistinctAttr::create(builder.getUnitAttr()), description);
446+
Attribute idAttr;
447+
if (verifySelfRef(aliasDomain)) {
448+
idAttr = DistinctAttr::create(builder.getUnitAttr());
449+
} else {
450+
auto name = cast<llvm::MDString>(aliasDomain->getOperand(0));
451+
idAttr = builder.getStringAttr(name->getString());
452+
}
453+
return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
443454
};
444455

445456
// Collect the alias scopes and domains to translate them.
@@ -452,10 +463,11 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
452463
// verifying its domain. Perform the verification before looking it up in
453464
// the alias scope mapping since it could have been inserted as a domain
454465
// node before.
455-
if (!verifySelfRef(scope) || !domain || !verifyDescription(scope, 2))
466+
if (!verifySelfRefOrString(scope) || !domain ||
467+
!verifyDescription(scope, 2))
456468
return emitError(loc) << "unsupported alias scope node: "
457469
<< diagMD(scope, llvmModule.get());
458-
if (!verifySelfRef(domain) || !verifyDescription(domain, 1))
470+
if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
459471
return emitError(loc) << "unsupported alias domain node: "
460472
<< diagMD(domain, llvmModule.get());
461473

@@ -473,9 +485,17 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
473485
StringAttr description = nullptr;
474486
if (!aliasScope.getName().empty())
475487
description = builder.getStringAttr(aliasScope.getName());
488+
Attribute idAttr;
489+
if (verifySelfRef(scope)) {
490+
idAttr = DistinctAttr::create(builder.getUnitAttr());
491+
} else {
492+
auto Name = cast<llvm::MDString>(scope->getOperand(0));
493+
idAttr = builder.getStringAttr(Name->getString());
494+
}
495+
476496
auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
477-
DistinctAttr::create(builder.getUnitAttr()),
478-
cast<AliasScopeDomainAttr>(it->second), description);
497+
idAttr, cast<AliasScopeDomainAttr>(it->second), description);
498+
479499
aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
480500
}
481501
}

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,25 +1724,38 @@ ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
17241724
aliasScopeAttr.getDomain(), nullptr);
17251725
if (insertedDomain) {
17261726
llvm::SmallVector<llvm::Metadata *, 2> operands;
1727-
// Placeholder for self-reference.
1727+
// Placeholder for potential self-reference.
17281728
operands.push_back(dummy.get());
17291729
if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
17301730
operands.push_back(llvm::MDString::get(ctx, description));
17311731
domainIt->second = llvm::MDNode::get(ctx, operands);
17321732
// Self-reference for uniqueness.
1733-
domainIt->second->replaceOperandWith(0, domainIt->second);
1733+
llvm::Metadata *replacement;
1734+
if (auto stringAttr =
1735+
dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId())) {
1736+
replacement = llvm::MDString::get(ctx, stringAttr.getValue());
1737+
} else {
1738+
replacement = domainIt->second;
1739+
}
1740+
domainIt->second->replaceOperandWith(0, replacement);
17341741
}
17351742
// Convert the scope metadata node.
17361743
assert(domainIt->second && "Scope's domain should already be valid");
17371744
llvm::SmallVector<llvm::Metadata *, 3> operands;
1738-
// Placeholder for self-reference.
1745+
// Placeholder for potential self-reference.
17391746
operands.push_back(dummy.get());
17401747
operands.push_back(domainIt->second);
17411748
if (StringAttr description = aliasScopeAttr.getDescription())
17421749
operands.push_back(llvm::MDString::get(ctx, description));
17431750
scopeIt->second = llvm::MDNode::get(ctx, operands);
17441751
// Self-reference for uniqueness.
1745-
scopeIt->second->replaceOperandWith(0, scopeIt->second);
1752+
llvm::Metadata *replacement;
1753+
if (auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId())) {
1754+
replacement = llvm::MDString::get(ctx, stringAttr.getValue());
1755+
} else {
1756+
replacement = scopeIt->second;
1757+
}
1758+
scopeIt->second->replaceOperandWith(0, replacement);
17461759
return scopeIt->second;
17471760
}
17481761

mlir/test/Dialect/LLVMIR/roundtrip.mlir

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,16 @@ llvm.func @experimental_noalias_scope_decl() {
750750
llvm.return
751751
}
752752

753+
#alias_scope_domain2 = #llvm.alias_scope_domain<id = "domainid", description = "The domain">
754+
#alias_scope2 = #llvm.alias_scope<id = "stringid", domain = #alias_scope_domain2, description = "The domain">
755+
756+
// CHECK-LABEL: @experimental_noalias_scope_decl
757+
llvm.func @experimental_noalias_scope_decl2() {
758+
// CHECK: llvm.intr.experimental.noalias.scope.decl #{{.*}}
759+
llvm.intr.experimental.noalias.scope.decl #alias_scope2
760+
llvm.return
761+
}
762+
753763
// CHECK-LABEL: @experimental_constrained_fptrunc
754764
llvm.func @experimental_constrained_fptrunc(%in: f64) {
755765
// CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} towardzero ignore : f64 to f32

mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,38 @@ declare void @foo(ptr %arg1)
9292
!0 = distinct !{!0, !"The domain"}
9393
!1 = !{!1, !0}
9494
!2 = !{!1}
95+
96+
; // -----
97+
98+
; CHECK: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<id = "domain1">
99+
; CHECK: #[[$SCOPE0:.*]] = #llvm.alias_scope<id = "scopeid1", domain = #[[DOMAIN]], description = "The first scope">
100+
; CHECK: #[[$SCOPE1:.*]] = #llvm.alias_scope<id = "scopeid2", domain = #[[DOMAIN]]>
101+
; CHECK: #[[$SCOPE2:.*]] = #llvm.alias_scope<id = "scopeid3", domain = #[[DOMAIN]]>
102+
103+
; CHECK-LABEL: llvm.func @alias_scope
104+
define void @alias_scope(ptr %arg1) {
105+
; CHECK: llvm.load
106+
; CHECK-SAME: alias_scopes = [#[[$SCOPE0]]]
107+
; CHECK-SAME: noalias_scopes = [#[[$SCOPE1]], #[[$SCOPE2]]]
108+
%1 = load i32, ptr %arg1, !alias.scope !4, !noalias !7
109+
; CHECK: llvm.load
110+
; CHECK-SAME: alias_scopes = [#[[$SCOPE1]]]
111+
; CHECK-SAME: noalias_scopes = [#[[$SCOPE0]], #[[$SCOPE2]]]
112+
%2 = load i32, ptr %arg1, !alias.scope !5, !noalias !8
113+
; CHECK: llvm.load
114+
; CHECK-SAME: alias_scopes = [#[[$SCOPE2]]]
115+
; CHECK-SAME: noalias_scopes = [#[[$SCOPE0]], #[[$SCOPE1]]]
116+
%3 = load i32, ptr %arg1, !alias.scope !6, !noalias !9
117+
ret void
118+
}
119+
120+
!0 = !{!"domain1"}
121+
!1 = !{!"scopeid1", !0, !"The first scope"}
122+
!2 = !{!"scopeid2", !0}
123+
!3 = !{!"scopeid3", !0}
124+
!4 = !{!1}
125+
!5 = !{!2}
126+
!6 = !{!3}
127+
!7 = !{!2, !3}
128+
!8 = !{!1, !3}
129+
!9 = !{!1, !2}

mlir/test/Target/LLVMIR/attribute-alias-scopes.mlir

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,54 @@ llvm.func @self_reference() {
104104
// CHECK-DAG: ![[SCOPES]] = !{![[SCOPE]]}
105105
// CHECK-DAG: = !DISubroutineType(types: ![[TYPES:[0-9]+]])
106106
// CHECK-DAG: ![[TYPES]] = !{null}
107+
108+
// -----
109+
110+
llvm.func @foo(%arg0: !llvm.ptr)
111+
112+
#alias_scope_domain = #llvm.alias_scope_domain<id = "domain1", description = "The domain">
113+
#alias_scope1 = #llvm.alias_scope<id = "scope1", domain = #alias_scope_domain, description = "The first scope">
114+
#alias_scope2 = #llvm.alias_scope<id = "scope2", domain = #alias_scope_domain>
115+
#alias_scope3 = #llvm.alias_scope<id = "scope3", domain = #alias_scope_domain>
116+
117+
// CHECK-LABEL: @alias_scopes
118+
llvm.func @alias_scopes(%arg1 : !llvm.ptr) {
119+
%0 = llvm.mlir.constant(0 : i32) : i32
120+
// CHECK: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPES1:[0-9]+]])
121+
llvm.intr.experimental.noalias.scope.decl #alias_scope1
122+
// CHECK: store {{.*}}, !alias.scope ![[SCOPES1]], !noalias ![[SCOPES23:[0-9]+]]
123+
llvm.store %0, %arg1 {alias_scopes = [#alias_scope1], noalias_scopes = [#alias_scope2, #alias_scope3]} : i32, !llvm.ptr
124+
// CHECK: load {{.*}}, !alias.scope ![[SCOPES2:[0-9]+]], !noalias ![[SCOPES13:[0-9]+]]
125+
%1 = llvm.load %arg1 {alias_scopes = [#alias_scope2], noalias_scopes = [#alias_scope1, #alias_scope3]} : !llvm.ptr -> i32
126+
// CHECK: atomicrmw {{.*}}, !alias.scope ![[SCOPES3:[0-9]+]], !noalias ![[SCOPES12:[0-9]+]]
127+
%2 = llvm.atomicrmw add %arg1, %0 monotonic {alias_scopes = [#alias_scope3], noalias_scopes = [#alias_scope1, #alias_scope2]} : !llvm.ptr, i32
128+
// CHECK: cmpxchg {{.*}}, !alias.scope ![[SCOPES3]]
129+
%3 = llvm.cmpxchg %arg1, %1, %2 acq_rel monotonic {alias_scopes = [#alias_scope3]} : !llvm.ptr, i32
130+
%5 = llvm.mlir.constant(42 : i8) : i8
131+
// CHECK: llvm.memcpy{{.*}}, !alias.scope ![[SCOPES3]]
132+
"llvm.intr.memcpy"(%arg1, %arg1, %0) <{isVolatile = false}> {alias_scopes = [#alias_scope3]} : (!llvm.ptr, !llvm.ptr, i32) -> ()
133+
// CHECK: llvm.memset{{.*}}, !noalias ![[SCOPES3]]
134+
"llvm.intr.memset"(%arg1, %5, %0) <{isVolatile = false}> {noalias_scopes = [#alias_scope3]} : (!llvm.ptr, i8, i32) -> ()
135+
// CHECK: call void @foo({{.*}} !alias.scope ![[SCOPES3]]
136+
llvm.call @foo(%arg1) {alias_scopes = [#alias_scope3]} : (!llvm.ptr) -> ()
137+
// CHECK: call void @foo({{.*}} !noalias ![[SCOPES3]]
138+
llvm.call @foo(%arg1) {noalias_scopes = [#alias_scope3]} : (!llvm.ptr) -> ()
139+
llvm.return
140+
}
141+
142+
// Check the intrinsic declarations.
143+
// CHECK-DAG: declare void @llvm.experimental.noalias.scope.decl(metadata)
144+
// CHECK-DAG: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
145+
// CHECK-DAG: declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
146+
147+
// Check the translated metadata.
148+
// CHECK-DAG: ![[DOMAIN:[0-9]+]] = !{!"domain1", !"The domain"}
149+
// CHECK-DAG: ![[SCOPE1:[0-9]+]] = !{!"scope1", ![[DOMAIN]], !"The first scope"}
150+
// CHECK-DAG: ![[SCOPE2:[0-9]+]] = !{!"scope2", ![[DOMAIN]]}
151+
// CHECK-DAG: ![[SCOPE3:[0-9]+]] = !{!"scope3", ![[DOMAIN]]}
152+
// CHECK-DAG: ![[SCOPES1]] = !{![[SCOPE1]]}
153+
// CHECK-DAG: ![[SCOPES2]] = !{![[SCOPE2]]}
154+
// CHECK-DAG: ![[SCOPES3]] = !{![[SCOPE3]]}
155+
// CHECK-DAG: ![[SCOPES12]] = !{![[SCOPE1]], ![[SCOPE2]]}
156+
// CHECK-DAG: ![[SCOPES13]] = !{![[SCOPE1]], ![[SCOPE3]]}
157+
// CHECK-DAG: ![[SCOPES23]] = !{![[SCOPE2]], ![[SCOPE3]]}

0 commit comments

Comments
 (0)