From e6bb6d906a75745fdd6fac861c6d073d113bd9b4 Mon Sep 17 00:00:00 2001 From: Karthik Senthil Date: Thu, 2 Apr 2026 10:56:55 -0700 Subject: [PATCH] [NVPTX][AsmPrinter] Demonstrate usage of NVPTXTargetAsmStreamer in NVPTXAsmPrinter. (#188539) Currently NVPTXAsmPrinter uses intermediate strings to generate ASM and emit directly to output streamer as raw text. This PR demonstrates how the printer can be updated to use NVPTXTargetAsmStreamer instead, thereby getting rid of the intermediate strings. This is shown only for the PTX header and module level directives. --- .../NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp | 4 +- .../MCTargetDesc/NVPTXTargetStreamer.cpp | 41 +++++++++++++-- .../NVPTX/MCTargetDesc/NVPTXTargetStreamer.h | 27 +++++++++- llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 51 +++++++++---------- llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h | 5 +- .../asm-printer-ptx-module-directives.ll | 14 +++++ 6 files changed, 106 insertions(+), 36 deletions(-) create mode 100644 llvm/test/CodeGen/NVPTX/asm-printer-ptx-module-directives.ll diff --git a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp index cb7132b5f304..5933f74fcb25 100644 --- a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp +++ b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp @@ -62,9 +62,9 @@ static MCInstPrinter *createNVPTXMCInstPrinter(const Triple &T, } static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S, - formatted_raw_ostream &, + formatted_raw_ostream &OS, MCInstPrinter *) { - return new NVPTXAsmTargetStreamer(S); + return new NVPTXAsmTargetStreamer(S, OS); } static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) { diff --git a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp index 329e3b564c34..46e6b6618016 100644 --- a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp +++ b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; @@ -27,10 +28,6 @@ using namespace llvm; NVPTXTargetStreamer::NVPTXTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} NVPTXTargetStreamer::~NVPTXTargetStreamer() = default; -NVPTXAsmTargetStreamer::NVPTXAsmTargetStreamer(MCStreamer &S) - : NVPTXTargetStreamer(S) {} -NVPTXAsmTargetStreamer::~NVPTXAsmTargetStreamer() = default; - void NVPTXTargetStreamer::outputDwarfFileDirectives() { for (const std::string &S : DwarfFiles) getStreamer().emitRawText(S); @@ -149,3 +146,39 @@ void NVPTXTargetStreamer::emitValue(const MCExpr *Value) { // Otherwise, print the Value normally. MCTargetStreamer::emitValue(Value); } + +// +// NVPTXAsmTargetStreamer Implementation +// + +NVPTXAsmTargetStreamer::NVPTXAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS) + : NVPTXTargetStreamer(S), OS(OS) {} +NVPTXAsmTargetStreamer::~NVPTXAsmTargetStreamer() = default; + +void NVPTXAsmTargetStreamer::emitBanner() { + OS << "//\n" + "// Generated by LLVM NVPTX Back-End\n" + "//\n" + "\n"; +} + +void NVPTXAsmTargetStreamer::emitVersionDirective(unsigned PTXVersion) { + OS << ".version " << (PTXVersion / 10) << "." << (PTXVersion % 10) << "\n"; +} + +void NVPTXAsmTargetStreamer::emitTargetDirective(StringRef Target, + bool TexModeIndependent, + bool HasDebug) { + OS << ".target " << Target; + if (TexModeIndependent) + OS << ", texmode_independent"; + if (HasDebug) + OS << ", debug"; + OS << "\n"; +} + +void NVPTXAsmTargetStreamer::emitAddressSizeDirective(unsigned AddrSize) { + OS << ".address_size " << AddrSize << "\n" + << "\n"; +} diff --git a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h index 36db76065e0c..35ba0016efea 100644 --- a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h +++ b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h @@ -13,6 +13,7 @@ namespace llvm { class MCSection; +class formatted_raw_ostream; /// Implments NVPTX-specific streamer. class NVPTXTargetStreamer : public MCTargetStreamer { @@ -24,6 +25,19 @@ public: NVPTXTargetStreamer(MCStreamer &S); ~NVPTXTargetStreamer() override; + /// Emit the banner which specifies details of PTX generator. + virtual void emitBanner() {} + + /// Emit the PTX ISA version number. + virtual void emitVersionDirective(unsigned PTXVersion) {} + + /// Emit architecture and platform target. + virtual void emitTargetDirective(StringRef Target, bool TexModeIndependent, + bool HasDebug) {} + + /// Emit address size used for this PTX module. + virtual void emitAddressSizeDirective(unsigned AddrSize) {} + /// Outputs the list of the DWARF '.file' directives to the streamer. void outputDwarfFileDirectives(); /// Close last section. @@ -53,9 +67,20 @@ public: }; class NVPTXAsmTargetStreamer : public NVPTXTargetStreamer { + formatted_raw_ostream &OS; + public: - NVPTXAsmTargetStreamer(MCStreamer &S); + NVPTXAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS); ~NVPTXAsmTargetStreamer() override; + + void emitBanner() override; + + void emitVersionDirective(unsigned PTXVersion) override; + + void emitTargetDirective(StringRef Target, bool TexModeIndependent, + bool HasDebug) override; + + void emitAddressSizeDirective(unsigned AddrSize) override; }; } // end namespace llvm diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp index 9e7a58498040..573671de03ab 100644 --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -685,12 +685,9 @@ void NVPTXAsmPrinter::emitStartOfAsmFile(Module &M) { // so the default TargetMachine will have all of the options. const NVPTXTargetMachine &NTM = static_cast(TM); const NVPTXSubtarget *STI = NTM.getSubtargetImpl(); - SmallString<128> Str1; - raw_svector_ostream OS1(Str1); // Emit header before any dwarf directives are emitted below. - emitHeader(M, OS1, *STI); - OutStreamer->emitRawText(OS1.str()); + emitHeader(M, *STI); } /// Create NVPTX-specific DwarfDebug handler. @@ -758,22 +755,11 @@ void NVPTXAsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) { OutStreamer->emitRawText(OS.str()); } -void NVPTXAsmPrinter::emitHeader(Module &M, raw_ostream &O, - const NVPTXSubtarget &STI) { - const unsigned PTXVersion = STI.getPTXVersion(); +NVPTXTargetStreamer *NVPTXAsmPrinter::getTargetStreamer() const { + return static_cast(OutStreamer->getTargetStreamer()); +} - O << "//\n" - "// Generated by LLVM NVPTX Back-End\n" - "//\n" - "\n" - << ".version " << (PTXVersion / 10) << "." << (PTXVersion % 10) << "\n" - << ".target " << STI.getTargetName(); - - const NVPTXTargetMachine &NTM = static_cast(TM); - if (NTM.getDrvInterface() == NVPTX::NVCL) - O << ", texmode_independent"; - - bool HasFullDebugInfo = false; +static bool hasFullDebugInfo(Module &M) { for (DICompileUnit *CU : M.debug_compile_units()) { switch(CU->getEmissionKind()) { case DICompileUnit::NoDebug: @@ -781,18 +767,27 @@ void NVPTXAsmPrinter::emitHeader(Module &M, raw_ostream &O, break; case DICompileUnit::LineTablesOnly: case DICompileUnit::FullDebug: - HasFullDebugInfo = true; - break; + return true; } - if (HasFullDebugInfo) - break; } - if (HasFullDebugInfo) - O << ", debug"; - O << "\n" - << ".address_size " << (NTM.is64Bit() ? "64" : "32") << "\n" - << "\n"; + return false; +} + +void NVPTXAsmPrinter::emitHeader(Module &M, const NVPTXSubtarget &STI) { + auto *TS = getTargetStreamer(); + + TS->emitBanner(); + + const unsigned PTXVersion = STI.getPTXVersion(); + TS->emitVersionDirective(PTXVersion); + + const NVPTXTargetMachine &NTM = static_cast(TM); + bool TexModeIndependent = NTM.getDrvInterface() == NVPTX::NVCL; + + TS->emitTargetDirective(STI.getTargetName(), TexModeIndependent, + hasFullDebugInfo(M)); + TS->emitAddressSizeDirective(M.getDataLayout().getPointerSizeInBits()); } bool NVPTXAsmPrinter::doFinalization(Module &M) { diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h index ebdfac93c04f..6085a9607766 100644 --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h @@ -58,6 +58,7 @@ namespace llvm { class MCOperand; +class NVPTXTargetStreamer; class LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter { @@ -153,6 +154,8 @@ public: private: const Function *F; + NVPTXTargetStreamer *getTargetStreamer() const; + void emitStartOfAsmFile(Module &M) override; void emitBasicBlockStart(const MachineBasicBlock &MBB) override; void emitFunctionEntryLabel() override; @@ -172,7 +175,7 @@ private: bool processDemoted, const NVPTXSubtarget &STI); void emitGlobals(const Module &M); void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override; - void emitHeader(Module &M, raw_ostream &O, const NVPTXSubtarget &STI); + void emitHeader(Module &M, const NVPTXSubtarget &STI); void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const; void emitVirtualRegister(unsigned int vr, raw_ostream &); void emitFunctionParamList(const Function *, raw_ostream &O); diff --git a/llvm/test/CodeGen/NVPTX/asm-printer-ptx-module-directives.ll b/llvm/test/CodeGen/NVPTX/asm-printer-ptx-module-directives.ll new file mode 100644 index 000000000000..cc4323a92176 --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/asm-printer-ptx-module-directives.ll @@ -0,0 +1,14 @@ +; Test to verify functionality of NVPTXAsmPrinter for PTX module directives and header. + +; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_100 -mattr=+ptx87 | FileCheck %s +; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64 -mcpu=sm_100 -mattr=+ptx87 | %ptxas-verify %} + +; CHECK: // +; CHECK-NEXT: // Generated by LLVM NVPTX Back-End +; CHECK-NEXT: // +; CHECK-EMPTY: +; CHECK-NEXT: .version 8.7 +; CHECK-NEXT: .target sm_100 +; CHECK-NEXT: .address_size 64 + +target triple = "nvptx64-nvidia-cuda"