diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt --- a/llvm/lib/Target/DirectX/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/CMakeLists.txt @@ -23,6 +23,7 @@ DXILPrepare.cpp DXILResource.cpp DXILResourceAnalysis.cpp + DXILShaderFlags.cpp DXILTranslateMetadata.cpp PointerTypeAnalysis.cpp diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h new file mode 100644 --- /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/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp new file mode 100644 --- /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/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp --- 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 @@ 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 --- /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 --- /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 --- /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 +}