Skip to content

Commit 4efc2b5

Browse files
committed
Unify representation of scalar and composite spec constants
Both scalar and composite spec constants are not communicated between the device compiler and runtime in a single propery set using unified format (the same as previously used for composite spec constants). This change was suggested on code review here: intel#2779 (comment)
1 parent 1792337 commit 4efc2b5

File tree

8 files changed

+74
-96
lines changed

8 files changed

+74
-96
lines changed

llvm/tools/sycl-post-link/SpecConstants.cpp

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -198,23 +198,28 @@ void setSpecConstSymIDMetadata(Instruction *I, StringRef SymID,
198198
I->setMetadata(SPEC_CONST_SYM_ID_MD_STRING, Entry);
199199
}
200200

201-
std::pair<StringRef, unsigned>
201+
std::pair<StringRef, std::vector<SpecConstantDescriptor>>
202202
getScalarSpecConstMetadata(const Instruction *I) {
203203
const MDNode *N = I->getMetadata(SPEC_CONST_SYM_ID_MD_STRING);
204204
if (!N)
205-
return std::make_pair("", 0);
205+
return std::make_pair("",
206+
std::vector<SpecConstantDescriptor>{});
206207
const auto *MDSym = cast<MDString>(N->getOperand(0));
207208
const auto *MDInt = cast<ConstantAsMetadata>(N->getOperand(1));
208209
unsigned ID = static_cast<unsigned>(
209210
cast<ConstantInt>(MDInt->getValue())->getValue().getZExtValue());
210-
return std::make_pair(MDSym->getString(), ID);
211+
std::vector<SpecConstantDescriptor> Res(1);
212+
Res[0].ID = ID;
213+
Res[0].Size = I->getType()->getPrimitiveSizeInBits() / /* bits in byte */8;
214+
Res[0].Offset = 0;
215+
return std::make_pair(MDSym->getString(), Res);
211216
}
212217

213218
/// Recursively iterates over a composite type in order to collect information
214219
/// about its scalar elements.
215220
void collectCompositeElementsInfoRecursive(
216221
const Module *M, Type *Ty, unsigned &Index, unsigned &Offset,
217-
std::vector<CompositeSpecConstElementDescriptor> &Result) {
222+
std::vector<SpecConstantDescriptor> &Result) {
218223
if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
219224
for (size_t I = 0; I < ArrTy->getNumElements(); ++I) {
220225
// TODO: this is a spot for potential optimization: for arrays we could
@@ -248,7 +253,7 @@ void collectCompositeElementsInfoRecursive(
248253
Offset, Result);
249254
}
250255
} else { // Assume that we encountered some scalar element
251-
CompositeSpecConstElementDescriptor Desc;
256+
SpecConstantDescriptor Desc;
252257
Desc.ID = 0; // To be filled later
253258
Desc.Offset = Offset;
254259
Desc.Size = Ty->getPrimitiveSizeInBits() / 8;
@@ -257,15 +262,15 @@ void collectCompositeElementsInfoRecursive(
257262
}
258263
}
259264

260-
std::pair<StringRef, std::vector<CompositeSpecConstElementDescriptor>>
265+
std::pair<StringRef, std::vector<SpecConstantDescriptor>>
261266
getCompositeSpecConstMetadata(const Instruction *I) {
262267
const MDNode *N = I->getMetadata(SPEC_CONST_SYM_ID_MD_STRING);
263268
if (!N)
264269
return std::make_pair("",
265-
std::vector<CompositeSpecConstElementDescriptor>{});
270+
std::vector<SpecConstantDescriptor>{});
266271
const auto *MDSym = cast<MDString>(N->getOperand(0));
267272

