@@ -610,6 +610,115 @@ Instruction *emitSpecConstantRecursive(Type *Ty, Instruction *InsertBefore,
610
610
DefaultValue);
611
611
}
612
612
613
+ // / Function creates load instruction from the given Buffer by the given Offset.
614
+ // / Function returns the value of load instruction.
615
+ Value *createLoadFromBuffer (CallInst *InsertBefore, Value *Buffer,
616
+ size_t Offset, Type *SCType) {
617
+ LLVMContext &C = InsertBefore->getContext ();
618
+ Type *Int8Ty = Type::getInt8Ty (C);
619
+ Type *Int32Ty = Type::getInt32Ty (C);
620
+ GetElementPtrInst *GEP = GetElementPtrInst::Create (
621
+ Int8Ty, Buffer, {ConstantInt::get (Int32Ty, Offset, false )}, " gep" ,
622
+ InsertBefore);
623
+
624
+ Instruction *BitCast = nullptr ;
625
+ if (SCType->isIntegerTy (1 )) // No bitcast to i1 before load
626
+ BitCast = GEP;
627
+ else
628
+ BitCast =
629
+ new BitCastInst (GEP, PointerType::get (SCType, GEP->getAddressSpace ()),
630
+ " bc" , InsertBefore);
631
+
632
+ // When we encounter i1 spec constant, we still load the whole byte
633
+ Value *Load = new LoadInst (SCType->isIntegerTy (1 ) ? Int8Ty : SCType, BitCast,
634
+ " load" , InsertBefore);
635
+ if (SCType->isIntegerTy (1 )) // trunc back to i1 if necessary
636
+ Load = CastInst::CreateIntegerCast (Load, SCType, /* IsSigned */ false ,
637
+ " tobool" , InsertBefore);
638
+
639
+ return Load;
640
+ }
641
+
642
+ // / Function tries to dig out the initializer from the given CallInst to
643
+ // / SpecConst function. ArgIndex is the expected index of the function operand
644
+ // / leading to the initializer.
645
+ // /
646
+ // / Examples:
647
+ // / 1)
648
+ // / %"spec_id" = type { i32 }
649
+ // / @value = internal addrspace(1) constant %"spec_id" { i32 123 }, align 4
650
+ // / call spir_func i32 @sycl_getScalar2020SpecConst(%1, @value, %2)
651
+ // /
652
+ // / 2)
653
+ // / %"spec_id" = type { %A }
654
+ // / %A = type { i32 }
655
+ // / @value = constant %"spec_id" { %A { i32 1 } }, align 4
656
+ // / call spir_func void @getCompositeSpecConst(%1, %2, @value, %3)
657
+ Constant *getSpecConstInitializerFromCI (CallInst *CI, unsigned ArgIndex) {
658
+ auto *GV =
659
+ cast<GlobalVariable>(CI->getArgOperand (ArgIndex)->stripPointerCasts ());
660
+
661
+ // Go through global variable if the argument was not null.
662
+ assert (GV->hasInitializer () && " GV is expected to have initializer" );
663
+ Constant *Initializer = GV->getInitializer ();
664
+ assert ((isa<ConstantAggregate>(Initializer) || Initializer->isZeroValue ()) &&
665
+ " expected specialization_id instance" );
666
+ // specialization_id structure contains a single field which is the
667
+ // default value of corresponding specialization constant.
668
+ return Initializer->getAggregateElement (0u );
669
+ }
670
+
671
+ // / Function replaces last Metadata node in the given vector with new
672
+ // / node which contains given Padding.
673
+ void updatePaddingInLastMDNode (LLVMContext &Ctx,
674
+ MapVector<StringRef, MDNode *> &SCMetadata,
675
+ unsigned Padding) {
676
+ // The spec constant map can't be empty as the first offset is 0
677
+ // and so it can't be misaligned.
678
+ assert (!SCMetadata.empty () && " Cannot add padding to first spec constant" );
679
+
680
+ // To communicate the padding to the runtime, update the metadata
681
+ // node of the previous spec constant to append a padding node. It
682
+ // can't be added in front of the current spec constant, as doing
683
+ // so would require the spec constant node to have a non-zero
684
+ // CompositeOffset which breaks accessing it in the runtime.
685
+ auto Last = SCMetadata.back ();
686
+
687
+ // Emulated spec constants don't use composite so should
688
+ // always be formatted as (SymID, ID, Offset, Size), except when
689
+ // they include padding, but since padding is added at insertion
690
+ // of the next element, the last element of the map can never be
691
+ // padded.
692
+ assert (Last.second ->getNumOperands () == 4 &&
693
+ " Incorrect emulated spec constant format" );
694
+
695
+ Type *Int32Ty = Type::getInt32Ty (Ctx);
696
+ SmallVector<Metadata *, 16 > MDOps;
697
+
698
+ // Copy the existing metadata.
699
+ MDOps.push_back (Last.second ->getOperand (0 ));
700
+ MDOps.push_back (Last.second ->getOperand (1 ));
701
+ MDOps.push_back (Last.second ->getOperand (2 ));
702
+ auto &SizeOp = Last.second ->getOperand (3 );
703
+ MDOps.push_back (SizeOp);
704
+
705
+ // Extract the size of the previous node to use as CompositeOffset
706
+ // for the padding node.
707
+ auto PrevSize = mdconst::extract<ConstantInt>(SizeOp)->getValue ();
708
+
709
+ // The max value is a magic value used for padding that the
710
+ // runtime knows to skip.
711
+ MDOps.push_back (ConstantAsMetadata::get (Constant::getIntegerValue (
712
+ Int32Ty, APInt (32 , std::numeric_limits<unsigned >::max ()))));
713
+ MDOps.push_back (
714
+ ConstantAsMetadata::get (Constant::getIntegerValue (Int32Ty, PrevSize)));
715
+ MDOps.push_back (ConstantAsMetadata::get (
716
+ Constant::getIntegerValue (Int32Ty, APInt (32 , Padding))));
717
+
718
+ // Replace the last metadata node with the node including the padding.
719
+ SCMetadata[Last.first ] = MDNode::get (Ctx, MDOps);
720
+ }
721
+
613
722
} // namespace
614
723
615
724
PreservedAnalyses SpecConstantsPass::run (Module &M,
@@ -627,6 +736,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
627
736
// setting (see below).
628
737
bool IRModified = false ;
629
738
739
+ LLVMContext &Ctx = M.getContext ();
630
740
for (Function &F : M) {
631
741
if (!F.isDeclaration ())
632
742
continue ;
@@ -665,23 +775,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
665
775
StringRef SymID = getStringLiteralArg (CI, NameArgNo, DelInsts);
666
776
Value *Replacement = nullptr ;
667
777
668
- Constant *DefaultValue = nullptr ;
669
- // There is a mechanism to specify the default value in SYCL 2020.
670
- // It is stored as an initializer of a global variable referenced by
671
- // the second argument of the intrinsic.
672
- auto *GV = dyn_cast<GlobalVariable>(
673
- CI->getArgOperand (NameArgNo + 1 )->stripPointerCasts ());
674
- // Go through global variable if the second argument was not null.
675
- if (GV) {
676
- assert (GV->hasInitializer () && " expected initializer" );
677
- auto *Initializer = GV->getInitializer ();
678
- assert ((isa<ConstantAggregate>(Initializer) ||
679
- Initializer->isZeroValue ()) &&
680
- " expected specialization_id instance" );
681
- // specialization_id structure contains a single field which is the
682
- // default value of corresponding specialization constant.
683
- DefaultValue = Initializer->getAggregateElement (0u );
684
- }
778
+ Constant *DefaultValue = getSpecConstInitializerFromCI (CI, NameArgNo + 1 );
685
779
686
780
bool IsNewSpecConstant = false ;
687
781
unsigned Padding = 0 ;
@@ -743,54 +837,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
743
837
OffsetMap[SymID] = NextOffset;
744
838
745
839
assert (CurrentOffset % Align == 0 && " Alignment calculation error" );
746
-
747
- // The spec constant map can't be empty as the first offset is 0
748
- // and so it can't be misaligned.
749
- assert (!SCMetadata.empty () &&
750
- " Cannot add padding to first spec constant" );
751
-
752
- // To communicate the padding to the runtime, update the metadata
753
- // node of the previous spec constant to append a padding node. It
754
- // can't be added in front of the current spec constant, as doing
755
- // so would require the spec constant node to have a non-zero
756
- // CompositeOffset which breaks accessing it in the runtime.
757
- auto Prev = SCMetadata.back ();
758
-
759
- // Emulated spec constants don't use composite so should
760
- // always be formatted as (SymID, ID, Offset, Size), except when
761
- // they include padding, but since padding is added at insertion
762
- // of the next element, the last element of the map can never be
763
- // padded.
764
- assert (Prev.second ->getNumOperands () == 4 &&
765
- " Incorrect emulated spec constant format" );
766
-
767
- LLVMContext &Ctx = M.getContext ();
768
- auto *Int32Ty = Type::getInt32Ty (Ctx);
769
- SmallVector<Metadata *, 16 > MDOps;
770
-
771
- // Copy the existing metadata.
772
- MDOps.push_back (Prev.second ->getOperand (0 ));
773
- MDOps.push_back (Prev.second ->getOperand (1 ));
774
- MDOps.push_back (Prev.second ->getOperand (2 ));
775
- auto &SizeOp = Prev.second ->getOperand (3 );
776
- MDOps.push_back (SizeOp);
777
-
778
- // Extract the size of the previous node to use as CompositeOffset
779
- // for the padding node.
780
- auto PrevSize = mdconst::extract<ConstantInt>(SizeOp)->getValue ();
781
-
782
- // The max value is a magic value used for padding that the
783
- // runtime knows to skip.
784
- MDOps.push_back (ConstantAsMetadata::get (Constant::getIntegerValue (
785
- Int32Ty, APInt (32 , std::numeric_limits<unsigned >::max ()))));
786
- MDOps.push_back (ConstantAsMetadata::get (
787
- Constant::getIntegerValue (Int32Ty, PrevSize)));
788
- MDOps.push_back (ConstantAsMetadata::get (
789
- Constant::getIntegerValue (Int32Ty, APInt (32 , Padding))));
790
-
791
- // Replace previous metadata node with the node including the
792
- // padding.
793
- SCMetadata[Prev.first ] = MDNode::get (Ctx, MDOps);
840
+ updatePaddingInLastMDNode (Ctx, SCMetadata, Padding);
794
841
}
795
842
796
843
SCMetadata[SymID] = generateSpecConstantMetadata (
@@ -800,31 +847,12 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
800
847
NextOffset += Size;
801
848
}
802
849
803
- Type *Int8Ty = Type::getInt8Ty (CI->getContext ());
804
- Type *Int32Ty = Type::getInt32Ty (CI->getContext ());
805
- GetElementPtrInst *GEP = GetElementPtrInst::Create (
806
- Int8Ty, RTBuffer, {ConstantInt::get (Int32Ty, CurrentOffset, false )},
807
- " gep" , CI);
808
-
809
- Instruction *BitCast = nullptr ;
810
- if (SCTy->isIntegerTy (1 )) // No bitcast to i1 before load
811
- BitCast = GEP;
812
- else
813
- BitCast = new BitCastInst (
814
- GEP, PointerType::get (SCTy, GEP->getAddressSpace ()), " bc" , CI);
815
-
816
- // When we encounter i1 spec constant, we still load the whole byte
817
- Replacement = new LoadInst (SCTy->isIntegerTy (1 ) ? Int8Ty : SCTy,
818
- BitCast, " load" , CI);
819
- if (SCTy->isIntegerTy (1 )) // trunc back to i1 if necessary
820
- Replacement = CastInst::CreateIntegerCast (
821
- Replacement, SCTy, /* IsSigned */ false , " tobool" , CI);
850
+ Replacement = createLoadFromBuffer (CI, RTBuffer, CurrentOffset, SCTy);
822
851
}
823
852
824
- if (IsNewSpecConstant && DefaultValue ) {
853
+ if (IsNewSpecConstant) {
825
854
if (Padding != 0 ) {
826
855
// Initialize the padding with null data
827
- LLVMContext &Ctx = DefaultValue->getContext ();
828
856
auto PadTy = ArrayType::get (Type::getInt8Ty (Ctx), Padding);
829
857
DefaultsMetadata.push_back (MDNode::get (
830
858
Ctx,
0 commit comments