1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // DxilUtil.cpp //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // Dxil helper functions. //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #include "dxc/DXIL/DxilTypeSystem.h"
- #include "dxc/DXIL/DxilUtil.h"
- #include "dxc/DXIL/DxilModule.h"
- #include "dxc/DXIL/DxilOperations.h"
- #include "dxc/HLSL/DxilConvergentName.h"
- #include "dxc/Support/Global.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/Bitcode/ReaderWriter.h"
- #include "llvm/IR/DiagnosticInfo.h"
- #include "llvm/IR/DiagnosticPrinter.h"
- #include "llvm/IR/GlobalVariable.h"
- #include "llvm/IR/IntrinsicInst.h"
- #include "llvm/IR/LLVMContext.h"
- #include "llvm/IR/Module.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/DIBuilder.h"
- #include "llvm/IR/IRBuilder.h"
- using namespace llvm;
- using namespace hlsl;
- namespace hlsl {
- namespace dxilutil {
- const char ManglingPrefix[] = "\01?";
- const char EntryPrefix[] = "dx.entry.";
- Type *GetArrayEltTy(Type *Ty) {
- if (isa<PointerType>(Ty))
- Ty = Ty->getPointerElementType();
- while (isa<ArrayType>(Ty)) {
- Ty = Ty->getArrayElementType();
- }
- return Ty;
- }
- bool HasDynamicIndexing(Value *V) {
- for (auto User : V->users()) {
- if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
- for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
- if (!isa<ConstantInt>(Idx))
- return true;
- }
- }
- }
- return false;
- }
- unsigned
- GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
- llvm::Type *Ty,
- DxilTypeSystem &typeSys) {
- while (isa<ArrayType>(Ty)) {
- Ty = Ty->getArrayElementType();
- }
- // Bytes.
- CompType compType = fieldAnnotation.GetCompType();
- unsigned compSize = compType.Is64Bit() ? 8 : compType.Is16Bit() && !typeSys.UseMinPrecision() ? 2 : 4;
- unsigned fieldSize = compSize;
- if (Ty->isVectorTy()) {
- fieldSize *= Ty->getVectorNumElements();
- } else if (StructType *ST = dyn_cast<StructType>(Ty)) {
- DxilStructAnnotation *EltAnnotation = typeSys.GetStructAnnotation(ST);
- if (EltAnnotation) {
- fieldSize = EltAnnotation->GetCBufferSize();
- } else {
- // Calculate size when don't have annotation.
- if (fieldAnnotation.HasMatrixAnnotation()) {
- const DxilMatrixAnnotation &matAnnotation =
- fieldAnnotation.GetMatrixAnnotation();
- unsigned rows = matAnnotation.Rows;
- unsigned cols = matAnnotation.Cols;
- if (matAnnotation.Orientation == MatrixOrientation::ColumnMajor) {
- rows = cols;
- cols = matAnnotation.Rows;
- } else if (matAnnotation.Orientation != MatrixOrientation::RowMajor) {
- // Invalid matrix orientation.
- fieldSize = 0;
- }
- fieldSize = (rows - 1) * 16 + cols * 4;
- } else {
- // Cannot find struct annotation.
- fieldSize = 0;
- }
- }
- }
- return fieldSize;
- }
- bool IsStaticGlobal(GlobalVariable *GV) {
- return GV->getLinkage() == GlobalValue::LinkageTypes::InternalLinkage &&
- GV->getType()->getPointerAddressSpace() == DXIL::kDefaultAddrSpace;
- }
- bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV) {
- return GV->getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace;
- }
- bool RemoveUnusedFunctions(Module &M, Function *EntryFunc,
- Function *PatchConstantFunc, bool IsLib) {
- std::vector<Function *> deadList;
- for (auto &F : M.functions()) {
- if (&F == EntryFunc || &F == PatchConstantFunc)
- continue;
- if (F.isDeclaration() || !IsLib) {
- if (F.user_empty())
- deadList.emplace_back(&F);
- }
- }
- bool bUpdated = deadList.size();
- for (Function *F : deadList)
- F->eraseFromParent();
- return bUpdated;
- }
- void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context) {
- DiagnosticPrinter *printer = reinterpret_cast<DiagnosticPrinter *>(Context);
- DI.print(*printer);
- }
- StringRef DemangleFunctionName(StringRef name) {
- if (!name.startswith(ManglingPrefix)) {
- // Name isn't mangled.
- return name;
- }
- size_t nameEnd = name.find_first_of("@");
- DXASSERT(nameEnd != StringRef::npos, "else Name isn't mangled but has \01?");
- return name.substr(2, nameEnd - 2);
- }
- std::string ReplaceFunctionName(StringRef originalName, StringRef newName) {
- if (originalName.startswith(ManglingPrefix)) {
- return (Twine(ManglingPrefix) + newName +
- originalName.substr(originalName.find_first_of('@'))).str();
- } else if (originalName.startswith(EntryPrefix)) {
- return (Twine(EntryPrefix) + newName).str();
- }
- return newName.str();
- }
- // From AsmWriter.cpp
- // PrintEscapedString - Print each character of the specified string, escaping
- // it if it is not printable or if it is an escape char.
- void PrintEscapedString(StringRef Name, raw_ostream &Out) {
- for (unsigned i = 0, e = Name.size(); i != e; ++i) {
- unsigned char C = Name[i];
- if (isprint(C) && C != '\\' && C != '"')
- Out << C;
- else
- Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
- }
- }
- void PrintUnescapedString(StringRef Name, raw_ostream &Out) {
- for (unsigned i = 0, e = Name.size(); i != e; ++i) {
- unsigned char C = Name[i];
- if (C == '\\') {
- C = Name[++i];
- unsigned value = hexDigitValue(C);
- if (value != -1U) {
- C = (unsigned char)value;
- unsigned value2 = hexDigitValue(Name[i+1]);
- assert(value2 != -1U && "otherwise, not a two digit hex escape");
- if (value2 != -1U) {
- C = (C << 4) + (unsigned char)value2;
- ++i;
- }
- } // else, the next character (in C) should be the escaped character
- }
- Out << C;
- }
- }
- std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::MemoryBuffer *MB,
- llvm::LLVMContext &Ctx,
- std::string &DiagStr) {
- // Note: the DiagStr is not used.
- auto pModule = llvm::parseBitcodeFile(MB->getMemBufferRef(), Ctx);
- if (!pModule) {
- return nullptr;
- }
- return std::unique_ptr<llvm::Module>(pModule.get().release());
- }
- std::unique_ptr<llvm::Module> LoadModuleFromBitcodeLazy(std::unique_ptr<llvm::MemoryBuffer> &&MB,
- llvm::LLVMContext &Ctx, std::string &DiagStr)
- {
- // Note: the DiagStr is not used.
- auto pModule = llvm::getLazyBitcodeModule(std::move(MB), Ctx, nullptr, true);
- if (!pModule) {
- return nullptr;
- }
- return std::unique_ptr<llvm::Module>(pModule.get().release());
- }
- std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::StringRef BC,
- llvm::LLVMContext &Ctx,
- std::string &DiagStr) {
- std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf(
- llvm::MemoryBuffer::getMemBuffer(BC, "", false));
- return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr);
- }
- DIGlobalVariable *FindGlobalVariableDebugInfo(GlobalVariable *GV,
- DebugInfoFinder &DbgInfoFinder) {
- struct GlobalFinder {
- GlobalVariable *GV;
- bool operator()(llvm::DIGlobalVariable *const arg) const {
- return arg->getVariable() == GV;
- }
- };
- GlobalFinder F = {GV};
- DebugInfoFinder::global_variable_iterator Found =
- std::find_if(DbgInfoFinder.global_variables().begin(),
- DbgInfoFinder.global_variables().end(), F);
- if (Found != DbgInfoFinder.global_variables().end()) {
- return *Found;
- }
- return nullptr;
- }
- static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
- DiagnosticSeverity severity);
- // If we don't have debug location and this is select/phi,
- // try recursing users to find instruction with debug info.
- // Only recurse phi/select and limit depth to prevent doing
- // too much work if no debug location found.
- static bool EmitWarningOrErrorOnInstructionFollowPhiSelect(Instruction *I,
- Twine Msg,
- DiagnosticSeverity severity,
- unsigned depth = 0) {
- if (depth > 4)
- return false;
- if (I->getDebugLoc().get()) {
- EmitWarningOrErrorOnInstruction(I, Msg, severity);
- return true;
- }
- if (isa<PHINode>(I) || isa<SelectInst>(I)) {
- for (auto U : I->users())
- if (Instruction *UI = dyn_cast<Instruction>(U))
- if (EmitWarningOrErrorOnInstructionFollowPhiSelect(UI, Msg, severity,
- depth + 1))
- return true;
- }
- return false;
- }
- static void EmitWarningOrErrorOnInstruction(Instruction *I, Twine Msg,
- DiagnosticSeverity severity) {
- const DebugLoc &DL = I->getDebugLoc();
- if (!DL.get() && (isa<PHINode>(I) || isa<SelectInst>(I))) {
- if (EmitWarningOrErrorOnInstructionFollowPhiSelect(I, Msg, severity))
- return;
- }
- I->getContext().diagnose(DiagnosticInfoDxil(I->getParent()->getParent(),
- DL.get(), Msg, severity));
- }
- void EmitErrorOnInstruction(Instruction *I, Twine Msg) {
- EmitWarningOrErrorOnInstruction(I, Msg, DiagnosticSeverity::DS_Error);
- }
- void EmitWarningOnInstruction(Instruction *I, Twine Msg) {
- EmitWarningOrErrorOnInstruction(I, Msg, DiagnosticSeverity::DS_Warning);
- }
- static void EmitWarningOrErrorOnFunction(llvm::LLVMContext &Ctx, Function *F, Twine Msg,
- DiagnosticSeverity severity) {
- DILocation *DLoc = nullptr;
- if (DISubprogram *DISP = getDISubprogram(F)) {
- DLoc = DILocation::get(F->getContext(), DISP->getLine(), 0,
- DISP, nullptr /*InlinedAt*/);
- }
- Ctx.diagnose(DiagnosticInfoDxil(F, DLoc, Msg, severity));
- }
- void EmitErrorOnFunction(llvm::LLVMContext &Ctx, Function *F, Twine Msg) {
- EmitWarningOrErrorOnFunction(Ctx, F, Msg, DiagnosticSeverity::DS_Error);
- }
- void EmitWarningOnFunction(llvm::LLVMContext &Ctx, Function *F, Twine Msg) {
- EmitWarningOrErrorOnFunction(Ctx, F, Msg, DiagnosticSeverity::DS_Warning);
- }
- static void EmitWarningOrErrorOnGlobalVariable(llvm::LLVMContext &Ctx, GlobalVariable *GV,
- Twine Msg, DiagnosticSeverity severity) {
- DIVariable *DIV = nullptr;
- DILocation *DLoc = nullptr;
- if (GV) {
- Module &M = *GV->getParent();
- if (hasDebugInfo(M)) {
- DebugInfoFinder FinderObj;
- DebugInfoFinder &Finder = FinderObj;
- // Debug modules have no dxil modules. Use it if you got it.
- if (M.HasDxilModule())
- Finder = M.GetDxilModule().GetOrCreateDebugInfoFinder();
- else
- Finder.processModule(M);
- DIV = FindGlobalVariableDebugInfo(GV, Finder);
- if (DIV)
- DLoc = DILocation::get(GV->getContext(), DIV->getLine(), 0,
- DIV->getScope(), nullptr /*InlinedAt*/);
- }
- }
- Ctx.diagnose(DiagnosticInfoDxil(nullptr /*Function*/, DLoc, Msg, severity));
- }
- void EmitErrorOnGlobalVariable(llvm::LLVMContext &Ctx, GlobalVariable *GV, Twine Msg) {
- EmitWarningOrErrorOnGlobalVariable(Ctx, GV, Msg, DiagnosticSeverity::DS_Error);
- }
- void EmitWarningOnGlobalVariable(llvm::LLVMContext &Ctx, GlobalVariable *GV, Twine Msg) {
- EmitWarningOrErrorOnGlobalVariable(Ctx, GV, Msg, DiagnosticSeverity::DS_Warning);
- }
- const char *kResourceMapErrorMsg =
- "local resource not guaranteed to map to unique global resource.";
- void EmitResMappingError(Instruction *Res) {
- EmitErrorOnInstruction(Res, kResourceMapErrorMsg);
- }
- // Mostly just a locationless diagnostic output
- static void EmitWarningOrErrorOnContext(LLVMContext &Ctx, Twine Msg, DiagnosticSeverity severity) {
- Ctx.diagnose(DiagnosticInfoDxil(nullptr /*Func*/, nullptr /*DLoc*/,
- Msg, severity));
- }
- void EmitErrorOnContext(LLVMContext &Ctx, Twine Msg) {
- EmitWarningOrErrorOnContext(Ctx, Msg, DiagnosticSeverity::DS_Error);
- }
- void EmitWarningOnContext(LLVMContext &Ctx, Twine Msg) {
- EmitWarningOrErrorOnContext(Ctx, Msg, DiagnosticSeverity::DS_Warning);
- }
- void EmitNoteOnContext(LLVMContext &Ctx, Twine Msg) {
- EmitWarningOrErrorOnContext(Ctx, Msg, DiagnosticSeverity::DS_Note);
- }
- void CollectSelect(llvm::Instruction *Inst,
- std::unordered_set<llvm::Instruction *> &selectSet) {
- unsigned startOpIdx = 0;
- // Skip Cond for Select.
- if (isa<SelectInst>(Inst)) {
- startOpIdx = 1;
- } else if (!isa<PHINode>(Inst)) {
- // Only check phi and select here.
- return;
- }
- // Already add.
- if (selectSet.count(Inst))
- return;
- selectSet.insert(Inst);
- // Scan operand to add node which is phi/select.
- unsigned numOperands = Inst->getNumOperands();
- for (unsigned i = startOpIdx; i < numOperands; i++) {
- Value *V = Inst->getOperand(i);
- if (Instruction *I = dyn_cast<Instruction>(V)) {
- CollectSelect(I, selectSet);
- }
- }
- }
- Value *MergeSelectOnSameValue(Instruction *SelInst, unsigned startOpIdx,
- unsigned numOperands) {
- Value *op0 = nullptr;
- for (unsigned i = startOpIdx; i < numOperands; i++) {
- Value *op = SelInst->getOperand(i);
- if (i == startOpIdx) {
- op0 = op;
- } else {
- if (op0 != op)
- return nullptr;
- }
- }
- if (op0) {
- SelInst->replaceAllUsesWith(op0);
- SelInst->eraseFromParent();
- }
- return op0;
- }
- bool SimplifyTrivialPHIs(BasicBlock *BB) {
- bool Changed = false;
- SmallVector<Instruction *, 16> Removed;
- for (Instruction &I : *BB) {
- PHINode *PN = dyn_cast<PHINode>(&I);
- if (!PN)
- continue;
- if (PN->getNumIncomingValues() == 1) {
- Value *V = PN->getIncomingValue(0);
- PN->replaceAllUsesWith(V);
- Removed.push_back(PN);
- Changed = true;
- }
- }
- for (Instruction *I : Removed)
- I->eraseFromParent();
- return Changed;
- }
- llvm::BasicBlock *GetSwitchSuccessorForCond(llvm::SwitchInst *Switch,llvm::ConstantInt *Cond) {
- for (auto it = Switch->case_begin(), end = Switch->case_end(); it != end; it++) {
- if (it.getCaseValue() == Cond) {
- return it.getCaseSuccessor();
- break;
- }
- }
- return Switch->getDefaultDest();
- }
- static DbgValueInst *FindDbgValueInst(Value *Val) {
- if (auto *ValAsMD = LocalAsMetadata::getIfExists(Val)) {
- if (auto *ValMDAsVal = MetadataAsValue::getIfExists(Val->getContext(), ValAsMD)) {
- for (User *ValMDUser : ValMDAsVal->users()) {
- if (DbgValueInst *DbgValInst = dyn_cast<DbgValueInst>(ValMDUser))
- return DbgValInst;
- }
- }
- }
- return nullptr;
- }
- void MigrateDebugValue(Value *Old, Value *New) {
- DbgValueInst *DbgValInst = FindDbgValueInst(Old);
- if (DbgValInst == nullptr) return;
-
- DbgValInst->setOperand(0, MetadataAsValue::get(New->getContext(), ValueAsMetadata::get(New)));
- // Move the dbg value after the new instruction
- if (Instruction *NewInst = dyn_cast<Instruction>(New)) {
- if (NewInst->getNextNode() != DbgValInst) {
- DbgValInst->removeFromParent();
- DbgValInst->insertAfter(NewInst);
- }
- }
- }
- // Propagates any llvm.dbg.value instruction for a given vector
- // to the elements that were used to create it through a series
- // of insertelement instructions.
- //
- // This is used after lowering a vector-returning intrinsic.
- // If we just keep the debug info on the recomposed vector,
- // we will lose it when we break it apart again during later
- // optimization stages.
- void TryScatterDebugValueToVectorElements(Value *Val) {
- if (!isa<InsertElementInst>(Val) || !Val->getType()->isVectorTy()) return;
- DbgValueInst *VecDbgValInst = FindDbgValueInst(Val);
- if (VecDbgValInst == nullptr) return;
- Type *ElemTy = Val->getType()->getVectorElementType();
- DIBuilder DbgInfoBuilder(*VecDbgValInst->getModule());
- unsigned ElemSizeInBits = VecDbgValInst->getModule()->getDataLayout().getTypeSizeInBits(ElemTy);
- DIExpression *ParentBitPiece = VecDbgValInst->getExpression();
- if (ParentBitPiece != nullptr && !ParentBitPiece->isBitPiece())
- ParentBitPiece = nullptr;
- while (InsertElementInst *InsertElt = dyn_cast<InsertElementInst>(Val)) {
- Value *NewElt = InsertElt->getOperand(1);
- unsigned EltIdx = static_cast<unsigned>(cast<ConstantInt>(InsertElt->getOperand(2))->getLimitedValue());
- unsigned OffsetInBits = EltIdx * ElemSizeInBits;
- if (ParentBitPiece) {
- assert(OffsetInBits + ElemSizeInBits <= ParentBitPiece->getBitPieceSize()
- && "Nested bit piece expression exceeds bounds of its parent.");
- OffsetInBits += ParentBitPiece->getBitPieceOffset();
- }
- DIExpression *DIExpr = DbgInfoBuilder.createBitPieceExpression(OffsetInBits, ElemSizeInBits);
- // Offset is basically unused and deprecated in later LLVM versions.
- // Emit it as zero otherwise later versions of the bitcode reader will drop the intrinsic.
- DbgInfoBuilder.insertDbgValueIntrinsic(NewElt, /* Offset */ 0, VecDbgValInst->getVariable(),
- DIExpr, VecDbgValInst->getDebugLoc(), InsertElt);
- Val = InsertElt->getOperand(0);
- }
- }
- Value *SelectOnOperation(llvm::Instruction *Inst, unsigned operandIdx) {
- Instruction *prototype = Inst;
- for (unsigned i = 0; i < prototype->getNumOperands(); i++) {
- if (i == operandIdx)
- continue;
- if (!isa<Constant>(prototype->getOperand(i)))
- return nullptr;
- }
- Value *V = prototype->getOperand(operandIdx);
- if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
- IRBuilder<> Builder(SI);
- Instruction *trueClone = Inst->clone();
- trueClone->setOperand(operandIdx, SI->getTrueValue());
- Builder.Insert(trueClone);
- Instruction *falseClone = Inst->clone();
- falseClone->setOperand(operandIdx, SI->getFalseValue());
- Builder.Insert(falseClone);
- Value *newSel =
- Builder.CreateSelect(SI->getCondition(), trueClone, falseClone);
- return newSel;
- }
- if (PHINode *Phi = dyn_cast<PHINode>(V)) {
- Type *Ty = Inst->getType();
- unsigned numOperands = Phi->getNumOperands();
- IRBuilder<> Builder(Phi);
- PHINode *newPhi = Builder.CreatePHI(Ty, numOperands);
- for (unsigned i = 0; i < numOperands; i++) {
- BasicBlock *b = Phi->getIncomingBlock(i);
- Value *V = Phi->getIncomingValue(i);
- Instruction *iClone = Inst->clone();
- IRBuilder<> iBuilder(b->getTerminator()->getPrevNode());
- iClone->setOperand(operandIdx, V);
- iBuilder.Insert(iClone);
- newPhi->addIncoming(iClone, b);
- }
- return newPhi;
- }
- return nullptr;
- }
- llvm::Instruction *SkipAllocas(llvm::Instruction *I) {
- // Step past any allocas:
- while (I && (isa<AllocaInst>(I) || isa<DbgInfoIntrinsic>(I)))
- I = I->getNextNode();
- return I;
- }
- llvm::Instruction *FindAllocaInsertionPt(llvm::BasicBlock* BB) {
- return &*BB->getFirstInsertionPt();
- }
- llvm::Instruction *FindAllocaInsertionPt(llvm::Function* F) {
- return FindAllocaInsertionPt(&F->getEntryBlock());
- }
- llvm::Instruction *FindAllocaInsertionPt(llvm::Instruction* I) {
- Function *F = I->getParent()->getParent();
- if (F)
- return FindAllocaInsertionPt(F);
- else // BB with no parent function
- return FindAllocaInsertionPt(I->getParent());
- }
- llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Instruction* I) {
- return SkipAllocas(FindAllocaInsertionPt(I));
- }
- llvm::Instruction *FirstNonAllocaInsertionPt(llvm::BasicBlock* BB) {
- return SkipAllocas(FindAllocaInsertionPt(BB));
- }
- llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Function* F) {
- return SkipAllocas(FindAllocaInsertionPt(F));
- }
- static bool ConsumePrefix(StringRef &Str, StringRef Prefix) {
- if (!Str.startswith(Prefix)) return false;
- Str = Str.substr(Prefix.size());
- return true;
- }
- bool IsResourceSingleComponent(Type *Ty) {
- if (llvm::ArrayType *arrType = llvm::dyn_cast<llvm::ArrayType>(Ty)) {
- if (arrType->getArrayNumElements() > 1) {
- return false;
- }
- return IsResourceSingleComponent(arrType->getArrayElementType());
- } else if (llvm::StructType *structType =
- llvm::dyn_cast<llvm::StructType>(Ty)) {
- if (structType->getStructNumElements() > 1) {
- return false;
- }
- return IsResourceSingleComponent(structType->getStructElementType(0));
- } else if (llvm::VectorType *vectorType =
- llvm::dyn_cast<llvm::VectorType>(Ty)) {
- if (vectorType->getNumElements() > 1) {
- return false;
- }
- return IsResourceSingleComponent(vectorType->getVectorElementType());
- }
- return true;
- }
- uint8_t GetResourceComponentCount(llvm::Type *Ty) {
- if (llvm::ArrayType *arrType = llvm::dyn_cast<llvm::ArrayType>(Ty)) {
- return arrType->getArrayNumElements() *
- GetResourceComponentCount(arrType->getArrayElementType());
- } else if (llvm::StructType *structType =
- llvm::dyn_cast<llvm::StructType>(Ty)) {
- uint32_t Count = 0;
- for (Type *EltTy : structType->elements()) {
- Count += GetResourceComponentCount(EltTy);
- }
- DXASSERT(Count <= 4, "Component Count out of bound.");
- return Count;
- } else if (llvm::VectorType *vectorType =
- llvm::dyn_cast<llvm::VectorType>(Ty)) {
- return vectorType->getNumElements();
- }
- return 1;
- }
- bool IsHLSLResourceType(llvm::Type *Ty) {
- return GetHLSLResourceProperties(Ty).first;
- }
- static DxilResourceProperties MakeResourceProperties(hlsl::DXIL::ResourceKind Kind, bool UAV, bool ROV, bool Cmp) {
- DxilResourceProperties Ret = {};
- Ret.Basic.IsROV = ROV;
- Ret.Basic.SamplerCmpOrHasCounter = Cmp;
- Ret.Basic.IsUAV = UAV;
- Ret.Basic.ResourceKind = (uint8_t)Kind;
- return Ret;
- }
- std::pair<bool, DxilResourceProperties> GetHLSLResourceProperties(llvm::Type *Ty)
- {
- using RetType = std::pair<bool, DxilResourceProperties>;
- RetType FalseRet(false, DxilResourceProperties{});
- if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
- if (!ST->hasName())
- return FalseRet;
- StringRef name = ST->getName();
- ConsumePrefix(name, "class.");
- ConsumePrefix(name, "struct.");
- if (name == "SamplerState")
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Sampler, false, false, false));
- if (name == "SamplerComparisonState")
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Sampler, false, false, /*cmp or counter*/true));
- if (name.startswith("AppendStructuredBuffer<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::StructuredBuffer, false, false, /*cmp or counter*/true));
- if (name.startswith("ConsumeStructuredBuffer<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::StructuredBuffer, false, false, /*cmp or counter*/true));
- if (name == "RaytracingAccelerationStructure")
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::RTAccelerationStructure, false, false, false));
- if (name.startswith("ConstantBuffer<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::CBuffer, false, false, false));
- if (name.startswith("TextureBuffer<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TBuffer, false, false, false));
- if (ConsumePrefix(name, "FeedbackTexture2D")) {
- hlsl::DXIL::ResourceKind kind = hlsl::DXIL::ResourceKind::Invalid;
- if (ConsumePrefix(name, "Array"))
- kind = hlsl::DXIL::ResourceKind::FeedbackTexture2DArray;
- else
- kind = hlsl::DXIL::ResourceKind::FeedbackTexture2D;
- if (name.startswith("<"))
- return RetType(true, MakeResourceProperties(kind, false, false, false));
- return FalseRet;
- }
- bool ROV = ConsumePrefix(name, "RasterizerOrdered");
- bool UAV = ConsumePrefix(name, "RW");
- if (name == "ByteAddressBuffer")
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::RawBuffer, UAV, ROV, false));
- if (name.startswith("Buffer<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TypedBuffer, UAV, ROV, false));
- if (name.startswith("StructuredBuffer<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::StructuredBuffer, UAV, ROV, false));
- if (ConsumePrefix(name, "Texture")) {
- if (name.startswith("1D<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture1D, UAV, ROV, false));
- if (name.startswith("1DArray<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture1DArray, UAV, ROV, false));
- if (name.startswith("2D<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2D, UAV, ROV, false));
- if (name.startswith("2DArray<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2DArray, UAV, ROV, false));
- if (name.startswith("3D<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture3D, UAV, ROV, false));
- if (name.startswith("Cube<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TextureCube, UAV, ROV, false));
- if (name.startswith("CubeArray<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::TextureCubeArray, UAV, ROV, false));
- if (name.startswith("2DMS<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2DMS, UAV, ROV, false));
- if (name.startswith("2DMSArray<"))
- return RetType(true, MakeResourceProperties(hlsl::DXIL::ResourceKind::Texture2DMSArray, UAV, ROV, false));
- return FalseRet;
- }
- }
- return FalseRet;
- }
- bool IsHLSLObjectType(llvm::Type *Ty) {
- if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
- if (!ST->hasName()) {
- return false;
- }
- StringRef name = ST->getName();
- // TODO: don't check names.
- if (name.startswith("dx.types.wave_t"))
- return true;
- if (name.compare("dx.types.Handle") == 0)
- return true;
- if (name.endswith("_slice_type"))
- return false;
- if (IsHLSLResourceType(Ty))
- return true;
- ConsumePrefix(name, "class.");
- ConsumePrefix(name, "struct.");
- if (name.startswith("TriangleStream<"))
- return true;
- if (name.startswith("PointStream<"))
- return true;
- if (name.startswith("LineStream<"))
- return true;
- }
- return false;
- }
- bool IsHLSLRayQueryType(llvm::Type *Ty) {
- if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
- if (!ST->hasName())
- return false;
- StringRef name = ST->getName();
- // TODO: don't check names.
- ConsumePrefix(name, "class.");
- if (name.startswith("RayQuery<"))
- return true;
- }
- return false;
- }
- bool IsHLSLResourceDescType(llvm::Type *Ty) {
- if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
- if (!ST->hasName())
- return false;
- StringRef name = ST->getName();
- // TODO: don't check names.
- if (name == ("struct..Resource"))
- return true;
- if (name == "struct..Sampler")
- return true;
- }
- return false;
- }
- bool IsIntegerOrFloatingPointType(llvm::Type *Ty) {
- return Ty->isIntegerTy() || Ty->isFloatingPointTy();
- }
- bool ContainsHLSLObjectType(llvm::Type *Ty) {
- // Unwrap pointer/array
- while (llvm::isa<llvm::PointerType>(Ty))
- Ty = llvm::cast<llvm::PointerType>(Ty)->getPointerElementType();
- while (llvm::isa<llvm::ArrayType>(Ty))
- Ty = llvm::cast<llvm::ArrayType>(Ty)->getArrayElementType();
- if (llvm::StructType *ST = llvm::dyn_cast<llvm::StructType>(Ty)) {
- if (ST->hasName() && ST->getName().startswith("dx.types."))
- return true;
- // TODO: How is this suppoed to check for Input/OutputPatch types if
- // these have already been eliminated in function arguments during CG?
- if (IsHLSLObjectType(Ty))
- return true;
- // Otherwise, recurse elements of UDT
- for (auto ETy : ST->elements()) {
- if (ContainsHLSLObjectType(ETy))
- return true;
- }
- }
- return false;
- }
- // Based on the implementation available in LLVM's trunk:
- // http://llvm.org/doxygen/Constants_8cpp_source.html#l02734
- bool IsSplat(llvm::ConstantDataVector *cdv) {
- const char *Base = cdv->getRawDataValues().data();
- // Compare elements 1+ to the 0'th element.
- unsigned EltSize = cdv->getElementByteSize();
- for (unsigned i = 1, e = cdv->getNumElements(); i != e; ++i)
- if (memcmp(Base, Base + i * EltSize, EltSize))
- return false;
- return true;
- }
- llvm::Type* StripArrayTypes(llvm::Type *Ty, llvm::SmallVectorImpl<unsigned> *OuterToInnerLengths) {
- DXASSERT_NOMSG(Ty);
- while (Ty->isArrayTy()) {
- if (OuterToInnerLengths) {
- OuterToInnerLengths->push_back(Ty->getArrayNumElements());
- }
- Ty = Ty->getArrayElementType();
- }
- return Ty;
- }
- llvm::Type* WrapInArrayTypes(llvm::Type *Ty, llvm::ArrayRef<unsigned> OuterToInnerLengths) {
- DXASSERT_NOMSG(Ty);
- for (auto it = OuterToInnerLengths.rbegin(), E = OuterToInnerLengths.rend(); it != E; ++it) {
- Ty = ArrayType::get(Ty, *it);
- }
- return Ty;
- }
- namespace {
- // Create { v0, v1 } from { v0.lo, v0.hi, v1.lo, v1.hi }
- void Make64bitResultForLoad(Type *EltTy, ArrayRef<Value *> resultElts32,
- unsigned size, MutableArrayRef<Value *> resultElts,
- hlsl::OP *hlslOP, IRBuilder<> &Builder) {
- Type *i64Ty = Builder.getInt64Ty();
- Type *doubleTy = Builder.getDoubleTy();
- if (EltTy == doubleTy) {
- Function *makeDouble =
- hlslOP->GetOpFunc(DXIL::OpCode::MakeDouble, doubleTy);
- Value *makeDoubleOpArg =
- Builder.getInt32((unsigned)DXIL::OpCode::MakeDouble);
- for (unsigned i = 0; i < size; i++) {
- Value *lo = resultElts32[2 * i];
- Value *hi = resultElts32[2 * i + 1];
- Value *V = Builder.CreateCall(makeDouble, {makeDoubleOpArg, lo, hi});
- resultElts[i] = V;
- }
- } else {
- for (unsigned i = 0; i < size; i++) {
- Value *lo = resultElts32[2 * i];
- Value *hi = resultElts32[2 * i + 1];
- lo = Builder.CreateZExt(lo, i64Ty);
- hi = Builder.CreateZExt(hi, i64Ty);
- hi = Builder.CreateShl(hi, 32);
- resultElts[i] = Builder.CreateOr(lo, hi);
- }
- }
- }
- // Split { v0, v1 } to { v0.lo, v0.hi, v1.lo, v1.hi }
- void Split64bitValForStore(Type *EltTy, ArrayRef<Value *> vals, unsigned size,
- MutableArrayRef<Value *> vals32, hlsl::OP *hlslOP,
- IRBuilder<> &Builder) {
- Type *i32Ty = Builder.getInt32Ty();
- Type *doubleTy = Builder.getDoubleTy();
- Value *undefI32 = UndefValue::get(i32Ty);
- if (EltTy == doubleTy) {
- Function *dToU = hlslOP->GetOpFunc(DXIL::OpCode::SplitDouble, doubleTy);
- Value *dToUOpArg = Builder.getInt32((unsigned)DXIL::OpCode::SplitDouble);
- for (unsigned i = 0; i < size; i++) {
- if (isa<UndefValue>(vals[i])) {
- vals32[2 * i] = undefI32;
- vals32[2 * i + 1] = undefI32;
- } else {
- Value *retVal = Builder.CreateCall(dToU, {dToUOpArg, vals[i]});
- Value *lo = Builder.CreateExtractValue(retVal, 0);
- Value *hi = Builder.CreateExtractValue(retVal, 1);
- vals32[2 * i] = lo;
- vals32[2 * i + 1] = hi;
- }
- }
- } else {
- for (unsigned i = 0; i < size; i++) {
- if (isa<UndefValue>(vals[i])) {
- vals32[2 * i] = undefI32;
- vals32[2 * i + 1] = undefI32;
- } else {
- Value *lo = Builder.CreateTrunc(vals[i], i32Ty);
- Value *hi = Builder.CreateLShr(vals[i], 32);
- hi = Builder.CreateTrunc(hi, i32Ty);
- vals32[2 * i] = lo;
- vals32[2 * i + 1] = hi;
- }
- }
- }
- }
- }
- llvm::CallInst *TranslateCallRawBufferLoadToBufferLoad(
- llvm::CallInst *CI, llvm::Function *newFunction, hlsl::OP *op) {
- IRBuilder<> Builder(CI);
- SmallVector<Value *, 4> args;
- args.emplace_back(op->GetI32Const((unsigned)DXIL::OpCode::BufferLoad));
- for (unsigned i = 1; i < 4; ++i) {
- args.emplace_back(CI->getArgOperand(i));
- }
- CallInst *newCall = Builder.CreateCall(newFunction, args);
- return newCall;
- }
- void ReplaceRawBufferLoadWithBufferLoad(
- llvm::Function *F, hlsl::OP *op) {
- Type *RTy = F->getReturnType();
- if (StructType *STy = dyn_cast<StructType>(RTy)) {
- Type *ETy = STy->getElementType(0);
- Function *newFunction = op->GetOpFunc(hlsl::DXIL::OpCode::BufferLoad, ETy);
- for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
- User *user = *(U++);
- if (CallInst *CI = dyn_cast<CallInst>(user)) {
- CallInst *newCall = TranslateCallRawBufferLoadToBufferLoad(CI, newFunction, op);
- CI->replaceAllUsesWith(newCall);
- CI->eraseFromParent();
- } else {
- DXASSERT(false, "function can only be used with call instructions.");
- }
- }
- } else {
- DXASSERT(false, "RawBufferLoad should return struct type.");
- }
- }
- llvm::CallInst *TranslateCallRawBufferStoreToBufferStore(
- llvm::CallInst *CI, llvm::Function *newFunction, hlsl::OP *op) {
- IRBuilder<> Builder(CI);
- SmallVector<Value *, 4> args;
- args.emplace_back(op->GetI32Const((unsigned)DXIL::OpCode::BufferStore));
- for (unsigned i = 1; i < 9; ++i) {
- args.emplace_back(CI->getArgOperand(i));
- }
- CallInst *newCall = Builder.CreateCall(newFunction, args);
- return newCall;
- }
- void ReplaceRawBufferStoreWithBufferStore(llvm::Function *F, hlsl::OP *op) {
- DXASSERT(F->getReturnType()->isVoidTy(), "rawBufferStore should return a void type.");
- Type *ETy = F->getFunctionType()->getParamType(4); // value
- Function *newFunction = op->GetOpFunc(hlsl::DXIL::OpCode::BufferStore, ETy);
- for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
- User *user = *(U++);
- if (CallInst *CI = dyn_cast<CallInst>(user)) {
- TranslateCallRawBufferStoreToBufferStore(CI, newFunction, op);
- CI->eraseFromParent();
- }
- else {
- DXASSERT(false, "function can only be used with call instructions.");
- }
- }
- }
- void ReplaceRawBufferLoad64Bit(llvm::Function *F, llvm::Type *EltTy, hlsl::OP *hlslOP) {
- Function *bufLd = hlslOP->GetOpFunc(DXIL::OpCode::RawBufferLoad,
- Type::getInt32Ty(hlslOP->GetCtx()));
- for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
- User *user = *(U++);
- if (CallInst *CI = dyn_cast<CallInst>(user)) {
- IRBuilder<> Builder(CI);
- SmallVector<Value *, 4> args(CI->arg_operands());
- Value *offset = CI->getArgOperand(
- DXIL::OperandIndex::kRawBufferLoadElementOffsetOpIdx);
- unsigned size = 0;
- bool bNeedStatus = false;
- for (User *U : CI->users()) {
- ExtractValueInst *Elt = cast<ExtractValueInst>(U);
- DXASSERT(Elt->getNumIndices() == 1, "else invalid use for resRet");
- unsigned idx = Elt->getIndices()[0];
- if (idx == 4) {
- bNeedStatus = true;
- } else {
- size = std::max(size, idx+1);
- }
- }
- unsigned maskHi = 0;
- unsigned maskLo = 0;
- switch (size) {
- case 1:
- maskLo = 3;
- break;
- case 2:
- maskLo = 0xf;
- break;
- case 3:
- maskLo = 0xf;
- maskHi = 3;
- break;
- case 4:
- maskLo = 0xf;
- maskHi = 0xf;
- break;
- }
- args[DXIL::OperandIndex::kRawBufferLoadMaskOpIdx] =
- Builder.getInt8(maskLo);
- Value *resultElts[5] = {nullptr, nullptr, nullptr, nullptr, nullptr};
- CallInst *newLd = Builder.CreateCall(bufLd, args);
- Value *resultElts32[8];
- unsigned eltBase = 0;
- for (unsigned i = 0; i < size; i++) {
- if (i == 2) {
- // Update offset 4 by 4 bytes.
- if (isa<UndefValue>(offset)) {
- // [RW]ByteAddressBuffer has undef element offset -> update index
- Value *index = CI->getArgOperand(DXIL::OperandIndex::kRawBufferLoadIndexOpIdx);
- args[DXIL::OperandIndex::kRawBufferLoadIndexOpIdx] =
- Builder.CreateAdd(index, Builder.getInt32(4 * 4));
- }
- else {
- // [RW]StructuredBuffer -> update element offset
- args[DXIL::OperandIndex::kRawBufferLoadElementOffsetOpIdx] =
- Builder.CreateAdd(offset, Builder.getInt32(4 * 4));
- }
- args[DXIL::OperandIndex::kRawBufferLoadMaskOpIdx] =
- Builder.getInt8(maskHi);
- newLd = Builder.CreateCall(bufLd, args);
- eltBase = 4;
- }
- unsigned resBase = 2 * i;
- resultElts32[resBase] =
- Builder.CreateExtractValue(newLd, resBase - eltBase);
- resultElts32[resBase + 1] =
- Builder.CreateExtractValue(newLd, resBase + 1 - eltBase);
- }
- Make64bitResultForLoad(EltTy, resultElts32, size, resultElts, hlslOP, Builder);
- if (bNeedStatus) {
- resultElts[4] = Builder.CreateExtractValue(newLd, 4);
- }
- for (auto it = CI->user_begin(); it != CI->user_end(); ) {
- ExtractValueInst *Elt = cast<ExtractValueInst>(*(it++));
- DXASSERT(Elt->getNumIndices() == 1, "else invalid use for resRet");
- unsigned idx = Elt->getIndices()[0];
- if (!Elt->user_empty()) {
- Value *newElt = resultElts[idx];
- Elt->replaceAllUsesWith(newElt);
- }
- Elt->eraseFromParent();
- }
- CI->eraseFromParent();
- } else {
- DXASSERT(false, "function can only be used with call instructions.");
- }
- }
- }
- void ReplaceRawBufferStore64Bit(llvm::Function *F, llvm::Type *ETy, hlsl::OP *hlslOP) {
- Function *newFunction = hlslOP->GetOpFunc(hlsl::DXIL::OpCode::RawBufferStore,
- Type::getInt32Ty(hlslOP->GetCtx()));
- for (auto U = F->user_begin(), E = F->user_end(); U != E;) {
- User *user = *(U++);
- if (CallInst *CI = dyn_cast<CallInst>(user)) {
- IRBuilder<> Builder(CI);
- SmallVector<Value *, 4> args(CI->arg_operands());
- Value *vals[4] = {
- CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal0OpIdx),
- CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal1OpIdx),
- CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal2OpIdx),
- CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreVal3OpIdx)};
- ConstantInt *cMask = cast<ConstantInt>(
- CI->getArgOperand(DXIL::OperandIndex::kRawBufferStoreMaskOpIdx));
- Value *undefI32 = UndefValue::get(Builder.getInt32Ty());
- Value *vals32[8] = {undefI32, undefI32, undefI32, undefI32,
- undefI32, undefI32, undefI32, undefI32};
- unsigned maskLo = 0;
- unsigned maskHi = 0;
- unsigned size = 0;
- unsigned mask = cMask->getLimitedValue();
- switch (mask) {
- case 1:
- maskLo = 3;
- size = 1;
- break;
- case 3:
- maskLo = 15;
- size = 2;
- break;
- case 7:
- maskLo = 15;
- maskHi = 3;
- size = 3;
- break;
- case 15:
- maskLo = 15;
- maskHi = 15;
- size = 4;
- break;
- default:
- DXASSERT(0, "invalid mask");
- }
- Split64bitValForStore(ETy, vals, size, vals32, hlslOP, Builder);
- args[DXIL::OperandIndex::kRawBufferStoreMaskOpIdx] =
- Builder.getInt8(maskLo);
- args[DXIL::OperandIndex::kRawBufferStoreVal0OpIdx] = vals32[0];
- args[DXIL::OperandIndex::kRawBufferStoreVal1OpIdx] = vals32[1];
- args[DXIL::OperandIndex::kRawBufferStoreVal2OpIdx] = vals32[2];
- args[DXIL::OperandIndex::kRawBufferStoreVal3OpIdx] = vals32[3];
- Builder.CreateCall(newFunction, args);
- if (maskHi) {
- // Update offset 4 by 4 bytes.
- Value *offset = args[DXIL::OperandIndex::kBufferStoreCoord1OpIdx];
- if (isa<UndefValue>(offset)) {
- // [RW]ByteAddressBuffer has element offset == undef -> update index instead
- Value *index = args[DXIL::OperandIndex::kBufferStoreCoord0OpIdx];
- index = Builder.CreateAdd(index, Builder.getInt32(4 * 4));
- args[DXIL::OperandIndex::kRawBufferStoreIndexOpIdx] = index;
- }
- else {
- // [RW]StructuredBuffer -> update element offset
- offset = Builder.CreateAdd(offset, Builder.getInt32(4 * 4));
- args[DXIL::OperandIndex::kRawBufferStoreElementOffsetOpIdx] = offset;
- }
- args[DXIL::OperandIndex::kRawBufferStoreMaskOpIdx] =
- Builder.getInt8(maskHi);
- args[DXIL::OperandIndex::kRawBufferStoreVal0OpIdx] = vals32[4];
- args[DXIL::OperandIndex::kRawBufferStoreVal1OpIdx] = vals32[5];
- args[DXIL::OperandIndex::kRawBufferStoreVal2OpIdx] = vals32[6];
- args[DXIL::OperandIndex::kRawBufferStoreVal3OpIdx] = vals32[7];
- Builder.CreateCall(newFunction, args);
- }
- CI->eraseFromParent();
- } else {
- DXASSERT(false, "function can only be used with call instructions.");
- }
- }
- }
- bool IsConvergentMarker(const char *Name) {
- StringRef RName = Name;
- return RName.startswith(kConvergentFunctionPrefix);
- }
- bool IsConvergentMarker(const Function *F) {
- return F && F->getName().startswith(kConvergentFunctionPrefix);
- }
- bool IsConvergentMarker(Value *V) {
- CallInst *CI = dyn_cast<CallInst>(V);
- if (!CI)
- return false;
- return IsConvergentMarker(CI->getCalledFunction());
- }
- Value *GetConvergentSource(Value *V) {
- return cast<CallInst>(V)->getOperand(0);
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- namespace {
- class DxilLoadMetadata : public ModulePass {
- public:
- static char ID; // Pass identification, replacement for typeid
- explicit DxilLoadMetadata () : ModulePass(ID) {}
- const char *getPassName() const override { return "HLSL load DxilModule from metadata"; }
- bool runOnModule(Module &M) override {
- if (!M.HasDxilModule()) {
- (void)M.GetOrCreateDxilModule();
- return true;
- }
- return false;
- }
- };
- }
- char DxilLoadMetadata::ID = 0;
- ModulePass *llvm::createDxilLoadMetadataPass() {
- return new DxilLoadMetadata();
- }
- INITIALIZE_PASS(DxilLoadMetadata, "hlsl-dxilload", "HLSL load DxilModule from metadata", false, false)
|