Index: llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def =================================================================== --- llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ 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) Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -46,6 +46,8 @@ return Value & 0xffff; case PPC::fixup_ppc_half16ds: return Value & 0xfffc; + case PPC::fixup_ppc_pcrel34: + return Value & 0x3ffffffff; } } @@ -68,6 +70,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: @@ -99,6 +102,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] = { @@ -110,6 +114,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 } }; Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -125,6 +125,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; Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h +++ 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. Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ 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, Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h +++ 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; Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ 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; } Index: llvm/lib/Target/PowerPC/PPC.h =================================================================== --- llvm/lib/Target/PowerPC/PPC.h +++ 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 = 16, + /// 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 Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -297,6 +297,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 Index: llvm/lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.h +++ llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -432,6 +432,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 @@ -734,6 +739,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. Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1448,6 +1448,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; @@ -2314,6 +2315,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? @@ -2404,6 +2410,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; @@ -2527,6 +2539,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) { @@ -2732,6 +2759,16 @@ // 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); + SDValue MatAddr = DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, ConstPool); + return MatAddr; + } setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0); return getTOCEntry(DAG, SDLoc(CP), GA); Index: llvm/lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ 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); } Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -322,6 +322,9 @@ def PPCdynalloc : SDNode<"PPCISD::DYNALLOC", SDTDynOp, [SDNPHasChain]>; def PPCdynareaoffset : SDNode<"PPCISD::DYNAREAOFFSET", SDTDynAreaOp, [SDNPHasChain]>; +// PC Relative Specific Nodes +def MATpcreladdr : SDNode<"PPCISD::MAT_PCREL_ADDR", SDTIntUnaryOp, []>; + //===----------------------------------------------------------------------===// // PowerPC specific transformation functions and pattern fragments. // @@ -733,6 +736,7 @@ } def s34imm : Operand { let PrintMethod = "printS34ImmOperand"; + let EncoderMethod = "getImm34Encoding"; let ParserMatchClass = PPCS34ImmAsmOperand; let DecoderMethod = "decodeSImmOperand<34>"; } @@ -976,6 +980,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()">; Index: llvm/lib/Target/PowerPC/PPCInstrPrefix.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -337,3 +337,42 @@ } } +// TODO: We have an added complexity of 500 here. This is only a temporatry +// 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. For the future we should refactor the addessing selection +// on PowerPC so that this AddedComplexity=500 will not be required. +let Predicates = [PCRelativeMemops], AddedComplexity = 500 in { + // Load f32 + def : Pat<(f32 (load (MATpcreladdr pcreladdr:$cp))), (PLFSpc $cp, 0)>; + + // Load f64 + def : Pat<(f64 (extloadf32 (MATpcreladdr pcreladdr:$cp))), + (COPY_TO_REGCLASS (PLFSpc $cp, 0), VSFRC)>; + def : Pat<(f64 (load (MATpcreladdr pcreladdr:$cp))), (PLFDpc $cp, 0)>; + + // Load f128 + def : Pat<(f128 (load (MATpcreladdr pcreladdr:$cp))), + (COPY_TO_REGCLASS (PLXVpc $cp, 0), VRRC)>; + + // Load v4i32 + def : Pat<(v4i32 (load (MATpcreladdr pcreladdr:$cp))), (PLXVpc $cp, 0)>; + + // Load v2i64 + def : Pat<(v2i64 (load (MATpcreladdr pcreladdr:$cp))), (PLXVpc $cp, 0)>; + + // Load v4f32 + def : Pat<(v4f32 (load (MATpcreladdr pcreladdr:$cp))), (PLXVpc $cp, 0)>; + + // Load v2f64 + def : Pat<(v2f64 (load (MATpcreladdr pcreladdr:$cp))), (PLXVpc $cp, 0)>; + + // If the MATpcreladdr 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<(MATpcreladdr pcreladdr:$cp), (PADDI8pc 0, $cp)>; +} + Index: llvm/lib/Target/PowerPC/PPCMCInstLower.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCMCInstLower.cpp +++ 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 MachineFunction *MF = MO.getParent()->getParent()->getParent(); const Module *M = MF->getFunction().getParent(); Index: llvm/test/CodeGen/PowerPC/constant-pool.ll =================================================================== --- /dev/null +++ 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> +} Index: llvm/test/CodeGen/PowerPC/csr-split.ll =================================================================== --- llvm/test/CodeGen/PowerPC/csr-split.ll +++ llvm/test/CodeGen/PowerPC/csr-split.ll @@ -1,5 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -verify-machineinstrs -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names \ +; RUN: -mtriple=powerpc64le-unknown-linux-gnu -mcpu=future < %s | FileCheck %s --check-prefix=CHECK-FUTURE +; RUN: llc -verify-machineinstrs -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names \ ; RUN: -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s --check-prefix=CHECK-PWR9 ; RUN: llc -verify-machineinstrs -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names \ ; RUN: -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s @@ -9,6 +11,34 @@ @a = dso_local local_unnamed_addr global i32 0, align 4 define dso_local signext i32 @test1(i32* %b) local_unnamed_addr { +; CHECK-FUTURE-LABEL: test1: +; CHECK-FUTURE: # %bb.0: # %entry +; CHECK-FUTURE-NEXT: mflr r0 +; CHECK-FUTURE-NEXT: .cfi_def_cfa_offset 48 +; CHECK-FUTURE-NEXT: .cfi_offset lr, 16 +; CHECK-FUTURE-NEXT: .cfi_offset r30, -16 +; CHECK-FUTURE-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-FUTURE-NEXT: std r0, 16(r1) +; CHECK-FUTURE-NEXT: stdu r1, -48(r1) +; CHECK-FUTURE-NEXT: addis r4, r2, a@toc@ha +; CHECK-FUTURE-NEXT: lwa r4, a@toc@l(r4) +; CHECK-FUTURE-NEXT: mr r30, r3 +; CHECK-FUTURE-NEXT: cmpld r4, r3 +; CHECK-FUTURE-NEXT: # implicit-def: $r3 +; CHECK-FUTURE-NEXT: bne cr0, .LBB0_2 +; CHECK-FUTURE-NEXT: # %bb.1: # %if.then +; CHECK-FUTURE-NEXT: bl callVoid +; CHECK-FUTURE-NEXT: nop +; CHECK-FUTURE-NEXT: mr r3, r30 +; CHECK-FUTURE-NEXT: bl callNonVoid@notoc +; CHECK-FUTURE-NEXT: .LBB0_2: # %if.end +; CHECK-FUTURE-NEXT: extsw r3, r3 +; CHECK-FUTURE-NEXT: addi r1, r1, 48 +; CHECK-FUTURE-NEXT: ld r0, 16(r1) +; CHECK-FUTURE-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-FUTURE-NEXT: mtlr r0 +; CHECK-FUTURE-NEXT: blr +; ; CHECK-PWR9-LABEL: test1: ; CHECK-PWR9: # %bb.0: # %entry ; CHECK-PWR9-NEXT: mflr r0 @@ -88,6 +118,37 @@ declare signext i32 @callNonVoid(i32*) local_unnamed_addr define dso_local signext i32 @test2(i32* %p1) local_unnamed_addr { +; CHECK-FUTURE-LABEL: test2: +; CHECK-FUTURE: # %bb.0: # %entry +; CHECK-FUTURE-NEXT: mflr r0 +; CHECK-FUTURE-NEXT: .cfi_def_cfa_offset 48 +; CHECK-FUTURE-NEXT: .cfi_offset lr, 16 +; CHECK-FUTURE-NEXT: .cfi_offset r30, -16 +; CHECK-FUTURE-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-FUTURE-NEXT: std r0, 16(r1) +; CHECK-FUTURE-NEXT: stdu r1, -48(r1) +; CHECK-FUTURE-NEXT: mr r30, r3 +; CHECK-FUTURE-NEXT: cmpldi r3, 0 +; CHECK-FUTURE-NEXT: li r3, 0 +; CHECK-FUTURE-NEXT: beq cr0, .LBB1_3 +; CHECK-FUTURE-NEXT: # %bb.1: # %if.end +; CHECK-FUTURE-NEXT: addis r4, r2, a@toc@ha +; CHECK-FUTURE-NEXT: lwa r4, a@toc@l(r4) +; CHECK-FUTURE-NEXT: cmpld r4, r30 +; CHECK-FUTURE-NEXT: bne cr0, .LBB1_3 +; CHECK-FUTURE-NEXT: # %bb.2: # %if.then2 +; CHECK-FUTURE-NEXT: bl callVoid +; CHECK-FUTURE-NEXT: nop +; CHECK-FUTURE-NEXT: mr r3, r30 +; CHECK-FUTURE-NEXT: bl callNonVoid@notoc +; CHECK-FUTURE-NEXT: .LBB1_3: # %return +; CHECK-FUTURE-NEXT: extsw r3, r3 +; CHECK-FUTURE-NEXT: addi r1, r1, 48 +; CHECK-FUTURE-NEXT: ld r0, 16(r1) +; CHECK-FUTURE-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-FUTURE-NEXT: mtlr r0 +; CHECK-FUTURE-NEXT: blr +; ; CHECK-PWR9-LABEL: test2: ; CHECK-PWR9: # %bb.0: # %entry ; CHECK-PWR9-NEXT: mflr r0 @@ -174,6 +235,36 @@ define dso_local i8* @test3(i8** nocapture %p1, i8 zeroext %p2) local_unnamed_addr { +; CHECK-FUTURE-LABEL: test3: +; CHECK-FUTURE: .localentry test3, 1 +; CHECK-FUTURE-NEXT: # %bb.0: # %entry +; CHECK-FUTURE-NEXT: mflr r0 +; CHECK-FUTURE-NEXT: .cfi_def_cfa_offset 64 +; CHECK-FUTURE-NEXT: .cfi_offset lr, 16 +; CHECK-FUTURE-NEXT: .cfi_offset r29, -24 +; CHECK-FUTURE-NEXT: .cfi_offset r30, -16 +; CHECK-FUTURE-NEXT: std r29, -24(r1) # 8-byte Folded Spill +; CHECK-FUTURE-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-FUTURE-NEXT: std r0, 16(r1) +; CHECK-FUTURE-NEXT: stdu r1, -64(r1) +; CHECK-FUTURE-NEXT: ld r30, 0(r3) +; CHECK-FUTURE-NEXT: cmpldi r30, 0 +; CHECK-FUTURE-NEXT: beq cr0, .LBB2_2 +; CHECK-FUTURE-NEXT: # %bb.1: # %land.rhs +; CHECK-FUTURE-NEXT: mr r29, r3 +; CHECK-FUTURE-NEXT: clrldi r4, r4, 32 +; CHECK-FUTURE-NEXT: mr r3, r30 +; CHECK-FUTURE-NEXT: bl bar@notoc +; CHECK-FUTURE-NEXT: std r3, 0(r29) +; CHECK-FUTURE-NEXT: .LBB2_2: # %land.end +; CHECK-FUTURE-NEXT: mr r3, r30 +; CHECK-FUTURE-NEXT: addi r1, r1, 64 +; CHECK-FUTURE-NEXT: ld r0, 16(r1) +; CHECK-FUTURE-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-FUTURE-NEXT: ld r29, -24(r1) # 8-byte Folded Reload +; CHECK-FUTURE-NEXT: mtlr r0 +; CHECK-FUTURE-NEXT: blr +; ; CHECK-PWR9-LABEL: test3: ; CHECK-PWR9: # %bb.0: # %entry ; CHECK-PWR9-NEXT: mflr r0 Index: llvm/test/CodeGen/PowerPC/pcrel.ll =================================================================== --- /dev/null +++ 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 +} + +