[llvm] 6e05c8d - [DX] Create globals for DXContainer parts

Chris Bieneman via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 18 09:48:17 PDT 2022


Author: Chris Bieneman
Date: 2022-10-18T11:48:08-05:00
New Revision: 6e05c8dfc86cb9d1161784f4bfaf4f89709249d5

URL: https://github.com/llvm/llvm-project/commit/6e05c8dfc86cb9d1161784f4bfaf4f89709249d5
DIFF: https://github.com/llvm/llvm-project/commit/6e05c8dfc86cb9d1161784f4bfaf4f89709249d5.diff

LOG: [DX] Create globals for DXContainer parts

DXContainer files have a handful of sections that need to be written.
This adds a pass to write the section data into IR globals, and writes
the shader flag data into a global.

The test cases here verify that the shader flags are correctly written
from the IR into the global and emitted to the DXContainer.

This change also fixes a bug in the MCDXContainerWriter, where the size
of the dxbc::ProgramHeader was not being included in the part offset
calcuations. This is verified to be working by the new testcases where
obj2yaml can properly dump part data for parts after the DXIL part.

Resolves issue #57742 (https://github.com/llvm/llvm-project/issues/57742)

Reviewed By: python3kgae

Differential Revision: https://reviews.llvm.org/D135793

Added: 
    llvm/lib/Target/DirectX/DXContainerGlobals.cpp

Modified: 
    llvm/lib/MC/MCDXContainerWriter.cpp
    llvm/lib/Target/DirectX/CMakeLists.txt
    llvm/lib/Target/DirectX/DXILShaderFlags.cpp
    llvm/lib/Target/DirectX/DXILShaderFlags.h
    llvm/lib/Target/DirectX/DirectX.h
    llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
    llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
    llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll
    llvm/test/CodeGen/DirectX/embed-dxil.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/MC/MCDXContainerWriter.cpp b/llvm/lib/MC/MCDXContainerWriter.cpp
index f5dad702d6f69..ddccc100967d4 100644
--- a/llvm/lib/MC/MCDXContainerWriter.cpp
+++ b/llvm/lib/MC/MCDXContainerWriter.cpp
@@ -65,6 +65,10 @@ uint64_t DXContainerObjectWriter::writeObject(MCAssembler &Asm,
     PartOffsets.push_back(PartOffset);
     PartOffset += sizeof(dxbc::PartHeader) + SectionSize;
     PartOffset = alignTo(PartOffset, Align(4ul));
+    // The DXIL part also writes a program header, so we need to include its
+    // size when computing the offset for a part after the DXIL part.
+    if (Sec.getName() == "DXIL")
+      PartOffset += sizeof(dxbc::ProgramHeader);
   }
   assert(PartOffset < std::numeric_limits<uint32_t>::max() &&
          "Part data too large for DXContainer");

