[llvm] b771c4a - [PowerPC][Future] More support for PCRel addressing for global values

Kamau Bridgeman via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 09:06:44 PDT 2020


Author: Stefan Pintilie
Date: 2020-04-17T11:06:13-05:00
New Revision: b771c4a842d65123ffcda2534540ee9dbd2ad3ce

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

LOG: [PowerPC][Future] More support for PCRel addressing for global values

Add initial support for PC Relative addressing for global values that
require GOT indirect addressing. This patch adds PCRelative support for
global addresses that may not be known at link time and may require
access through the GOT.

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

Added: 
    llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll

Modified: 
    llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
    llvm/lib/Target/PowerPC/PPC.h
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
    llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
    llvm/test/CodeGen/PowerPC/pcrel-call-linkage-with-calls.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
index eb88c530b42d..e28c9caaefaf 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def
@@ -98,6 +98,7 @@
 #undef R_PPC64_DTPREL16_HIGHA
 #undef R_PPC64_REL24_NOTOC
 #undef R_PPC64_PCREL34
+#undef R_PPC64_GOT_PCREL34
 #undef R_PPC64_IRELATIVE
 #undef R_PPC64_REL16
 #undef R_PPC64_REL16_LO
@@ -194,6 +195,7 @@ ELF_RELOC(R_PPC64_DTPREL16_HIGH,        114)
 ELF_RELOC(R_PPC64_DTPREL16_HIGHA,       115)
 ELF_RELOC(R_PPC64_REL24_NOTOC,          116)
 ELF_RELOC(R_PPC64_PCREL34,              132)
+ELF_RELOC(R_PPC64_GOT_PCREL34,          133)
 ELF_RELOC(R_PPC64_IRELATIVE,            248)
 ELF_RELOC(R_PPC64_REL16,                249)
 ELF_RELOC(R_PPC64_REL16_LO,             250)

diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index d1ffef779a52..776e116a6e16 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -210,9 +210,9 @@ class MCSymbolRefExpr : public MCExpr {
     VK_TLSLDM,
     VK_TPOFF,
     VK_DTPOFF,
-    VK_TLSCALL,   // symbol(tlscall)
-    VK_TLSDESC,   // symbol(tlsdesc)
-    VK_TLVP,      // Mach-O thread local variable relocations
+    VK_TLSCALL, // symbol(tlscall)
+    VK_TLSDESC, // symbol(tlsdesc)
+    VK_TLVP,    // Mach-O thread local variable relocations
     VK_TLVPPAGE,
     VK_TLVPPAGEOFF,
     VK_PAGE,
@@ -220,8 +220,8 @@ class MCSymbolRefExpr : public MCExpr {
     VK_GOTPAGE,
     VK_GOTPAGEOFF,
     VK_SECREL,
-    VK_SIZE,      // symbol at SIZE
-    VK_WEAKREF,   // The link between the symbols in .weakref foo, bar
+    VK_SIZE,    // symbol at SIZE
+    VK_WEAKREF, // The link between the symbols in .weakref foo, bar
 
     VK_X86_ABS8,
 
@@ -230,8 +230,8 @@ class MCSymbolRefExpr : public MCExpr {
     VK_ARM_TARGET1,
     VK_ARM_TARGET2,
     VK_ARM_PREL31,
-    VK_ARM_SBREL,          // symbol(sbrel)
-    VK_ARM_TLSLDO,         // symbol(tlsldo)
+    VK_ARM_SBREL,  // symbol(sbrel)
+    VK_ARM_TLSLDO, // symbol(tlsldo)
     VK_ARM_TLSDESCSEQ,
 
     VK_AVR_NONE,
@@ -242,65 +242,66 @@ class MCSymbolRefExpr : public MCExpr {
     VK_AVR_DIFF16,
     VK_AVR_DIFF32,
 
-    VK_PPC_LO,             // symbol at l
-    VK_PPC_HI,             // symbol at h
-    VK_PPC_HA,             // symbol at ha
-    VK_PPC_HIGH,           // symbol at high
-    VK_PPC_HIGHA,          // symbol at higha
-    VK_PPC_HIGHER,         // symbol at higher
-    VK_PPC_HIGHERA,        // symbol at highera
-    VK_PPC_HIGHEST,        // symbol at highest
-    VK_PPC_HIGHESTA,       // symbol at highesta
-    VK_PPC_GOT_LO,         // symbol at got@l
-    VK_PPC_GOT_HI,         // symbol at got@h
-    VK_PPC_GOT_HA,         // symbol at got@ha
-    VK_PPC_TOCBASE,        // symbol at tocbase
-    VK_PPC_TOC,            // symbol at toc
-    VK_PPC_TOC_LO,         // symbol at toc@l
-    VK_PPC_TOC_HI,         // symbol at toc@h
-    VK_PPC_TOC_HA,         // symbol at toc@ha
-    VK_PPC_U,              // symbol at u
-    VK_PPC_L,              // symbol at l
-    VK_PPC_DTPMOD,         // symbol at dtpmod
-    VK_PPC_TPREL_LO,       // symbol at tprel@l
-    VK_PPC_TPREL_HI,       // symbol at tprel@h
-    VK_PPC_TPREL_HA,       // symbol at tprel@ha
-    VK_PPC_TPREL_HIGH,     // symbol at tprel@high
-    VK_PPC_TPREL_HIGHA,    // symbol at tprel@higha
-    VK_PPC_TPREL_HIGHER,   // symbol at tprel@higher
-    VK_PPC_TPREL_HIGHERA,  // symbol at tprel@highera
-    VK_PPC_TPREL_HIGHEST,  // symbol at tprel@highest
-    VK_PPC_TPREL_HIGHESTA, // symbol at tprel@highesta
-    VK_PPC_DTPREL_LO,      // symbol at dtprel@l
-    VK_PPC_DTPREL_HI,      // symbol at dtprel@h
-    VK_PPC_DTPREL_HA,      // symbol at dtprel@ha
-    VK_PPC_DTPREL_HIGH,    // symbol at dtprel@high
-    VK_PPC_DTPREL_HIGHA,   // symbol at dtprel@higha
-    VK_PPC_DTPREL_HIGHER,  // symbol at dtprel@higher
-    VK_PPC_DTPREL_HIGHERA, // symbol at dtprel@highera
-    VK_PPC_DTPREL_HIGHEST, // symbol at dtprel@highest
-    VK_PPC_DTPREL_HIGHESTA,// symbol at dtprel@highesta
-    VK_PPC_GOT_TPREL,      // symbol at got@tprel
-    VK_PPC_GOT_TPREL_LO,   // symbol at got@tprel at l
-    VK_PPC_GOT_TPREL_HI,   // symbol at got@tprel at h
-    VK_PPC_GOT_TPREL_HA,   // symbol at got@tprel at ha
-    VK_PPC_GOT_DTPREL,     // symbol at got@dtprel
-    VK_PPC_GOT_DTPREL_LO,  // symbol at got@dtprel at l
-    VK_PPC_GOT_DTPREL_HI,  // symbol at got@dtprel at h
-    VK_PPC_GOT_DTPREL_HA,  // symbol at got@dtprel at ha
-    VK_PPC_TLS,            // symbol at tls
-    VK_PPC_GOT_TLSGD,      // symbol at got@tlsgd
-    VK_PPC_GOT_TLSGD_LO,   // symbol at got@tlsgd at l
-    VK_PPC_GOT_TLSGD_HI,   // symbol at got@tlsgd at h
-    VK_PPC_GOT_TLSGD_HA,   // symbol at got@tlsgd at ha
-    VK_PPC_TLSGD,          // symbol at tlsgd
-    VK_PPC_GOT_TLSLD,      // symbol at got@tlsld
-    VK_PPC_GOT_TLSLD_LO,   // symbol at got@tlsld at l
-    VK_PPC_GOT_TLSLD_HI,   // symbol at got@tlsld at h
-    VK_PPC_GOT_TLSLD_HA,   // symbol at got@tlsld at ha
-    VK_PPC_TLSLD,          // symbol at tlsld
-    VK_PPC_LOCAL,          // symbol at local
-    VK_PPC_NOTOC,          // symbol at notoc
+    VK_PPC_LO,              // symbol at l
+    VK_PPC_HI,              // symbol at h
+    VK_PPC_HA,              // symbol at ha
+    VK_PPC_HIGH,            // symbol at high
+    VK_PPC_HIGHA,           // symbol at higha
+    VK_PPC_HIGHER,          // symbol at higher
+    VK_PPC_HIGHERA,         // symbol at highera
+    VK_PPC_HIGHEST,         // symbol at highest
+    VK_PPC_HIGHESTA,        // symbol at highesta
+    VK_PPC_GOT_LO,          // symbol at got@l
+    VK_PPC_GOT_HI,          // symbol at got@h
+    VK_PPC_GOT_HA,          // symbol at got@ha
+    VK_PPC_TOCBASE,         // symbol at tocbase
+    VK_PPC_TOC,             // symbol at toc
+    VK_PPC_TOC_LO,          // symbol at toc@l
+    VK_PPC_TOC_HI,          // symbol at toc@h
+    VK_PPC_TOC_HA,          // symbol at toc@ha
+    VK_PPC_U,               // symbol at u
+    VK_PPC_L,               // symbol at l
+    VK_PPC_DTPMOD,          // symbol at dtpmod
+    VK_PPC_TPREL_LO,        // symbol at tprel@l
+    VK_PPC_TPREL_HI,        // symbol at tprel@h
+    VK_PPC_TPREL_HA,        // symbol at tprel@ha
+    VK_PPC_TPREL_HIGH,      // symbol at tprel@high
+    VK_PPC_TPREL_HIGHA,     // symbol at tprel@higha
+    VK_PPC_TPREL_HIGHER,    // symbol at tprel@higher
+    VK_PPC_TPREL_HIGHERA,   // symbol at tprel@highera
+    VK_PPC_TPREL_HIGHEST,   // symbol at tprel@highest
+    VK_PPC_TPREL_HIGHESTA,  // symbol at tprel@highesta
+    VK_PPC_DTPREL_LO,       // symbol at dtprel@l
+    VK_PPC_DTPREL_HI,       // symbol at dtprel@h
+    VK_PPC_DTPREL_HA,       // symbol at dtprel@ha
+    VK_PPC_DTPREL_HIGH,     // symbol at dtprel@high
+    VK_PPC_DTPREL_HIGHA,    // symbol at dtprel@higha
+    VK_PPC_DTPREL_HIGHER,   // symbol at dtprel@higher
+    VK_PPC_DTPREL_HIGHERA,  // symbol at dtprel@highera
+    VK_PPC_DTPREL_HIGHEST,  // symbol at dtprel@highest
+    VK_PPC_DTPREL_HIGHESTA, // symbol at dtprel@highesta
+    VK_PPC_GOT_TPREL,       // symbol at got@tprel
+    VK_PPC_GOT_TPREL_LO,    // symbol at got@tprel at l
+    VK_PPC_GOT_TPREL_HI,    // symbol at got@tprel at h
+    VK_PPC_GOT_TPREL_HA,    // symbol at got@tprel at ha
+    VK_PPC_GOT_DTPREL,      // symbol at got@dtprel
+    VK_PPC_GOT_DTPREL_LO,   // symbol at got@dtprel at l
+    VK_PPC_GOT_DTPREL_HI,   // symbol at got@dtprel at h
+    VK_PPC_GOT_DTPREL_HA,   // symbol at got@dtprel at ha
+    VK_PPC_TLS,             // symbol at tls
+    VK_PPC_GOT_TLSGD,       // symbol at got@tlsgd
+    VK_PPC_GOT_TLSGD_LO,    // symbol at got@tlsgd at l
+    VK_PPC_GOT_TLSGD_HI,    // symbol at got@tlsgd at h
+    VK_PPC_GOT_TLSGD_HA,    // symbol at got@tlsgd at ha
+    VK_PPC_TLSGD,           // symbol at tlsgd
+    VK_PPC_GOT_TLSLD,       // symbol at got@tlsld
+    VK_PPC_GOT_TLSLD_LO,    // symbol at got@tlsld at l
+    VK_PPC_GOT_TLSLD_HI,    // symbol at got@tlsld at h
+    VK_PPC_GOT_TLSLD_HA,    // symbol at got@tlsld at ha
+    VK_PPC_GOT_PCREL,       // symbol at got@pcrel
+    VK_PPC_TLSLD,           // symbol at tlsld
+    VK_PPC_LOCAL,           // symbol at local
+    VK_PPC_NOTOC,           // symbol at notoc
 
     VK_COFF_IMGREL32, // symbol at imgrel (image-relative)
 

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 1448a54a04e3..ead2ef21c617 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -317,6 +317,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
   case VK_PPC_GOT_TLSLD_LO: return "got at tlsld@l";
   case VK_PPC_GOT_TLSLD_HI: return "got at tlsld@h";
   case VK_PPC_GOT_TLSLD_HA: return "got at tlsld@ha";
+  case VK_PPC_GOT_PCREL:
+    return "got at pcrel";
   case VK_PPC_TLSLD: return "tlsld";
   case VK_PPC_LOCAL: return "local";
   case VK_PPC_NOTOC: return "notoc";

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
index 1687b2975825..d8b3301e97f1 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
@@ -129,7 +129,16 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
       errs() << '\n';
       report_fatal_error("Invalid PC-relative half16ds relocation");
     case PPC::fixup_ppc_pcrel34:
-      Type = ELF::R_PPC64_PCREL34;
+      switch (Modifier) {
+      default:
+        llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
+      case MCSymbolRefExpr::VK_PCREL:
+        Type = ELF::R_PPC64_PCREL34;
+        break;
+      case MCSymbolRefExpr::VK_PPC_GOT_PCREL:
+        Type = ELF::R_PPC64_GOT_PCREL34;
+        break;
+      }
       break;
     case FK_Data_4:
     case FK_PCRel_4:

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index e782fc194791..f1b57114ec1c 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -193,8 +193,9 @@ PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
     const MCExpr *Expr = MO.getExpr();
     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
     (void)SRE;
-    assert(SRE->getKind() == MCSymbolRefExpr::VK_PCREL &&
-           "VariantKind must be VK_PCREL");
+    assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
+            SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&
+           "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");
     Fixups.push_back(
         MCFixup::create(IsLittleEndian ? 0 : 1, Expr,
                         static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));

diff  --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h
index 8a78a8d0a017..815c67286a2c 100644
--- a/llvm/lib/Target/PowerPC/PPC.h
+++ b/llvm/lib/Target/PowerPC/PPC.h
@@ -102,6 +102,11 @@ namespace llvm {
     /// the current instruction address(pc), e.g., var at pcrel. Fixup is VK_PCREL.
     MO_PCREL_FLAG = 4,
 
+    /// MO_GOT_FLAG - If this bit is set the symbol reference is to be computed
+    /// via the GOT. For example when combined with the MO_PCREL_FLAG it should
+    /// produce the relocation @got at pcrel. Fixup is VK_PPC_GOT_PCREL.
+    MO_GOT_FLAG = 32,
+
     /// The next are not flags but distinct values.
     MO_ACCESS_MASK = 0xf00,
 

diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 6cf4b85a4f74..c9bd6e845450 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3051,11 +3051,21 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op,
   // 64-bit SVR4 ABI & AIX ABI code is always position-independent.
   // The actual address of the GlobalValue is stored in the TOC.
   if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
-    if (!isAccessedAsGotIndirect(Op) && Subtarget.isUsingPCRelativeCalls()) {
+    if (Subtarget.isUsingPCRelativeCalls()) {
       EVT Ty = getPointerTy(DAG.getDataLayout());
-      SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty, GSDN->getOffset(),
-                                              PPCII::MO_PCREL_FLAG);
-      return DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, GA);
+      if (isAccessedAsGotIndirect(Op)) {
+        SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty, GSDN->getOffset(),
+                                                PPCII::MO_PCREL_FLAG |
+                                                    PPCII::MO_GOT_FLAG);
+        SDValue MatPCRel = DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, GA);
+        SDValue Load = DAG.getLoad(MVT::i64, DL, DAG.getEntryNode(), MatPCRel,
+                                   MachinePointerInfo());
+        return Load;
+      } else {
+        SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty, GSDN->getOffset(),
+                                                PPCII::MO_PCREL_FLAG);
+        return DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, GA);
+      }
     }
     setUsesTOCBasePtr(DAG);
     SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset());

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index 2dfc5c5e2bd1..709b21384538 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -2048,7 +2048,8 @@ PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
   static const std::pair<unsigned, const char *> TargetFlags[] = {
       {MO_PLT, "ppc-plt"},
       {MO_PIC_FLAG, "ppc-pic"},
-      {MO_PCREL_FLAG, "ppc-pcrel"}};
+      {MO_PCREL_FLAG, "ppc-pcrel"},
+      {MO_GOT_FLAG, "ppc-got"}};
   return makeArrayRef(TargetFlags);
 }
 

