1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #include "SpirMetaDataApi.h"
10 #include "Probe/Assertion.h"
11 
12 namespace IGC {
13     namespace SPIRMD
14     {
15         static bool isNamedNode(const llvm::Metadata*, const char*);
16 
17         ///
18         // Ctor - loads the VectorTypeHintMetaData from the given metadata node
19         //
VectorTypeHintMetaData(const llvm::MDNode * pNode,bool hasId)20         VectorTypeHintMetaData::VectorTypeHintMetaData(const llvm::MDNode* pNode, bool hasId) :
21             _Mybase(pNode, hasId),
22             m_VecType(getVecTypeNode(pNode)),
23             m_Sign(getSignNode(pNode)),
24             m_pNode(pNode)
25         {}
26 
27         ///
28         // Default Ctor - creates the empty, not named VectorTypeHintMetaData object
29         //
VectorTypeHintMetaData()30         VectorTypeHintMetaData::VectorTypeHintMetaData() :
31             m_pNode(NULL)
32         {}
33 
34         ///
35         // Ctor - creates the empty, named VectorTypeHintMetaData object
36         //
VectorTypeHintMetaData(const char * name)37         VectorTypeHintMetaData::VectorTypeHintMetaData(const char* name) :
38             _Mybase(name),
39             m_pNode(NULL)
40         {}
41 
hasValue() const42         bool VectorTypeHintMetaData::hasValue() const
43         {
44             if (m_VecType.hasValue())
45             {
46                 return true;
47             }
48 
49 
50             if (m_Sign.hasValue())
51             {
52                 return true;
53             }
54             return NULL != m_pNode || dirty();
55         }
56 
57         ///
58         // Returns true if any of the VectorTypeHintMetaData`s members has changed
dirty() const59         bool VectorTypeHintMetaData::dirty() const
60         {
61             if (m_VecType.dirty())
62             {
63                 return true;
64             }
65             if (m_Sign.dirty())
66             {
67                 return true;
68             }
69             return false;
70         }
71 
72         ///
73         // Discards the changes done to the VectorTypeHintMetaData instance
discardChanges()74         void VectorTypeHintMetaData::discardChanges()
75         {
76             m_VecType.discardChanges();
77             m_Sign.discardChanges();
78         }
79 
80         ///
81         // Generates the new MDNode hierarchy for the given structure
generateNode(llvm::LLVMContext & context) const82         llvm::Metadata* VectorTypeHintMetaData::generateNode(llvm::LLVMContext& context) const
83         {
84             llvm::SmallVector<llvm::Metadata*, 5> args;
85 
86             llvm::Metadata* pIDNode = _Mybase::generateNode(context);
87             if (NULL != pIDNode)
88             {
89                 args.push_back(pIDNode);
90             }
91 
92             args.push_back(m_VecType.generateNode(context));
93             args.push_back(m_Sign.generateNode(context));
94 
95             return llvm::MDNode::get(context, args);
96         }
97 
98         ///
99         // Saves the structure changes to the given MDNode
save(llvm::LLVMContext & context,llvm::MDNode * pNode) const100         void VectorTypeHintMetaData::save(llvm::LLVMContext& context, llvm::MDNode* pNode) const
101         {
102             IGC_ASSERT_MESSAGE(nullptr != pNode, "The target node should be valid pointer");
103 
104             // we assume that underlying metadata node has not changed under our foot
105             if (pNode == m_pNode && !dirty())
106             {
107                 return;
108             }
109 #if 0
110             // check that we could save the new information to the given node without regenerating it
111             if (!compatibleWith(pNode))
112             {
113                 pNode->replaceAllUsesWith(generateNode(context));
114                 return;
115             }
116 #endif
117 
118             m_VecType.save(context, llvm::cast<llvm::MDNode>(getVecTypeNode(pNode)));
119             m_Sign.save(context, llvm::cast<llvm::MDNode>(getSignNode(pNode)));
120         }
121 
getVecTypeNode(const llvm::MDNode * pParentNode) const122         llvm::Metadata* VectorTypeHintMetaData::getVecTypeNode(const llvm::MDNode* pParentNode) const
123         {
124             if (!pParentNode)
125             {
126                 return NULL;
127             }
128 
129             unsigned int offset = _Mybase::getStartIndex();
130             return pParentNode->getOperand(0 + offset).get();
131         }
132 
getSignNode(const llvm::MDNode * pParentNode) const133         llvm::Metadata* VectorTypeHintMetaData::getSignNode(const llvm::MDNode* pParentNode) const
134         {
135             if (!pParentNode)
136             {
137                 return NULL;
138             }
139 
140             unsigned int offset = _Mybase::getStartIndex();
141             return pParentNode->getOperand(1 + offset).get();
142         }
143 
144         ///
145         // Ctor - loads the VersionMetaData from the given metadata node
146         //
VersionMetaData(const llvm::MDNode * pNode,bool hasId)147         VersionMetaData::VersionMetaData(const llvm::MDNode* pNode, bool hasId) :
148             _Mybase(pNode, hasId),
149             m_Major(getMajorNode(pNode)),
150             m_Minor(getMinorNode(pNode)),
151             m_pNode(pNode)
152         {}
153 
154         ///
155         // Default Ctor - creates the empty, not named VersionMetaData object
156         //
VersionMetaData()157         VersionMetaData::VersionMetaData() :
158             m_pNode(NULL)
159         {}
160 
161         ///
162         // Ctor - creates the empty, named VersionMetaData object
163         //
VersionMetaData(const char * name)164         VersionMetaData::VersionMetaData(const char* name) :
165             _Mybase(name),
166             m_pNode(NULL)
167         {}
168 
hasValue() const169         bool VersionMetaData::hasValue() const
170         {
171             if (m_Major.hasValue())
172             {
173                 return true;
174             }
175 
176 
177             if (m_Minor.hasValue())
178             {
179                 return true;
180             }
181             return NULL != m_pNode || dirty();
182         }
183 
184         ///
185         // Returns true if any of the VersionMetaData`s members has changed
dirty() const186         bool VersionMetaData::dirty() const
187         {
188             if (m_Major.dirty())
189             {
190                 return true;
191             }
192             if (m_Minor.dirty())
193             {
194                 return true;
195             }
196             return false;
197         }
198 
199         ///
200         // Discards the changes done to the VersionMetaData instance
discardChanges()201         void VersionMetaData::discardChanges()
202         {
203             m_Major.discardChanges();
204             m_Minor.discardChanges();
205         }
206 
207         ///
208         // Generates the new MDNode hierarchy for the given structure
generateNode(llvm::LLVMContext & context) const209         llvm::Metadata* VersionMetaData::generateNode(llvm::LLVMContext& context) const
210         {
211             llvm::SmallVector<llvm::Metadata*, 5> args;
212 
213             llvm::Metadata* pIDNode = _Mybase::generateNode(context);
214             if (NULL != pIDNode)
215             {
216                 args.push_back(pIDNode);
217             }
218 
219             args.push_back(m_Major.generateNode(context));
220             args.push_back(m_Minor.generateNode(context));
221 
222             return llvm::MDNode::get(context, args);
223         }
224 
225         ///
226         // Saves the structure changes to the given MDNode
save(llvm::LLVMContext & context,llvm::MDNode * pNode) const227         void VersionMetaData::save(llvm::LLVMContext& context, llvm::MDNode* pNode) const
228         {
229             IGC_ASSERT_MESSAGE(nullptr != pNode, "The target node should be valid pointer");
230 
231             // we assume that underlying metadata node has not changed under our foot
232             if (pNode == m_pNode && !dirty())
233             {
234                 return;
235             }
236 #if 0
237             // check that we could save the new information to the given node without regenerating it
238             if (!compatibleWith(pNode))
239             {
240                 pNode->replaceAllUsesWith(generateNode(context));
241                 return;
242             }
243 #endif
244 
245             m_Major.save(context, llvm::cast<llvm::MDNode>(getMajorNode(pNode)));
246             m_Minor.save(context, llvm::cast<llvm::MDNode>(getMinorNode(pNode)));
247         }
248 
getMajorNode(const llvm::MDNode * pParentNode) const249         llvm::Metadata* VersionMetaData::getMajorNode(const llvm::MDNode* pParentNode) const
250         {
251             if (!pParentNode)
252             {
253                 return NULL;
254             }
255 
256             unsigned int offset = _Mybase::getStartIndex();
257             return pParentNode->getOperand(0 + offset).get();
258         }
259 
getMinorNode(const llvm::MDNode * pParentNode) const260         llvm::Metadata* VersionMetaData::getMinorNode(const llvm::MDNode* pParentNode) const
261         {
262             if (!pParentNode)
263             {
264                 return NULL;
265             }
266 
267             unsigned int offset = _Mybase::getStartIndex();
268             return pParentNode->getOperand(1 + offset).get();
269         }
270 
271 
272 
273         ///
274         // Ctor - loads the WorkGroupDimensionsMetaData from the given metadata node
275         //
WorkGroupDimensionsMetaData(const llvm::MDNode * pNode,bool hasId)276         WorkGroupDimensionsMetaData::WorkGroupDimensionsMetaData(const llvm::MDNode* pNode, bool hasId) :
277             _Mybase(pNode, hasId),
278             m_XDim(getXDimNode(pNode)),
279             m_YDim(getYDimNode(pNode)),
280             m_ZDim(getZDimNode(pNode)),
281             m_pNode(pNode)
282         {}
283 
284         ///
285         // Default Ctor - creates the empty, not named WorkGroupDimensionsMetaData object
286         //
WorkGroupDimensionsMetaData()287         WorkGroupDimensionsMetaData::WorkGroupDimensionsMetaData() :
288             m_pNode(NULL)
289         {}
290 
291         ///
292         // Ctor - creates the empty, named WorkGroupDimensionsMetaData object
293         //
WorkGroupDimensionsMetaData(const char * name)294         WorkGroupDimensionsMetaData::WorkGroupDimensionsMetaData(const char* name) :
295             _Mybase(name),
296             m_pNode(NULL)
297         {}
298 
hasValue() const299         bool WorkGroupDimensionsMetaData::hasValue() const
300         {
301             if (m_XDim.hasValue())
302             {
303                 return true;
304             }
305 
306 
307             if (m_YDim.hasValue())
308             {
309                 return true;
310             }
311 
312 
313             if (m_ZDim.hasValue())
314             {
315                 return true;
316             }
317             return NULL != m_pNode || dirty();
318         }
319 
320         ///
321         // Returns true if any of the WorkGroupDimensionsMetaData`s members has changed
dirty() const322         bool WorkGroupDimensionsMetaData::dirty() const
323         {
324             if (m_XDim.dirty())
325             {
326                 return true;
327             }
328             if (m_YDim.dirty())
329             {
330                 return true;
331             }
332             if (m_ZDim.dirty())
333             {
334                 return true;
335             }
336             return false;
337         }
338 
339         ///
340         // Discards the changes done to the WorkGroupDimensionsMetaData instance
discardChanges()341         void WorkGroupDimensionsMetaData::discardChanges()
342         {
343             m_XDim.discardChanges();
344             m_YDim.discardChanges();
345             m_ZDim.discardChanges();
346         }
347 
348         ///
349         // Generates the new MDNode hierarchy for the given structure
generateNode(llvm::LLVMContext & context) const350         llvm::Metadata* WorkGroupDimensionsMetaData::generateNode(llvm::LLVMContext& context) const
351         {
352             llvm::SmallVector<llvm::Metadata*, 5> args;
353 
354             llvm::Metadata* pIDNode = _Mybase::generateNode(context);
355             if (NULL != pIDNode)
356             {
357                 args.push_back(pIDNode);
358             }
359 
360             args.push_back(m_XDim.generateNode(context));
361             args.push_back(m_YDim.generateNode(context));
362             args.push_back(m_ZDim.generateNode(context));
363 
364             return llvm::MDNode::get(context, args);
365         }
366 
367         ///
368         // Saves the structure changes to the given MDNode
save(llvm::LLVMContext & context,llvm::MDNode * pNode) const369         void WorkGroupDimensionsMetaData::save(llvm::LLVMContext& context, llvm::MDNode* pNode) const
370         {
371             IGC_ASSERT_MESSAGE(nullptr != pNode, "The target node should be valid pointer");
372 
373             // we assume that underlying metadata node has not changed under our foot
374             if (pNode == m_pNode && !dirty())
375             {
376                 return;
377             }
378 #if 0
379             // check that we could save the new information to the given node without regenerating it
380             if (!compatibleWith(pNode))
381             {
382                 pNode->replaceAllUsesWith(generateNode(context));
383                 return;
384             }
385 #endif
386 
387             m_XDim.save(context, llvm::cast<llvm::MDNode>(getXDimNode(pNode)));
388             m_YDim.save(context, llvm::cast<llvm::MDNode>(getYDimNode(pNode)));
389             m_ZDim.save(context, llvm::cast<llvm::MDNode>(getZDimNode(pNode)));
390         }
391 
getXDimNode(const llvm::MDNode * pParentNode) const392         llvm::Metadata* WorkGroupDimensionsMetaData::getXDimNode(const llvm::MDNode* pParentNode) const
393         {
394             if (!pParentNode)
395             {
396                 return NULL;
397             }
398 
399             unsigned int offset = _Mybase::getStartIndex();
400             return pParentNode->getOperand(0 + offset).get();
401         }
402 
getYDimNode(const llvm::MDNode * pParentNode) const403         llvm::Metadata* WorkGroupDimensionsMetaData::getYDimNode(const llvm::MDNode* pParentNode) const
404         {
405             if (!pParentNode)
406             {
407                 return NULL;
408             }
409 
410             unsigned int offset = _Mybase::getStartIndex();
411             return pParentNode->getOperand(1 + offset).get();
412         }
413 
getZDimNode(const llvm::MDNode * pParentNode) const414         llvm::Metadata* WorkGroupDimensionsMetaData::getZDimNode(const llvm::MDNode* pParentNode) const
415         {
416             if (!pParentNode)
417             {
418                 return NULL;
419             }
420 
421             unsigned int offset = _Mybase::getStartIndex();
422             return pParentNode->getOperand(2 + offset).get();
423         }
424 
425 
426 
427         ///
428         // Ctor - loads the SubGroupDimensionsMetaData from the given metadata node
429         //
SubGroupDimensionsMetaData(const llvm::MDNode * pNode,bool hasId)430         SubGroupDimensionsMetaData::SubGroupDimensionsMetaData(const llvm::MDNode* pNode, bool hasId) :
431             _Mybase(pNode, hasId),
432             m_SIMD_Size(getSIMD_SizeNode(pNode)),
433             m_pNode(pNode)
434         {}
435 
436         ///
437         // Default Ctor - creates the empty, not named SubGroupDimensionsMetaData object
438         //
SubGroupDimensionsMetaData()439         SubGroupDimensionsMetaData::SubGroupDimensionsMetaData() :
440             m_pNode(NULL)
441         {}
442 
443         ///
444         // Ctor - creates the empty, named SubGroupDimensionsMetaData object
445         //
SubGroupDimensionsMetaData(const char * name)446         SubGroupDimensionsMetaData::SubGroupDimensionsMetaData(const char* name) :
447             _Mybase(name),
448             m_pNode(NULL)
449         {}
450 
hasValue() const451         bool SubGroupDimensionsMetaData::hasValue() const
452         {
453             if (m_SIMD_Size.hasValue())
454             {
455                 return true;
456             }
457             return NULL != m_pNode || dirty();
458         }
459 
460         ///
461         // Returns true if any of the SubGroupDimensionsMetaData`s members has changed
dirty() const462         bool SubGroupDimensionsMetaData::dirty() const
463         {
464             if (m_SIMD_Size.dirty())
465             {
466                 return true;
467             }
468             return false;
469         }
470 
471         ///
472         // Discards the changes done to the SubGroupDimensionsMetaData instance
discardChanges()473         void SubGroupDimensionsMetaData::discardChanges()
474         {
475             m_SIMD_Size.discardChanges();
476         }
477 
478         ///
479         // Generates the new MDNode hierarchy for the given structure
generateNode(llvm::LLVMContext & context) const480         llvm::Metadata* SubGroupDimensionsMetaData::generateNode(llvm::LLVMContext& context) const
481         {
482             llvm::SmallVector<llvm::Metadata*, 5> args;
483 
484             llvm::Metadata* pIDNode = _Mybase::generateNode(context);
485             if (NULL != pIDNode)
486             {
487                 args.push_back(pIDNode);
488             }
489 
490             args.push_back(m_SIMD_Size.generateNode(context));
491 
492             return llvm::MDNode::get(context, args);
493         }
494 
495         ///
496         // Saves the structure changes to the given MDNode
save(llvm::LLVMContext & context,llvm::MDNode * pNode) const497         void SubGroupDimensionsMetaData::save(llvm::LLVMContext& context, llvm::MDNode* pNode) const
498         {
499             IGC_ASSERT_MESSAGE(nullptr != pNode, "The target node should be valid pointer");
500 
501             // we assume that underlying metadata node has not changed under our foot
502             if (pNode == m_pNode && !dirty())
503             {
504                 return;
505             }
506 #if 0
507             // check that we could save the new information to the given node without regenerating it
508             if (!compatibleWith(pNode))
509             {
510                 pNode->replaceAllUsesWith(generateNode(context));
511                 return;
512             }
513 #endif
514 
515             m_SIMD_Size.save(context, llvm::cast<llvm::MDNode>(getSIMD_SizeNode(pNode)));
516         }
517 
getSIMD_SizeNode(const llvm::MDNode * pParentNode) const518         llvm::Metadata* SubGroupDimensionsMetaData::getSIMD_SizeNode(const llvm::MDNode* pParentNode) const
519         {
520             if (!pParentNode)
521             {
522                 return NULL;
523             }
524 
525             unsigned int offset = _Mybase::getStartIndex();
526             return pParentNode->getOperand(0 + offset).get();
527         }
528 
529 
530         ///
531         // Ctor - loads the WorkgroupWalkOrderMetaData from the given metadata node
532         //
WorkgroupWalkOrderMetaData(const llvm::MDNode * pNode,bool hasId)533         WorkgroupWalkOrderMetaData::WorkgroupWalkOrderMetaData(const llvm::MDNode* pNode, bool hasId) :
534             _Mybase(pNode, hasId),
535             m_Dim0(getDim0Node(pNode)),
536             m_Dim1(getDim1Node(pNode)),
537             m_Dim2(getDim2Node(pNode)),
538             m_pNode(pNode)
539         {}
540 
541         ///
542         // Default Ctor - creates the empty, not named SubGroupSizeMetaData object
543         //
WorkgroupWalkOrderMetaData()544         WorkgroupWalkOrderMetaData::WorkgroupWalkOrderMetaData() :
545             m_pNode(NULL)
546         {}
547 
548         ///
549         // Ctor - creates the empty, named SubGroupSizeMetaData object
550         //
WorkgroupWalkOrderMetaData(const char * name)551         WorkgroupWalkOrderMetaData::WorkgroupWalkOrderMetaData(const char* name) :
552             _Mybase(name),
553             m_pNode(NULL)
554         {}
555 
hasValue() const556         bool WorkgroupWalkOrderMetaData::hasValue() const
557         {
558             if (m_Dim0.hasValue())
559             {
560                 return true;
561             }
562 
563             if (m_Dim1.hasValue())
564             {
565                 return true;
566             }
567 
568             if (m_Dim2.hasValue())
569             {
570                 return true;
571             }
572 
573             return NULL != m_pNode || dirty();
574         }
575 
576         ///
577         // Returns true if any of the SubGroupSizeMetaData`s members has changed
dirty() const578         bool WorkgroupWalkOrderMetaData::dirty() const
579         {
580             if (m_Dim0.dirty())
581             {
582                 return true;
583             }
584 
585             if (m_Dim1.dirty())
586             {
587                 return true;
588             }
589 
590             if (m_Dim2.dirty())
591             {
592                 return true;
593             }
594             return false;
595         }
596 
597         ///
598         // Discards the changes done to the SubGroupSizeMetaData instance
discardChanges()599         void WorkgroupWalkOrderMetaData::discardChanges()
600         {
601             m_Dim0.discardChanges();
602             m_Dim1.discardChanges();
603             m_Dim2.discardChanges();
604         }
605 
606         ///
607         // Generates the new MDNode hierarchy for the given structure
generateNode(llvm::LLVMContext & context) const608         llvm::Metadata* WorkgroupWalkOrderMetaData::generateNode(llvm::LLVMContext& context) const
609         {
610             llvm::SmallVector<llvm::Metadata*, 5> args;
611 
612             llvm::Metadata* pIDNode = _Mybase::generateNode(context);
613             if (NULL != pIDNode)
614             {
615                 args.push_back(pIDNode);
616             }
617 
618             args.push_back(m_Dim0.generateNode(context));
619             args.push_back(m_Dim1.generateNode(context));
620             args.push_back(m_Dim2.generateNode(context));
621 
622             return llvm::MDNode::get(context, args);
623         }
624 
625         ///
626         // Saves the structure changes to the given MDNode
save(llvm::LLVMContext & context,llvm::MDNode * pNode) const627         void WorkgroupWalkOrderMetaData::save(llvm::LLVMContext& context, llvm::MDNode* pNode) const
628         {
629             IGC_ASSERT_MESSAGE(nullptr != pNode, "The target node should be valid pointer");
630 
631             // we assume that underlying metadata node has not changed under our foot
632             if (pNode == m_pNode && !dirty())
633             {
634                 return;
635             }
636 #if 0
637             // check that we could save the new information to the given node without regenerating it
638             if (!compatibleWith(pNode))
639             {
640                 pNode->replaceAllUsesWith(generateNode(context));
641                 return;
642             }
643 #endif
644 
645             m_Dim0.save(context, llvm::cast<llvm::MDNode>(getDim0Node(pNode)));
646             m_Dim1.save(context, llvm::cast<llvm::MDNode>(getDim1Node(pNode)));
647             m_Dim2.save(context, llvm::cast<llvm::MDNode>(getDim2Node(pNode)));
648         }
649 
getDim0Node(const llvm::MDNode * pParentNode) const650         llvm::Metadata* WorkgroupWalkOrderMetaData::getDim0Node(const llvm::MDNode* pParentNode) const
651         {
652             if (!pParentNode)
653             {
654                 return NULL;
655             }
656 
657             unsigned int offset = _Mybase::getStartIndex();
658             return pParentNode->getOperand(0 + offset).get();
659         }
660 
getDim1Node(const llvm::MDNode * pParentNode) const661         llvm::Metadata* WorkgroupWalkOrderMetaData::getDim1Node(const llvm::MDNode* pParentNode) const
662         {
663             if (!pParentNode)
664             {
665                 return NULL;
666             }
667 
668             unsigned int offset = _Mybase::getStartIndex();
669             return pParentNode->getOperand(1 + offset).get();
670         }
671 
getDim2Node(const llvm::MDNode * pParentNode) const672         llvm::Metadata* WorkgroupWalkOrderMetaData::getDim2Node(const llvm::MDNode* pParentNode) const
673         {
674             if (!pParentNode)
675             {
676                 return NULL;
677             }
678 
679             unsigned int offset = _Mybase::getStartIndex();
680             return pParentNode->getOperand(2 + offset).get();
681         }
682 
683 
684         ///
685         // Ctor - loads the KernelMetaData from the given metadata node
686         //
KernelMetaData(const llvm::MDNode * pNode,bool hasId)687         KernelMetaData::KernelMetaData(const llvm::MDNode* pNode, bool hasId) :
688             _Mybase(pNode, hasId),
689             m_Function(getFunctionNode(pNode)),
690             m_WorkGroupSizeHint(WorkGroupDimensionsMetaData::get(getWorkGroupSizeHintNode(pNode), true)),
691             m_RequiredWorkGroupSize(WorkGroupDimensionsMetaData::get(getRequiredWorkGroupSizeNode(pNode), true)),
692             m_RequiredSubGroupSize(SubGroupDimensionsMetaData::get(getRequiredSubGroupSizeNode(pNode), true)),
693             m_WorkgroupWalkOrder(WorkgroupWalkOrderMetaData::get(getWorkgroupWalkOrderNode(pNode), true)),
694             m_VectorTypeHint(VectorTypeHintMetaData::get(getVectorTypeHintNode(pNode), true)),
695             m_ArgAddressSpaces(getArgAddressSpacesNode(pNode), true),
696             m_ArgAccessQualifiers(getArgAccessQualifiersNode(pNode), true),
697             m_ArgTypes(getArgTypesNode(pNode), true),
698             m_ArgBaseTypes(getArgBaseTypesNode(pNode), true),
699             m_ArgTypeQualifiers(getArgTypeQualifiersNode(pNode), true),
700             m_ArgNames(getArgNamesNode(pNode), true),
701             m_pNode(pNode)
702         {}
703 
704         ///
705         // Default Ctor - creates the empty, not named KernelMetaData object
706         //
KernelMetaData()707         KernelMetaData::KernelMetaData() : m_WorkGroupSizeHint(WorkGroupDimensionsMetaDataHandle::ObjectType::get("work_group_size_hint")),
708             m_RequiredWorkGroupSize(WorkGroupDimensionsMetaDataHandle::ObjectType::get("reqd_work_group_size")),
709             m_RequiredSubGroupSize(SubGroupDimensionsMetaDataHandle::ObjectType::get("intel_reqd_sub_group_size")),
710             m_WorkgroupWalkOrder(WorkgroupWalkOrderMetaDataHandle::ObjectType::get("intel_reqd_workgroup_walk_order")),
711             m_VectorTypeHint(VectorTypeHintMetaDataHandle::ObjectType::get("vec_type_hint")),
712             m_ArgAddressSpaces("kernel_arg_addr_space"),
713             m_ArgAccessQualifiers("kernel_arg_access_qual"),
714             m_ArgTypes("kernel_arg_type"),
715             m_ArgBaseTypes("kernel_arg_base_type"),
716             m_ArgTypeQualifiers("kernel_arg_type_qual"),
717             m_ArgNames("kernel_arg_name"),
718             m_pNode(NULL)
719         {}
720 
721         ///
722         // Ctor - creates the empty, named KernelMetaData object
723         //
KernelMetaData(const char * name)724         KernelMetaData::KernelMetaData(const char* name) :
725             _Mybase(name), m_WorkGroupSizeHint(WorkGroupDimensionsMetaDataHandle::ObjectType::get("work_group_size_hint")),
726             m_RequiredWorkGroupSize(WorkGroupDimensionsMetaDataHandle::ObjectType::get("reqd_work_group_size")),
727             m_RequiredSubGroupSize(SubGroupDimensionsMetaDataHandle::ObjectType::get("intel_reqd_sub_group_size")),
728             m_WorkgroupWalkOrder(WorkgroupWalkOrderMetaDataHandle::ObjectType::get("intel_reqd_workgroup_walk_order")),
729             m_VectorTypeHint(VectorTypeHintMetaDataHandle::ObjectType::get("vec_type_hint")),
730             m_ArgAddressSpaces("kernel_arg_addr_space"),
731             m_ArgAccessQualifiers("kernel_arg_access_qual"),
732             m_ArgTypes("kernel_arg_type"),
733             m_ArgBaseTypes("kernel_arg_base_type"),
734             m_ArgTypeQualifiers("kernel_arg_type_qual"),
735             m_ArgNames("kernel_arg_name"),
736             m_pNode(NULL)
737         {}
738 
hasValue() const739         bool KernelMetaData::hasValue() const
740         {
741             if (m_Function.hasValue())
742             {
743                 return true;
744             }
745 
746 
747             if (m_WorkGroupSizeHint->hasValue())
748             {
749                 return true;
750             }
751 
752 
753             if (m_RequiredWorkGroupSize->hasValue())
754             {
755                 return true;
756             }
757 
758 
759             if (m_RequiredSubGroupSize->hasValue())
760             {
761                 return true;
762             }
763 
764             if (m_WorkgroupWalkOrder->hasValue())
765             {
766                 return true;
767             }
768 
769 
770             if (m_VectorTypeHint->hasValue())
771             {
772                 return true;
773             }
774 
775 
776             if (m_ArgAddressSpaces.hasValue())
777             {
778                 return true;
779             }
780 
781 
782             if (m_ArgAccessQualifiers.hasValue())
783             {
784                 return true;
785             }
786 
787 
788             if (m_ArgTypes.hasValue())
789             {
790                 return true;
791             }
792 
793 
794             if (m_ArgBaseTypes.hasValue())
795             {
796                 return true;
797             }
798 
799 
800             if (m_ArgTypeQualifiers.hasValue())
801             {
802                 return true;
803             }
804 
805 
806             if (m_ArgNames.hasValue())
807             {
808                 return true;
809             }
810             return NULL != m_pNode || dirty();
811         }
812 
813         ///
814         // Returns true if any of the KernelMetaData`s members has changed
dirty() const815         bool KernelMetaData::dirty() const
816         {
817             if (m_Function.dirty())
818             {
819                 return true;
820             }
821             if (m_WorkGroupSizeHint.dirty())
822             {
823                 return true;
824             }
825             if (m_RequiredWorkGroupSize.dirty())
826             {
827                 return true;
828             }
829             if (m_RequiredSubGroupSize.dirty())
830             {
831                 return true;
832             }
833             if (m_WorkgroupWalkOrder.dirty())
834             {
835                 return true;
836             }
837             if (m_VectorTypeHint.dirty())
838             {
839                 return true;
840             }
841             if (m_ArgAddressSpaces.dirty())
842             {
843                 return true;
844             }
845             if (m_ArgAccessQualifiers.dirty())
846             {
847                 return true;
848             }
849             if (m_ArgTypes.dirty())
850             {
851                 return true;
852             }
853             if (m_ArgBaseTypes.dirty())
854             {
855                 return true;
856             }
857             if (m_ArgTypeQualifiers.dirty())
858             {
859                 return true;
860             }
861             if (m_ArgNames.dirty())
862             {
863                 return true;
864             }
865             return false;
866         }
867 
868         ///
869         // Discards the changes done to the KernelMetaData instance
discardChanges()870         void KernelMetaData::discardChanges()
871         {
872             m_Function.discardChanges();
873             m_WorkGroupSizeHint.discardChanges();
874             m_RequiredWorkGroupSize.discardChanges();
875             m_RequiredSubGroupSize.discardChanges();
876             m_WorkgroupWalkOrder.discardChanges();
877             m_VectorTypeHint.discardChanges();
878             m_ArgAddressSpaces.discardChanges();
879             m_ArgAccessQualifiers.discardChanges();
880             m_ArgTypes.discardChanges();
881             m_ArgBaseTypes.discardChanges();
882             m_ArgTypeQualifiers.discardChanges();
883             m_ArgNames.discardChanges();
884         }
885 
886         ///
887         // Generates the new MDNode hierarchy for the given structure
generateNode(llvm::LLVMContext & context) const888         llvm::Metadata* KernelMetaData::generateNode(llvm::LLVMContext& context) const
889         {
890             llvm::SmallVector<llvm::Metadata*, 5> args;
891 
892             llvm::Metadata* pIDNode = _Mybase::generateNode(context);
893             if (NULL != pIDNode)
894             {
895                 args.push_back(pIDNode);
896             }
897 
898             args.push_back(m_Function.generateNode(context));
899             if (m_WorkGroupSizeHint->hasValue())
900             {
901                 args.push_back(m_WorkGroupSizeHint.generateNode(context));
902             }
903 
904             if (m_RequiredWorkGroupSize->hasValue())
905             {
906                 args.push_back(m_RequiredWorkGroupSize.generateNode(context));
907             }
908 
909             if (m_RequiredSubGroupSize->hasValue())
910             {
911                 args.push_back(m_RequiredSubGroupSize.generateNode(context));
912             }
913 
914             if (m_WorkgroupWalkOrder->hasValue())
915             {
916                 args.push_back(m_WorkgroupWalkOrder.generateNode(context));
917             }
918 
919             if (m_VectorTypeHint->hasValue())
920             {
921                 args.push_back(m_VectorTypeHint.generateNode(context));
922             }
923 
924             args.push_back(m_ArgAddressSpaces.generateNode(context));
925             args.push_back(m_ArgAccessQualifiers.generateNode(context));
926             args.push_back(m_ArgTypes.generateNode(context));
927             args.push_back(m_ArgBaseTypes.generateNode(context));
928             args.push_back(m_ArgTypeQualifiers.generateNode(context));
929             if (isArgNamesHasValue())
930             {
931                 args.push_back(m_ArgNames.generateNode(context));
932             }
933 
934             return llvm::MDNode::get(context, args);
935         }
936 
937         ///
938         // Saves the structure changes to the given MDNode
save(llvm::LLVMContext & context,llvm::MDNode * pNode) const939         void KernelMetaData::save(llvm::LLVMContext& context, llvm::MDNode* pNode) const
940         {
941             IGC_ASSERT_MESSAGE(nullptr != pNode, "The target node should be valid pointer");
942 
943             // we assume that underlying metadata node has not changed under our foot
944             if (pNode == m_pNode && !dirty())
945             {
946                 return;
947             }
948 #if 0
949             // check that we could save the new information to the given node without regenerating it
950             if (!compatibleWith(pNode))
951             {
952                 pNode->replaceAllUsesWith(generateNode(context));
953                 return;
954             }
955 #endif
956 
957             m_Function.save(context, llvm::cast<llvm::MDNode>(getFunctionNode(pNode)));
958             m_WorkGroupSizeHint.save(context, llvm::cast<llvm::MDNode>(getWorkGroupSizeHintNode(pNode)));
959             m_RequiredWorkGroupSize.save(context, llvm::cast<llvm::MDNode>(getRequiredWorkGroupSizeNode(pNode)));
960             m_RequiredSubGroupSize.save(context, llvm::cast<llvm::MDNode>(getRequiredSubGroupSizeNode(pNode)));
961             m_WorkgroupWalkOrder.save(context, llvm::cast<llvm::MDNode>(getWorkgroupWalkOrderNode(pNode)));
962             m_VectorTypeHint.save(context, llvm::cast<llvm::MDNode>(getVectorTypeHintNode(pNode)));
963             m_ArgAddressSpaces.save(context, llvm::cast<llvm::MDNode>(getArgAddressSpacesNode(pNode)));
964             m_ArgAccessQualifiers.save(context, llvm::cast<llvm::MDNode>(getArgAccessQualifiersNode(pNode)));
965             m_ArgTypes.save(context, llvm::cast<llvm::MDNode>(getArgTypesNode(pNode)));
966             m_ArgBaseTypes.save(context, llvm::cast<llvm::MDNode>(getArgBaseTypesNode(pNode)));
967             m_ArgTypeQualifiers.save(context, llvm::cast<llvm::MDNode>(getArgTypeQualifiersNode(pNode)));
968             m_ArgNames.save(context, llvm::cast<llvm::MDNode>(getArgNamesNode(pNode)));
969         }
970 
getFunctionNode(const llvm::MDNode * pParentNode) const971         llvm::Metadata* KernelMetaData::getFunctionNode(const llvm::MDNode* pParentNode) const
972         {
973             if (!pParentNode)
974             {
975                 return NULL;
976             }
977 
978             unsigned int offset = _Mybase::getStartIndex();
979             return pParentNode->getOperand(0 + offset).get();
980         }
981 
getWorkGroupSizeHintNode(const llvm::MDNode * pParentNode) const982         llvm::MDNode* KernelMetaData::getWorkGroupSizeHintNode(const llvm::MDNode* pParentNode) const
983         {
984             if (!pParentNode)
985             {
986                 return NULL;
987             }
988 
989             unsigned int offset = _Mybase::getStartIndex();
990             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
991             {
992                 if (isNamedNode(i.get(), "work_group_size_hint"))
993                 {
994                     return llvm::dyn_cast<llvm::MDNode>(i.get());
995                 }
996             }
997             return NULL;
998         }
999 
getRequiredWorkGroupSizeNode(const llvm::MDNode * pParentNode) const1000         llvm::MDNode* KernelMetaData::getRequiredWorkGroupSizeNode(const llvm::MDNode* pParentNode) const
1001         {
1002             if (!pParentNode)
1003             {
1004                 return NULL;
1005             }
1006 
1007             unsigned int offset = _Mybase::getStartIndex();
1008             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1009             {
1010                 if (isNamedNode(i.get(), "reqd_work_group_size"))
1011                 {
1012                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1013                 }
1014             }
1015             return NULL;
1016         }
1017 
getRequiredSubGroupSizeNode(const llvm::MDNode * pParentNode) const1018         llvm::MDNode* KernelMetaData::getRequiredSubGroupSizeNode(const llvm::MDNode* pParentNode) const
1019         {
1020             if (!pParentNode)
1021             {
1022                 return NULL;
1023             }
1024 
1025             unsigned int offset = _Mybase::getStartIndex();
1026             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1027             {
1028                 if (isNamedNode(i.get(), "intel_reqd_sub_group_size"))
1029                 {
1030                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1031                 }
1032             }
1033             return NULL;
1034         }
1035 
getWorkgroupWalkOrderNode(const llvm::MDNode * pParentNode) const1036         llvm::MDNode* KernelMetaData::getWorkgroupWalkOrderNode(const llvm::MDNode* pParentNode) const
1037         {
1038             if (!pParentNode)
1039             {
1040                 return NULL;
1041             }
1042 
1043             unsigned int offset = _Mybase::getStartIndex();
1044             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1045             {
1046                 if (isNamedNode(i.get(), "intel_reqd_workgroup_walk_order"))
1047                 {
1048                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1049                 }
1050             }
1051             return NULL;
1052         }
1053 
getVectorTypeHintNode(const llvm::MDNode * pParentNode) const1054         llvm::MDNode* KernelMetaData::getVectorTypeHintNode(const llvm::MDNode* pParentNode) const
1055         {
1056             if (!pParentNode)
1057             {
1058                 return NULL;
1059             }
1060 
1061             unsigned int offset = _Mybase::getStartIndex();
1062             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1063             {
1064                 if (isNamedNode(i.get(), "vec_type_hint"))
1065                 {
1066                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1067                 }
1068             }
1069             return NULL;
1070         }
1071 
getArgAddressSpacesNode(const llvm::MDNode * pParentNode) const1072         llvm::MDNode* KernelMetaData::getArgAddressSpacesNode(const llvm::MDNode* pParentNode) const
1073         {
1074             if (!pParentNode)
1075             {
1076                 return NULL;
1077             }
1078 
1079             unsigned int offset = _Mybase::getStartIndex();
1080             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1081             {
1082                 if (isNamedNode(i.get(), "kernel_arg_addr_space"))
1083                 {
1084                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1085                 }
1086             }
1087             return NULL;
1088         }
1089 
getArgAccessQualifiersNode(const llvm::MDNode * pParentNode) const1090         llvm::MDNode* KernelMetaData::getArgAccessQualifiersNode(const llvm::MDNode* pParentNode) const
1091         {
1092             if (!pParentNode)
1093             {
1094                 return NULL;
1095             }
1096 
1097             unsigned int offset = _Mybase::getStartIndex();
1098             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1099             {
1100                 if (isNamedNode(i.get(), "kernel_arg_access_qual"))
1101                 {
1102                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1103                 }
1104             }
1105             return NULL;
1106         }
1107 
getArgTypesNode(const llvm::MDNode * pParentNode) const1108         llvm::MDNode* KernelMetaData::getArgTypesNode(const llvm::MDNode* pParentNode) const
1109         {
1110             if (!pParentNode)
1111             {
1112                 return NULL;
1113             }
1114 
1115             unsigned int offset = _Mybase::getStartIndex();
1116             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1117             {
1118                 if (isNamedNode(i.get(), "kernel_arg_type"))
1119                 {
1120                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1121                 }
1122             }
1123             return NULL;
1124         }
1125 
getArgBaseTypesNode(const llvm::MDNode * pParentNode) const1126         llvm::MDNode* KernelMetaData::getArgBaseTypesNode(const llvm::MDNode* pParentNode) const
1127         {
1128             if (!pParentNode)
1129             {
1130                 return NULL;
1131             }
1132 
1133             unsigned int offset = _Mybase::getStartIndex();
1134             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1135             {
1136                 if (isNamedNode(i.get(), "kernel_arg_base_type"))
1137                 {
1138                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1139                 }
1140             }
1141             return NULL;
1142         }
1143 
getArgTypeQualifiersNode(const llvm::MDNode * pParentNode) const1144         llvm::MDNode* KernelMetaData::getArgTypeQualifiersNode(const llvm::MDNode* pParentNode) const
1145         {
1146             if (!pParentNode)
1147             {
1148                 return NULL;
1149             }
1150 
1151             unsigned int offset = _Mybase::getStartIndex();
1152             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1153             {
1154                 if (isNamedNode(i.get(), "kernel_arg_type_qual"))
1155                 {
1156                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1157                 }
1158             }
1159             return NULL;
1160         }
1161 
getArgNamesNode(const llvm::MDNode * pParentNode) const1162         llvm::MDNode* KernelMetaData::getArgNamesNode(const llvm::MDNode* pParentNode) const
1163         {
1164             if (!pParentNode)
1165             {
1166                 return NULL;
1167             }
1168 
1169             unsigned int offset = _Mybase::getStartIndex();
1170             for (NodeIterator i = NodeIterator(pParentNode, 1 + offset), e = NodeIterator(pParentNode); i != e; ++i)
1171             {
1172                 if (isNamedNode(i.get(), "kernel_arg_name"))
1173                 {
1174                     return llvm::dyn_cast<llvm::MDNode>(i.get());
1175                 }
1176             }
1177             return NULL;
1178         }
1179 
1180 
1181         ///
1182         // dtor
1183         //SpirMetaDataUtils::~SpirMetaDataUtils()
1184         //{
1185            //
1186         //}
1187 
isNamedNode(const llvm::Metadata * pNode,const char * name)1188         static bool isNamedNode(const llvm::Metadata* pNode, const char* name)
1189         {
1190             const llvm::MDNode* pMDNode = llvm::dyn_cast<llvm::MDNode>(pNode);
1191 
1192             if (!pMDNode)
1193             {
1194                 return false;
1195             }
1196 
1197             if (pMDNode->getNumOperands() < 1)
1198             {
1199                 return false;
1200             }
1201 
1202             const llvm::MDString* pIdNode = llvm::dyn_cast<const llvm::MDString>(pMDNode->getOperand(0));
1203             if (!pIdNode)
1204             {
1205                 return false;
1206             }
1207 
1208             llvm::StringRef id = pIdNode->getString();
1209             if (id.compare(name))
1210             {
1211                 return false;
1212             }
1213             return true;
1214         }
1215 
1216     }
1217 }
1218