diff --git a/llvm/lib/Target/DirectX/DXILMetadata.h b/llvm/lib/Target/DirectX/DXILMetadata.h --- a/llvm/lib/Target/DirectX/DXILMetadata.h +++ b/llvm/lib/Target/DirectX/DXILMetadata.h @@ -30,6 +30,8 @@ bool isEmpty(); }; +void createEntryMD(Module &M); + } // namespace dxil } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILMetadata.cpp b/llvm/lib/Target/DirectX/DXILMetadata.cpp --- a/llvm/lib/Target/DirectX/DXILMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILMetadata.cpp @@ -15,21 +15,28 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/ADT/Triple.h" using namespace llvm; using namespace llvm::dxil; +static ConstantAsMetadata *uint32ToConstMD(unsigned V, LLVMContext &Ctx) { + return ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), V)); +} + +static ConstantAsMetadata *uint64ToConstMD(uint64_t V, LLVMContext &Ctx) { + return ConstantAsMetadata::get(ConstantInt::get(Type::getInt64Ty(Ctx), V)); +} + ValidatorVersionMD::ValidatorVersionMD(Module &M) : Entry(M.getOrInsertNamedMetadata("dx.valver")) {} void ValidatorVersionMD::update(VersionTuple ValidatorVer) { auto &Ctx = Entry->getParent()->getContext(); - IRBuilder<> B(Ctx); Metadata *MDVals[2]; - MDVals[0] = ConstantAsMetadata::get(B.getInt32(ValidatorVer.getMajor())); - MDVals[1] = - ConstantAsMetadata::get(B.getInt32(ValidatorVer.getMinor().value_or(0))); + MDVals[0] = uint32ToConstMD(ValidatorVer.getMajor(), Ctx); + MDVals[1] = uint32ToConstMD(ValidatorVer.getMinor().value_or(0), Ctx); if (isEmpty()) Entry->addOperand(MDNode::get(Ctx, MDVals)); @@ -38,3 +45,163 @@ } bool ValidatorVersionMD::isEmpty() { return Entry->getNumOperands() == 0; } + +namespace { +constexpr StringLiteral DXILEntryKey = "hlsl.shader"; + +struct EntryProps { + Triple::EnvironmentType ShaderKind; + union { + // Compute shader. + struct { + unsigned NumThreads[3]; + } CS; + } ShaderProps; + EntryProps(Function &F) { + Attribute EntryAttr = F.getFnAttribute(DXILEntryKey); + StringRef EntryProfile = EntryAttr.getValueAsString(); + Triple T("", "", "", EntryProfile); + ShaderKind = T.getEnvironment(); + if (ShaderKind == Triple::EnvironmentType::Compute) { + constexpr StringLiteral NumThreadsKey = "hlsl.numthreads"; + auto NumThreadsStr = F.getFnAttribute(NumThreadsKey).getValueAsString(); + SmallVector NumThreads; + NumThreadsStr.split(NumThreads, ','); + assert(NumThreads.size() == 3 && "invalid numthreads"); + ShaderProps.CS.NumThreads[0] = std::stoi(NumThreads[0].str()); + ShaderProps.CS.NumThreads[1] = std::stoi(NumThreads[1].str()); + ShaderProps.CS.NumThreads[2] = std::stoi(NumThreads[2].str()); + } + } + MDTuple *emitDXILEntryProps(uint64_t RawShaderFlag, LLVMContext &Ctx) { + std::vector MDVals; + + if (RawShaderFlag != 0) + appendShaderFlags(MDVals, RawShaderFlag, Ctx); + + if (ShaderKind == Triple::EnvironmentType::Compute) + appendNumThreads(MDVals, Ctx); + // FIXME: support more props. + // See https://github.com/llvm/llvm-project/issues/57948. + return MDNode::get(Ctx, MDVals); + } + +private: + void appendNumThreads(std::vector &MDVals, LLVMContext &Ctx) { + constexpr unsigned DXILNumThreadsTag = 4; + MDVals.emplace_back(uint32ToConstMD(DXILNumThreadsTag, Ctx)); + + std::vector NumThreadVals; + NumThreadVals.emplace_back( + uint32ToConstMD(ShaderProps.CS.NumThreads[0], Ctx)); + NumThreadVals.emplace_back( + uint32ToConstMD(ShaderProps.CS.NumThreads[1], Ctx)); + NumThreadVals.emplace_back( + uint32ToConstMD(ShaderProps.CS.NumThreads[2], Ctx)); + MDVals.emplace_back(MDNode::get(Ctx, NumThreadVals)); + } + void appendShaderFlags(std::vector &MDVals, + uint64_t RawShaderFlag, LLVMContext &Ctx) { + constexpr unsigned DxilShaderFlagsTag = 0; + MDVals.emplace_back(uint32ToConstMD(DxilShaderFlagsTag, Ctx)); + MDVals.emplace_back(uint64ToConstMD(RawShaderFlag, Ctx)); + } +}; + +class EntryMD { + Function &F; + LLVMContext &Ctx; + EntryProps Props; + +public: + EntryMD(Function &F) : F(F), Ctx(F.getContext()), Props(F) {} + MDTuple *emitEntryTuple(MDTuple *Resources, uint64_t RawShaderFlag) { + // FIXME: add signature for profile other than CS. + // See https://github.com/llvm/llvm-project/issues/57928. + MDTuple *Signatures = nullptr; + return emitDxilEntryPointTuple(&F, F.getName().str(), Signatures, Resources, + Props.emitDXILEntryProps(RawShaderFlag, Ctx), + Ctx); + } + + // Library will have empty entry metadata which only store the resource table + // metadata. + static MDTuple *emitEmptyEntryForLib(MDTuple *Resources, LLVMContext &Ctx) { + return emitDxilEntryPointTuple(nullptr, "", nullptr, Resources, nullptr, + Ctx); + } + +private: + static MDTuple *emitDxilEntryPointTuple(Function *Fn, const std::string &Name, + MDTuple *Signatures, + MDTuple *Resources, + MDTuple *Properties, + LLVMContext &Ctx) { + enum EntryMDNode { + EntryMDFn = 0, + EntryMDName, + EntryMDSignature, + EntryMDResources, + EntryMDProps, + EntryMDSize + }; + Metadata *MDVals[EntryMDSize]; + MDVals[EntryMDFn] = Fn ? ValueAsMetadata::get(Fn) : nullptr; + MDVals[EntryMDName] = MDString::get(Ctx, Name.c_str()); + MDVals[EntryMDSignature] = Signatures; + MDVals[EntryMDResources] = Resources; + MDVals[EntryMDProps] = Properties; + return MDNode::get(Ctx, MDVals); + } +}; +} // namespace + +void dxil::createEntryMD(Module &M) { + SmallVector EntryList; + for (auto &F : M.functions()) { + if (!F.hasFnAttribute(DXILEntryKey)) + continue; + EntryList.emplace_back(&F); + } + + auto &Ctx = M.getContext(); + // FIXME: generate metadata for resource. + // See https://github.com/llvm/llvm-project/issues/57926. + MDTuple *MDResources = nullptr; + + // FIXME: build shader flags. + // See https://github.com/llvm/llvm-project/issues/57925 + uint64_t ShaderFlags = 0; + + std::vector Entries; + Triple T = Triple(M.getTargetTriple()); + switch (T.getEnvironment()) { + default: + llvm_unreachable("invalid profile"); + break; + case Triple::EnvironmentType::Library: { + // Add empty entry to put resource metadata. + MDTuple *EmptyEntry = EntryMD::emitEmptyEntryForLib(MDResources, Ctx); + Entries.emplace_back(EmptyEntry); + + for (Function *Entry : EntryList) { + EntryMD MD(*Entry); + Entries.emplace_back(MD.emitEntryTuple(nullptr, ShaderFlags)); + } + } break; + // FIXME: support more shader profiles. + // See https://github.com/llvm/llvm-project/issues/57927. + case Triple::EnvironmentType::Compute: { + assert(EntryList.size() == 1 && + "non-lib profiles should only have one entry"); + EntryMD MD(*EntryList.front()); + Entries.emplace_back(MD.emitEntryTuple(MDResources, ShaderFlags)); + } break; + } + + constexpr StringLiteral DXILEntryPointsMDName = "dx.entryPoints"; + NamedMDNode *EntryPointsNamedMD = + M.getOrInsertNamedMetadata(DXILEntryPointsMDName); + for (auto *Entry : Entries) + EntryPointsNamedMD->addOperand(Entry); +} diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -37,6 +37,8 @@ dxil::ValidatorVersionMD ValVerMD(M); if (ValVerMD.isEmpty()) ValVerMD.update(VersionTuple(1, 0)); + + dxil::createEntryMD(M); return false; } diff --git a/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll b/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll --- a/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll +++ b/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=asm %s -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" define i64 @test(ptr %p) { store i32 0, ptr %p diff --git a/llvm/test/CodeGen/DirectX/empty_cs_entry.ll b/llvm/test/CodeGen/DirectX/empty_cs_entry.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/empty_cs_entry.ll @@ -0,0 +1,17 @@ +; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-unknown-shadermodel6.7-compute" + +;CHECK:!dx.entryPoints = !{![[entry:[0-9]+]]} + +;CHECK:![[entry]] = !{ptr @entry, !"entry", null, null, ![[extra:[0-9]+]]} +;CHECK:![[extra]] = !{i32 4, ![[numthreads:[0-9]+]]} +;CHECK:![[numthreads]] = !{i32 1, i32 2, i32 1} + +; Function Attrs: noinline nounwind +define void @entry() #0 { +entry: + ret void +} + +attributes #0 = { noinline nounwind "hlsl.numthreads"="1,2,1" "hlsl.shader"="compute" } diff --git a/llvm/test/CodeGen/DirectX/fneg-conversion.ll b/llvm/test/CodeGen/DirectX/fneg-conversion.ll --- a/llvm/test/CodeGen/DirectX/fneg-conversion.ll +++ b/llvm/test/CodeGen/DirectX/fneg-conversion.ll @@ -1,5 +1,5 @@ ; RUN: llc %s --filetype=asm -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" define float @negateF(float %0) { ; CHECK: %2 = fsub float -0.000000e+00, %0 diff --git a/llvm/test/CodeGen/DirectX/lib_entry.ll b/llvm/test/CodeGen/DirectX/lib_entry.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/lib_entry.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-unknown-shadermodel6.7-library" + +;CHECK:!dx.entryPoints = !{![[empty_entry:[0-9]+]], ![[entry:[0-9]+]]} + +; Make sure generate empty entry for lib profile. +;CHECK![[empty_entry]] = !{null, !"", null, null, null} + +;CHECK:![[entry]] = !{ptr @entry, !"entry", null, null, ![[extra:[0-9]+]]} +;CHECK:![[extra]] = !{i32 4, ![[numthreads:[0-9]+]]} +;CHECK:![[numthreads]] = !{i32 1, i32 2, i32 1} + +; Function Attrs: noinline nounwind +define void @entry() #0 { +entry: + ret void +} + +attributes #0 = { noinline nounwind "hlsl.numthreads"="1,2,1" "hlsl.shader"="compute" } diff --git a/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll b/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll --- a/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll +++ b/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=asm %s -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" define i64 @test(ptr %p) { %v = load i64, ptr %p diff --git a/llvm/test/CodeGen/DirectX/strip-fn-attrs.ll b/llvm/test/CodeGen/DirectX/strip-fn-attrs.ll --- a/llvm/test/CodeGen/DirectX/strip-fn-attrs.ll +++ b/llvm/test/CodeGen/DirectX/strip-fn-attrs.ll @@ -1,5 +1,5 @@ ; RUN: llc %s --filetype=asm -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" ; CHECK: Function Attrs: nounwind readnone ; Function Attrs: norecurse nounwind readnone willreturn diff --git a/llvm/test/tools/dxil-dis/BasicIR.ll b/llvm/test/tools/dxil-dis/BasicIR.ll --- a/llvm/test/tools/dxil-dis/BasicIR.ll +++ b/llvm/test/tools/dxil-dis/BasicIR.ll @@ -6,7 +6,7 @@ ; CHECK: ret i32 %Q ; CHECK: } -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" define i32 @foo(i32 %X, i32 %Y) { %Z = sub i32 %X, %Y diff --git a/llvm/test/tools/dxil-dis/attribute-filter.ll b/llvm/test/tools/dxil-dis/attribute-filter.ll --- a/llvm/test/tools/dxil-dis/attribute-filter.ll +++ b/llvm/test/tools/dxil-dis/attribute-filter.ll @@ -1,7 +1,7 @@ ; RUN: llc %s --filetype=obj -o - | dxil-dis -o - | FileCheck %s -; CHECK: target triple = "dxil-unknown-unknown" -target triple = "dxil-unknown-unknown" +; CHECK: target triple = "dxil-unknown-shadermodel6.7-library" +target triple = "dxil-unknown-shadermodel6.7-library" ; CHECK: Function Attrs: nounwind readnone ; Function Attrs: norecurse nounwind readnone willreturn diff --git a/llvm/test/tools/dxil-dis/debug-info.ll b/llvm/test/tools/dxil-dis/debug-info.ll --- a/llvm/test/tools/dxil-dis/debug-info.ll +++ b/llvm/test/tools/dxil-dis/debug-info.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" ; CHECK: define float @fma(float, float, float) unnamed_addr #0 !dbg [[Fn:[!][0-9]+]] diff --git a/llvm/test/tools/dxil-dis/di-compile-unit.ll b/llvm/test/tools/dxil-dis/di-compile-unit.ll --- a/llvm/test/tools/dxil-dis/di-compile-unit.ll +++ b/llvm/test/tools/dxil-dis/di-compile-unit.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} diff --git a/llvm/test/tools/dxil-dis/di-subprogram.ll b/llvm/test/tools/dxil-dis/di-subprogram.ll --- a/llvm/test/tools/dxil-dis/di-subprogram.ll +++ b/llvm/test/tools/dxil-dis/di-subprogram.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} diff --git a/llvm/test/tools/dxil-dis/di-subrotine.ll b/llvm/test/tools/dxil-dis/di-subrotine.ll --- a/llvm/test/tools/dxil-dis/di-subrotine.ll +++ b/llvm/test/tools/dxil-dis/di-subrotine.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" !llvm.used = !{!0} diff --git a/llvm/test/tools/dxil-dis/metadata.ll b/llvm/test/tools/dxil-dis/metadata.ll --- a/llvm/test/tools/dxil-dis/metadata.ll +++ b/llvm/test/tools/dxil-dis/metadata.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" !llvm.foo = !{!0} !llvm.bar = !{!1} diff --git a/llvm/test/tools/dxil-dis/opaque-gep.ll b/llvm/test/tools/dxil-dis/opaque-gep.ll --- a/llvm/test/tools/dxil-dis/opaque-gep.ll +++ b/llvm/test/tools/dxil-dis/opaque-gep.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" define i32 @fn(ptr %0) { %2 = getelementptr i32, ptr %0, i32 4 diff --git a/llvm/test/tools/dxil-dis/opaque-pointers.ll b/llvm/test/tools/dxil-dis/opaque-pointers.ll --- a/llvm/test/tools/dxil-dis/opaque-pointers.ll +++ b/llvm/test/tools/dxil-dis/opaque-pointers.ll @@ -1,5 +1,5 @@ ; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-unknown" +target triple = "dxil-unknown-shadermodel6.7-library" define i64 @test(ptr %p) { store i32 0, ptr %p diff --git a/llvm/test/tools/dxil-dis/opaque-value_as_metadata.ll b/llvm/test/tools/dxil-dis/opaque-value_as_metadata.ll --- a/llvm/test/tools/dxil-dis/opaque-value_as_metadata.ll +++ b/llvm/test/tools/dxil-dis/opaque-value_as_metadata.ll @@ -1,6 +1,6 @@ ; RUN: llc --filetype=obj %s -o - 2>&1 | dxil-dis -o - | FileCheck %s target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" -target triple = "dxil-ms-dx" +target triple = "dxil-unknown-shadermodel6.7-library" %"$Globals" = type { float }