Index: llvm/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3163,29 +3163,13 @@ return V; if (isPositionIndependent()) { + // PC-relative. bool UseGOT_PREL = !TM.shouldAssumeDSOLocal(*GV->getParent(), GV); - - MachineFunction &MF = DAG.getMachineFunction(); - ARMFunctionInfo *AFI = MF.getInfo(); - 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( - PtrVT, dl, DAG.getEntryNode(), CPAddr, - MachinePointerInfo::getConstantPool(DAG.getMachineFunction())); - SDValue Chain = Result.getValue(1); - SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, dl, MVT::i32); - Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); + SDValue G = DAG.getTargetGlobalAddress(GV, dl, PtrVT); + SDValue Result = DAG.getNode(ARMISD::WrapperPIC, dl, PtrVT, G); if (UseGOT_PREL) Result = - DAG.getLoad(PtrVT, dl, Chain, Result, + DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Result, MachinePointerInfo::getGOT(DAG.getMachineFunction())); return Result; } else if (Subtarget->isROPI() && IsRO) { Index: llvm/lib/Target/ARM/ARMInstrInfo.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrInfo.td +++ llvm/lib/Target/ARM/ARMInstrInfo.td @@ -332,6 +332,8 @@ let RecomputePerFunction = 1 in { def UseMovt : Predicate<"Subtarget->useMovt(*MF)">; def DontUseMovt : Predicate<"!Subtarget->useMovt(*MF)">; + def UseMovtInPic : Predicate<"Subtarget->useMovt(*MF) && Subtarget->allowPositionIndependentMovt()">; + def DontUseMovtInPic : Predicate<"!Subtarget->useMovt(*MF) || !Subtarget->allowPositionIndependentMovt()">; } def UseFPVMLx : Predicate<"Subtarget->useFPVMLx()">; def UseMulOps : Predicate<"Subtarget->useMulOps()">; @@ -5644,26 +5646,26 @@ def MOV_ga_pcrel : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), IIC_iMOVix2addpc, [(set GPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>, - Requires<[IsARM, UseMovt]>; + Requires<[IsARM, UseMovtInPic]>; def LDRLIT_ga_pcrel : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), IIC_iLoadiALU, [(set GPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>, - Requires<[IsARM, DontUseMovt]>; + Requires<[IsARM, DontUseMovtInPic]>; let AddedComplexity = 10 in def LDRLIT_ga_pcrel_ldr : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), NoItinerary, [(set GPR:$dst, (load (ARMWrapperPIC tglobaladdr:$addr)))]>, - Requires<[IsARM, DontUseMovt]>; + Requires<[IsARM, DontUseMovtInPic]>; let AddedComplexity = 10 in def MOV_ga_pcrel_ldr : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), IIC_iMOVix2ld, [(set GPR:$dst, (load (ARMWrapperPIC tglobaladdr:$addr)))]>, - Requires<[IsARM, UseMovt]>; + Requires<[IsARM, UseMovtInPic]>; } // isReMaterializable // The many different faces of TLS access. @@ -5676,15 +5678,15 @@ Requires<[IsARM, DontUseMovt]>; def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr), - (MOV_ga_pcrel tglobaltlsaddr:$addr)>, Requires<[IsARM, UseMovt]>; + (MOV_ga_pcrel tglobaltlsaddr:$addr)>, Requires<[IsARM, UseMovtInPic]>; def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr), (LDRLIT_ga_pcrel tglobaltlsaddr:$addr)>, - Requires<[IsARM, DontUseMovt]>; + Requires<[IsARM, DontUseMovtInPic]>; let AddedComplexity = 10 in def : Pat<(load (ARMWrapperPIC tglobaltlsaddr:$addr)), (MOV_ga_pcrel_ldr tglobaltlsaddr:$addr)>, - Requires<[IsARM, UseMovt]>; + Requires<[IsARM, UseMovtInPic]>; // ConstantPool, GlobalAddress, and JumpTable Index: llvm/lib/Target/ARM/ARMInstrThumb.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrThumb.td +++ llvm/lib/Target/ARM/ARMInstrThumb.td @@ -1509,7 +1509,7 @@ IIC_iLoadiALU, [(set tGPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>, - Requires<[IsThumb, DontUseMovt]>; + Requires<[IsThumb, DontUseMovtInPic]>; def tLDRLIT_ga_abs : PseudoInst<(outs tGPR:$dst), (ins i32imm:$src), IIC_iLoad_i, @@ -1520,7 +1520,7 @@ // TLS globals def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr), (tLDRLIT_ga_pcrel tglobaltlsaddr:$addr)>, - Requires<[IsThumb, DontUseMovt]>; + Requires<[IsThumb, DontUseMovtInPic]>; def : Pat<(ARMWrapper tglobaltlsaddr:$addr), (tLDRLIT_ga_abs tglobaltlsaddr:$addr)>, Requires<[IsThumb, DontUseMovt]>; Index: llvm/lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrThumb2.td +++ llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -3843,13 +3843,13 @@ def t2MOV_ga_pcrel : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr), IIC_iMOVix2addpc, [(set rGPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>, - Requires<[IsThumb, HasV8MBaseline, UseMovt]>; + Requires<[IsThumb, HasV8MBaseline, UseMovtInPic]>; } def : T2Pat<(ARMWrapperPIC tglobaltlsaddr :$dst), (t2MOV_ga_pcrel tglobaltlsaddr:$dst)>, - Requires<[IsThumb2, UseMovt]>; + Requires<[IsThumb2, UseMovtInPic]>; def : T2Pat<(ARMWrapper tglobaltlsaddr:$dst), (t2MOVi32imm tglobaltlsaddr:$dst)>, Requires<[IsThumb2, UseMovt]>; Index: llvm/lib/Target/ARM/ARMSubtarget.h =================================================================== --- llvm/lib/Target/ARM/ARMSubtarget.h +++ llvm/lib/Target/ARM/ARMSubtarget.h @@ -767,6 +767,13 @@ return ARM::BX_RET; return ARM::MOVPCLR; } + + /// Allow movt+movw for PIC global address calculation. + /// ELF does not have GOT relocations for movt+movw. + /// ROPI does not use GOT. + bool allowPositionIndependentMovt() const { + return isROPI() || !isTargetELF(); + } }; } // end namespace llvm Index: llvm/test/CodeGen/ARM/load-global2.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/load-global2.ll @@ -0,0 +1,30 @@ +; PR35221. Test that external global address is not reloaded from GOT in each BB. +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -relocation-model=pic | FileCheck %s -check-prefix=LINUX-PIC + +@x = external global i8, align 1 + +define signext i8 @foo() { +entry: +; LINUX-PIC: ldr r[[A:.]], .LCPI0_0 +; LINUX-PIC: ldr r[[B:.]], [pc, r[[A]]] +; LINUX-PIC: ldrb r{{.}}, [r[[B]]] + %0 = load i8, i8* @x + %tobool = icmp eq i8 %0, 0 + br i1 %tobool, label %bb1, label %bb2 + +bb1: + call void @bar() +; No more pc-relative loads! Reuse r[[B]]. +; LINUX-PIC: bl bar +; LINUX-PIC-NOT: ldr{{.*}}[pc, +; LINUX-PIC: ldrsb r{{.}}, [r[[B]]] + %1 = load i8, i8* @x + ret i8 %1 + +bb2: + ret i8 0 +} + +declare void @bar() + + Index: llvm/test/CodeGen/Thumb2/v8_IT_3.ll =================================================================== --- llvm/test/CodeGen/Thumb2/v8_IT_3.ll +++ llvm/test/CodeGen/Thumb2/v8_IT_3.ll @@ -55,7 +55,11 @@ ; CHECK-PIC: cmp ; CHECK-PIC: cmp ; CHECK-PIC: cmp -; CHECK-PIC-NEXT: bne +; CHECK-PIC: it eq +; CHECK-PIC-NEXT: ldreq +; CHECK-PIC-NEXT: it eq +; CHECK-PIC-NEXT: cmpeq +; CHECK-PIC-NEXT: beq ; CHECK-PIC: %bb6 ; CHECK-PIC-NEXT: movs ; CHECK-PIC-NEXT: add