Skip to content

Commit e39e30e

Browse files
authored
[mlir][llvm] Fix access group translation (#83257)
This commit fixes the translation of access group metadata to LLVM IR. Previously, it did not use a temporary metadata node to model the placeholder of the self-referencing access group nodes. This is dangerous since, the translation may produce a metadata list with a null entry that is later on changed changed with a self reference. At the same time, for example the debug info translation may create the same uniqued node, which after setting the self-reference the suddenly references the access group metadata. The commit avoids such breakages.
1 parent 06f775a commit e39e30e

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,13 +1512,14 @@ ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
15121512
if (!scopeInserted)
15131513
return scopeIt->second;
15141514
llvm::LLVMContext &ctx = llvmModule->getContext();
1515+
auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
15151516
// Convert the domain metadata node if necessary.
15161517
auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
15171518
aliasScopeAttr.getDomain(), nullptr);
15181519
if (insertedDomain) {
15191520
llvm::SmallVector<llvm::Metadata *, 2> operands;
15201521
// Placeholder for self-reference.
1521-
operands.push_back({});
1522+
operands.push_back(dummy.get());
15221523
if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
15231524
operands.push_back(llvm::MDString::get(ctx, description));
15241525
domainIt->second = llvm::MDNode::get(ctx, operands);
@@ -1529,7 +1530,7 @@ ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) {
15291530
assert(domainIt->second && "Scope's domain should already be valid");
15301531
llvm::SmallVector<llvm::Metadata *, 3> operands;
15311532
// Placeholder for self-reference.
1532-
operands.push_back({});
1533+
operands.push_back(dummy.get());
15331534
operands.push_back(domainIt->second);
15341535
if (StringAttr description = aliasScopeAttr.getDescription())
15351536
operands.push_back(llvm::MDString::get(ctx, description));

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

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,48 @@ llvm.func @alias_scopes(%arg1 : !llvm.ptr) {
5959
#alias_scope1 = #llvm.alias_scope<id = distinct[1]<>, domain = #alias_scope_domain>
6060

6161
// CHECK-LABEL: @noalias_intr_only
62-
llvm.func @noalias_intr_only(%arg1 : !llvm.ptr) {
63-
%0 = llvm.mlir.constant(0 : i32) : i32
64-
// CHECK: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPES1:[0-9]+]])
62+
llvm.func @noalias_intr_only() {
63+
// CHECK: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPES:[0-9]+]])
6564
llvm.intr.experimental.noalias.scope.decl #alias_scope1
6665
llvm.return
6766
}
6867

6968
// Check the translated metadata.
7069
// CHECK-DAG: ![[DOMAIN:[0-9]+]] = distinct !{![[DOMAIN]], !"The domain"}
71-
// CHECK-DAG: ![[SCOPE1:[0-9]+]] = distinct !{![[SCOPE1]], ![[DOMAIN]]}
72-
// CHECK-DAG: ![[SCOPES1]] = !{![[SCOPE1]]}
70+
// CHECK-DAG: ![[SCOPE:[0-9]+]] = distinct !{![[SCOPE]], ![[DOMAIN]]}
71+
// CHECK-DAG: ![[SCOPES]] = !{![[SCOPE]]}
72+
73+
// -----
74+
75+
// This test ensures the alias scope translation creates a temporary metadata
76+
// node as a placeholder for self-references. Without this, the debug info
77+
// translation of a type list with a null entry could inadvertently reference
78+
// access group metadata. This occurs when both translations generate a metadata
79+
// list with a null entry, which are then uniqued to the same metadata node.
80+
// The access group translation subsequently updates the null entry to a
81+
// self-reference, which causes the type list to reference the access
82+
// group node as well. The use of a temporary placeholder node avoids the issue.
83+
84+
#alias_scope_domain = #llvm.alias_scope_domain<id = distinct[0]<>>
85+
#alias_scope = #llvm.alias_scope<id = distinct[1]<>, domain = #alias_scope_domain>
86+
87+
#di_null_type = #llvm.di_null_type
88+
#di_subroutine_type = #llvm.di_subroutine_type<types = #di_null_type>
89+
#di_file = #llvm.di_file<"attribute-alias-scope.mlir" in "">
90+
#di_compile_unit = #llvm.di_compile_unit<id = distinct[3]<>, sourceLanguage = DW_LANG_C11, file = #di_file, isOptimized = true, emissionKind = Full>
91+
#di_subprogram = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #di_compile_unit, scope = #di_file, file = #di_file, subprogramFlags = "Definition", type = #di_subroutine_type>
92+
93+
// CHECK-LABEL: @self_reference
94+
llvm.func @self_reference() {
95+
// CHECK: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPES:[0-9]+]])
96+
llvm.intr.experimental.noalias.scope.decl #alias_scope
97+
llvm.return
98+
} loc(fused<#di_subprogram>[unknown])
99+
100+
// Check that the translated subroutine types do not reference the access group
101+
// domain since both of them are created as metadata list with a null entry.
102+
// CHECK-DAG: ![[DOMAIN:[0-9]+]] = distinct !{![[DOMAIN]]}
103+
// CHECK-DAG: ![[SCOPE:[0-9]+]] = distinct !{![[SCOPE]], ![[DOMAIN]]}
104+
// CHECK-DAG: ![[SCOPES]] = !{![[SCOPE]]}
105+
// CHECK-DAG: = !DISubroutineType(types: ![[TYPES:[0-9]+]])
106+
// CHECK-DAG: ![[TYPES]] = !{null}

0 commit comments

Comments
 (0)