diff  --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt
index 034b85d2fc7b1..9dc4e5b41706b 100644
--- a/llvm/lib/Target/DirectX/CMakeLists.txt
+++ b/llvm/lib/Target/DirectX/CMakeLists.txt
@@ -17,6 +17,7 @@ add_llvm_target(DirectXCodeGen
   DirectXRegisterInfo.cpp
   DirectXSubtarget.cpp
   DirectXTargetMachine.cpp
+  DXContainerGlobals.cpp
   DXILMetadata.cpp
   DXILOpBuilder.cpp
   DXILOpLowering.cpp

diff  --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
new file mode 100644
index 0000000000000..1a20a158e674a
--- /dev/null
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -0,0 +1,71 @@
+//===- DXContainerGlobals.cpp - DXContainer global generator pass ---------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// DXContainerGlobalsPass implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DXILShaderFlags.h"
+#include "DirectX.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+
+using namespace llvm;
+using namespace llvm::dxil;
+
+namespace {
+class DXContainerGlobals : public llvm::ModulePass {
+
+public:
+  static char ID; // Pass identification, replacement for typeid
+  DXContainerGlobals() : ModulePass(ID) {
+    initializeDXContainerGlobalsPass(*PassRegistry::getPassRegistry());
+  }
+
+  StringRef getPassName() const override {
+    return "DXContainer Global Emitter";
+  }
+
+  bool runOnModule(Module &M) override;
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+    AU.addRequired<ShaderFlagsAnalysisWrapper>();
+  }
+};
+
+} // namespace
+
+bool DXContainerGlobals::runOnModule(Module &M) {
+  const uint64_t Flags =
+      (uint64_t)(getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags());
+
+  Constant *FlagsConstant = ConstantInt::get(M.getContext(), APInt(64, Flags));
+  auto *GV = new llvm::GlobalVariable(M, FlagsConstant->getType(), true,
+                                      GlobalValue::PrivateLinkage,
+                                      FlagsConstant, "dx.sfi0");
+  GV->setSection("SFI0");
+  GV->setAlignment(Align(4));
+  appendToCompilerUsed(M, {GV});
+  return true;
+}
+
+char DXContainerGlobals::ID = 0;
+INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals",
+                      "DXContainer Global Emitter", false, true)
+INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper)
+INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals",
+                    "DXContainer Global Emitter", false, true)
+
+ModulePass *llvm::createDXContainerGlobalsPass() {
+  return new DXContainerGlobals();
+}

diff  --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 6af38477da9a5..bbb5643566021 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -71,3 +71,8 @@ PreservedAnalyses ShaderFlagsAnalysisPrinter::run(Module &M,
   Flags.print(OS);
   return PreservedAnalyses::all();
 }
+
+char ShaderFlagsAnalysisWrapper::ID = 0;
+
+INITIALIZE_PASS(ShaderFlagsAnalysisWrapper, "dx-shader-flag-analysis",
+                "DXIL Shader Flag Analysis", true, true)

diff  --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h
index e877594fde57f..216d8a3f1f9e3 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.h
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.h
@@ -73,6 +73,26 @@ class ShaderFlagsAnalysisPrinter
   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
 };
 
+/// Wrapper pass for the legacy pass manager.
+///
+/// This is required because the passes that will depend on this are codegen
+/// passes which run through the legacy pass manager.
+class ShaderFlagsAnalysisWrapper : public ModulePass {
+  ComputedShaderFlags Flags;
+
+public:
+  static char ID;
+
+  ShaderFlagsAnalysisWrapper() : ModulePass(ID) {}
+
+  const ComputedShaderFlags &getShaderFlags() { return Flags; }
+
+  bool runOnModule(Module &M) override {
+    Flags = ComputedShaderFlags::computeFlags(M);
+    return false;
+  }
+};
+
 } // namespace dxil
 } // namespace llvm
 

diff  --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h
index c1bd1f467723f..eaecc3ac280c4 100644
--- a/llvm/lib/Target/DirectX/DirectX.h
+++ b/llvm/lib/Target/DirectX/DirectX.h
@@ -49,6 +49,14 @@ ModulePass *createDXILPrettyPrinterPass(raw_ostream &OS);
 /// Initializer for DXILPrettyPrinter.
 void initializeDXILPrettyPrinterPass(PassRegistry &);
 
+/// Initializer for dxil::ShaderFlagsAnalysisWrapper pass.
+void initializeShaderFlagsAnalysisWrapperPass(PassRegistry &);
+
+/// Initializer for DXContainerGlobals pass.
+void initializeDXContainerGlobalsPass(PassRegistry &);
+
+/// Pass for generating DXContainer part globals.
+ModulePass *createDXContainerGlobalsPass();
 } // namespace llvm
 
 #endif // LLVM_LIB_TARGET_DIRECTX_DIRECTX_H

