diff options
author | Evan Cheng <evan.cheng@apple.com> | 2011-01-17 08:03:18 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2011-01-17 08:03:18 +0000 |
commit | 5de5d4b6d0eb3fd379fa571d82f6fa764460b3b8 (patch) | |
tree | 3e3003c4648ab61634d5f42fa60ae13332153883 | |
parent | b1086a9c6d6d5ee3070a68076f38eec841cefd58 (diff) | |
download | external_llvm-5de5d4b6d0eb3fd379fa571d82f6fa764460b3b8.zip external_llvm-5de5d4b6d0eb3fd379fa571d82f6fa764460b3b8.tar.gz external_llvm-5de5d4b6d0eb3fd379fa571d82f6fa764460b3b8.tar.bz2 |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123619 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/ARM/ARMAsmPrinter.cpp | 96 | ||||
-rw-r--r-- | lib/Target/ARM/ARMAsmPrinter.h | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInfo.h | 12 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 8 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantIslandPass.cpp | 4 | ||||
-rw-r--r-- | lib/Target/ARM/ARMExpandPseudoInsts.cpp | 47 | ||||
-rw-r--r-- | lib/Target/ARM/ARMFastISel.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 3 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 74 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.h | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 19 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 17 | ||||
-rw-r--r-- | lib/Target/ARM/ARMJITInfo.h | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMachineFunctionInfo.h | 22 | ||||
-rw-r--r-- | lib/Target/ARM/ARMSubtarget.cpp | 15 | ||||
-rw-r--r-- | test/CodeGen/ARM/2010-11-30-reloc-movt.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/ARM/2010-12-13-reloc-pic.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/ARM/2010-12-15-elf-lcomm.ll | 4 |
18 files changed, 248 insertions, 85 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index d1a975d..71a471d 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -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: diff --git a/lib/Target/ARM/ARMAsmPrinter.h b/lib/Target/ARM/ARMAsmPrinter.h index 76a43d4..5852684 100644 --- a/lib/Target/ARM/ARMAsmPrinter.h +++ b/lib/Target/ARM/ARMAsmPrinter.h @@ -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); diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h index 63e8f96..d3831d2 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -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 diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index a53d8cb..925569e 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -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 diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 4915bae..84499b1 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -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(); diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 05d7231..2dde617 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -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; diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 14ed25d..b9d6fc6 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -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); diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index eb54ba5..b88f136 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -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); diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 0167bd7..3710be2 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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(); diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index db31e49..9d105da 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -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. diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 277ee21..9909dd0 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -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]>; diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 4afe79a..1acb647 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -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]>; diff --git a/lib/Target/ARM/ARMJITInfo.h b/lib/Target/ARM/ARMJITInfo.h index f5d9eff..2f97928 100644 --- a/lib/Target/ARM/ARMJITInfo.h +++ b/lib/Target/ARM/ARMJITInfo.h @@ -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; } diff --git a/lib/Target/ARM/ARMMachineFunctionInfo.h b/lib/Target/ARM/ARMMachineFunctionInfo.h index dbb3fe2..0eaa00d 100644 --- a/lib/Target/ARM/ARMMachineFunctionInfo.h +++ b/lib/Target/ARM/ARMMachineFunctionInfo.h @@ -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; } diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 5dfd5d7..1ba52d2 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -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; diff --git a/test/CodeGen/ARM/2010-11-30-reloc-movt.ll b/test/CodeGen/ARM/2010-11-30-reloc-movt.ll index a8dc52e..930cd8d 100644 --- a/test/CodeGen/ARM/2010-11-30-reloc-movt.ll +++ b/test/CodeGen/ARM/2010-11-30-reloc-movt.ll @@ -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" diff --git a/test/CodeGen/ARM/2010-12-13-reloc-pic.ll b/test/CodeGen/ARM/2010-12-13-reloc-pic.ll index 52fd2df..d5aefbe 100644 --- a/test/CodeGen/ARM/2010-12-13-reloc-pic.ll +++ b/test/CodeGen/ARM/2010-12-13-reloc-pic.ll @@ -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, diff --git a/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll b/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll index e08fe8d5..eaa34e7 100644 --- a/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll +++ b/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll @@ -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 |