@@ -749,6 +749,135 @@ SPIRVToLLVM::getMetadataFromNameAndParameter(std::string Name,
749
749
return llvm::MDNode::get (*Context, Metadata);
750
750
}
751
751
752
+ class IVDepMetadataEmitter {
753
+ public:
754
+ using PointerSafeLenMapTy = std::map<Value *, unsigned >;
755
+ static void emit (LLVMContext *Context, const Loop *LoopObj,
756
+ const PointerSafeLenMapTy &PointerSafeLenMap,
757
+ std::vector<llvm::Metadata *> &Metadata) {
758
+ if (LoopsEmitted.contains (LoopObj))
759
+ return ;
760
+ const auto ArrayGEPMap = mapArrayToGEPs (LoopObj, PointerSafeLenMap);
761
+ emitMetadata (Context, ArrayGEPMap, PointerSafeLenMap, Metadata);
762
+ LoopsEmitted.insert (LoopObj);
763
+ }
764
+
765
+ private:
766
+ static llvm::DenseSet<const Loop *> LoopsEmitted;
767
+
768
+ using ArrayGEPMapTy = std::map<Value *, std::vector<GetElementPtrInst *>>;
769
+ // A single run over the loop to retrieve all GetElementPtr instructions
770
+ // that access relevant array variables
771
+ static ArrayGEPMapTy
772
+ mapArrayToGEPs (const Loop *LoopObj,
773
+ const PointerSafeLenMapTy &PointerSafeLenMap) {
774
+ ArrayGEPMapTy ArrayGEPMap;
775
+ for (const auto &BB : LoopObj->blocks ()) {
776
+ for (Instruction &I : *BB) {
777
+ auto *GEP = dyn_cast<GetElementPtrInst>(&I);
778
+ if (!GEP)
779
+ continue ;
780
+
781
+ Value *AccessedPointer = GEP->getPointerOperand ();
782
+ if (auto *LI = dyn_cast<LoadInst>(AccessedPointer))
783
+ AccessedPointer = LI->getPointerOperand ();
784
+ auto PointerSafeLenIt = PointerSafeLenMap.find (AccessedPointer);
785
+ if (PointerSafeLenIt != PointerSafeLenMap.end ()) {
786
+ ArrayGEPMap[AccessedPointer].push_back (GEP);
787
+ }
788
+ }
789
+ }
790
+ return ArrayGEPMap;
791
+ }
792
+
793
+ // Create index group metadata nodes - one per each of the array
794
+ // variables. Mark each GEP accessing a particular array variable
795
+ // into a corresponding index group
796
+ static void emitMetadata (LLVMContext *Context,
797
+ const ArrayGEPMapTy &ArrayGEPMap,
798
+ const PointerSafeLenMapTy &PointerSafeLenMap,
799
+ std::vector<llvm::Metadata *> &Metadata) {
800
+ using SafeLenIdxGroupMapTy = std::map<unsigned , SmallSet<MDNode *, 4 >>;
801
+ SafeLenIdxGroupMapTy SafeLenIdxGroupMap;
802
+ // Whenever a kernel closure field access is pointed to instead of
803
+ // an array/pointer variable, ensure that all GEPs to that memory
804
+ // share the same index group by hashing the newly added index groups.
805
+ // "Memory offset info" represents a handle to the whole closure block
806
+ // + an integer offset to a particular captured parameter.
807
+ using MemoryOffsetInfo = std::pair<Value *, unsigned >;
808
+ std::map<MemoryOffsetInfo, MDNode *> OffsetIdxGroupMap;
809
+
810
+ for (auto &ArrayGEPIt : ArrayGEPMap) {
811
+ MDNode *CurrentDepthIdxGroup = nullptr ;
812
+ if (auto *PrecedingGEP = dyn_cast<GetElementPtrInst>(ArrayGEPIt.first )) {
813
+ Value *ClosureFieldPointer = PrecedingGEP->getPointerOperand ();
814
+ unsigned Offset =
815
+ cast<ConstantInt>(PrecedingGEP->getOperand (2 ))->getZExtValue ();
816
+ MemoryOffsetInfo Info{ClosureFieldPointer, Offset};
817
+ auto OffsetIdxGroupIt = OffsetIdxGroupMap.find (Info);
818
+ if (OffsetIdxGroupIt == OffsetIdxGroupMap.end ()) {
819
+ // This is the first GEP encountered for this closure field.
820
+ // Emit a distinct index group that will be referenced from
821
+ // llvm.loop.parallel_access_indices metadata; hash the new
822
+ // MDNode for future accesses to the same memory.
823
+ CurrentDepthIdxGroup = llvm::MDNode::getDistinct (*Context, None);
824
+ OffsetIdxGroupMap.emplace (Info, CurrentDepthIdxGroup);
825
+ } else {
826
+ // Previous accesses to that field have already been indexed,
827
+ // just use the already-existing metadata.
828
+ CurrentDepthIdxGroup = OffsetIdxGroupIt->second ;
829
+ }
830
+ } else /* Regular kernel-scope array/pointer variable */ {
831
+ // Emit a distinct index group that will be referenced from
832
+ // llvm.loop.parallel_access_indices metadata
833
+ CurrentDepthIdxGroup = llvm::MDNode::getDistinct (*Context, None);
834
+ }
835
+
836
+ unsigned SafeLen = PointerSafeLenMap.find (ArrayGEPIt.first )->second ;
837
+ SafeLenIdxGroupMap[SafeLen].insert (CurrentDepthIdxGroup);
838
+ for (auto *GEP : ArrayGEPIt.second ) {
839
+ StringRef IdxGroupMDName (" llvm.index.group" );
840
+ llvm::MDNode *PreviousIdxGroup = GEP->getMetadata (IdxGroupMDName);
841
+ if (!PreviousIdxGroup) {
842
+ GEP->setMetadata (IdxGroupMDName, CurrentDepthIdxGroup);
843
+ continue ;
844
+ }
845
+
846
+ // If we're dealing with an embedded loop, it may be the case
847
+ // that GEP instructions for some of the arrays were already
848
+ // marked by the algorithm when it went over the outer level loops.
849
+ // In order to retain the IVDep information for each "loop
850
+ // dimension", we will mark such GEP's into a separate joined node
851
+ // that will refer to the previous levels' index groups AND to the
852
+ // index group specific to the current loop.
853
+ std::vector<llvm::Metadata *> CurrentDepthOperands (
854
+ PreviousIdxGroup->op_begin (), PreviousIdxGroup->op_end ());
855
+ if (CurrentDepthOperands.empty ())
856
+ CurrentDepthOperands.push_back (PreviousIdxGroup);
857
+ CurrentDepthOperands.push_back (CurrentDepthIdxGroup);
858
+ auto *JointIdxGroup = llvm::MDNode::get (*Context, CurrentDepthOperands);
859
+ GEP->setMetadata (IdxGroupMDName, JointIdxGroup);
860
+ }
861
+ }
862
+
863
+ for (auto &SafeLenIdxGroupIt : SafeLenIdxGroupMap) {
864
+ auto *Name = MDString::get (*Context, " llvm.loop.parallel_access_indices" );
865
+ unsigned SafeLenValue = SafeLenIdxGroupIt.first ;
866
+ llvm::Metadata *SafeLenMDOp =
867
+ SafeLenValue ? ConstantAsMetadata::get (ConstantInt::get (
868
+ Type::getInt32Ty (*Context), SafeLenValue))
869
+ : nullptr ;
870
+ std::vector<llvm::Metadata *> Parameters{Name};
871
+ for (auto *Node : SafeLenIdxGroupIt.second )
872
+ Parameters.push_back (Node);
873
+ if (SafeLenMDOp)
874
+ Parameters.push_back (SafeLenMDOp);
875
+ Metadata.push_back (llvm::MDNode::get (*Context, Parameters));
876
+ }
877
+ }
878
+ };
879
+ llvm::DenseSet<const Loop *> IVDepMetadataEmitter::LoopsEmitted;
880
+
752
881
template <typename LoopInstType>
753
882
void SPIRVToLLVM::setLLVMLoopMetadata (const LoopInstType *LM,
754
883
const Loop *LoopObj) {
@@ -843,7 +972,7 @@ void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM,
843
972
}
844
973
if (LC & LoopControlDependencyArrayINTELMask) {
845
974
// Collect pointer variable <-> safelen information
846
- std::map<Value *, unsigned > PointerSflnMap ;
975
+ IVDepMetadataEmitter::PointerSafeLenMapTy PointerSafeLenMap ;
847
976
unsigned NumOperandPairs = LoopControlParameters[NumParam];
848
977
unsigned OperandsEndIndex = NumParam + NumOperandPairs * 2 ;
849
978
assert (OperandsEndIndex <= LoopControlParameters.size () &&
@@ -852,109 +981,13 @@ void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM,
852
981
while (NumParam < OperandsEndIndex) {
853
982
SPIRVId ArraySPIRVId = LoopControlParameters[++NumParam];
854
983
Value *PointerVar = ValueMap[M->getValue (ArraySPIRVId)];
855
- unsigned Safelen = LoopControlParameters[++NumParam];
856
- PointerSflnMap.emplace (PointerVar, Safelen);
857
- }
858
-
859
- // A single run over the loop to retrieve all GetElementPtr instructions
860
- // that access relevant array variables
861
- std::map<Value *, std::vector<GetElementPtrInst *>> ArrayGEPMap;
862
- for (const auto &BB : LoopObj->blocks ()) {
863
- for (Instruction &I : *BB) {
864
- auto *GEP = dyn_cast<GetElementPtrInst>(&I);
865
- if (!GEP)
866
- continue ;
867
-
868
- Value *AccessedPointer = GEP->getPointerOperand ();
869
- if (auto *LI = dyn_cast<LoadInst>(AccessedPointer))
870
- AccessedPointer = LI->getPointerOperand ();
871
- auto PointerSflnIt = PointerSflnMap.find (AccessedPointer);
872
- if (PointerSflnIt != PointerSflnMap.end ()) {
873
- ArrayGEPMap[AccessedPointer].push_back (GEP);
874
- }
875
- }
876
- }
877
-
878
- // Create index group metadata nodes - one per each of the array
879
- // variables. Mark each GEP accessing a particular array variable
880
- // into a corresponding index group
881
- std::map<unsigned , SmallSet<MDNode *, 4 >> SafelenIdxGroupMap;
882
- // Whenever a kernel closure field access is pointed to instead of
883
- // an array/pointer variable, ensure that all GEPs to that memory
884
- // share the same index group by hashing the newly added index groups.
885
- // "Memory offset info" represents a handle to the whole closure block
886
- // + an integer offset to a particular captured parameter.
887
- using MemoryOffsetInfo = std::pair<Value *, unsigned >;
888
- std::map<MemoryOffsetInfo, MDNode *> OffsetIdxGroupMap;
889
-
890
- for (auto &ArrayGEPIt : ArrayGEPMap) {
891
- MDNode *CurrentDepthIdxGroup = nullptr ;
892
- if (auto *PrecedingGEP = dyn_cast<GetElementPtrInst>(ArrayGEPIt.first )) {
893
- Value *ClosureFieldPointer = PrecedingGEP->getPointerOperand ();
894
- unsigned Offset =
895
- cast<ConstantInt>(PrecedingGEP->getOperand (2 ))->getZExtValue ();
896
- MemoryOffsetInfo Info{ClosureFieldPointer, Offset};
897
- auto OffsetIdxGroupIt = OffsetIdxGroupMap.find (Info);
898
- if (OffsetIdxGroupIt == OffsetIdxGroupMap.end ()) {
899
- // This is the first GEP encountered for this closure field.
900
- // Emit a distinct index group that will be referenced from
901
- // llvm.loop.parallel_access_indices metadata; hash the new
902
- // MDNode for future accesses to the same memory.
903
- CurrentDepthIdxGroup = llvm::MDNode::getDistinct (*Context, None);
904
- OffsetIdxGroupMap.emplace (Info, CurrentDepthIdxGroup);
905
- } else {
906
- // Previous accesses to that field have already been indexed,
907
- // just use the already-existing metadata.
908
- CurrentDepthIdxGroup = OffsetIdxGroupIt->second ;
909
- }
910
- } else /* Regular kernel-scope array/pointer variable */ {
911
- // Emit a distinct index group that will be referenced from
912
- // llvm.loop.parallel_access_indices metadata
913
- CurrentDepthIdxGroup = llvm::MDNode::getDistinct (*Context, None);
914
- }
915
-
916
- unsigned Safelen = PointerSflnMap.find (ArrayGEPIt.first )->second ;
917
- SafelenIdxGroupMap[Safelen].insert (CurrentDepthIdxGroup);
918
- for (auto *GEP : ArrayGEPIt.second ) {
919
- StringRef IdxGroupMDName (" llvm.index.group" );
920
- llvm::MDNode *PreviousIdxGroup = GEP->getMetadata (IdxGroupMDName);
921
- if (!PreviousIdxGroup) {
922
- GEP->setMetadata (IdxGroupMDName, CurrentDepthIdxGroup);
923
- continue ;
924
- }
925
-
926
- // If we're dealing with an embedded loop, it may be the case
927
- // that GEP instructions for some of the arrays were already
928
- // marked by the algorithm when it went over the outer level loops.
929
- // In order to retain the IVDep information for each "loop
930
- // dimension", we will mark such GEP's into a separate joined node
931
- // that will refer to the previous levels' index groups AND to the
932
- // index group specific to the current loop.
933
- std::vector<llvm::Metadata *> CurrentDepthOperands (
934
- PreviousIdxGroup->op_begin (), PreviousIdxGroup->op_end ());
935
- if (CurrentDepthOperands.empty ())
936
- CurrentDepthOperands.push_back (PreviousIdxGroup);
937
- CurrentDepthOperands.push_back (CurrentDepthIdxGroup);
938
- auto *JointIdxGroup = llvm::MDNode::get (*Context, CurrentDepthOperands);
939
- GEP->setMetadata (IdxGroupMDName, JointIdxGroup);
940
- }
941
- }
942
-
943
- for (auto &SflnIdxGroupIt : SafelenIdxGroupMap) {
944
- auto *Name = MDString::get (*Context, " llvm.loop.parallel_access_indices" );
945
- unsigned SflnValue = SflnIdxGroupIt.first ;
946
- llvm::Metadata *SafelenMDOp =
947
- SflnValue ? ConstantAsMetadata::get (ConstantInt::get (
948
- Type::getInt32Ty (*Context), SflnValue))
949
- : nullptr ;
950
- std::vector<llvm::Metadata *> Parameters{Name};
951
- for (auto *Node : SflnIdxGroupIt.second )
952
- Parameters.push_back (Node);
953
- if (SafelenMDOp)
954
- Parameters.push_back (SafelenMDOp);
955
- Metadata.push_back (llvm::MDNode::get (*Context, Parameters));
984
+ unsigned SafeLen = LoopControlParameters[++NumParam];
985
+ PointerSafeLenMap.emplace (PointerVar, SafeLen);
956
986
}
987
+ IVDepMetadataEmitter::emit (Context, LoopObj, PointerSafeLenMap, Metadata);
957
988
++NumParam;
989
+ assert (NumParam <= LoopControlParameters.size () &&
990
+ " Missing loop control parameter!" );
958
991
}
959
992
if (LC & LoopControlPipelineEnableINTELMask) {
960
993
Metadata.push_back (llvm::MDNode::get (
0 commit comments