DxilPIXVirtualRegisters.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilPIXVirtualRegisters.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Defines functions for dealing with the virtual register annotations in //
  9. // DXIL instructions. //
  10. // //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "dxc/DxilPIXPasses/DxilPIXVirtualRegisters.h"
  13. #include "dxc/Support/Global.h"
  14. #include "llvm/IR/Constant.h"
  15. #include "llvm/IR/Constants.h"
  16. #include "llvm/IR/IRBuilder.h"
  17. #include "llvm/IR/InstIterator.h"
  18. #include "llvm/IR/Instruction.h"
  19. #include "llvm/IR/Instructions.h"
  20. #include "llvm/IR/Metadata.h"
  21. #include "llvm/IR/Type.h"
  22. void pix_dxil::PixDxilInstNum::AddMD(llvm::LLVMContext &Ctx,
  23. llvm::Instruction *pI,
  24. std::uint32_t InstNum) {
  25. llvm::IRBuilder<> B(Ctx);
  26. pI->setMetadata(
  27. llvm::StringRef(MDName),
  28. llvm::MDNode::get(Ctx,
  29. {llvm::ConstantAsMetadata::get(B.getInt32(ID)),
  30. llvm::ConstantAsMetadata::get(B.getInt32(InstNum))}));
  31. }
  32. bool pix_dxil::PixDxilInstNum::FromInst(llvm::Instruction *pI,
  33. std::uint32_t *pInstNum) {
  34. *pInstNum = 0;
  35. auto *mdNodes = pI->getMetadata(MDName);
  36. if (mdNodes == nullptr) {
  37. return false;
  38. }
  39. if (mdNodes->getNumOperands() != 2) {
  40. return false;
  41. }
  42. auto *mdID =
  43. llvm::mdconst::dyn_extract<llvm::ConstantInt>(mdNodes->getOperand(0));
  44. if (mdID == nullptr || mdID->getLimitedValue() != ID) {
  45. return false;
  46. }
  47. auto *mdInstNum =
  48. llvm::mdconst::dyn_extract<llvm::ConstantInt>(mdNodes->getOperand(1));
  49. if (mdInstNum == nullptr) {
  50. return false;
  51. }
  52. *pInstNum = mdInstNum->getLimitedValue();
  53. return true;
  54. }
  55. void pix_dxil::PixDxilReg::AddMD(llvm::LLVMContext &Ctx, llvm::Instruction *pI,
  56. std::uint32_t RegNum) {
  57. llvm::IRBuilder<> B(Ctx);
  58. pI->setMetadata(
  59. llvm::StringRef(MDName),
  60. llvm::MDNode::get(Ctx,
  61. {llvm::ConstantAsMetadata::get(B.getInt32(ID)),
  62. llvm::ConstantAsMetadata::get(B.getInt32(RegNum))}));
  63. }
  64. bool pix_dxil::PixDxilReg::FromInst(llvm::Instruction *pI,
  65. std::uint32_t *pRegNum) {
  66. *pRegNum = 0;
  67. auto *mdNodes = pI->getMetadata(MDName);
  68. if (mdNodes == nullptr) {
  69. return false;
  70. }
  71. if (mdNodes->getNumOperands() != 2) {
  72. return false;
  73. }
  74. auto *mdID =
  75. llvm::mdconst::dyn_extract<llvm::ConstantInt>(mdNodes->getOperand(0));
  76. if (mdID == nullptr || mdID->getLimitedValue() != ID) {
  77. return false;
  78. }
  79. auto *mdRegNum =
  80. llvm::mdconst::dyn_extract<llvm::ConstantInt>(mdNodes->getOperand(1));
  81. if (mdRegNum == nullptr) {
  82. return false;
  83. }
  84. *pRegNum = mdRegNum->getLimitedValue();
  85. return true;
  86. }
  87. static bool ParsePixAllocaReg(llvm::MDNode *MD, std::uint32_t *RegNum,
  88. std::uint32_t *Count) {
  89. if (MD->getNumOperands() != 3) {
  90. return false;
  91. }
  92. auto *mdID = llvm::mdconst::dyn_extract<llvm::ConstantInt>(MD->getOperand(0));
  93. if (mdID == nullptr ||
  94. mdID->getLimitedValue() != pix_dxil::PixAllocaReg::ID) {
  95. return false;
  96. }
  97. auto *mdRegNum =
  98. llvm::mdconst::dyn_extract<llvm::ConstantInt>(MD->getOperand(1));
  99. auto *mdCount =
  100. llvm::mdconst::dyn_extract<llvm::ConstantInt>(MD->getOperand(2));
  101. if (mdRegNum == nullptr || mdCount == nullptr) {
  102. return false;
  103. }
  104. *RegNum = mdRegNum->getLimitedValue();
  105. *Count = mdCount->getLimitedValue();
  106. return true;
  107. }
  108. void pix_dxil::PixAllocaReg::AddMD(llvm::LLVMContext &Ctx,
  109. llvm::AllocaInst *pAlloca,
  110. std::uint32_t RegNum, std::uint32_t Count) {
  111. llvm::IRBuilder<> B(Ctx);
  112. pAlloca->setMetadata(
  113. llvm::StringRef(MDName),
  114. llvm::MDNode::get(Ctx,
  115. {llvm::ConstantAsMetadata::get(B.getInt32(ID)),
  116. llvm::ConstantAsMetadata::get(B.getInt32(RegNum)),
  117. llvm::ConstantAsMetadata::get(B.getInt32(Count))}));
  118. }
  119. bool pix_dxil::PixAllocaReg::FromInst(llvm::AllocaInst *pAlloca,
  120. std::uint32_t *pRegBase,
  121. std::uint32_t *pRegSize) {
  122. *pRegBase = 0;
  123. *pRegSize = 0;
  124. auto *mdNodes = pAlloca->getMetadata(MDName);
  125. if (mdNodes == nullptr) {
  126. return false;
  127. }
  128. return ParsePixAllocaReg(mdNodes, pRegBase, pRegSize);
  129. }
  130. namespace pix_dxil {
  131. namespace PixAllocaRegWrite {
  132. static constexpr uint32_t IndexIsConst = 1;
  133. static constexpr uint32_t IndexIsPixInst = 2;
  134. } // namespace PixAllocaRegWrite
  135. } // namespace pix_dxil
  136. void pix_dxil::PixAllocaRegWrite::AddMD(llvm::LLVMContext &Ctx,
  137. llvm::StoreInst *pSt,
  138. llvm::MDNode *pAllocaReg,
  139. llvm::Value *Index) {
  140. llvm::IRBuilder<> B(Ctx);
  141. if (auto *C = llvm::dyn_cast<llvm::ConstantInt>(Index)) {
  142. pSt->setMetadata(
  143. llvm::StringRef(MDName),
  144. llvm::MDNode::get(
  145. Ctx, {llvm::ConstantAsMetadata::get(B.getInt32(ID)), pAllocaReg,
  146. llvm::ConstantAsMetadata::get(B.getInt32(IndexIsConst)),
  147. llvm::ConstantAsMetadata::get(C)}));
  148. }
  149. if (auto *I = llvm::dyn_cast<llvm::Instruction>(Index)) {
  150. std::uint32_t InstNum;
  151. if (!PixDxilInstNum::FromInst(I, &InstNum)) {
  152. return;
  153. }
  154. pSt->setMetadata(
  155. llvm::StringRef(MDName),
  156. llvm::MDNode::get(
  157. Ctx, {llvm::ConstantAsMetadata::get(B.getInt32(ID)), pAllocaReg,
  158. llvm::ConstantAsMetadata::get(B.getInt32(IndexIsPixInst)),
  159. llvm::ConstantAsMetadata::get(B.getInt32(InstNum))}));
  160. }
  161. }
  162. bool pix_dxil::PixAllocaRegWrite::FromInst(llvm::StoreInst *pI,
  163. std::uint32_t *pRegBase,
  164. std::uint32_t *pRegSize,
  165. llvm::Value **pIndex) {
  166. *pRegBase = 0;
  167. *pRegSize = 0;
  168. *pIndex = nullptr;
  169. auto *mdNodes = pI->getMetadata(MDName);
  170. if (mdNodes == nullptr || mdNodes->getNumOperands() != 4) {
  171. return false;
  172. }
  173. auto *mdID =
  174. llvm::mdconst::dyn_extract<llvm::ConstantInt>(mdNodes->getOperand(0));
  175. if (mdID == nullptr || mdID->getLimitedValue() != ID) {
  176. return false;
  177. }
  178. auto *mdAllocaReg = llvm::dyn_cast<llvm::MDNode>(mdNodes->getOperand(1));
  179. if (mdAllocaReg == nullptr ||
  180. !ParsePixAllocaReg(mdAllocaReg, pRegBase, pRegSize)) {
  181. return false;
  182. }
  183. auto *mdIndexType =
  184. llvm::dyn_cast<llvm::ConstantAsMetadata>(mdNodes->getOperand(2));
  185. if (mdIndexType == nullptr) {
  186. return false;
  187. }
  188. auto *cIndexType = llvm::dyn_cast<llvm::ConstantInt>(mdIndexType->getValue());
  189. if (cIndexType == nullptr) {
  190. return false;
  191. }
  192. auto *mdIndex =
  193. llvm::dyn_cast<llvm::ConstantAsMetadata>(mdNodes->getOperand(3));
  194. if (mdIndex == nullptr) {
  195. return false;
  196. }
  197. auto *cIndex = llvm::dyn_cast<llvm::ConstantInt>(mdIndex->getValue());
  198. if (cIndex == nullptr) {
  199. return false;
  200. }
  201. switch (cIndexType->getLimitedValue()) {
  202. default:
  203. return false;
  204. case IndexIsConst: {
  205. *pIndex = cIndex;
  206. return true;
  207. }
  208. case IndexIsPixInst: {
  209. for (llvm::Instruction &I :
  210. llvm::inst_range(pI->getParent()->getParent())) {
  211. uint32_t InstNum;
  212. if (PixDxilInstNum::FromInst(&I, &InstNum)) {
  213. *pIndex = &I;
  214. if (InstNum == cIndex->getLimitedValue()) {
  215. return true;
  216. }
  217. }
  218. }
  219. return false;
  220. }
  221. }
  222. return false;
  223. }