From 2b2afb2529a143d91989716212709e63926e9547 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 11 Oct 2022 12:09:30 -0500 Subject: [PATCH] [DX] Add analysis and printer for shader flags This adds infrastructural pieces for an analysis to compute the DXIL shader flags. In this state the analysis can compute two fairly straightforward feature flags for use of double-precision floating point values and the DX 11.1 extended double support. This patch does conflict with D135190, conflicts will be resolved prior to merging. Reviewed By: python3kgae Differential Revision: https://reviews.llvm.org/D135393 # Conflicts: # llvm/lib/Target/DirectX/CMakeLists.txt # llvm/lib/Target/DirectX/DirectXTargetMachine.cpp --- llvm/lib/Target/DirectX/CMakeLists.txt | 1 + llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 73 ++++++++++++++++++++ llvm/lib/Target/DirectX/DXILShaderFlags.h | 79 ++++++++++++++++++++++ llvm/lib/Target/DirectX/DirectXTargetMachine.cpp | 6 ++ .../DirectX/ShaderFlags/double-extensions.ll | 13 ++++ llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll | 12 ++++ llvm/test/CodeGen/DirectX/ShaderFlags/no_flags.ll | 9 +++ 7 files changed, 193 insertions(+) create mode 100644 llvm/lib/Target/DirectX/DXILShaderFlags.cpp create mode 100644 llvm/lib/Target/DirectX/DXILShaderFlags.h create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/no_flags.ll diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt index 62e51a5..4079762 100644 --- a/llvm/lib/Target/DirectX/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/CMakeLists.txt @@ -23,6 +23,7 @@ add_llvm_target(DirectXCodeGen DXILPrepare.cpp DXILResource.cpp DXILResourceAnalysis.cpp + DXILShaderFlags.cpp DXILTranslateMetadata.cpp PointerTypeAnalysis.cpp diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp new file mode 100644 index 0000000..6af3847 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp @@ -0,0 +1,73 @@ +//===- DXILShaderFlags.cpp - DXIL Shader Flags helper objects -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains helper objects and APIs for working with DXIL +/// Shader Flags. +/// +//===----------------------------------------------------------------------===// + +#include "DXILShaderFlags.h" +#include "DirectX.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::dxil; + +static void updateFlags(ComputedShaderFlags &Flags, const Instruction &I) { + Type *Ty = I.getType(); + if (Ty->isDoubleTy()) { + Flags.Doubles = true; + switch (I.getOpcode()) { + case Instruction::FDiv: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + Flags.DX11_1_DoubleExtensions = true; + break; + } + } +} + +ComputedShaderFlags ComputedShaderFlags::computeFlags(Module &M) { + ComputedShaderFlags Flags; + for (const auto &F : M) + for (const auto &BB : F) + for (const auto &I : BB) + updateFlags(Flags, I); + return Flags; +} + +void ComputedShaderFlags::print(raw_ostream &OS) const { + uint64_t FlagVal = (uint64_t) * this; + OS << formatv("; Shader Flags Value: {0:x8}\n;\n", FlagVal); + if (FlagVal == 0) + return; + OS << "; Note: shader requires additional functionality:\n"; +#define SHADER_FLAG(bit, FlagName, Str) \ + if (FlagName) \ + OS << "; " Str "\n"; +#include "llvm/BinaryFormat/DXContainerConstants.def" + OS << ";\n"; +} + +AnalysisKey ShaderFlagsAnalysis::Key; + +ComputedShaderFlags ShaderFlagsAnalysis::run(Module &M, + ModuleAnalysisManager &AM) { + return ComputedShaderFlags::computeFlags(M); +} + +PreservedAnalyses ShaderFlagsAnalysisPrinter::run(Module &M, + ModuleAnalysisManager &AM) { + ComputedShaderFlags Flags = AM.getResult(M); + Flags.print(OS); + return PreservedAnalyses::all(); +} diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h new file mode 100644 index 0000000..e877594 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.h @@ -0,0 +1,79 @@ +//===- DXILShaderFlags.h - DXIL Shader Flags helper objects ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains helper objects and APIs for working with DXIL +/// Shader Flags. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H +#define LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H + +#include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { +class Module; +class GlobalVariable; + +namespace dxil { + +struct ComputedShaderFlags { +#define SHADER_FLAG(bit, FlagName, Str) bool FlagName : 1; +#include "llvm/BinaryFormat/DXContainerConstants.def" + +#define SHADER_FLAG(bit, FlagName, Str) FlagName = false; + ComputedShaderFlags() { +#include "llvm/BinaryFormat/DXContainerConstants.def" + } + + operator uint64_t() const { + uint64_t FlagValue = 0; +#define SHADER_FLAG(bit, FlagName, Str) \ + FlagValue |= \ + FlagName ? static_cast(dxbc::FeatureFlags::FlagName) : 0ull; +#include "llvm/BinaryFormat/DXContainerConstants.def" + return FlagValue; + } + + static ComputedShaderFlags computeFlags(Module &M); + void print(raw_ostream &OS = dbgs()) const; + LLVM_DUMP_METHOD void dump() const { print(); } +}; + +class ShaderFlagsAnalysis : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static AnalysisKey Key; + +public: + ShaderFlagsAnalysis() = default; + + using Result = ComputedShaderFlags; + + ComputedShaderFlags run(Module &M, ModuleAnalysisManager &AM); +}; + +/// Printer pass for ShaderFlagsAnalysis results. +class ShaderFlagsAnalysisPrinter + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit ShaderFlagsAnalysisPrinter(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // namespace dxil +} // namespace llvm + +#endif // LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp index 81aaf86..c435ca6 100644 --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -13,6 +13,7 @@ #include "DirectXTargetMachine.h" #include "DXILResourceAnalysis.h" +#include "DXILShaderFlags.h" #include "DXILWriter/DXILWriterPass.h" #include "DirectX.h" #include "DirectXSubtarget.h" @@ -103,11 +104,16 @@ void DirectXTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { PM.addPass(DXILResourcePrinterPass(dbgs())); return true; } + if (PassName == "print-dx-shader-flags") { + PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs())); + return true; + } return false; }); PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) { MAM.registerPass([&] { return DXILResourceAnalysis(); }); + MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); }); }); } diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll new file mode 100644 index 0000000..4eba4f2 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll @@ -0,0 +1,13 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.7-library" + +; CHECK: ; Shader Flags Value: 0x00000021 +; CHECK: ; Note: shader requires additional functionality: +; CHECK-NEXT: ; Double-precision floating point +; CHECK-NEXT: ; Double-precision extensions for 11.1 +; CHECK-NEXT: {{^;$}} +define double @div(double %a, double %b) { + %res = fdiv double %a, %b + ret double %res +} diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll new file mode 100644 index 0000000..01ba14b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll @@ -0,0 +1,12 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.7-library" + +; CHECK: ; Shader Flags Value: 0x00000001 +; CHECK: ; Note: shader requires additional functionality: +; CHECK-NEXT: ; Double-precision floating point +; CHECK-NEXT: {{^;$}} +define double @add(double %a, double %b) { + %sum = fadd double %a, %b + ret double %sum +} diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/no_flags.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/no_flags.ll new file mode 100644 index 0000000..f7baa1b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/no_flags.ll @@ -0,0 +1,9 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.7-library" + +; CHECK: ; Shader Flags Value: 0x00000000 +define i32 @add(i32 %a, i32 %b) { + %sum = add i32 %a, %b + ret i32 %sum +} -- 2.7.4