forked from OSchip/llvm-project
[PowerPC][Future] Initial support for PCRel addressing for constant pool loads
Add initial support for PC Relative addressing for constant pool loads. This includes adding a new relocation for @pcrel and adding a new PowerPC flag to identify PC relative addressing. Differential Revision: https://reviews.llvm.org/D74486
This commit is contained in:
parent
015dee1ac8
commit
75828ef615
|
@ -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_TPREL16_HIGHA, 113)
|
|||
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)
|
||||
|
|
|
@ -45,6 +45,8 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||
return Value & 0xffff;
|
||||
case PPC::fixup_ppc_half16ds:
|
||||
return Value & 0xfffc;
|
||||
case PPC::fixup_ppc_pcrel34:
|
||||
return Value & 0x3ffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +67,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
|
|||
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 @@ public:
|
|||
{ "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 @@ public:
|
|||
{ "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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -128,6 +128,9 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
|
|||
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;
|
||||
|
|
|
@ -40,6 +40,9 @@ enum Fixups {
|
|||
/// 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.
|
||||
|
|
|
@ -400,9 +400,13 @@ void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
|
|||
|
||||
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,
|
||||
|
|
|
@ -104,6 +104,20 @@ unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &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<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
|
@ -175,6 +189,16 @@ PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
|
|||
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<MCSymbolRefExpr>(Expr);
|
||||
assert(SRE->getKind() == MCSymbolRefExpr::VK_PCREL &&
|
||||
"VariantKind must be VK_PCREL");
|
||||
Fixups.push_back(
|
||||
MCFixup::create(IsLittleEndian ? 0 : 1, Expr,
|
||||
static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
|
||||
return 0;
|
||||
}
|
||||
return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned long getImm34Encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
|
|
@ -98,24 +98,28 @@ namespace llvm {
|
|||
/// 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
|
||||
|
||||
|
|
|
@ -296,6 +296,10 @@ namespace {
|
|||
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
|
||||
|
|
|
@ -1480,6 +1480,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||
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::SelectAddressEVXRegReg(SDValue N, SDValue &Base,
|
|||
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 @@ bool PPCTargetLowering::SelectAddressRegImm(SDValue N, SDValue &Disp,
|
|||
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 @@ bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base,
|
|||
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<ConstantPoolSDNode>(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 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op,
|
|||
// 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);
|
||||
|
|
|
@ -428,6 +428,11 @@ namespace llvm {
|
|||
/// 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 @@ namespace llvm {
|
|||
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.
|
||||
|
|
|
@ -2046,7 +2046,9 @@ ArrayRef<std::pair<unsigned, const char *>>
|
|||
PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
|
||||
using namespace PPCII;
|
||||
static const std::pair<unsigned, const char *> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -319,6 +319,9 @@ def SDTDynAreaOp : SDTypeProfile<1, 1, []>;
|
|||
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 PPCS34ImmAsmOperand : AsmOperandClass {
|
|||
}
|
||||
def s34imm : Operand<i64> {
|
||||
let PrintMethod = "printS34ImmOperand";
|
||||
let EncoderMethod = "getImm34Encoding";
|
||||
let ParserMatchClass = PPCS34ImmAsmOperand;
|
||||
let DecoderMethod = "decodeSImmOperand<34>";
|
||||
}
|
||||
|
@ -977,6 +981,9 @@ def addr : ComplexPattern<iPTR, 1, "SelectAddr",[], []>;
|
|||
/// This is just the offset part of iaddr, used for preinc.
|
||||
def iaddroff : ComplexPattern<iPTR, 1, "SelectAddrImmOffs", [], []>;
|
||||
|
||||
// PC Relative Address
|
||||
def pcreladdr : ComplexPattern<iPTR, 1, "SelectAddrPCRel", [], []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PowerPC Instruction Predicate Definitions.
|
||||
def In32BitMode : Predicate<"!PPCSubTarget->isPPC64()">;
|
||||
|
|
|
@ -337,3 +337,43 @@ let Predicates = [PrefixInstrs] in {
|
|||
}
|
||||
}
|
||||
|
||||
// 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)>;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,10 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
|
|||
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();
|
||||
|
||||
|
|
|
@ -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> <i8 -128, i8 -127, i8 -126, i8 -125, i8 -124, i8 -123, i8 -122, i8 -121, i8 -120, i8 -119, i8 -118, i8 -117, i8 -116, i8 -115, i8 -114, i8 -113>
|
||||
}
|
||||
|
||||
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> <i16 -32768, i16 -32767, i16 -32766, i16 -32765, i16 -32764, i16 -32763, i16 -32762, i16 -32761>
|
||||
}
|
||||
|
||||
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> <i32 -2147483648, i32 -2147483647, i32 -2147483646, i32 -2147483645>
|
||||
}
|
||||
|
||||
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> <i64 -9223372036854775808, i64 -9223372036854775807>
|
||||
}
|
||||
|
||||
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> <i128 -27670116110564327424>
|
||||
}
|
||||
|
||||
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> <float 0x380FFFF840000000, float 0x380FFF57C0000000, float 0x3843FFFB20000000, float 0x3843FF96C0000000>
|
||||
}
|
||||
|
||||
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> <double 2.225070e-308, double 2.225000e-308>
|
||||
}
|
|
@ -162,12 +162,9 @@ entry:
|
|||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue