DxilUtil.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilUtil.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. // Dxil helper functions. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/DXIL/DxilTypeSystem.h"
  12. #include "dxc/DXIL/DxilUtil.h"
  13. #include "dxc/DXIL/DxilModule.h"
  14. #include "dxc/DXIL/DxilOperations.h"
  15. #include "dxc/HLSL/DxilConvergentName.h"
  16. #include "dxc/Support/Global.h"
  17. #include "llvm/ADT/StringExtras.h"
  18. #include "llvm/ADT/Twine.h"
  19. #include "llvm/Bitcode/ReaderWriter.h"
  20. #include "llvm/IR/DiagnosticInfo.h"
  21. #include "llvm/IR/DiagnosticPrinter.h"
  22. #include "llvm/IR/GlobalVariable.h"
  23. #include "llvm/IR/IntrinsicInst.h"
  24. #include "llvm/IR/LLVMContext.h"
  25. #include "llvm/IR/Module.h"
  26. #include "llvm/Support/MemoryBuffer.h"
  27. #include "llvm/Support/raw_ostream.h"
  28. #include "llvm/IR/Instructions.h"
  29. #include "llvm/IR/Constants.h"
  30. #include "llvm/IR/DIBuilder.h"
  31. #include "llvm/IR/IRBuilder.h"
  32. using namespace llvm;
  33. using namespace hlsl;
  34. namespace hlsl {
  35. namespace dxilutil {
  36. const char ManglingPrefix[] = "\01?";
  37. const char EntryPrefix[] = "dx.entry.";
  38. Type *GetArrayEltTy(Type *Ty) {
  39. if (isa<PointerType>(Ty))
  40. Ty = Ty->getPointerElementType();
  41. while (isa<ArrayType>(Ty)) {
  42. Ty = Ty->getArrayElementType();
  43. }
  44. return Ty;
  45. }
  46. bool HasDynamicIndexing(Value *V) {
  47. for (auto User : V->users()) {
  48. if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
  49. for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
  50. if (!isa<ConstantInt>(Idx))
  51. return true;
  52. }
  53. }
  54. }
  55. return false;
  56. }
  57. unsigned
  58. GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
  59. llvm::Type *Ty,
  60. DxilTypeSystem &typeSys) {
  61. while (isa<ArrayType>(Ty)) {
  62. Ty = Ty->getArrayElementType();
  63. }
  64. // Bytes.
  65. CompType compType = fieldAnnotation.GetCompType();
  66. unsigned compSize = compType.Is64Bit() ? 8 : compType.Is16Bit() && !typeSys.UseMinPrecision() ? 2 : 4;
  67. unsigned fieldSize = compSize;
  68. if (Ty->isVectorTy()) {
  69. fieldSize *= Ty->getVectorNumElements();
  70. } else if (StructType *ST = dyn_cast<StructType>(Ty)) {
  71. DxilStructAnnotation *EltAnnotation = typeSys.GetStructAnnotation(ST);
  72. if (EltAnnotation) {
  73. fieldSize = EltAnnotation->GetCBufferSize();
  74. } else {
  75. // Calculate size when don't have annotation.
  76. if (fieldAnnotation.HasMatrixAnnotation()) {
  77. const DxilMatrixAnnotation &matAnnotation =
  78. fieldAnnotation.GetMatrixAnnotation();
  79. unsigned rows = matAnnotation.Rows;
  80. unsigned cols = matAnnotation.Cols;
  81. if (matAnnotation.Orientation == MatrixOrientation::ColumnMajor) {
  82. rows = cols;
  83. cols = matAnnotation.Rows;
  84. } else if (matAnnotation.Orientation != MatrixOrientation::RowMajor) {
  85. // Invalid matrix orientation.
  86. fieldSize = 0;
  87. }
  88. fieldSize = (rows - 1) * 16 + cols * 4;
  89. } else {
  90. // Cannot find struct annotation.
  91. fieldSize = 0;
  92. }
  93. }
  94. }
  95. return fieldSize;
  96. }
  97. bool IsStaticGlobal(GlobalVariable *GV) {
  98. return GV->getLinkage() == GlobalValue::LinkageTypes::InternalLinkage &&
  99. GV->getType()->getPointerAddressSpace() == DXIL::kDefaultAddrSpace;
  100. }
  101. bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV) {
  102. return GV->getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace;
  103. }
  104. bool RemoveUnusedFunctions(Module &M, Function *EntryFunc,
  105. Function *PatchConstantFunc, bool IsLib) {
  106. std::vector<Function *> deadList;
  107. for (auto &F : M.functions()) {
  108. if (&F == EntryFunc || &F == PatchConstantFunc)
  109. continue;
  110. if (F.isDeclaration() || !IsLib) {
  111. if (F.user_empty())
  112. deadList.emplace_back(&F);
  113. }
  114. }
  115. bool bUpdated = deadList.size();
  116. for (Function *F : deadList)
  117. F->eraseFromParent();
  118. return bUpdated;
  119. }
  120. void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context) {
  121. DiagnosticPrinter *printer = reinterpret_cast<DiagnosticPrinter *>(Context);
  122. DI.print(*printer);
  123. }
  124. StringRef DemangleFunctionName(StringRef name) {
  125. if (!name.startswith(ManglingPrefix)) {
  126. // Name isn't mangled.
  127. return name;
  128. }
  129. size_t nameEnd = name.find_first_of("@");
  130. DXASSERT(nameEnd != StringRef::npos, "else Name isn't mangled but has \01?");
  131. return name.substr(2, nameEnd - 2);
  132. }
  133. std::string ReplaceFunctionName(StringRef originalName, StringRef newName) {
  134. if (originalName.startswith(ManglingPrefix)) {
  135. return (Twine(ManglingPrefix) + newName +
  136. originalName.substr(originalName.find_first_of('@'))).str();
  137. } else if (originalName.startswith(EntryPrefix)) {
  138. return (Twine(EntryPrefix) + newName).str();
  139. }
  140. return newName.str();
  141. }
  142. // From AsmWriter.cpp
  143. // PrintEscapedString - Print each character of the specified string, escaping
  144. // it if it is not printable or if it is an escape char.
  145. void PrintEscapedString(StringRef Name, raw_ostream &Out) {
  146. for (unsigned i = 0, e = Name.size(); i != e; ++i) {
  147. unsigned char C = Name[i];
  148. if (isprint(C) && C != '\\' && C != '"')
  149. Out << C;
  150. else
  151. Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
  152. }
  153. }
  154. void PrintUnescapedString(StringRef Name, raw_ostream &Out) {
  155. for (unsigned i = 0, e = Name.size(); i != e; ++i) {
  156. unsigned char C = Name[i];
  157. if (C == '\\') {
  158. C = Name[++i];
  159. unsigned value = hexDigitValue(C);
  160. if (value != -1U) {
  161. C = (unsigned char)value;
  162. unsigned value2 = hexDigitValue(Name[i+1]);
  163. assert(value2 != -1U && "otherwise, not a two digit hex escape");
  164. if (value2 != -1U) {
  165. C = (C << 4) + (unsigned char)value2;
  166. ++i;
  167. }
  168. } // else, the next character (in C) should be the escaped character
  169. }
  170. Out << C;
  171. }
  172. }
  173. std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::MemoryBuffer *MB,
  174. llvm::LLVMContext &Ctx,
  175. std::string &DiagStr) {
  176. // Note: the DiagStr is not used.
  177. auto pModule = llvm::parseBitcodeFile(MB->getMemBufferRef(), Ctx);
  178. if (!pModule) {
  179. return nullptr;
  180. }
  181. return std::unique_ptr<llvm::Module>(pModule.get().release());
  182. }
  183. std::unique_ptr<llvm::Module> LoadModuleFromBitcodeLazy(std::unique_ptr<llvm::MemoryBuffer> &&MB,
  184. llvm::LLVMContext &Ctx, std::string &DiagStr)
  185. {
  186. // Note: the DiagStr is not used.
  187. auto pModule = llvm::getLazyBitcodeModule(std::move(MB), Ctx, nullptr, true);
  188. if (!pModule) {
  189. return nullptr;
  190. }
  191. return std::unique_ptr<llvm::Module>(pModule.get().release());
  192. }
  193. std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::StringRef BC,
  194. llvm::LLVMContext &Ctx,
  195. std::string &DiagStr) {
  196. std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf(
  197. llvm::MemoryBuffer::getMemBuffer(BC, "", false));
  198. return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr);
  199. }
  200. DIGlobalVariable *FindGlobalVariableDebugInfo(GlobalVariable *GV,
  201. DebugInfoFinder &DbgInfoFinder) {
  202. struct GlobalFinder {
  203. GlobalVariable *GV;
  204. bool operator()(llvm::DIGlobalVariable *const arg) const {
  205. return arg->getVariable() == GV;
  206. }
  207. };
  208. GlobalFinder F = {GV};
  209. DebugInfoFinder::global_variable_iterator Found =
  210. std::find_if(DbgInfoFinder.global_variables().begin(),
  211. DbgInfoFinder.global_variables().end(), F);
  212. if (Found != DbgInfoFinder.global_variables().end()) {
  213. return *Found;
  214. }
  215. return nullptr;
  216. }
  217. static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
  218. DiagnosticSeverity severity);
  219. // If we don't have debug location and this is select/phi,
  220. // try recursing users to find instruction with debug info.
  221. // Only recurse phi/select and limit depth to prevent doing
  222. // too much work if no debug location found.
  223. static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
  224. Twine Msg,
  225. DiagnosticSeverity severity,
  226. unsigned depth = 0) {
  227. if (depth > 4)
  228. return false;
  229. if (I->getDebugLoc().get()) {
  230. EmitWarningOrErrorOnInstruction(I, Msg, severity);
  231. return true;
  232. }
  233. if (isa<PHINode>(I) || isa<SelectInst>(I)) {
  234. for (auto U : I->users())
  235. if (Instruction *UI = dyn_cast<Instruction>(U))
  236. if (EmitWarningOrErrorOnInstructionFollowPhiSelect(UI, Msg, severity,
  237. depth + 1))
  238. return true;
  239. }
  240. return false;
  241. }
  242. static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
  243. DiagnosticSeverity severity) {
  244. const DebugLoc &DL = I->getDebugLoc();
  245. if (!DL.get() && (isa<PHINode>(I) || isa<SelectInst>(I))) {
  246. if (EmitWarningOrErrorOnInstructionFollowPhiSelect(I, Msg, severity))
  247. return;
  248. }
  249. I->getContext().diagnose(DiagnosticInfoDxil(I->getParent()->getParent(),
  250. DL.get(), Msg, severity));
  251. }
  252. void EmitErrorOnInstruction(Instruction *I, Twine Msg) {
  253. EmitWarningOrErrorOnInstruction(I, Msg, DiagnosticSeverity::DS_Error);
  254. }
  255. void EmitWarningOnInstruction(Instruction *I, Twine Msg) {
  256. EmitWarningOrErrorOnInstruction(I, Msg, DiagnosticSeverity::DS_Warning);
  257. }
  258. static void EmitWarningOrErrorOnFunction(llvm::LLVMContext &Ctx, Function *F, Twine Msg,
  259. DiagnosticSeverity severity) {
  260. DILocation *DLoc = nullptr;
  261. if (DISubprogram *DISP = getDISubprogram(F)) {
  262. DLoc = DILocation::get(F->getContext(), DISP->getLine(), 0,
  263. DISP, nullptr /*InlinedAt*/);
  264. }
  265. Ctx.diagnose(DiagnosticInfoDxil(F, DLoc, Msg, severity));
  266. }
  267. void EmitErrorOnFunction(llvm::LLVMContext &Ctx, Function *F, Twine Msg) {
  268. EmitWarningOrErrorOnFunction(Ctx, F, Msg, DiagnosticSeverity::DS_Error);
  269. }
  270. void EmitWarningOnFunction(llvm::LLVMContext &Ctx, Function *F, Twine Msg) {
  271. EmitWarningOrErrorOnFunction(Ctx, F, Msg, DiagnosticSeverity::DS_Warning);
  272. }
  273. static void EmitWarningOrErrorOnGlobalVariable(llvm::LLVMContext &Ctx, GlobalVariable *GV,
  274. Twine Msg, DiagnosticSeverity severity) {
  275. DIVariable *DIV = nullptr;
  276. DILocation *DLoc = nullptr;
  277. if (GV) {
  278. Module &M = *GV->getParent();
  279. if (hasDebugInfo(M)) {
  280. DebugInfoFinder FinderObj;
  281. DebugInfoFinder &Finder = FinderObj;
  282. // Debug modules have no dxil modules. Use it if you got it.
  283. if (M.HasDxilModule())
  284. Finder = M.GetDxilModule().GetOrCreateDebugInfoFinder();
  285. else
  286. Finder.processModule(M);
  287. DIV = FindGlobalVariableDebugInfo(GV, Finder);
  288. if (DIV)
  289. DLoc = DILocation::get(GV->getContext(), DIV->getLine(), 0,
  290. DIV->getScope(), nullptr /*InlinedAt*/);
  291. }
  292. }
  293. Ctx.diagnose(DiagnosticInfoDxil(nullptr /*Function*/, DLoc, Msg, severity));
  294. }
  295. void EmitErrorOnGlobalVariable(llvm::LLVMContext &Ctx, GlobalVariable *GV, Twine Msg) {
  296. EmitWarningOrErrorOnGlobalVariable(Ctx, GV, Msg, DiagnosticSeverity::DS_Error);
  297. }
  298. void EmitWarningOnGlobalVariable(llvm::LLVMContext &Ctx, GlobalVariable *GV, Twine Msg) {
  299. EmitWarningOrErrorOnGlobalVariable(Ctx, GV, Msg, DiagnosticSeverity::DS_Warning);
  300. }
  301. const char *kResourceMapErrorMsg =
  302. "local resource not guaranteed to map to unique global resource.";
  303. void EmitResMappingError(Instruction *Res) {
  304. EmitErrorOnInstruction(Res, kResourceMapErrorMsg);
  305. }
  306. // Mostly just a locationless diagnostic output
  307. static void EmitWarningOrErrorOnContext(LLVMContext &Ctx, Twine Msg, DiagnosticSeverity severity) {
  308. Ctx.diagnose(DiagnosticInfoDxil(nullptr /*Func*/, nullptr /*DLoc*/,
  309. Msg, severity));
  310. }
  311. void EmitErrorOnContext(LLVMContext &Ctx, Twine Msg) {
  312. EmitWarningOrErrorOnContext(Ctx, Msg, DiagnosticSeverity::DS_Error);
  313. }
  314. void EmitWarningOnContext(LLVMContext &Ctx, Twine Msg) {
  315. EmitWarningOrErrorOnContext(Ctx, Msg, DiagnosticSeverity::DS_Warning);
  316. }
  317. void EmitNoteOnContext(LLVMContext &Ctx, Twine Msg) {
  318. EmitWarningOrErrorOnContext(Ctx, Msg, DiagnosticSeverity::DS_Note);
  319. }
  320. void CollectSelect(llvm::Instruction *Inst,
  321. std::unordered_set<llvm::Instruction *> &selectSet) {
  322. unsigned startOpIdx = 0;
  323. // Skip Cond for Select.
  324. if (isa<SelectInst>(Inst)) {
  325. startOpIdx = 1;
  326. } else if (!isa<PHINode>(Inst)) {
  327. // Only check phi and select here.
  328. return;
  329. }
  330. // Already add.
  331. if (selectSet.count(Inst))
  332. return;
  333. selectSet.insert(Inst);
  334. // Scan operand to add node which is phi/select.
  335. unsigned numOperands = Inst->getNumOperands();
  336. for (unsigned i = startOpIdx; i < numOperands; i++) {
  337. Value *V = Inst->getOperand(i);
  338. if (Instruction *I = dyn_cast<Instruction>(V)) {
  339. CollectSelect(I, selectSet);
  340. }
  341. }
  342. }
  343. Value *MergeSelectOnSameValue(Instruction *SelInst, unsigned startOpIdx,
  344. unsigned numOperands) {
  345. Value *op0 = nullptr;
  346. for (unsigned i = startOpIdx; i < numOperands; i++) {
  347. Value *op = SelInst->getOperand(i);
  348. if (i == startOpIdx) {
  349. op0 = op;
  350. } else {
  351. if (op0 != op)
  352. return nullptr;
  353. }
  354. }
  355. if (op0) {
  356. SelInst->replaceAllUsesWith(op0);
  357. SelInst->eraseFromParent();
  358. }
  359. return op0;
  360. }
  361. bool SimplifyTrivialPHIs(BasicBlock *BB) {
  362. bool Changed = false;
  363. SmallVector<Instruction *, 16> Removed;
  364. for (Instruction &I : *BB) {
  365. PHINode *PN = dyn_cast<PHINode>(&I);
  366. if (!PN)
  367. continue;
  368. if (PN->getNumIncomingValues() == 1) {
  369. Value *V = PN->getIncomingValue(0);
  370. PN->replaceAllUsesWith(V);
  371. Removed.push_back(PN);
  372. Changed = true;
  373. }
  374. }
  375. for (Instruction *I : Removed)
  376. I->eraseFromParent();
  377. return Changed;
  378. }
  379. llvm::BasicBlock *GetSwitchSuccessorForCond(llvm::SwitchInst *Switch,llvm::ConstantInt *Cond) {
  380. for (auto it = Switch->case_begin(), end = Switch->case_end(); it != end; it++) {
  381. if (it.getCaseValue() == Cond) {
  382. return it.getCaseSuccessor();
  383. break;
  384. }
  385. }
  386. return Switch->getDefaultDest();
  387. }
  388. static DbgValueInst *FindDbgValueInst(Value *Val) {
  389. if (auto *ValAsMD = LocalAsMetadata::getIfExists(Val)) {
  390. if (auto *ValMDAsVal = MetadataAsValue::getIfExists(Val->getContext(), ValAsMD)) {
  391. for (User *ValMDUser : ValMDAsVal->users()) {
  392. if (DbgValueInst *DbgValInst = dyn_cast<DbgValueInst>(ValMDUser))
  393. return DbgValInst;
  394. }
  395. }
  396. }
  397. return nullptr;
  398. }
  399. void MigrateDebugValue(Value *Old, Value *New) {
  400. DbgValueInst *DbgValInst = FindDbgValueInst(Old);
  401. if (DbgValInst == nullptr) return;
  402. DbgValInst->setOperand(0, MetadataAsValue::get(New->getContext(), ValueAsMetadata::get(New)));
  403. // Move the dbg value after the new instruction
  404. if (Instruction *NewInst = dyn_cast<Instruction>(New)) {
  405. if (NewInst->getNextNode() != DbgValInst) {
  406. DbgValInst->removeFromParent();
  407. DbgValInst->insertAfter(NewInst);
  408. }
  409. }
  410. }
  411. // Propagates any llvm.dbg.value instruction for a given vector
  412. // to the elements that were used to create it through a series
  413. // of insertelement instructions.
  414. //
  415. // This is used after lowering a vector-returning intrinsic.
  416. // If we just keep the debug info on the recomposed vector,
  417. // we will lose it when we break it apart again during later
  418. // optimization stages.
  419. void TryScatterDebugValueToVectorElements(Value *Val) {
  420. if (!isa<InsertElementInst>(Val) || !Val->getType()->isVectorTy()) return;
  421. DbgValueInst *VecDbgValInst = FindDbgValueInst(Val);
  422. if (VecDbgValInst == nullptr) return;
  423. Type *ElemTy = Val->getType()->getVectorElementType();
  424. DIBuilder DbgInfoBuilder(*VecDbgValInst->getModule());
  425. unsigned ElemSizeInBits = VecDbgValInst->getModule()->getDataLayout().getTypeSizeInBits(ElemTy);
  426. DIExpression *ParentBitPiece = VecDbgValInst->getExpression();
  427. if (ParentBitPiece != nullptr && !ParentBitPiece->isBitPiece())
  428. ParentBitPiece = nullptr;
  429. while (InsertElementInst *InsertElt = dyn_cast<InsertElementInst>(Val)) {
  430. Value *NewElt = InsertElt->getOperand(1);
  431. unsigned EltIdx = static_cast<unsigned>(cast<ConstantInt>(InsertElt->getOperand(2))->getLimitedValue());
  432. unsigned OffsetInBits = EltIdx * ElemSizeInBits;
  433. if (ParentBitPiece) {
  434. assert(OffsetInBits + ElemSizeInBits <= ParentBitPiece->getBitPieceSize()
  435. && "Nested bit piece expression exceeds bounds of its parent.");
  436. OffsetInBits += ParentBitPiece->getBitPieceOffset();
  437. }
  438. DIExpression *DIExpr = DbgInfoBuilder.createBitPieceExpression(OffsetInBits, ElemSizeInBits);
  439. // Offset is basically unused and deprecated in later LLVM versions.
  440. // Emit it as zero otherwise later versions of the bitcode reader will drop the intrinsic.
  441. DbgInfoBuilder.insertDbgValueIntrinsic(NewElt, /* Offset */ 0, VecDbgValInst->getVariable(),
  442. DIExpr, VecDbgValInst->getDebugLoc(), InsertElt);
  443. Val = InsertElt->getOperand(0);
  444. }
  445. }
  446. Value *SelectOnOperation(llvm::Instruction *Inst, unsigned operandIdx) {
  447. Instruction *prototype = Inst;
  448. for (unsigned i = 0; i < prototype->getNumOperands(); i++) {
  449. if (i == operandIdx)
  450. continue;
  451. if (!isa<Constant>(prototype->getOperand(i)))
  452. return nullptr;
  453. }
  454. Value *V = prototype->getOperand(operandIdx);
  455. if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
  456. IRBuilder<> Builder(SI);
  457. Instruction *trueClone = Inst->clone();
  458. trueClone->setOperand(operandIdx, SI->getTrueValue());
  459. Builder.Insert(trueClone);
  460. Instruction *falseClone = Inst->clone();
  461. falseClone->setOperand(operandIdx, SI->getFalseValue());
  462. Builder.Insert(falseClone);
  463. Value *newSel =
  464. Builder.CreateSelect(SI->getCondition(), trueClone, falseClone);
  465. return newSel;
  466. }
  467. if (PHINode *Phi = dyn_cast<PHINode>(V)) {
  468. Type *Ty = Inst->getType();
  469. unsigned numOperands = Phi->getNumOperands();
  470. IRBuilder<> Builder(Phi);
  471. PHINode *newPhi = Builder.CreatePHI(Ty, numOperands);
  472. for (unsigned i = 0; i < numOperands; i++) {
  473. BasicBlock *b = Phi->getIncomingBlock(i);
  474. Value *V = Phi->getIncomingValue(i);
  475. Instruction *iClone = Inst->clone();
  476. IRBuilder<> iBuilder(b->getTerminator()->getPrevNode());
  477. iClone->setOperand(operandIdx, V);
  478. iBuilder.Insert(iClone);
  479. newPhi->addIncoming(iClone, b);
  480. }
  481. return newPhi;
  482. }
  483. return nullptr;
  484. }
  485. llvm::Instruction *SkipAllocas(llvm::Instruction *I) {
  486. // Step past any allocas:
  487. while (I && (isa<AllocaInst>(I) || isa<DbgInfoIntrinsic>(I)))
  488. I = I->getNextNode();
  489. return I;
  490. }
  491. llvm::Instruction *FindAllocaInsertionPt(llvm::BasicBlock* BB) {
  492. return &*BB->getFirstInsertionPt();
  493. }
  494. llvm::Instruction *FindAllocaInsertionPt(llvm::Function* F) {
  495. return FindAllocaInsertionPt(&F->getEntryBlock());
  496. }
  497. llvm::Instruction *FindAllocaInsertionPt(llvm::Instruction* I) {
  498. Function *F = I->getParent()->getParent();
  499. if (F)
  500. return FindAllocaInsertionPt(F);
  501. else // BB with no parent function
  502. return FindAllocaInsertionPt(I->getParent());
  503. }
  504. llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Instruction* I) {
  505. return SkipAllocas(FindAllocaInsertionPt(I));
  506. }
  507. llvm::Instruction *FirstNonAllocaInsertionPt(llvm::BasicBlock* BB) {
  508. return SkipAllocas(FindAllocaInsertionPt(BB));
  509. }
  510. llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Function* F) {
  511. return SkipAllocas(FindAllocaInsertionPt(F));
  512. }
  513. static bool ConsumePrefix(StringRef &Str, StringRef Prefix) {
  514. if (!Str.startswith(Prefix)) return false;
  515. Str = Str.substr(Prefix.size());
  516. return true;
  517. }
  518. bool IsResourceSingleComponent(Type *Ty) {
  519. if (llvm::ArrayType *arrType = llvm::dyn_cast<llvm::ArrayType>(Ty)) {
  520. if (arrType->getArrayNumElements() > 1) {
  521. return false;
  522. }
  523. return IsResourceSingleComponent(arrType->getArrayElementType());
  524. } else if (llvm::StructType *structType =
  525. llvm::dyn_cast<llvm::StructType>(Ty)) {
  526. if (structType->getStructNumElements() > 1) {
  527. return false;
  528. }
  529. return IsResourceSingleComponent(structType->getStructElementType(0));
  530. } else if (llvm::VectorType *vectorType =
  531. llvm::dyn_cast<llvm::VectorType>(Ty)) {
  532. if (vectorType->getNumElements() > 1) {
  533. return false;
  534. }
  535. return IsResourceSingleComponent(vectorType->getVectorElementType());
  536. }
  537. return true;
  538. }
  539. uint8_t GetResourceComponentCount(llvm::Type *Ty) {
  540. if (llvm::ArrayType *arrType = llvm::dyn_cast<llvm::ArrayType>(Ty)) {
  541. return arrType->getArrayNumElements() *
  542. GetResourceComponentCount(arrType->getArrayElementType());
  543. } else if (llvm::StructType *structType =
  544. llvm::dyn_cast<llvm::StructType>(Ty)) {
  545. uint32_t Count = 0;
  546. for (Type *EltTy : structType->elements()) {
  547. Count += GetResourceComponentCount(EltTy);
  548. }
  549. DXASSERT(Count <= 4, "Component Count out of bound.");
  550. return Count;
  551. } else if (llvm::VectorType *vectorType =
  552. llvm::dyn_cast<llvm::VectorType>(Ty)) {
  553. return vectorType->getNumElements();
  554. }
  555. return 1;
  556. }
  557. bool IsHLSLResourceType(llvm::Type *Ty) {
  558. return GetHLSLResourceProperties(Ty).first;
  559. }
  560. static DxilResourceProperties MakeResourceProperties(hlsl::DXIL::ResourceKind Kind, bool UAV, bool ROV, bool Cmp) {
  561. DxilResourceProperties Ret = {};
  562. Ret.Basic.IsROV = ROV;
  563. Ret.Basic.SamplerCmpOrHasCounter = Cmp;
  564. Ret.Basic.IsUAV = UAV;
  565. Ret.Basic.ResourceKind = (uint8_t)Kind;
  566. return Ret;
  567. }
  568. std::pair<bool, DxilResourceProperties> GetHLSLResourceProperties(llvm::Type *Ty)
  569. {
  570. using RetType = std::pair<bool, DxilResourceProperties>;
  571. RetType FalseRet(false, DxilResourceProperties{});
  572. if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
  573. if (!ST->hasName())
  574. return FalseRet;
  575. StringRef name = ST->getName();
  576. ConsumePrefix(name, "class.");
  577. ConsumePrefix(name, "struct.");
  578. if (name == "SamplerState")
  579. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Sampler, false, false, false));
  580. if (name == "SamplerComparisonState")
  581. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Sampler, false, false, /*cmp or counter*/true));
  582. if (name.startswith("AppendStructuredBuffer<"))
  583. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::StructuredBuffer, false, false, /*cmp or counter*/true));
  584. if (name.startswith("ConsumeStructuredBuffer<"))
  585. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::StructuredBuffer, false, false, /*cmp or counter*/true));
  586. if (name == "RaytracingAccelerationStructure")
  587. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::RTAccelerationStructure, false, false, false));
  588. if (name.startswith("ConstantBuffer<"))
  589. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::CBuffer, false, false, false));
  590. if (name.startswith("TextureBuffer<"))
  591. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TBuffer, false, false, false));
  592. if (ConsumePrefix(name, "FeedbackTexture2D")) {
  593. hlsl::DXIL::ResourceKind kind = hlsl::DXIL::ResourceKind::Invalid;
  594. if (ConsumePrefix(name, "Array"))
  595. kind = hlsl::DXIL::ResourceKind::FeedbackTexture2DArray;
  596. else
  597. kind = hlsl::DXIL::ResourceKind::FeedbackTexture2D;
  598. if (name.startswith("<"))
  599. return RetType(true, MakeResourceProperties(kind, false, false, false));
  600. return FalseRet;
  601. }
  602. bool ROV = ConsumePrefix(name, "RasterizerOrdered");
  603. bool UAV = ConsumePrefix(name, "RW");
  604. if (name == "ByteAddressBuffer")
  605. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::RawBuffer, UAV, ROV, false));
  606. if (name.startswith("Buffer<"))
  607. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TypedBuffer, UAV, ROV, false));
  608. if (name.startswith("StructuredBuffer<"))
  609. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::StructuredBuffer, UAV, ROV, false));
  610. if (ConsumePrefix(name, "Texture")) {
  611. if (name.startswith("1D<"))
  612. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture1D, UAV, ROV, false));
  613. if (name.startswith("1DArray<"))
  614. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture1DArray, UAV, ROV, false));
  615. if (name.startswith("2D<"))
  616. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2D, UAV, ROV, false));
  617. if (name.startswith("2DArray<"))
  618. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2DArray, UAV, ROV, false));
  619. if (name.startswith("3D<"))
  620. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture3D, UAV, ROV, false));
  621. if (name.startswith("Cube<"))
  622. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TextureCube, UAV, ROV, false));
  623. if (name.startswith("CubeArray<"))
  624. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TextureCubeArray, UAV, ROV, false));
  625. if (name.startswith("2DMS<"))
  626. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2DMS, UAV, ROV, false));
  627. if (name.startswith("2DMSArray<"))
  628. return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2DMSArray, UAV, ROV, false));
  629. return FalseRet;
  630. }
  631. }
  632. return FalseRet;
  633. }
  634. bool IsHLSLObjectType(llvm::Type *Ty) {
  635. if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
  636. if (!ST->hasName()) {
  637. return false;
  638. }
  639. StringRef name = ST->getName();
  640. // TODO: don't check names.
  641. if (name.startswith("dx.types.wave_t"))
  642. return true;
  643. if (name.compare("dx.types.Handle") == 0)
  644. return true;
  645. if (name.endswith("_slice_type"))
  646. return false;
  647. if (IsHLSLResourceType(Ty))
  648. return true;
  649. ConsumePrefix(name, "class.");
  650. ConsumePrefix(name, "struct.");
  651. if (name.startswith("TriangleStream<"))
  652. return true;
  653. if (name.startswith("PointStream<"))
  654. return true;
  655. if (name.startswith("LineStream<"))
  656. return true;
  657. }
  658. return false;
  659. }
  660. bool IsHLSLRayQueryType(llvm::Type *Ty) {
  661. if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
  662. if (!ST->hasName())
  663. return false;
  664. StringRef name = ST->getName();
  665. // TODO: don't check names.
  666. ConsumePrefix(name, "class.");
  667. if (name.startswith("RayQuery<"))
  668. return true;
  669. }
  670. return false;
  671. }
  672. bool IsHLSLResourceDescType(llvm::Type *Ty) {
  673. if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
  674. if (!ST->hasName())
  675. return false;
  676. StringRef name = ST->getName();
  677. // TODO: don't check names.
  678. if (name == ("struct..Resource"))
  679. return true;
  680. if (name == "struct..Sampler")
  681. return true;
  682. }
  683. return false;
  684. }
  685. bool IsIntegerOrFloatingPointType(llvm::Type *Ty) {
  686. return Ty->isIntegerTy() || Ty->isFloatingPointTy();
  687. }
  688. bool ContainsHLSLObjectType(llvm::Type *Ty) {
  689. // Unwrap pointer/array
  690. while (llvm::isa<llvm::PointerType>(Ty))
  691. Ty = llvm::cast<llvm::PointerType>(Ty)->getPointerElementType();
  692. while (llvm::isa<llvm::ArrayType>(Ty))
  693. Ty = llvm::cast<llvm::ArrayType>(Ty)->getArrayElementType();
  694. if (llvm::StructType *ST = llvm::dyn_cast<llvm::StructType>(Ty)) {
  695. if (ST->hasName() && ST->getName().startswith("dx.types."))
  696. return true;
  697. // TODO: How is this suppoed to check for Input/OutputPatch types if
  698. // these have already been eliminated in function arguments during CG?
  699. if (IsHLSLObjectType(Ty))
  700. return true;
  701. // Otherwise, recurse elements of UDT
  702. for (auto ETy : ST->elements()) {
  703. if (ContainsHLSLObjectType(ETy))
  704. return true;
  705. }
  706. }
  707. return false;
  708. }
  709. // Based on the implementation available in LLVM's trunk:
  710. // http://llvm.org/doxygen/Constants_8cpp_source.html#l02734
  711. bool IsSplat(llvm::ConstantDataVector *cdv) {
  712. const char *Base = cdv->getRawDataValues().data();
  713. // Compare elements 1+ to the 0'th element.
  714. unsigned EltSize = cdv->getElementByteSize();
  715. for (unsigned i = 1, e = cdv->getNumElements(); i != e; ++i)
  716. if (memcmp(Base, Base + i * EltSize, EltSize))
  717. return false;
  718. return true;
  719. }
  720. llvm::Type* StripArrayTypes(llvm::Type *Ty, llvm::SmallVectorImpl<unsigned> *OuterToInnerLengths) {
  721. DXASSERT_NOMSG(Ty);
  722. while (Ty->isArrayTy()) {
  723. if (OuterToInnerLengths) {
  724. OuterToInnerLengths->push_back(Ty->getArrayNumElements());
  725. }
  726. Ty = Ty->getArrayElementType();
  727. }
  728. return Ty;
  729. }
  730. llvm::Type* WrapInArrayTypes(llvm::Type *Ty, llvm::ArrayRef<unsigned> OuterToInnerLengths) {
  731. DXASSERT_NOMSG(Ty);
  732. for (auto it = OuterToInnerLengths.rbegin(), E = OuterToInnerLengths.rend(); it != E; ++it) {
  733. Ty = ArrayType::get(Ty, *it);
  734. }
  735. return Ty;
  736. }
  737. namespace {
  738. // Create { v0, v1 } from { v0.lo, v0.hi, v1.lo, v1.hi }
  739. void Make64bitResultForLoad(Type *EltTy, ArrayRef<Value *> resultElts32,
  740. unsigned size, MutableArrayRef<Value *> resultElts,
  741. hlsl::OP *hlslOP, IRBuilder<> &Builder) {
  742. Type *i64Ty = Builder.getInt64Ty();
  743. Type *doubleTy = Builder.getDoubleTy();
  744. if (EltTy == doubleTy) {
  745. Function *makeDouble =
  746. hlslOP->GetOpFunc(DXIL::OpCode::MakeDouble, doubleTy);
  747. Value *makeDoubleOpArg =
  748. Builder.getInt32((unsigned)DXIL::OpCode::MakeDouble);
  749. for (unsigned i = 0; i < size; i++) {
  750. Value *lo = resultElts32[2 * i];
  751. Value *hi = resultElts32[2 * i + 1];
  752. Value *V = Builder.CreateCall(makeDouble, {makeDoubleOpArg, lo, hi});
  753. resultElts[i] = V;
  754. }
  755. } else {
  756. for (unsigned i = 0; i < size; i++) {
  757. Value *lo = resultElts32[2 * i];
  758. Value *hi = resultElts32[2 * i + 1];
  759. lo = Builder.CreateZExt(lo, i64Ty);
  760. hi = Builder.CreateZExt(hi, i64Ty);
  761. hi = Builder.CreateShl(hi, 32);
  762. resultElts[i] = Builder.CreateOr(lo, hi);
  763. }
  764. }
  765. }
  766. // Split { v0, v1 } to { v0.lo, v0.hi, v1.lo, v1.hi }
  767. void Split64bitValForStore(Type *EltTy, ArrayRef<Value *> vals, unsigned size,
  768. MutableArrayRef<Value *> vals32, hlsl::OP *hlslOP,
  769. IRBuilder<> &Builder) {
  770. Type *i32Ty = Builder.getInt32Ty();
  771. Type *doubleTy = Builder.getDoubleTy();
  772. Value *undefI32 = UndefValue::get(i32Ty);
  773. if (EltTy == doubleTy) {
  774. Function *dToU = hlslOP->GetOpFunc(DXIL::OpCode::SplitDouble, doubleTy);
  775. Value *dToUOpArg = Builder.getInt32((unsigned)DXIL::OpCode::SplitDouble);
  776. for (unsigned i = 0; i < size; i++) {
  777. if (isa<UndefValue>(vals[i])) {
  778. vals32[2 * i] = undefI32;
  779. vals32[2 * i + 1] = undefI32;
  780. } else {
  781. Value *retVal = Builder.CreateCall(dToU, {dToUOpArg, vals[i]});
  782. Value *lo = Builder.CreateExtractValue(retVal, 0);
  783. Value *hi = Builder.CreateExtractValue(retVal, 1);
  784. vals32[2 * i] = lo;
  785. vals32[2 * i + 1] = hi;
  786. }
  787. }
  788. } else {
  789. for (unsigned i = 0; i < size; i++) {
  790. if (isa<UndefValue>(vals[i])) {
  791. vals32[2 * i] = undefI32;
  792. vals32[2 * i + 1] = undefI32;
  793. } else {
  794. Value *lo = Builder.CreateTrunc(vals[i], i32Ty);
  795. Value *hi = Builder.CreateLShr(vals[i], 32);
  796. hi = Builder.CreateTrunc(hi, i32Ty);
  797. vals32[2 * i] = lo;
  798. vals32[2 * i + 1] = hi;
  799. }
  800. }
  801. }
  802. }
  803. }
  804. llvm::CallInst *TranslateCallRawBufferLoadToBufferLoad(
  805. llvm::CallInst *CI, llvm::Function *newFunction, hlsl::OP *op) {
  806. IRBuilder<> Builder(CI);
  807. SmallVector<Value *, 4> args;
  808. args.emplace_back(op->GetI32Const((unsigned)DXIL::OpCode::BufferLoad));
  809. for (unsigned i = 1; i < 4; ++i) {
  810. args.emplace_back(CI->getArgOperand(i));
  811. }
  812. CallInst *newCall = Builder.CreateCall(newFunction, args);
  813. return newCall;
  814. }
  815. void ReplaceRawBufferLoadWithBufferLoad(
  816. llvm::Function *F, hlsl::OP *op) {
  817. Type *RTy = F->getReturnType();
  818. if (StructType *STy = dyn_cast<StructType>(RTy)) {
  819. Type *ETy = STy->getElementType(0);
  820. Function *newFunction = op->GetOpFunc(hlsl::DXIL::OpCode::BufferLoad, ETy);
  821. for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
  822. User *user = *(U++);
  823. if (CallInst *CI = dyn_cast<CallInst>(user)) {
  824. CallInst *newCall = TranslateCallRawBufferLoadToBufferLoad(CI, newFunction, op);
  825. CI->replaceAllUsesWith(newCall);
  826. CI->eraseFromParent();
  827. } else {
  828. DXASSERT(false, "function can only be used with call instructions.");
  829. }
  830. }
  831. } else {
  832. DXASSERT(false, "RawBufferLoad should return struct type.");
  833. }
  834. }
  835. llvm::CallInst *TranslateCallRawBufferStoreToBufferStore(
  836. llvm::CallInst *CI, llvm::Function *newFunction, hlsl::OP *op) {
  837. IRBuilder<> Builder(CI);
  838. SmallVector<Value *, 4> args;
  839. args.emplace_back(op->GetI32Const((unsigned)DXIL::OpCode::BufferStore));
  840. for (unsigned i = 1; i < 9; ++i) {
  841. args.emplace_back(CI->getArgOperand(i));
  842. }
  843. CallInst *newCall = Builder.CreateCall(newFunction, args);
  844. return newCall;
  845. }
  846. void ReplaceRawBufferStoreWithBufferStore(llvm::Function *F, hlsl::OP *op) {
  847. DXASSERT(F->getReturnType()->isVoidTy(), "rawBufferStore should return a void type.");
  848. Type *ETy = F->getFunctionType()->getParamType(4); // value
  849. Function *newFunction = op->GetOpFunc(hlsl::DXIL::OpCode::BufferStore, ETy);
  850. for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
  851. User *user = *(U++);
  852. if (CallInst *CI = dyn_cast<CallInst>(user)) {
  853. TranslateCallRawBufferStoreToBufferStore(CI, newFunction, op);
  854. CI->eraseFromParent();
  855. }
  856. else {
  857. DXASSERT(false, "function can only be used with call instructions.");
  858. }
  859. }
  860. }
  861. void ReplaceRawBufferLoad64Bit(llvm::Function *F, llvm::Type *EltTy, hlsl::OP *hlslOP) {
  862. Function *bufLd = hlslOP->GetOpFunc(DXIL::OpCode::RawBufferLoad,
  863. Type::getInt32Ty(hlslOP->GetCtx()));
  864. for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
  865. User *user = *(U++);
  866. if (CallInst *CI = dyn_cast<CallInst>(user)) {
  867. IRBuilder<> Builder(CI);
  868. SmallVector<Value *, 4> args(CI->arg_operands());
  869. Value *offset = CI->getArgOperand(
  870. DXIL::OperandIndex::kRawBufferLoadElementOffsetOpIdx);
  871. unsigned size = 0;
  872. bool bNeedStatus = false;
  873. for (User *U : CI->users()) {
  874. ExtractValueInst *Elt = cast<ExtractValueInst>(U);
  875. DXASSERT(Elt->getNumIndices() == 1, "else invalid use for resRet");
  876. unsigned idx = Elt->getIndices()[0];
  877. if (idx == 4) {
  878. bNeedStatus = true;
  879. } else {
  880. size = std::max(size, idx+1);
  881. }
  882. }
  883. unsigned maskHi = 0;
  884. unsigned maskLo = 0;
  885. switch (size) {
  886. case 1:
  887. maskLo = 3;
  888. break;
  889. case 2:
  890. maskLo = 0xf;
  891. break;
  892. case 3:
  893. maskLo = 0xf;
  894. maskHi = 3;
  895. break;
  896. case 4:
  897. maskLo = 0xf;
  898. maskHi = 0xf;
  899. break;
  900. }
  901. args[DXIL::OperandIndex::kRawBufferLoadMaskOpIdx] =
  902. Builder.getInt8(maskLo);
  903. Value *resultElts[5] = {nullptr, nullptr, nullptr, nullptr, nullptr};
  904. CallInst *newLd = Builder.CreateCall(bufLd, args);
  905. Value *resultElts32[8];
  906. unsigned eltBase = 0;
  907. for (unsigned i = 0; i < size; i++) {
  908. if (i == 2) {
  909. // Update offset 4 by 4 bytes.
  910. if (isa<UndefValue>(offset)) {
  911. // [RW]ByteAddressBuffer has undef element offset -> update index
  912. Value *index = CI->getArgOperand(DXIL::OperandIndex::kRawBufferLoadIndexOpIdx);
  913. args[DXIL::OperandIndex::kRawBufferLoadIndexOpIdx] =
  914. Builder.CreateAdd(index, Builder.getInt32(4 * 4));
  915. }
  916. else {
  917. // [RW]StructuredBuffer -> update element offset
  918. args[DXIL::OperandIndex::kRawBufferLoadElementOffsetOpIdx] =
  919. Builder.CreateAdd(offset, Builder.getInt32(4 * 4));
  920. }
  921. args[DXIL::OperandIndex::kRawBufferLoadMaskOpIdx] =
  922. Builder.getInt8(maskHi);
  923. newLd = Builder.CreateCall(bufLd, args);
  924. eltBase = 4;
  925. }
  926. unsigned resBase = 2 * i;
  927. resultElts32[resBase] =
  928. Builder.CreateExtractValue(newLd, resBase - eltBase);
  929. resultElts32[resBase + 1] =
  930. Builder.CreateExtractValue(newLd, resBase + 1 - eltBase);
  931. }
  932. Make64bitResultForLoad(EltTy, resultElts32, size, resultElts, hlslOP, Builder);
  933. if (bNeedStatus) {
  934. resultElts[4] = Builder.CreateExtractValue(newLd, 4);
  935. }
  936. for (auto it = CI->user_begin(); it != CI->user_end(); ) {
  937. ExtractValueInst *Elt = cast<ExtractValueInst>(*(it++));
  938. DXASSERT(Elt->getNumIndices() == 1, "else invalid use for resRet");
  939. unsigned idx = Elt->getIndices()[0];
  940. if (!Elt->user_empty()) {
  941. Value *newElt = resultElts[idx];
  942. Elt->replaceAllUsesWith(newElt);
  943. }
  944. Elt->eraseFromParent();
  945. }
  946. CI->eraseFromParent();
  947. } else {
  948. DXASSERT(false, "function can only be used with call instructions.");
  949. }
  950. }
  951. }
  952. void ReplaceRawBufferStore64Bit(llvm::Function *F, llvm::Type *ETy, hlsl::OP *hlslOP) {
  953. Function *newFunction = hlslOP->GetOpFunc(hlsl::DXIL::OpCode::RawBufferStore,
  954. Type::getInt32Ty(hlslOP->GetCtx()));
  955. for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
  956. User *user = *(U++);
  957. if (CallInst *CI = dyn_cast<CallInst>(user)) {
  958. IRBuilder<> Builder(CI);
  959. SmallVector<Value *, 4> args(CI->arg_operands());
  960. Value *vals[4] = {
  961. CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal0OpIdx),
  962. CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal1OpIdx),
  963. CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal2OpIdx),
  964. CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal3OpIdx)};
  965. ConstantInt *cMask = cast<ConstantInt>(
  966. CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreMaskOpIdx));
  967. Value *undefI32 = UndefValue::get(Builder.getInt32Ty());
  968. Value *vals32[8] = {undefI32, undefI32, undefI32, undefI32,
  969. undefI32, undefI32, undefI32, undefI32};
  970. unsigned maskLo = 0;
  971. unsigned maskHi = 0;
  972. unsigned size = 0;
  973. unsigned mask = cMask->getLimitedValue();
  974. switch (mask) {
  975. case 1:
  976. maskLo = 3;
  977. size = 1;
  978. break;
  979. case 3:
  980. maskLo = 15;
  981. size = 2;
  982. break;
  983. case 7:
  984. maskLo = 15;
  985. maskHi = 3;
  986. size = 3;
  987. break;
  988. case 15:
  989. maskLo = 15;
  990. maskHi = 15;
  991. size = 4;
  992. break;
  993. default:
  994. DXASSERT(0, "invalid mask");
  995. }
  996. Split64bitValForStore(ETy, vals, size, vals32, hlslOP, Builder);
  997. args[DXIL::OperandIndex::kRawBufferStoreMaskOpIdx] =
  998. Builder.getInt8(maskLo);
  999. args[DXIL::OperandIndex::kRawBufferStoreVal0OpIdx] = vals32[0];
  1000. args[DXIL::OperandIndex::kRawBufferStoreVal1OpIdx] = vals32[1];
  1001. args[DXIL::OperandIndex::kRawBufferStoreVal2OpIdx] = vals32[2];
  1002. args[DXIL::OperandIndex::kRawBufferStoreVal3OpIdx] = vals32[3];
  1003. Builder.CreateCall(newFunction, args);
  1004. if (maskHi) {
  1005. // Update offset 4 by 4 bytes.
  1006. Value *offset = args[DXIL::OperandIndex::kBufferStoreCoord1OpIdx];
  1007. if (isa<UndefValue>(offset)) {
  1008. // [RW]ByteAddressBuffer has element offset == undef -> update index instead
  1009. Value *index = args[DXIL::OperandIndex::kBufferStoreCoord0OpIdx];
  1010. index = Builder.CreateAdd(index, Builder.getInt32(4 * 4));
  1011. args[DXIL::OperandIndex::kRawBufferStoreIndexOpIdx] = index;
  1012. }
  1013. else {
  1014. // [RW]StructuredBuffer -> update element offset
  1015. offset = Builder.CreateAdd(offset, Builder.getInt32(4 * 4));
  1016. args[DXIL::OperandIndex::kRawBufferStoreElementOffsetOpIdx] = offset;
  1017. }
  1018. args[DXIL::OperandIndex::kRawBufferStoreMaskOpIdx] =
  1019. Builder.getInt8(maskHi);
  1020. args[DXIL::OperandIndex::kRawBufferStoreVal0OpIdx] = vals32[4];
  1021. args[DXIL::OperandIndex::kRawBufferStoreVal1OpIdx] = vals32[5];
  1022. args[DXIL::OperandIndex::kRawBufferStoreVal2OpIdx] = vals32[6];
  1023. args[DXIL::OperandIndex::kRawBufferStoreVal3OpIdx] = vals32[7];
  1024. Builder.CreateCall(newFunction, args);
  1025. }
  1026. CI->eraseFromParent();
  1027. } else {
  1028. DXASSERT(false, "function can only be used with call instructions.");
  1029. }
  1030. }
  1031. }
  1032. bool IsConvergentMarker(const char *Name) {
  1033. StringRef RName = Name;
  1034. return RName.startswith(kConvergentFunctionPrefix);
  1035. }
  1036. bool IsConvergentMarker(const Function *F) {
  1037. return F && F->getName().startswith(kConvergentFunctionPrefix);
  1038. }
  1039. bool IsConvergentMarker(Value *V) {
  1040. CallInst *CI = dyn_cast<CallInst>(V);
  1041. if (!CI)
  1042. return false;
  1043. return IsConvergentMarker(CI->getCalledFunction());
  1044. }
  1045. Value *GetConvergentSource(Value *V) {
  1046. return cast<CallInst>(V)->getOperand(0);
  1047. }
  1048. }
  1049. }
  1050. ///////////////////////////////////////////////////////////////////////////////
  1051. namespace {
  1052. class DxilLoadMetadata : public ModulePass {
  1053. public:
  1054. static char ID; // Pass identification, replacement for typeid
  1055. explicit DxilLoadMetadata () : ModulePass(ID) {}
  1056. const char *getPassName() const override { return "HLSL load DxilModule from metadata"; }
  1057. bool runOnModule(Module &M) override {
  1058. if (!M.HasDxilModule()) {
  1059. (void)M.GetOrCreateDxilModule();
  1060. return true;
  1061. }
  1062. return false;
  1063. }
  1064. };
  1065. }
  1066. char DxilLoadMetadata::ID = 0;
  1067. ModulePass *llvm::createDxilLoadMetadataPass() {
  1068. return new DxilLoadMetadata();
  1069. }
  1070. INITIALIZE_PASS(DxilLoadMetadata, "hlsl-dxilload", "HLSL load DxilModule from metadata", false, false)