diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -97,6 +97,7 @@ #undef R_PPC64_DTPREL16_HIGH #undef R_PPC64_DTPREL16_HIGHA #undef R_PPC64_REL24_NOTOC +#undef R_PPC64_PCREL34 #undef R_PPC64_IRELATIVE #undef R_PPC64_REL16 #undef R_PPC64_REL16_LO @@ -192,6 +193,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_IRELATIVE, 248) ELF_RELOC(R_PPC64_REL16, 249) ELF_RELOC(R_PPC64_REL16_LO, 250) diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -45,6 +45,8 @@ return Value & 0xffff; case PPC::fixup_ppc_half16ds: return Value & 0xfffc; + case PPC::fixup_ppc_pcrel34: + return Value & 0x3ffffffff; } } @@ -65,6 +67,7 @@ case PPC::fixup_ppc_br24abs: case PPC::fixup_ppc_br24_notoc: return 4; + case PPC::fixup_ppc_pcrel34: case FK_Data_8: return 8; case PPC::fixup_ppc_nofixup: @@ -96,6 +99,7 @@ { "fixup_ppc_brcond14abs", 16, 14, 0 }, { "fixup_ppc_half16", 0, 16, 0 }, { "fixup_ppc_half16ds", 0, 14, 0 }, + { "fixup_ppc_pcrel34", 0, 34, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_nofixup", 0, 0, 0 } }; const static MCFixupKindInfo InfosLE[PPC::NumTargetFixupKinds] = { @@ -107,6 +111,7 @@ { "fixup_ppc_brcond14abs", 2, 14, 0 }, { "fixup_ppc_half16", 0, 16, 0 }, { "fixup_ppc_half16ds", 2, 14, 0 }, + { "fixup_ppc_pcrel34", 0, 34, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_nofixup", 0, 0, 0 } }; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -128,6 +128,9 @@ Target.print(errs()); errs() << '\n'; report_fatal_error("Invalid PC-relative half16ds relocation"); + case PPC::fixup_ppc_pcrel34: + Type = ELF::R_PPC64_PCREL34; + break; case FK_Data_4: case FK_PCRel_4: Type = ELF::R_PPC_REL32; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h @@ -40,6 +40,9 @@ /// instrs like 'std'. fixup_ppc_half16ds, + // A 34-bit fixup corresponding to PC-relative paddi. + fixup_ppc_pcrel34, + /// Not a true fixup, but ties a symbol to a call to __tls_get_addr for the /// TLS general and local dynamic models, or inserts the thread-pointer /// register number. diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -400,9 +400,13 @@ void PPCInstPrinter::printS34ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { - long long Value = MI->getOperand(OpNo).getImm(); - assert(isInt<34>(Value) && "Invalid s34imm argument!"); - O << (long long)Value; + if (MI->getOperand(OpNo).isImm()) { + long long Value = MI->getOperand(OpNo).getImm(); + assert(isInt<34>(Value) && "Invalid s34imm argument!"); + O << (long long)Value; + } + else + printOperand(MI, OpNo, O); } void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h @@ -50,6 +50,9 @@ unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned long getImm34Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -104,6 +104,20 @@ return 0; } +unsigned long +PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); + + // Add a fixup for the immediate field. + Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 1, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_pcrel34)); + return 0; +} + unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { @@ -175,6 +189,16 @@ report_fatal_error("Operand must be 0"); const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isExpr()) { + const MCExpr *Expr = MO.getExpr(); + const MCSymbolRefExpr *SRE = cast(Expr); + assert(SRE->getKind() == MCSymbolRefExpr::VK_PCREL && + "VariantKind must be VK_PCREL"); + Fixups.push_back( + MCFixup::create(IsLittleEndian ? 0 : 1, Expr, + static_cast(PPC::fixup_ppc_pcrel34))); + return 0; + } return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits; } diff --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h --- a/llvm/lib/Target/PowerPC/PPC.h +++ b/llvm/lib/Target/PowerPC/PPC.h @@ -98,24 +98,28 @@ /// the function's picbase, e.g. lo16(symbol-picbase). MO_PIC_FLAG = 2, + /// MO_PCREL_FLAG - If this bit is set, the symbol reference is relative to + /// the current instruction address(pc), e.g., var@pcrel. Fixup is VK_PCREL. + MO_PCREL_FLAG = 4, + /// The next are not flags but distinct values. - MO_ACCESS_MASK = 0xf0, + MO_ACCESS_MASK = 0xf00, /// MO_LO, MO_HA - lo16(symbol) and ha16(symbol) - MO_LO = 1 << 4, - MO_HA = 2 << 4, + MO_LO = 1 << 8, + MO_HA = 2 << 8, - MO_TPREL_LO = 4 << 4, - MO_TPREL_HA = 3 << 4, + MO_TPREL_LO = 4 << 8, + MO_TPREL_HA = 3 << 8, /// These values identify relocations on immediates folded /// into memory operations. - MO_DTPREL_LO = 5 << 4, - MO_TLSLD_LO = 6 << 4, - MO_TOC_LO = 7 << 4, + MO_DTPREL_LO = 5 << 8, + MO_TLSLD_LO = 6 << 8, + MO_TOC_LO = 7 << 8, // Symbol for VK_PPC_TLS fixup attached to an ADD instruction - MO_TLS = 8 << 4 + MO_TLS = 8 << 8 }; } // end namespace PPCII diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -296,6 +296,10 @@ return true; } + bool SelectAddrPCRel(SDValue N, SDValue &Base) { + return PPCLowering->SelectAddressPCRel(N, Base); + } + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. It is always correct to compute the value into /// a register. The case of adding a (possibly relocatable) constant to a diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -428,6 +428,11 @@ /// lower (IDX=1) half of v4f32 to v2f64. FP_EXTEND_HALF, + /// MAT_PCREL_ADDR = Materialize a PC Relative address. This can be done + /// either through an add like PADDI or through a PC Relative load like + /// PLD. + MAT_PCREL_ADDR, + /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a /// byte-swapping store instruction. It byte-swaps the low "Type" bits of /// the GPRC input, then stores it through Ptr. Type can be either i16 or @@ -730,6 +735,10 @@ bool SelectAddressRegRegOnly(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG) const; + /// SelectAddressPCRel - Represent the specified address as pc relative to + /// be represented as [pc+imm] + bool SelectAddressPCRel(SDValue N, SDValue &Base) const; + Sched::Preference getSchedulingPreference(SDNode *N) const override; /// LowerOperation - Provide custom lowering hooks for some operations. diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1480,6 +1480,7 @@ case PPCISD::EXTSWSLI: return "PPCISD::EXTSWSLI"; case PPCISD::LD_VSX_LH: return "PPCISD::LD_VSX_LH"; case PPCISD::FP_EXTEND_HALF: return "PPCISD::FP_EXTEND_HALF"; + case PPCISD::MAT_PCREL_ADDR: return "PPCISD::MAT_PCREL_ADDR"; case PPCISD::LD_SPLAT: return "PPCISD::LD_SPLAT"; } return nullptr; @@ -2346,6 +2347,11 @@ bool PPCTargetLowering::SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG, unsigned EncodingAlignment) const { + // If we have a PC Relative target flag don't select as [reg+reg]. It will be + // a [pc+imm]. + if (SelectAddressPCRel(N, Base)) + return false; + int16_t imm = 0; if (N.getOpcode() == ISD::ADD) { // Is there any SPE load/store (f64), which can't handle 16bit offset? @@ -2435,6 +2441,12 @@ unsigned EncodingAlignment) const { // FIXME dl should come from parent load or store, not from address SDLoc dl(N); + + // If we have a PC Relative target flag don't select as [reg+imm]. It will be + // a [pc+imm]. + if (SelectAddressPCRel(N, Base)) + return false; + // If this can be more profitably realized as r+r, fail. if (SelectAddressRegReg(N, Disp, Base, DAG, EncodingAlignment)) return false; @@ -2558,6 +2570,21 @@ return true; } +/// Returns true if this address is a PC Relative address. +/// PC Relative addresses are marked with the flag PPCII::MO_PCREL_FLAG. +bool PPCTargetLowering::SelectAddressPCRel(SDValue N, SDValue &Base) const { + ConstantPoolSDNode *ConstPoolNode = + dyn_cast(N.getNode()); + bool HasFlag = ConstPoolNode && + ConstPoolNode->getTargetFlags() == PPCII::MO_PCREL_FLAG; + bool HasNode = N.getOpcode() == PPCISD::MAT_PCREL_ADDR; + if (HasFlag || HasNode) { + Base = N; + return true; + } + return false; +} + /// Returns true if we should use a direct load into vector instruction /// (such as lxsd or lfd), instead of a load into gpr + direct move sequence. static bool usePartialVectorLoads(SDNode *N, const PPCSubtarget& ST) { @@ -2763,6 +2790,15 @@ // 64-bit SVR4 ABI and AIX ABI code are always position-independent. // The actual address of the GlobalValue is stored in the TOC. if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) { + if (Subtarget.hasPCRelativeMemops()) { + SDLoc DL(CP); + EVT Ty = getPointerTy(DAG.getDataLayout()); + SDValue ConstPool = DAG.getTargetConstantPool(C, Ty, + CP->getAlignment(), + CP->getOffset(), + PPCII::MO_PCREL_FLAG); + return DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, ConstPool); + } setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0); return getTOCEntry(DAG, SDLoc(CP), GA); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -2046,7 +2046,9 @@ PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { using namespace PPCII; static const std::pair TargetFlags[] = { - {MO_PLT, "ppc-plt"}, {MO_PIC_FLAG, "ppc-pic"}}; + {MO_PLT, "ppc-plt"}, + {MO_PIC_FLAG, "ppc-pic"}, + {MO_PCREL_FLAG, "ppc-pcrel"}}; return makeArrayRef(TargetFlags); } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -319,6 +319,9 @@ def PPCdynalloc : SDNode<"PPCISD::DYNALLOC", SDTDynOp, [SDNPHasChain]>; def PPCdynareaoffset : SDNode<"PPCISD::DYNAREAOFFSET", SDTDynAreaOp, [SDNPHasChain]>; +// PC Relative Specific Nodes +def PPCmatpcreladdr : SDNode<"PPCISD::MAT_PCREL_ADDR", SDTIntUnaryOp, []>; + //===----------------------------------------------------------------------===// // PowerPC specific transformation functions and pattern fragments. // @@ -730,6 +733,7 @@ } def s34imm : Operand { let PrintMethod = "printS34ImmOperand"; + let EncoderMethod = "getImm34Encoding"; let ParserMatchClass = PPCS34ImmAsmOperand; let DecoderMethod = "decodeSImmOperand<34>"; } @@ -977,6 +981,9 @@ /// This is just the offset part of iaddr, used for preinc. def iaddroff : ComplexPattern; +// PC Relative Address +def pcreladdr : ComplexPattern; + //===----------------------------------------------------------------------===// // PowerPC Instruction Predicate Definitions. def In32BitMode : Predicate<"!PPCSubTarget->isPPC64()">; diff --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td --- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -337,3 +337,43 @@ } } +// TODO: We have an added complexity of 500 here. This is only a temporary +// solution to have tablegen consider these patterns first. The way we do +// addressing for PowerPC is complex depending on available D form, X form, or +// aligned D form loads/stores like DS and DQ forms. The prefixed +// instructions in this file also add additional PC Relative loads/stores +// and D form loads/stores with 34 bit immediates. It is very difficult to force +// instruction selection to consistently pick these first without the current +// added complexity. Once pc-relative implementation is complete, a set of +// follow-up patches will address this refactoring and the AddedComplexity will +// be removed. +let Predicates = [PCRelativeMemops], AddedComplexity = 500 in { + // Load f32 + def : Pat<(f32 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLFSpc $addr, 0)>; + + // Load f64 + def : Pat<(f64 (extloadf32 (PPCmatpcreladdr pcreladdr:$addr))), + (COPY_TO_REGCLASS (PLFSpc $addr, 0), VSFRC)>; + def : Pat<(f64 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLFDpc $addr, 0)>; + + // Load f128 + def : Pat<(f128 (load (PPCmatpcreladdr pcreladdr:$addr))), + (COPY_TO_REGCLASS (PLXVpc $addr, 0), VRRC)>; + + // Load v4i32 + def : Pat<(v4i32 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + + // Load v2i64 + def : Pat<(v2i64 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + + // Load v4f32 + def : Pat<(v4f32 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + + // Load v2f64 + def : Pat<(v2f64 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + + // If the PPCmatpcreladdr node is not caught by any other pattern it should be + // caught here and turned into a paddi instruction to materialize the address. + def : Pat<(PPCmatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>; +} + diff --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp --- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -78,8 +78,10 @@ break; } - if (MO.getTargetFlags() == PPCII::MO_PLT) + if (MO.getTargetFlags() == PPCII::MO_PLT) RefKind = MCSymbolRefExpr::VK_PLT; + else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) + RefKind = MCSymbolRefExpr::VK_PCREL; const MachineInstr *MI = MO.getParent(); diff --git a/llvm/test/CodeGen/PowerPC/constant-pool.ll b/llvm/test/CodeGen/PowerPC/constant-pool.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/constant-pool.ll @@ -0,0 +1,92 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=future -enable-ppc-quad-precision -ppc-asm-full-reg-names \ +; RUN: < %s | FileCheck %s + + define float @FloatConstantPool() { +; CHECK-LABEL: FloatConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plfs f1, .LCPI0_0@PCREL(0), 1 +entry: + ret float 0x380FFFF840000000 +} + + define double @DoubleConstantPool() { +; CHECK-LABEL: DoubleConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plfd f1, .LCPI1_0@PCREL(0), 1 +entry: + ret double 2.225070e-308 +} + + define ppc_fp128 @LongDoubleConstantPool() { +; CHECK-LABEL: LongDoubleConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plfd f1, .LCPI2_0@PCREL(0), 1 +; CHECK-NEXT: plfd f2, .LCPI2_1@PCREL(0), 1 +entry: + ret ppc_fp128 0xM03600000DBA876CC800D16974FD9D27B +} + + define fp128 @__Float128ConstantPool() { +; CHECK-LABEL: __Float128ConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI3_0@PCREL(0), 1 +entry: + ret fp128 0xL00000000000000003C00FFFFC5D02B3A +} + + define <16 x i8> @VectorCharConstantPool() { +; CHECK-LABEL: VectorCharConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI4_0@PCREL(0), 1 +entry: + ret <16 x i8> +} + + define <8 x i16> @VectorShortConstantPool() { +; CHECK-LABEL: VectorShortConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI5_0@PCREL(0), 1 +entry: + ret <8 x i16> +} + + define <4 x i32> @VectorIntConstantPool() { +; CHECK-LABEL: VectorIntConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI6_0@PCREL(0), 1 +entry: + ret <4 x i32> +} + + define <2 x i64> @VectorLongLongConstantPool() { +; CHECK-LABEL: VectorLongLongConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI7_0@PCREL(0), 1 +entry: + ret <2 x i64> +} + + define <1 x i128> @VectorInt128ConstantPool() { +; CHECK-LABEL: VectorInt128ConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI8_0@PCREL(0), 1 +entry: + ret <1 x i128> +} + + define <4 x float> @VectorFloatConstantPool() { +; CHECK-LABEL: VectorFloatConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI9_0@PCREL(0), 1 +entry: + ret <4 x float> +} + + define <2 x double> @VectorDoubleConstantPool() { +; CHECK-LABEL: VectorDoubleConstantPool: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: plxv vs34, .LCPI10_0@PCREL(0), 1 +entry: + ret <2 x double> +} diff --git a/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-leaf.ll b/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-leaf.ll --- a/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-leaf.ll +++ b/llvm/test/CodeGen/PowerPC/pcrel-call-linkage-leaf.ll @@ -162,12 +162,9 @@ define dso_local double @UsesX2AsConstPoolTOC() local_unnamed_addr { ; CHECK-S-LABEL: UsesX2AsConstPoolTOC: -; CHECK-S: addis r2, r12, .TOC.-.Lfunc_gep7@ha -; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep7@l -; CHECK-S: .localentry UsesX2AsConstPoolTOC, .Lfunc_lep7-.Lfunc_gep7 +; CHECK-S-NOT: .localentry ; CHECK-S: # %bb.0: # %entry -; CHECK-S-NEXT: addis r3, r2, .LCPI7_0@toc@ha -; CHECK-S-NEXT: lfd f1, .LCPI7_0@toc@l(r3) +; CHECK-S-NEXT: plfd f1, .LCPI7_0@PCREL(0), 1 ; CHECK-S-NEXT: blr entry: ret double 0x404124A4EBDD334C diff --git a/llvm/test/CodeGen/PowerPC/pcrel.ll b/llvm/test/CodeGen/PowerPC/pcrel.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/pcrel.ll @@ -0,0 +1,23 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=future -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-S +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=future -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr \ +; RUN: --filetype=obj < %s | \ +; RUN: llvm-objdump --mcpu=future -dr - | FileCheck %s --check-prefix=CHECK-O + +; Constant Pool Index. +; CHECK-S-LABEL: ConstPool +; CHECK-S: plfd f1, .LCPI0_0@PCREL(0), 1 +; CHECK-S: blr + +; CHECK-O-LABEL: ConstPool +; CHECK-O: plfd 1, 0(0), 1 +; CHECK-O-NEXT: R_PPC64_PCREL34 .rodata.cst8 +; CHECK-O: blr +define dso_local double @ConstPool() local_unnamed_addr { + entry: + ret double 0x406ECAB439581062 +} + +