[llvm] addd073 - [AIX][PowerPC][PGO] Generate .ref for some PGO sections

Wael Yehia via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 5 04:04:46 PST 2022


Author: Wael Yehia
Date: 2022-02-05T06:34:20-05:00
New Revision: addd0733250af38da0ff5503d65250156a9c179a

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

LOG: [AIX][PowerPC][PGO] Generate .ref for some PGO sections

For PGO on AIX, when we switch to the linux-style PGO variable access
(via _start and _stop labels), we need the compiler to generate a .ref
assembly for each of the three csects:

 -   __llvm_prf_data[RW]
 -   __llvm_prf_names[RO]
 -   __llvm_prf_vnds[RW]

We insert the .ref inside the __llvm_prf_cnts[RW] csect so that if it's
live then the 3 csects are live.

For example, for a testcase with at least one function definition, when
compiled with -fprofile-generate we should generate:

        .csect __llvm_prf_cnts[RW],3
        .ref __llvm_prf_data[RW]   <<============ needs to be inserted
        .ref __llvm_prf_names[RO]  <<===========

the __llvm_prf_vnds is not always present, so we reference it only when
it's present.

Reviewed By: sfertile, daltenty

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

Added: 
    llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll

Modified: 
    llvm/include/llvm/MC/MCContext.h
    llvm/include/llvm/MC/MCStreamer.h
    llvm/include/llvm/MC/MCXCOFFStreamer.h
    llvm/lib/MC/MCAsmStreamer.cpp
    llvm/lib/MC/MCContext.cpp
    llvm/lib/MC/MCStreamer.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index d2307d6922780..96a4024ff8d8d 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -650,6 +650,9 @@ namespace llvm {
                                   unsigned Flags, const MCSymbolWasm *Group,
                                   unsigned UniqueID, const char *BeginSymName);
 
+    bool hasXCOFFSection(StringRef Section,
+                         XCOFF::CsectProperties CsectProp) const;
+
     MCSectionXCOFF *getXCOFFSection(
         StringRef Section, SectionKind K,
         Optional<XCOFF::CsectProperties> CsectProp = None,

diff  --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 3d6c512bfe73d..3be890cc6feaa 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -615,6 +615,12 @@ class MCStreamer {
   /// changed at the end of assembly.
   virtual void emitXCOFFRenameDirective(const MCSymbol *Name, StringRef Rename);
 
+  /// Emit a XCOFF .ref directive which creates R_REF type entry in the
+  /// relocation table for one or more symbols.
+  ///
+  /// \param Sym - The symbol on the .ref directive.
+  virtual void emitXCOFFRefDirective(StringRef Sym);
+
   /// Emit an ELF .size directive.
   ///
   /// This corresponds to an assembler statement such as:

diff  --git a/llvm/include/llvm/MC/MCXCOFFStreamer.h b/llvm/include/llvm/MC/MCXCOFFStreamer.h
index 5fc2efbe52849..3faa03fa69e91 100644
--- a/llvm/include/llvm/MC/MCXCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h
@@ -32,6 +32,10 @@ class MCXCOFFStreamer : public MCObjectStreamer {
   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
                                             MCSymbolAttr Linkage,
                                             MCSymbolAttr Visibility) override;
+  void emitXCOFFRefDirective(StringRef Name) override {
+    report_fatal_error("emitXCOFFRefDirective is not implemented yet on object"
+                       "generation path");
+  }
   void emitXCOFFRenameDirective(const MCSymbol *Name,
                                 StringRef Rename) override {
     report_fatal_error("emitXCOFFRenameDirective is not implemented yet on "

diff  --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 61ec941f50b82..3ca1813a90939 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -198,6 +198,8 @@ class MCAsmStreamer final : public MCStreamer {
   void emitXCOFFRenameDirective(const MCSymbol *Name,
                                 StringRef Rename) override;
 
+  void emitXCOFFRefDirective(StringRef Name) override;
+
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         unsigned ByteAlignment) override;
@@ -931,6 +933,11 @@ void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
   EmitEOL();
 }
 
+void MCAsmStreamer::emitXCOFFRefDirective(StringRef Name) {
+  OS << "\t.ref " << Name;
+  EmitEOL();
+}
+
 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
   assert(MAI->hasDotTypeDotSizeDirective());
   OS << "\t.size\t";

diff  --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index eafcee1e0607b..bbbbfe5731b5d 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -732,6 +732,12 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
   return Result;
 }
 
+bool MCContext::hasXCOFFSection(StringRef Section,
+                                XCOFF::CsectProperties CsectProp) const {
+  return XCOFFUniquingMap.count(
+             XCOFFSectionKey(Section.str(), CsectProp.MappingClass)) != 0;
+}
+
 MCSectionXCOFF *MCContext::getXCOFFSection(
     StringRef Section, SectionKind Kind,
     Optional<XCOFF::CsectProperties> CsectProp, bool MultiSymbolsAllowed,

diff  --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index a14f0de65a9d1..8608d7a90fecb 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -1180,6 +1180,10 @@ void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
                    "XCOFF targets");
 }
 
+void MCStreamer::emitXCOFFRefDirective(StringRef Name) {
+  llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets");
+}
+
 void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
 void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
                                         StringRef Name, bool KeepOriginalSym) {}

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 7809818069965..387fa027054a7 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -254,6 +254,8 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
 
   void emitFunctionBodyEnd() override;
 