diff  --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
index 0a0e168c0076..add4de24275f 100644
--- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
+++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
@@ -82,6 +82,8 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
     RefKind = MCSymbolRefExpr::VK_PLT;
   else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG)
     RefKind = MCSymbolRefExpr::VK_PCREL;
+  else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG))
+    RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL;
 
   const MachineInstr *MI = MO.getParent();
 

diff  --git a/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-with-calls.ll b/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-with-calls.ll
index 59001d482665..ed96e732b08b 100644
--- a/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-with-calls.ll
+++ b/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-with-calls.ll
@@ -53,9 +53,7 @@ entry:
 
 define dso_local signext i32 @DirectCallLocal2(i32 signext %a, i32 signext %b) local_unnamed_addr {
 ; CHECK-ALL-LABEL: DirectCallLocal2:
-; CHECK-S:         addis r2, r12, .TOC.-.Lfunc_gep2 at ha
-; CHECK-S-NEXT:    addi r2, r2, .TOC.-.Lfunc_gep2 at l
-; CHECK-S:         .localentry     DirectCallLocal2, .Lfunc_lep2-.Lfunc_gep2
+; CHECK-S:         .localentry     DirectCallLocal2
 ; CHECK-S:       # %bb.0: # %entry
 ; CHECK-S-NEXT:    mflr r0
 ; CHECK-S-NEXT:    std r0, 16(r1)
@@ -64,10 +62,8 @@ define dso_local signext i32 @DirectCallLocal2(i32 signext %a, i32 signext %b) l
 ; CHECK-S-NEXT:    .cfi_offset lr, 16
 ; CHECK-S-NEXT:    add r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3
-; CHECK-S-NEXT:    bl localCall
-; CHECK-S-NEXT:    nop
-; CHECK-S-NEXT:    addis r4, r2, .LC0 at toc@ha
-; CHECK-S-NEXT:    ld r4, .LC0 at toc@l(r4)
+; CHECK-S-NEXT:    bl localCall at notoc
+; CHECK-S-NEXT:    pld r4, externGlobalVar at got@pcrel(0), 1
 ; CHECK-S-NEXT:    lwz r4, 0(r4)
 ; CHECK-S-NEXT:    mullw r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3
@@ -140,9 +136,7 @@ declare signext i32 @externCall(i32 signext) local_unnamed_addr
 
 define dso_local signext i32 @DirectCallExtern2(i32 signext %a, i32 signext %b) local_unnamed_addr {
 ; CHECK-ALL-LABEL: DirectCallExtern2:
-; CHECK-S:         addis r2, r12, .TOC.-.Lfunc_gep5 at ha
-; CHECK-S-NEXT:    addi r2, r2, .TOC.-.Lfunc_gep5 at l
-; CHECK-S:         .localentry     DirectCallExtern2, .Lfunc_lep5-.Lfunc_gep5
+; CHECK-S:         .localentry     DirectCallExtern2
 ; CHECK-S:       # %bb.0: # %entry
 ; CHECK-S-NEXT:    mflr r0
 ; CHECK-S-NEXT:    std r0, 16(r1)
@@ -151,10 +145,8 @@ define dso_local signext i32 @DirectCallExtern2(i32 signext %a, i32 signext %b)
 ; CHECK-S-NEXT:    .cfi_offset lr, 16
 ; CHECK-S-NEXT:    add r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3
-; CHECK-S-NEXT:    bl externCall
-; CHECK-S-NEXT:    nop
-; CHECK-S-NEXT:    addis r4, r2, .LC0 at toc@ha
-; CHECK-S-NEXT:    ld r4, .LC0 at toc@l(r4)
+; CHECK-S-NEXT:    bl externCall at notoc
+; CHECK-S-NEXT:    pld r4, externGlobalVar at got@pcrel(0), 1
 ; CHECK-S-NEXT:    lwz r4, 0(r4)
 ; CHECK-S-NEXT:    mullw r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3
@@ -223,22 +215,18 @@ entry:
 
 define dso_local signext i32 @TailCallLocal2(i32 signext %a) local_unnamed_addr {
 ; CHECK-ALL-LABEL: TailCallLocal2:
-; CHECK-S:         addis r2, r12, .TOC.-.Lfunc_gep8 at ha
-; CHECK-S-NEXT:    addi r2, r2, .TOC.-.Lfunc_gep8 at l
-; CHECK-S:         .localentry     TailCallLocal2, .Lfunc_lep8-.Lfunc_gep8
+; CHECK-S:         .localentry     TailCallLocal2
 ; CHECK-S:       # %bb.0: # %entry
 ; CHECK-S-NEXT:    mflr r0
 ; CHECK-S-NEXT:    std r0, 16(r1)
 ; CHECK-S-NEXT:    stdu r1, -32(r1)
 ; CHECK-S-NEXT:    .cfi_def_cfa_offset 32
 ; CHECK-S-NEXT:    .cfi_offset lr, 16
-; CHECK-S-NEXT:    addis r4, r2, .LC0 at toc@ha
-; CHECK-S-NEXT:    ld r4, .LC0 at toc@l(r4)
+; CHECK-S-NEXT:    pld r4, externGlobalVar at got@pcrel(0), 1
 ; CHECK-S-NEXT:    lwz r4, 0(r4)
 ; CHECK-S-NEXT:    add r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3
-; CHECK-S-NEXT:    bl localCall
-; CHECK-S-NEXT:    nop
+; CHECK-S-NEXT:    bl localCall at notoc
 ; CHECK-S-NEXT:    addi r1, r1, 32
 ; CHECK-S-NEXT:    ld r0, 16(r1)
 ; CHECK-S-NEXT:    mtlr r0
@@ -296,22 +284,18 @@ entry:
 
 define dso_local signext i32 @TailCallExtern2(i32 signext %a) local_unnamed_addr {
 ; CHECK-ALL-LABEL: TailCallExtern2:
-; CHECK-S:         addis r2, r12, .TOC.-.Lfunc_gep11 at ha
-; CHECK-S-NEXT:    addi r2, r2, .TOC.-.Lfunc_gep11 at l
-; CHECK-S:         .localentry     TailCallExtern2, .Lfunc_lep11-.Lfunc_gep11
+; CHECK-S:         .localentry     TailCallExtern2
 ; CHECK-S:       # %bb.0: # %entry
 ; CHECK-S-NEXT:    mflr r0
 ; CHECK-S-NEXT:    std r0, 16(r1)
 ; CHECK-S-NEXT:    stdu r1, -32(r1)
 ; CHECK-S-NEXT:    .cfi_def_cfa_offset 32
 ; CHECK-S-NEXT:    .cfi_offset lr, 16
-; CHECK-S-NEXT:    addis r4, r2, .LC0 at toc@ha
-; CHECK-S-NEXT:    ld r4, .LC0 at toc@l(r4)
+; CHECK-S-NEXT:    pld r4, externGlobalVar at got@pcrel(0), 1
 ; CHECK-S-NEXT:    lwz r4, 0(r4)
 ; CHECK-S-NEXT:    add r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3
-; CHECK-S-NEXT:    bl externCall
-; CHECK-S-NEXT:    nop
+; CHECK-S-NEXT:    bl externCall at notoc
 ; CHECK-S-NEXT:    addi r1, r1, 32
 ; CHECK-S-NEXT:    ld r0, 16(r1)
 ; CHECK-S-NEXT:    mtlr r0
@@ -394,8 +378,7 @@ define dso_local signext i32 @IndirectCall2(i32 signext %a, i32 signext %b) loca
 ; CHECK-S-NEXT:    mtctr r12
 ; CHECK-S-NEXT:    bctrl
 ; CHECK-S-NEXT:    ld 2, 24(r1)
-; CHECK-S-NEXT:    addis r4, r2, .LC0 at toc@ha
-; CHECK-S-NEXT:    ld r4, .LC0 at toc@l(r4)
+; CHECK-S-NEXT:    pld r4, externGlobalVar at got@pcrel(0), 1
 ; CHECK-S-NEXT:    lwz r4, 0(r4)
 ; CHECK-S-NEXT:    mullw r3, r4, r3
 ; CHECK-S-NEXT:    extsw r3, r3

diff  --git a/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll b/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll
new file mode 100644
index 000000000000..e9aeccd4ac16
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/pcrel-got-indirect.ll
@@ -0,0 +1,253 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=future -enable-ppc-quad-precision -ppc-asm-full-reg-names \
+; RUN:   -ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+%struct.Struct = type { i8, i16, i32 }
+
+ at valChar = external local_unnamed_addr global i8, align 1
+ at valShort = external local_unnamed_addr global i16, align 2
+ at valInt = external global i32, align 4
+ at valUnsigned = external local_unnamed_addr global i32, align 4
+ at valLong = external local_unnamed_addr global i64, align 8
+ at ptr = external local_unnamed_addr global i32*, align 8
+ at array = external local_unnamed_addr global [10 x i32], align 4
+ at structure = external local_unnamed_addr global %struct.Struct, align 4
+ at ptrfunc = external local_unnamed_addr global void (...)*, align 8
+
+define dso_local signext i32 @ReadGlobalVarChar() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalVarChar:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valChar at got@pcrel(0), 1
+; CHECK-NEXT:    lbz r3, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i8, i8* @valChar, align 1
+  %conv = zext i8 %0 to i32
+  ret i32 %conv
+}
+
+define dso_local void @WriteGlobalVarChar() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalVarChar:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valChar at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 3
+; CHECK-NEXT:    stb r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i8 3, i8* @valChar, align 1
+  ret void
+}
+
+define dso_local signext i32 @ReadGlobalVarShort() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalVarShort:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valShort at got@pcrel(0), 1
+; CHECK-NEXT:    lha r3, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i16, i16* @valShort, align 2
+  %conv = sext i16 %0 to i32
+  ret i32 %conv
+}
+
+define dso_local void @WriteGlobalVarShort() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalVarShort:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valShort at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 3
+; CHECK-NEXT:    sth r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i16 3, i16* @valShort, align 2
+  ret void
+}
+
+define dso_local signext i32 @ReadGlobalVarInt() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalVarInt:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valInt at got@pcrel(0), 1
+; CHECK-NEXT:    lwa r3, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @valInt, align 4
+  ret i32 %0
+}
+
+define dso_local void @WriteGlobalVarInt() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalVarInt:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valInt at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 33
+; CHECK-NEXT:    stw r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i32 33, i32* @valInt, align 4
+  ret void
+}
+
+define dso_local signext i32 @ReadGlobalVarUnsigned() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalVarUnsigned:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valUnsigned at got@pcrel(0), 1
+; CHECK-NEXT:    lwa r3, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @valUnsigned, align 4
+  ret i32 %0
+}
+
+define dso_local void @WriteGlobalVarUnsigned() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalVarUnsigned:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valUnsigned at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 33
+; CHECK-NEXT:    stw r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i32 33, i32* @valUnsigned, align 4
+  ret void
+}
+
+define dso_local signext i32 @ReadGlobalVarLong() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalVarLong:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valLong at got@pcrel(0), 1
+; CHECK-NEXT:    lwa r3, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i64, i64* @valLong, align 8
+  %conv = trunc i64 %0 to i32
+  ret i32 %conv
+}
+
+define dso_local void @WriteGlobalVarLong() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalVarLong:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valLong at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 3333
+; CHECK-NEXT:    std r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i64 3333, i64* @valLong, align 8
+  ret void
+}
+
+define dso_local i32* @ReadGlobalPtr() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalPtr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, ptr at got@pcrel(0), 1
+; CHECK-NEXT:    ld r3, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32*, i32** @ptr, align 8
+  ret i32* %0
+}
+
+define dso_local void @WriteGlobalPtr() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalPtr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, ptr at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 3
+; CHECK-NEXT:    ld r3, 0(r3)
+; CHECK-NEXT:    stw r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32*, i32** @ptr, align 8
+  store i32 3, i32* %0, align 4
+  ret void
+}
+
+define dso_local nonnull i32* @GlobalVarAddr() local_unnamed_addr  {
+; CHECK-LABEL: GlobalVarAddr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, valInt at got@pcrel(0), 1
+; CHECK-NEXT:    blr
+entry:
+  ret i32* @valInt
+}
+
+define dso_local signext i32 @ReadGlobalArray() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalArray:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, array at got@pcrel(0), 1
+; CHECK-NEXT:    lwa r3, 12(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @array, i64 0, i64 3), align 4
+  ret i32 %0
+}
+
+define dso_local void @WriteGlobalArray() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalArray:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, array at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 5
+; CHECK-NEXT:    stw r4, 12(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i32 5, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @array, i64 0, i64 3), align 4
+  ret void
+}
+
+define dso_local signext i32 @ReadGlobalStruct() local_unnamed_addr  {
+; CHECK-LABEL: ReadGlobalStruct:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, structure at got@pcrel(0), 1
+; CHECK-NEXT:    lwa r3, 4(r3)
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* getelementptr inbounds (%struct.Struct, %struct.Struct* @structure, i64 0, i32 2), align 4
+  ret i32 %0
+}
+
+define dso_local void @WriteGlobalStruct() local_unnamed_addr  {
+; CHECK-LABEL: WriteGlobalStruct:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, structure at got@pcrel(0), 1
+; CHECK-NEXT:    li r4, 3
+; CHECK-NEXT:    stw r4, 4(r3)
+; CHECK-NEXT:    blr
+entry:
+  store i32 3, i32* getelementptr inbounds (%struct.Struct, %struct.Struct* @structure, i64 0, i32 2), align 4
+  ret void
+}
+
+define dso_local void @ReadFuncPtr() local_unnamed_addr  {
+; CHECK-LABEL: ReadFuncPtr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mflr r0
+; CHECK-NEXT:    std r0, 16(r1)
+; CHECK-NEXT:    stdu r1, -32(r1)
+; CHECK-NEXT:    std r2, 24(r1)
+; CHECK-NEXT:    .cfi_def_cfa_offset 32
+; CHECK-NEXT:    .cfi_offset lr, 16
+; CHECK-NEXT:    pld r3, ptrfunc at got@pcrel(0), 1
+; CHECK-NEXT:    ld r12, 0(r3)
+; CHECK-NEXT:    mtctr r12
+; CHECK-NEXT:    bctrl
+; CHECK-NEXT:    ld 2, 24(r1)
+; CHECK-NEXT:    addi r1, r1, 32
+; CHECK-NEXT:    ld r0, 16(r1)
+; CHECK-NEXT:    mtlr r0
+; CHECK-NEXT:    blr
+entry:
+  %0 = load void ()*, void ()** bitcast (void (...)** @ptrfunc to void ()**), align 8
+  tail call void %0()
+  ret void
+}
+
+define dso_local void @WriteFuncPtr() local_unnamed_addr  {
+; CHECK-LABEL: WriteFuncPtr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pld r3, ptrfunc at got@pcrel(0), 1
+; CHECK-NEXT:    pld r4, function at got@pcrel(0), 1
+; CHECK-NEXT:    std r4, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  store void (...)* @function, void (...)** @ptrfunc, align 8
+  ret void
+}
+
+declare void @function(...)
+


        


More information about the llvm-commits mailing list