Skip to content

Commit 5cd2c2a

Browse files
authored
[SYCLLowerIR] Fix metadata format for Intel cache controls (#20753)
This patch aligns metadata with the format defined in the commit message for KhronosGroup/SPIRV-LLVM-Translator@c8bfc33. Unfortunately, the format is still not documented in https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst. This patch fixes the crash in the translator tool, which tries to handle wrong metadata format. I manually checked that the translator successfully converts properties_cache_control.cpp test to SPIR-V format with CacheControl decorations.
1 parent a848782 commit 5cd2c2a

File tree

2 files changed

+82
-71
lines changed

2 files changed

+82
-71
lines changed

llvm/lib/SYCLLowerIR/CompileTimePropertiesPass.cpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ constexpr StringRef SyclRegisterAllocModeAttr = "sycl-register-alloc-mode";
3333
constexpr StringRef SyclGrfSizeAttr = "sycl-grf-size";
3434

3535
constexpr StringRef SpirvDecorMdKind = "spirv.Decorations";
36+
constexpr StringRef SpirvDecorCacheControlMdKind =
37+
"spirv.DecorationCacheControlINTEL";
3638
constexpr StringRef SpirvParamDecorMdKind = "spirv.ParameterDecorations";
3739
// The corresponding SPIR-V OpCode for the host_access property is documented
3840
// in the SPV_INTEL_global_variable_decorations design document:
@@ -128,21 +130,7 @@ MDNode *buildSpirvDecorMetadata(LLVMContext &Ctx, uint32_t OpCode,
128130
return MDNode::get(Ctx, MD);
129131
}
130132

131-
/// Builds a metadata node for a SPIR-V decoration for cache controls
132-
/// where decoration code and value are both uint32_t integers.
133-
/// The value encodes a cache level and a cache control type.
134-
///
135-
/// @param Ctx [in] the LLVM Context.
136-
/// @param Name [in] the SPIR-V property string name.
137-
/// @param OpCode [in] the SPIR-V opcode.
138-
/// @param CacheMode [in] whether read or write.
139-
/// @param CacheLevel [in] the cache level.
140-
///
141-
/// @returns a pointer to the metadata node created for the required decoration
142-
/// and its values.
143-
MDNode *buildSpirvDecorCacheProp(LLVMContext &Ctx, StringRef Name,
144-
uint32_t OpCode, uint32_t CacheMode,
145-
uint32_t CacheLevel) {
133+
static uint32_t getCacheProperty(StringRef Name, uint32_t CacheMode) {
146134
// SPIR-V encodings of read control
147135
enum CacheControlReadType {
148136
read_uncached = 0,
@@ -177,12 +165,25 @@ MDNode *buildSpirvDecorCacheProp(LLVMContext &Ctx, StringRef Name,
177165
write_uncached, write_through, write_back};
178166

179167
// Map SYCL encoding to SPIR-V
180-
uint32_t CacheProp;
181168
if (Name.starts_with("sycl-cache-read"))
182-
CacheProp = SPIRVReadControl[CacheMode];
183-
else
184-
CacheProp = SPIRVWriteControl[CacheMode];
169+
return SPIRVReadControl[CacheMode];
170+
171+
return SPIRVWriteControl[CacheMode];
172+
}
185173

174+
/// Builds a metadata node for a SPIR-V decoration for cache controls.
175+
///
176+
/// @param Ctx [in] the LLVM Context.
177+
/// @param OpCode [in] the SPIR-V opcode.
178+
/// @param CacheLevel [in] the cache level.
179+
/// @param CacheProp [in] the cache property.
180+
/// @param OperandNum [in] the operand number to decorate.
181+
///
182+
/// @returns a pointer to the metadata node created for the required decoration
183+
/// and its values.
184+
MDNode *buildSpirvDecorCacheProp(LLVMContext &Ctx, uint32_t OpCode,
185+
uint32_t CacheLevel, uint32_t CacheProp,
186+
uint32_t OperandNum) {
186187
auto *Ty = Type::getInt32Ty(Ctx);
187188
SmallVector<Metadata *, 3> MD;
188189
MD.push_back(ConstantAsMetadata::get(
@@ -191,6 +192,8 @@ MDNode *buildSpirvDecorCacheProp(LLVMContext &Ctx, StringRef Name,
191192
Constant::getIntegerValue(Ty, APInt(32, CacheLevel))));
192193
MD.push_back(ConstantAsMetadata::get(
193194
Constant::getIntegerValue(Ty, APInt(32, CacheProp))));
195+
MD.push_back(ConstantAsMetadata::get(
196+
Constant::getIntegerValue(Ty, APInt(32, OperandNum))));
194197
return MDNode::get(Ctx, MD);
195198
}
196199

@@ -831,7 +834,7 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
831834
// Read the annotation values and create new annotation strings.
832835
std::string NewAnnotString = "";
833836
auto Properties = parseSYCLPropertiesString(M, IntrInst);
834-
SmallVector<Metadata *, 8> MDOpsCacheProp;
837+
SmallVector<std::array<uint32_t, 3>, 8> MDOpsCacheProp;
835838
bool CacheProp = false;
836839
bool FPGAProp = false;
837840
for (const auto &[PropName, PropVal] : Properties) {
@@ -856,7 +859,6 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
856859
// !CC1 = !{i32 Load/Store, i32 Level, i32 Control}
857860
// !CC2 = !{i32 Load/Store, i32 Level, i32 Control}
858861
// ...
859-
LLVMContext &Ctx = M.getContext();
860862
uint32_t CacheMode = 0;
861863
while (AttrVal) {
862864
// The attribute value encodes cache control and levels.
@@ -869,8 +871,8 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
869871
uint32_t LevelMask = AttrVal & 0xf;
870872
while (LevelMask) {
871873
if (LevelMask & 1)
872-
MDOpsCacheProp.push_back(buildSpirvDecorCacheProp(
873-
Ctx, *PropName, DecorCode, CacheMode, CacheLevel));
874+
MDOpsCacheProp.push_back({DecorCode, CacheLevel,
875+
getCacheProperty(*PropName, CacheMode)});
874876
++CacheLevel;
875877
LevelMask >>= 1;
876878
}
@@ -941,7 +943,7 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
941943

942944
if (CacheProp) {
943945
LLVMContext &Ctx = M.getContext();
944-
unsigned MDKindID = Ctx.getMDKindID(SpirvDecorMdKind);
946+
unsigned MDKindID = Ctx.getMDKindID(SpirvDecorCacheControlMdKind);
945947
if (!FPGAProp && llvm::isa<llvm::Instruction>(IntrInst->getArgOperand(0))) {
946948
// Find all load/store instructions using the pointer being annotated and
947949
// apply the cache control metadata to them.
@@ -950,15 +952,15 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
950952
getUserListIgnoringCast<StoreInst>(IntrInst, TargetedInstList);
951953
getUserListIgnoringCast<MemTransferInst>(IntrInst, TargetedInstList);
952954
for (const auto &[Inst, MDVal] : TargetedInstList) {
955+
assert(MDVal >= 0 && "Invalid operand number for instruction.");
953956
// Merge with existing metadata if present.
954957
SmallVector<Metadata *, 8> MDOps;
955958
if (MDNode *CurrentMD = Inst->getMetadata(MDKindID))
956959
for (Metadata *Op : CurrentMD->operands())
957960
MDOps.push_back(Op);
958-
for (Metadata *Op : MDOpsCacheProp)
959-
MDOps.push_back(Op);
960-
MDOps.push_back(ConstantAsMetadata::get(Constant::getIntegerValue(
961-
Type::getInt32Ty(Ctx), APInt(32, MDVal))));
961+
for (const std::array<uint32_t, 3> &Op : MDOpsCacheProp)
962+
MDOps.push_back(buildSpirvDecorCacheProp(Ctx, Op[0], Op[1], Op[2],
963+
uint32_t(MDVal)));
962964
Inst->setMetadata(MDKindID, MDTuple::get(Ctx, MDOps));
963965
}
964966
// Replace all uses of ptr.annotations intrinsic with first operand and
@@ -969,7 +971,11 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
969971
} else {
970972
// If there were FPGA annotations then we retain the original intrinsic
971973
// and apply the cache control properties to its result.
972-
IntrInst->setMetadata(MDKindID, MDTuple::get(Ctx, MDOpsCacheProp));
974+
SmallVector<Metadata *, 8> MDOps;
975+
for (const std::array<uint32_t, 3> &Op : MDOpsCacheProp)
976+
MDOps.push_back(
977+
buildSpirvDecorCacheProp(Ctx, Op[0], Op[1], Op[2], uint32_t(0)));
978+
IntrInst->setMetadata(MDKindID, MDTuple::get(Ctx, MDOps));
973979
}
974980
}
975981

sycl/test/check_device_code/extensions/properties/properties_cache_control.cpp

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -171,62 +171,67 @@ SYCL_EXTERNAL void annotated_ptr_func_param_test(float *p) {
171171
}
172172

173173
// CHECK: spir_func{{.*}}annotated_ptr_func_param_test
174-
// CHECK: store float 4.200000e+01, ptr addrspace(4) %{{.*}}, !spirv.Decorations ![[WHINT:[0-9]+]]
174+
// CHECK: store float 4.200000e+01, ptr addrspace(4) %{{.*}}, !spirv.DecorationCacheControlINTEL ![[WHINT:[0-9]+]]
175175
// CHECK: ret void
176176

177177
// CHECK: spir_kernel{{.*}}cache_control_read_hint_func
178-
// CHECK: store float 5.500000e+01, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[RHINT:[0-9]+]]
178+
// CHECK: store float 5.500000e+01, ptr addrspace(1) %{{.*}}, !spirv.DecorationCacheControlINTEL ![[RHINT:[0-9]+]]
179179
// CHECK: ret void
180180

181181
// CHECK: spir_kernel{{.*}}cache_control_read_assertion_func
182-
// CHECK: store i32 66, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[RASSERT:[0-9]+]]
182+
// CHECK: store i32 66, ptr addrspace(1) %{{.*}}, !spirv.DecorationCacheControlINTEL ![[RASSERT:[0-9]+]]
183183
// CHECK: ret void
184184

185185
// CHECK: spir_kernel{{.*}}cache_control_write_hint_func
186-
// CHECK: store float 7.700000e+01, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[WHINT]]
186+
// CHECK: store float 7.700000e+01, ptr addrspace(1) %{{.*}}, !spirv.DecorationCacheControlINTEL ![[WHINT]]
187187
// CHECK: ret void
188188

189189
// CHECK: spir_kernel{{.*}}cache_control_read_write_func
190-
// CHECK: store float 7.700000e+01, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[RWHINT:[0-9]+]]
190+
// CHECK: store float 7.700000e+01, ptr addrspace(1) %{{.*}}, !spirv.DecorationCacheControlINTEL ![[RWHINT:[0-9]+]]
191191
// CHECK: ret void
192192

193193
// CHECK: spir_kernel{{.*}}cache_control_load_store_func
194-
// CHECK: store double 1.000000e+00, ptr addrspace(1) %[[PTR_A:.*]], align 8{{.*}}, !spirv.Decorations ![[STHINT_A:[0-9]+]]
195-
// CHECK: store double 1.000000e+00, ptr addrspace(1) %[[PTR_B:.*]], align 8{{.*}}, !spirv.Decorations ![[STHINT_B:[0-9]+]]
196-
// CHECK: load double, ptr addrspace(1) %[[PTR_A]], align 8{{.*}}, !spirv.Decorations ![[LDHINT_A:[0-9]+]]
197-
// CHECK: load double, ptr addrspace(1) %[[PTR_B]], align 8{{.*}}, !spirv.Decorations ![[LDHINT_B:[0-9]+]]
194+
// CHECK: store double 1.000000e+00, ptr addrspace(1) %[[PTR_A:.*]], align 8{{.*}}, !spirv.DecorationCacheControlINTEL ![[STHINT_A:[0-9]+]]
195+
// CHECK: store double 1.000000e+00, ptr addrspace(1) %[[PTR_B:.*]], align 8{{.*}}, !spirv.DecorationCacheControlINTEL ![[STHINT_B:[0-9]+]]
196+
// CHECK: load double, ptr addrspace(1) %[[PTR_A]], align 8{{.*}}, !spirv.DecorationCacheControlINTEL ![[LDHINT_A:[0-9]+]]
197+
// CHECK: load double, ptr addrspace(1) %[[PTR_B]], align 8{{.*}}, !spirv.DecorationCacheControlINTEL ![[LDHINT_B:[0-9]+]]
198198
// CHECK: ret void
199199

200-
// CHECK: [[WHINT]] = !{[[WHINT1:.*]], [[WHINT2:.*]], [[WHINT3:.*]], [[WHINT4:.*]], i32 1}
201-
// CHECK: [[WHINT1]] = !{i32 6443, i32 3, i32 3}
202-
// CHECK: [[WHINT2]] = !{i32 6443, i32 0, i32 1}
203-
// CHECK: [[WHINT3]] = !{i32 6443, i32 1, i32 2}
204-
// CHECK: [[WHINT4]] = !{i32 6443, i32 2, i32 2}
205-
206-
// CHECK: [[RHINT]] = !{[[RHINT1:.*]], [[RHINT2:.*]], [[RHINT3:.*]], i32 1}
207-
// CHECK: [[RHINT1]] = !{i32 6442, i32 1, i32 0}
208-
// CHECK: [[RHINT2]] = !{i32 6442, i32 2, i32 0}
209-
// CHECK: [[RHINT3]] = !{i32 6442, i32 0, i32 1}
210-
211-
// CHECK: [[RASSERT]] = !{[[RASSERT1:.*]], [[RASSERT2:.*]], [[RASSERT3:.*]], i32 1}
212-
// CHECK: [[RASSERT1]] = !{i32 6442, i32 1, i32 3}
213-
// CHECK: [[RASSERT2]] = !{i32 6442, i32 2, i32 3}
214-
// CHECK: [[RASSERT3]] = !{i32 6442, i32 0, i32 4}
215-
216-
// CHECK: [[RWHINT]] = !{[[RWHINT1:.*]], [[RWHINT2:.*]], [[RWHINT3:.*]], i32 1}
217-
// CHECK: [[RWHINT1]] = !{i32 6442, i32 2, i32 1}
218-
// CHECK: [[RWHINT2]] = !{i32 6442, i32 3, i32 4}
219-
// CHECK: [[RWHINT3]] = !{i32 6443, i32 3, i32 1}
220-
221-
// CHECK: [[STHINT_A]] = !{[[STHINT_A1:.*]], [[STHINT_A2:.*]], [[STHINT_A3:.*]], i32 1}
222-
// CHECK: [[STHINT_A1]] = !{i32 6443, i32 0, i32 0}
223-
// CHECK: [[STHINT_A2]] = !{i32 6443, i32 1, i32 0}
224-
// CHECK: [[STHINT_A3]] = !{i32 6443, i32 2, i32 0}
225-
226-
// CHECK: [[STHINT_B]] = !{[[STHINT_A2]], [[STHINT_A3]], [[STHINT_B1:.*]], i32 1}
227-
// CHECK: [[STHINT_B1]] = !{i32 6443, i32 0, i32 2}
228-
229-
// CHECK: [[LDHINT_A]] = !{[[RHINT1]], [[RHINT2]], [[RHINT3]], i32 0}
230-
// CHECK: [[LDHINT_B]] = !{[[LDHINT_B1:.*]], [[RWHINT1]], [[LDHINT_B2:.*]], i32 0}
231-
// CHECK: [[LDHINT_B1]] = !{i32 6442, i32 1, i32 1}
232-
// CHECK: [[LDHINT_B2]] = !{i32 6442, i32 0, i32 2}
200+
// CHECK: [[WHINT]] = !{[[WHINT1:.*]], [[WHINT2:.*]], [[WHINT3:.*]], [[WHINT4:.*]]}
201+
// CHECK: [[WHINT1]] = !{i32 6443, i32 3, i32 3, i32 1}
202+
// CHECK: [[WHINT2]] = !{i32 6443, i32 0, i32 1, i32 1}
203+
// CHECK: [[WHINT3]] = !{i32 6443, i32 1, i32 2, i32 1}
204+
// CHECK: [[WHINT4]] = !{i32 6443, i32 2, i32 2, i32 1}
205+
206+
// CHECK: [[RHINT]] = !{[[RHINT1:.*]], [[RHINT2:.*]], [[RHINT3:.*]]}
207+
// CHECK: [[RHINT1]] = !{i32 6442, i32 1, i32 0, i32 1}
208+
// CHECK: [[RHINT2]] = !{i32 6442, i32 2, i32 0, i32 1}
209+
// CHECK: [[RHINT3]] = !{i32 6442, i32 0, i32 1, i32 1}
210+
211+
// CHECK: [[RASSERT]] = !{[[RASSERT1:.*]], [[RASSERT2:.*]], [[RASSERT3:.*]]}
212+
// CHECK: [[RASSERT1]] = !{i32 6442, i32 1, i32 3, i32 1}
213+
// CHECK: [[RASSERT2]] = !{i32 6442, i32 2, i32 3, i32 1}
214+
// CHECK: [[RASSERT3]] = !{i32 6442, i32 0, i32 4, i32 1}
215+
216+
// CHECK: [[RWHINT]] = !{[[RWHINT1:.*]], [[RWHINT2:.*]], [[RWHINT3:.*]]}
217+
// CHECK: [[RWHINT1]] = !{i32 6442, i32 2, i32 1, i32 1}
218+
// CHECK: [[RWHINT2]] = !{i32 6442, i32 3, i32 4, i32 1}
219+
// CHECK: [[RWHINT3]] = !{i32 6443, i32 3, i32 1, i32 1}
220+
221+
// CHECK: [[STHINT_A]] = !{[[STHINT_A1:.*]], [[STHINT_A2:.*]], [[STHINT_A3:.*]]}
222+
// CHECK: [[STHINT_A1]] = !{i32 6443, i32 0, i32 0, i32 1}
223+
// CHECK: [[STHINT_A2]] = !{i32 6443, i32 1, i32 0, i32 1}
224+
// CHECK: [[STHINT_A3]] = !{i32 6443, i32 2, i32 0, i32 1}
225+
226+
// CHECK: [[STHINT_B]] = !{[[STHINT_A2]], [[STHINT_A3]], [[STHINT_B1:.*]]}
227+
// CHECK: [[STHINT_B1]] = !{i32 6443, i32 0, i32 2, i32 1}
228+
229+
// CHECK: [[LDHINT_A]] = !{[[LDHINT_A1:.*]], [[LDHINT_A2:.*]], [[LDHINT_A3:.*]]}
230+
// CHECK: [[LDHINT_A1]] = !{i32 6442, i32 1, i32 0, i32 0}
231+
// CHECK: [[LDHINT_A2]] = !{i32 6442, i32 2, i32 0, i32 0}
232+
// CHECK: [[LDHINT_A3]] = !{i32 6442, i32 0, i32 1, i32 0}
233+
234+
// CHECK: [[LDHINT_B]] = !{[[LDHINT_B1:.*]], [[LDHINT_B2:.*]], [[LDHINT_B3:.*]]}
235+
// CHECK: [[LDHINT_B1]] = !{i32 6442, i32 1, i32 1, i32 0}
236+
// CHECK: [[LDHINT_B2]] = !{i32 6442, i32 2, i32 1, i32 0}
237+
// CHECK: [[LDHINT_B3]] = !{i32 6442, i32 0, i32 2, i32 0}

0 commit comments

Comments
 (0)