forked from OSchip/llvm-project
Materialize GA addresses with movw + movt pairs for Darwin in PIC mode. e.g.
movw r0, :lower16:(L_foo$non_lazy_ptr-(LPC0_0+4)) movt r0, :upper16:(L_foo$non_lazy_ptr-(LPC0_0+4)) LPC0_0: add r0, pc, r0 It's not yet enabled by default as some tests are failing. I suspect bugs in down stream tools. llvm-svn: 123619
This commit is contained in:
parent
67431d7943
commit
dfce83c8f5
|
@ -20,6 +20,7 @@
|
|||
#include "ARMBaseRegisterInfo.h"
|
||||
#include "ARMConstantPoolValue.h"
|
||||
#include "ARMMachineFunctionInfo.h"
|
||||
#include "ARMMCExpr.h"
|
||||
#include "ARMTargetMachine.h"
|
||||
#include "ARMTargetObjectFile.h"
|
||||
#include "InstPrinter/ARMInstPrinter.h"
|
||||
|
@ -537,6 +538,25 @@ getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
|
|||
return MCSymbolRefExpr::VK_None;
|
||||
}
|
||||
|
||||
MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV) {
|
||||
bool isIndirect = Subtarget->isTargetDarwin() &&
|
||||
Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
|
||||
if (!isIndirect)
|
||||
return Mang->getSymbol(GV);
|
||||
|
||||
// FIXME: Remove this when Darwin transition to @GOT like syntax.
|
||||
MCSymbol *MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
|
||||
MachineModuleInfoMachO &MMIMachO =
|
||||
MMI->getObjFileInfo<MachineModuleInfoMachO>();
|
||||
MachineModuleInfoImpl::StubValueTy &StubSym =
|
||||
GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) :
|
||||
MMIMachO.getGVStubEntry(MCSym);
|
||||
if (StubSym.getPointer() == 0)
|
||||
StubSym = MachineModuleInfoImpl::
|
||||
StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
|
||||
return MCSym;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::
|
||||
EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
|
||||
int Size = TM.getTargetData()->getTypeAllocSize(MCPV->getType());
|
||||
|
@ -553,23 +573,7 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
|
|||
MCSym = GetBlockAddressSymbol(ACPV->getBlockAddress());
|
||||
} else if (ACPV->isGlobalValue()) {
|
||||
const GlobalValue *GV = ACPV->getGV();
|
||||
bool isIndirect = Subtarget->isTargetDarwin() &&
|
||||
Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
|
||||
if (!isIndirect)
|
||||
MCSym = Mang->getSymbol(GV);
|
||||
else {
|
||||
// FIXME: Remove this when Darwin transition to @GOT like syntax.
|
||||
MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
|
||||
|
||||
MachineModuleInfoMachO &MMIMachO =
|
||||
MMI->getObjFileInfo<MachineModuleInfoMachO>();
|
||||
MachineModuleInfoImpl::StubValueTy &StubSym =
|
||||
GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) :
|
||||
MMIMachO.getGVStubEntry(MCSym);
|
||||
if (StubSym.getPointer() == 0)
|
||||
StubSym = MachineModuleInfoImpl::
|
||||
StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
|
||||
}
|
||||
MCSym = GetARMGVSymbol(GV);
|
||||
} else {
|
||||
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
|
||||
MCSym = GetExternalSymbolSymbol(ACPV->getSymbol());
|
||||
|
@ -737,7 +741,8 @@ void ARMAsmPrinter::EmitPatchedInstruction(const MachineInstr *MI,
|
|||
}
|
||||
|
||||
void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
switch (MI->getOpcode()) {
|
||||
unsigned Opc = MI->getOpcode();
|
||||
switch (Opc) {
|
||||
default: break;
|
||||
case ARM::t2ADDrSPi:
|
||||
case ARM::t2ADDrSPi12:
|
||||
|
@ -858,6 +863,61 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
}
|
||||
return;
|
||||
}
|
||||
case ARM::MOVi16_pic_ga:
|
||||
case ARM::t2MOVi16_pic_ga: {
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(Opc == ARM::MOVi16_pic_ga ? ARM::MOVi16 : ARM::t2MOVi16);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
|
||||
|
||||
const GlobalValue *GV = MI->getOperand(1).getGlobal();
|
||||
MCSymbol *GVSym = GetARMGVSymbol(GV);
|
||||
const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
|
||||
MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
|
||||
getFunctionNumber(), MI->getOperand(2).getImm(),
|
||||
OutContext);
|
||||
const MCExpr *LabelSymExpr = MCSymbolRefExpr::Create(LabelSym, OutContext);
|
||||
const MCExpr *PCRelExpr =
|
||||
ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr,
|
||||
MCBinaryExpr::CreateAdd(LabelSymExpr,
|
||||
MCConstantExpr::Create(4, OutContext),
|
||||
OutContext), OutContext), OutContext);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
|
||||
// Add predicate operands.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
// Add 's' bit operand (always reg0 for this)
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
case ARM::MOVTi16_pic_ga:
|
||||
case ARM::t2MOVTi16_pic_ga: {
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(Opc==ARM::MOVTi16_pic_ga ? ARM::MOVTi16 : ARM::t2MOVTi16);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
|
||||
|
||||
const GlobalValue *GV = MI->getOperand(2).getGlobal();
|
||||
MCSymbol *GVSym = GetARMGVSymbol(GV);
|
||||
const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
|
||||
MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
|
||||
getFunctionNumber(), MI->getOperand(3).getImm(),
|
||||
OutContext);
|
||||
const MCExpr *LabelSymExpr = MCSymbolRefExpr::Create(LabelSym, OutContext);
|
||||
const MCExpr *PCRelExpr =
|
||||
ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr,
|
||||
MCBinaryExpr::CreateAdd(LabelSymExpr,
|
||||
MCConstantExpr::Create(4, OutContext),
|
||||
OutContext), OutContext), OutContext);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
|
||||
// Add predicate operands.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
// Add 's' bit operand (always reg0 for this)
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
case ARM::tPICADD: {
|
||||
// This is a pseudo op for a label + instruction sequence, which looks like:
|
||||
// LPC0:
|
||||
|
|
|
@ -101,6 +101,8 @@ public:
|
|||
|
||||
MCSymbol *GetARMSJLJEHLabel(void) const;
|
||||
|
||||
MCSymbol *GetARMGVSymbol(const GlobalValue *GV);
|
||||
|
||||
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
|
||||
/// the .s file.
|
||||
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
|
||||
|
|
|
@ -185,6 +185,18 @@ namespace ARMII {
|
|||
/// higher 16 bit of the address. Used only via movt instruction.
|
||||
MO_HI16,
|
||||
|
||||
/// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the PC relative address of the
|
||||
/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
|
||||
/// Used only via movw instruction.
|
||||
MO_LO16_NONLAZY_PIC,
|
||||
|
||||
/// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the PC relative address of the
|
||||
/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
|
||||
/// Used only via movt instruction.
|
||||
MO_HI16_NONLAZY_PIC,
|
||||
|
||||
/// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a
|
||||
/// call operand.
|
||||
MO_PLT
|
||||
|
|
|
@ -561,8 +561,14 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
|||
case ARMII::Size2Bytes: return 2; // Thumb1 instruction.
|
||||
case ARMII::SizeSpecial: {
|
||||
switch (Opc) {
|
||||
case ARM::MOVi16_pic_ga:
|
||||
case ARM::MOVTi16_pic_ga:
|
||||
case ARM::t2MOVi16_pic_ga:
|
||||
case ARM::t2MOVTi16_pic_ga:
|
||||
return 4;
|
||||
case ARM::MOVi32imm:
|
||||
case ARM::t2MOVi32imm:
|
||||
case ARM::MOV_pic_ga:
|
||||
return 8;
|
||||
case ARM::CONSTPOOL_ENTRY:
|
||||
// If this machine instr is a constant pool entry, its size is recorded as
|
||||
|
@ -977,7 +983,7 @@ static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI) {
|
|||
ARMConstantPoolValue *ACPV =
|
||||
static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);
|
||||
|
||||
unsigned PCLabelId = AFI->createConstPoolEntryUId();
|
||||
unsigned PCLabelId = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *NewCPV = 0;
|
||||
// FIXME: The below assumes PIC relocation model and that the function
|
||||
// is Thumb mode (t1 or t2). PCAdjustment would be 8 for ARM mode PIC, and
|
||||
|
|
|
@ -316,7 +316,7 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &MF) {
|
|||
}
|
||||
|
||||
/// The next UID to take is the first unused one.
|
||||
AFI->initConstPoolEntryUId(CPEMIs.size());
|
||||
AFI->initPICLabelUId(CPEMIs.size());
|
||||
|
||||
// Do the initial scan of the function, building up information about the
|
||||
// sizes of each block, the location of all the water, and finding all of the
|
||||
|
@ -1245,7 +1245,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &MF,
|
|||
|
||||
// No existing clone of this CPE is within range.
|
||||
// We will be generating a new clone. Get a UID for it.
|
||||
unsigned ID = AFI->createConstPoolEntryUId();
|
||||
unsigned ID = AFI->createPICLabelUId();
|
||||
|
||||
// Look for water where we can place this CPE.
|
||||
MachineBasicBlock *NewIsland = MF.CreateMachineBasicBlock();
|
||||
|
|
|
@ -765,13 +765,16 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
|
|||
|
||||
case ARM::MOVi32imm:
|
||||
case ARM::MOVCCi32imm:
|
||||
case ARM::MOV_pic_ga:
|
||||
case ARM::t2MOVi32imm:
|
||||
case ARM::t2MOVCCi32imm: {
|
||||
case ARM::t2MOVCCi32imm:
|
||||
case ARM::t2MOV_pic_ga: {
|
||||
unsigned PredReg = 0;
|
||||
ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
|
||||
unsigned DstReg = MI.getOperand(0).getReg();
|
||||
bool DstIsDead = MI.getOperand(0).isDead();
|
||||
bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm;
|
||||
bool isPIC_GA = (Opcode == ARM::t2MOV_pic_ga || Opcode == ARM::MOV_pic_ga);
|
||||
const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1);
|
||||
MachineInstrBuilder LO16, HI16;
|
||||
|
||||
|
@ -798,14 +801,24 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
|
|||
break;
|
||||
}
|
||||
|
||||
bool isThumb =
|
||||
(Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm);
|
||||
unsigned LO16Opc = 0;
|
||||
unsigned HI16Opc = 0;
|
||||
if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) {
|
||||
LO16Opc = ARM::t2MOVi16;
|
||||
HI16Opc = ARM::t2MOVTi16;
|
||||
} else if (Opcode == ARM::MOV_pic_ga) {
|
||||
LO16Opc = ARM::MOVi16_pic_ga;
|
||||
HI16Opc = ARM::MOVTi16_pic_ga;
|
||||
} else if (Opcode == ARM::t2MOV_pic_ga) {
|
||||
LO16Opc = ARM::t2MOVi16_pic_ga;
|
||||
HI16Opc = ARM::t2MOVTi16_pic_ga;
|
||||
} else {
|
||||
LO16Opc = ARM::MOVi16;
|
||||
HI16Opc = ARM::MOVTi16;
|
||||
}
|
||||
|
||||
LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
|
||||
TII->get(isThumb ? ARM::t2MOVi16 : ARM::MOVi16),
|
||||
DstReg);
|
||||
HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
|
||||
TII->get(isThumb ? ARM::t2MOVTi16 : ARM::MOVTi16))
|
||||
LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg);
|
||||
HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc))
|
||||
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
|
||||
.addReg(DstReg);
|
||||
|
||||
|
@ -815,16 +828,30 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
|
|||
unsigned Hi16 = (Imm >> 16) & 0xffff;
|
||||
LO16 = LO16.addImm(Lo16);
|
||||
HI16 = HI16.addImm(Hi16);
|
||||
} else if (isPIC_GA) {
|
||||
unsigned LabelId = MI.getOperand(2).getImm();
|
||||
const GlobalValue *GV = MO.getGlobal();
|
||||
unsigned TF = MO.getTargetFlags();
|
||||
LO16 = LO16.addGlobalAddress(GV, MO.getOffset(),
|
||||
TF | ARMII::MO_LO16_NONLAZY_PIC)
|
||||
.addImm(LabelId);
|
||||
HI16 = HI16.addGlobalAddress(GV, MO.getOffset(),
|
||||
TF | ARMII::MO_HI16_NONLAZY_PIC)
|
||||
.addImm(LabelId);
|
||||
} else {
|
||||
const GlobalValue *GV = MO.getGlobal();
|
||||
unsigned TF = MO.getTargetFlags();
|
||||
LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
|
||||
HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
|
||||
}
|
||||
|
||||
(*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
|
||||
(*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
|
||||
LO16.addImm(Pred).addReg(PredReg);
|
||||
HI16.addImm(Pred).addReg(PredReg);
|
||||
|
||||
if (!isPIC_GA) {
|
||||
LO16.addImm(Pred).addReg(PredReg);
|
||||
HI16.addImm(Pred).addReg(PredReg);
|
||||
}
|
||||
TransferImpOps(MI, LO16, HI16);
|
||||
MI.eraseFromParent();
|
||||
break;
|
||||
|
|
|
@ -517,7 +517,7 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, EVT VT) {
|
|||
|
||||
// Grab index.
|
||||
unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb() ? 4 : 8);
|
||||
unsigned Id = AFI->createConstPoolEntryUId();
|
||||
unsigned Id = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, Id,
|
||||
ARMCP::CPValue, PCAdj);
|
||||
unsigned Idx = MCP.getConstantPoolIndex(CPV, Align);
|
||||
|
|
|
@ -127,8 +127,7 @@ public:
|
|||
SDValue &Offset);
|
||||
bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
|
||||
|
||||
bool SelectAddrModePC(SDValue N, SDValue &Offset,
|
||||
SDValue &Label);
|
||||
bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
|
||||
|
||||
// Thumb Addressing Modes:
|
||||
bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
|
||||
|
|
|
@ -734,6 +734,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||
switch (Opcode) {
|
||||
default: return 0;
|
||||
case ARMISD::Wrapper: return "ARMISD::Wrapper";
|
||||
case ARMISD::WrapperPIC: return "ARMISD::WrapperPIC";
|
||||
case ARMISD::WrapperJT: return "ARMISD::WrapperJT";
|
||||
case ARMISD::CALL: return "ARMISD::CALL";
|
||||
case ARMISD::CALL_PRED: return "ARMISD::CALL_PRED";
|
||||
|
@ -1315,7 +1316,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
|||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
const GlobalValue *GV = G->getGlobal();
|
||||
// Create a constant pool entry for the callee address
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV,
|
||||
ARMPCLabelIndex,
|
||||
ARMCP::CPValue, 0);
|
||||
|
@ -1330,7 +1331,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
|||
const char *Sym = S->getSymbol();
|
||||
|
||||
// Create a constant pool entry for the callee address
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
|
||||
Sym, ARMPCLabelIndex, 0);
|
||||
// Get the address of the callee into a register
|
||||
|
@ -1352,7 +1353,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
|||
isLocalARMFunc = !Subtarget->isThumb() && (!isExt || !ARMInterworking);
|
||||
// tBX takes a register source operand.
|
||||
if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV,
|
||||
ARMPCLabelIndex,
|
||||
ARMCP::CPValue, 4);
|
||||
|
@ -1381,7 +1382,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
|||
// tBX takes a register source operand.
|
||||
const char *Sym = S->getSymbol();
|
||||
if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
|
||||
Sym, ARMPCLabelIndex, 4);
|
||||
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
|
||||
|
@ -1808,7 +1809,7 @@ SDValue ARMTargetLowering::LowerBlockAddress(SDValue Op,
|
|||
CPAddr = DAG.getTargetConstantPool(BA, PtrVT, 4);
|
||||
} else {
|
||||
unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||
ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(BA, ARMPCLabelIndex,
|
||||
ARMCP::CPBlockAddress,
|
||||
PCAdj);
|
||||
|
@ -1833,7 +1834,7 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
|
|||
unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV =
|
||||
new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex,
|
||||
ARMCP::CPValue, PCAdj, ARMCP::TLSGD, true);
|
||||
|
@ -1878,7 +1879,7 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA,
|
|||
if (GV->isDeclaration()) {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
// Initial exec model.
|
||||
unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||
ARMConstantPoolValue *CPV =
|
||||
|
@ -1949,36 +1950,55 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op,
|
|||
Result = DAG.getLoad(PtrVT, dl, Chain, Result,
|
||||
MachinePointerInfo::getGOT(), false, false, 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If we have T2 ops, we can materialize the address directly via movt/movw
|
||||
// pair. This is always cheaper.
|
||||
if (Subtarget->useMovt()) {
|
||||
// FIXME: Once remat is capable of dealing with instructions with register
|
||||
// operands, expand this into two nodes.
|
||||
return DAG.getNode(ARMISD::Wrapper, dl, PtrVT,
|
||||
DAG.getTargetGlobalAddress(GV, dl, PtrVT));
|
||||
} else {
|
||||
// If we have T2 ops, we can materialize the address directly via movt/movw
|
||||
// pair. This is always cheaper.
|
||||
if (Subtarget->useMovt()) {
|
||||
return DAG.getNode(ARMISD::Wrapper, dl, PtrVT,
|
||||
DAG.getTargetGlobalAddress(GV, dl, PtrVT));
|
||||
} else {
|
||||
SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||
return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr,
|
||||
MachinePointerInfo::getConstantPool(),
|
||||
false, false, 0);
|
||||
}
|
||||
SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||
return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr,
|
||||
MachinePointerInfo::getConstantPool(),
|
||||
false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
unsigned ARMPCLabelIndex = 0;
|
||||
EVT PtrVT = getPointerTy();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
|
||||
if (Subtarget->useMovt()) {
|
||||
// FIXME: Once remat is capable of dealing with instructions with register
|
||||
// operands, expand this into two nodes.
|
||||
if (RelocM != Reloc::PIC_)
|
||||
return DAG.getNode(ARMISD::Wrapper, dl, PtrVT,
|
||||
DAG.getTargetGlobalAddress(GV, dl, PtrVT));
|
||||
|
||||
// FIXME: Not a constant pool!
|
||||
unsigned PICLabelIndex = AFI->createPICLabelUId();
|
||||
SDValue PICLabel = DAG.getConstant(PICLabelIndex, MVT::i32);
|
||||
SDValue Result = DAG.getNode(ARMISD::WrapperPIC, dl, PtrVT,
|
||||
DAG.getTargetGlobalAddress(GV, dl, PtrVT),
|
||||
PICLabel);
|
||||
return DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
|
||||
}
|
||||
|
||||
unsigned ARMPCLabelIndex = 0;
|
||||
SDValue CPAddr;
|
||||
if (RelocM == Reloc::Static)
|
||||
if (RelocM == Reloc::Static) {
|
||||
CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4);
|
||||
else {
|
||||
ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
} else {
|
||||
ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb()?4:8);
|
||||
ARMConstantPoolValue *CPV =
|
||||
new ARMConstantPoolValue(GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj);
|
||||
|
@ -2009,7 +2029,7 @@ SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op,
|
|||
"GLOBAL OFFSET TABLE not implemented for non-ELF targets");
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
EVT PtrVT = getPointerTy();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||
|
@ -2062,7 +2082,7 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG,
|
|||
case Intrinsic::eh_sjlj_lsda: {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
unsigned ARMPCLabelIndex = AFI->createConstPoolEntryUId();
|
||||
unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
|
||||
EVT PtrVT = getPointerTy();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace llvm {
|
|||
|
||||
Wrapper, // Wrapper - A wrapper node for TargetConstantPool,
|
||||
// TargetExternalSymbol, and TargetGlobalAddress.
|
||||
WrapperPIC, // WrapperPIC - A wrapper node for TargetGlobalAddress in
|
||||
// PIC mode.
|
||||
WrapperJT, // WrapperJT - A wrapper node for TargetJumpTable
|
||||
|
||||
CALL, // Function call.
|
||||
|
|
|
@ -70,6 +70,7 @@ def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
|
|||
// Node definitions.
|
||||
def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>;
|
||||
def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>;
|
||||
def ARMWrapperPIC : SDNode<"ARMISD::WrapperPIC", SDTIntBinOp>;
|
||||
|
||||
def ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeqStart,
|
||||
[SDNPHasChain, SDNPOutGlue]>;
|
||||
|
@ -1930,7 +1931,10 @@ def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm_hilo16:$imm),
|
|||
let Inst{25} = 1;
|
||||
}
|
||||
|
||||
let Constraints = "$src = $Rd" in
|
||||
def MOVi16_pic_ga : PseudoInst<(outs GPR:$Rd),
|
||||
(ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>;
|
||||
|
||||
let Constraints = "$src = $Rd" in {
|
||||
def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm),
|
||||
DPFrm, IIC_iMOVi,
|
||||
"movt", "\t$Rd, $imm",
|
||||
|
@ -1947,6 +1951,11 @@ def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm),
|
|||
let Inst{25} = 1;
|
||||
}
|
||||
|
||||
def MOVTi16_pic_ga : PseudoInst<(outs GPR:$Rd),
|
||||
(ins GPR:$src, i32imm:$addr, pclabel:$id), IIC_iMOVi, []>;
|
||||
|
||||
} // Constraints
|
||||
|
||||
def : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>,
|
||||
Requires<[IsARM, HasV6T2]>;
|
||||
|
||||
|
@ -3363,11 +3372,17 @@ def Int_eh_sjlj_dispatchsetup :
|
|||
// This is a single pseudo instruction, the benefit is that it can be remat'd
|
||||
// as a single unit instead of having to handle reg inputs.
|
||||
// FIXME: Remove this when we can do generalized remat.
|
||||
let isReMaterializable = 1, isMoveImm = 1 in
|
||||
let isReMaterializable = 1, isMoveImm = 1 in {
|
||||
def MOVi32imm : PseudoInst<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVix2,
|
||||
[(set GPR:$dst, (arm_i32imm:$src))]>,
|
||||
Requires<[IsARM]>;
|
||||
|
||||
def MOV_pic_ga : PseudoInst<(outs GPR:$dst),
|
||||
(ins i32imm:$addr, pclabel:$id), IIC_iMOVix2,
|
||||
[(set GPR:$dst, (ARMWrapperPIC tglobaladdr:$addr, imm:$id))]>,
|
||||
Requires<[IsARM, UseMovt]>;
|
||||
} // isReMaterializable = 1, isMoveImm = 1 in
|
||||
|
||||
// ConstantPool, GlobalAddress, and JumpTable
|
||||
def : ARMPat<(ARMWrapper tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>,
|
||||
Requires<[IsARM, DontUseMovt]>;
|
||||
|
|
|
@ -1696,7 +1696,10 @@ def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi,
|
|||
let Inst{7-0} = imm{7-0};
|
||||
}
|
||||
|
||||
let Constraints = "$src = $Rd" in
|
||||
def t2MOVi16_pic_ga : PseudoInst<(outs rGPR:$Rd),
|
||||
(ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>;
|
||||
|
||||
let Constraints = "$src = $Rd" in {
|
||||
def t2MOVTi16 : T2I<(outs rGPR:$Rd),
|
||||
(ins rGPR:$src, i32imm_hilo16:$imm), IIC_iMOVi,
|
||||
"movt", "\t$Rd, $imm",
|
||||
|
@ -1718,6 +1721,10 @@ def t2MOVTi16 : T2I<(outs rGPR:$Rd),
|
|||
let Inst{7-0} = imm{7-0};
|
||||
}
|
||||
|
||||
def t2MOVTi16_pic_ga : PseudoInst<(outs rGPR:$Rd),
|
||||
(ins rGPR:$src, i32imm:$addr, pclabel:$id), IIC_iMOVi, []>;
|
||||
} // Constraints
|
||||
|
||||
def : T2Pat<(or rGPR:$src, 0xffff0000), (t2MOVTi16 rGPR:$src, 0xffff)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -3209,11 +3216,17 @@ def t2RFEIA : T2RFE<0b111010011001,
|
|||
// 32-bit immediate using movw + movt.
|
||||
// This is a single pseudo instruction to make it re-materializable.
|
||||
// FIXME: Remove this when we can do generalized remat.
|
||||
let isReMaterializable = 1, isMoveImm = 1 in
|
||||
let isReMaterializable = 1, isMoveImm = 1 in {
|
||||
def t2MOVi32imm : PseudoInst<(outs rGPR:$dst), (ins i32imm:$src), IIC_iMOVix2,
|
||||
[(set rGPR:$dst, (i32 imm:$src))]>,
|
||||
Requires<[IsThumb, HasV6T2]>;
|
||||
|
||||
def t2MOV_pic_ga : PseudoInst<(outs rGPR:$dst),
|
||||
(ins i32imm:$addr, pclabel:$id), IIC_iMOVix2,
|
||||
[(set rGPR:$dst, (ARMWrapperPIC tglobaladdr:$addr, imm:$id))]>,
|
||||
Requires<[IsThumb2, UseMovt]>;
|
||||
} // isReMaterializable = 1, isMoveImm = 1 in
|
||||
|
||||
// ConstantPool, GlobalAddress, and JumpTable
|
||||
def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>,
|
||||
Requires<[IsThumb2, DontUseMovt]>;
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace llvm {
|
|||
/// model is PIC.
|
||||
void Initialize(const MachineFunction &MF, bool isPIC) {
|
||||
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
ConstPoolId2AddrMap.resize(AFI->getNumConstPoolEntries());
|
||||
ConstPoolId2AddrMap.resize(AFI->getNumPICLabels());
|
||||
JumpTableId2AddrMap.resize(AFI->getNumJumpTables());
|
||||
IsPIC = isPIC;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ class ARMFunctionInfo : public MachineFunctionInfo {
|
|||
///
|
||||
unsigned JumpTableUId;
|
||||
|
||||
unsigned ConstPoolEntryUId;
|
||||
unsigned PICLabelUId;
|
||||
|
||||
/// VarArgsFrameIndex - FrameIndex for start of varargs area.
|
||||
int VarArgsFrameIndex;
|
||||
|
@ -104,8 +104,8 @@ public:
|
|||
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
|
||||
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
|
||||
GPRCS1Frames(0), GPRCS2Frames(0), DPRCSFrames(0),
|
||||
JumpTableUId(0), ConstPoolEntryUId(0), VarArgsFrameIndex(0),
|
||||
HasITBlocks(false) {}
|
||||
JumpTableUId(0), PICLabelUId(0),
|
||||
VarArgsFrameIndex(0), HasITBlocks(false) {}
|
||||
|
||||
explicit ARMFunctionInfo(MachineFunction &MF) :
|
||||
isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
|
||||
|
@ -116,8 +116,8 @@ public:
|
|||
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
|
||||
GPRCS1Frames(32), GPRCS2Frames(32), DPRCSFrames(32),
|
||||
SpilledCSRegs(MF.getTarget().getRegisterInfo()->getNumRegs()),
|
||||
JumpTableUId(0), ConstPoolEntryUId(0), VarArgsFrameIndex(0),
|
||||
HasITBlocks(false) {}
|
||||
JumpTableUId(0), PICLabelUId(0),
|
||||
VarArgsFrameIndex(0), HasITBlocks(false) {}
|
||||
|
||||
bool isThumbFunction() const { return isThumb; }
|
||||
bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
|
||||
|
@ -227,16 +227,16 @@ public:
|
|||
return JumpTableUId;
|
||||
}
|
||||
|
||||
void initConstPoolEntryUId(unsigned UId) {
|
||||
ConstPoolEntryUId = UId;
|
||||
void initPICLabelUId(unsigned UId) {
|
||||
PICLabelUId = UId;
|
||||
}
|
||||
|
||||
unsigned getNumConstPoolEntries() const {
|
||||
return ConstPoolEntryUId;
|
||||
unsigned getNumPICLabels() const {
|
||||
return PICLabelUId;
|
||||
}
|
||||
|
||||
unsigned createConstPoolEntryUId() {
|
||||
return ConstPoolEntryUId++;
|
||||
unsigned createPICLabelUId() {
|
||||
return PICLabelUId++;
|
||||
}
|
||||
|
||||
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
|
||||
|
|
|
@ -25,8 +25,7 @@ ReserveR9("arm-reserve-r9", cl::Hidden,
|
|||
cl::desc("Reserve R9, making it unavailable as GPR"));
|
||||
|
||||
static cl::opt<bool>
|
||||
UseMOVT("arm-use-movt",
|
||||
cl::init(true), cl::Hidden);
|
||||
UseMOVT("arm-darwin-use-movt", cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
StrictAlign("arm-strict-align", cl::Hidden,
|
||||
|
@ -45,7 +44,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
|
|||
, NoARM(false)
|
||||
, PostRAScheduler(false)
|
||||
, IsR9Reserved(ReserveR9)
|
||||
, UseMovt(UseMOVT)
|
||||
, UseMovt(false)
|
||||
, HasFP16(false)
|
||||
, HasD16(false)
|
||||
, HasHardwareDivide(false)
|
||||
|
@ -147,8 +146,16 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
|
|||
if (isAAPCS_ABI())
|
||||
stackAlignment = 8;
|
||||
|
||||
if (isTargetDarwin())
|
||||
if (!isTargetDarwin())
|
||||
UseMovt = hasV6T2Ops();
|
||||
else {
|
||||
IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
|
||||
if (UseMOVT && hasV6T2Ops()) {
|
||||
unsigned Maj, Min, Rev;
|
||||
TargetTriple.getDarwinNumber(Maj, Min, Rev);
|
||||
UseMovt = (Maj > 4 || Min > 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isThumb() || hasThumb2())
|
||||
PostRAScheduler = true;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -arm-use-movt -filetype=obj -o - | \
|
||||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -filetype=obj -o - | \
|
||||
; RUN: elf-dump --dump-section-data | FileCheck -check-prefix=OBJ %s
|
||||
|
||||
target triple = "armv7-none-linux-gnueabi"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -arm-use-movt -relocation-model=pic -filetype=obj -o - | \
|
||||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -relocation-model=pic -filetype=obj -o - | \
|
||||
; RUN: elf-dump --dump-section-data | FileCheck -check-prefix=PIC01 %s
|
||||
|
||||
;; FIXME: Reduce this test further, or even better,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -arm-use-movt -filetype=obj -o - | \
|
||||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -filetype=obj -o - | \
|
||||
; RUN: elf-dump --dump-section-data | FileCheck -check-prefix=OBJ %s
|
||||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -arm-use-movt -o - | \
|
||||
; RUN: llc %s -mtriple=armv7-linux-gnueabi -o - | \
|
||||
; RUN: FileCheck -check-prefix=ASM %s
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue