xref: /llvm-project/llvm/lib/Target/DirectX/DXILShaderFlags.cpp (revision b6287fd9714d2a34b27e7ef4953f6e68f39463a4)
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