1//===- DXILShaderFlags.h - 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#ifndef LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H
15#define LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H
16
17#include "llvm/Analysis/DXILMetadataAnalysis.h"
18#include "llvm/IR/Function.h"
19#include "llvm/IR/PassManager.h"
20#include "llvm/Pass.h"
21#include "llvm/Support/Compiler.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/raw_ostream.h"
24#include <cstdint>
25
26namespace llvm {
27class Module;
28class GlobalVariable;
29class DXILResourceTypeMap;
30class DXILResourceMap;
31
32namespace dxil {
33
34struct ComputedShaderFlags {
35#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \
36 bool FlagName : 1;
37#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) bool FlagName : 1;
38#include "llvm/BinaryFormat/DXContainerConstants.def"
39
40#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \
41 FlagName = false;
42#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) FlagName = false;
43 ComputedShaderFlags() {
44#include "llvm/BinaryFormat/DXContainerConstants.def"
45 }
46
47 constexpr uint64_t getMask(int Bit) const {
48 return Bit != -1 ? 1ull << Bit : 0;
49 }
50
51 uint64_t getModuleFlags() const {
52 uint64_t ModuleFlags = 0;
53#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) \
54 ModuleFlags |= FlagName ? getMask(DxilModuleBit) : 0ull;
55#include "llvm/BinaryFormat/DXContainerConstants.def"
56 return ModuleFlags;
57 }
58
59 operator uint64_t() const {
60 uint64_t FlagValue = getModuleFlags();
61#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \
62 FlagValue |= FlagName ? getMask(DxilModuleBit) : 0ull;
63#include "llvm/BinaryFormat/DXContainerConstants.def"
64 return FlagValue;
65 }
66
67 uint64_t getFeatureFlags() const {
68 uint64_t FeatureFlags = 0;
69#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \
70 FeatureFlags |= FlagName ? getMask(FeatureBit) : 0ull;
71#include "llvm/BinaryFormat/DXContainerConstants.def"
72 return FeatureFlags;
73 }
74
75 void merge(const ComputedShaderFlags CSF) {
76#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \
77 FlagName |= CSF.FlagName;
78#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) FlagName |= CSF.FlagName;
79#include "llvm/BinaryFormat/DXContainerConstants.def"
80 }
81
82 void print(raw_ostream &OS = dbgs()) const;
83 LLVM_DUMP_METHOD void dump() const { print(); }
84};
85
86struct ModuleShaderFlags {
87 void initialize(Module &, DXILResourceTypeMap &DRTM,
88 const DXILResourceMap &DRM, const ModuleMetadataInfo &MMDI);
89 const ComputedShaderFlags &getFunctionFlags(const Function *) const;
90 const ComputedShaderFlags &getCombinedFlags() const { return CombinedSFMask; }
91
92private:
93 // This boolean is inversely set by the LLVM module flag dx.resmayalias to
94 // determine whether or not the ResMayNotAlias DXIL module flag can be set
95 bool CanSetResMayNotAlias;
96
97 /// Map of Function-Shader Flag Mask pairs representing properties of each of
98 /// the functions in the module. Shader Flags of each function represent both
99 /// module-level and function-level flags
100 DenseMap<const Function *, ComputedShaderFlags> FunctionFlags;
101 /// Combined Shader Flag Mask of all functions of the module
102 ComputedShaderFlags CombinedSFMask{};
103 ComputedShaderFlags gatherGlobalModuleFlags(const Module &M,
104 const DXILResourceMap &,
105 const ModuleMetadataInfo &);
106 void updateFunctionFlags(ComputedShaderFlags &, const Instruction &,
107 DXILResourceTypeMap &, const ModuleMetadataInfo &);
108};
109
110class ShaderFlagsAnalysis : public AnalysisInfoMixin<ShaderFlagsAnalysis> {
111 friend AnalysisInfoMixin<ShaderFlagsAnalysis>;
112 static AnalysisKey Key;
113
114public:
115 ShaderFlagsAnalysis() = default;
116
117 using Result = ModuleShaderFlags;
118
119 ModuleShaderFlags run(Module &M, ModuleAnalysisManager &AM);
120};
121
122/// Printer pass for ShaderFlagsAnalysis results.
123class ShaderFlagsAnalysisPrinter
124 : public OptionalPassInfoMixin<ShaderFlagsAnalysisPrinter> {
125 raw_ostream &OS;
126
127public:
128 explicit ShaderFlagsAnalysisPrinter(raw_ostream &OS) : OS(OS) {}
129 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
130};
131
132/// Wrapper pass for the legacy pass manager.
133///
134/// This is required because the passes that will depend on this are codegen
135/// passes which run through the legacy pass manager.
136class ShaderFlagsAnalysisWrapper : public ModulePass {
137 ModuleShaderFlags MSFI;
138
139public:
140 static char ID;
141
142 ShaderFlagsAnalysisWrapper() : ModulePass(ID) {}
143
144 const ModuleShaderFlags &getShaderFlags() { return MSFI; }
145
146 bool runOnModule(Module &M) override;
147
148 void getAnalysisUsage(AnalysisUsage &AU) const override;
149};
150
151} // namespace dxil
152} // namespace llvm
153
154#endif // LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H
155