HLUtil.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. DxilFunctionAnnotation *annotation = typeSys.GetFunctionAnnotation(F);
  101. if (!annotation) {
  102. HLOpcodeGroup group = hlsl::GetHLOpcodeGroupByName(F);
  103. switch (group) {
  104. case HLOpcodeGroup::HLMatLoadStore: {
  105. HLMatLoadStoreOpcode opcode =
  106. static_cast<HLMatLoadStoreOpcode>(hlsl::GetHLOpcode(CI));
  107. switch (opcode) {
  108. case HLMatLoadStoreOpcode::ColMatLoad:
  109. case HLMatLoadStoreOpcode::RowMatLoad:
  110. PS.MarkAsLoaded();
  111. break;
  112. case HLMatLoadStoreOpcode::ColMatStore:
  113. case HLMatLoadStoreOpcode::RowMatStore:
  114. PS.MarkAsStored();
  115. break;
  116. default:
  117. DXASSERT(0, "invalid opcode");
  118. PS.MarkAsStored();
  119. PS.MarkAsLoaded();
  120. }
  121. } break;
  122. case HLOpcodeGroup::HLSubscript: {
  123. HLSubscriptOpcode opcode =
  124. static_cast<HLSubscriptOpcode>(hlsl::GetHLOpcode(CI));
  125. switch (opcode) {
  126. case HLSubscriptOpcode::VectorSubscript:
  127. case HLSubscriptOpcode::ColMatElement:
  128. case HLSubscriptOpcode::ColMatSubscript:
  129. case HLSubscriptOpcode::RowMatElement:
  130. case HLSubscriptOpcode::RowMatSubscript:
  131. analyzePointer(CI, PS, typeSys, bStructElt, bLdStOnly);
  132. break;
  133. default:
  134. // Rest are resource ptr like buf[i].
  135. // Only read of resource handle.
  136. PS.MarkAsLoaded();
  137. break;
  138. }
  139. } break;
  140. default: {
  141. // If not sure its out param or not. Take as out param.
  142. PS.MarkAsStored();
  143. PS.MarkAsLoaded();
  144. }
  145. }
  146. continue;
  147. }
  148. unsigned argSize = F->arg_size();
  149. for (unsigned i = 0; i < argSize; i++) {
  150. Value *arg = CI->getArgOperand(i);
  151. if (V == arg) {
  152. if (bLdStOnly) {
  153. auto &paramAnnot = annotation->GetParameterAnnotation(i);
  154. switch (paramAnnot.GetParamInputQual()) {
  155. default:
  156. PS.MarkAsStored();
  157. PS.MarkAsLoaded();
  158. break;
  159. case DxilParamInputQual::Out:
  160. PS.MarkAsStored();
  161. break;
  162. case DxilParamInputQual::In:
  163. PS.MarkAsLoaded();
  164. break;
  165. }
  166. } else {
  167. // Do not replace struct arg.
  168. // Mark stored and loaded to disable replace.
  169. PS.MarkAsStored();
  170. PS.MarkAsLoaded();
  171. }
  172. }
  173. }
  174. }
  175. }
  176. }
  177. }
  178. namespace hlsl {
  179. namespace hlutil {
  180. void PointerStatus::analyze(DxilTypeSystem &typeSys, bool bStructElt) {
  181. analyzePointer(Ptr, *this, typeSys, bStructElt, bLoadStoreOnly);
  182. }
  183. PointerStatus::PointerStatus(llvm::Value *ptr, unsigned size, bool bLdStOnly)
  184. : storedType(StoredType::NotStored), loadedType(LoadedType::NotLoaded),
  185. StoredOnceValue(nullptr), StoringMemcpy(nullptr), LoadingMemcpy(nullptr),
  186. AccessingFunction(nullptr), HasMultipleAccessingFunctions(false),
  187. Size(size), Ptr(ptr), bLoadStoreOnly(bLdStOnly) {}
  188. void PointerStatus::MarkAsStored() {
  189. storedType = StoredType::Stored;
  190. StoredOnceValue = nullptr;
  191. }
  192. void PointerStatus::MarkAsLoaded() { loadedType = LoadedType::Loaded; }
  193. bool PointerStatus::HasStored() {
  194. return storedType != StoredType::NotStored &&
  195. storedType != StoredType::InitializerStored;
  196. }
  197. bool PointerStatus::HasLoaded() { return loadedType != LoadedType::NotLoaded; }
  198. } // namespace hlutil
  199. } // namespace hlsl