12b2afb25SChris Bieneman //===- DXILShaderFlags.cpp - DXIL Shader Flags helper objects -------------===// 22b2afb25SChris Bieneman // 32b2afb25SChris Bieneman // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42b2afb25SChris Bieneman // See https://llvm.org/LICENSE.txt for license information. 52b2afb25SChris Bieneman // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62b2afb25SChris Bieneman // 72b2afb25SChris Bieneman //===----------------------------------------------------------------------===// 82b2afb25SChris Bieneman /// 92b2afb25SChris Bieneman /// \file This file contains helper objects and APIs for working with DXIL 102b2afb25SChris Bieneman /// Shader Flags. 112b2afb25SChris Bieneman /// 122b2afb25SChris Bieneman //===----------------------------------------------------------------------===// 132b2afb25SChris Bieneman 142b2afb25SChris Bieneman #include "DXILShaderFlags.h" 152b2afb25SChris Bieneman #include "DirectX.h" 16a4b7a2d0SS. Bharadwaj Yadavalli #include "llvm/ADT/SCCIterator.h" 17a4b7a2d0SS. Bharadwaj Yadavalli #include "llvm/ADT/SmallVector.h" 18a4b7a2d0SS. Bharadwaj Yadavalli #include "llvm/Analysis/CallGraph.h" 199b3d85f0SJustin Bogner #include "llvm/Analysis/DXILResource.h" 202b2afb25SChris Bieneman #include "llvm/IR/Instruction.h" 21a4b7a2d0SS. Bharadwaj Yadavalli #include "llvm/IR/Instructions.h" 229b3d85f0SJustin Bogner #include "llvm/IR/IntrinsicInst.h" 239b3d85f0SJustin Bogner #include "llvm/IR/Intrinsics.h" 249b3d85f0SJustin Bogner #include "llvm/IR/IntrinsicsDirectX.h" 252b2afb25SChris Bieneman #include "llvm/IR/Module.h" 269b3d85f0SJustin Bogner #include "llvm/InitializePasses.h" 272b2afb25SChris Bieneman #include "llvm/Support/FormatVariadic.h" 2896547decSS. Bharadwaj Yadavalli #include "llvm/Support/raw_ostream.h" 292b2afb25SChris Bieneman 302b2afb25SChris Bieneman using namespace llvm; 312b2afb25SChris Bieneman using namespace llvm::dxil; 322b2afb25SChris Bieneman 33a4b7a2d0SS. Bharadwaj Yadavalli /// Update the shader flags mask based on the given instruction. 34a4b7a2d0SS. Bharadwaj Yadavalli /// \param CSF Shader flags mask to update. 35a4b7a2d0SS. Bharadwaj Yadavalli /// \param I Instruction to check. 36a4b7a2d0SS. Bharadwaj Yadavalli void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF, 37a4b7a2d0SS. Bharadwaj Yadavalli const Instruction &I, 389b3d85f0SJustin Bogner DXILResourceTypeMap &DRTM) { 3996547decSS. Bharadwaj Yadavalli if (!CSF.Doubles) 4096547decSS. Bharadwaj Yadavalli CSF.Doubles = I.getType()->isDoubleTy(); 4196547decSS. Bharadwaj Yadavalli 4296547decSS. Bharadwaj Yadavalli if (!CSF.Doubles) { 43a4b7a2d0SS. Bharadwaj Yadavalli for (const Value *Op : I.operands()) { 44a4b7a2d0SS. Bharadwaj Yadavalli if (Op->getType()->isDoubleTy()) { 45a4b7a2d0SS. Bharadwaj Yadavalli CSF.Doubles = true; 46a4b7a2d0SS. Bharadwaj Yadavalli break; 4796547decSS. Bharadwaj Yadavalli } 48a4b7a2d0SS. Bharadwaj Yadavalli } 49a4b7a2d0SS. Bharadwaj Yadavalli } 50a4b7a2d0SS. Bharadwaj Yadavalli 5196547decSS. Bharadwaj Yadavalli if (CSF.Doubles) { 522b2afb25SChris Bieneman switch (I.getOpcode()) { 532b2afb25SChris Bieneman case Instruction::FDiv: 542b2afb25SChris Bieneman case Instruction::UIToFP: 552b2afb25SChris Bieneman case Instruction::SIToFP: 562b2afb25SChris Bieneman case Instruction::FPToUI: 572b2afb25SChris Bieneman case Instruction::FPToSI: 5896547decSS. Bharadwaj Yadavalli CSF.DX11_1_DoubleExtensions = true; 592b2afb25SChris Bieneman break; 602b2afb25SChris Bieneman } 612b2afb25SChris Bieneman } 629b3d85f0SJustin Bogner 639b3d85f0SJustin Bogner if (auto *II = dyn_cast<IntrinsicInst>(&I)) { 649b3d85f0SJustin Bogner switch (II->getIntrinsicID()) { 659b3d85f0SJustin Bogner default: 669b3d85f0SJustin Bogner break; 67*b6287fd9SJustin Bogner case Intrinsic::dx_resource_handlefrombinding: 68*b6287fd9SJustin Bogner switch (DRTM[cast<TargetExtType>(II->getType())].getResourceKind()) { 69*b6287fd9SJustin Bogner case dxil::ResourceKind::StructuredBuffer: 70*b6287fd9SJustin Bogner case dxil::ResourceKind::RawBuffer: 71*b6287fd9SJustin Bogner CSF.EnableRawAndStructuredBuffers = true; 72*b6287fd9SJustin Bogner break; 73*b6287fd9SJustin Bogner default: 74*b6287fd9SJustin Bogner break; 75*b6287fd9SJustin Bogner } 76*b6287fd9SJustin Bogner break; 77aa07f922SJustin Bogner case Intrinsic::dx_resource_load_typedbuffer: { 789b3d85f0SJustin Bogner dxil::ResourceTypeInfo &RTI = 799b3d85f0SJustin Bogner DRTM[cast<TargetExtType>(II->getArgOperand(0)->getType())]; 809b3d85f0SJustin Bogner if (RTI.isTyped()) 819b3d85f0SJustin Bogner CSF.TypedUAVLoadAdditionalFormats |= RTI.getTyped().ElementCount > 1; 82*b6287fd9SJustin Bogner break; 839b3d85f0SJustin Bogner } 849b3d85f0SJustin Bogner } 859b3d85f0SJustin Bogner } 86a4b7a2d0SS. Bharadwaj Yadavalli // Handle call instructions 87a4b7a2d0SS. Bharadwaj Yadavalli if (auto *CI = dyn_cast<CallInst>(&I)) { 88a4b7a2d0SS. Bharadwaj Yadavalli const Function *CF = CI->getCalledFunction(); 89a4b7a2d0SS. Bharadwaj Yadavalli // Merge-in shader flags mask of the called function in the current module 90a4b7a2d0SS. Bharadwaj Yadavalli if (FunctionFlags.contains(CF)) 91a4b7a2d0SS. Bharadwaj Yadavalli CSF.merge(FunctionFlags[CF]); 92a4b7a2d0SS. Bharadwaj Yadavalli 93a4b7a2d0SS. Bharadwaj Yadavalli // TODO: Set DX11_1_DoubleExtensions if I is a call to DXIL intrinsic 94a4b7a2d0SS. Bharadwaj Yadavalli // DXIL::Opcode::Fma https://github.com/llvm/llvm-project/issues/114554 95a4b7a2d0SS. Bharadwaj Yadavalli } 962b2afb25SChris Bieneman } 972b2afb25SChris Bieneman 98a4b7a2d0SS. Bharadwaj Yadavalli /// Construct ModuleShaderFlags for module Module M 99a4b7a2d0SS. Bharadwaj Yadavalli void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM) { 100a4b7a2d0SS. Bharadwaj Yadavalli CallGraph CG(M); 1019b3d85f0SJustin Bogner 102a4b7a2d0SS. Bharadwaj Yadavalli // Compute Shader Flags Mask for all functions using post-order visit of SCC 103a4b7a2d0SS. Bharadwaj Yadavalli // of the call graph. 104a4b7a2d0SS. Bharadwaj Yadavalli for (scc_iterator<CallGraph *> SCCI = scc_begin(&CG); !SCCI.isAtEnd(); 105a4b7a2d0SS. Bharadwaj Yadavalli ++SCCI) { 106a4b7a2d0SS. Bharadwaj Yadavalli const std::vector<CallGraphNode *> &CurSCC = *SCCI; 107a4b7a2d0SS. Bharadwaj Yadavalli 108a4b7a2d0SS. Bharadwaj Yadavalli // Union of shader masks of all functions in CurSCC 109a4b7a2d0SS. Bharadwaj Yadavalli ComputedShaderFlags SCCSF; 110a4b7a2d0SS. Bharadwaj Yadavalli // List of functions in CurSCC that are neither external nor declarations 111a4b7a2d0SS. Bharadwaj Yadavalli // and hence whose flags are collected 112a4b7a2d0SS. Bharadwaj Yadavalli SmallVector<Function *> CurSCCFuncs; 113a4b7a2d0SS. Bharadwaj Yadavalli for (CallGraphNode *CGN : CurSCC) { 114a4b7a2d0SS. Bharadwaj Yadavalli Function *F = CGN->getFunction(); 115a4b7a2d0SS. Bharadwaj Yadavalli if (!F) 116a4b7a2d0SS. Bharadwaj Yadavalli continue; 117a4b7a2d0SS. Bharadwaj Yadavalli 118a4b7a2d0SS. Bharadwaj Yadavalli if (F->isDeclaration()) { 119a4b7a2d0SS. Bharadwaj Yadavalli assert(!F->getName().starts_with("dx.op.") && 120bfd05102SJustin Bogner "DXIL Shader Flag analysis should not be run post-lowering."); 12196547decSS. Bharadwaj Yadavalli continue; 122bfd05102SJustin Bogner } 123a4b7a2d0SS. Bharadwaj Yadavalli 12496547decSS. Bharadwaj Yadavalli ComputedShaderFlags CSF; 125a4b7a2d0SS. Bharadwaj Yadavalli for (const auto &BB : *F) 1262b2afb25SChris Bieneman for (const auto &I : BB) 1279b3d85f0SJustin Bogner updateFunctionFlags(CSF, I, DRTM); 128a4b7a2d0SS. Bharadwaj Yadavalli // Update combined shader flags mask for all functions in this SCC 129a4b7a2d0SS. Bharadwaj Yadavalli SCCSF.merge(CSF); 130a4b7a2d0SS. Bharadwaj Yadavalli 131a4b7a2d0SS. Bharadwaj Yadavalli CurSCCFuncs.push_back(F); 13296547decSS. Bharadwaj Yadavalli } 133a4b7a2d0SS. Bharadwaj Yadavalli 134a4b7a2d0SS. Bharadwaj Yadavalli // Update combined shader flags mask for all functions of the module 135a4b7a2d0SS. Bharadwaj Yadavalli CombinedSFMask.merge(SCCSF); 136a4b7a2d0SS. Bharadwaj Yadavalli 137a4b7a2d0SS. Bharadwaj Yadavalli // Shader flags mask of each of the functions in an SCC of the call graph is 138a4b7a2d0SS. Bharadwaj Yadavalli // the union of all functions in the SCC. Update shader flags masks of 139a4b7a2d0SS. Bharadwaj Yadavalli // functions in CurSCC accordingly. This is trivially true if SCC contains 140a4b7a2d0SS. Bharadwaj Yadavalli // one function. 141a4b7a2d0SS. Bharadwaj Yadavalli for (Function *F : CurSCCFuncs) 142a4b7a2d0SS. Bharadwaj Yadavalli // Merge SCCSF with that of F 143a4b7a2d0SS. Bharadwaj Yadavalli FunctionFlags[F].merge(SCCSF); 144a4b7a2d0SS. Bharadwaj Yadavalli } 1452b2afb25SChris Bieneman } 1462b2afb25SChris Bieneman 1472b2afb25SChris Bieneman void ComputedShaderFlags::print(raw_ostream &OS) const { 1482b2afb25SChris Bieneman uint64_t FlagVal = (uint64_t) * this; 1492b2afb25SChris Bieneman OS << formatv("; Shader Flags Value: {0:x8}\n;\n", FlagVal); 1502b2afb25SChris Bieneman if (FlagVal == 0) 1512b2afb25SChris Bieneman return; 1522b2afb25SChris Bieneman OS << "; Note: shader requires additional functionality:\n"; 1534dc03701SXiang Li #define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleNum, FlagName, Str) \ 1542b2afb25SChris Bieneman if (FlagName) \ 1554dc03701SXiang Li (OS << ";").indent(7) << Str << "\n"; 1564dc03701SXiang Li #include "llvm/BinaryFormat/DXContainerConstants.def" 1574dc03701SXiang Li OS << "; Note: extra DXIL module flags:\n"; 1584dc03701SXiang Li #define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) \ 1594dc03701SXiang Li if (FlagName) \ 1604dc03701SXiang Li (OS << ";").indent(7) << Str << "\n"; 1612b2afb25SChris Bieneman #include "llvm/BinaryFormat/DXContainerConstants.def" 1622b2afb25SChris Bieneman OS << ";\n"; 1632b2afb25SChris Bieneman } 1642b2afb25SChris Bieneman 16596547decSS. Bharadwaj Yadavalli /// Return the shader flags mask of the specified function Func. 16696547decSS. Bharadwaj Yadavalli const ComputedShaderFlags & 16796547decSS. Bharadwaj Yadavalli ModuleShaderFlags::getFunctionFlags(const Function *Func) const { 168a4b7a2d0SS. Bharadwaj Yadavalli auto Iter = FunctionFlags.find(Func); 16996547decSS. Bharadwaj Yadavalli assert((Iter != FunctionFlags.end() && Iter->first == Func) && 170a4b7a2d0SS. Bharadwaj Yadavalli "Get Shader Flags : No Shader Flags Mask exists for function"); 17196547decSS. Bharadwaj Yadavalli return Iter->second; 17296547decSS. Bharadwaj Yadavalli } 17396547decSS. Bharadwaj Yadavalli 17496547decSS. Bharadwaj Yadavalli //===----------------------------------------------------------------------===// 17596547decSS. Bharadwaj Yadavalli // ShaderFlagsAnalysis and ShaderFlagsAnalysisPrinterPass 17696547decSS. Bharadwaj Yadavalli 17796547decSS. Bharadwaj Yadavalli // Provide an explicit template instantiation for the static ID. 1782b2afb25SChris Bieneman AnalysisKey ShaderFlagsAnalysis::Key; 1792b2afb25SChris Bieneman 18096547decSS. Bharadwaj Yadavalli ModuleShaderFlags ShaderFlagsAnalysis::run(Module &M, 1812b2afb25SChris Bieneman ModuleAnalysisManager &AM) { 1829b3d85f0SJustin Bogner DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M); 1839b3d85f0SJustin Bogner 18496547decSS. Bharadwaj Yadavalli ModuleShaderFlags MSFI; 1859b3d85f0SJustin Bogner MSFI.initialize(M, DRTM); 1869b3d85f0SJustin Bogner 18796547decSS. Bharadwaj Yadavalli return MSFI; 1882b2afb25SChris Bieneman } 1892b2afb25SChris Bieneman 1902b2afb25SChris Bieneman PreservedAnalyses ShaderFlagsAnalysisPrinter::run(Module &M, 1912b2afb25SChris Bieneman ModuleAnalysisManager &AM) { 19296547decSS. Bharadwaj Yadavalli const ModuleShaderFlags &FlagsInfo = AM.getResult<ShaderFlagsAnalysis>(M); 19396547decSS. Bharadwaj Yadavalli // Print description of combined shader flags for all module functions 19496547decSS. Bharadwaj Yadavalli OS << "; Combined Shader Flags for Module\n"; 19596547decSS. Bharadwaj Yadavalli FlagsInfo.getCombinedFlags().print(OS); 19696547decSS. Bharadwaj Yadavalli // Print shader flags mask for each of the module functions 19796547decSS. Bharadwaj Yadavalli OS << "; Shader Flags for Module Functions\n"; 19896547decSS. Bharadwaj Yadavalli for (const auto &F : M.getFunctionList()) { 19996547decSS. Bharadwaj Yadavalli if (F.isDeclaration()) 20096547decSS. Bharadwaj Yadavalli continue; 201a4b7a2d0SS. Bharadwaj Yadavalli const ComputedShaderFlags &SFMask = FlagsInfo.getFunctionFlags(&F); 20296547decSS. Bharadwaj Yadavalli OS << formatv("; Function {0} : {1:x8}\n;\n", F.getName(), 20396547decSS. Bharadwaj Yadavalli (uint64_t)(SFMask)); 20496547decSS. Bharadwaj Yadavalli } 20596547decSS. Bharadwaj Yadavalli 2062b2afb25SChris Bieneman return PreservedAnalyses::all(); 2072b2afb25SChris Bieneman } 2086e05c8dfSChris Bieneman 20996547decSS. Bharadwaj Yadavalli //===----------------------------------------------------------------------===// 21096547decSS. Bharadwaj Yadavalli // ShaderFlagsAnalysis and ShaderFlagsAnalysisPrinterPass 21196547decSS. Bharadwaj Yadavalli 21296547decSS. Bharadwaj Yadavalli bool ShaderFlagsAnalysisWrapper::runOnModule(Module &M) { 2139b3d85f0SJustin Bogner DXILResourceTypeMap &DRTM = 2149b3d85f0SJustin Bogner getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap(); 2159b3d85f0SJustin Bogner 2169b3d85f0SJustin Bogner MSFI.initialize(M, DRTM); 21796547decSS. Bharadwaj Yadavalli return false; 21896547decSS. Bharadwaj Yadavalli } 21996547decSS. Bharadwaj Yadavalli 2209b3d85f0SJustin Bogner void ShaderFlagsAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { 2219b3d85f0SJustin Bogner AU.setPreservesAll(); 2229b3d85f0SJustin Bogner AU.addRequiredTransitive<DXILResourceTypeWrapperPass>(); 2239b3d85f0SJustin Bogner } 2249b3d85f0SJustin Bogner 2256e05c8dfSChris Bieneman char ShaderFlagsAnalysisWrapper::ID = 0; 2266e05c8dfSChris Bieneman 2279b3d85f0SJustin Bogner INITIALIZE_PASS_BEGIN(ShaderFlagsAnalysisWrapper, "dx-shader-flag-analysis", 2289b3d85f0SJustin Bogner "DXIL Shader Flag Analysis", true, true) 2299b3d85f0SJustin Bogner INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) 2309b3d85f0SJustin Bogner INITIALIZE_PASS_END(ShaderFlagsAnalysisWrapper, "dx-shader-flag-analysis", 2316e05c8dfSChris Bieneman "DXIL Shader Flag Analysis", true, true) 232