DxilUtil.cpp 40 KB

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