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,6 +15,7 @@ #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; @@ -38,3 +39,146 @@ } bool ValidatorVersionMD::isEmpty() { return Entry->getNumOperands() == 0; } + +namespace { +struct DxilFunctionProps { + Triple::EnvironmentType ShaderKind; + union { + // Compute shader. + struct { + unsigned NumThreads[3]; + } CS; + } ShaderProps; +}; +} // namespace + +static uint64_t collectShaderFlags(Module &M) { + uint64_t Flags = 0; + // FIXME: build shader flags. + // See https://github.com/llvm/llvm-project/issues/57925 + return Flags; +} + +static ConstantAsMetadata *uint32ToConstMD(unsigned V, LLVMContext &Ctx) { + return ConstantAsMetadata::get( + Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, V))); +} + +static ConstantAsMetadata *uint64ToConstMD(uint64_t V, LLVMContext &Ctx) { + return ConstantAsMetadata::get( + Constant::getIntegerValue(IntegerType::get(Ctx, 64), APInt(64, V))); +} + +static MDTuple *emitDXILEntryProps(DxilFunctionProps &Props, LLVMContext &Ctx, + uint64_t RawShaderFlag) { + std::vector MDVals; + + if (RawShaderFlag != 0) { + constexpr unsigned DxilShaderFlagsTag = 0; + MDVals.emplace_back(uint32ToConstMD(DxilShaderFlagsTag, Ctx)); + MDVals.emplace_back(uint64ToConstMD(RawShaderFlag, Ctx)); + } + + if (Props.ShaderKind == Triple::EnvironmentType::Compute) { + auto &CS = Props.ShaderProps.CS; + constexpr unsigned DXILNumThreadsTag = 4; + MDVals.emplace_back(uint32ToConstMD(DXILNumThreadsTag, Ctx)); + + std::vector NumThreadVals; + NumThreadVals.emplace_back(uint32ToConstMD(CS.NumThreads[0], Ctx)); + NumThreadVals.emplace_back(uint32ToConstMD(CS.NumThreads[1], Ctx)); + NumThreadVals.emplace_back(uint32ToConstMD(CS.NumThreads[2], Ctx)); + MDVals.emplace_back(MDNode::get(Ctx, NumThreadVals)); + } + + return MDNode::get(Ctx, MDVals); +} + +static MDTuple *emitDxilEntryPointTuple(Function *Fn, const std::string &Name, + MDTuple *Signatures, MDTuple *Resources, + MDTuple *Properties, LLVMContext &Ctx) { + Metadata *MDVals[5]; + MDVals[0] = Fn ? ValueAsMetadata::get(Fn) : nullptr; + MDVals[1] = MDString::get(Ctx, Name.c_str()); + MDVals[2] = Signatures; + MDVals[3] = Resources; + MDVals[4] = Properties; + return MDNode::get(Ctx, MDVals); +} + +void dxil::createEntryMD(Module &M) { + SmallVector> EntryList; + constexpr StringLiteral DXILEntryKey = "hlsl.shader"; + for (auto &F : M.functions()) { + if (!F.hasFnAttribute(DXILEntryKey)) + continue; + Attribute EntryAttr = F.getFnAttribute(DXILEntryKey); + StringRef EntryProfile = EntryAttr.getValueAsString(); + Triple T("", "", "", EntryProfile); + DxilFunctionProps Props; + Props.ShaderKind = T.getEnvironment(); + if (Props.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"); + Props.ShaderProps.CS.NumThreads[0] = std::stoi(NumThreads[0].str()); + Props.ShaderProps.CS.NumThreads[1] = std::stoi(NumThreads[1].str()); + Props.ShaderProps.CS.NumThreads[2] = std::stoi(NumThreads[2].str()); + } + EntryList.emplace_back(std::make_pair(&F, Props)); + } + + auto &Ctx = M.getContext(); + // FIXME: generate metadata for resource. + // See https://github.com/llvm/llvm-project/issues/57926. + MDTuple *MDResources = nullptr; + + uint64_t ShaderFlags = collectShaderFlags(M); + 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 = + emitDxilEntryPointTuple(nullptr, "", nullptr, nullptr, nullptr, Ctx); + Entries.emplace_back(EmptyEntry); + } 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"); + break; + } + + for (auto &It : EntryList) { + Function *F = It.first; + DxilFunctionProps &Props = It.second; + MDTuple *MDProps = emitDXILEntryProps(Props, Ctx, ShaderFlags); + // FIXME: add signature for profile other than CS. + // See https://github.com/llvm/llvm-project/issues/57928. + MDTuple *Sig = nullptr; + + MDTuple *SubEntry = emitDxilEntryPointTuple(F, F->getName().str(), Sig, + nullptr, MDProps, Ctx); + + Entries.emplace_back(SubEntry); + } + + // Set resource for first entry. + constexpr unsigned DXILEntryPointResources = 3; + Entries.front()->replaceOperandWith(DXILEntryPointResources, MDResources); + + 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/lit.local.cfg b/llvm/test/tools/dxil-dis/lit.local.cfg --- a/llvm/test/tools/dxil-dis/lit.local.cfg +++ b/llvm/test/tools/dxil-dis/lit.local.cfg @@ -1,3 +1,2 @@ -if not config.dxil_tests: - config.unsupported = True + config.suffixes = ['.ll'] 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 }