diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 7da30e6cf96f6c..20cca592878277 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -428,6 +428,10 @@ class Triple { /// (SubArch). This should only be called with Vulkan SPIR-V triples. VersionTuple getVulkanVersion() const; + /// Parse the DXIL version number from the DXIL version + /// (SubArch). This should only be called with DXIL triples. + VersionTuple getDXILVersion() const; + /// @} /// @name Direct Component Access /// @{ diff --git a/llvm/lib/Target/DirectX/DXILMetadata.cpp b/llvm/lib/Target/DirectX/DXILMetadata.cpp index 03758dc76e7eb0..ed0434ac98a18b 100644 --- a/llvm/lib/Target/DirectX/DXILMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILMetadata.cpp @@ -90,6 +90,18 @@ void dxil::createShaderModelMD(Module &M) { Entry->addOperand(MDNode::get(Ctx, Vals)); } +void dxil::createDXILVersionMD(Module &M) { + Triple TT(Triple::normalize(M.getTargetTriple())); + VersionTuple Ver = TT.getDXILVersion(); + LLVMContext &Ctx = M.getContext(); + IRBuilder<> B(Ctx); + NamedMDNode *Entry = M.getOrInsertNamedMetadata("dx.version"); + Metadata *Vals[2]; + Vals[0] = ConstantAsMetadata::get(B.getInt32(Ver.getMajor())); + Vals[1] = ConstantAsMetadata::get(B.getInt32(Ver.getMinor().value_or(0))); + Entry->addOperand(MDNode::get(Ctx, Vals)); +} + static uint32_t getShaderStage(Triple::EnvironmentType Env) { return (uint32_t)Env - (uint32_t)llvm::Triple::Pixel; } diff --git a/llvm/lib/Target/DirectX/DXILMetadata.h b/llvm/lib/Target/DirectX/DXILMetadata.h index cd9f4c83fbd0f8..e05db8d5370dbe 100644 --- a/llvm/lib/Target/DirectX/DXILMetadata.h +++ b/llvm/lib/Target/DirectX/DXILMetadata.h @@ -34,6 +34,7 @@ class ValidatorVersionMD { }; void createShaderModelMD(Module &M); +void createDXILVersionMD(Module &M); void createEntryMD(Module &M, const uint64_t ShaderFlags); } // namespace dxil diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 80d94bf0c9d488..ae6d6f96904c86 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -48,6 +48,7 @@ bool DXILTranslateMetadata::runOnModule(Module &M) { if (ValVerMD.isEmpty()) ValVerMD.update(VersionTuple(1, 0)); dxil::createShaderModelMD(M); + dxil::createDXILVersionMD(M); const dxil::Resources &Res = getAnalysis().getDXILResource(); diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index f3f244c814e7ee..18ec6029681099 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -1420,6 +1420,17 @@ VersionTuple Triple::getVulkanVersion() const { return VersionTuple(0); } +VersionTuple Triple::getDXILVersion() const { + if (getArch() != dxil || getOS() != ShaderModel) + llvm_unreachable("invalid DXIL triple"); + StringRef Arch = getArchName(); + Arch.consume_front("dxilv"); + VersionTuple DXILVersion = parseVersionFromName(Arch); + // FIXME: validate DXIL version against Shader Model version. + // Tracked by https://github.com/llvm/llvm-project/issues/91388 + return DXILVersion; +} + void Triple::setTriple(const Twine &Str) { *this = Triple(Str); } diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll new file mode 100644 index 00000000000000..254479e5f94cbd --- /dev/null +++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll @@ -0,0 +1,12 @@ +; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +target triple = "dxil-pc-shadermodel6.0-vertex" + +; CHECK: !dx.version = !{![[DXVER:[0-9]+]]} +; CHECK: ![[DXVER]] = !{i32 1, i32 0} + +define void @entry() #0 { +entry: + ret void +} + +attributes #0 = { noinline nounwind "hlsl.shader"="vertex" } diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll new file mode 100644 index 00000000000000..efeb5a1b24862e --- /dev/null +++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll @@ -0,0 +1,12 @@ +; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +target triple = "dxil-pc-shadermodel6.8-compute" + +; CHECK: !dx.version = !{![[DXVER:[0-9]+]]} +; CHECK: ![[DXVER]] = !{i32 1, i32 8} + +define void @entry() #0 { +entry: + ret void +} + +attributes #0 = { noinline nounwind "hlsl.numthreads"="1,2,1" "hlsl.shader"="compute" } diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp index b8f5fbd87407d3..8e90ee6858f458 100644 --- a/llvm/unittests/TargetParser/TripleTest.cpp +++ b/llvm/unittests/TargetParser/TripleTest.cpp @@ -437,6 +437,85 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(VersionTuple(1, 3), T.getVulkanVersion()); EXPECT_EQ(Triple::Compute, T.getEnvironment()); + T = Triple("dxilv1.0--shadermodel6.0-pixel"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_0, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 0), T.getDXILVersion()); + EXPECT_EQ(Triple::Pixel, T.getEnvironment()); + + T = Triple("dxilv1.1--shadermodel6.1-vertex"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_1, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 1), T.getDXILVersion()); + EXPECT_EQ(Triple::Vertex, T.getEnvironment()); + + T = Triple("dxilv1.2--shadermodel6.2-geometry"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_2, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 2), T.getDXILVersion()); + EXPECT_EQ(Triple::Geometry, T.getEnvironment()); + + T = Triple("dxilv1.3--shadermodel6.3-library"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_3, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 3), T.getDXILVersion()); + EXPECT_EQ(Triple::Library, T.getEnvironment()); + + T = Triple("dxilv1.4--shadermodel6.4-hull"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_4, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 4), T.getDXILVersion()); + EXPECT_EQ(Triple::Hull, T.getEnvironment()); + + T = Triple("dxilv1.5--shadermodel6.5-domain"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_5, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 5), T.getDXILVersion()); + EXPECT_EQ(Triple::Domain, T.getEnvironment()); + + T = Triple("dxilv1.6--shadermodel6.6-compute"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_6, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 6), T.getDXILVersion()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + + T = Triple("dxilv1.7-unknown-shadermodel6.7-mesh"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_7, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 7), T.getDXILVersion()); + EXPECT_EQ(Triple::Mesh, T.getEnvironment()); + + T = Triple("dxilv1.8-unknown-shadermodel6.8-amplification"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_8, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 8), T.getDXILVersion()); + EXPECT_EQ(Triple::Amplification, T.getEnvironment()); + + T = Triple("dxilv1.8-unknown-shadermodel6.15-library"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_8, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 8), T.getDXILVersion()); + T = Triple("x86_64-unknown-fuchsia"); EXPECT_EQ(Triple::x86_64, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor());