DxilGenerationPass.cpp 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilGenerationPass.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. // DxilGenerationPass implementation. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/HLSL/DxilGenerationPass.h"
  12. #include "dxc/HLSL/DxilOperations.h"
  13. #include "dxc/HLSL/DxilSignatureElement.h"
  14. #include "dxc/HLSL/DxilSigPoint.h"
  15. #include "dxc/HLSL/DxilModule.h"
  16. #include "dxc/HLSL/HLModule.h"
  17. #include "dxc/HLSL/HLOperations.h"
  18. #include "dxc/HLSL/HLMatrixLowerHelper.h"
  19. #include "dxc/HlslIntrinsicOp.h"
  20. #include "dxc/Support/Global.h"
  21. #include "dxc/HLSL/DxilTypeSystem.h"
  22. #include "dxc/HLSL/HLOperationLower.h"
  23. #include "llvm/IR/GetElementPtrTypeIterator.h"
  24. #include "llvm/IR/IRBuilder.h"
  25. #include "llvm/IR/Instructions.h"
  26. #include "llvm/IR/InstIterator.h"
  27. #include "llvm/IR/IntrinsicInst.h"
  28. #include "llvm/IR/Module.h"
  29. #include "llvm/IR/DebugInfo.h"
  30. #include "llvm/IR/PassManager.h"
  31. #include "llvm/ADT/BitVector.h"
  32. #include "llvm/Pass.h"
  33. #include "llvm/Transforms/Utils/Local.h"
  34. #include "llvm/Transforms/Utils/SSAUpdater.h"
  35. #include <memory>
  36. #include <unordered_set>
  37. using namespace llvm;
  38. using namespace hlsl;
  39. // TODO: use hlsl namespace for the most of this file.
  40. namespace {
  41. class ResourcePromoter : public LoadAndStorePromoter {
  42. AllocaInst *AI;
  43. AllocaInst *NewAI;
  44. bool HasUnmappedLd;
  45. std::unordered_map<Instruction *, Value *> &handleMap;
  46. public:
  47. ResourcePromoter(ArrayRef<Instruction *> Insts, SSAUpdater &S,
  48. std::unordered_map<Instruction *, Value *> &handleMap)
  49. : LoadAndStorePromoter(Insts, S), AI(nullptr), handleMap(handleMap),
  50. HasUnmappedLd(false) {}
  51. AllocaInst *run(AllocaInst *AI, const SmallVectorImpl<Instruction *> &Insts) {
  52. // Remember which alloca we're promoting (for isInstInList).
  53. this->AI = AI;
  54. // Only want to add load of resource allocas to handleMap.
  55. // But LoadAndStorePromoter::run will remove all load/store and alloca.
  56. // So need to clone.
  57. // Clone to keep the debug info.
  58. NewAI = cast<AllocaInst>(AI->clone());
  59. IRBuilder<> Builder(AI);
  60. Builder.Insert(NewAI);
  61. LoadAndStorePromoter::run(Insts);
  62. AI->eraseFromParent();
  63. bool allLoadMapped = true;
  64. for (User *U : NewAI->users()) {
  65. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  66. if (handleMap.count(LI) == 0) {
  67. allLoadMapped = false;
  68. break;
  69. }
  70. }
  71. }
  72. return allLoadMapped? nullptr : NewAI;
  73. }
  74. bool
  75. isInstInList(Instruction *I,
  76. const SmallVectorImpl<Instruction *> &Insts) const override {
  77. if (LoadInst *LI = dyn_cast<LoadInst>(I))
  78. return LI->getOperand(0) == AI;
  79. return cast<StoreInst>(I)->getPointerOperand() == AI;
  80. }
  81. void updateDebugInfo(Instruction *Inst) const override {
  82. // Store use go this path.
  83. // Clone to keep the debug info.
  84. Instruction *NewInst = Inst->clone();
  85. NewInst->replaceUsesOfWith(AI, NewAI);
  86. IRBuilder<> Builder(Inst);
  87. Builder.Insert(NewInst);
  88. }
  89. void replaceLoadWithValue(LoadInst *LI, Value *V) const override {
  90. // Load use go here.
  91. // Clone to keep the debug info.
  92. Instruction *NewInst = LI->clone();
  93. NewInst->replaceUsesOfWith(AI, NewAI);
  94. IRBuilder<> Builder(LI);
  95. Builder.Insert(NewInst);
  96. LI->replaceAllUsesWith(NewInst);
  97. // Mark handle map.
  98. // If cannot find, will return false in run();
  99. if (Instruction *I = dyn_cast<Instruction>(V)) {
  100. if (handleMap.count(I))
  101. handleMap[NewInst] = handleMap[I];
  102. }
  103. }
  104. };
  105. void InitResourceBase(const DxilResourceBase *pSource, DxilResourceBase *pDest) {
  106. DXASSERT_NOMSG(pSource->GetClass() == pDest->GetClass());
  107. pDest->SetKind(pSource->GetKind());
  108. pDest->SetID(pSource->GetID());
  109. pDest->SetSpaceID(pSource->GetSpaceID());
  110. pDest->SetLowerBound(pSource->GetLowerBound());
  111. pDest->SetRangeSize(pSource->GetRangeSize());
  112. pDest->SetGlobalSymbol(pSource->GetGlobalSymbol());
  113. pDest->SetGlobalName(pSource->GetGlobalName());
  114. pDest->SetHandle(pSource->GetHandle());
  115. }
  116. void InitResource(const DxilResource *pSource, DxilResource *pDest) {
  117. pDest->SetCompType(pSource->GetCompType());
  118. pDest->SetSampleCount(pSource->GetSampleCount());
  119. pDest->SetElementStride(pSource->GetElementStride());
  120. pDest->SetGloballyCoherent(pSource->IsGloballyCoherent());
  121. pDest->SetHasCounter(pSource->HasCounter());
  122. pDest->SetRW(pSource->IsRW());
  123. pDest->SetROV(pSource->IsROV());
  124. InitResourceBase(pSource, pDest);
  125. }
  126. void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) {
  127. // Subsystems.
  128. M.SetShaderModel(H.GetShaderModel());
  129. // Entry function.
  130. Function *EntryFn = H.GetEntryFunction();
  131. HLFunctionProps *FnProps = H.HasHLFunctionProps(EntryFn) ? &H.GetHLFunctionProps(EntryFn) : nullptr;
  132. M.SetEntryFunction(EntryFn);
  133. M.SetEntryFunctionName(H.GetEntryFunctionName());
  134. std::vector<GlobalVariable* > &LLVMUsed = M.GetLLVMUsed();
  135. // Resources
  136. for (auto && C : H.GetCBuffers()) {
  137. auto b = make_unique<DxilCBuffer>();
  138. InitResourceBase(C.get(), b.get());
  139. b->SetSize(C->GetSize());
  140. if (HasDebugInfo)
  141. LLVMUsed.emplace_back(cast<GlobalVariable>(b->GetGlobalSymbol()));
  142. else
  143. b->SetGlobalSymbol(UndefValue::get(b->GetGlobalSymbol()->getType()));
  144. M.AddCBuffer(std::move(b));
  145. }
  146. for (auto && C : H.GetUAVs()) {
  147. auto b = make_unique<DxilResource>();
  148. InitResource(C.get(), b.get());
  149. if (HasDebugInfo)
  150. LLVMUsed.emplace_back(cast<GlobalVariable>(b->GetGlobalSymbol()));
  151. else
  152. b->SetGlobalSymbol(UndefValue::get(b->GetGlobalSymbol()->getType()));
  153. M.AddUAV(std::move(b));
  154. }
  155. for (auto && C : H.GetSRVs()) {
  156. auto b = make_unique<DxilResource>();
  157. InitResource(C.get(), b.get());
  158. if (HasDebugInfo)
  159. LLVMUsed.emplace_back(cast<GlobalVariable>(b->GetGlobalSymbol()));
  160. else
  161. b->SetGlobalSymbol(UndefValue::get(b->GetGlobalSymbol()->getType()));
  162. M.AddSRV(std::move(b));
  163. }
  164. for (auto && C : H.GetSamplers()) {
  165. auto b = make_unique<DxilSampler>();
  166. InitResourceBase(C.get(), b.get());
  167. b->SetSamplerKind(C->GetSamplerKind());
  168. if (HasDebugInfo)
  169. LLVMUsed.emplace_back(cast<GlobalVariable>(b->GetGlobalSymbol()));
  170. else
  171. b->SetGlobalSymbol(UndefValue::get(b->GetGlobalSymbol()->getType()));
  172. M.AddSampler(std::move(b));
  173. }
  174. // Signatures.
  175. M.ResetInputSignature(H.ReleaseInputSignature());
  176. M.ResetOutputSignature(H.ReleaseOutputSignature());
  177. M.ResetPatchConstantSignature(H.ReleasePatchConstantSignature());
  178. M.ResetRootSignature(H.ReleaseRootSignature());
  179. // Shader properties.
  180. //bool m_bDisableOptimizations;
  181. M.m_ShaderFlags.SetDisableOptimizations(H.GetHLOptions().bDisableOptimizations);
  182. //bool m_bDisableMathRefactoring;
  183. //bool m_bEnableDoublePrecision;
  184. //bool m_bEnableDoubleExtensions;
  185. //bool m_bEnableMinPrecision;
  186. M.CollectShaderFlags();
  187. //bool m_bForceEarlyDepthStencil;
  188. //bool m_bEnableRawAndStructuredBuffers;
  189. //bool m_bEnableMSAD;
  190. M.m_ShaderFlags.SetAllResourcesBound(H.GetHLOptions().bAllResourcesBound);
  191. // Compute shader.
  192. if (FnProps != nullptr && FnProps->shaderKind == DXIL::ShaderKind::Compute) {
  193. auto &CS = FnProps->ShaderProps.CS;
  194. for (size_t i = 0; i < _countof(M.m_NumThreads); ++i)
  195. M.m_NumThreads[i] = CS.numThreads[i];
  196. }
  197. // Geometry shader.
  198. if (FnProps != nullptr && FnProps->shaderKind == DXIL::ShaderKind::Geometry) {
  199. auto &GS = FnProps->ShaderProps.GS;
  200. M.SetInputPrimitive(GS.inputPrimitive);
  201. M.SetMaxVertexCount(GS.maxVertexCount);
  202. for (size_t i = 0; i < _countof(GS.streamPrimitiveTopologies); ++i) {
  203. if (GS.streamPrimitiveTopologies[i] != DXIL::PrimitiveTopology::Undefined) {
  204. M.SetStreamActive(i, true);
  205. DXASSERT_NOMSG(M.GetStreamPrimitiveTopology() ==
  206. DXIL::PrimitiveTopology::Undefined ||
  207. M.GetStreamPrimitiveTopology() ==
  208. GS.streamPrimitiveTopologies[i]);
  209. M.SetStreamPrimitiveTopology(GS.streamPrimitiveTopologies[i]);
  210. }
  211. }
  212. M.SetGSInstanceCount(GS.instanceCount);
  213. }
  214. // Hull and Domain shaders.
  215. if (FnProps != nullptr && FnProps->shaderKind == DXIL::ShaderKind::Domain) {
  216. auto &DS = FnProps->ShaderProps.DS;
  217. M.SetTessellatorDomain(DS.domain);
  218. M.SetInputControlPointCount(DS.inputControlPoints);
  219. }
  220. // Hull shader.
  221. if (FnProps != nullptr && FnProps->shaderKind == DXIL::ShaderKind::Hull) {
  222. auto &HS = FnProps->ShaderProps.HS;
  223. M.SetPatchConstantFunction(HS.patchConstantFunc);
  224. M.SetTessellatorDomain(HS.domain);
  225. M.SetTessellatorPartitioning(HS.partition);
  226. M.SetTessellatorOutputPrimitive(HS.outputPrimitive);
  227. M.SetInputControlPointCount(HS.inputControlPoints);
  228. M.SetOutputControlPointCount(HS.outputControlPoints);
  229. M.SetMaxTessellationFactor(HS.maxTessFactor);
  230. }
  231. // Pixel shader.
  232. if (FnProps != nullptr && FnProps->shaderKind == DXIL::ShaderKind::Pixel) {
  233. auto &PS = FnProps->ShaderProps.PS;
  234. M.m_ShaderFlags.SetForceEarlyDepthStencil(PS.EarlyDepthStencil);
  235. }
  236. // DXIL type system.
  237. M.ResetTypeSystem(H.ReleaseTypeSystem());
  238. // Keep llvm used.
  239. M.EmitLLVMUsed();
  240. }
  241. class DxilGenerationPass : public ModulePass {
  242. HLModule *m_pHLModule;
  243. bool m_HasDbgInfo;
  244. HLSLExtensionsCodegenHelper *m_extensionsCodegenHelper;
  245. public:
  246. static char ID; // Pass identification, replacement for typeid
  247. explicit DxilGenerationPass(bool NoOpt = false)
  248. : ModulePass(ID), m_pHLModule(nullptr), NotOptimized(NoOpt), m_extensionsCodegenHelper(nullptr) {}
  249. const char *getPassName() const override { return "DXIL Generator"; }
  250. void SetExtensionsHelper(HLSLExtensionsCodegenHelper *helper) {
  251. m_extensionsCodegenHelper = helper;
  252. }
  253. bool runOnModule(Module &M) override {
  254. m_pHLModule = &M.GetOrCreateHLModule();
  255. const ShaderModel *SM = m_pHLModule->GetShaderModel();
  256. // Load up debug information, to cross-reference values and the instructions
  257. // used to load them.
  258. m_HasDbgInfo = getDebugMetadataVersionFromModule(M) != 0;
  259. if (!SM->IsCS()) {
  260. CreateDxilSignatures();
  261. // Allocate input output.
  262. AllocateDxilInputOutputs();
  263. GenerateDxilInputs();
  264. GenerateDxilOutputs();
  265. } else
  266. GenerateDxilCSInputs();
  267. if (SM->IsDS() || SM->IsHS())
  268. GenerateDxilPatchConstantLdSt();
  269. if (SM->IsHS())
  270. GenerateDxilPatchConstantFunctionInputs();
  271. std::unordered_map<Instruction *, Value *> handleMap;
  272. GenerateDxilResourceHandles(handleMap);
  273. GenerateDxilCBufferHandles(handleMap);
  274. if (NotOptimized || m_HasDbgInfo) {
  275. // For module which not promote mem2reg.
  276. // Add local resource load to handle map.
  277. MapLocalDxilResourceHandles(handleMap);
  278. }
  279. GenerateParamDxilResourceHandles(handleMap);
  280. GenerateDxilOperations(M, handleMap);
  281. // Translate precise on allocas into function call to keep the information after mem2reg.
  282. // The function calls will be removed after propagate precise attribute.
  283. TranslatePreciseAttribute();
  284. // Change struct type to legacy layout for cbuf and struct buf.
  285. UpdateStructTypeForLegacyLayout();
  286. // High-level metadata should now be turned into low-level metadata.
  287. const bool SkipInit = true;
  288. hlsl::DxilModule &DxilMod = M.GetOrCreateDxilModule(SkipInit);
  289. InitDxilModuleFromHLModule(*m_pHLModule, DxilMod, m_HasDbgInfo);
  290. HLModule::ClearHLMetadata(M);
  291. M.ResetHLModule();
  292. // Remove debug code when not debug info.
  293. if (!m_HasDbgInfo)
  294. DxilMod.StripDebugRelatedCode();
  295. return true;
  296. }
  297. private:
  298. void ProcessArgument(Function *func, DxilFunctionAnnotation *EntryAnnotation, Argument &arg, bool isPatchConstantFunction, bool forceOut, bool &hasClipPlane);
  299. void CreateDxilSignatures();
  300. // Allocate DXIL input/output.
  301. void AllocateDxilInputOutputs();
  302. // generate DXIL input load, output store
  303. void GenerateDxilInputs();
  304. void GenerateDxilOutputs();
  305. void GenerateDxilInputsOutputs(bool bInput);
  306. void GenerateDxilCSInputs();
  307. void GenerateDxilPatchConstantLdSt();
  308. void GenerateDxilPatchConstantFunctionInputs();
  309. void GenerateClipPlanesForVS(Value *outPosition);
  310. bool HasClipPlanes();
  311. void TranslateLocalDxilResourceUses(Function *F, std::unordered_map<Instruction *, Value *> &handleMap);
  312. void MapLocalDxilResourceHandles(
  313. std::unordered_map<Instruction *, Value *> &handleMap);
  314. void TranslateDxilResourceUses(
  315. DxilResourceBase &res,
  316. std::unordered_map<Instruction *, Value *> &handleMap);
  317. void GenerateDxilResourceHandles(
  318. std::unordered_map<Instruction *, Value *> &handleMap);
  319. void TranslateParamDxilResourceHandles(Function *F, std::unordered_map<Instruction *, Value *> &handleMap);
  320. void GenerateParamDxilResourceHandles(
  321. std::unordered_map<Instruction *, Value *> &handleMap);
  322. // Generate DXIL cbuffer handles.
  323. void GenerateDxilCBufferHandles(
  324. std::unordered_map<Instruction *, Value *> &handleMap);
  325. // Generate DXIL stream output operation.
  326. void GenerateStreamOutputOperation(Value *streamVal, unsigned streamID);
  327. // Generate DXIL stream output operations.
  328. void GenerateStreamOutputOperations();
  329. // change built-in funtion into DXIL operations
  330. void GenerateDxilOperations(
  331. Module &M, std::unordered_map<Instruction *, Value *> &handleMap);
  332. // Change struct type to legacy layout for cbuf and struct buf.
  333. void UpdateStructTypeForLegacyLayout();
  334. // Translate precise attribute into HL function call.
  335. void TranslatePreciseAttribute();
  336. // SignatureElement to Value map.
  337. std::unordered_map<DxilSignatureElement *, Value *> m_sigValueMap;
  338. // Set to save inout arguments.
  339. std::unordered_set<Value *> m_inoutArgSet;
  340. // SignatureElement which has precise attribute.
  341. std::unordered_set<DxilSignatureElement *> m_preciseSigSet;
  342. // Patch constant function inputs to signature element map.
  343. std::unordered_map<unsigned, DxilSignatureElement *> m_patchConstantInputsSigMap;
  344. // Input module is not optimized.
  345. bool NotOptimized;
  346. // For validation
  347. std::unordered_map<unsigned, std::unordered_set<unsigned> > m_InputSemanticsUsed,
  348. m_OutputSemanticsUsed[4], m_PatchConstantSemanticsUsed, m_OtherSemanticsUsed;
  349. };
  350. class SimplifyInst : public FunctionPass {
  351. public:
  352. static char ID;
  353. SimplifyInst() : FunctionPass(ID) {
  354. initializeScalarizerPass(*PassRegistry::getPassRegistry());
  355. }
  356. bool runOnFunction(Function &F) override;
  357. private:
  358. };
  359. }
  360. char SimplifyInst::ID = 0;
  361. FunctionPass *llvm::createSimplifyInstPass() { return new SimplifyInst(); }
  362. INITIALIZE_PASS(SimplifyInst, "simplify-inst", "Simplify Instructions", false, false)
  363. bool SimplifyInst::runOnFunction(Function &F) {
  364. for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
  365. BasicBlock *BB = BBI;
  366. llvm::SimplifyInstructionsInBlock(BB, nullptr);
  367. }
  368. return true;
  369. }
  370. // Decompose semantic name (eg FOO1=>FOO,1), change interp mode for SV_Position.
  371. // Return semantic index.
  372. static unsigned UpateSemanticAndInterpMode(StringRef &semName,
  373. DXIL::InterpolationMode &mode,
  374. DXIL::SigPointKind kind,
  375. LLVMContext &Context) {
  376. llvm::StringRef baseSemName; // The 'FOO' in 'FOO1'.
  377. uint32_t semIndex; // The '1' in 'FOO1'
  378. // Split semName and index.
  379. Semantic::DecomposeNameAndIndex(semName, &baseSemName, &semIndex);
  380. semName = baseSemName;
  381. const Semantic *semantic = Semantic::GetByName(semName, kind);
  382. if (semantic && semantic->GetKind() == Semantic::Kind::Position) {
  383. // Update interp mode to no_perspective version for SV_Position.
  384. switch (mode) {
  385. case InterpolationMode::Kind::LinearCentroid:
  386. mode = InterpolationMode::Kind::LinearNoperspectiveCentroid;
  387. break;
  388. case InterpolationMode::Kind::LinearSample:
  389. mode = InterpolationMode::Kind::LinearNoperspectiveSample;
  390. break;
  391. case InterpolationMode::Kind::Linear:
  392. mode = InterpolationMode::Kind::LinearNoperspective;
  393. break;
  394. case InterpolationMode::Kind::Constant: {
  395. Context.emitError("invalid interpolation mode for SV_Position");
  396. } break;
  397. }
  398. }
  399. return semIndex;
  400. }
  401. static DxilSignatureElement *FindArgInSignature(Argument &arg, llvm::StringRef semantic, DXIL::InterpolationMode interpMode, DXIL::SigPointKind kind,
  402. DxilSignature &sig) {
  403. // Match output ID.
  404. unsigned semIndex =
  405. UpateSemanticAndInterpMode(semantic, interpMode, kind, arg.getContext());
  406. for (uint32_t i = 0; i < sig.GetElements().size(); i++) {
  407. DxilSignatureElement &SE = sig.GetElement(i);
  408. bool semNameMatch = semantic.equals_lower(SE.GetName());
  409. bool semIndexMatch = semIndex == SE.GetSemanticIndexVec()[0];
  410. if (semNameMatch && semIndexMatch) {
  411. // Find a match.
  412. return &SE;
  413. }
  414. }
  415. DXASSERT(0, "must find a match");
  416. return nullptr;
  417. }
  418. static void replaceInputOutputWithIntrinsic(DXIL::SemanticKind semKind, Value * GV, OP * hlslOP, IRBuilder<>& Builder);
  419. void DxilGenerationPass::ProcessArgument(Function *func,
  420. DxilFunctionAnnotation *funcAnnotation,
  421. Argument &arg,
  422. bool isPatchConstantFunction,
  423. bool forceOut, bool &hasClipPlane) {
  424. const ShaderModel *SM = m_pHLModule->GetShaderModel();
  425. Type *Ty = arg.getType();
  426. DxilParameterAnnotation &paramAnnotation =
  427. funcAnnotation->GetParameterAnnotation(arg.getArgNo());
  428. hlsl::DxilParamInputQual qual =
  429. forceOut ? DxilParamInputQual::Out : paramAnnotation.GetParamInputQual();
  430. bool isInout = qual == DxilParamInputQual::Inout;
  431. // If this was an inout param, do the output side first
  432. if (isInout) {
  433. DXASSERT(!isPatchConstantFunction,
  434. "Patch Constant function should not have inout param");
  435. m_inoutArgSet.insert(&arg);
  436. ProcessArgument(func, funcAnnotation, arg, isPatchConstantFunction,
  437. /*forceOut*/ true, hasClipPlane);
  438. qual = DxilParamInputQual::In;
  439. }
  440. // Get stream index
  441. unsigned streamIdx = 0;
  442. switch (qual) {
  443. case DxilParamInputQual::OutStream1:
  444. streamIdx = 1;
  445. break;
  446. case DxilParamInputQual::OutStream2:
  447. streamIdx = 2;
  448. break;
  449. case DxilParamInputQual::OutStream3:
  450. streamIdx = 3;
  451. break;
  452. }
  453. const SigPoint *sigPoint = SigPoint::GetSigPoint(
  454. SigPointFromInputQual(qual, SM->GetKind(), isPatchConstantFunction));
  455. unsigned rows, cols;
  456. HLModule::GetParameterRowsAndCols(Ty, rows, cols, paramAnnotation);
  457. CompType EltTy = paramAnnotation.GetCompType();
  458. DXIL::InterpolationMode interpMode =
  459. paramAnnotation.GetInterpolationMode().GetKind();
  460. // Set undefined interpMode.
  461. if (!sigPoint->NeedsInterpMode())
  462. interpMode = InterpolationMode::Kind::Undefined;
  463. else if (interpMode == InterpolationMode::Kind::Undefined) {
  464. // Type-based default: linear for floats, constant for others.
  465. if (EltTy.IsFloatTy())
  466. interpMode = InterpolationMode::Kind::Linear;
  467. else
  468. interpMode = InterpolationMode::Kind::Constant;
  469. }
  470. llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
  471. if (semanticStr.empty()) {
  472. m_pHLModule->GetModule()->getContext().emitError(
  473. "Semantic must be defined for all parameters of an entry function or "
  474. "patch constant function");
  475. return;
  476. }
  477. UpateSemanticAndInterpMode(semanticStr, interpMode, sigPoint->GetKind(),
  478. arg.getContext());
  479. // Get Semantic interpretation, skipping if not in signature
  480. const Semantic *pSemantic = Semantic::GetByName(semanticStr);
  481. DXIL::SemanticInterpretationKind interpretation =
  482. SigPoint::GetInterpretation(pSemantic->GetKind(), sigPoint->GetKind(),
  483. SM->GetMajor(), SM->GetMinor());
  484. // Verify system value semantics do not overlap.
  485. // Note: Arbitrary are always in the signature and will be verified with a different mechanism.
  486. // For patch constant function, only validate patch constant elements (others already validated on hull function)
  487. if (pSemantic->GetKind() != DXIL::SemanticKind::Arbitrary &&
  488. (!isPatchConstantFunction || (!sigPoint->IsInput() && !sigPoint->IsOutput()))) {
  489. auto &SemanticUseMap = sigPoint->IsInput() ? m_InputSemanticsUsed :
  490. (sigPoint->IsOutput() ? m_OutputSemanticsUsed[streamIdx] :
  491. (sigPoint->IsPatchConstant() ? m_PatchConstantSemanticsUsed : m_OtherSemanticsUsed));
  492. if (SemanticUseMap.count((unsigned)pSemantic->GetKind()) > 0) {
  493. auto &SemanticIndexSet = SemanticUseMap[(unsigned)pSemantic->GetKind()];
  494. for (unsigned idx : paramAnnotation.GetSemanticIndexVec()) {
  495. if (SemanticIndexSet.count(idx) > 0) {
  496. m_pHLModule->GetModule()->getContext().emitError(
  497. Twine("Parameter with semantic ") + semanticStr +
  498. Twine(" has overlapping semantic index at ") + Twine(idx));
  499. return;
  500. }
  501. }
  502. }
  503. auto &SemanticIndexSet = SemanticUseMap[(unsigned)pSemantic->GetKind()];
  504. for (unsigned idx : paramAnnotation.GetSemanticIndexVec()) {
  505. SemanticIndexSet.emplace(idx);
  506. }
  507. // Enforce Coverage and InnerCoverage input mutual exclusivity
  508. if (sigPoint->IsInput()) {
  509. if ((pSemantic->GetKind() == DXIL::SemanticKind::Coverage && SemanticUseMap.count((unsigned)DXIL::SemanticKind::InnerCoverage) > 0) ||
  510. (pSemantic->GetKind() == DXIL::SemanticKind::InnerCoverage && SemanticUseMap.count((unsigned)DXIL::SemanticKind::Coverage) > 0)) {
  511. m_pHLModule->GetModule()->getContext().emitError(
  512. "Pixel shader inputs SV_Coverage and SV_InnerCoverage are mutually exclusive");
  513. return;
  514. }
  515. }
  516. }
  517. // Validate interpretation and replace argument usage with load/store
  518. // intrinsics
  519. {
  520. switch (interpretation) {
  521. case DXIL::SemanticInterpretationKind::NA:
  522. m_pHLModule->GetModule()->getContext().emitError(
  523. Twine("Semantic ") + semanticStr +
  524. Twine(" is invalid for shader model: ") + SM->GetKindName());
  525. return;
  526. case DXIL::SemanticInterpretationKind::NotInSig:
  527. case DXIL::SemanticInterpretationKind::Shadow: {
  528. IRBuilder<> funcBuilder(func->getEntryBlock().getFirstInsertionPt());
  529. if (DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(&arg)) {
  530. funcBuilder.SetCurrentDebugLocation(DDI->getDebugLoc());
  531. }
  532. replaceInputOutputWithIntrinsic(pSemantic->GetKind(), &arg,
  533. m_pHLModule->GetOP(), funcBuilder);
  534. if (interpretation == DXIL::SemanticInterpretationKind::NotInSig)
  535. return; // This argument should not be included in the signature
  536. break;
  537. }
  538. case DXIL::SemanticInterpretationKind::SV:
  539. case DXIL::SemanticInterpretationKind::SGV:
  540. case DXIL::SemanticInterpretationKind::Arb:
  541. case DXIL::SemanticInterpretationKind::Target:
  542. case DXIL::SemanticInterpretationKind::TessFactor:
  543. case DXIL::SemanticInterpretationKind::NotPacked:
  544. // Will be replaced with load/store intrinsics in
  545. // GenerateDxilInputsOutputs
  546. break;
  547. default:
  548. DXASSERT(false, "Unexpected SemanticInterpretationKind");
  549. return;
  550. }
  551. }
  552. // Determine signature this argument belongs in, if any
  553. DxilSignature *pSig = nullptr;
  554. DXIL::SignatureKind sigKind = sigPoint->GetSignatureKindWithFallback();
  555. switch (sigKind) {
  556. case DXIL::SignatureKind::Input:
  557. pSig = &m_pHLModule->GetInputSignature();
  558. break;
  559. case DXIL::SignatureKind::Output:
  560. pSig = &m_pHLModule->GetOutputSignature();
  561. break;
  562. case DXIL::SignatureKind::PatchConstant:
  563. pSig = &m_pHLModule->GetPatchConstantSignature();
  564. break;
  565. default:
  566. DXASSERT(false, "Expected real signature kind at this point");
  567. return; // No corresponding signature
  568. }
  569. // Create and add element to signature
  570. DxilSignatureElement *pSE = nullptr;
  571. {
  572. // Add signature element to appropriate maps
  573. if (isPatchConstantFunction &&
  574. sigKind != DXIL::SignatureKind::PatchConstant) {
  575. pSE = FindArgInSignature(arg, paramAnnotation.GetSemanticString(),
  576. interpMode, sigPoint->GetKind(), *pSig);
  577. m_patchConstantInputsSigMap[arg.getArgNo()] = pSE;
  578. } else {
  579. std::unique_ptr<DxilSignatureElement> SE = pSig->CreateElement();
  580. pSE = SE.get();
  581. pSig->AppendElement(std::move(SE));
  582. pSE->SetSigPointKind(sigPoint->GetKind());
  583. pSE->Initialize(semanticStr, EltTy, interpMode, rows, cols,
  584. Semantic::kUndefinedRow, Semantic::kUndefinedCol,
  585. pSE->GetID(), paramAnnotation.GetSemanticIndexVec());
  586. m_sigValueMap[pSE] = &arg;
  587. }
  588. }
  589. if (paramAnnotation.IsPrecise())
  590. m_preciseSigSet.insert(pSE);
  591. if (sigKind == DXIL::SignatureKind::Output &&
  592. pSemantic->GetKind() == Semantic::Kind::Position && hasClipPlane) {
  593. GenerateClipPlanesForVS(&arg);
  594. hasClipPlane = false;
  595. }
  596. // Set Output Stream.
  597. if (streamIdx > 0)
  598. pSE->SetOutputStream(streamIdx);
  599. }
  600. void DxilGenerationPass::CreateDxilSignatures() {
  601. const ShaderModel *SM = m_pHLModule->GetShaderModel();
  602. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  603. DXASSERT(EntryFunc->getReturnType()->isVoidTy(), "Should changed in SROA_Parameter_HLSL");
  604. DxilFunctionAnnotation *EntryAnnotation = m_pHLModule->GetFunctionAnnotation(EntryFunc);
  605. DXASSERT(EntryAnnotation, "must have function annotation for entry function");
  606. bool bHasClipPlane = SM->IsVS() ? HasClipPlanes() : false;
  607. for (Argument &arg : EntryFunc->getArgumentList()) {
  608. Type *Ty = arg.getType();
  609. // Skip streamout obj.
  610. if (HLModule::IsStreamOutputPtrType(Ty))
  611. continue;
  612. ProcessArgument(EntryFunc, EntryAnnotation, arg, /*isPatchConstantFunction*/false, /*forceOut*/false, bHasClipPlane);
  613. }
  614. if (bHasClipPlane) {
  615. EntryFunc->getContext().emitError("Cannot use clipplanes attribute without "
  616. "specifying a 4-component SV_Position "
  617. "output");
  618. }
  619. m_OtherSemanticsUsed.clear();
  620. if (SM->IsHS()) {
  621. HLFunctionProps &EntryProps = m_pHLModule->GetHLFunctionProps(EntryFunc);
  622. Function *patchConstantFunc = EntryProps.ShaderProps.HS.patchConstantFunc;
  623. DxilFunctionAnnotation *patchFuncAnnotation = m_pHLModule->GetFunctionAnnotation(patchConstantFunc);
  624. DXASSERT(patchFuncAnnotation, "must have function annotation for patch constant function");
  625. for (Argument &arg : patchConstantFunc->getArgumentList()) {
  626. ProcessArgument(patchConstantFunc, patchFuncAnnotation, arg, /*isPatchConstantFunction*/true, /*forceOut*/false, bHasClipPlane);
  627. }
  628. }
  629. }
  630. // Allocate input/output slots
  631. void DxilGenerationPass::AllocateDxilInputOutputs() {
  632. m_pHLModule->GetInputSignature().PackElements();
  633. if (!m_pHLModule->GetInputSignature().IsFullyAllocated()) {
  634. m_pHLModule->GetCtx().emitError("Failed to allocate all input signature elements in available space.");
  635. }
  636. m_pHLModule->GetOutputSignature().PackElements();
  637. if (!m_pHLModule->GetOutputSignature().IsFullyAllocated()) {
  638. m_pHLModule->GetCtx().emitError("Failed to allocate all output signature elements in available space.");
  639. }
  640. if (m_pHLModule->GetShaderModel()->IsHS() ||
  641. m_pHLModule->GetShaderModel()->IsDS()) {
  642. m_pHLModule->GetPatchConstantSignature().PackElements();
  643. if (!m_pHLModule->GetPatchConstantSignature().IsFullyAllocated()) {
  644. m_pHLModule->GetCtx().emitError("Failed to allocate all patch constant signature elements in available space.");
  645. }
  646. }
  647. }
  648. void DxilGenerationPass::GenerateDxilInputs() {
  649. GenerateDxilInputsOutputs(/*bInput*/ true);
  650. }
  651. void DxilGenerationPass::GenerateDxilOutputs() {
  652. GenerateDxilInputsOutputs(/*bInput*/ false);
  653. }
  654. static void GenerateStOutput(Function *stOutput, MutableArrayRef<Value *> args,
  655. IRBuilder<> &Builder, bool cast) {
  656. if (cast) {
  657. Value *value = args[DXIL::OperandIndex::kStoreOutputValOpIdx];
  658. args[DXIL::OperandIndex::kStoreOutputValOpIdx] =
  659. Builder.CreateZExt(value, Builder.getInt32Ty());
  660. }
  661. Builder.CreateCall(stOutput, args);
  662. }
  663. static void replaceStWithStOutput(Function *stOutput, StoreInst *stInst,
  664. OP::OpCode opcode, Constant *outputID,
  665. Value *idx, unsigned cols, bool bI1Cast, OP *hlslOP) {
  666. IRBuilder<> Builder(stInst);
  667. Value *val = stInst->getValueOperand();
  668. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  669. if (VectorType *VT = dyn_cast<VectorType>(val->getType())) {
  670. DXASSERT(cols == VT->getNumElements(), "vec size must match");
  671. for (unsigned col = 0; col < cols; col++) {
  672. Value *subVal = Builder.CreateExtractElement(val, col);
  673. Value *colIdx = hlslOP->GetU8Const(col);
  674. Value *args[] = {OpArg, outputID, idx, colIdx, subVal};
  675. GenerateStOutput(stOutput, args, Builder, bI1Cast);
  676. }
  677. // remove stInst
  678. stInst->eraseFromParent();
  679. } else if (!val->getType()->isArrayTy()) {
  680. // TODO: support case cols not 1
  681. DXASSERT(cols == 1, "only support scalar here");
  682. Value *colIdx = hlslOP->GetU8Const(0);
  683. Value *args[] = {OpArg, outputID, idx, colIdx, val};
  684. GenerateStOutput(stOutput, args, Builder, bI1Cast);
  685. // remove stInst
  686. stInst->eraseFromParent();
  687. } else {
  688. DXASSERT(0, "not support array yet");
  689. // TODO: support array.
  690. Value *colIdx = hlslOP->GetU8Const(0);
  691. ArrayType *AT = cast<ArrayType>(val->getType());
  692. Value *args[] = {OpArg, outputID, idx, colIdx, /*val*/nullptr};
  693. args;
  694. AT;
  695. }
  696. }
  697. static Value *GenerateLdInput(Function *loadInput, ArrayRef<Value *> args,
  698. IRBuilder<> &Builder, Value *zero, bool bCast, Type *Ty) {
  699. Value *input = Builder.CreateCall(loadInput, args);
  700. if (!bCast)
  701. return input;
  702. else {
  703. Value *bVal = Builder.CreateICmpNE(input, zero);
  704. IntegerType *IT = cast<IntegerType>(Ty);
  705. if (IT->getBitWidth() == 1)
  706. return bVal;
  707. else
  708. return Builder.CreateZExt(bVal, Ty);
  709. }
  710. }
  711. static Value *replaceLdWithLdInput(Function *loadInput,
  712. LoadInst *ldInst,
  713. unsigned cols,
  714. MutableArrayRef<Value *>args,
  715. bool bCast,
  716. OP *hlslOP) {
  717. IRBuilder<> Builder(ldInst);
  718. Type *Ty = ldInst->getType();
  719. Type *EltTy = Ty->getScalarType();
  720. // Change i1 to i32 for load input.
  721. Value *zero = hlslOP->GetU32Const(0);
  722. if (VectorType *VT = dyn_cast<VectorType>(Ty)) {
  723. Value *newVec = llvm::UndefValue::get(VT);
  724. DXASSERT(cols == VT->getNumElements(), "vec size must match");
  725. for (unsigned col = 0; col < cols; col++) {
  726. Value *colIdx = hlslOP->GetU8Const(col);
  727. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  728. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  729. newVec = Builder.CreateInsertElement(newVec, input, col);
  730. }
  731. ldInst->replaceAllUsesWith(newVec);
  732. ldInst->eraseFromParent();
  733. return newVec;
  734. } else {
  735. Value *colIdx = args[DXIL::OperandIndex::kLoadInputColOpIdx];
  736. if (colIdx == nullptr) {
  737. DXASSERT(cols == 1, "only support scalar here");
  738. colIdx = hlslOP->GetU8Const(0);
  739. }
  740. if (isa<ConstantInt>(colIdx)) {
  741. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  742. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  743. ldInst->replaceAllUsesWith(input);
  744. ldInst->eraseFromParent();
  745. return input;
  746. }
  747. else {
  748. // Vector indexing.
  749. // Load to array.
  750. ArrayType *AT = ArrayType::get(ldInst->getType(), cols);
  751. Value *arrayVec = Builder.CreateAlloca(AT);
  752. Value *zeroIdx = hlslOP->GetU32Const(0);
  753. for (unsigned col = 0; col < cols; col++) {
  754. Value *colIdx = hlslOP->GetU8Const(col);
  755. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  756. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  757. Value *GEP = Builder.CreateInBoundsGEP(arrayVec, {zeroIdx, colIdx});
  758. Builder.CreateStore(input, GEP);
  759. }
  760. Value *vecIndexingPtr = Builder.CreateInBoundsGEP(arrayVec, {zeroIdx, colIdx});
  761. Value *input = Builder.CreateLoad(vecIndexingPtr);
  762. ldInst->replaceAllUsesWith(input);
  763. ldInst->eraseFromParent();
  764. return input;
  765. }
  766. }
  767. }
  768. static void replaceDirectInputParameter(Value *param, Function *loadInput,
  769. unsigned cols,
  770. MutableArrayRef<Value *>args, bool bCast,
  771. OP *hlslOP, IRBuilder<> &Builder) {
  772. Value *zero = hlslOP->GetU32Const(0);
  773. Type *Ty = param->getType();
  774. Type *EltTy = Ty->getScalarType();
  775. if (VectorType *VT = dyn_cast<VectorType>(Ty)) {
  776. Value *newVec = llvm::UndefValue::get(VT);
  777. DXASSERT(cols == VT->getNumElements(), "vec size must match");
  778. for (unsigned col = 0; col < cols; col++) {
  779. Value *colIdx = hlslOP->GetU8Const(col);
  780. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  781. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  782. newVec = Builder.CreateInsertElement(newVec, input, col);
  783. }
  784. param->replaceAllUsesWith(newVec);
  785. } else if (!Ty->isArrayTy() && !HLMatrixLower::IsMatrixType(Ty)) {
  786. DXASSERT(cols == 1, "only support scalar here");
  787. Value *colIdx = hlslOP->GetU8Const(0);
  788. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  789. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  790. param->replaceAllUsesWith(input);
  791. } else if (HLMatrixLower::IsMatrixType(Ty)) {
  792. Value *colIdx = hlslOP->GetU8Const(0);
  793. colIdx;
  794. DXASSERT(param->hasOneUse(), "matrix arg should only has one use as matrix to vec");
  795. CallInst *CI = cast<CallInst>(param->user_back());
  796. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  797. DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLCast, "must be hlcast here");
  798. unsigned opcode = GetHLOpcode(CI);
  799. HLCastOpcode matOp = static_cast<HLCastOpcode>(opcode);
  800. switch (matOp) {
  801. case HLCastOpcode::ColMatrixToVecCast: {
  802. IRBuilder<> LocalBuilder(CI);
  803. Type *matTy = CI->getArgOperand(HLOperandIndex::kUnaryOpSrc0Idx)
  804. ->getType();
  805. unsigned col, row;
  806. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  807. std::vector<Value *> matElts(col * row);
  808. for (unsigned c = 0; c < col; c++) {
  809. Value *rowIdx = hlslOP->GetI32Const(c);
  810. args[DXIL::OperandIndex::kLoadInputRowOpIdx] = rowIdx;
  811. for (unsigned r = 0; r < row; r++) {
  812. Value *colIdx = hlslOP->GetU8Const(r);
  813. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  814. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  815. unsigned matIdx = c * row + r;
  816. matElts[matIdx] = input;
  817. }
  818. }
  819. Value *newVec = HLMatrixLower::BuildMatrix(EltTy, col, row, false,
  820. matElts, LocalBuilder);
  821. CI->replaceAllUsesWith(newVec);
  822. CI->eraseFromParent();
  823. } break;
  824. case HLCastOpcode::RowMatrixToVecCast: {
  825. IRBuilder<> LocalBuilder(CI);
  826. Type *matTy = CI->getArgOperand(HLOperandIndex::kUnaryOpSrc0Idx)
  827. ->getType();
  828. unsigned col, row;
  829. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  830. std::vector<Value *> matElts(col * row);
  831. for (unsigned r = 0; r < row; r++) {
  832. Value *rowIdx = hlslOP->GetI32Const(r);
  833. args[DXIL::OperandIndex::kLoadInputRowOpIdx] = rowIdx;
  834. for (unsigned c = 0; c < col; c++) {
  835. Value *colIdx = hlslOP->GetU8Const(c);
  836. args[DXIL::OperandIndex::kLoadInputColOpIdx] = colIdx;
  837. Value *input = GenerateLdInput(loadInput, args, Builder, zero, bCast, EltTy);
  838. unsigned matIdx = r * col + c;
  839. matElts[matIdx] = input;
  840. }
  841. }
  842. Value *newVec = HLMatrixLower::BuildMatrix(EltTy, col, row, false,
  843. matElts, LocalBuilder);
  844. CI->replaceAllUsesWith(newVec);
  845. CI->eraseFromParent();
  846. } break;
  847. }
  848. } else {
  849. DXASSERT(0, "invalid type for direct input");
  850. }
  851. }
  852. namespace {
  853. struct InputOutputAccessInfo {
  854. // For input output which has only 1 row, idx is 0.
  855. Value *idx;
  856. // VertexID for HS/DS/GS input.
  857. Value *vertexID;
  858. // Vector index.
  859. Value *vectorIdx;
  860. // Load/Store/LoadMat/StoreMat on input/output.
  861. Instruction *user;
  862. InputOutputAccessInfo(Value *index, Instruction *I)
  863. : idx(index), user(I), vertexID(nullptr), vectorIdx(nullptr) {}
  864. InputOutputAccessInfo(Value *index, Instruction *I, Value *ID, Value *vecIdx)
  865. : idx(index), user(I), vertexID(ID), vectorIdx(vecIdx) {}
  866. };
  867. }
  868. static void collectInputOutputAccessInfo(Value *GV, Constant *constZero,
  869. std::vector<InputOutputAccessInfo> &accessInfoList,
  870. bool hasVertexID, bool bInput) {
  871. auto User = GV->user_begin();
  872. auto UserE = GV->user_end();
  873. for (; User != UserE;) {
  874. Value *I = *(User++);
  875. if (LoadInst *ldInst = dyn_cast<LoadInst>(I)) {
  876. if (bInput) {
  877. InputOutputAccessInfo info = {constZero, ldInst};
  878. accessInfoList.push_back(info);
  879. }
  880. } else if (StoreInst *stInst = dyn_cast<StoreInst>(I)) {
  881. if (!bInput) {
  882. InputOutputAccessInfo info = {constZero, stInst};
  883. accessInfoList.push_back(info);
  884. }
  885. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
  886. // Vector indexing may has more indices.
  887. // Vector indexing changed to array indexing in SROA_HLSL.
  888. auto idx = GEP->idx_begin();
  889. DXASSERT_LOCALVAR(idx, idx->get() == constZero,
  890. "only support 0 offset for input pointer");
  891. Value *vertexID = nullptr;
  892. Value *vectorIdx = nullptr;
  893. gep_type_iterator GEPIt = gep_type_begin(GEP), E = gep_type_end(GEP);
  894. // Skip first pointer idx which must be 0.
  895. GEPIt++;
  896. if (hasVertexID) {
  897. // Save vertexID.
  898. vertexID = GEPIt.getOperand();
  899. GEPIt++;
  900. }
  901. // Start from first index.
  902. Value *rowIdx = GEPIt.getOperand();
  903. if (GEPIt != E) {
  904. if ((*GEPIt)->isVectorTy()) {
  905. // Vector indexing.
  906. rowIdx = constZero;
  907. vectorIdx = GEPIt.getOperand();
  908. DXASSERT_NOMSG((++GEPIt) == E);
  909. } else {
  910. // Array which may have vector indexing.
  911. GEPIt++;
  912. IRBuilder<> Builder(GEP);
  913. Type *idxTy = rowIdx->getType();
  914. for (; GEPIt != E; ++GEPIt) {
  915. DXASSERT(!GEPIt->isStructTy(),
  916. "Struct should be flattened SROA_Parameter_HLSL");
  917. DXASSERT(!GEPIt->isPointerTy(),
  918. "not support pointer type in middle of GEP");
  919. if (GEPIt->isArrayTy()) {
  920. Constant *arraySize =
  921. ConstantInt::get(idxTy, GEPIt->getArrayNumElements());
  922. rowIdx = Builder.CreateMul(rowIdx, arraySize);
  923. rowIdx = Builder.CreateAdd(rowIdx, GEPIt.getOperand());
  924. } else {
  925. Type *Ty = *GEPIt;
  926. DXASSERT_LOCALVAR(Ty, Ty->isVectorTy(),
  927. "must be vector type here to index");
  928. // Save vector idx.
  929. vectorIdx = GEPIt.getOperand();
  930. }
  931. }
  932. }
  933. } else
  934. rowIdx = constZero;
  935. auto GepUser = GEP->user_begin();
  936. auto GepUserE = GEP->user_end();
  937. Value *idxVal = rowIdx;
  938. for (; GepUser != GepUserE;) {
  939. auto GepUserIt = GepUser++;
  940. if (LoadInst *ldInst = dyn_cast<LoadInst>(*GepUserIt)) {
  941. if (bInput) {
  942. InputOutputAccessInfo info = {idxVal, ldInst, vertexID, vectorIdx};
  943. accessInfoList.push_back(info);
  944. }
  945. } else if (StoreInst *stInst = dyn_cast<StoreInst>(*GepUserIt)) {
  946. if (!bInput) {
  947. InputOutputAccessInfo info = {idxVal, stInst, vertexID, vectorIdx};
  948. accessInfoList.push_back(info);
  949. }
  950. } else if (CallInst *CI = dyn_cast<CallInst>(*GepUserIt)) {
  951. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  952. DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLMatLoadStore,
  953. "input/output should only used by ld/st");
  954. HLMatLoadStoreOpcode opcode = (HLMatLoadStoreOpcode)GetHLOpcode(CI);
  955. if ((opcode == HLMatLoadStoreOpcode::ColMatLoad || opcode == HLMatLoadStoreOpcode::RowMatLoad) ? bInput : !bInput) {
  956. InputOutputAccessInfo info = {idxVal, CI, vertexID, vectorIdx};
  957. accessInfoList.push_back(info);
  958. }
  959. } else
  960. DXASSERT(0, "input output should only used by ld/st");
  961. }
  962. } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
  963. InputOutputAccessInfo info = {constZero, CI};
  964. accessInfoList.push_back(info);
  965. } else
  966. DXASSERT(0, "input output should only used by ld/st");
  967. }
  968. }
  969. static void replaceInputOutputWithIntrinsic(DXIL::SemanticKind semKind, Value *GV, OP *hlslOP, IRBuilder<> &Builder) {
  970. Type *Ty = GV->getType();
  971. if (Ty->isPointerTy())
  972. Ty = Ty->getPointerElementType();
  973. OP::OpCode opcode;
  974. switch (semKind) {
  975. case Semantic::Kind::DomainLocation: opcode = OP::OpCode::DomainLocation; break;
  976. case Semantic::Kind::OutputControlPointID: opcode = OP::OpCode::OutputControlPointID; break;
  977. case Semantic::Kind::GSInstanceID: opcode = OP::OpCode::GSInstanceID; break;
  978. case Semantic::Kind::PrimitiveID: opcode = OP::OpCode::PrimitiveID; break;
  979. case Semantic::Kind::SampleIndex: opcode = OP::OpCode::SampleIndex; break;
  980. case Semantic::Kind::Coverage: opcode = OP::OpCode::Coverage; break;
  981. case Semantic::Kind::InnerCoverage: opcode = OP::OpCode::InnerCoverage; break;
  982. default:
  983. DXASSERT(0, "invalid semantic");
  984. return;
  985. }
  986. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty->getScalarType());
  987. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  988. Value *newArg = nullptr;
  989. if (semKind == Semantic::Kind::DomainLocation) {
  990. unsigned vecSize = 1;
  991. if (Ty->isVectorTy())
  992. vecSize = Ty->getVectorNumElements();
  993. newArg = Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU8Const(0)});
  994. if (vecSize > 1) {
  995. Value *result = UndefValue::get(Ty);
  996. result = Builder.CreateInsertElement(result, newArg, (uint64_t)0);
  997. for (unsigned i = 1; i < vecSize; i++) {
  998. Value *newElt =
  999. Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU8Const(i)});
  1000. result = Builder.CreateInsertElement(result, newElt, i);
  1001. }
  1002. newArg = result;
  1003. }
  1004. } else {
  1005. newArg = Builder.CreateCall(dxilFunc, {OpArg});
  1006. }
  1007. if (newArg->getType() != GV->getType()) {
  1008. DXASSERT_NOMSG(GV->getType()->isPointerTy());
  1009. for (User *U : GV->users()) {
  1010. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  1011. LI->replaceAllUsesWith(newArg);
  1012. }
  1013. }
  1014. } else {
  1015. GV->replaceAllUsesWith(newArg);
  1016. }
  1017. }
  1018. void DxilGenerationPass::GenerateDxilInputsOutputs(bool bInput) {
  1019. OP *hlslOP = m_pHLModule->GetOP();
  1020. const ShaderModel *pSM = m_pHLModule->GetShaderModel();
  1021. Module &M = *(m_pHLModule->GetModule());
  1022. OP::OpCode opcode = bInput ? OP::OpCode::LoadInput : OP::OpCode::StoreOutput;
  1023. bool bNeedVertexID = bInput && (pSM->IsGS() || pSM->IsDS() || pSM->IsHS());
  1024. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1025. Constant *columnConsts[] = {
  1026. hlslOP->GetU8Const(0), hlslOP->GetU8Const(1), hlslOP->GetU8Const(2),
  1027. hlslOP->GetU8Const(3), hlslOP->GetU8Const(4), hlslOP->GetU8Const(5),
  1028. hlslOP->GetU8Const(6), hlslOP->GetU8Const(7), hlslOP->GetU8Const(8),
  1029. hlslOP->GetU8Const(9), hlslOP->GetU8Const(10), hlslOP->GetU8Const(11),
  1030. hlslOP->GetU8Const(12), hlslOP->GetU8Const(13), hlslOP->GetU8Const(14),
  1031. hlslOP->GetU8Const(15)};
  1032. Constant *constZero = hlslOP->GetU32Const(0);
  1033. Value *undefVertexIdx =
  1034. UndefValue::get(Type::getInt32Ty(m_pHLModule->GetCtx()));
  1035. DxilSignature &Sig = bInput ? m_pHLModule->GetInputSignature()
  1036. : m_pHLModule->GetOutputSignature();
  1037. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  1038. Type *i1Ty = Type::getInt1Ty(constZero->getContext());
  1039. Type *i32Ty = constZero->getType();
  1040. llvm::SmallVector<unsigned, 8> removeIndices;
  1041. for (unsigned i = 0; i < Sig.GetElements().size(); i++) {
  1042. DxilSignatureElement *SE = &Sig.GetElement(i);
  1043. llvm::Type *Ty = SE->GetCompType().GetLLVMType(m_pHLModule->GetCtx());
  1044. // Cast i1 to i32 for load input.
  1045. bool bI1Cast = false;
  1046. if (Ty == i1Ty) {
  1047. bI1Cast = true;
  1048. Ty = i32Ty;
  1049. }
  1050. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty);
  1051. Constant *ID = hlslOP->GetU32Const(i);
  1052. unsigned cols = SE->GetCols();
  1053. Value *GV = m_sigValueMap[SE];
  1054. bool bIsInout = m_inoutArgSet.count(GV) > 0;
  1055. IRBuilder<> EntryBuilder(EntryFunc->getEntryBlock().getFirstInsertionPt());
  1056. if (DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(GV)) {
  1057. EntryBuilder.SetCurrentDebugLocation(DDI->getDebugLoc());
  1058. }
  1059. DXIL::SemanticInterpretationKind SI = SE->GetInterpretation();
  1060. DXASSERT_NOMSG(SI < DXIL::SemanticInterpretationKind::Invalid);
  1061. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NA);
  1062. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NotInSig);
  1063. if (SI == DXIL::SemanticInterpretationKind::Shadow)
  1064. continue; // Handled in ProcessArgument
  1065. if (!GV->getType()->isPointerTy()) {
  1066. DXASSERT(bInput, "direct parameter must be input");
  1067. Value *vertexID = undefVertexIdx;
  1068. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1069. Value *args[] = {OpArg, ID, /*rowIdx*/constZero, /*colIdx*/nullptr, vertexID};
  1070. replaceDirectInputParameter(GV, dxilFunc, cols, args, bI1Cast, hlslOP, EntryBuilder);
  1071. continue;
  1072. }
  1073. bool isArrayTy = GV->getType()->getPointerElementType()->isArrayTy();
  1074. bool isPrecise = m_preciseSigSet.count(SE);
  1075. if (isPrecise)
  1076. HLModule::MarkPreciseAttributeOnPtrWithFunctionCall(GV, M);
  1077. std::vector<InputOutputAccessInfo> accessInfoList;
  1078. collectInputOutputAccessInfo(GV, constZero, accessInfoList, bNeedVertexID && isArrayTy, bInput);
  1079. for (InputOutputAccessInfo &info : accessInfoList) {
  1080. Value *idxVal = info.idx;
  1081. Value *vertexID = undefVertexIdx;
  1082. if (bNeedVertexID && isArrayTy) {
  1083. vertexID = info.vertexID;
  1084. idxVal = constZero;
  1085. }
  1086. if (LoadInst *ldInst = dyn_cast<LoadInst>(info.user)) {
  1087. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1088. Value *args[] = {OpArg, ID, idxVal, info.vectorIdx, vertexID};
  1089. replaceLdWithLdInput(dxilFunc, ldInst, cols, args, bI1Cast, hlslOP);
  1090. }
  1091. else if (StoreInst *stInst = dyn_cast<StoreInst>(info.user)) {
  1092. if (bInput) {
  1093. DXASSERT_LOCALVAR(bIsInout, bIsInout, "input should not have store use.");
  1094. } else {
  1095. DXASSERT(!info.vectorIdx,
  1096. "not implement vector indexing on output yet.");
  1097. replaceStWithStOutput(dxilFunc, stInst, opcode, ID, idxVal, cols,
  1098. bI1Cast, hlslOP);
  1099. }
  1100. } else if (CallInst *CI = dyn_cast<CallInst>(info.user)) {
  1101. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  1102. // Intrinsic will be translated later.
  1103. if (group == HLOpcodeGroup::HLIntrinsic)
  1104. continue;
  1105. unsigned opcode = GetHLOpcode(CI);
  1106. DXASSERT(group == HLOpcodeGroup::HLMatLoadStore, "");
  1107. HLMatLoadStoreOpcode matOp = static_cast<HLMatLoadStoreOpcode>(opcode);
  1108. switch (matOp) {
  1109. case HLMatLoadStoreOpcode::ColMatLoad: {
  1110. IRBuilder<> LocalBuilder(CI);
  1111. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatLoadPtrOpIdx)
  1112. ->getType()
  1113. ->getPointerElementType();
  1114. unsigned col, row;
  1115. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  1116. std::vector<Value *> matElts(col * row);
  1117. for (unsigned c = 0; c < col; c++) {
  1118. Constant *constRowIdx = hlslOP->GetI32Const(c);
  1119. Value *rowIdx = LocalBuilder.CreateAdd(idxVal, constRowIdx);
  1120. for (unsigned r = 0; r < row; r++) {
  1121. Value *input = LocalBuilder.CreateCall(
  1122. dxilFunc, {OpArg, ID, rowIdx, columnConsts[r], vertexID});
  1123. unsigned matIdx = c * row + r;
  1124. matElts[matIdx] = input;
  1125. }
  1126. }
  1127. Value *newVec = HLMatrixLower::BuildMatrix(EltTy, col, row, true,
  1128. matElts, LocalBuilder);
  1129. CI->replaceAllUsesWith(newVec);
  1130. CI->eraseFromParent();
  1131. } break;
  1132. case HLMatLoadStoreOpcode::RowMatLoad: {
  1133. IRBuilder<> LocalBuilder(CI);
  1134. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatLoadPtrOpIdx)
  1135. ->getType()
  1136. ->getPointerElementType();
  1137. unsigned col, row;
  1138. Type *EltTy = HLMatrixLower::GetMatrixInfo(matTy, col, row);
  1139. std::vector<Value *> matElts(col * row);
  1140. for (unsigned r = 0; r < row; r++) {
  1141. Constant *constRowIdx = hlslOP->GetI32Const(r);
  1142. Value *rowIdx = LocalBuilder.CreateAdd(idxVal, constRowIdx);
  1143. for (unsigned c = 0; c < col; c++) {
  1144. Value *input = LocalBuilder.CreateCall(
  1145. dxilFunc, {OpArg, ID, rowIdx, columnConsts[c], vertexID});
  1146. unsigned matIdx = r * col + c;
  1147. matElts[matIdx] = input;
  1148. }
  1149. }
  1150. Value *newVec = HLMatrixLower::BuildMatrix(EltTy, col, row, false,
  1151. matElts, LocalBuilder);
  1152. CI->replaceAllUsesWith(newVec);
  1153. CI->eraseFromParent();
  1154. } break;
  1155. case HLMatLoadStoreOpcode::ColMatStore: {
  1156. IRBuilder<> LocalBuilder(CI);
  1157. Value *Val = CI->getArgOperand(HLOperandIndex::kMatStoreValOpIdx);
  1158. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatStoreDstPtrOpIdx)
  1159. ->getType()
  1160. ->getPointerElementType();
  1161. unsigned col, row;
  1162. HLMatrixLower::GetMatrixInfo(matTy, col, row);
  1163. for (unsigned c = 0; c < col; c++) {
  1164. Constant *constColIdx = hlslOP->GetI32Const(c);
  1165. Value *colIdx = LocalBuilder.CreateAdd(idxVal, constColIdx);
  1166. for (unsigned r = 0; r < row; r++) {
  1167. unsigned matIdx = c * row + r;
  1168. Value *Elt = LocalBuilder.CreateExtractElement(Val, matIdx);
  1169. LocalBuilder.CreateCall(
  1170. dxilFunc, {OpArg, ID, colIdx, columnConsts[r], Elt});
  1171. }
  1172. }
  1173. CI->eraseFromParent();
  1174. } break;
  1175. case HLMatLoadStoreOpcode::RowMatStore: {
  1176. IRBuilder<> LocalBuilder(CI);
  1177. Value *Val = CI->getArgOperand(HLOperandIndex::kMatStoreValOpIdx);
  1178. Type *matTy = CI->getArgOperand(HLOperandIndex::kMatStoreDstPtrOpIdx)
  1179. ->getType()
  1180. ->getPointerElementType();
  1181. unsigned col, row;
  1182. HLMatrixLower::GetMatrixInfo(matTy, col, row);
  1183. for (unsigned r = 0; r < row; r++) {
  1184. Constant *constRowIdx = hlslOP->GetI32Const(r);
  1185. Value *rowIdx = LocalBuilder.CreateAdd(idxVal, constRowIdx);
  1186. for (unsigned c = 0; c < col; c++) {
  1187. unsigned matIdx = r * col + c;
  1188. Value *Elt = LocalBuilder.CreateExtractElement(Val, matIdx);
  1189. LocalBuilder.CreateCall(
  1190. dxilFunc, {OpArg, ID, rowIdx, columnConsts[c], Elt});
  1191. }
  1192. }
  1193. CI->eraseFromParent();
  1194. } break;
  1195. }
  1196. } else
  1197. DXASSERT(0, "invalid operation on input output");
  1198. }
  1199. }
  1200. }
  1201. void DxilGenerationPass::GenerateDxilCSInputs() {
  1202. OP *hlslOP = m_pHLModule->GetOP();
  1203. Function *entry = m_pHLModule->GetEntryFunction();
  1204. DxilFunctionAnnotation *funcAnnotation = m_pHLModule->GetFunctionAnnotation(entry);
  1205. DXASSERT(funcAnnotation, "must find annotation for entry function");
  1206. IRBuilder<> Builder(entry->getEntryBlock().getFirstInsertionPt());
  1207. for (Argument &arg : entry->args()) {
  1208. DxilParameterAnnotation &paramAnnotation = funcAnnotation->GetParameterAnnotation(arg.getArgNo());
  1209. llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();
  1210. if (semanticStr.empty()) {
  1211. m_pHLModule->GetCtx().emitError(
  1212. "Semantic must be defined for all parameters of an entry function or patch constant function");
  1213. return;
  1214. }
  1215. const Semantic *semantic =
  1216. Semantic::GetByName(semanticStr, DXIL::SigPointKind::CSIn);
  1217. OP::OpCode opcode;
  1218. switch (semantic->GetKind()) {
  1219. case Semantic::Kind::GroupThreadID:
  1220. opcode = OP::OpCode::ThreadIdInGroup;
  1221. break;
  1222. case Semantic::Kind::GroupID:
  1223. opcode = OP::OpCode::GroupId;
  1224. break;
  1225. case Semantic::Kind::DispatchThreadID:
  1226. opcode = OP::OpCode::ThreadId;
  1227. break;
  1228. case Semantic::Kind::GroupIndex:
  1229. opcode = OP::OpCode::FlattenedThreadIdInGroup;
  1230. break;
  1231. default:
  1232. DXASSERT(semantic->IsInvalid(), "else compute shader semantics out-of-date");
  1233. this->m_pHLModule->GetCtx().emitError("invalid semantic found in CS");
  1234. return;
  1235. }
  1236. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1237. Type *Ty = arg.getType();
  1238. if (Ty->isPointerTy())
  1239. Ty = Ty->getPointerElementType();
  1240. Function *dxilFunc = hlslOP->GetOpFunc(opcode, Ty->getScalarType());
  1241. Value *newArg = nullptr;
  1242. if (opcode == OP::OpCode::FlattenedThreadIdInGroup) {
  1243. newArg = Builder.CreateCall(dxilFunc, {OpArg});
  1244. } else {
  1245. unsigned vecSize = 1;
  1246. if (Ty->isVectorTy())
  1247. vecSize = Ty->getVectorNumElements();
  1248. newArg = Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU32Const(0)});
  1249. if (vecSize > 1) {
  1250. Value *result = UndefValue::get(Ty);
  1251. result = Builder.CreateInsertElement(result, newArg, (uint64_t)0);
  1252. for (unsigned i = 1; i < vecSize; i++) {
  1253. Value *newElt =
  1254. Builder.CreateCall(dxilFunc, {OpArg, hlslOP->GetU32Const(i)});
  1255. result = Builder.CreateInsertElement(result, newElt, i);
  1256. }
  1257. newArg = result;
  1258. }
  1259. }
  1260. if (newArg->getType() != arg.getType()) {
  1261. DXASSERT_NOMSG(arg.getType()->isPointerTy());
  1262. for (User *U : arg.users()) {
  1263. LoadInst *LI = cast<LoadInst>(U);
  1264. LI->replaceAllUsesWith(newArg);
  1265. }
  1266. } else {
  1267. arg.replaceAllUsesWith(newArg);
  1268. }
  1269. }
  1270. }
  1271. void DxilGenerationPass::GenerateDxilPatchConstantLdSt() {
  1272. OP *hlslOP = m_pHLModule->GetOP();
  1273. Module &M = *(m_pHLModule->GetModule());
  1274. Constant *constZero = hlslOP->GetU32Const(0);
  1275. DxilSignature &Sig = m_pHLModule->GetPatchConstantSignature();
  1276. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  1277. auto InsertPt = EntryFunc->getEntryBlock().getFirstInsertionPt();
  1278. if (m_pHLModule->GetShaderModel()->IsHS()) {
  1279. HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
  1280. Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
  1281. InsertPt = patchConstantFunc->getEntryBlock().getFirstInsertionPt();
  1282. }
  1283. IRBuilder<> Builder(InsertPt);
  1284. Type *i1Ty = Type::getInt1Ty(constZero->getContext());
  1285. Type *i32Ty = constZero->getType();
  1286. for (unsigned i = 0; i < Sig.GetElements().size(); i++) {
  1287. DxilSignatureElement *SE = &Sig.GetElement(i);
  1288. Value *GV = m_sigValueMap[SE];
  1289. DXIL::SemanticInterpretationKind SI = SE->GetInterpretation();
  1290. DXASSERT_NOMSG(SI < DXIL::SemanticInterpretationKind::Invalid);
  1291. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NA);
  1292. DXASSERT_NOMSG(SI != DXIL::SemanticInterpretationKind::NotInSig);
  1293. if (SI == DXIL::SemanticInterpretationKind::Shadow)
  1294. continue; // Handled in ProcessArgument
  1295. Constant *ID = hlslOP->GetU32Const(i);
  1296. // Generate LoadPatchConstant.
  1297. Type *Ty = SE->GetCompType().GetLLVMType(m_pHLModule->GetCtx());
  1298. // Cast i1 to i32 for load input.
  1299. bool bI1Cast = false;
  1300. if (Ty == i1Ty) {
  1301. bI1Cast = true;
  1302. Ty = i32Ty;
  1303. }
  1304. Function *dxilLdFunc = hlslOP->GetOpFunc(OP::OpCode::LoadPatchConstant, Ty);
  1305. Function *dxilStFunc = hlslOP->GetOpFunc(OP::OpCode::StorePatchConstant, Ty);
  1306. unsigned cols = SE->GetCols();
  1307. if (!GV->getType()->isPointerTy()) {
  1308. // Must be DS input.
  1309. Constant *OpArg = hlslOP->GetU32Const(static_cast<unsigned>(OP::OpCode::LoadPatchConstant));
  1310. Value *args[] = {OpArg, ID, /*rowIdx*/constZero, /*colIdx*/nullptr};
  1311. replaceDirectInputParameter(GV, dxilLdFunc, cols, args, bI1Cast, hlslOP, Builder);
  1312. continue;
  1313. }
  1314. std::vector<InputOutputAccessInfo> accessInfoList;
  1315. collectInputOutputAccessInfo(GV, constZero, accessInfoList, /*hasVertexID*/ false,
  1316. !m_pHLModule->GetShaderModel()->IsHS());
  1317. bool isPrecise = m_preciseSigSet.count(SE);
  1318. if (isPrecise)
  1319. HLModule::MarkPreciseAttributeOnPtrWithFunctionCall(GV, M);
  1320. for (InputOutputAccessInfo &info : accessInfoList) {
  1321. Value *idxVal = info.idx;
  1322. if (LoadInst *ldInst = dyn_cast<LoadInst>(info.user)) {
  1323. OP::OpCode opcode = OP::OpCode::LoadPatchConstant;
  1324. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1325. Value *args[] = {OpArg, ID, idxVal, /*colIdx*/nullptr};
  1326. replaceLdWithLdInput(dxilLdFunc, ldInst, cols, args, bI1Cast, hlslOP);
  1327. } else if (StoreInst *stInst = dyn_cast<StoreInst>(info.user))
  1328. replaceStWithStOutput(dxilStFunc, stInst,
  1329. OP::OpCode::StorePatchConstant, ID, idxVal, cols,
  1330. bI1Cast, hlslOP);
  1331. else
  1332. DXASSERT(0, "invalid instruction on patch constant");
  1333. }
  1334. }
  1335. }
  1336. void DxilGenerationPass::GenerateDxilPatchConstantFunctionInputs() {
  1337. // Map input patch, to input sig
  1338. // LoadOutputControlPoint for output patch .
  1339. OP *hlslOP = m_pHLModule->GetOP();
  1340. Constant *constZero = hlslOP->GetU32Const(0);
  1341. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  1342. HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
  1343. Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
  1344. DxilFunctionAnnotation *patchFuncAnnotation = m_pHLModule->GetFunctionAnnotation(patchConstantFunc);
  1345. DXASSERT(patchFuncAnnotation, "must find annotation for patch constant function");
  1346. Type *i1Ty = Type::getInt1Ty(constZero->getContext());
  1347. Type *i32Ty = constZero->getType();
  1348. for (Argument &arg : patchConstantFunc->args()) {
  1349. DxilParameterAnnotation &paramAnnotation =
  1350. patchFuncAnnotation->GetParameterAnnotation(arg.getArgNo());
  1351. DxilParamInputQual inputQual = paramAnnotation.GetParamInputQual();
  1352. if (inputQual == DxilParamInputQual::InputPatch ||
  1353. inputQual == DxilParamInputQual::OutputPatch) {
  1354. DxilSignatureElement *SE = m_patchConstantInputsSigMap[arg.getArgNo()];
  1355. if (!SE) // Error should have been reported at an earlier stage.
  1356. continue;
  1357. Constant *inputID = hlslOP->GetU32Const(SE->GetID());
  1358. unsigned cols = SE->GetCols();
  1359. Type *Ty = SE->GetCompType().GetLLVMType(m_pHLModule->GetCtx());
  1360. // Cast i1 to i32 for load input.
  1361. bool bI1Cast = false;
  1362. if (Ty == i1Ty) {
  1363. bI1Cast = true;
  1364. Ty = i32Ty;
  1365. }
  1366. OP::OpCode opcode = inputQual == DxilParamInputQual::InputPatch?
  1367. OP::OpCode::LoadInput : OP::OpCode::LoadOutputControlPoint;
  1368. Function *dxilLdFunc = hlslOP->GetOpFunc(opcode, Ty);
  1369. std::vector<InputOutputAccessInfo> accessInfoList;
  1370. collectInputOutputAccessInfo(&arg, constZero, accessInfoList, /*hasVertexID*/ true, true);
  1371. for (InputOutputAccessInfo &info : accessInfoList) {
  1372. if (LoadInst *ldInst = dyn_cast<LoadInst>(info.user)) {
  1373. Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
  1374. Value *args[] = {OpArg, inputID, info.idx, info.vectorIdx, info.vertexID};
  1375. replaceLdWithLdInput(dxilLdFunc, ldInst, cols, args, bI1Cast, hlslOP);
  1376. } else
  1377. DXASSERT(0, "input should only be ld");
  1378. }
  1379. }
  1380. }
  1381. }
  1382. bool DxilGenerationPass::HasClipPlanes() {
  1383. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  1384. if (!m_pHLModule->HasHLFunctionProps(EntryFunc))
  1385. return false;
  1386. HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
  1387. auto &VS = EntryQual.ShaderProps.VS;
  1388. unsigned numClipPlanes = 0;
  1389. for (unsigned i=0;i<DXIL::kNumClipPlanes;i++) {
  1390. if (!VS.clipPlanes[i])
  1391. break;
  1392. numClipPlanes++;
  1393. }
  1394. return numClipPlanes != 0;
  1395. }
  1396. void DxilGenerationPass::GenerateClipPlanesForVS(Value *outPosition) {
  1397. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  1398. HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFunc);
  1399. auto &VS = EntryQual.ShaderProps.VS;
  1400. unsigned numClipPlanes = 0;
  1401. for (unsigned i=0;i<DXIL::kNumClipPlanes;i++) {
  1402. if (!VS.clipPlanes[i])
  1403. break;
  1404. numClipPlanes++;
  1405. }
  1406. if (!numClipPlanes)
  1407. return;
  1408. LLVMContext &Ctx = EntryFunc->getContext();
  1409. Function *dp4 = m_pHLModule->GetOP()->GetOpFunc(DXIL::OpCode::Dot4, Type::getFloatTy(Ctx));
  1410. Value *dp4Args[] = {
  1411. ConstantInt::get(Type::getInt32Ty(Ctx), static_cast<unsigned>(DXIL::OpCode::Dot4)),
  1412. nullptr, nullptr, nullptr, nullptr,
  1413. nullptr, nullptr, nullptr, nullptr,
  1414. };
  1415. // out SV_Position should only have StoreInst use.
  1416. // Done by LegalizeDxilInputOutputs in ScalarReplAggregatesHLSL.cpp
  1417. for (User *U : outPosition->users()) {
  1418. StoreInst *ST = cast<StoreInst>(U);
  1419. Value *posVal = ST->getValueOperand();
  1420. DXASSERT(posVal->getType()->isVectorTy(), "SV_Position must be a vector");
  1421. IRBuilder<> Builder(ST);
  1422. // Put position to args.
  1423. for (unsigned i=0;i<4;i++)
  1424. dp4Args[i+1] = Builder.CreateExtractElement(posVal, i);
  1425. // For each clip plane.
  1426. // clipDistance = dp4 position, clipPlane.
  1427. auto argIt = EntryFunc->getArgumentList().rbegin();
  1428. for (int clipIdx = numClipPlanes - 1; clipIdx >= 0; clipIdx--) {
  1429. Constant *GV = VS.clipPlanes[clipIdx];
  1430. DXASSERT_NOMSG(GV->hasOneUse());
  1431. StoreInst *ST = cast<StoreInst>(GV->user_back());
  1432. Value *clipPlane = ST->getValueOperand();
  1433. ST->eraseFromParent();
  1434. Argument &arg = *(argIt++);
  1435. // Put clipPlane to args.
  1436. for (unsigned i = 0; i < 4; i++)
  1437. dp4Args[i + 5] = Builder.CreateExtractElement(clipPlane, i);
  1438. Value *clipDistance = Builder.CreateCall(dp4, dp4Args);
  1439. Builder.CreateStore(clipDistance, &arg);
  1440. }
  1441. }
  1442. }
  1443. static Value *MergeImmResClass(Value *resClass) {
  1444. if (ConstantInt *Imm = dyn_cast<ConstantInt>(resClass)) {
  1445. return resClass;
  1446. } else {
  1447. PHINode *phi = cast<PHINode>(resClass);
  1448. Value *immResClass = MergeImmResClass(phi->getIncomingValue(0));
  1449. unsigned numOperands = phi->getNumOperands();
  1450. for (unsigned i=0;i<numOperands;i++)
  1451. phi->setIncomingValue(i, immResClass);
  1452. return immResClass;
  1453. }
  1454. }
  1455. static void AddCreateHandleForPhiNode(std::unordered_map<Instruction *, Value *> &handleMap, OP *hlslOP) {
  1456. Function *createHandle = hlslOP->GetOpFunc(
  1457. OP::OpCode::CreateHandle, llvm::Type::getVoidTy(hlslOP->GetCtx()));
  1458. std::unordered_set<PHINode *> objPhiList;
  1459. for (auto It : handleMap) {
  1460. Instruction *I = It.first;
  1461. for (User *U : I->users()) {
  1462. if (PHINode *phi = dyn_cast<PHINode>(U)) {
  1463. if (objPhiList.count(phi) == 0)
  1464. objPhiList.insert(phi);
  1465. }
  1466. }
  1467. }
  1468. // Scan phi list to add resource phi node which all operands are phi nodes.
  1469. std::vector<PHINode *> objPhiVec(objPhiList.begin(), objPhiList.end());
  1470. while (!objPhiVec.empty()) {
  1471. PHINode *phi = objPhiVec.back();
  1472. objPhiVec.pop_back();
  1473. unsigned numOperands = phi->getNumOperands();
  1474. for (unsigned i = 0; i < numOperands; i++) {
  1475. if (PHINode *nestPhi = dyn_cast<PHINode>(phi->getIncomingValue(i))) {
  1476. if (objPhiList.count(nestPhi) == 0) {
  1477. objPhiList.insert(nestPhi);
  1478. objPhiVec.emplace_back(nestPhi);
  1479. }
  1480. }
  1481. }
  1482. }
  1483. Value *opArg = hlslOP->GetU32Const((unsigned)OP::OpCode::CreateHandle);
  1484. Type *resClassTy = Type::getInt8Ty(opArg->getContext());
  1485. Type *resIDTy = opArg->getType();
  1486. Type *resAddressTy = opArg->getType();
  1487. // Phi node object is not uniform
  1488. Value *isUniformRes = hlslOP->GetI1Const(0);
  1489. // Generate phi for each operands of the createHandle
  1490. // Then generate createHandle with phi operands.
  1491. for (PHINode *phi : objPhiList) {
  1492. IRBuilder<> Builder(phi);
  1493. unsigned numOperands = phi->getNumOperands();
  1494. // res class must be same.
  1495. Value *resClassPhi = Builder.CreatePHI(resClassTy, numOperands);
  1496. Value *resIDPhi = Builder.CreatePHI(resIDTy, numOperands);
  1497. Value *resAddressPhi = Builder.CreatePHI(resAddressTy, numOperands);
  1498. IRBuilder<> HandleBuilder(phi->getParent()->getFirstNonPHI());
  1499. Value *handlePhi = HandleBuilder.CreateCall(createHandle, { opArg, resClassPhi, resIDPhi, resAddressPhi, isUniformRes});
  1500. handleMap[phi] = handlePhi;
  1501. }
  1502. // Setup operands for phi operands.
  1503. for (PHINode *phi : objPhiList) {
  1504. IRBuilder<> Builder(phi);
  1505. unsigned numOperands = phi->getNumOperands();
  1506. CallInst *handlePhi = cast<CallInst>(handleMap[phi]);
  1507. PHINode *resClassPhi = cast<PHINode>(handlePhi->getArgOperand(
  1508. DXIL::OperandIndex::kCreateHandleResClassOpIdx));
  1509. PHINode *resIDPhi = cast<PHINode>(
  1510. handlePhi->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx));
  1511. PHINode *resAddressPhi = cast<PHINode>(handlePhi->getArgOperand(
  1512. DXIL::OperandIndex::kCreateHandleResIndexOpIdx));
  1513. for (unsigned i = 0; i < numOperands; i++) {
  1514. BasicBlock *BB = phi->getIncomingBlock(i);
  1515. Instruction *phiOperand = cast<Instruction>(phi->getOperand(i));
  1516. DXASSERT(handleMap.count(phiOperand), "must map to handle");
  1517. CallInst *handleI = cast<CallInst>(handleMap[phiOperand]);
  1518. Value *resClassI = handleI->getArgOperand(
  1519. DXIL::OperandIndex::kCreateHandleResClassOpIdx);
  1520. resClassPhi->addIncoming(resClassI, BB);
  1521. Value *resIDI =
  1522. handleI->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
  1523. resIDPhi->addIncoming(resIDI, BB);
  1524. Value *resAddressI = handleI->getArgOperand(
  1525. DXIL::OperandIndex::kCreateHandleResIndexOpIdx);
  1526. resAddressPhi->addIncoming(resAddressI, BB);
  1527. }
  1528. }
  1529. // Merge res class into imm.
  1530. for (PHINode *phi : objPhiList) {
  1531. Instruction *phiOperand = cast<Instruction>(phi->getOperand(0));
  1532. CallInst *handle0 = cast<CallInst>(handleMap[phiOperand]);
  1533. Value *resClass =
  1534. handle0->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
  1535. Value *immResClass = MergeImmResClass(resClass);
  1536. handle0->setArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx,
  1537. immResClass);
  1538. }
  1539. // Drop all ref of the phi to help remove the useless createHandles.
  1540. for (PHINode *phi : objPhiList) {
  1541. Value *undefObj = UndefValue::get(phi->getType());
  1542. unsigned numOperands = phi->getNumOperands();
  1543. for (unsigned i = 0; i < numOperands; i++) {
  1544. phi->setIncomingValue(i, undefObj);
  1545. }
  1546. }
  1547. }
  1548. void DxilGenerationPass::TranslateLocalDxilResourceUses(Function *F, std::unordered_map<Instruction *, Value *> &handleMap) {
  1549. BasicBlock &BB = F->getEntryBlock(); // Get the entry node for the function
  1550. std::unordered_set<AllocaInst *> localResources;
  1551. for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I)
  1552. if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) { // Is it an alloca?
  1553. bool isResource = HLModule::IsHLSLObjectType(AI->getAllocatedType());
  1554. if (ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) {
  1555. Type *EltTy = AT->getElementType();
  1556. while (isa<ArrayType>(EltTy)) {
  1557. EltTy = EltTy->getArrayElementType();
  1558. }
  1559. isResource = HLModule::IsHLSLObjectType(EltTy);
  1560. // TODO: support local resource array.
  1561. DXASSERT(!isResource, "local resource array");
  1562. }
  1563. if (isResource) {
  1564. localResources.insert(AI);
  1565. }
  1566. }
  1567. SSAUpdater SSA;
  1568. SmallVector<Instruction *, 4> Insts;
  1569. // Make sure every resource load has mapped to handle.
  1570. while (!localResources.empty()) {
  1571. for (auto it = localResources.begin(); it != localResources.end();) {
  1572. AllocaInst *AI = *(it++);
  1573. // Build list of instructions to promote.
  1574. for (User *U : AI->users())
  1575. Insts.emplace_back(cast<Instruction>(U));
  1576. AllocaInst *NewAI = ResourcePromoter(Insts, SSA, handleMap).run(AI, Insts);
  1577. localResources.erase(AI);
  1578. if (NewAI)
  1579. localResources.insert(NewAI);
  1580. Insts.clear();
  1581. }
  1582. }
  1583. }
  1584. void DxilGenerationPass::MapLocalDxilResourceHandles(
  1585. std::unordered_map<Instruction *, Value *> &handleMap) {
  1586. Module &M = *m_pHLModule->GetModule();
  1587. for (Function &F : M.functions()) {
  1588. if (!F.isDeclaration())
  1589. TranslateLocalDxilResourceUses(&F, handleMap);
  1590. }
  1591. }
  1592. void DxilGenerationPass::TranslateParamDxilResourceHandles(Function *F, std::unordered_map<Instruction *, Value *> &handleMap) {
  1593. Type *handleTy = m_pHLModule->GetOP()->GetHandleType();
  1594. IRBuilder<> Builder(F->getEntryBlock().getFirstInsertionPt());
  1595. for (Argument &arg : F->args()) {
  1596. Type *Ty = arg.getType();
  1597. if (isa<PointerType>(Ty))
  1598. Ty = Ty->getPointerElementType();
  1599. SmallVector<unsigned,4> arraySizeList;
  1600. while (isa<ArrayType>(Ty)) {
  1601. arraySizeList.push_back(Ty->getArrayNumElements());
  1602. Ty = Ty->getArrayElementType();
  1603. }
  1604. DXIL::ResourceClass RC = m_pHLModule->GetResourceClass(Ty);
  1605. if (RC != DXIL::ResourceClass::Invalid) {
  1606. Type *curTy = handleTy;
  1607. for (auto it = arraySizeList.rbegin(), E = arraySizeList.rend(); it != E;
  1608. it++) {
  1609. curTy = ArrayType::get(curTy, *it);
  1610. }
  1611. curTy = PointerType::get(curTy, 0);
  1612. CallInst *castToHandle = cast<CallInst>(HLModule::EmitHLOperationCall(
  1613. Builder, HLOpcodeGroup::HLCast, 0, curTy,
  1614. {UndefValue::get(arg.getType())}, *F->getParent()));
  1615. for (User *U : arg.users()) {
  1616. Instruction *I = cast<Instruction>(U);
  1617. IRBuilder<> userBuilder(I);
  1618. if (LoadInst *ldInst = dyn_cast<LoadInst>(U)) {
  1619. Value *handleLd = userBuilder.CreateLoad(castToHandle);
  1620. handleMap[ldInst] = handleLd;
  1621. } else if (StoreInst *stInst = dyn_cast<StoreInst>(U)) {
  1622. Value *res = stInst->getValueOperand();
  1623. Value *handle = HLModule::EmitHLOperationCall(
  1624. userBuilder, HLOpcodeGroup::HLCast, 0, handleTy, {res},
  1625. *F->getParent());
  1626. userBuilder.CreateStore(handle, castToHandle);
  1627. } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
  1628. // Don't flatten argument here.
  1629. continue;
  1630. } else {
  1631. DXASSERT(
  1632. dyn_cast<GEPOperator>(U) != nullptr,
  1633. "else AddOpcodeParamForIntrinsic in CodeGen did not patch uses "
  1634. "to only have ld/st refer to temp object");
  1635. GEPOperator *GEP = cast<GEPOperator>(U);
  1636. std::vector<Value *> idxList(GEP->idx_begin(), GEP->idx_end());
  1637. Value *handleGEP = userBuilder.CreateGEP(castToHandle, idxList);
  1638. for (auto GEPU : GEP->users()) {
  1639. Instruction *GEPI = cast<Instruction>(GEPU);
  1640. IRBuilder<> gepUserBuilder(GEPI);
  1641. if (LoadInst *ldInst = dyn_cast<LoadInst>(GEPU)) {
  1642. handleMap[ldInst] = gepUserBuilder.CreateLoad(handleGEP);
  1643. } else {
  1644. StoreInst *stInst = cast<StoreInst>(GEPU);
  1645. Value *res = stInst->getValueOperand();
  1646. Value *handle = HLModule::EmitHLOperationCall(
  1647. gepUserBuilder, HLOpcodeGroup::HLCast, 0, handleTy, {res},
  1648. *F->getParent());
  1649. gepUserBuilder.CreateStore(handle, handleGEP);
  1650. }
  1651. }
  1652. }
  1653. }
  1654. castToHandle->setArgOperand(0, &arg);
  1655. }
  1656. }
  1657. }
  1658. void DxilGenerationPass::GenerateParamDxilResourceHandles(
  1659. std::unordered_map<Instruction *, Value *> &handleMap) {
  1660. Module &M = *m_pHLModule->GetModule();
  1661. for (Function &F : M.functions()) {
  1662. if (!F.isDeclaration())
  1663. TranslateParamDxilResourceHandles(&F, handleMap);
  1664. }
  1665. }
  1666. void DxilGenerationPass::TranslateDxilResourceUses(DxilResourceBase &res, std::unordered_map<Instruction *, Value *> &handleMap) {
  1667. OP *hlslOP = m_pHLModule->GetOP();
  1668. Function *createHandle = hlslOP->GetOpFunc(
  1669. OP::OpCode::CreateHandle, llvm::Type::getVoidTy(m_pHLModule->GetCtx()));
  1670. Value *opArg = hlslOP->GetU32Const((unsigned)OP::OpCode::CreateHandle);
  1671. bool isViewResource = res.GetClass() == DXIL::ResourceClass::SRV || res.GetClass() == DXIL::ResourceClass::UAV;
  1672. bool isROV = isViewResource && static_cast<DxilResource &>(res).IsROV();
  1673. std::string handleName = (res.GetGlobalName() + Twine("_") + Twine(res.GetResClassName())).str();
  1674. if (isViewResource)
  1675. handleName += (Twine("_") + Twine(res.GetResDimName())).str();
  1676. if (isROV)
  1677. handleName += "_ROV";
  1678. Value *resClassArg = hlslOP->GetU8Const(
  1679. static_cast<std::underlying_type<DxilResourceBase::Class>::type>(
  1680. res.GetClass()));
  1681. Value *resIDArg = hlslOP->GetU32Const(res.GetID());
  1682. // resLowerBound will be added after allocation in DxilCondenseResources.
  1683. Value *resLowerBound = hlslOP->GetU32Const(0);
  1684. // TODO: Set Non-uniform resource bit based on whether index comes from IOP_NonUniformResourceIndex.
  1685. Value *isUniformRes = hlslOP->GetI1Const(0);
  1686. Value *createHandleArgs[] = {opArg, resClassArg, resIDArg, resLowerBound, isUniformRes};
  1687. Value *GV = res.GetGlobalSymbol();
  1688. Module *pM = m_pHLModule->GetModule();
  1689. // TODO: add debug info to create handle.
  1690. DIVariable *DIV = nullptr;
  1691. DILocation *DL = nullptr;
  1692. if (m_HasDbgInfo) {
  1693. DebugInfoFinder &Finder = m_pHLModule->GetOrCreateDebugInfoFinder();
  1694. DIV =
  1695. HLModule::FindGlobalVariableDebugInfo(cast<GlobalVariable>(GV), Finder);
  1696. if (DIV)
  1697. // TODO: how to get col?
  1698. DL =
  1699. DILocation::get(pM->getContext(), DIV->getLine(), 1, DIV->getScope());
  1700. }
  1701. bool isResArray = res.GetRangeSize() > 1;
  1702. std::unordered_map<Function *, Value *> handleMapOnFunction;
  1703. for (iplist<Function>::iterator F : pM->getFunctionList()) {
  1704. if (!F->isDeclaration()) {
  1705. if (!isResArray) {
  1706. IRBuilder<> Builder(F->getEntryBlock().getFirstInsertionPt());
  1707. if (m_HasDbgInfo) {
  1708. // TODO: set debug info.
  1709. //Builder.SetCurrentDebugLocation(DL);
  1710. }
  1711. handleMapOnFunction[F] = Builder.CreateCall(createHandle, createHandleArgs, handleName);
  1712. }
  1713. }
  1714. }
  1715. for (auto U = GV->user_begin(), E = GV->user_end(); U != E; ) {
  1716. User *user = *(U++);
  1717. // Skip unused user.
  1718. if (user->user_empty())
  1719. continue;
  1720. if (LoadInst *ldInst = dyn_cast<LoadInst>(user)) {
  1721. Function *userF = ldInst->getParent()->getParent();
  1722. DXASSERT(handleMapOnFunction.count(userF), "must exist");
  1723. Value *handle = handleMapOnFunction[userF];
  1724. handleMap[ldInst] = handle;
  1725. } else {
  1726. DXASSERT(dyn_cast<GEPOperator>(user) != nullptr,
  1727. "else AddOpcodeParamForIntrinsic in CodeGen did not patch uses "
  1728. "to only have ld/st refer to temp object");
  1729. GEPOperator *GEP = cast<GEPOperator>(user);
  1730. Value *idx = nullptr;
  1731. if (GEP->getNumIndices() == 2) {
  1732. // one dim array of resource
  1733. idx = (GEP->idx_begin() + 1)->get();
  1734. } else {
  1735. gep_type_iterator GEPIt = gep_type_begin(GEP), E = gep_type_end(GEP);
  1736. // Must be instruction for multi dim array.
  1737. std::unique_ptr<IRBuilder<> > Builder;
  1738. if (GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(GEP)) {
  1739. Builder = std::make_unique<IRBuilder<> >(GEPInst);
  1740. } else {
  1741. Builder = std::make_unique<IRBuilder<> >(GV->getContext());
  1742. }
  1743. for (; GEPIt != E; ++GEPIt) {
  1744. if (GEPIt->isArrayTy()) {
  1745. unsigned arraySize = GEPIt->getArrayNumElements();
  1746. Value * tmpIdx = GEPIt.getOperand();
  1747. if (idx == nullptr)
  1748. idx = tmpIdx;
  1749. else {
  1750. idx = Builder->CreateMul(idx, Builder->getInt32(arraySize));
  1751. idx = Builder->CreateAdd(idx, tmpIdx);
  1752. }
  1753. }
  1754. }
  1755. }
  1756. createHandleArgs[DXIL::OperandIndex::kCreateHandleResIndexOpIdx] = idx;
  1757. Value *handle = nullptr;
  1758. if (GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(GEP)) {
  1759. IRBuilder<> Builder = IRBuilder<>(GEPInst);
  1760. handle = Builder.CreateCall(createHandle, createHandleArgs, handleName);
  1761. }
  1762. for (auto GEPU = GEP->user_begin(), GEPE = GEP->user_end(); GEPU != GEPE; ) {
  1763. // Must be load inst.
  1764. LoadInst *ldInst = cast<LoadInst>(*(GEPU++));
  1765. if (handle)
  1766. handleMap[ldInst] = handle;
  1767. else {
  1768. IRBuilder<> Builder = IRBuilder<>(ldInst);
  1769. handleMap[ldInst] = Builder.CreateCall(createHandle, createHandleArgs, handleName);
  1770. }
  1771. }
  1772. }
  1773. }
  1774. }
  1775. void DxilGenerationPass::GenerateDxilResourceHandles(std::unordered_map<Instruction *, Value *> &handleMap) {
  1776. // Create sampler handle first, may be used by SRV operations.
  1777. for (size_t i = 0; i < m_pHLModule->GetSamplers().size(); i++) {
  1778. DxilSampler &S = m_pHLModule->GetSampler(i);
  1779. TranslateDxilResourceUses(S, handleMap);
  1780. }
  1781. for (size_t i = 0; i < m_pHLModule->GetSRVs().size(); i++) {
  1782. HLResource &SRV = m_pHLModule->GetSRV(i);
  1783. TranslateDxilResourceUses(SRV, handleMap);
  1784. }
  1785. for (size_t i = 0; i < m_pHLModule->GetUAVs().size(); i++) {
  1786. HLResource &UAV = m_pHLModule->GetUAV(i);
  1787. TranslateDxilResourceUses(UAV, handleMap);
  1788. }
  1789. AddCreateHandleForPhiNode(handleMap, m_pHLModule->GetOP());
  1790. }
  1791. void DxilGenerationPass::GenerateDxilCBufferHandles(std::unordered_map<Instruction *, Value *> &handleMap) {
  1792. // For CBuffer, handle are mapped to CBufferSubscript.
  1793. OP *hlslOP = m_pHLModule->GetOP();
  1794. Function *createHandle = hlslOP->GetOpFunc(
  1795. OP::OpCode::CreateHandle, llvm::Type::getVoidTy(m_pHLModule->GetCtx()));
  1796. Value *opArg = hlslOP->GetU32Const((unsigned)OP::OpCode::CreateHandle);
  1797. Value *resClassArg = hlslOP->GetU8Const(
  1798. static_cast<std::underlying_type<DxilResourceBase::Class>::type>(
  1799. DXIL::ResourceClass::CBuffer));
  1800. Value *args[] = { opArg, resClassArg, nullptr, nullptr, hlslOP->GetI1Const(0)};
  1801. for (size_t i = 0; i < m_pHLModule->GetCBuffers().size(); i++) {
  1802. DxilCBuffer &CB = m_pHLModule->GetCBuffer(i);
  1803. GlobalVariable *GV = cast<GlobalVariable>(CB.GetGlobalSymbol());
  1804. std::string handleName = std::string(GV->getName()) + "_buffer";
  1805. DIVariable *DIV = nullptr;
  1806. DILocation *DL = nullptr;
  1807. if (m_HasDbgInfo) {
  1808. DebugInfoFinder &Finder = m_pHLModule->GetOrCreateDebugInfoFinder();
  1809. DIV = HLModule::FindGlobalVariableDebugInfo(GV, Finder);
  1810. if (DIV)
  1811. // TODO: how to get col?
  1812. DL = DILocation::get(createHandle->getContext(), DIV->getLine(), 1,
  1813. DIV->getScope());
  1814. }
  1815. Value *resIDArg = hlslOP->GetU32Const(CB.GetID());
  1816. args[DXIL::OperandIndex::kCreateHandleResIDOpIdx] = resIDArg;
  1817. // resLowerBound will be added after allocation in DxilCondenseResources.
  1818. Value *resLowerBound = hlslOP->GetU32Const(0);
  1819. if (CB.GetRangeSize() == 1) {
  1820. args[DXIL::OperandIndex::kCreateHandleResIndexOpIdx] = resLowerBound;
  1821. for (auto U : GV->users()) {
  1822. // Must CBufferSubscript.
  1823. CallInst *CI = cast<CallInst>((U));
  1824. IRBuilder<> Builder(CI);
  1825. CallInst *handle = Builder.CreateCall(createHandle, args, handleName);
  1826. if (m_HasDbgInfo) {
  1827. // TODO: add debug info.
  1828. //handle->setDebugLoc(DL);
  1829. }
  1830. handleMap[CI] = handle;
  1831. }
  1832. } else {
  1833. for (auto U : GV->users()) {
  1834. // Must CBufferSubscript.
  1835. CallInst *CI = cast<CallInst>(U);
  1836. IRBuilder<> Builder(CI);
  1837. args[DXIL::OperandIndex::kCreateHandleResIndexOpIdx] =
  1838. CI->getArgOperand(HLOperandIndex::kSubscriptIndexOpIdx);
  1839. CallInst *handle = Builder.CreateCall(createHandle, args, handleName);
  1840. handleMap[CI] = handle;
  1841. }
  1842. }
  1843. }
  1844. }
  1845. static void GenerateStOutput(Function *stOutput, Value *eltVal, Value *outputID,
  1846. Value *rowIdx, Value *colIdx, OP *hlslOP,
  1847. IRBuilder<> Builder) {
  1848. Constant *OpArg = hlslOP->GetU32Const((unsigned)OP::OpCode::StoreOutput);
  1849. Builder.CreateCall(stOutput, {OpArg, outputID, rowIdx, colIdx, eltVal});
  1850. }
  1851. static Value *TranslateStreamAppend(CallInst *CI, unsigned ID, hlsl::OP *OP) {
  1852. Function *DxilFunc = OP->GetOpFunc(OP::OpCode::EmitStream, CI->getType());
  1853. // TODO: generate a emit which has the data being emited as its argment.
  1854. // Value *data = CI->getArgOperand(HLOperandIndex::kStreamAppendDataOpIndex);
  1855. Constant *opArg = OP->GetU32Const((unsigned)OP::OpCode::EmitStream);
  1856. IRBuilder<> Builder(CI);
  1857. Constant *streamID = OP->GetU8Const(ID);
  1858. Value *args[] = {opArg, streamID};
  1859. return Builder.CreateCall(DxilFunc, args);
  1860. }
  1861. static Value *TranslateStreamCut(CallInst *CI, unsigned ID, hlsl::OP *OP) {
  1862. Function *DxilFunc = OP->GetOpFunc(OP::OpCode::CutStream, CI->getType());
  1863. // TODO: generate a emit which has the data being emited as its argment.
  1864. // Value *data = CI->getArgOperand(HLOperandIndex::kStreamAppendDataOpIndex);
  1865. Constant *opArg = OP->GetU32Const((unsigned)OP::OpCode::CutStream);
  1866. IRBuilder<> Builder(CI);
  1867. Constant *streamID = OP->GetU8Const(ID);
  1868. Value *args[] = {opArg, streamID};
  1869. return Builder.CreateCall(DxilFunc, args);
  1870. }
  1871. // Generate DXIL stream output operation.
  1872. void DxilGenerationPass::GenerateStreamOutputOperation(Value *streamVal, unsigned ID) {
  1873. OP * hlslOP = m_pHLModule->GetOP();
  1874. for (auto U = streamVal->user_begin(); U != streamVal->user_end();) {
  1875. Value *user = *(U++);
  1876. // Should only used by append, restartStrip .
  1877. CallInst *CI = cast<CallInst>(user);
  1878. HLOpcodeGroup group = GetHLOpcodeGroupByName(CI->getCalledFunction());
  1879. unsigned opcode = GetHLOpcode(CI);
  1880. DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLIntrinsic, "");
  1881. IntrinsicOp IOP = static_cast<IntrinsicOp>(opcode);
  1882. switch (IOP) {
  1883. case IntrinsicOp::MOP_Append:
  1884. TranslateStreamAppend(CI, ID, hlslOP);
  1885. break;
  1886. case IntrinsicOp::MOP_RestartStrip:
  1887. TranslateStreamCut(CI, ID, hlslOP);
  1888. break;
  1889. default:
  1890. DXASSERT(0, "invalid operation on stream");
  1891. }
  1892. CI->eraseFromParent();
  1893. }
  1894. }
  1895. // Generate DXIL stream output operations.
  1896. void DxilGenerationPass::GenerateStreamOutputOperations() {
  1897. Function *EntryFunc = m_pHLModule->GetEntryFunction();
  1898. DxilFunctionAnnotation *EntryAnnotation = m_pHLModule->GetFunctionAnnotation(EntryFunc);
  1899. DXASSERT(EntryAnnotation, "must find annotation for entry function");
  1900. for (Argument &arg : EntryFunc->getArgumentList()) {
  1901. if (HLModule::IsStreamOutputPtrType(arg.getType())) {
  1902. unsigned streamID = 0;
  1903. DxilParameterAnnotation &paramAnnotation = EntryAnnotation->GetParameterAnnotation(arg.getArgNo());
  1904. DxilParamInputQual inputQual = paramAnnotation.GetParamInputQual();
  1905. switch (inputQual) {
  1906. case DxilParamInputQual::OutStream0:
  1907. streamID = 0;
  1908. break;
  1909. case DxilParamInputQual::OutStream1:
  1910. streamID = 1;
  1911. break;
  1912. case DxilParamInputQual::OutStream2:
  1913. streamID = 2;
  1914. break;
  1915. case DxilParamInputQual::OutStream3:
  1916. default:
  1917. DXASSERT(inputQual == DxilParamInputQual::OutStream3, "invalid input qual.");
  1918. streamID = 3;
  1919. break;
  1920. }
  1921. GenerateStreamOutputOperation(&arg, streamID);
  1922. }
  1923. }
  1924. }
  1925. void DxilGenerationPass::GenerateDxilOperations(
  1926. Module &M, std::unordered_map<Instruction *, Value *> &handleMap) {
  1927. // remove all functions except entry function
  1928. Function *entry = m_pHLModule->GetEntryFunction();
  1929. const ShaderModel *pSM = m_pHLModule->GetShaderModel();
  1930. Function *patchConstantFunc = nullptr;
  1931. if (pSM->IsHS()) {
  1932. HLFunctionProps &funcProps = m_pHLModule->GetHLFunctionProps(entry);
  1933. patchConstantFunc = funcProps.ShaderProps.HS.patchConstantFunc;
  1934. }
  1935. for (auto F = M.begin(); F != M.end();) {
  1936. Function *func = F++;
  1937. if (func->isDeclaration())
  1938. continue;
  1939. if (func == entry)
  1940. continue;
  1941. if (func == patchConstantFunc)
  1942. continue;
  1943. if (func->user_empty())
  1944. func->eraseFromParent();
  1945. }
  1946. TranslateBuiltinOperations(*m_pHLModule, handleMap, m_extensionsCodegenHelper);
  1947. if (pSM->IsGS())
  1948. GenerateStreamOutputOperations();
  1949. // Remove unused HL Operation functions.
  1950. std::vector<Function *> deadList;
  1951. for (iplist<Function>::iterator F : M.getFunctionList()) {
  1952. if (F->isDeclaration()) {
  1953. hlsl::HLOpcodeGroup group = hlsl::GetHLOpcodeGroupByName(F);
  1954. if (group != HLOpcodeGroup::NotHL || F->isIntrinsic())
  1955. if (F->user_empty())
  1956. deadList.emplace_back(F);
  1957. }
  1958. }
  1959. for (Function *F : deadList)
  1960. F->eraseFromParent();
  1961. }
  1962. static void TranslatePreciseAttributeOnFunction(Function &F, Module &M) {
  1963. BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function
  1964. // Find allocas that has precise attribute, by looking at all instructions in
  1965. // the entry node
  1966. for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E;) {
  1967. Instruction *Inst = (I++);
  1968. if (AllocaInst *AI = dyn_cast<AllocaInst>(Inst)) {
  1969. if (HLModule::HasPreciseAttributeWithMetadata(AI)) {
  1970. HLModule::MarkPreciseAttributeOnPtrWithFunctionCall(AI, M);
  1971. }
  1972. } else {
  1973. DXASSERT(!HLModule::HasPreciseAttributeWithMetadata(Inst), "Only alloca can has precise metadata.");
  1974. }
  1975. }
  1976. FastMathFlags FMF;
  1977. FMF.setUnsafeAlgebra();
  1978. // Set fast math for all FPMathOperators.
  1979. // Already set FastMath in options. But that only enable things like fadd.
  1980. // Every inst which type is float can be cast to FPMathOperator.
  1981. for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
  1982. BasicBlock *BB = BBI;
  1983. for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
  1984. if (FPMathOperator *FPMath = dyn_cast<FPMathOperator>(I)) {
  1985. I->copyFastMathFlags(FMF);
  1986. }
  1987. }
  1988. }
  1989. }
  1990. void DxilGenerationPass::TranslatePreciseAttribute() {
  1991. bool bIEEEStrict = m_pHLModule->GetHLOptions().bIEEEStrict;
  1992. // If IEEE strict, everying is precise, don't need to mark it.
  1993. if (bIEEEStrict)
  1994. return;
  1995. Module &M = *m_pHLModule->GetModule();
  1996. // TODO: If not inline every function, for function has call site with precise
  1997. // argument and call site without precise argument, need to clone the function
  1998. // to propagate the precise for the precise call site.
  1999. // This should be done at CGMSHLSLRuntime::FinishCodeGen.
  2000. Function *EntryFn = m_pHLModule->GetEntryFunction();
  2001. TranslatePreciseAttributeOnFunction(*EntryFn, M);
  2002. if (m_pHLModule->GetShaderModel()->IsHS()) {
  2003. HLFunctionProps &EntryQual = m_pHLModule->GetHLFunctionProps(EntryFn);
  2004. Function *patchConstantFunc = EntryQual.ShaderProps.HS.patchConstantFunc;
  2005. TranslatePreciseAttributeOnFunction(*patchConstantFunc, M);
  2006. }
  2007. }
  2008. char DxilGenerationPass::ID = 0;
  2009. ModulePass *llvm::createDxilGenerationPass(bool NotOptimized, hlsl::HLSLExtensionsCodegenHelper *extensionsHelper) {
  2010. DxilGenerationPass *dxilPass = new DxilGenerationPass(NotOptimized);
  2011. dxilPass->SetExtensionsHelper(extensionsHelper);
  2012. return dxilPass;
  2013. }
  2014. INITIALIZE_PASS(DxilGenerationPass, "dxilgen", "HLSL DXIL Generation", false, false)
  2015. ///////////////////////////////////////////////////////////////////////////////
  2016. namespace {
  2017. StructType *UpdateStructTypeForLegacyLayout(StructType *ST, bool IsCBuf,
  2018. DxilTypeSystem &TypeSys, Module &M);
  2019. Type *UpdateFieldTypeForLegacyLayout(Type *Ty, bool IsCBuf, DxilFieldAnnotation &annotation,
  2020. DxilTypeSystem &TypeSys, Module &M) {
  2021. DXASSERT(!Ty->isPointerTy(), "struct field should not be a pointer");
  2022. if (Ty->isArrayTy()) {
  2023. Type *EltTy = Ty->getArrayElementType();
  2024. Type *UpdatedTy = UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, annotation, TypeSys, M);
  2025. if (EltTy == UpdatedTy)
  2026. return Ty;
  2027. else
  2028. return ArrayType::get(UpdatedTy, Ty->getArrayNumElements());
  2029. } else if (HLMatrixLower::IsMatrixType(Ty)) {
  2030. DXASSERT(annotation.HasMatrixAnnotation(), "must a matrix");
  2031. unsigned rows, cols;
  2032. Type *EltTy = HLMatrixLower::GetMatrixInfo(Ty, cols, rows);
  2033. // Get cols and rows from annotation.
  2034. const DxilMatrixAnnotation &matrix = annotation.GetMatrixAnnotation();
  2035. if (matrix.Orientation == MatrixOrientation::RowMajor) {
  2036. rows = matrix.Rows;
  2037. cols = matrix.Cols;
  2038. } else {
  2039. DXASSERT(matrix.Orientation == MatrixOrientation::ColumnMajor, "");
  2040. cols = matrix.Rows;
  2041. rows = matrix.Cols;
  2042. }
  2043. // CBuffer matrix must 4 * 4 bytes align.
  2044. if (IsCBuf)
  2045. cols = 4;
  2046. EltTy = UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, annotation, TypeSys, M);
  2047. Type *rowTy = VectorType::get(EltTy, cols);
  2048. return ArrayType::get(rowTy, rows);
  2049. } else if (StructType *ST = dyn_cast<StructType>(Ty)) {
  2050. return UpdateStructTypeForLegacyLayout(ST, IsCBuf, TypeSys, M);
  2051. } else if (Ty->isVectorTy()) {
  2052. Type *EltTy = Ty->getVectorElementType();
  2053. Type *UpdatedTy = UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, annotation, TypeSys, M);
  2054. if (EltTy == UpdatedTy)
  2055. return Ty;
  2056. else
  2057. return VectorType::get(UpdatedTy, Ty->getVectorNumElements());
  2058. } else {
  2059. Type *i32Ty = Type::getInt32Ty(Ty->getContext());
  2060. // Basic types.
  2061. if (Ty->isHalfTy()) {
  2062. return Type::getFloatTy(Ty->getContext());
  2063. } else if (IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
  2064. if (ITy->getBitWidth() <= 32)
  2065. return i32Ty;
  2066. else
  2067. return Ty;
  2068. } else
  2069. return Ty;
  2070. }
  2071. }
  2072. StructType *UpdateStructTypeForLegacyLayout(StructType *ST, bool IsCBuf,
  2073. DxilTypeSystem &TypeSys, Module &M) {
  2074. bool bUpdated = false;
  2075. unsigned fieldsCount = ST->getNumElements();
  2076. std::vector<Type *> fieldTypes(fieldsCount);
  2077. DxilStructAnnotation *SA = TypeSys.GetStructAnnotation(ST);
  2078. DXASSERT(SA, "must have annotation for struct type");
  2079. for (unsigned i = 0; i < fieldsCount; i++) {
  2080. Type *EltTy = ST->getElementType(i);
  2081. Type *UpdatedTy =
  2082. UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, SA->GetFieldAnnotation(i), TypeSys, M);
  2083. fieldTypes[i] = UpdatedTy;
  2084. if (EltTy != UpdatedTy)
  2085. bUpdated = true;
  2086. }
  2087. if (!bUpdated) {
  2088. return ST;
  2089. } else {
  2090. std::string legacyName = "dx.alignment.legacy." + ST->getName().str();
  2091. if (StructType *legacyST = M.getTypeByName(legacyName))
  2092. return legacyST;
  2093. StructType *NewST = StructType::create(ST->getContext(), fieldTypes, legacyName);
  2094. DxilStructAnnotation *NewSA = TypeSys.AddStructAnnotation(NewST);
  2095. // Clone annotation.
  2096. *NewSA = *SA;
  2097. return NewST;
  2098. }
  2099. }
  2100. void UpdateStructTypeForLegacyLayout(DxilResourceBase &Res, DxilTypeSystem &TypeSys, Module &M) {
  2101. GlobalVariable *GV = cast<GlobalVariable>(Res.GetGlobalSymbol());
  2102. Type *Ty = GV->getType()->getPointerElementType();
  2103. bool IsResourceArray = Res.GetRangeSize() != 1;
  2104. if (IsResourceArray) {
  2105. // Support Array of struct buffer.
  2106. if (Ty->isArrayTy())
  2107. Ty = Ty->getArrayElementType();
  2108. }
  2109. StructType *ST = cast<StructType>(Ty);
  2110. if (ST->isOpaque()) {
  2111. DXASSERT(Res.GetClass() == DxilResourceBase::Class::CBuffer,
  2112. "Only cbuffer can have opaque struct.");
  2113. return;
  2114. }
  2115. Type *UpdatedST = UpdateStructTypeForLegacyLayout(ST, IsResourceArray, TypeSys, M);
  2116. if (ST != UpdatedST) {
  2117. Type *Ty = GV->getType()->getPointerElementType();
  2118. if (IsResourceArray) {
  2119. // Support Array of struct buffer.
  2120. if (Ty->isArrayTy()) {
  2121. UpdatedST = ArrayType::get(UpdatedST, Ty->getArrayNumElements());
  2122. }
  2123. }
  2124. GlobalVariable *NewGV = cast<GlobalVariable>(M.getOrInsertGlobal(GV->getName().str() + "_legacy", UpdatedST));
  2125. Res.SetGlobalSymbol(NewGV);
  2126. // Delete old GV.
  2127. for (auto UserIt = GV->user_begin(); UserIt != GV->user_end(); ) {
  2128. Value *User = *(UserIt++);
  2129. DXASSERT(User->user_empty(),
  2130. "GV user should not have use after HLOperationLower.");
  2131. if (Instruction *I = dyn_cast<Instruction>(User)) {
  2132. I->eraseFromParent();
  2133. } else {
  2134. ConstantExpr *CE = cast<ConstantExpr>(User);
  2135. CE->dropAllReferences();
  2136. }
  2137. }
  2138. GV->eraseFromParent();
  2139. }
  2140. }
  2141. void UpdateStructTypeForLegacyLayoutOnHLM(HLModule &HLM) {
  2142. DxilTypeSystem &TypeSys = HLM.GetTypeSystem();
  2143. Module &M = *HLM.GetModule();
  2144. for (auto &CBuf : HLM.GetCBuffers()) {
  2145. UpdateStructTypeForLegacyLayout(*CBuf.get(), TypeSys, M);
  2146. }
  2147. for (auto &UAV : HLM.GetUAVs()) {
  2148. if (UAV->GetKind() == DxilResourceBase::Kind::StructuredBuffer)
  2149. UpdateStructTypeForLegacyLayout(*UAV.get(), TypeSys, M);
  2150. }
  2151. for (auto &SRV : HLM.GetSRVs()) {
  2152. if (SRV->GetKind() == DxilResourceBase::Kind::StructuredBuffer)
  2153. UpdateStructTypeForLegacyLayout(*SRV.get(), TypeSys, M);
  2154. }
  2155. }
  2156. }
  2157. void DxilGenerationPass::UpdateStructTypeForLegacyLayout() {
  2158. UpdateStructTypeForLegacyLayoutOnHLM(*m_pHLModule);
  2159. }
  2160. ///////////////////////////////////////////////////////////////////////////////
  2161. namespace {
  2162. class HLEmitMetadata : public ModulePass {
  2163. public:
  2164. static char ID; // Pass identification, replacement for typeid
  2165. explicit HLEmitMetadata() : ModulePass(ID) {}
  2166. const char *getPassName() const override { return "HLSL High-Level Metadata Emit"; }
  2167. bool runOnModule(Module &M) override {
  2168. if (M.HasHLModule()) {
  2169. M.GetHLModule().EmitHLMetadata();
  2170. return true;
  2171. }
  2172. return false;
  2173. }
  2174. };
  2175. }
  2176. char HLEmitMetadata::ID = 0;
  2177. ModulePass *llvm::createHLEmitMetadataPass() {
  2178. return new HLEmitMetadata();
  2179. }
  2180. INITIALIZE_PASS(HLEmitMetadata, "hlsl-hlemit", "HLSL High-Level Metadata Emit", false, false)
  2181. ///////////////////////////////////////////////////////////////////////////////
  2182. namespace {
  2183. class HLEnsureMetadata : public ModulePass {
  2184. public:
  2185. static char ID; // Pass identification, replacement for typeid
  2186. explicit HLEnsureMetadata() : ModulePass(ID) {}
  2187. const char *getPassName() const override { return "HLSL High-Level Metadata Ensure"; }
  2188. bool runOnModule(Module &M) override {
  2189. if (!M.HasHLModule()) {
  2190. M.GetOrCreateHLModule();
  2191. return true;
  2192. }
  2193. return false;
  2194. }
  2195. };
  2196. }
  2197. char HLEnsureMetadata::ID = 0;
  2198. ModulePass *llvm::createHLEnsureMetadataPass() {
  2199. return new HLEnsureMetadata();
  2200. }
  2201. INITIALIZE_PASS(HLEnsureMetadata, "hlsl-hlensure", "HLSL High-Level Metadata Ensure", false, false)
  2202. ///////////////////////////////////////////////////////////////////////////////
  2203. namespace {
  2204. Function *StripFunctionParameter(Function *F, DxilModule &DM,
  2205. DenseMap<const Function *, DISubprogram *> &FunctionDIs) {
  2206. Module &M = *DM.GetModule();
  2207. Type *VoidTy = Type::getVoidTy(M.getContext());
  2208. FunctionType *FT = FunctionType::get(VoidTy, false);
  2209. for (auto &arg : F->args()) {
  2210. if (!arg.user_empty())
  2211. return nullptr;
  2212. }
  2213. Function *NewFunc = Function::Create(FT, F->getLinkage(), F->getName());
  2214. M.getFunctionList().insert(F, NewFunc);
  2215. // Splice the body of the old function right into the new function.
  2216. NewFunc->getBasicBlockList().splice(NewFunc->begin(), F->getBasicBlockList());
  2217. // Patch the pointer to LLVM function in debug info descriptor.
  2218. auto DI = FunctionDIs.find(F);
  2219. if (DI != FunctionDIs.end()) {
  2220. DISubprogram *SP = DI->second;
  2221. SP->replaceFunction(NewFunc);
  2222. // Ensure the map is updated so it can be reused on subsequent argument
  2223. // promotions of the same function.
  2224. FunctionDIs.erase(DI);
  2225. FunctionDIs[NewFunc] = SP;
  2226. }
  2227. NewFunc->takeName(F);
  2228. DM.GetTypeSystem().EraseFunctionAnnotation(F);
  2229. F->eraseFromParent();
  2230. DM.GetTypeSystem().AddFunctionAnnotation(NewFunc);
  2231. return NewFunc;
  2232. }
  2233. class DxilEmitMetadata : public ModulePass {
  2234. public:
  2235. static char ID; // Pass identification, replacement for typeid
  2236. explicit DxilEmitMetadata() : ModulePass(ID) {}
  2237. const char *getPassName() const override { return "HLSL DXIL Metadata Emit"; }
  2238. bool runOnModule(Module &M) override {
  2239. if (M.HasDxilModule()) {
  2240. // Remove store undef output.
  2241. hlsl::OP *hlslOP = M.GetDxilModule().GetOP();
  2242. for (iplist<Function>::iterator F : M.getFunctionList()) {
  2243. if (!hlslOP->IsDxilOpFunc(F))
  2244. continue;
  2245. // Check store output.
  2246. FunctionType *FT = F->getFunctionType();
  2247. // Num params not match.
  2248. if (FT->getNumParams() !=
  2249. (DXIL::OperandIndex::kStoreOutputValOpIdx + 1))
  2250. continue;
  2251. Type *overloadTy =
  2252. FT->getParamType(DXIL::OperandIndex::kStoreOutputValOpIdx);
  2253. // overload illegal.
  2254. if (!hlslOP->IsOverloadLegal(DXIL::OpCode::StoreOutput, overloadTy))
  2255. continue;
  2256. Function *storeOutput =
  2257. hlslOP->GetOpFunc(DXIL::OpCode::StoreOutput, overloadTy);
  2258. // Not store output.
  2259. if (storeOutput != F)
  2260. continue;
  2261. for (auto it = F->user_begin(); it != F->user_end();) {
  2262. CallInst *CI = dyn_cast<CallInst>(*(it++));
  2263. if (!CI)
  2264. continue;
  2265. Value *V =
  2266. CI->getArgOperand(DXIL::OperandIndex::kStoreOutputValOpIdx);
  2267. // Remove the store of undef.
  2268. if (isa<UndefValue>(V))
  2269. CI->eraseFromParent();
  2270. }
  2271. }
  2272. // Remove unused external functions.
  2273. std::vector<Function *> deadList;
  2274. for (iplist<Function>::iterator F : M.getFunctionList()) {
  2275. if (F->isDeclaration()) {
  2276. if (F->user_empty())
  2277. deadList.emplace_back(F);
  2278. }
  2279. }
  2280. for (Function *F : deadList)
  2281. F->eraseFromParent();
  2282. // Remove unused internal global.
  2283. std::vector<GlobalVariable *> staticGVs;
  2284. for (GlobalVariable &GV : M.globals()) {
  2285. if (HLModule::IsStaticGlobal(&GV) ||
  2286. HLModule::IsSharedMemoryGlobal(&GV)) {
  2287. staticGVs.emplace_back(&GV);
  2288. }
  2289. }
  2290. for (GlobalVariable *GV : staticGVs) {
  2291. bool onlyStoreUse = true;
  2292. for (User *user : GV->users()) {
  2293. if (isa<StoreInst>(user))
  2294. continue;
  2295. if (isa<ConstantExpr>(user) && user->user_empty())
  2296. continue;
  2297. onlyStoreUse = false;
  2298. break;
  2299. }
  2300. if (onlyStoreUse) {
  2301. for (auto UserIt = GV->user_begin(); UserIt != GV->user_end();) {
  2302. Value *User = *(UserIt++);
  2303. if (Instruction *I = dyn_cast<Instruction>(User)) {
  2304. I->eraseFromParent();
  2305. } else {
  2306. ConstantExpr *CE = cast<ConstantExpr>(User);
  2307. CE->dropAllReferences();
  2308. }
  2309. }
  2310. GV->eraseFromParent();
  2311. }
  2312. }
  2313. DxilModule &DM = M.GetDxilModule();
  2314. DenseMap<const Function *, DISubprogram *> FunctionDIs =
  2315. makeSubprogramMap(M);
  2316. if (Function *PatchConstantFunc = DM.GetPatchConstantFunction()) {
  2317. PatchConstantFunc =
  2318. StripFunctionParameter(PatchConstantFunc, DM, FunctionDIs);
  2319. if (PatchConstantFunc)
  2320. DM.SetPatchConstantFunction(PatchConstantFunc);
  2321. }
  2322. if (Function *EntryFunc = DM.GetEntryFunction()) {
  2323. StringRef Name = DM.GetEntryFunctionName();
  2324. EntryFunc->setName(Name);
  2325. EntryFunc = StripFunctionParameter(EntryFunc, DM, FunctionDIs);
  2326. if (EntryFunc)
  2327. DM.SetEntryFunction(EntryFunc);
  2328. }
  2329. DM.CollectShaderFlags(); // Update flags to reflect any changes.
  2330. DM.EmitDxilMetadata();
  2331. return true;
  2332. }
  2333. return false;
  2334. }
  2335. };
  2336. }
  2337. char DxilEmitMetadata::ID = 0;
  2338. ModulePass *llvm::createDxilEmitMetadataPass() {
  2339. return new DxilEmitMetadata();
  2340. }
  2341. INITIALIZE_PASS(DxilEmitMetadata, "hlsl-dxilemit", "HLSL DXIL Metadata Emit", false, false)
  2342. ///////////////////////////////////////////////////////////////////////////////
  2343. // Precise propagate.
  2344. namespace {
  2345. class DxilPrecisePropagatePass : public ModulePass {
  2346. HLModule *m_pHLModule;
  2347. public:
  2348. static char ID; // Pass identification, replacement for typeid
  2349. explicit DxilPrecisePropagatePass() : ModulePass(ID), m_pHLModule(nullptr) {}
  2350. const char *getPassName() const override { return "DXIL Precise Propagate"; }
  2351. bool runOnModule(Module &M) override {
  2352. DxilModule &dxilModule = M.GetOrCreateDxilModule();
  2353. DxilTypeSystem &typeSys = dxilModule.GetTypeSystem();
  2354. std::vector<Function*> deadList;
  2355. for (Function &F : M.functions()) {
  2356. if (HLModule::HasPreciseAttribute(&F)) {
  2357. PropagatePreciseOnFunctionUser(F, typeSys);
  2358. deadList.emplace_back(&F);
  2359. }
  2360. }
  2361. for (Function *F : deadList)
  2362. F->eraseFromParent();
  2363. return true;
  2364. }
  2365. private:
  2366. void PropagatePreciseOnFunctionUser(Function &F, DxilTypeSystem &typeSys);
  2367. };
  2368. char DxilPrecisePropagatePass::ID = 0;
  2369. }
  2370. static void PropagatePreciseAttribute(Instruction *I, DxilTypeSystem &typeSys);
  2371. static void PropagatePreciseAttributeOnOperand(Value *V, DxilTypeSystem &typeSys, LLVMContext &Context) {
  2372. Instruction *I = dyn_cast<Instruction>(V);
  2373. // Skip none inst.
  2374. if (!I)
  2375. return;
  2376. FPMathOperator *FPMath = dyn_cast<FPMathOperator>(I);
  2377. // Skip none FPMath
  2378. if (!FPMath)
  2379. return;
  2380. // Skip inst already marked.
  2381. if (!I->hasUnsafeAlgebra())
  2382. return;
  2383. // TODO: skip precise on integer type, sample instruction...
  2384. // Clear fast math.
  2385. I->copyFastMathFlags(FastMathFlags());
  2386. PropagatePreciseAttribute(I, typeSys);
  2387. }
  2388. static void PropagatePreciseAttributeOnPointer(Value *Ptr, DxilTypeSystem &typeSys, LLVMContext &Context) {
  2389. // Find all store and propagate on the val operand of store.
  2390. // For CallInst, if Ptr is used as out parameter, mark it.
  2391. for (User *U : Ptr->users()) {
  2392. Instruction *user = cast<Instruction>(U);
  2393. if (StoreInst *stInst = dyn_cast<StoreInst>(user)) {
  2394. Value *val = stInst->getValueOperand();
  2395. PropagatePreciseAttributeOnOperand(val, typeSys, Context);
  2396. }
  2397. else if (CallInst *CI = dyn_cast<CallInst>(user)) {
  2398. bool bReadOnly = true;
  2399. Function *F = CI->getCalledFunction();
  2400. const DxilFunctionAnnotation *funcAnnotation = typeSys.GetFunctionAnnotation(F);
  2401. for (unsigned i = 0; i < CI->getNumArgOperands(); ++i) {
  2402. if (Ptr != CI->getArgOperand(i))
  2403. continue;
  2404. const DxilParameterAnnotation &paramAnnotation =
  2405. funcAnnotation->GetParameterAnnotation(i);
  2406. // OutputPatch and OutputStream will be checked after scalar repl.
  2407. // Here only check out/inout
  2408. if (paramAnnotation.GetParamInputQual() == DxilParamInputQual::Out ||
  2409. paramAnnotation.GetParamInputQual() == DxilParamInputQual::Inout) {
  2410. bReadOnly = false;
  2411. break;
  2412. }
  2413. }
  2414. if (!bReadOnly)
  2415. PropagatePreciseAttributeOnOperand(CI, typeSys, Context);
  2416. }
  2417. }
  2418. }
  2419. static void PropagatePreciseAttribute(Instruction *I, DxilTypeSystem &typeSys) {
  2420. LLVMContext &Context = I->getContext();
  2421. if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
  2422. PropagatePreciseAttributeOnPointer(AI, typeSys, Context);
  2423. } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
  2424. // Propagate every argument.
  2425. // TODO: only propagate precise argument.
  2426. for (Value *src : I->operands())
  2427. PropagatePreciseAttributeOnOperand(src, typeSys, Context);
  2428. } else if (FPMathOperator *FPMath = dyn_cast<FPMathOperator>(I)) {
  2429. // TODO: only propagate precise argument.
  2430. for (Value *src : I->operands())
  2431. PropagatePreciseAttributeOnOperand(src, typeSys, Context);
  2432. }
  2433. else if (LoadInst *ldInst = dyn_cast<LoadInst>(I)) {
  2434. Value *Ptr = ldInst->getPointerOperand();
  2435. PropagatePreciseAttributeOnPointer(Ptr, typeSys, Context);
  2436. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I))
  2437. PropagatePreciseAttributeOnPointer(GEP, typeSys, Context);
  2438. // TODO: support more case which need
  2439. }
  2440. void DxilPrecisePropagatePass::PropagatePreciseOnFunctionUser(Function &F, DxilTypeSystem &typeSys) {
  2441. LLVMContext &Context = F.getContext();
  2442. for (auto U=F.user_begin(), E=F.user_end();U!=E;) {
  2443. CallInst *CI = cast<CallInst>(*(U++));
  2444. Value *V = CI->getArgOperand(0);
  2445. PropagatePreciseAttributeOnOperand(V, typeSys, Context);
  2446. CI->eraseFromParent();
  2447. }
  2448. }
  2449. ModulePass *llvm::createDxilPrecisePropagatePass() {
  2450. return new DxilPrecisePropagatePass();
  2451. }
  2452. INITIALIZE_PASS(DxilPrecisePropagatePass, "hlsl-dxil-precise", "DXIL precise attribute propagate", false, false)