VK_WEAKREF, // The link between the symbols in .weakref foo, bar
VK_ARM_NONE,
+ VK_ARM_GOT_PREL,
VK_ARM_TARGET1,
VK_ARM_TARGET2,
VK_ARM_PREL31,
case VK_SIZE: return "SIZE";
case VK_WEAKREF: return "WEAKREF";
case VK_ARM_NONE: return "none";
+ case VK_ARM_GOT_PREL: return "GOT_PREL";
case VK_ARM_TARGET1: return "target1";
case VK_ARM_TARGET2: return "target2";
case VK_ARM_PREL31: return "prel31";
.Case("got", VK_GOT)
.Case("gotoff", VK_GOTOFF)
.Case("gotpcrel", VK_GOTPCREL)
- .Case("got_prel", VK_GOTPCREL)
.Case("gottpoff", VK_GOTTPOFF)
.Case("indntpoff", VK_INDNTPOFF)
.Case("ntpoff", VK_NTPOFF)
.Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
.Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
.Case("none", VK_ARM_NONE)
+ .Case("got_prel", VK_ARM_GOT_PREL)
.Case("target1", VK_ARM_TARGET1)
.Case("target2", VK_ARM_TARGET2)
.Case("prel31", VK_ARM_PREL31)
FunctionPass *createA15SDOptimizerPass();
FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
FunctionPass *createARMExpandPseudoPass();
-FunctionPass *createARMGlobalBaseRegPass();
FunctionPass *createARMConstantIslandPass();
FunctionPass *createMLxExpansionPass();
FunctionPass *createThumb2ITBlockPass();
case ARMCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
case ARMCP::TPOFF: return MCSymbolRefExpr::VK_TPOFF;
case ARMCP::GOTTPOFF: return MCSymbolRefExpr::VK_GOTTPOFF;
- case ARMCP::GOT: return MCSymbolRefExpr::VK_GOT;
- case ARMCP::GOTOFF: return MCSymbolRefExpr::VK_GOTOFF;
+ case ARMCP::GOT_PREL: return MCSymbolRefExpr::VK_ARM_GOT_PREL;
}
llvm_unreachable("Invalid ARMCPModifier!");
}
// instructions, so that's probably OK, but is PIC always correct when
// we get here?
if (ACPV->isGlobalValue())
- NewCPV = ARMConstantPoolConstant::
- Create(cast<ARMConstantPoolConstant>(ACPV)->getGV(), PCLabelId,
- ARMCP::CPValue, 4);
+ NewCPV = ARMConstantPoolConstant::Create(
+ cast<ARMConstantPoolConstant>(ACPV)->getGV(), PCLabelId, ARMCP::CPValue,
+ 4, ACPV->getModifier(), ACPV->mustAddCurrentAddress());
else if (ACPV->isExtSymbol())
NewCPV = ARMConstantPoolSymbol::
Create(MF.getFunction()->getContext(),
// strings if that's legal.
case ARMCP::no_modifier: return "none";
case ARMCP::TLSGD: return "tlsgd";
- case ARMCP::GOT: return "GOT";
- case ARMCP::GOTOFF: return "GOTOFF";
+ case ARMCP::GOT_PREL: return "GOT_PREL";
case ARMCP::GOTTPOFF: return "gottpoff";
case ARMCP::TPOFF: return "tpoff";
}
enum ARMCPModifier {
no_modifier,
TLSGD,
- GOT,
- GOTOFF,
+ GOT_PREL,
GOTTPOFF,
TPOFF
};
unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV,
unsigned Align, MVT VT) {
- bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
- ARMConstantPoolConstant *CPV =
- ARMConstantPoolConstant::Create(GV, UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT);
- unsigned Idx = MCP.getConstantPoolIndex(CPV, Align);
+ bool UseGOT_PREL =
+ !(GV->hasHiddenVisibility() || GV->isStrongDefinitionForLinker());
+
+ LLVMContext *Context = &MF->getFunction()->getContext();
+ unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
+ unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
+ ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(
+ GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj,
+ UseGOT_PREL ? ARMCP::GOT_PREL : ARMCP::no_modifier,
+ /*AddCurrentAddress=*/UseGOT_PREL);
+
+ unsigned ConstAlign =
+ MF->getDataLayout().getPrefTypeAlignment(Type::getInt32PtrTy(*Context));
+ unsigned Idx = MF->getConstantPool()->getConstantPoolIndex(CPV, ConstAlign);
+
+ unsigned TempReg = MF->getRegInfo().createVirtualRegister(&ARM::rGPRRegClass);
+ unsigned Opc = isThumb2 ? ARM::t2LDRpci : ARM::LDRcp;
+ MachineInstrBuilder MIB =
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), TempReg)
+ .addConstantPoolIndex(Idx);
+ if (Opc == ARM::LDRcp)
+ MIB.addImm(0);
+ AddDefaultPred(MIB);
- unsigned Opc;
- unsigned DestReg1 = createResultReg(TLI.getRegClassFor(VT));
- // Load value.
- if (isThumb2) {
- DestReg1 = constrainOperandRegClass(TII.get(ARM::t2LDRpci), DestReg1, 0);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::t2LDRpci), DestReg1)
- .addConstantPoolIndex(Idx));
- Opc = UseGOTOFF ? ARM::t2ADDrr : ARM::t2LDRs;
- } else {
- // The extra immediate is for addrmode2.
- DestReg1 = constrainOperandRegClass(TII.get(ARM::LDRcp), DestReg1, 0);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
- DbgLoc, TII.get(ARM::LDRcp), DestReg1)
- .addConstantPoolIndex(Idx).addImm(0));
- Opc = UseGOTOFF ? ARM::ADDrr : ARM::LDRrs;
- }
+ // Fix the address by adding pc.
+ unsigned DestReg = createResultReg(TLI.getRegClassFor(VT));
+ Opc = Subtarget->isThumb() ? ARM::tPICADD : UseGOT_PREL ? ARM::PICLDR
+ : ARM::PICADD;
+ DestReg = constrainOperandRegClass(TII.get(Opc), DestReg, 0);
+ MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg)
+ .addReg(TempReg)
+ .addImm(ARMPCLabelIndex);
+ if (!Subtarget->isThumb())
+ AddDefaultPred(MIB);
- unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
- if (GlobalBaseReg == 0) {
- GlobalBaseReg = MRI.createVirtualRegister(TLI.getRegClassFor(VT));
- AFI->setGlobalBaseReg(GlobalBaseReg);
+ if (UseGOT_PREL && Subtarget->isThumb()) {
+ unsigned NewDestReg = createResultReg(TLI.getRegClassFor(VT));
+ MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ TII.get(ARM::t2LDRi12), NewDestReg)
+ .addReg(DestReg)
+ .addImm(0);
+ DestReg = NewDestReg;
+ AddOptionalDefs(MIB);
}
-
- unsigned DestReg2 = createResultReg(TLI.getRegClassFor(VT));
- DestReg2 = constrainOperandRegClass(TII.get(Opc), DestReg2, 0);
- DestReg1 = constrainOperandRegClass(TII.get(Opc), DestReg1, 1);
- GlobalBaseReg = constrainOperandRegClass(TII.get(Opc), GlobalBaseReg, 2);
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
- DbgLoc, TII.get(Opc), DestReg2)
- .addReg(DestReg1)
- .addReg(GlobalBaseReg);
- if (!UseGOTOFF)
- MIB.addImm(0);
- AddOptionalDefs(MIB);
-
- return DestReg2;
+ return DestReg;
}
bool ARMFastISel::fastLowerArguments() {
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
- setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
SDLoc dl(Op);
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
- bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
- ARMConstantPoolValue *CPV =
- ARMConstantPoolConstant::Create(GV,
- UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT);
+ bool UseGOT_PREL =
+ !(GV->hasHiddenVisibility() || GV->isStrongDefinitionForLinker());
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
+ unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
+ SDLoc dl(Op);
+ unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
+ ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(
+ GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj,
+ UseGOT_PREL ? ARMCP::GOT_PREL : ARMCP::no_modifier,
+ /*AddCurrentAddress=*/UseGOT_PREL);
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
SDValue Result = DAG.getLoad(
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()), false,
false, false, 0);
SDValue Chain = Result.getValue(1);
- SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT);
- Result = DAG.getNode(ISD::ADD, dl, PtrVT, Result, GOT);
- if (!UseGOTOFF)
+ SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, dl, MVT::i32);
+ Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
+ if (UseGOT_PREL)
Result = DAG.getLoad(PtrVT, dl, Chain, Result,
MachinePointerInfo::getGOT(DAG.getMachineFunction()),
false, false, false, 0);
return Result;
}
-SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op,
- SelectionDAG &DAG) const {
- assert(Subtarget->isTargetELF() &&
- "GLOBAL OFFSET TABLE not implemented for non-ELF targets");
- MachineFunction &MF = DAG.getMachineFunction();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
- EVT PtrVT = getPointerTy(DAG.getDataLayout());
- SDLoc dl(Op);
- unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
- ARMConstantPoolValue *CPV =
- ARMConstantPoolSymbol::Create(*DAG.getContext(), "_GLOBAL_OFFSET_TABLE_",
- ARMPCLabelIndex, PCAdj);
- SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
- CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
- SDValue Result =
- DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr,
- MachinePointerInfo::getConstantPool(DAG.getMachineFunction()),
- false, false, false, 0);
- SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, dl, MVT::i32);
- return DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
-}
-
SDValue
ARMTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const {
SDLoc dl(Op);
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
- case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG);
case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG);
case ISD::EH_SJLJ_SETUP_DISPATCH: return LowerEH_SJLJ_SETUP_DISPATCH(Op, DAG);
SDValue LowerToTLSExecModels(GlobalAddressSDNode *GA,
SelectionDAG &DAG,
TLSModel::Model model) const;
- SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
MIB.setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
AddDefaultPred(MIB);
}
-
-namespace {
-/// ARMCGBR - Create Global Base Reg pass. This initializes the PIC
-/// global base register for ARM ELF.
-struct ARMCGBR : public MachineFunctionPass {
- static char ID;
- ARMCGBR() : MachineFunctionPass(ID) {}
-
- bool runOnMachineFunction(MachineFunction &MF) override {
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- if (AFI->getGlobalBaseReg() == 0)
- return false;
- const ARMSubtarget &STI =
- static_cast<const ARMSubtarget &>(MF.getSubtarget());
- // Don't do this for Thumb1.
- if (STI.isThumb1Only())
- return false;
-
- const TargetMachine &TM = MF.getTarget();
- if (TM.getRelocationModel() != Reloc::PIC_)
- return false;
-
- LLVMContext *Context = &MF.getFunction()->getContext();
- unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
- unsigned PCAdj = STI.isThumb() ? 4 : 8;
- ARMConstantPoolValue *CPV = ARMConstantPoolSymbol::Create(
- *Context, "_GLOBAL_OFFSET_TABLE_", ARMPCLabelIndex, PCAdj);
-
- unsigned Align =
- MF.getDataLayout().getPrefTypeAlignment(Type::getInt32PtrTy(*Context));
- unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align);
-
- MachineBasicBlock &FirstMBB = MF.front();
- MachineBasicBlock::iterator MBBI = FirstMBB.begin();
- DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
- unsigned TempReg =
- MF.getRegInfo().createVirtualRegister(&ARM::rGPRRegClass);
- unsigned Opc = STI.isThumb2() ? ARM::t2LDRpci : ARM::LDRcp;
- const TargetInstrInfo &TII = *STI.getInstrInfo();
- MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL, TII.get(Opc), TempReg)
- .addConstantPoolIndex(Idx);
- if (Opc == ARM::LDRcp)
- MIB.addImm(0);
- AddDefaultPred(MIB);
-
- // Fix the GOT address by adding pc.
- unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
- Opc = STI.isThumb2() ? ARM::tPICADD : ARM::PICADD;
- MIB = BuildMI(FirstMBB, MBBI, DL, TII.get(Opc), GlobalBaseReg)
- .addReg(TempReg)
- .addImm(ARMPCLabelIndex);
- if (Opc == ARM::PICADD)
- AddDefaultPred(MIB);
-
- return true;
- }
-
- const char *getPassName() const override {
- return "ARM PIC Global Base Reg Initialization";
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
-};
-}
-
-char ARMCGBR::ID = 0;
-FunctionPass *llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); }
RestoreSPFromFP(false), LRSpilledForFarJump(false),
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
- PICLabelUId(0), VarArgsFrameIndex(0), HasITBlocks(false),
- GlobalBaseReg(0) {}
+ PICLabelUId(0), VarArgsFrameIndex(0), HasITBlocks(false) {}
/// pass.
DenseMap<unsigned, unsigned> CPEClones;
- /// GlobalBaseReg - keeps track of the virtual register initialized for
- /// use as the global base register. This is used for PIC in some PIC
- /// relocation models.
- unsigned GlobalBaseReg;
-
/// ArgumentStackSize - amount of bytes on stack consumed by the arguments
/// being passed on the stack
unsigned ArgumentStackSize;
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
GPRCS1Size(0), GPRCS2Size(0), DPRCSAlignGapSize(0), DPRCSSize(0),
NumAlignedDPRCS2Regs(0), PICLabelUId(0),
- VarArgsFrameIndex(0), HasITBlocks(false), GlobalBaseReg(0) {}
+ VarArgsFrameIndex(0), HasITBlocks(false) {}
explicit ARMFunctionInfo(MachineFunction &MF);
bool hasITBlocks() const { return HasITBlocks; }
void setHasITBlocks(bool h) { HasITBlocks = h; }
- unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
- void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
-
void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
if (!CPEClones.insert(std::make_pair(CPCloneIdx, CPIdx)).second)
llvm_unreachable("Duplicate entries!");
bool ARMPassConfig::addInstSelector() {
addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
-
- if (TM->getTargetTriple().isOSBinFormatELF() && TM->Options.EnableFastISel)
- addPass(createARMGlobalBaseRegPass());
return false;
}
case MCSymbolRefExpr::VK_GOTTPOFF:
Type = ELF::R_ARM_TLS_IE32;
break;
- case MCSymbolRefExpr::VK_GOTPCREL:
+ case MCSymbolRefExpr::VK_ARM_GOT_PREL:
Type = ELF::R_ARM_GOT_PREL;
break;
}
case MCSymbolRefExpr::VK_GOTOFF:
Type = ELF::R_ARM_GOTOFF32;
break;
- case MCSymbolRefExpr::VK_GOTPCREL:
+ case MCSymbolRefExpr::VK_ARM_GOT_PREL:
Type = ELF::R_ARM_GOT_PREL;
break;
case MCSymbolRefExpr::VK_ARM_TARGET1:
define i32 @my_get_xyz() {
; ARM32-LABEL: my_get_xyz:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl my_emutls_get_address(PLT)
; ARM32-NEXT: ldr r0, [r0]
define i32 @f1() {
; ARM32-LABEL: f1:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldr r0, [r0]
define i32* @f2() {
; ARM32-LABEL: f2:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: pop
define i32 @f3() nounwind {
; ARM32-LABEL: f3:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldr r0, [r0]
define i32* @f4() {
; ARM32-LABEL: f4:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: pop
define i32 @f5() nounwind {
; ARM32-LABEL: f5:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldr r0, [r0]
define i32* @f6() {
; ARM32-LABEL: f6:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: pop
define i32 @f7() {
; ARM32-LABEL: f7:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldr r0, [r0]
define i32* @f8() {
; ARM32-LABEL: f8:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: pop
define i32 @f9() {
; ARM32-LABEL: f9:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldr r0, [r0]
define i32* @f10() {
; ARM32-LABEL: f10:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: pop
define i16 @f11() {
; ARM32-LABEL: f11:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldrh r0, [r0]
define i32 @f12() {
; ARM32-LABEL: f12:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldrsh r0, [r0]
define i8 @f13() {
; ARM32-LABEL: f13:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldrb r0, [r0]
; ARM32-NEXT: pop
define i32 @f14() {
; ARM32-LABEL: f14:
; ARM32: ldr r0,
-; ARM32-NEXT: ldr r1,
-; ARM32: add r0, pc, r0
-; ARM32-NEXT: ldr r0, [r1, r0]
+; ARM32: ldr r0, [pc, r0]
; ARM32-NEXT: bl __emutls_get_address(PLT)
; ARM32-NEXT: ldrsb r0, [r0]
; ARM32-NEXT: pop
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=pic -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARMv7
-; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=pic -mtriple=thumbv7-none-linux-gnueabi | FileCheck %s --check-prefix=THUMB-ELF
-; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=pic -mtriple=armv7-none-linux-gnueabi | FileCheck %s --check-prefix=ARMv7-ELF
+; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -arm-force-fast-isel -relocation-model=pic -mtriple=thumbv7-none-linux-gnueabi | FileCheck %s --check-prefix=THUMB-ELF
+; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -arm-force-fast-isel -relocation-model=pic -mtriple=armv7-none-linux-gnueabi | FileCheck %s --check-prefix=ARMv7-ELF
@g = global i32 0, align 4
; THUMB: add [[reg0]], pc
; THUMB-ELF: LoadGV
; THUMB-ELF: ldr r[[reg0:[0-9]+]],
-; THUMB-ELF: ldr r[[reg1:[0-9]+]],
-; THUMB-ELF: ldr r[[reg0]], [r[[reg0]], r[[reg1]]]
+; THUMB-ELF: add r[[reg0]], pc
+; THUMB-ELF: ldr r[[reg0]], [r[[reg0]]]
; ARM: LoadGV
; ARM: ldr [[reg1:r[0-9]+]],
; ARM: add [[reg1]], pc, [[reg1]]
; ARMv7-ELF: ldr r[[reg2:[0-9]+]],
; ARMv7-ELF: .LPC
; ARMv7-ELF-NEXT: add r[[reg2]], pc
-; ARMv7-ELF: ldr r[[reg3:[0-9]+]],
-; ARMv7-ELF: ldr r[[reg2]], [r[[reg3]], r[[reg2]]]
+; ARMv7-ELF: ldr r[[reg2]], [r[[reg2]]]
%tmp = load i32, i32* @g
ret i32 %tmp
}
; THUMB: ldr r[[reg3]], [r[[reg3]]]
; THUMB-ELF: LoadIndirectSymbol
; THUMB-ELF: ldr r[[reg3:[0-9]+]],
-; THUMB-ELF: ldr r[[reg4:[0-9]+]],
-; THUMB-ELF: ldr r[[reg3]], [r[[reg3]], r[[reg4]]]
+; THUMB-ELF: ldr r[[reg4:[0-9]+]], [r[[reg3]]]
+; THUMB-ELF: ldr r0, [r[[reg4]]]
; ARM: LoadIndirectSymbol
; ARM: ldr [[reg4:r[0-9]+]],
; ARM: ldr [[reg4]], [pc, [[reg4]]]
; ARMv7-ELF: LoadIndirectSymbol
; ARMv7-ELF: ldr r[[reg5:[0-9]+]],
; ARMv7-ELF: .LPC
-; ARMv7-ELF-NEXT: add r[[reg5]], pc
-; ARMv7-ELF: ldr r[[reg6:[0-9]+]],
-; ARMv7-ELF: ldr r[[reg5]], [r[[reg6]], r[[reg5]]]
+; ARMv7-ELF: ldr r[[reg6:[0-9]+]], [pc, r[[reg5]]]
+; ARMv7-ELF: ldr r0, [r[[reg5]]]
%tmp = load i32, i32* @i
ret i32 %tmp
}
; LinuxPIC-LABEL: test1:
; LinuxPIC: ldr r0, .LCPI0_0
-; LinuxPIC: ldr r1, .LCPI0_1
; LinuxPIC: .LPC0_0:
-; LinuxPIC: add r0, pc, r0
-; LinuxPIC: ldr r0, [r1, r0]
+; LinuxPIC: ldr r0, [pc, r0]
; LinuxPIC: ldr r0, [r0]
; LinuxPIC: bx lr
; LinuxPIC: .align 2
; LinuxPIC: .LCPI0_0:
-; LinuxPIC: .long _GLOBAL_OFFSET_TABLE_-(.LPC0_0+8)
-; LinuxPIC: .LCPI0_1:
-; LinuxPIC: .long G(GOT)
+; LinuxPIC: .Ltmp0:
+; LinuxPIC: .long G(GOT_PREL)-((.LPC0_0+8)-.Ltmp0)
; RUN: llc < %s -mtriple=thumbv6-apple-darwin -relocation-model=pic | FileCheck %s -check-prefix=PIC_T
; RUN: llc < %s -mtriple=armv7-apple-darwin -relocation-model=pic | FileCheck %s -check-prefix=PIC_V7
; RUN: llc < %s -mtriple=armv6-linux-gnueabi -relocation-model=pic | FileCheck %s -check-prefix=LINUX
+; RUN: llc < %s -mtriple=thumbv6-linux-gnueabi -relocation-model=pic | FileCheck %s -check-prefix=LINUX_T
@G = external global i32
; LINUX: test1
; LINUX: ldr r0, .LCPI0_0
-; LINUX: ldr r1, .LCPI0_1
-; LINUX: add r0, pc, r0
-; LINUX: ldr r0, [r1, r0]
+; LINUX: ldr r0, [pc, r0]
; LINUX: ldr r0, [r0]
-; LINUX: .long G(GOT)
+; LINUX: .long G(GOT_PREL)-((.LPC0_0+8)-.Ltmp0)
+
+; LINUX_T: ldr r0, .LCPI0_0
+; LINUX_T: add r0, pc
+; LINUX_T: ldr r0, [r0]
+; LINUX_T: ldr r0, [r0]
%tmp = load i32, i32* @G
ret i32 %tmp
}