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 @@ -11,7 +11,8 @@ //===----------------------------------------------------------------------===// #include "DXILMetadata.h" -#include "llvm/IR/IRBuilder.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/Support/VersionTuple.h" @@ -24,12 +25,12 @@ 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] = ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(Ctx), ValidatorVer.getMajor())); + MDVals[1] = ConstantAsMetadata::get(ConstantInt::get( + Type::getInt32Ty(Ctx), ValidatorVer.getMinor().value_or(0))); if (isEmpty()) Entry->addOperand(MDNode::get(Ctx, MDVals)); @@ -38,3 +39,161 @@ } bool ValidatorVersionMD::isEmpty() { return Entry->getNumOperands() == 0; } + +namespace { + +struct EntryProps { + Triple::EnvironmentType ShaderKind; + struct { + unsigned NumThreads[3]; + } CS; + EntryProps(Function &F) { + Attribute EntryAttr = F.getFnAttribute("hlsl.shader"); + 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"); + for (int I = 0; I < 3; ++I) { + APInt V; + if (NumThreads[I].getAsInteger(10, V)) + assert(0 && "invalid num thread"); + CS.NumThreads[I] = V.getLimitedValue(); + } + } + } + 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: + enum EntryPropsTag { DXILShaderFlagsTag = 0, DXILNumThreadsTag = 4 }; + void appendNumThreads(std::vector &MDVals, LLVMContext &Ctx) { + MDVals.emplace_back(ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(Ctx), DXILNumThreadsTag))); + + std::vector NumThreadVals; + for (int I = 0; I < 3; ++I) + NumThreadVals.emplace_back(ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(Ctx), CS.NumThreads[I]))); + MDVals.emplace_back(MDNode::get(Ctx, NumThreadVals)); + } + void appendShaderFlags(std::vector &MDVals, + uint64_t RawShaderFlag, LLVMContext &Ctx) { + MDVals.emplace_back(ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(Ctx), DXILShaderFlagsTag))); + MDVals.emplace_back(ConstantAsMetadata::get( + ConstantInt::get(Type::getInt64Ty(Ctx), RawShaderFlag))); + } +}; + +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) { + 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); + } +}; +} // namespace + +void dxil::createEntryMD(Module &M) { + SmallVector EntryList; + for (auto &F : M.functions()) { + if (!F.hasFnAttribute("hlsl.shader")) + 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()) { + 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; + case Triple::EnvironmentType::Amplification: + case Triple::EnvironmentType::Mesh: + case Triple::EnvironmentType::Vertex: + case Triple::EnvironmentType::Hull: + case Triple::EnvironmentType::Domain: + case Triple::EnvironmentType::Geometry: + case Triple::EnvironmentType::Pixel: + assert(0 && "unsupported profile"); + break; + default: + assert(0 && "invalid profile"); + break; + } + + NamedMDNode *EntryPointsNamedMD = + M.getOrInsertNamedMetadata("dx.entryPoints"); + 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 }