Skip to content

Commit 563904b

Browse files
authored
[SYCL] Add aspect names to sycl_used_aspects before cleaning up (#13486)
The `sycl_aspects` metadata kept track of the aspect names and their enum values as defined by [sycl/include/sycl/info/aspects.def](https://github.com/intel/llvm/blob/sycl/sycl/include/sycl/info/aspects.def). This metadata was populated by the frontend by looking for the declaration of the SYCL aspects enum. The `CleanupSYCLMetadata` pass then deletes this metadata after device compilation. https://github.com/intel/llvm/blob/f6e73e8953e848ad87259798e9c861e9d44e93b0/clang/lib/CodeGen/BackendUtil.cpp#L1156-L1158 However, some processing in `sycl-post-link` that will be added in #12727 needs the `sycl_aspects` metadata (which at that point, the metadata is already deleted by `CleanupSYCLMetadata`). To fix this, in this PR, before cleaning up the metadata in `CleanupSYCLMetadataPass`, we update `sycl_used_aspects` metadata to include the aspect name. Note that the aspect name might not exist, e.g. in the case of the negative-valued "internal" aspects, in which case the value is passed along as normal.
1 parent 5b6cc5e commit 563904b

File tree

11 files changed

+240
-8
lines changed

11 files changed

+240
-8
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "llvm/SYCLLowerIR/ESIMD/LowerESIMD.h"
5454
#include "llvm/SYCLLowerIR/LowerWGLocalMemory.h"
5555
#include "llvm/SYCLLowerIR/MutatePrintfAddrspace.h"
56+
#include "llvm/SYCLLowerIR/RecordSYCLAspectNames.h"
5657
#include "llvm/SYCLLowerIR/SYCLAddOptLevelAttribute.h"
5758
#include "llvm/SYCLLowerIR/SYCLPropagateAspectsUsage.h"
5859
#include "llvm/SYCLLowerIR/SYCLPropagateJointMatrixUsage.h"
@@ -1153,6 +1154,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
11531154
// Process properties and annotations
11541155
MPM.addPass(CompileTimePropertiesPass());
11551156

1157+
// Record SYCL aspect names (this should come after propagating aspects
1158+
// and before cleaning up metadata)
1159+
MPM.addPass(RecordSYCLAspectNamesPass());
1160+
11561161
// Remove SYCL metadata added by the frontend, like sycl_aspects
11571162
// Note, this pass should be at the end of the pipeline
11581163
MPM.addPass(CleanupSYCLMetadataPass());
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===-------- RecordSYCLAspectNames.h - RecordSYCLAspectNames Pass --------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// The !sycl_used_aspects metadata is populated from C++ attributes and
10+
// further populated by the SYCLPropagateAspectsPass that describes which
11+
// apsects a function uses. The format of this metadata initially just an
12+
// integer value corresponding to the enum value in C++. The !sycl_aspects
13+
// named metadata contains the associations from aspect values to aspect names.
14+
// These associations are needed later in sycl-post-link, but we drop
15+
// !sycl_aspects before that to avoid LLVM IR bloat, so this pass takes
16+
// the associations from !sycl_aspects and then updates all the
17+
// !sycl_used_aspects metadata to include the aspect names, which allows us
18+
// to preserve these associations.
19+
//===----------------------------------------------------------------------===//
20+
//
21+
#ifndef LLVM_RECORD_SYCL_ASPECT_NAMES
22+
#define LLVM_RECORD_SYCL_ASPECT_NAMES
23+
24+
#include "llvm/IR/PassManager.h"
25+
26+
namespace llvm {
27+
28+
class RecordSYCLAspectNamesPass
29+
: public PassInfoMixin<RecordSYCLAspectNamesPass> {
30+
public:
31+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
32+
};
33+
34+
} // namespace llvm
35+
36+
#endif // LLVM_RECORD_SYCL_ASPECT_NAMES

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
#include "llvm/SYCLLowerIR/LowerWGLocalMemory.h"
121121
#include "llvm/SYCLLowerIR/LowerWGScope.h"
122122
#include "llvm/SYCLLowerIR/MutatePrintfAddrspace.h"
123+
#include "llvm/SYCLLowerIR/RecordSYCLAspectNames.h"
123124
#include "llvm/SYCLLowerIR/SYCLAddOptLevelAttribute.h"
124125
#include "llvm/SYCLLowerIR/SYCLPropagateAspectsUsage.h"
125126
#include "llvm/SYCLLowerIR/SYCLPropagateJointMatrixUsage.h"

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ MODULE_PASS("sycl-add-opt-level-attribute", SYCLAddOptLevelAttributePass())
160160
MODULE_PASS("compile-time-properties", CompileTimePropertiesPass())
161161
MODULE_PASS("cleanup-sycl-metadata", CleanupSYCLMetadataPass())
162162
MODULE_PASS("lower-slm-reservation-calls", ESIMDLowerSLMReservationCalls())
163+
MODULE_PASS("record-sycl-aspect-names", RecordSYCLAspectNamesPass())
163164
#undef MODULE_PASS
164165

165166
#ifndef MODULE_PASS_WITH_PARAMS

llvm/lib/SYCLLowerIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ add_llvm_component_library(LLVMSYCLLowerIR
4444
ESIMD/ESIMDRemoveOptnoneNoinline.cpp
4545
ESIMD/LowerESIMD.cpp
4646
ESIMD/LowerESIMDKernelAttrs.cpp
47+
RecordSYCLAspectNames.cpp
4748
CleanupSYCLMetadata.cpp
4849
CompileTimePropertiesPass.cpp
4950
DeviceGlobals.cpp

llvm/lib/SYCLLowerIR/ModuleSplitter.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,36 @@ class FunctionsCategorizer {
802802
Rules.emplace_back(Rule::RKind::K_SortedIntegersListMetadata, MetadataName);
803803
}
804804

805+
// Creates a rule, which adds a list of sorted dash-separated integers from
806+
// converted into strings listed in a metadata to a resulting identifier.
807+
// The form of the metadata is expected to be a metadata node, with its
808+
// operands being either an integer or another metadata node with the
809+
// form of {!"<aspect_name>", iN <aspect_value>}.
810+
void registerAspectListRule(StringRef MetadataName) {
811+
registerRule([MetadataName](Function *F) {
812+
SmallString<128> Result;
813+
if (MDNode *UsedAspects = F->getMetadata(MetadataName)) {
814+
SmallVector<std::uint64_t, 8> Values;
815+
for (const MDOperand &MDOp : UsedAspects->operands()) {
816+
if (auto MDN = dyn_cast<MDNode>(MDOp)) {
817+
assert(MDN->getNumOperands() == 2);
818+
Values.push_back(mdconst::extract<ConstantInt>(MDN->getOperand(1))
819+
->getZExtValue());
820+
} else if (auto C = mdconst::dyn_extract<ConstantInt>(MDOp)) {
821+
Values.push_back(C->getZExtValue());
822+
}
823+
}
824+
825+
llvm::sort(Values);
826+
827+
for (std::uint64_t V : Values)
828+
Result += ("-" + Twine(V)).str();
829+
}
830+
831+
return std::string(Result);
832+
});
833+
}
834+
805835
private:
806836
struct Rule {
807837
struct FlagRuleData {
@@ -980,7 +1010,7 @@ getDeviceCodeSplitter(ModuleDesc &&MD, IRSplitMode Mode, bool IROutputOnly,
9801010
// output files in existing tests.
9811011
Categorizer.registerSimpleStringAttributeRule("sycl-register-alloc-mode");
9821012
Categorizer.registerSimpleStringAttributeRule("sycl-grf-size");
983-
Categorizer.registerListOfIntegersInMetadataSortedRule("sycl_used_aspects");
1013+
Categorizer.registerAspectListRule("sycl_used_aspects");
9841014
Categorizer.registerListOfIntegersInMetadataRule("reqd_work_group_size");
9851015
Categorizer.registerListOfIntegersInMetadataRule("work_group_num_dim");
9861016
Categorizer.registerListOfIntegersInMetadataRule(
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===-------- RecordSYCLAspectNames.cpp - RecordSYCLAspectNames Pass ------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// The !sycl_used_aspects metadata is populated from C++ attributes and
10+
// further populated by the SYCLPropagateAspectsPass that describes which
11+
// apsects a function uses. The format of this metadata initially just an
12+
// integer value corresponding to the enum value in C++. The !sycl_aspects
13+
// named metadata contains the associations from aspect values to aspect names.
14+
// These associations are needed later in sycl-post-link, but we drop
15+
// !sycl_aspects before that to avoid LLVM IR bloat, so this pass takes
16+
// the associations from !sycl_aspects and then updates all the
17+
// !sycl_used_aspects metadata to include the aspect names, which allows us
18+
// to preserve these associations.
19+
//===----------------------------------------------------------------------===//
20+
//
21+
22+
#include "llvm/SYCLLowerIR/RecordSYCLAspectNames.h"
23+
24+
#include "llvm/IR/Constants.h"
25+
#include "llvm/IR/Module.h"
26+
27+
using namespace llvm;
28+
29+
PreservedAnalyses RecordSYCLAspectNamesPass::run(Module &M,
30+
ModuleAnalysisManager &MAM) {
31+
SmallDenseMap<int64_t, Metadata *, 128> ValueToNameValuePairMD;
32+
if (NamedMDNode *Node = M.getNamedMetadata("sycl_aspects")) {
33+
for (MDNode *N : Node->operands()) {
34+
assert(N->getNumOperands() == 2 &&
35+
"Each operand of sycl_aspects must be a pair.");
36+
37+
// The aspect's integral value is the second operand.
38+
auto *C = mdconst::extract<ConstantInt>(N->getOperand(1));
39+
ValueToNameValuePairMD[C->getSExtValue()] = N;
40+
}
41+
}
42+
43+
auto &Ctx = M.getContext();
44+
const char *MetadataToProcess[] = {"sycl_used_aspects",
45+
"sycl_declared_aspects"};
46+
for (Function &F : M.functions()) {
47+
for (auto MetadataName : MetadataToProcess) {
48+
auto *MDNode = F.getMetadata(MetadataName);
49+
if (!MDNode)
50+
continue;
51+
52+
// Change the metadata from {1, 2} to
53+
// a format like {{"cpu", 1}, {"gpu", 2}}
54+
SmallVector<Metadata *, 8> AspectNameValuePairs;
55+
for (const auto &MDOp : MDNode->operands()) {
56+
auto *C = mdconst::extract<ConstantInt>(MDOp);
57+
int64_t AspectValue = C->getSExtValue();
58+
if (auto It = ValueToNameValuePairMD.find(AspectValue);
59+
It != ValueToNameValuePairMD.end())
60+
AspectNameValuePairs.push_back(It->second);
61+
else
62+
AspectNameValuePairs.push_back(MDOp);
63+
}
64+
65+
F.setMetadata(MetadataName, MDNode::get(Ctx, AspectNameValuePairs));
66+
}
67+
}
68+
69+
return PreservedAnalyses::all();
70+
}

llvm/lib/SYCLLowerIR/SYCLDeviceRequirements.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "llvm/ADT/SmallString.h"
1212
#include "llvm/ADT/StringRef.h"
13+
#include "llvm/IR/Constants.h"
1314
#include "llvm/IR/Module.h"
1415
#include "llvm/SYCLLowerIR/ModuleSplitter.h"
1516
#include "llvm/Support/PropertySetIO.h"
@@ -42,8 +43,15 @@ llvm::computeDeviceRequirements(const module_split::ModuleDesc &MD) {
4243
// Process all functions in the module
4344
for (const Function &F : MD.getModule()) {
4445
if (auto *MDN = F.getMetadata("sycl_used_aspects")) {
45-
for (size_t I = 0, E = MDN->getNumOperands(); I < E; ++I) {
46-
auto Val = ExtractSignedIntegerFromMDNodeOperand(MDN, I);
46+
for (auto &MDOp : MDN->operands()) {
47+
int64_t Val;
48+
if (auto Pair = dyn_cast<MDNode>(MDOp)) {
49+
assert(Pair->getNumOperands() == 2);
50+
Val = mdconst::extract<ConstantInt>(Pair->getOperand(1))
51+
->getZExtValue();
52+
} else {
53+
Val = mdconst::extract<ConstantInt>(MDOp)->getZExtValue();
54+
}
4755
// Don't put internal aspects (with negative integer value) into the
4856
// requirements, they are used only for device image splitting.
4957
if (Val >= 0)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
; RUN: opt -passes=record-sycl-aspect-names -S < %s | FileCheck %s
2+
;
3+
; Basic add-aspect-names functionality test. Checks that
4+
; the !sycl_used_apsects metadata is updated from just being
5+
; integer values to aspect value/name pairs as determined
6+
; by !sycl_aspects.
7+
8+
; e.g. !sycl_used_aspects = !{i32 1, i32 0}
9+
; => !sycl_used_aspects = !{!{!"B", i32 1}, !{!"A", i32 0}}
10+
11+
; Additionally checks that when there is no association
12+
; for a given aspect value, that metadata remains unchanged.
13+
14+
; e.g. !sycl_used_aspects = !{i32 4, i32 0}
15+
; => !sycl_used_aspects = !{i32 4, !{!"A", i32 0}}
16+
17+
%A = type { i32 }
18+
%B = type { i32 }
19+
%C = type { i32 }
20+
%D = type { i32 }
21+
22+
; CHECK: funcA() !sycl_used_aspects ![[fA:[0-9]+]]
23+
define spir_func void @funcA() !sycl_used_aspects !5 {
24+
%tmp = alloca %A, align 8
25+
ret void
26+
}
27+
28+
; CHECK: funcB() !sycl_used_aspects ![[fB:[0-9]+]]
29+
define spir_func void @funcB() !sycl_used_aspects !6 {
30+
%tmp = alloca %B, align 8
31+
call spir_func void @funcA()
32+
ret void
33+
}
34+
35+
; CHECK: funcC() !sycl_used_aspects ![[fC:[0-9]+]]
36+
define spir_func void @funcC() !sycl_used_aspects !7 {
37+
%tmp = alloca %C, align 8
38+
call spir_func void @funcB()
39+
ret void
40+
}
41+
42+
; CHECK: funcD() !sycl_used_aspects ![[fD:[0-9]+]]
43+
define spir_func void @funcD() !sycl_used_aspects !8 {
44+
%tmp = alloca %D, align 8
45+
call spir_func void @funcC()
46+
ret void
47+
}
48+
49+
define spir_kernel void @kernel() !sycl_used_aspects !8 !sycl_fixed_targets !9 {
50+
call spir_func void @funcD()
51+
ret void
52+
}
53+
54+
!sycl_types_that_use_aspects = !{!0, !1, !2, !3}
55+
!sycl_aspects = !{!0, !1, !2, !3, !4}
56+
57+
; CHECK-DAG: ![[mA:[0-9]+]] = !{!"A", i32 0}
58+
; CHECK-DAG: ![[mB:[0-9]+]] = !{!"B", i32 1}
59+
; CHECK-DAG: ![[mC:[0-9]+]] = !{!"C", i32 2}
60+
; CHECK-DAG: ![[mD:[0-9]+]] = !{!"D", i32 3}
61+
; CHECK-DAG: ![[fA]] = !{![[mA]]}
62+
; CHECK-DAG: ![[fB]] = !{![[mB]], ![[mA]]}
63+
; CHECK-DAG: ![[fC]] = !{![[mC]], ![[mB]], ![[mA]]}
64+
; CHECK-DAG: ![[fD]] = !{![[mA]], ![[mB]], ![[mC]], ![[mD]], i32 4}
65+
66+
!0 = !{!"A", i32 0}
67+
!1 = !{!"B", i32 1}
68+
!2 = !{!"C", i32 2}
69+
!3 = !{!"D", i32 3}
70+
!4 = !{!"fp64", i32 6}
71+
!5 = !{i32 0}
72+
!6 = !{i32 1, i32 0}
73+
!7 = !{i32 2, i32 1, i32 0}
74+
!8 = !{i32 0, i32 1, i32 2, i32 3, i32 4}
75+
!9 = !{}

sycl/test/check_device_code/device_has.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,20 @@ void foo() {
6868
});
6969
}
7070

71-
// CHECK-ASPECTS-DAG: [[ASPECTS1]] = !{i32 1}
71+
// CHECK-ASPECTS-DAG: [[ASPECTS1]] = !{![[ASPECTCPU:[0-9]+]]}
72+
// CHECK-ASPECTS-DAG: [[ASPECTCPU]] = !{!"cpu", i32 1}
7273
// CHECK-SRCLOC-DAG: [[SRCLOC1]] = !{i32 {{[0-9]+}}}
7374
// CHECK-ASPECTS-DAG: [[EMPTYASPECTS]] = !{}
7475
// CHECK-SRCLOC-DAG: [[SRCLOC2]] = !{i32 {{[0-9]+}}}
75-
// CHECK-ASPECTS-DAG: [[ASPECTS2]] = !{i32 5, i32 2}
76+
// CHECK-ASPECTS-DAG: [[ASPECTS2]] = !{![[ASPECTFP16:[0-9]+]], ![[ASPECTGPU:[0-9]+]]}
77+
// CHECK-ASPECTS-DAG: [[ASPECTFP16]] = !{!"fp16", i32 5}
78+
// CHECK-ASPECTS-DAG: [[ASPECTGPU]] = !{!"gpu", i32 2}
7679
// CHECK-SRCLOC-DAG: [[SRCLOC3]] = !{i32 {{[0-9]+}}}
7780
// CHECK-SRCLOC-DAG: [[SRCLOC4]] = !{i32 {{[0-9]+}}}
78-
// CHECK-ASPECTS-DAG: [[ASPECTS3]] = !{i32 0}
81+
// CHECK-ASPECTS-DAG: [[ASPECTS3]] = !{![[ASPECTHOST:[0-9]+]]}
82+
// CHECK-ASPECTS-DAG: [[ASPECTHOST]] = !{!"host", i32 0}
7983
// CHECK-SRCLOC-DAG: [[SRCLOC5]] = !{i32 {{[0-9]+}}}
8084
// CHECK-SRCLOC-DAG: [[SRCLOC6]] = !{i32 {{[0-9]+}}}
8185
// CHECK-SRCLOC-DAG: [[SRCLOC7]] = !{i32 {{[0-9]+}}}
82-
// CHECK-ASPECTS-DAG: [[ASPECTS4]] = !{i32 2}
86+
// CHECK-ASPECTS-DAG: [[ASPECTS4]] = !{![[ASPECTGPU]]}
8387
// CHECK-SRCLOC-DAG: [[SRCLOC8]] = !{i32 {{[0-9]+}}}

0 commit comments

Comments
 (0)