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