268-
std::vector<CompositeSpecConstElementDescriptor> Result(N->getNumOperands() -
273+
std::vector<SpecConstantDescriptor> Result(N->getNumOperands() -
269274
1);
270275
unsigned Index = 0, Offset = 0;
271276
collectCompositeElementsInfoRecursive(I->getModule(), I->getType(), Index,
@@ -505,9 +510,8 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
505510
return IRModified ? PreservedAnalyses::none() : PreservedAnalyses::all();
506511
}
507512

508-
bool SpecConstantsPass::collectSpecConstantMetadata(
509-
Module &M, ScalarSpecIDMapTy &ScalarIDMap,
510-
CompositeSpecIDMapTy &CompositeIDMap) {
513+
bool SpecConstantsPass::collectSpecConstantMetadata(Module &M,
514+
SpecIDMapTy &IDMap) {
511515
bool Met = false;
512516

513517
for (Function &F : M) {
@@ -521,18 +525,16 @@ bool SpecConstantsPass::collectSpecConstantMetadata(
521525
if (!CI || CI->isIndirectCall() || !(Callee = CI->getCalledFunction()))
522526
continue;
523527

528+
std::pair<StringRef, std::vector<SpecConstantDescriptor>> Res;
524529
if (Callee->getName().contains(SPIRV_GET_SPEC_CONST_COMPOSITE)) {
525-
auto Res = getCompositeSpecConstMetadata(CI);
526-
if (!Res.first.empty()) {
527-
CompositeIDMap[Res.first] = Res.second;
528-
Met = true;
529-
}
530+
Res = getCompositeSpecConstMetadata(CI);
530531
} else if (Callee->getName().contains(SPIRV_GET_SPEC_CONST_VAL)) {
531-
auto Res = getScalarSpecConstMetadata(CI);
532-
if (!Res.first.empty()) {
533-
ScalarIDMap[Res.first] = Res.second;
534-
Met = true;
535-
}
532+
Res = getScalarSpecConstMetadata(CI);
533+
}
534+
535+
if (!Res.first.empty()) {
536+
IDMap[Res.first] = Res.second;
537+
Met = true;
536538
}
537539
}
538540
}

llvm/tools/sycl-post-link/SpecConstants.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,27 @@
2424

2525
using namespace llvm;
2626

27-
using ScalarSpecIDMapTy = std::map<StringRef, unsigned>;
28-
// Represents an element of a composite speciailization constant - at SYCL RT
29-
// level composite specialization constants are being represented as a single
30-
// byte-array, while at SPIR-V level they are represented by a number of scalar
31-
// specialization constants.
32-
struct CompositeSpecConstElementDescriptor {
27+
// Represents either an element of a composite speciailization constant or a
28+
// single scalar specialization constant - at SYCL RT level composite
29+
// specialization constants are being represented as a single byte-array, while
30+
// at SPIR-V level they are represented by a number of scalar specialization
31+
// constants.
32+
// The same representation is re-used for scalar specialization constants in
33+
// order to unify they processing with composite ones.
34+
struct SpecConstantDescriptor {
3335
// Encodes ID of a scalar specialization constants which is a leaf of some
3436
// composite specialization constant.
3537
unsigned ID;
3638
// Encodes offset from the beginning of composite, where scalar resides, i.e.
3739
// location of the scalar value within a byte-array containing the whole
38-
// composite specialization constant.
40+
// composite specialization constant. If descriptor is used to represent a
41+
// whole scalar specialization constant instead of an element of a composite,
42+
// this field should be contain zero.
3943
unsigned Offset;
4044
// Encodes size of scalar specialization constant.
4145
unsigned Size;
4246
};
43-
using CompositeSpecIDMapTy =
44-
std::map<StringRef, std::vector<CompositeSpecConstElementDescriptor>>;
47+
using SpecIDMapTy = std::map<StringRef, std::vector<SpecConstantDescriptor>>;
4548

4649
class SpecConstantsPass : public PassInfoMixin<SpecConstantsPass> {
4750
public:
@@ -57,9 +60,7 @@ class SpecConstantsPass : public PassInfoMixin<SpecConstantsPass> {
5760
// constants and
5861
// "spec constant name" -> vector<"spec constant int ID"> map for composite
5962
// spec constants
60-
static bool collectSpecConstantMetadata(Module &M,
61-
ScalarSpecIDMapTy &ScalarIDMap,
62-
CompositeSpecIDMapTy &CompositeIDMap);
63+
static bool collectSpecConstantMetadata(Module &M, SpecIDMapTy &IDMap);
6364

6465
private:
6566
bool SetValAtRT;

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -545,16 +545,12 @@ static string_vector saveDeviceImageProperty(
545545
if (ImgPSInfo.DoSpecConst && ImgPSInfo.SetSpecConstAtRT) {
546546
if (ImgPSInfo.SpecConstsMet) {
547547
// extract spec constant maps per each module
548-
ScalarSpecIDMapTy TmpScalarSpecIDMap;
549-
CompositeSpecIDMapTy TmpCompositeSpecIDMap;
550-
SpecConstantsPass::collectSpecConstantMetadata(
551-
*ResultModules[I].get(), TmpScalarSpecIDMap, TmpCompositeSpecIDMap);
548+
SpecIDMapTy TmpSpecIDMap;
549+
SpecConstantsPass::collectSpecConstantMetadata(*ResultModules[I].get(),
550+
TmpSpecIDMap);
552551
PropSet.add(
553552
llvm::util::PropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS,
554-
TmpScalarSpecIDMap);
555-
PropSet.add(llvm::util::PropertySetRegistry::
556-
SYCL_COMPOSITE_SPECIALIZATION_CONSTANTS,
557-
TmpCompositeSpecIDMap);
553+
TmpSpecIDMap);
558554
}
559555
}
560556
if (ImgPSInfo.EmitKernelParamInfo) {

sycl/include/CL/sycl/detail/pi.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,8 @@ static const uint8_t PI_DEVICE_BINARY_OFFLOAD_KIND_SYCL = 4;
660660
/// Name must be consistent with
661661
/// PropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS defined in
662662
/// PropertySetIO.h
663-
#define __SYCL_PI_PROPERTY_SET_SCALAR_SPEC_CONST_MAP \
663+
#define __SYCL_PI_PROPERTY_SET_SPEC_CONST_MAP \
664664
"SYCL/specialization constants"
665-
/// PropertySetRegistry::SYCL_COMPOSITE_SPECIALIZATION_CONSTANTS defined in
666-
/// PropertySetIO.h
667-
#define __SYCL_PI_PROPERTY_SET_COMPOSITE_SPEC_CONST_MAP \
668-
"SYCL/composite specialization constants"
669665
/// PropertySetRegistry::SYCL_DEVICELIB_REQ_MASK defined in PropertySetIO.h
670666
#define __SYCL_PI_PROPERTY_SET_DEVICELIB_REQ_MASK "SYCL/devicelib req mask"
671667
/// PropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO defined in PropertySetIO.h

sycl/include/CL/sycl/detail/pi.hpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -283,20 +283,18 @@ class DeviceBinaryImage {
283283
return Format;
284284
}
285285

286-
/// Gets the iterator range over scalar specialization constants in this
287-
/// binary image. For each property pointed to by an iterator within the
286+
/// Gets the iterator range over specialization constants in this binary
287+
/// image. For each property pointed to by an iterator within the
288288
/// range, the name of the property is the specialization constant symbolic ID
289-
/// and the value is 32-bit unsigned integer ID.
290-
const PropertyRange &getScalarSpecConstants() const {
291-
return ScalarSpecConstIDMap;
292-
}
293-
/// Gets the iterator range over composite specialization constants in this
294-
/// binary image. For each property pointed to by an iterator within the
295-
/// range, the name of the property is the specialization constant symbolic ID
296-
/// and the value is a list of tuples of 32-bit unsigned integer values, which
297-
/// encode scalar specialization constants, that form the composite one.
289+
/// and the value is a list of 3-element tuples of 32-bit unsigned integers,
290+
/// describing the specialization constant.
291+
/// This is done in order to unify representation of both scalar and composite
292+
/// specialization constants: composite specialization constant is represented
293+
/// by its leaf elements, so for scalars the list contains only a single
294+
/// tuple, while for composite there might be more of them.
298295
/// Each tuple consists of ID of scalar specialization constant, its location
299-
/// within a composite (offset in bytes from the beginning) and its size.
296+
/// within a composite (offset in bytes from the beginning or 0 if it is not
297+
/// an element of a composite specialization constant) and its size.
300298
/// For example, for the following structure:
301299
/// struct A { int a; float b; };
302300
/// struct POD { A a[2]; int b; };
@@ -306,8 +304,11 @@ class DeviceBinaryImage {
306304
/// { ID2, 8, 4 }, // .a[1].a
307305
/// { ID3, 12, 4 }, // .a[1].b
308306
/// { ID4, 16, 4 }, // .b
309-
const PropertyRange &getCompositeSpecConstants() const {
310-
return CompositeSpecConstIDMap;
307+
/// And for an interger specialization constant, the list of tuples will look
308+
/// like:
309+
/// { ID5, 0, 4 }
310+
const PropertyRange &getSpecConstants() const {
311+
return SpecConstIDMap;
311312
}
312313
const PropertyRange &getDeviceLibReqMask() const { return DeviceLibReqMask; }
313314
const PropertyRange &getKernelParamOptInfo() const {
@@ -321,8 +322,7 @@ class DeviceBinaryImage {
321322

322323
pi_device_binary Bin;
323324
pi::PiDeviceBinaryType Format = PI_DEVICE_BINARY_TYPE_NONE;
324-
DeviceBinaryImage::PropertyRange ScalarSpecConstIDMap;
325-
DeviceBinaryImage::PropertyRange CompositeSpecConstIDMap;
325+
DeviceBinaryImage::PropertyRange SpecConstIDMap;
326326
DeviceBinaryImage::PropertyRange DeviceLibReqMask;
327327
DeviceBinaryImage::PropertyRange KernelParamOptInfo;
328328
};

sycl/source/detail/pi.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,9 +593,7 @@ void DeviceBinaryImage::init(pi_device_binary Bin) {
593593
// try to determine the format; may remain "NONE"
594594
Format = getBinaryImageFormat(Bin->BinaryStart, getSize());
595595

596-
ScalarSpecConstIDMap.init(Bin, __SYCL_PI_PROPERTY_SET_SCALAR_SPEC_CONST_MAP);
597-
CompositeSpecConstIDMap.init(Bin,
598-
__SYCL_PI_PROPERTY_SET_COMPOSITE_SPEC_CONST_MAP);
596+
SpecConstIDMap.init(Bin, __SYCL_PI_PROPERTY_SET_SPEC_CONST_MAP);
599597
DeviceLibReqMask.init(Bin, __SYCL_PI_PROPERTY_SET_DEVICELIB_REQ_MASK);
600598
KernelParamOptInfo.init(Bin, __SYCL_PI_PROPERTY_SET_KERNEL_PARAM_OPT_INFO);
601599
}

sycl/source/detail/program_impl.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -523,29 +523,14 @@ void program_impl::flush_spec_constants(const RTDeviceBinaryImage &Img,
523523
RT::PiProgram NativePrg) const {
524524
// iterate via all specialization constants the program's image depends on,
525525
// and set each to current runtime value (if any)
526-
const pi::DeviceBinaryImage::PropertyRange &ScalarSCRange =
527-
Img.getScalarSpecConstants();
528-
const pi::DeviceBinaryImage::PropertyRange &CompositeSCRange =
529-
Img.getCompositeSpecConstants();
526+
const pi::DeviceBinaryImage::PropertyRange &SCRange = Img.getSpecConstants();
530527
ContextImplPtr Ctx = getSyclObjImpl(get_context());
531528
using SCItTy = pi::DeviceBinaryImage::PropertyRange::ConstIterator;
532529

533530
auto LockGuard = Ctx->getKernelProgramCache().acquireCachedPrograms();
534531
NativePrg = NativePrg ? NativePrg : getHandleRef();
535532

536-
for (SCItTy SCIt : ScalarSCRange) {
537-
auto SCEntry = SpecConstRegistry.find((*SCIt)->Name);
538-
if (SCEntry == SpecConstRegistry.end())
539-
// spec constant has not been set in user code - SPIR-V will use default
540-
continue;
541-
const spec_constant_impl &SC = SCEntry->second;
542-
assert(SC.isSet() && "uninitialized spec constant");
543-
pi_uint32 ID = pi::DeviceBinaryProperty(*SCIt).asUint32();
544-
Ctx->getPlugin().call<PiApiKind::piextProgramSetSpecializationConstant>(
545-
NativePrg, ID, SC.getSize(), SC.getValuePtr());
546-
}
547-
548-
for (SCItTy SCIt : CompositeSCRange) {
533+
for (SCItTy SCIt : SCRange) {
549534
auto SCEntry = SpecConstRegistry.find((*SCIt)->Name);
550535
if (SCEntry == SpecConstRegistry.end())
551536
// spec constant has not been set in user code - SPIR-V will use default
@@ -557,9 +542,9 @@ void program_impl::flush_spec_constants(const RTDeviceBinaryImage &Img,
557542
assert(Descriptors.size() > 8 && "Unexpected property size");
558543
// Expected layout is vector of 3-component tuples (flattened into a vector
559544
// of scalars), where each tuple consists of: ID of a scalar spec constant,
560-
// which is a member of the composite; offset, which is used to calculate
561-
// location of scalar member within the composite; size of a scalar member
562-
// of the composite.
545+
// (which might be a member of the composite); offset, which is used to
546+
// calculate location of scalar member within the composite or zero for
547+
// scalar spec constants; size of a spec constant
563548
assert(((Descriptors.size() - 8) / sizeof(std::uint32_t)) % 3 == 0 &&
564549
"unexpected layout of composite spec const descriptors");
565550
auto *It = reinterpret_cast<const std::uint32_t *>(&Descriptors[8]);

sycl/test/basic_tests/spec_const_types.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,35 +44,35 @@ int main() {
4444
// Create specialization constants.
4545
cl::sycl::ONEAPI::experimental::spec_constant<bool, MyBoolConst> i1 =
4646
program.set_spec_constant<MyBoolConst>((bool)get_value());
47-
// CHECK-DAG: _ZTS11MyBoolConst=1|0
47+
// CHECK-DAG: _ZTS11MyBoolConst=2|
4848

4949
cl::sycl::ONEAPI::experimental::spec_constant<int8_t, MyInt8Const> i8 =
5050
program.set_spec_constant<MyInt8Const>((int8_t)get_value());
51-
// CHECK-DAG: _ZTS11MyInt8Const=1|1
51+
// CHECK-DAG: _ZTS11MyInt8Const=2|
5252
cl::sycl::ONEAPI::experimental::spec_constant<uint8_t, MyUInt8Const> ui8 =
5353
program.set_spec_constant<MyUInt8Const>((uint8_t)get_value());
54-
// CHECK-DAG: _ZTS12MyUInt8Const=1|2
54+
// CHECK-DAG: _ZTS12MyUInt8Const=2|
5555

5656
cl::sycl::ONEAPI::experimental::spec_constant<int16_t, MyInt16Const> i16 =
5757
program.set_spec_constant<MyInt16Const>((int16_t)get_value());
58-
// CHECK-DAG: _ZTS12MyInt16Const=1|3
58+
// CHECK-DAG: _ZTS12MyInt16Const=2|
5959
cl::sycl::ONEAPI::experimental::spec_constant<uint16_t, MyUInt16Const> ui16 =
6060
program.set_spec_constant<MyUInt16Const>((uint16_t)get_value());
61-
// CHECK-DAG: _ZTS13MyUInt16Const=1|4
61+
// CHECK-DAG: _ZTS13MyUInt16Const=2|
6262

6363
cl::sycl::ONEAPI::experimental::spec_constant<int32_t, MyInt32Const> i32 =
6464
program.set_spec_constant<MyInt32Const>((int32_t)get_value());
65-
// CHECK-DAG: _ZTS12MyInt32Const=1|5
65+
// CHECK-DAG: _ZTS12MyInt32Const=2|
6666
cl::sycl::ONEAPI::experimental::spec_constant<uint32_t, MyUInt32Const> ui32 =
6767
program.set_spec_constant<MyUInt32Const>((uint32_t)get_value());
68-
// CHECK-DAG: _ZTS13MyUInt32Const=1|6
68+
// CHECK-DAG: _ZTS13MyUInt32Const=2|
6969

7070
cl::sycl::ONEAPI::experimental::spec_constant<int64_t, MyInt64Const> i64 =
7171
program.set_spec_constant<MyInt64Const>((int64_t)get_value());
72-
// CHECK-DAG: _ZTS12MyInt64Const=1|7
72+
// CHECK-DAG: _ZTS12MyInt64Const=2|
7373
cl::sycl::ONEAPI::experimental::spec_constant<uint64_t, MyUInt64Const> ui64 =
7474
program.set_spec_constant<MyUInt64Const>((uint64_t)get_value());
75-
// CHECK-DAG: _ZTS13MyUInt64Const=1|8
75+
// CHECK-DAG: _ZTS13MyUInt64Const=2|
7676

7777
#define HALF 0 // TODO not yet supported
7878
#if HALF
@@ -82,11 +82,11 @@ int main() {
8282

8383
cl::sycl::ONEAPI::experimental::spec_constant<float, MyFloatConst> f32 =
8484
program.set_spec_constant<MyFloatConst>((float)get_value());
85-
// CHECK-DAG: _ZTS12MyFloatConst=1|9
85+
// CHECK-DAG: _ZTS12MyFloatConst=2|
8686

8787
cl::sycl::ONEAPI::experimental::spec_constant<double, MyDoubleConst> f64 =
8888
program.set_spec_constant<MyDoubleConst>((double)get_value());
89-
// CHECK-DAG: _ZTS13MyDoubleConst=1|10
89+
// CHECK-DAG: _ZTS13MyDoubleConst=2|
9090

9191
program.build_with_kernel_type<SpecializedKernel>();
9292

0 commit comments

Comments
 (0)