forked from OSchip/llvm-project
[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
This commit is contained in:
parent
a127d61835
commit
b771c4a842
|
@ -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)
|
||||
|
|
|
@ -210,9 +210,9 @@ public:
|
|||
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 @@ public:
|
|||
VK_GOTPAGE,
|
||||
VK_GOTPAGEOFF,
|
||||
VK_SECREL,
|
||||
VK_SIZE, // symbol@SIZE
|
||||
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
|
||||
VK_SIZE, // symbol@SIZE
|
||||
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
|
||||
|
||||
VK_X86_ABS8,
|
||||
|
||||
|
@ -230,8 +230,8 @@ public:
|
|||
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 @@ public:
|
|||
VK_AVR_DIFF16,
|
||||
VK_AVR_DIFF32,
|
||||
|
||||
VK_PPC_LO, // symbol@l
|
||||
VK_PPC_HI, // symbol@h
|
||||
VK_PPC_HA, // symbol@ha
|
||||
VK_PPC_HIGH, // symbol@high
|
||||
VK_PPC_HIGHA, // symbol@higha
|
||||
VK_PPC_HIGHER, // symbol@higher
|
||||
VK_PPC_HIGHERA, // symbol@highera
|
||||
VK_PPC_HIGHEST, // symbol@highest
|
||||
VK_PPC_HIGHESTA, // symbol@highesta
|
||||
VK_PPC_GOT_LO, // symbol@got@l
|
||||
VK_PPC_GOT_HI, // symbol@got@h
|
||||
VK_PPC_GOT_HA, // symbol@got@ha
|
||||
VK_PPC_TOCBASE, // symbol@tocbase
|
||||
VK_PPC_TOC, // symbol@toc
|
||||
VK_PPC_TOC_LO, // symbol@toc@l
|
||||
VK_PPC_TOC_HI, // symbol@toc@h
|
||||
VK_PPC_TOC_HA, // symbol@toc@ha
|
||||
VK_PPC_U, // symbol@u
|
||||
VK_PPC_L, // symbol@l
|
||||
VK_PPC_DTPMOD, // symbol@dtpmod
|
||||
VK_PPC_TPREL_LO, // symbol@tprel@l
|
||||
VK_PPC_TPREL_HI, // symbol@tprel@h
|
||||
VK_PPC_TPREL_HA, // symbol@tprel@ha
|
||||
VK_PPC_TPREL_HIGH, // symbol@tprel@high
|
||||
VK_PPC_TPREL_HIGHA, // symbol@tprel@higha
|
||||
VK_PPC_TPREL_HIGHER, // symbol@tprel@higher
|
||||
VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera
|
||||
VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest
|
||||
VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta
|
||||
VK_PPC_DTPREL_LO, // symbol@dtprel@l
|
||||
VK_PPC_DTPREL_HI, // symbol@dtprel@h
|
||||
VK_PPC_DTPREL_HA, // symbol@dtprel@ha
|
||||
VK_PPC_DTPREL_HIGH, // symbol@dtprel@high
|
||||
VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha
|
||||
VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher
|
||||
VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera
|
||||
VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest
|
||||
VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta
|
||||
VK_PPC_GOT_TPREL, // symbol@got@tprel
|
||||
VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l
|
||||
VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h
|
||||
VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha
|
||||
VK_PPC_GOT_DTPREL, // symbol@got@dtprel
|
||||
VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l
|
||||
VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h
|
||||
VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha
|
||||
VK_PPC_TLS, // symbol@tls
|
||||
VK_PPC_GOT_TLSGD, // symbol@got@tlsgd
|
||||
VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l
|
||||
VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h
|
||||
VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha
|
||||
VK_PPC_TLSGD, // symbol@tlsgd
|
||||
VK_PPC_GOT_TLSLD, // symbol@got@tlsld
|
||||
VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l
|
||||
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h
|
||||
VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha
|
||||
VK_PPC_TLSLD, // symbol@tlsld
|
||||
VK_PPC_LOCAL, // symbol@local
|
||||
VK_PPC_NOTOC, // symbol@notoc
|
||||
VK_PPC_LO, // symbol@l
|
||||
VK_PPC_HI, // symbol@h
|
||||
VK_PPC_HA, // symbol@ha
|
||||
VK_PPC_HIGH, // symbol@high
|
||||
VK_PPC_HIGHA, // symbol@higha
|
||||
VK_PPC_HIGHER, // symbol@higher
|
||||
VK_PPC_HIGHERA, // symbol@highera
|
||||
VK_PPC_HIGHEST, // symbol@highest
|
||||
VK_PPC_HIGHESTA, // symbol@highesta
|
||||
VK_PPC_GOT_LO, // symbol@got@l
|
||||
VK_PPC_GOT_HI, // symbol@got@h
|
||||
VK_PPC_GOT_HA, // symbol@got@ha
|
||||
VK_PPC_TOCBASE, // symbol@tocbase
|
||||
VK_PPC_TOC, // symbol@toc
|
||||
VK_PPC_TOC_LO, // symbol@toc@l
|
||||
VK_PPC_TOC_HI, // symbol@toc@h
|
||||
VK_PPC_TOC_HA, // symbol@toc@ha
|
||||
VK_PPC_U, // symbol@u
|
||||
VK_PPC_L, // symbol@l
|
||||
VK_PPC_DTPMOD, // symbol@dtpmod
|
||||
VK_PPC_TPREL_LO, // symbol@tprel@l
|
||||
VK_PPC_TPREL_HI, // symbol@tprel@h
|
||||
VK_PPC_TPREL_HA, // symbol@tprel@ha
|
||||
VK_PPC_TPREL_HIGH, // symbol@tprel@high
|
||||
VK_PPC_TPREL_HIGHA, // symbol@tprel@higha
|
||||
VK_PPC_TPREL_HIGHER, // symbol@tprel@higher
|
||||
VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera
|
||||
VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest
|
||||
VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta
|
||||
VK_PPC_DTPREL_LO, // symbol@dtprel@l
|
||||
VK_PPC_DTPREL_HI, // symbol@dtprel@h
|
||||
VK_PPC_DTPREL_HA, // symbol@dtprel@ha
|
||||
VK_PPC_DTPREL_HIGH, // symbol@dtprel@high
|
||||
VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha
|
||||
VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher
|
||||
VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera
|
||||
VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest
|
||||
VK_PPC_DTPREL_HIGHESTA, // symbol@dtprel@highesta
|
||||
VK_PPC_GOT_TPREL, // symbol@got@tprel
|
||||
VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l
|
||||
VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h
|
||||
VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha
|
||||
VK_PPC_GOT_DTPREL, // symbol@got@dtprel
|
||||
VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l
|
||||
VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h
|
||||
VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha
|
||||
VK_PPC_TLS, // symbol@tls
|
||||
VK_PPC_GOT_TLSGD, // symbol@got@tlsgd
|
||||
VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l
|
||||
VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h
|
||||
VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha
|
||||
VK_PPC_TLSGD, // symbol@tlsgd
|
||||
VK_PPC_GOT_TLSLD, // symbol@got@tlsld
|
||||
VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l
|
||||
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h
|
||||
VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha
|
||||
VK_PPC_GOT_PCREL, // symbol@got@pcrel
|
||||
VK_PPC_TLSLD, // symbol@tlsld
|
||||
VK_PPC_LOCAL, // symbol@local
|
||||
VK_PPC_NOTOC, // symbol@notoc
|
||||
|
||||
VK_COFF_IMGREL32, // symbol@imgrel (image-relative)
|
||||
|
||||
|
|
|
@ -317,6 +317,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
|
|||
case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
|
||||
case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
|
||||
case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
|
||||
case VK_PPC_GOT_PCREL:
|
||||
return "got@pcrel";
|
||||
case VK_PPC_TLSLD: return "tlsld";
|
||||
case VK_PPC_LOCAL: return "local";
|
||||
case VK_PPC_NOTOC: return "notoc";
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -102,6 +102,11 @@ namespace llvm {
|
|||
/// the current instruction address(pc), e.g., var@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@pcrel. Fixup is VK_PPC_GOT_PCREL.
|
||||
MO_GOT_FLAG = 32,
|
||||
|
||||
/// The next are not flags but distinct values.
|
||||
MO_ACCESS_MASK = 0xf00,
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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@ha
|
||||
; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep2@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@toc@ha
|
||||
; CHECK-S-NEXT: ld r4, .LC0@toc@l(r4)
|
||||
; CHECK-S-NEXT: bl localCall@notoc
|
||||
; CHECK-S-NEXT: pld r4, externGlobalVar@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@ha
|
||||
; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep5@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@toc@ha
|
||||
; CHECK-S-NEXT: ld r4, .LC0@toc@l(r4)
|
||||
; CHECK-S-NEXT: bl externCall@notoc
|
||||
; CHECK-S-NEXT: pld r4, externGlobalVar@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@ha
|
||||
; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep8@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@toc@ha
|
||||
; CHECK-S-NEXT: ld r4, .LC0@toc@l(r4)
|
||||
; CHECK-S-NEXT: pld r4, externGlobalVar@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@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@ha
|
||||
; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep11@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@toc@ha
|
||||
; CHECK-S-NEXT: ld r4, .LC0@toc@l(r4)
|
||||
; CHECK-S-NEXT: pld r4, externGlobalVar@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@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@toc@ha
|
||||
; CHECK-S-NEXT: ld r4, .LC0@toc@l(r4)
|
||||
; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1
|
||||
; CHECK-S-NEXT: lwz r4, 0(r4)
|
||||
; CHECK-S-NEXT: mullw r3, r4, r3
|
||||
; CHECK-S-NEXT: extsw r3, r3
|
||||
|
|
|
@ -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 }
|
||||
|
||||
@valChar = external local_unnamed_addr global i8, align 1
|
||||
@valShort = external local_unnamed_addr global i16, align 2
|
||||
@valInt = external global i32, align 4
|
||||
@valUnsigned = external local_unnamed_addr global i32, align 4
|
||||
@valLong = external local_unnamed_addr global i64, align 8
|
||||
@ptr = external local_unnamed_addr global i32*, align 8
|
||||
@array = external local_unnamed_addr global [10 x i32], align 4
|
||||
@structure = external local_unnamed_addr global %struct.Struct, align 4
|
||||
@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@got@pcrel(0), 1
|
||||
; CHECK-NEXT: pld r4, function@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(...)
|
||||
|
Loading…
Reference in New Issue