@@ -93,6 +93,15 @@ MDNode *buildSpirvDecorMetadata(LLVMContext &Ctx, uint32_t OpCode,
93
93
return MDNode::get (Ctx, MD);
94
94
}
95
95
96
+ // / Gets the string value in a global variable. If the parameter is not a global
97
+ // / variable or it does not contain string data, then \c None is returned.
98
+ // /
99
+ // / @param StringV [in] the LLVM value of supposed \c GlobalVariable type with
100
+ // / a string value.
101
+ // /
102
+ // / @returns a \c StringRef with the string contained in \c StringV and \c None
103
+ // / if \c StringV is not a \c GlobalVariable or does not contain string
104
+ // / data.
96
105
Optional<StringRef> getGlobalVariableString (const Value *StringV) {
97
106
if (const auto *StringGV = dyn_cast<GlobalVariable>(StringV))
98
107
if (const auto *StringData =
@@ -102,6 +111,106 @@ Optional<StringRef> getGlobalVariableString(const Value *StringV) {
102
111
return {};
103
112
}
104
113
114
+ // / Tries to generate a SPIR-V decorate metadata node from an attribute. If
115
+ // / the attribute is unknown \c nullptr will be returned.
116
+ // /
117
+ // / @param Ctx [in] the LLVM context.
118
+ // / @param Attr [in] the LLVM attribute to generate metadata for.
119
+ // /
120
+ // / @returns a pointer to a new metadata node if \c Attr is an attribute with a
121
+ // / known corresponding SPIR-V decorate and the arguments are valid.
122
+ // / Otherwise \c nullptr is returned.
123
+ MDNode *attributeToDecorateMetadata (LLVMContext &Ctx, const Attribute &Attr) {
124
+ // Currently, only string attributes are supported
125
+ if (!Attr.isStringAttribute ())
126
+ return nullptr ;
127
+ auto DecorIt = SpirvDecorMap.find (Attr.getKindAsString ());
128
+ if (DecorIt == SpirvDecorMap.end ())
129
+ return nullptr ;
130
+ Decor DecorFound = DecorIt->second ;
131
+ uint32_t DecorCode = DecorFound.Code ;
132
+ switch (DecorFound.Type ) {
133
+ case DecorValueTy::uint32:
134
+ return buildSpirvDecorMetadata (Ctx, DecorCode,
135
+ getAttributeAsInteger<uint32_t >(Attr));
136
+ case DecorValueTy::boolean:
137
+ return buildSpirvDecorMetadata (Ctx, DecorCode, hasProperty (Attr));
138
+ default :
139
+ llvm_unreachable (" Unhandled decorator type." );
140
+ }
141
+ }
142
+
143
+ // / Tries to generate a SPIR-V execution mode metadata node from an attribute.
144
+ // / If the attribute is unknown \c None will be returned.
145
+ // /
146
+ // / @param M [in] the LLVM module.
147
+ // / @param Attr [in] the LLVM attribute to generate metadata for.
148
+ // /
149
+ // / @returns a pair with the name of the resulting metadata and a pointer to
150
+ // / the metadata node with its values if the attribute has a
151
+ // / corresponding SPIR-V execution mode. Otherwise \c None is returned.
152
+ Optional<std::pair<std::string, MDNode *>>
153
+ attributeToExecModeMetadata (Module &M, const Attribute &Attr) {
154
+ LLVMContext &Ctx = M.getContext ();
155
+ const DataLayout &DLayout = M.getDataLayout ();
156
+
157
+ // Currently, only string attributes are supported
158
+ if (!Attr.isStringAttribute ())
159
+ return None;
160
+ StringRef AttrKindStr = Attr.getKindAsString ();
161
+ // Early exit if it is not a sycl-* attribute.
162
+ if (!AttrKindStr.startswith (" sycl-" ))
163
+ return None;
164
+
165
+ if (AttrKindStr == " sycl-work-group-size" ||
166
+ AttrKindStr == " sycl-work-group-size-hint" ) {
167
+ // Split values in the comma-separated list integers.
168
+ SmallVector<StringRef, 3 > ValStrs;
169
+ Attr.getValueAsString ().split (ValStrs, ' ,' );
170
+
171
+ assert (ValStrs.size () <= 3 &&
172
+ " sycl-work-group-size and sycl-work-group-size-hint currently only "
173
+ " support up to three values" );
174
+
175
+ // SYCL work-group sizes must be reversed for SPIR-V.
176
+ std::reverse (ValStrs.begin (), ValStrs.end ());
177
+
178
+ // Use integer pointer size as closest analogue to size_t.
179
+ IntegerType *IntPtrTy = DLayout.getIntPtrType (Ctx);
180
+ IntegerType *SizeTTy = Type::getIntNTy (Ctx, IntPtrTy->getBitWidth ());
181
+ unsigned SizeTBitSize = SizeTTy->getBitWidth ();
182
+
183
+ // Get the integers from the strings.
184
+ SmallVector<Metadata *, 3 > MDVals;
185
+ for (StringRef ValStr : ValStrs)
186
+ MDVals.push_back (ConstantAsMetadata::get (Constant::getIntegerValue (
187
+ SizeTTy, APInt (SizeTBitSize, ValStr, 10 ))));
188
+
189
+ // The SPIR-V translator expects 3 values, so we pad the remaining
190
+ // dimensions with 1.
191
+ for (size_t I = MDVals.size (); I < 3 ; ++I)
192
+ MDVals.push_back (ConstantAsMetadata::get (
193
+ Constant::getIntegerValue (SizeTTy, APInt (SizeTBitSize, 1 ))));
194
+
195
+ const char *MDName = (AttrKindStr == " sycl-work-group-size" )
196
+ ? " reqd_work_group_size"
197
+ : " work_group_size_hint" ;
198
+ return std::pair<std::string, MDNode *>(MDName, MDNode::get (Ctx, MDVals));
199
+ }
200
+
201
+ if (AttrKindStr == " sycl-sub-group-size" ) {
202
+ uint32_t SubGroupSize = getAttributeAsInteger<uint32_t >(Attr);
203
+ IntegerType *Ty = Type::getInt32Ty (Ctx);
204
+ Metadata *MDVal = ConstantAsMetadata::get (
205
+ Constant::getIntegerValue (Ty, APInt (32 , SubGroupSize)));
206
+ SmallVector<Metadata *, 1 > MD{MDVal};
207
+ return std::pair<std::string, MDNode *>(" intel_reqd_sub_group_size" ,
208
+ MDNode::get (Ctx, MD));
209
+ }
210
+
211
+ return None;
212
+ }
213
+
105
214
} // anonymous namespace
106
215
107
216
PreservedAnalyses CompileTimePropertiesPass::run (Module &M,
@@ -117,18 +226,9 @@ PreservedAnalyses CompileTimePropertiesPass::run(Module &M,
117
226
// decorations in the SPV_INTEL_* extensions.
118
227
SmallVector<Metadata *, 8 > MDOps;
119
228
for (auto &Attribute : GV.getAttributes ()) {
120
- // Currently, only string attributes are supported
121
- if (!Attribute.isStringAttribute ())
122
- continue ;
123
- auto DecorIt = SpirvDecorMap.find (Attribute.getKindAsString ());
124
- if (DecorIt == SpirvDecorMap.end ())
125
- continue ;
126
- auto Decor = DecorIt->second ;
127
- auto DecorCode = Decor.Code ;
128
- auto DecorValue = Decor.Type == DecorValueTy::uint32
129
- ? getAttributeAsInteger<uint32_t >(Attribute)
130
- : hasProperty (Attribute);
131
- MDOps.push_back (buildSpirvDecorMetadata (Ctx, DecorCode, DecorValue));
229
+ MDNode *SPIRVMetadata = attributeToDecorateMetadata (Ctx, Attribute);
230
+ if (SPIRVMetadata)
231
+ MDOps.push_back (SPIRVMetadata);
132
232
}
133
233
134
234
// Some properties should be handled specially.
@@ -154,6 +254,36 @@ PreservedAnalyses CompileTimePropertiesPass::run(Module &M,
154
254
}
155
255
}
156
256
257
+ // Process all properties on kernels.
258
+ for (Function &F : M) {
259
+ // Only consider kernels.
260
+ if (F.getCallingConv () != CallingConv::SPIR_KERNEL)
261
+ continue ;
262
+
263
+ SmallVector<Metadata *, 8 > MDOps;
264
+ SmallVector<std::pair<std::string, MDNode *>, 8 > NamedMDOps;
265
+ for (const Attribute &Attribute : F.getAttributes ().getFnAttrs ()) {
266
+ if (MDNode *SPIRVMetadata = attributeToDecorateMetadata (Ctx, Attribute))
267
+ MDOps.push_back (SPIRVMetadata);
268
+ else if (auto NamedMetadata = attributeToExecModeMetadata (M, Attribute))
269
+ NamedMDOps.push_back (*NamedMetadata);
270
+ }
271
+
272
+ // Add the generated metadata to the kernel function.
273
+ if (!MDOps.empty ()) {
274
+ F.addMetadata (MDKindID, *MDNode::get (Ctx, MDOps));
275
+ CompileTimePropertiesMet = true ;
276
+ }
277
+
278
+ // Add the new named metadata to the kernel function.
279
+ for (std::pair<std::string, MDNode *> NamedMD : NamedMDOps) {
280
+ // If multiple sources defined this metadata, prioritize the existing one.
281
+ if (F.hasMetadata (NamedMD.first ))
282
+ continue ;
283
+ F.addMetadata (NamedMD.first , *NamedMD.second );
284
+ }
285
+ }
286
+
157
287
// Check pointer annotations.
158
288
SmallVector<IntrinsicInst *, 4 > RemovableAnnots;
159
289
for (Function &F : M)
0 commit comments