diff  --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
index 8223639330a2c..7031b66c9668f 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
@@ -43,6 +43,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
   initializeDXILOpLoweringLegacyPass(*PR);
   initializeDXILTranslateMetadataPass(*PR);
   initializeDXILResourceWrapperPass(*PR);
+  initializeShaderFlagsAnalysisWrapperPass(*PR);
 }
 
 class DXILTargetObjectFile : public TargetLoweringObjectFile {
@@ -126,6 +127,9 @@ bool DirectXTargetMachine::addPassesToEmitFile(
 
   if (TargetPassConfig::willCompleteCodeGenPipeline()) {
     PM.add(createDXILEmbedderPass());
+    // We embed the other DXContainer globals after embedding DXIL so that the
+    // globals don't pollute the DXIL.
+    PM.add(createDXContainerGlobalsPass());
   }
   switch (FileType) {
   case CGFT_AssemblyFile:

diff  --git a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
index 4eba4f28abffe..26487ca2a7115 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
 
 target triple = "dxil-pc-shadermodel6.7-library"
 
@@ -11,3 +12,14 @@ define double @div(double %a, double %b) {
   %res = fdiv double %a, %b
   ret double %res
 }
+
+
+; DXC: - Name:            SFI0
+; DXC-NEXT:     Size:            16
+; DXC-NEXT:     Flags:
+; DXC-NEXT:       Doubles:         true
+; DXC-NOT:   {{[A-Za-z]+: +true}}
+; DXC:            DX11_1_DoubleExtensions:         true
+; DXC-NOT:   {{[A-Za-z]+: +true}}
+; DXC:       NextUnusedBit:   false
+; DXC: ...

diff  --git a/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll
index 01ba14bec238b..95320dd495d49 100644
--- a/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll
@@ -1,4 +1,5 @@
 ; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
 
 target triple = "dxil-pc-shadermodel6.7-library"
 
@@ -10,3 +11,11 @@ define double @add(double %a, double %b) {
   %sum = fadd double %a, %b
   ret double %sum
 }
+
+; DXC: - Name:            SFI0
+; DXC-NEXT:     Size:            16
+; DXC-NEXT:     Flags:
+; DXC-NEXT:       Doubles:         true
+; DXC-NOT:   {{[A-Za-z]+: +true}}
+; DXC:       NextUnusedBit:   false
+; DXC: ...

diff  --git a/llvm/test/CodeGen/DirectX/embed-dxil.ll b/llvm/test/CodeGen/DirectX/embed-dxil.ll
index c84bd2cac2698..aa9c75a3ffe4e 100644
--- a/llvm/test/CodeGen/DirectX/embed-dxil.ll
+++ b/llvm/test/CodeGen/DirectX/embed-dxil.ll
@@ -9,7 +9,10 @@ define i32 @add(i32 %a, i32 %b) {
 }
 
 ; CHECK: @dx.dxil = private constant [[BC_TYPE:\[[0-9]+ x i8\]]] c"BC\C0\DE{{[^"]+}}", section "DXIL", align 4
-; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @dx.dxil], section "llvm.metadata"
+
+; The dxil global should be the first here because we generate it before the
+; other globals. If it isn't the first here, that's probably a bug.
+; CHECK: @llvm.compiler.used = appending global {{\[[0-9]+ x ptr\]}} [ptr @dx.dxil
 
 ; This is using regex matches on some sizes, offsets and fields. These are all
 ; going to change as the DirectX backend continues to evolve and implement more
@@ -41,3 +44,6 @@ define i32 @add(i32 %a, i32 %b) {
 ; DXC-NEXT:       DXILMinorVersion: [[#]]
 ; DXC-NEXT:       DXILSize:        [[#SIZE - 32]]
 ; DXC-NEXT:       DXIL:            [ 0x42, 0x43, 0xC0, 0xDE,
+; DXC:      - Name:            SFI0
+; DXC-NEXT:   Size:            16
+; DXC-NOT:    Flags:


        


More information about the llvm-commits mailing list