@@ -51,6 +51,14 @@ constexpr char SPEC_CONST_MD_STRING[] = "sycl.specialization-constants";
51
51
constexpr char SPEC_CONST_DEFAULT_VAL_MD_STRING[] =
52
52
" sycl.specialization-constants-default-values" ;
53
53
54
+ // / Spec. Constant ID is a pair of Id and a flag whether this Id belongs to an
55
+ // / undefined value. Undefined values ('undef' in the IR) are used to get the
56
+ // / required alignment and should be handled in a special manner as padding.
57
+ struct ID {
58
+ unsigned ID;
59
+ bool Undef;
60
+ };
61
+
54
62
StringRef getStringLiteralArg (const CallInst *CI, unsigned ArgNo,
55
63
SmallVectorImpl<Instruction *> &DelInsts) {
56
64
Value *V = CI->getArgOperand (ArgNo)->stripPointerCasts ();
@@ -236,8 +244,13 @@ MDNode *generateSpecConstDefaultValueMetadata(StringRef SymID, Value *Default) {
236
244
// / Recursively iterates over a composite type in order to collect information
237
245
// / about its scalar elements.
238
246
void collectCompositeElementsInfoRecursive (
239
- const Module &M, Type *Ty, const unsigned *&IDIter, unsigned &Offset,
247
+ const Module &M, Type *Ty, const ID *&IDIter, unsigned &Offset,
240
248
std::vector<SpecConstantDescriptor> &Result) {
249
+ if (IDIter->Undef ) {
250
+ // We can just skip undefined values because every such value is just a
251
+ // padding and will be handled in a different manner.
252
+ return ;
253
+ }
241
254
if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
242
255
for (size_t I = 0 ; I < ArrTy->getNumElements (); ++I) {
243
256
// TODO: this is a spot for potential optimization: for arrays we could
@@ -246,7 +259,9 @@ void collectCompositeElementsInfoRecursive(
246
259
collectCompositeElementsInfoRecursive (M, ArrTy->getElementType (), IDIter,
247
260
Offset, Result);
248
261
}
249
- } else if (auto *StructTy = dyn_cast<StructType>(Ty)) {
262
+ return ;
263
+ }
264
+ if (auto *StructTy = dyn_cast<StructType>(Ty)) {
250
265
const StructLayout *SL = M.getDataLayout ().getStructLayout (StructTy);
251
266
const unsigned BaseOffset = Offset;
252
267
unsigned LocalOffset = Offset;
@@ -267,7 +282,12 @@ void collectCompositeElementsInfoRecursive(
267
282
BaseOffset + SL->getSizeInBytes () - LocalOffset;
268
283
if (PostStructPadding > 0 ) {
269
284
SpecConstantDescriptor Desc;
270
- // ID of padding descriptors is the max value possible.
285
+ // ID of padding descriptors is the max value possible. This value is a
286
+ // magic value for the runtime and will just be skipped. Even if there
287
+ // are many specialization constants and every constant has padding of
288
+ // a different length, everything will work regardless rewriting
289
+ // the descriptions with Desc.ID equals to the max value: they will just
290
+ // be ignored at all.
271
291
Desc.ID = std::numeric_limits<unsigned >::max ();
272
292
Desc.Offset = LocalOffset;
273
293
Desc.Size = PostStructPadding;
@@ -277,25 +297,29 @@ void collectCompositeElementsInfoRecursive(
277
297
// Update "global" offset according to the total size of a handled struct
278
298
// type.
279
299
Offset += SL->getSizeInBytes ();
280
- } else if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) {
300
+ return ;
301
+ }
302
+ if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) {
281
303
for (size_t I = 0 ; I < VecTy->getNumElements (); ++I) {
282
304
// TODO: this is a spot for potential optimization: for vectors we could
283
305
// just make a single recursive call here and use it to populate Result
284
306
// in a loop.
285
307
collectCompositeElementsInfoRecursive (M, VecTy->getElementType (), IDIter,
286
308
Offset, Result);
287
309
}
288
- } else { // Assume that we encountered some scalar element
289
- SpecConstantDescriptor Desc;
290
- Desc.ID = *IDIter;
291
- Desc.Offset = Offset;
292
- Desc.Size = M.getDataLayout ().getTypeStoreSize (Ty);
293
- Result.push_back (Desc);
294
-
295
- // Move current ID and offset
296
- ++IDIter;
297
- Offset += Desc.Size ;
310
+ return ;
298
311
}
312
+
313
+ // Assume that we encountered some scalar element
314
+ SpecConstantDescriptor Desc;
315
+ Desc.ID = IDIter->ID ;
316
+ Desc.Offset = Offset;
317
+ Desc.Size = M.getDataLayout ().getTypeStoreSize (Ty);
318
+ Result.push_back (Desc);
319
+
320
+ // Move current ID and offset
321
+ ++IDIter;
322
+ Offset += Desc.Size ;
299
323
}
300
324
301
325
// / Recursively iterates over a composite type in order to collect information
@@ -306,8 +330,8 @@ void collectCompositeElementsInfoRecursive(
306
330
void collectCompositeElementsDefaultValuesRecursive (
307
331
const Module &M, Constant *C, unsigned &Offset,
308
332
std::vector<char > &DefaultValues) {
309
- if (isa<ConstantAggregateZero>(C)) {
310
- // This code is generic for zeroinitializer for both arrays and structs
333
+ if (isa<ConstantAggregateZero>(C) || isa<UndefValue>(C) ) {
334
+ // This code is generic for both arrays and structs
311
335
size_t NumBytes = M.getDataLayout ().getTypeStoreSize (C->getType ());
312
336
std::fill_n (std::back_inserter (DefaultValues), NumBytes, 0 );
313
337
Offset += NumBytes;
@@ -400,7 +424,7 @@ void collectCompositeElementsDefaultValuesRecursive(
400
424
}
401
425
402
426
MDNode *generateSpecConstantMetadata (const Module &M, StringRef SymbolicID,
403
- Type *SCTy, ArrayRef<unsigned > IDs,
427
+ Type *SCTy, ArrayRef<ID > IDs,
404
428
bool IsNativeSpecConstant) {
405
429
SmallVector<Metadata *, 16 > MDOps;
406
430
LLVMContext &Ctx = M.getContext ();
@@ -413,7 +437,7 @@ MDNode *generateSpecConstantMetadata(const Module &M, StringRef SymbolicID,
413
437
std::vector<SpecConstantDescriptor> Result;
414
438
Result.reserve (IDs.size ());
415
439
unsigned Offset = 0 ;
416
- const unsigned *IDPtr = IDs.data ();
440
+ const ID *IDPtr = IDs.data ();
417
441
collectCompositeElementsInfoRecursive (M, SCTy, IDPtr, Offset, Result);
418
442
419
443
// We may have padding elements so size should be at least the same size as
@@ -432,7 +456,7 @@ MDNode *generateSpecConstantMetadata(const Module &M, StringRef SymbolicID,
432
456
assert (IDs.size () == 1 &&
433
457
" There must be a single ID for emulated spec constant" );
434
458
MDOps.push_back (ConstantAsMetadata::get (
435
- Constant::getIntegerValue (Int32Ty, APInt (32 , IDs[0 ]))));
459
+ Constant::getIntegerValue (Int32Ty, APInt (32 , IDs[0 ]. ID ))));
436
460
// Second element is always zero here
437
461
MDOps.push_back (ConstantAsMetadata::get (
438
462
Constant::getIntegerValue (Int32Ty, APInt (32 , 0 ))));
@@ -519,14 +543,9 @@ Instruction *emitSpecConstant(unsigned NumericID, Type *Ty,
519
543
return emitCall (Ty, SPIRV_GET_SPEC_CONST_VAL, Args, InsertBefore);
520
544
}
521
545
522
- Instruction *emitSpecConstantComposite (Type *Ty,
523
- ArrayRef<Instruction *> Elements,
546
+ Instruction *emitSpecConstantComposite (Type *Ty, ArrayRef<Value *> Elements,
524
547
Instruction *InsertBefore) {
525
- SmallVector<Value *, 8 > Args (Elements.size ());
526
- for (unsigned I = 0 ; I < Elements.size (); ++I) {
527
- Args[I] = cast<Value>(Elements[I]);
528
- }
529
- return emitCall (Ty, SPIRV_GET_SPEC_CONST_COMPOSITE, Args, InsertBefore);
548
+ return emitCall (Ty, SPIRV_GET_SPEC_CONST_COMPOSITE, Elements, InsertBefore);
530
549
}
531
550
532
551
// / For specified specialization constant type emits LLVM IR which is required
@@ -553,28 +572,46 @@ Instruction *emitSpecConstantComposite(Type *Ty,
553
572
// / composite (plus for the top-level composite). Also enumerates all
554
573
// / encountered scalars and assigns them IDs (or re-uses existing ones).
555
574
Instruction *emitSpecConstantRecursiveImpl (Type *Ty, Instruction *InsertBefore,
556
- SmallVectorImpl<unsigned > &IDs,
575
+ SmallVectorImpl<ID > &IDs,
557
576
unsigned &Index,
558
577
Constant *DefaultValue) {
559
578
if (!Ty->isArrayTy () && !Ty->isStructTy () && !Ty->isVectorTy ()) { // Scalar
560
579
if (Index >= IDs.size ()) {
561
580
// If it is a new specialization constant, we need to generate IDs for
562
581
// scalar elements, starting with the second one.
563
- IDs.push_back (IDs.back () + 1 );
582
+ assert (!isa_and_nonnull<UndefValue>(DefaultValue) &&
583
+ " All scalar values should be defined" );
584
+ IDs.push_back ({IDs.back ().ID + 1 , false });
564
585
}
565
- return emitSpecConstant (IDs[Index++], Ty, InsertBefore, DefaultValue);
586
+ return emitSpecConstant (IDs[Index++]. ID , Ty, InsertBefore, DefaultValue);
566
587
}
567
588
568
- SmallVector<Instruction *, 8 > Elements;
589
+ SmallVector<Value *, 8 > Elements;
590
+ auto HandleUndef = [&](Constant *Def) {
591
+ if (Index >= IDs.size ()) {
592
+ // If it is a new specialization constant, we need to generate IDs for
593
+ // the whole undef value.
594
+ IDs.push_back ({IDs.back ().ID + 1 , true });
595
+ }
596
+ Elements.push_back (Def);
597
+ };
569
598
auto LoopIteration = [&](Type *Ty, unsigned LocalIndex) {
570
599
// Select corresponding element of the default value if it was provided
571
600
Constant *Def =
572
601
DefaultValue ? DefaultValue->getAggregateElement (LocalIndex) : nullptr ;
573
- Elements.push_back (
574
- emitSpecConstantRecursiveImpl (Ty, InsertBefore, IDs, Index, Def));
602
+ if (isa_and_nonnull<UndefValue>(Def))
603
+ HandleUndef (Def);
604
+ else
605
+ Elements.push_back (
606
+ emitSpecConstantRecursiveImpl (Ty, InsertBefore, IDs, Index, Def));
575
607
};
576
608
577
- if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
609
+ if (isa_and_nonnull<UndefValue>(DefaultValue)) {
610
+ // If the default value is a composite and has the value 'undef', we should
611
+ // not generate a bunch of __spirv_SpecConstant for its elements but
612
+ // pass it into __spirv_SpecConstantComposite as is.
613
+ HandleUndef (DefaultValue);
614
+ } else if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
578
615
for (size_t I = 0 ; I < ArrTy->getNumElements (); ++I) {
579
616
LoopIteration (ArrTy->getElementType (), I);
580
617
}
@@ -596,7 +633,7 @@ Instruction *emitSpecConstantRecursiveImpl(Type *Ty, Instruction *InsertBefore,
596
633
597
634
// / Wrapper intended to hide IsFirstElement argument from the caller
598
635
Instruction *emitSpecConstantRecursive (Type *Ty, Instruction *InsertBefore,
599
- SmallVectorImpl<unsigned > &IDs,
636
+ SmallVectorImpl<ID > &IDs,
600
637
Constant *DefaultValue) {
601
638
unsigned Index = 0 ;
602
639
return emitSpecConstantRecursiveImpl (Ty, InsertBefore, IDs, Index,
@@ -607,9 +644,9 @@ Instruction *emitSpecConstantRecursive(Type *Ty, Instruction *InsertBefore,
607
644
608
645
PreservedAnalyses SpecConstantsPass::run (Module &M,
609
646
ModuleAnalysisManager &MAM) {
610
- unsigned NextID = 0 ;
647
+ ID NextID = { 0 , false } ;
611
648
unsigned NextOffset = 0 ;
612
- StringMap<SmallVector<unsigned , 1 >> IDMap;
649
+ StringMap<SmallVector<ID , 1 >> IDMap;
613
650
StringMap<unsigned > OffsetMap;
614
651
MapVector<StringRef, MDNode *> SCMetadata;
615
652
SmallVector<MDNode *, 4 > DefaultsMetadata;
@@ -690,9 +727,8 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
690
727
if (SetValAtRT) {
691
728
// 2. Spec constant value will be set at run time - then add the literal
692
729
// to a "spec const string literal ID" -> "vector of integer IDs" map,
693
- // uniquing the integer IDs if this is a new literal
694
- auto Ins =
695
- IDMap.insert (std::make_pair (SymID, SmallVector<unsigned , 1 >{}));
730
+ // making the integer IDs unique if this is a new literal
731
+ auto Ins = IDMap.insert (std::make_pair (SymID, SmallVector<ID, 1 >{}));
696
732
IsNewSpecConstant = Ins.second ;
697
733
auto &IDs = Ins.first ->second ;
698
734
if (IsNewSpecConstant) {
@@ -708,7 +744,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
708
744
// emitSpecConstantRecursive might emit more than one spec constant
709
745
// (because of composite types) and therefore, we need to adjust
710
746
// NextID according to the actual amount of emitted spec constants.
711
- NextID += IDs.size ();
747
+ NextID. ID += IDs.size ();
712
748
713
749
// Generate necessary metadata which later will be pulled by
714
750
// sycl-post-link and transformed into device image properties
@@ -740,7 +776,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
740
776
SCMetadata[SymID] = generateSpecConstantMetadata (
741
777
M, SymID, SCTy, NextID, /* is native spec constant */ false );
742
778
743
- ++NextID;
779
+ ++NextID. ID ;
744
780
NextOffset += Size;
745
781
}
746
782
0 commit comments