LLVM 21.0.0git
DXILShaderFlags.cpp
Go to the documentation of this file.
1//===- DXILShaderFlags.cpp - DXIL Shader Flags helper objects -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file This file contains helper objects and APIs for working with DXIL
10/// Shader Flags.
11///
12//===----------------------------------------------------------------------===//
13
14#include "DXILShaderFlags.h"
15#include "DirectX.h"
20#include "llvm/IR/Attributes.h"
22#include "llvm/IR/Instruction.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/IntrinsicsDirectX.h"
27#include "llvm/IR/Module.h"
31
32using namespace llvm;
33using namespace llvm::dxil;
34
35/// Update the shader flags mask based on the given instruction.
36/// \param CSF Shader flags mask to update.
37/// \param I Instruction to check.
38void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
39 const Instruction &I,
40 DXILResourceTypeMap &DRTM) {
41 if (!CSF.Doubles)
42 CSF.Doubles = I.getType()->isDoubleTy();
43
44 if (!CSF.Doubles) {
45 for (const Value *Op : I.operands()) {
46 if (Op->getType()->isDoubleTy()) {
47 CSF.Doubles = true;
48 break;
49 }
50 }
51 }
52
53 if (CSF.Doubles) {
54 switch (I.getOpcode()) {
55 case Instruction::FDiv:
56 case Instruction::UIToFP:
57 case Instruction::SIToFP:
58 case Instruction::FPToUI:
59 case Instruction::FPToSI:
60 CSF.DX11_1_DoubleExtensions = true;
61 break;
62 }
63 }
64
65 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
66 switch (II->getIntrinsicID()) {
67 default:
68 break;
69 case Intrinsic::dx_resource_handlefrombinding:
70 switch (DRTM[cast<TargetExtType>(II->getType())].getResourceKind()) {
73 CSF.EnableRawAndStructuredBuffers = true;
74 break;
75 default:
76 break;
77 }
78 break;
79 case Intrinsic::dx_resource_load_typedbuffer: {
81 DRTM[cast<TargetExtType>(II->getArgOperand(0)->getType())];
82 if (RTI.isTyped())
83 CSF.TypedUAVLoadAdditionalFormats |= RTI.getTyped().ElementCount > 1;
84 break;
85 }
86 }
87 }
88 // Handle call instructions
89 if (auto *CI = dyn_cast<CallInst>(&I)) {
90 const Function *CF = CI->getCalledFunction();
91 // Merge-in shader flags mask of the called function in the current module
92 if (FunctionFlags.contains(CF))
93 CSF.merge(FunctionFlags[CF]);
94
95 // TODO: Set DX11_1_DoubleExtensions if I is a call to DXIL intrinsic
96 // DXIL::Opcode::Fma https://github.com/llvm/llvm-project/issues/114554
97 }
98}
99
100/// Construct ModuleShaderFlags for module Module M
102 const ModuleMetadataInfo &MMDI) {
103 CallGraph CG(M);
104
105 // Compute Shader Flags Mask for all functions using post-order visit of SCC
106 // of the call graph.
107 for (scc_iterator<CallGraph *> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
108 ++SCCI) {
109 const std::vector<CallGraphNode *> &CurSCC = *SCCI;
110
111 // Union of shader masks of all functions in CurSCC
113 // List of functions in CurSCC that are neither external nor declarations
114 // and hence whose flags are collected
115 SmallVector<Function *> CurSCCFuncs;
116 for (CallGraphNode *CGN : CurSCC) {
117 Function *F = CGN->getFunction();
118 if (!F)
119 continue;
120
121 if (F->isDeclaration()) {
122 assert(!F->getName().starts_with("dx.op.") &&
123 "DXIL Shader Flag analysis should not be run post-lowering.");
124 continue;
125 }
126
128 for (const auto &BB : *F)
129 for (const auto &I : BB)
130 updateFunctionFlags(CSF, I, DRTM);
131 // Update combined shader flags mask for all functions in this SCC
132 SCCSF.merge(CSF);
133
134 CurSCCFuncs.push_back(F);
135 }
136
137 // Update combined shader flags mask for all functions of the module
138 CombinedSFMask.merge(SCCSF);
139
140 // Shader flags mask of each of the functions in an SCC of the call graph is
141 // the union of all functions in the SCC. Update shader flags masks of
142 // functions in CurSCC accordingly. This is trivially true if SCC contains
143 // one function.
144 for (Function *F : CurSCCFuncs)
145 // Merge SCCSF with that of F
146 FunctionFlags[F].merge(SCCSF);
147 }
148
149 // Set DisableOptimizations flag based on the presence of OptimizeNone
150 // attribute of entry functions.
151 if (MMDI.EntryPropertyVec.size() > 0) {
152 CombinedSFMask.DisableOptimizations =
153 MMDI.EntryPropertyVec[0].Entry->hasFnAttribute(
154 llvm::Attribute::OptimizeNone);
155 // Ensure all entry functions have the same optimization attribute
156 for (const auto &EntryFunProps : MMDI.EntryPropertyVec)
157 if (CombinedSFMask.DisableOptimizations !=
158 EntryFunProps.Entry->hasFnAttribute(llvm::Attribute::OptimizeNone))
159 EntryFunProps.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
160 *(EntryFunProps.Entry), "Inconsistent optnone attribute "));
161 }
162}
163
165 uint64_t FlagVal = (uint64_t) * this;
166 OS << formatv("; Shader Flags Value: {0:x8}\n;\n", FlagVal);
167 if (FlagVal == 0)
168 return;
169 OS << "; Note: shader requires additional functionality:\n";
170#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleNum, FlagName, Str) \
171 if (FlagName) \
172 (OS << ";").indent(7) << Str << "\n";
173#include "llvm/BinaryFormat/DXContainerConstants.def"
174 OS << "; Note: extra DXIL module flags:\n";
175#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) \
176 if (FlagName) \
177 (OS << ";").indent(7) << Str << "\n";
178#include "llvm/BinaryFormat/DXContainerConstants.def"
179 OS << ";\n";
180}
181
182/// Return the shader flags mask of the specified function Func.
185 auto Iter = FunctionFlags.find(Func);
186 assert((Iter != FunctionFlags.end() && Iter->first == Func) &&
187 "Get Shader Flags : No Shader Flags Mask exists for function");
188 return Iter->second;
189}
190
191//===----------------------------------------------------------------------===//
192// ShaderFlagsAnalysis and ShaderFlagsAnalysisPrinterPass
193
194// Provide an explicit template instantiation for the static ID.
195AnalysisKey ShaderFlagsAnalysis::Key;
196
201
203 MSFI.initialize(M, DRTM, MMDI);
204
205 return MSFI;
206}
207
210 const ModuleShaderFlags &FlagsInfo = AM.getResult<ShaderFlagsAnalysis>(M);
211 // Print description of combined shader flags for all module functions
212 OS << "; Combined Shader Flags for Module\n";
213 FlagsInfo.getCombinedFlags().print(OS);
214 // Print shader flags mask for each of the module functions
215 OS << "; Shader Flags for Module Functions\n";
216 for (const auto &F : M.getFunctionList()) {
217 if (F.isDeclaration())
218 continue;
219 const ComputedShaderFlags &SFMask = FlagsInfo.getFunctionFlags(&F);
220 OS << formatv("; Function {0} : {1:x8}\n;\n", F.getName(),
221 (uint64_t)(SFMask));
222 }
223
224 return PreservedAnalyses::all();
225}
226
227//===----------------------------------------------------------------------===//
228// ShaderFlagsAnalysis and ShaderFlagsAnalysisPrinterPass
229
231 DXILResourceTypeMap &DRTM =
232 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
233 const ModuleMetadataInfo MMDI =
234 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
235
236 MSFI.initialize(M, DRTM, MMDI);
237 return false;
238}
239
241 AU.setPreservesAll();
244}
245
247
249 "DXIL Shader Flag Analysis", true, true)
253 "DXIL Shader Flag Analysis", true, true)
This file contains the simple types necessary to represent the attributes associated with functions a...
basic Basic Alias true
block Block Frequency Analysis
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
module summary analysis
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:410
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
A node in the call graph for a module.
Definition: CallGraph.h:165
The basic data container for the call graph of a Module of IR.
Definition: CallGraph.h:71
This class represents an Operation in the Expression.
Diagnostic information for unsupported feature in backend.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
LLVM Value Representation.
Definition: Value.h:74
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Wrapper pass for the legacy pass manager.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
ModuleShaderFlags run(Module &M, ModuleAnalysisManager &AM)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
Definition: SCCIterator.h:49
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
Definition: SCCIterator.h:233
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:28
void merge(const ComputedShaderFlags CSF)
void print(raw_ostream &OS=dbgs()) const
SmallVector< EntryProperties > EntryPropertyVec
const ComputedShaderFlags & getFunctionFlags(const Function *) const
Return the shader flags mask of the specified function Func.
const ComputedShaderFlags & getCombinedFlags() const
void initialize(Module &, DXILResourceTypeMap &DRTM, const ModuleMetadataInfo &MMDI)
Construct ModuleShaderFlags for module Module M.