+  void emitPGORefs();
+
   void emitEndOfAsmFile(Module &) override;
 
   void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
@@ -2475,12 +2477,39 @@ void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
       });
 }
 
+void PPCAIXAsmPrinter::emitPGORefs() {
+  if (OutContext.hasXCOFFSection(
+          "__llvm_prf_cnts",
+          XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
+    MCSection *CntsSection = OutContext.getXCOFFSection(
+        "__llvm_prf_cnts", SectionKind::getData(),
+        XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
+        /*MultiSymbolsAllowed*/ true);
+
+    OutStreamer->SwitchSection(CntsSection);
+    if (OutContext.hasXCOFFSection(
+            "__llvm_prf_data",
+            XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
+      OutStreamer->emitXCOFFRefDirective("__llvm_prf_data[RW]");
+    if (OutContext.hasXCOFFSection(
+            "__llvm_prf_names",
+            XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD)))
+      OutStreamer->emitXCOFFRefDirective("__llvm_prf_names[RO]");
+    if (OutContext.hasXCOFFSection(
+            "__llvm_prf_vnds",
+            XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
+      OutStreamer->emitXCOFFRefDirective("__llvm_prf_vnds[RW]");
+  }
+}
+
 void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
   // If there are no functions and there are no toc-data definitions in this
   // module, we will never need to reference the TOC base.
   if (M.empty() && TOCDataGlobalVars.empty())
     return;
 
+  emitPGORefs();
+
   // Switch to section to emit TOC base.
   OutStreamer->SwitchSection(getObjFileLowering().getTOCBaseSection());
 

diff  --git a/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll b/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll
new file mode 100644
index 0000000000000..92deedf4a0263
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll
@@ -0,0 +1,82 @@
+; RUN: rm -rf %t && split-file %s %t
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff -xcoff-traceback-table=false < %t/no-ref.ll | FileCheck %s --check-prefixes=NOREF
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff -xcoff-traceback-table=false < %t/no-vnds.ll | FileCheck %s --check-prefixes=NOVNDS
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff -xcoff-traceback-table=false < %t/with-vnds.ll | FileCheck %s --check-prefixes=WITHVNDS
+
+
+;--- no-ref.ll
+; The absence of a __llvm_prf_cnts section should stop generating the .refs.
+;
+target datalayout = "E-m:a-p:32:32-i64:64-n32"
+target triple = "powerpc-ibm-aix7.2.0.0"
+
+ at __profd_main = private global i64 zeroinitializer, section "__llvm_prf_data", align 8
+ at __llvm_prf_nm = private constant [6 x i8] c"\04\00main", section "__llvm_prf_names", align 1
+
+ at llvm.used = appending global [2 x i8*]
+  [i8* bitcast (i64* @__profd_main to i8*),
+   i8* getelementptr inbounds ([6 x i8], [6 x i8]* @__llvm_prf_nm, i32 0, i32 0)], section "llvm.metadata"
+
+define i32 @main() #0 {
+entry:
+  ret i32 1
+}
+
+; NOREF-NOT:  .ref __llvm_prf_data
+; NOREF-NOT:  .ref __llvm_prf_names
+; NOREF-NOT:  .ref __llvm_prf_vnds
+
+;--- no-vnds.ll
+; This is the most common case. When -fprofile-generate is used and there exists executable code, we generate the __llvm_prf_cnts, __llvm_prf_data, and __llvm_prf_names sections.
+;
+target datalayout = "E-m:a-p:32:32-i64:64-n32"
+target triple = "powerpc-ibm-aix7.2.0.0"
+
+ at __profc_main = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8
+ at __profd_main = private global i64 zeroinitializer, section "__llvm_prf_data", align 8
+ at __llvm_prf_nm = private constant [6 x i8] c"\04\00main", section "__llvm_prf_names", align 1
+
+ at llvm.used = appending global [3 x i8*]
+  [i8* bitcast ([1 x i64]* @__profc_main to i8*),
+   i8* bitcast (i64* @__profd_main to i8*),
+   i8* getelementptr inbounds ([6 x i8], [6 x i8]* @__llvm_prf_nm, i32 0, i32 0)], section "llvm.metadata"
+
+define i32 @main() #0 {
+entry:
+  ret i32 1
+}
+; There will be two __llvm_prf_cnts .csects, one to represent the actual csect 
+; that holds @__profc_main, and one generated to hold the .ref directives. In 
+; XCOFF, a csect can be defined in pieces, so this is is legal assembly.
+;
+; NOVNDS:      .csect __llvm_prf_cnts[RW],3
+; NOVNDS:      .csect __llvm_prf_cnts[RW],3
+; NOVNDS-NEXT: .ref __llvm_prf_data[RW]
+; NOVNDS-NEXT: .ref __llvm_prf_names[RO]
+; NOVNDS-NOT:  .ref __llvm_prf_vnds
+
+;--- with-vnds.ll
+; When value profiling is needed, the PGO instrumentation generates variables in the __llvm_prf_vnds section, so we generate a .ref for them too.
+;
+ at __profc_main = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8
+ at __profd_main = private global i64 zeroinitializer, section "__llvm_prf_data", align 8
+ at __llvm_prf_nm = private constant [6 x i8] c"\04\00main", section "__llvm_prf_names", align 1
+ at __llvm_prf_vnodes = private global [10 x { i64, i64, i8* }] zeroinitializer, section "__llvm_prf_vnds"
+
+ at llvm.used = appending global [4 x i8*]
+  [i8* bitcast ([1 x i64]* @__profc_main to i8*),
+   i8* bitcast (i64* @__profd_main to i8*),
+   i8* getelementptr inbounds ([6 x i8], [6 x i8]* @__llvm_prf_nm, i32 0, i32 0),
+   i8* bitcast ([10 x { i64, i64, i8* }]* @__llvm_prf_vnodes to i8*)], section "llvm.metadata"
+
+define i32 @main() #0 {
+entry:
+  ret i32 1
+}
+
+; WITHVNDS:      .csect __llvm_prf_cnts[RW],3
+; WITHVNDS:      .csect __llvm_prf_cnts[RW],3
+; WITHVNDS-NEXT: .ref __llvm_prf_data[RW]
+; WITHVNDS-NEXT: .ref __llvm_prf_names[RO]
+; WITHVNDS-NEXT: .ref __llvm_prf_vnds[RW]


        


More information about the llvm-commits mailing list