HLUtil.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // HLUtil.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. // HL helper functions. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/HLSL/HLUtil.h"
  12. #include "dxc/HLSL/HLOperations.h"
  13. #include "dxc/DXIL/DxilTypeSystem.h"
  14. #include "dxc/Support/Global.h"
  15. #include "llvm/IR/Operator.h"
  16. #include "llvm/IR/Instructions.h"
  17. #include "llvm/IR/IntrinsicInst.h"
  18. #include "llvm/IR/GetElementPtrTypeIterator.h"
  19. using namespace llvm;
  20. using namespace hlsl;
  21. using namespace hlsl::hlutil;
  22. namespace {
  23. void analyzePointer(const Value *V, PointerStatus &PS, DxilTypeSystem &typeSys,
  24. bool bStructElt, bool bLdStOnly) {
  25. // Early return when only care load store.
  26. if (bLdStOnly) {
  27. if (PS.HasLoaded() && PS.HasStored())
  28. return;
  29. }
  30. for (const User *U : V->users()) {
  31. if (const Instruction *I = dyn_cast<Instruction>(U)) {
  32. const Function *F = I->getParent()->getParent();
  33. if (!PS.AccessingFunction) {
  34. PS.AccessingFunction = F;
  35. } else {
  36. if (F != PS.AccessingFunction)
  37. PS.HasMultipleAccessingFunctions = true;
  38. }
  39. }
  40. if (const BitCastOperator *BC = dyn_cast<BitCastOperator>(U)) {
  41. analyzePointer(BC, PS, typeSys, bStructElt, bLdStOnly);
  42. } else if (const MemCpyInst *MC = dyn_cast<MemCpyInst>(U)) {
  43. // Do not collect memcpy on struct GEP use.
  44. // These memcpy will be flattened in next level.
  45. if (!bStructElt) {
  46. MemCpyInst *MI = const_cast<MemCpyInst *>(MC);
  47. PS.memcpySet.insert(MI);
  48. bool bFullCopy = false;
  49. if (ConstantInt *Length = dyn_cast<ConstantInt>(MC->getLength())) {
  50. bFullCopy = PS.Size == Length->getLimitedValue() || PS.Size == 0 ||
  51. Length->getLimitedValue() == 0; // handle unbounded arrays
  52. }
  53. if (MC->getRawDest() == V) {
  54. if (bFullCopy &&
  55. PS.storedType == PointerStatus::StoredType::NotStored) {
  56. PS.storedType = PointerStatus::StoredType::MemcopyDestOnce;
  57. PS.StoringMemcpy = MI;
  58. } else {
  59. PS.MarkAsStored();
  60. PS.StoringMemcpy = nullptr;
  61. }
  62. } else if (MC->getRawSource() == V) {
  63. if (bFullCopy &&
  64. PS.loadedType == PointerStatus::LoadedType::NotLoaded) {
  65. PS.loadedType = PointerStatus::LoadedType::MemcopySrcOnce;
  66. PS.LoadingMemcpy = MI;
  67. } else {
  68. PS.MarkAsLoaded();
  69. PS.LoadingMemcpy = nullptr;
  70. }
  71. }
  72. } else {
  73. if (MC->getRawDest() == V) {
  74. PS.MarkAsStored();
  75. } else {
  76. DXASSERT(MC->getRawSource() == V, "must be source here");
  77. PS.MarkAsLoaded();
  78. }
  79. }
  80. } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
  81. gep_type_iterator GEPIt = gep_type_begin(GEP);
  82. gep_type_iterator GEPEnd = gep_type_end(GEP);
  83. // Skip pointer idx.
  84. GEPIt++;
  85. // Struct elt will be flattened in next level.
  86. bool bStructElt = (GEPIt != GEPEnd) && GEPIt->isStructTy();
  87. analyzePointer(GEP, PS, typeSys, bStructElt, bLdStOnly);
  88. } else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
  89. Value *V = SI->getOperand(0);
  90. if (PS.storedType == PointerStatus::StoredType::NotStored) {
  91. PS.storedType = PointerStatus::StoredType::StoredOnce;
  92. PS.StoredOnceValue = V;
  93. } else {
  94. PS.MarkAsStored();
  95. }
  96. } else if (dyn_cast<LoadInst>(U)) {
  97. PS.MarkAsLoaded();
  98. } else if (const CallInst *CI = dyn_cast<CallInst>(U)) {
  99. Function *F = CI->getCalledFunction();
  100. if (F->isIntrinsic()) {
  101. if (F->getIntrinsicID() == Intrinsic::lifetime_start ||
  102. F->getIntrinsicID() == Intrinsic::lifetime_end)
  103. continue;
  104. }
  105. DxilFunctionAnnotation *annotation = typeSys.GetFunctionAnnotation(F);
  106. if (!annotation) {
  107. HLOpcodeGroup group = hlsl::GetHLOpcodeGroupByName(F);
  108. switch (group) {
  109. case HLOpcodeGroup::HLMatLoadStore: {
  110. HLMatLoadStoreOpcode opcode =
  111. static_cast<HLMatLoadStoreOpcode>(hlsl::GetHLOpcode(CI));
  112. switch (opcode) {
  113. case HLMatLoadStoreOpcode::ColMatLoad:
  114. case HLMatLoadStoreOpcode::RowMatLoad:
  115. PS.MarkAsLoaded();
  116. break;
  117. case HLMatLoadStoreOpcode::ColMatStore:
  118. case HLMatLoadStoreOpcode::RowMatStore:
  119. PS.MarkAsStored();
  120. break;
  121. default:
  122. DXASSERT(0, "invalid opcode");
  123. PS.MarkAsStored();
  124. PS.MarkAsLoaded();
  125. }
  126. } break;
  127. case HLOpcodeGroup::HLSubscript: {
  128. HLSubscriptOpcode opcode =
  129. static_cast<HLSubscriptOpcode>(hlsl::GetHLOpcode(CI));
  130. switch (opcode) {
  131. case HLSubscriptOpcode::VectorSubscript:
  132. case HLSubscriptOpcode::ColMatElement:
  133. case HLSubscriptOpcode::ColMatSubscript:
  134. case HLSubscriptOpcode::RowMatElement:
  135. case HLSubscriptOpcode::RowMatSubscript:
  136. analyzePointer(CI, PS, typeSys, bStructElt, bLdStOnly);
  137. break;
  138. default:
  139. // Rest are resource ptr like buf[i].
  140. // Only read of resource handle.
  141. PS.MarkAsLoaded();
  142. break;
  143. }
  144. } break;
  145. default: {
  146. // If not sure its out param or not. Take as out param.
  147. PS.MarkAsStored();
  148. PS.MarkAsLoaded();
  149. }
  150. }
  151. continue;
  152. }
  153. unsigned argSize = F->arg_size();
  154. for (unsigned i = 0; i < argSize; i++) {
  155. Value *arg = CI->getArgOperand(i);
  156. if (V == arg) {
  157. if (bLdStOnly) {
  158. auto &paramAnnot = annotation->GetParameterAnnotation(i);
  159. switch (paramAnnot.GetParamInputQual()) {
  160. default:
  161. PS.MarkAsStored();
  162. PS.MarkAsLoaded();
  163. break;
  164. case DxilParamInputQual::Out:
  165. PS.MarkAsStored();
  166. break;
  167. case DxilParamInputQual::In:
  168. PS.MarkAsLoaded();
  169. break;
  170. }
  171. } else {
  172. // Do not replace struct arg.
  173. // Mark stored and loaded to disable replace.
  174. PS.MarkAsStored();
  175. PS.MarkAsLoaded();
  176. }
  177. }
  178. }
  179. }
  180. }
  181. }
  182. }
  183. namespace hlsl {
  184. namespace hlutil {
  185. void PointerStatus::analyze(DxilTypeSystem &typeSys, bool bStructElt) {
  186. analyzePointer(Ptr, *this, typeSys, bStructElt, bLoadStoreOnly);
  187. }
  188. PointerStatus::PointerStatus(llvm::Value *ptr, unsigned size, bool bLdStOnly)
  189. : storedType(StoredType::NotStored), loadedType(LoadedType::NotLoaded),
  190. StoredOnceValue(nullptr), StoringMemcpy(nullptr), LoadingMemcpy(nullptr),
  191. AccessingFunction(nullptr), HasMultipleAccessingFunctions(false),
  192. Size(size), Ptr(ptr), bLoadStoreOnly(bLdStOnly) {}
  193. void PointerStatus::MarkAsStored() {
  194. storedType = StoredType::Stored;
  195. StoredOnceValue = nullptr;
  196. }
  197. void PointerStatus::MarkAsLoaded() { loadedType = LoadedType::Loaded; }
  198. bool PointerStatus::HasStored() {
  199. return storedType != StoredType::NotStored &&
  200. storedType != StoredType::InitializerStored;
  201. }
  202. bool PointerStatus::HasLoaded() { return loadedType != LoadedType::NotLoaded; }
  203. } // namespace hlutil
  204. } // namespace hlsl