-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[DirectX] Infrastructure to collect shader flags for each function #112967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
3da01ee
397f70b
ae373d4
c02053a
47ab4c5
fa8ec60
a4f1e51
a6d84b2
31b0770
3427781
56af02a
f8e501f
c6b3390
70e46e0
07734f7
a0d2a31
2cee00a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -13,43 +13,114 @@ | |||||
|
|
||||||
| #include "DXILShaderFlags.h" | ||||||
| #include "DirectX.h" | ||||||
| #include "llvm/ADT/STLExtras.h" | ||||||
| #include "llvm/IR/DiagnosticInfo.h" | ||||||
| #include "llvm/IR/DiagnosticPrinter.h" | ||||||
| #include "llvm/IR/Instruction.h" | ||||||
| #include "llvm/IR/Module.h" | ||||||
| #include "llvm/Support/FormatVariadic.h" | ||||||
| #include "llvm/Support/raw_ostream.h" | ||||||
|
|
||||||
| using namespace llvm; | ||||||
| using namespace llvm::dxil; | ||||||
|
|
||||||
| static void updateFlags(DXILModuleShaderFlagsInfo &MSFI, const Instruction &I) { | ||||||
| ComputedShaderFlags &FSF = MSFI.FuncShaderFlagsMap[I.getFunction()]; | ||||||
| namespace { | ||||||
| /// A simple Wrapper DiagnosticInfo that generates Module-level diagnostic | ||||||
| /// for ShaderFlagsAnalysis pass | ||||||
| class DiagnosticInfoShaderFlags : public DiagnosticInfo { | ||||||
| private: | ||||||
| const Twine &Msg; | ||||||
|
||||||
| const Module &Mod; | ||||||
|
|
||||||
| public: | ||||||
| /// \p M is the module for which the diagnostic is being emitted. \p Msg is | ||||||
| /// the message to show. Note that this class does not copy this message, so | ||||||
| /// this reference must be valid for the whole life time of the diagnostic. | ||||||
| DiagnosticInfoShaderFlags(const Module &M, const Twine &Msg, | ||||||
| DiagnosticSeverity Severity = DS_Error) | ||||||
| : DiagnosticInfo(DK_Unsupported, Severity), Msg(Msg), Mod(M) {} | ||||||
|
|
||||||
| void print(DiagnosticPrinter &DP) const override { | ||||||
| DP << Mod.getName() << ": " << Msg << '\n'; | ||||||
| } | ||||||
| }; | ||||||
| } // namespace | ||||||
|
|
||||||
| static void updateFlags(ComputedShaderFlags &CSF, const Instruction &I) { | ||||||
| Type *Ty = I.getType(); | ||||||
| if (Ty->isDoubleTy()) { | ||||||
| FSF.Doubles = true; | ||||||
| bool DoubleTyInUse = Ty->isDoubleTy(); | ||||||
| for (Value *Op : I.operands()) { | ||||||
| DoubleTyInUse |= Op->getType()->isDoubleTy(); | ||||||
| } | ||||||
|
|
||||||
| if (DoubleTyInUse) { | ||||||
| CSF.Doubles = true; | ||||||
| switch (I.getOpcode()) { | ||||||
| case Instruction::FDiv: | ||||||
| case Instruction::UIToFP: | ||||||
| case Instruction::SIToFP: | ||||||
| case Instruction::FPToUI: | ||||||
| case Instruction::FPToSI: | ||||||
| FSF.DX11_1_DoubleExtensions = true; | ||||||
| // TODO: To be set if I is a call to DXIL intrinsic DXIL::Opcode::Fma | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have an issue for this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
| CSF.DX11_1_DoubleExtensions = true; | ||||||
| break; | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| static bool compareFuncSFPairs(const FuncShaderFlagsMask &First, | ||||||
| const FuncShaderFlagsMask &Second) { | ||||||
| // Construct string representation of the functions in each pair | ||||||
| // as "retTypefunctionNamearg1Typearg2Ty..." where the function signature is | ||||||
| // retType functionName(arg1Type, arg2Ty,...). Spaces, braces and commas are | ||||||
| // omitted in the string representation of the signature. This allows | ||||||
| // determining a consistent lexicographical order of all functions by their | ||||||
| // signatures. | ||||||
| std::string FirstFunSig; | ||||||
| std::string SecondFunSig; | ||||||
damyanp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| raw_string_ostream FRSO(FirstFunSig); | ||||||
| raw_string_ostream SRSO(SecondFunSig); | ||||||
|
|
||||||
| // Return type | ||||||
| First.first->getReturnType()->print(FRSO); | ||||||
| Second.first->getReturnType()->print(SRSO); | ||||||
| // Function name | ||||||
| FRSO << First.first->getName(); | ||||||
| SRSO << Second.first->getName(); | ||||||
| // Argument types | ||||||
| for (const Argument &Arg : First.first->args()) { | ||||||
| Arg.getType()->print(FRSO); | ||||||
| } | ||||||
| for (const Argument &Arg : Second.first->args()) { | ||||||
| Arg.getType()->print(SRSO); | ||||||
| } | ||||||
| FRSO.flush(); | ||||||
| SRSO.flush(); | ||||||
|
|
||||||
| return FRSO.str().compare(SRSO.str()) < 0; | ||||||
| } | ||||||
|
|
||||||
| static DXILModuleShaderFlagsInfo computeFlags(Module &M) { | ||||||
| DXILModuleShaderFlagsInfo MSFI; | ||||||
| for (const auto &F : M) { | ||||||
| for (auto &F : M) { | ||||||
| if (F.isDeclaration()) | ||||||
| continue; | ||||||
| if (!MSFI.FuncShaderFlagsMap.contains(&F)) { | ||||||
| ComputedShaderFlags CSF{}; | ||||||
| MSFI.FuncShaderFlagsMap[&F] = CSF; | ||||||
| // Each of the functions in a module are unique. Hence no prior shader flags | ||||||
| // mask of the function should be present. | ||||||
| if (MSFI.hasShaderFlagsMask(&F)) { | ||||||
bharadwajy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| M.getContext().diagnose(DiagnosticInfoShaderFlags( | ||||||
| M, "Shader Flags mask for Function '" + Twine(F.getName()) + | ||||||
damyanp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| "' already exits")); | ||||||
damyanp marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| } | ||||||
| ComputedShaderFlags CSF{}; | ||||||
|
||||||
| ComputedShaderFlags CSF{}; | |
| ComputedShaderFlags CSF; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ComputedShaderFlags has a default constructor to zero itself out, the empty initializer list is unnecessary.
Changed.
bharadwajy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
bharadwajy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
bharadwajy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,7 +14,6 @@ | |
| #ifndef LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H | ||
| #define LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H | ||
|
|
||
| #include "llvm/ADT/DenseMap.h" | ||
| #include "llvm/IR/Function.h" | ||
| #include "llvm/IR/PassManager.h" | ||
| #include "llvm/Pass.h" | ||
|
|
@@ -66,14 +65,18 @@ struct ComputedShaderFlags { | |
| LLVM_DUMP_METHOD void dump() const { print(); } | ||
| }; | ||
|
|
||
| using FunctionShaderFlagsMap = | ||
| SmallDenseMap<Function const *, ComputedShaderFlags>; | ||
| using FuncShaderFlagsMask = std::pair<Function const *, ComputedShaderFlags>; | ||
| using FunctionShaderFlagsVec = SmallVector<FuncShaderFlagsMask>; | ||
bharadwajy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| struct DXILModuleShaderFlagsInfo { | ||
|
||
| // Shader Flag mask representing module-level properties | ||
| ComputedShaderFlags ModuleFlags; | ||
| // Map representing shader flag mask representing properties of each of the | ||
| // functions in the module | ||
| FunctionShaderFlagsMap FuncShaderFlagsMap; | ||
| // Vector of Function-Shader Flag mask pairs representing properties of each | ||
| // of the functions in the module | ||
| FunctionShaderFlagsVec FuncShaderFlagsVec; | ||
bharadwajy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const ComputedShaderFlags getShaderFlagsMask(const Function *Func) const; | ||
| bool hasShaderFlagsMask(const Function *Func) const; | ||
| void print(raw_ostream &OS = dbgs()) const; | ||
bogner marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }; | ||
|
|
||
| class ShaderFlagsAnalysis : public AnalysisInfoMixin<ShaderFlagsAnalysis> { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| ; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC | ||
bogner marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| target triple = "dxil-pc-shadermodel6.7-library" | ||
| define double @div(double %a, double %b) #0 { | ||
| %res = fdiv double %a, %b | ||
| ret double %res | ||
| } | ||
|
|
||
| attributes #0 = { convergent norecurse nounwind "hlsl.export"} | ||
|
|
||
| ; DXC: - Name: SFI0 | ||
| ; DXC-NEXT: Size: 8 | ||
| ; DXC-NEXT: Flags: | ||
| ; DXC-NEXT: Doubles: true | ||
| ; DXC-NOT: {{[A-Za-z]+: +true}} | ||
| ; DXC: DX11_1_DoubleExtensions: true | ||
| ; DXC-NOT: {{[A-Za-z]+: +true}} | ||
| ; DXC: NextUnusedBit: false | ||
|
||
| ; DXC: ... | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,74 @@ | ||
| ; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s | ||
| ; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC | ||
|
|
||
| target triple = "dxil-pc-shadermodel6.7-library" | ||
|
|
||
| ; CHECK: ; Shader Flags Value: 0x00000044 | ||
| ; CHECK: ; Note: shader requires additional functionality: | ||
| ; CHECK: ; Shader Flags mask for Module: | ||
| ; CHECK-NEXT: ; Shader Flags Value: 0x00000000 | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Shader Flags mask for Function: test_fdiv_double | ||
| ; CHECK-NEXT: ; Shader Flags Value: 0x00000044 | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Note: shader requires additional functionality: | ||
| ; CHECK-NEXT: ; Double-precision floating point | ||
| ; CHECK-NEXT: ; Double-precision extensions for 11.1 | ||
| ; CHECK-NEXT: ; Note: extra DXIL module flags: | ||
| ; CHECK-NEXT: {{^;$}} | ||
| define double @div(double %a, double %b) #0 { | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Shader Flags mask for Function: test_sitofp_i64 | ||
| ; CHECK-NEXT: ; Shader Flags Value: 0x00000044 | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Note: shader requires additional functionality: | ||
| ; CHECK-NEXT: ; Double-precision floating point | ||
| ; CHECK-NEXT: ; Double-precision extensions for 11.1 | ||
| ; CHECK-NEXT: ; Note: extra DXIL module flags: | ||
|
||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Shader Flags mask for Function: test_uitofp_i64 | ||
| ; CHECK-NEXT: ; Shader Flags Value: 0x00000044 | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Note: shader requires additional functionality: | ||
| ; CHECK-NEXT: ; Double-precision floating point | ||
| ; CHECK-NEXT: ; Double-precision extensions for 11.1 | ||
| ; CHECK-NEXT: ; Note: extra DXIL module flags: | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Shader Flags mask for Function: test_fptoui_i32 | ||
| ; CHECK-NEXT: ; Shader Flags Value: 0x00000044 | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Note: shader requires additional functionality: | ||
| ; CHECK-NEXT: ; Double-precision floating point | ||
| ; CHECK-NEXT: ; Double-precision extensions for 11.1 | ||
| ; CHECK-NEXT: ; Note: extra DXIL module flags: | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Shader Flags mask for Function: test_fptosi_i64 | ||
| ; CHECK-NEXT: ; Shader Flags Value: 0x00000044 | ||
| ; CHECK-NEXT: ; | ||
| ; CHECK-NEXT: ; Note: shader requires additional functionality: | ||
| ; CHECK-NEXT: ; Double-precision floating point | ||
| ; CHECK-NEXT: ; Double-precision extensions for 11.1 | ||
| ; CHECK-NEXT: ; Note: extra DXIL module flags: | ||
| ; CHECK-NEXT: ; | ||
|
|
||
| define double @test_fdiv_double(double %a, double %b) #0 { | ||
| %res = fdiv double %a, %b | ||
| ret double %res | ||
| } | ||
|
|
||
| attributes #0 = { convergent norecurse nounwind "hlsl.export"} | ||
| define double @test_uitofp_i64(i64 %a) #0 { | ||
| %r = uitofp i64 %a to double | ||
| ret double %r | ||
| } | ||
|
|
||
| define double @test_sitofp_i64(i64 %a) #0 { | ||
| %r = sitofp i64 %a to double | ||
| ret double %r | ||
| } | ||
|
|
||
| ; DXC: - Name: SFI0 | ||
| ; DXC-NEXT: Size: 8 | ||
| ; DXC-NEXT: Flags: | ||
| ; DXC-NEXT: Doubles: true | ||
| ; DXC-NOT: {{[A-Za-z]+: +true}} | ||
| ; DXC: DX11_1_DoubleExtensions: true | ||
| ; DXC-NOT: {{[A-Za-z]+: +true}} | ||
| ; DXC: NextUnusedBit: false | ||
| ; DXC: ... | ||
| define i32 @test_fptoui_i32(double %a) #0 { | ||
| %r = fptoui double %a to i32 | ||
| ret i32 %r | ||
| } | ||
|
|
||
| define i64 @test_fptosi_i64(double %a) #0 { | ||
| %r = fptosi double %a to i64 | ||
| ret i64 %r | ||
| } | ||
|
|
||
| attributes #0 = { convergent norecurse nounwind "hlsl.export"} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have an issue tracking this?