Index: llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -1308,9 +1308,11 @@ if (IsPIC) { unsigned PCAdj = IsARM ? 8 : 4; + auto Modifier = STI->getCPModifier(GV); ARMPCLabelIndex = AFI->createPICLabelUId(); - CPV = ARMConstantPoolConstant::Create(GV, ARMPCLabelIndex, - ARMCP::CPValue, PCAdj); + CPV = ARMConstantPoolConstant::Create( + GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj, Modifier, + /*AddCurrentAddr*/ Modifier == ARMCP::GOT_PREL); } else CPV = ARMConstantPoolConstant::Create(GV, ARMCP::no_modifier); Index: llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp +++ llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp @@ -492,10 +492,6 @@ DEBUG(dbgs() << "ROPI and RWPI not supported yet\n"); return false; } - if (TM.isPositionIndependent()) { - DEBUG(dbgs() << "PIC not supported yet\n"); - return false; - } auto GV = MIB->getOperand(1).getGlobal(); if (GV->isThreadLocal()) { @@ -509,6 +505,28 @@ auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat(); bool UseMovt = TII.getSubtarget().useMovt(MF); + unsigned Alignment = 4; + if (TM.isPositionIndependent()) { + bool Indirect = TII.getSubtarget().isGVIndirectSymbol(GV); + // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't + // support it yet. See PR28229. + unsigned Opc = + UseMovt && !TII.getSubtarget().isTargetELF() + ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel) + : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel); + MIB->setDesc(TII.get(Opc)); + + if (TII.getSubtarget().isTargetDarwin()) + MIB->getOperand(1).setTargetFlags(ARMII::MO_NONLAZY); + + if (Indirect) + MIB.addMemOperand(MF.getMachineMemOperand( + MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, + TM.getPointerSize(), Alignment)); + + return true; + } + if (ObjectFormat == Triple::ELF) { if (UseMovt) { MIB->setDesc(TII.get(ARM::MOVi32imm)); @@ -516,7 +534,6 @@ // Load the global's address from the constant pool. MIB->setDesc(TII.get(ARM::LDRi12)); MIB->RemoveOperand(1); - unsigned Alignment = 4; MIB.addConstantPoolIndex( MF.getConstantPool()->getConstantPoolIndex(GV, Alignment), /* Offset */ 0, /* TargetFlags */ 0) Index: llvm/trunk/lib/Target/ARM/ARMSubtarget.h =================================================================== --- llvm/trunk/lib/Target/ARM/ARMSubtarget.h +++ llvm/trunk/lib/Target/ARM/ARMSubtarget.h @@ -16,6 +16,7 @@ #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" +#include "ARMConstantPoolValue.h" #include "ARMFrameLowering.h" #include "ARMISelLowering.h" #include "ARMSelectionDAGInfo.h" @@ -750,6 +751,9 @@ /// True if the GV will be accessed via an indirect symbol. bool isGVIndirectSymbol(const GlobalValue *GV) const; + /// Returns the constant pool modifier needed to access the GV. + ARMCP::ARMCPModifier getCPModifier(const GlobalValue *GV) const; + /// True if fast-isel is used. bool useFastISel() const; Index: llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp +++ llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp @@ -342,6 +342,13 @@ return false; } +ARMCP::ARMCPModifier ARMSubtarget::getCPModifier(const GlobalValue *GV) const { + if (isTargetELF() && TM.isPositionIndependent() && + !TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + return ARMCP::GOT_PREL; + return ARMCP::no_modifier; +} + unsigned ARMSubtarget::getMispredictionPenalty() const { return SchedModel.MispredictPenalty; } Index: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-pic.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-pic.ll +++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-pic.ll @@ -0,0 +1,58 @@ +; RUN: llc -mtriple armv7-linux -relocation-model=pic -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +; RUN: llc -mtriple armv7-linux -relocation-model=pic -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +; RUN: llc -mtriple armv7-darwin -relocation-model=pic -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN,DARWIN-MOVT +; RUN: llc -mtriple armv7-darwin -relocation-model=pic -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN,DARWIN-NOMOVT + +@internal_global = internal global i32 42 +define i32 @test_internal_global() { +; CHECK-LABEL: test_internal_global: +; ELF: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ELF: [[ANCHOR:.L[[:alnum:]_]+]]: +; DARWIN-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; DARWIN-MOVT: movw [[OFFSET:r[0-9]+]], :lower16:(_internal_global-([[ANCHOR:L[[:alnum:]_]+]]+8)) +; DARWIN-MOVT-NEXT: movt [[OFFSET]], :upper16:(_internal_global-([[ANCHOR]]+8)) +; DARWIN: [[ANCHOR:L[[:alnum:]_]+]]: +; CHECK-NEXT: add r[[ADDR:[0-9]+]], pc, [[OFFSET]] +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF: [[LABEL]]: +; ELF-NEXT: .long internal_global-([[ANCHOR]]+8) +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT-NEXT: .long _internal_global-([[ANCHOR]]+8) +; DARWIN-MOVT-NOT: .long _internal_global + +entry: + %v = load i32, i32* @internal_global + ret i32 %v +} + +@external_global = external global i32 +define i32 @test_external_global() { +; CHECK-LABEL: test_external_global: +; ELF: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ELF: [[ANCHOR:.L[[:alnum:]_]+]]: +; ELF-NEXT: ldr r[[ADDR:[0-9]+]], [pc, [[OFFSET]]] +; DARWIN-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; DARWIN-MOVT: movw [[OFFSET:r[0-9]+]], :lower16:(L_external_global$non_lazy_ptr-([[ANCHOR:L[[:alnum:]_]+]]+8)) +; DARWIN-MOVT: movt [[OFFSET]], :upper16:(L_external_global$non_lazy_ptr-([[ANCHOR]]+8)) +; DARWIN: [[ANCHOR:L[[:alnum:]_]+]]: +; DARWIN: ldr r[[ADDR:[0-9]+]], [pc, [[OFFSET]]] +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF: [[LABEL]]: +; ELF: [[TMPLABEL:.L[[:alnum:]_]+]]: +; ELF: .long external_global(GOT_PREL)-(([[ANCHOR]]+8)-[[TMPLABEL]]) +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT: .long L_external_global$non_lazy_ptr-([[ANCHOR]]+8) +; DARWIN-NOMOVT-NOT: .long L_external_global +entry: + %v = load i32, i32* @external_global + ret i32 %v +} + +; ELF: internal_global: +; DARWIN: _internal_global: +; CHECK: .long 42 +; ELF: .size internal_global, 4 +; DARWIN: L_external_global$non_lazy_ptr: +; DARWIN: .indirect_symbol _external_global Index: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-pic.mir =================================================================== --- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-pic.mir +++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-pic.mir @@ -0,0 +1,63 @@ +# RUN: llc -O0 -mtriple arm-linux -relocation-model=pic -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +# RUN: llc -O0 -mtriple arm-linux -relocation-model=pic -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +# RUN: llc -O0 -mtriple arm-darwin -relocation-model=pic -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN-NOMOVT +# RUN: llc -O0 -mtriple arm-darwin -relocation-model=pic -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN-MOVT +--- | + @internal_global = internal global i32 42 + define void @test_internal_global() { ret void } + + @external_global = external global i32 + define void @test_external_global() { ret void } +... +--- +name: test_internal_global +# CHECK-LABEL: name: test_internal_global +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @internal_global + ; DARWIN-MOVT: [[G:%[0-9]+]] = MOV_ga_pcrel {{.*}}@internal_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel {{.*}}@internal_global + ; ELF: [[G:%[0-9]+]] = LDRLIT_ga_pcrel {{.*}}@internal_global + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_global) + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, implicit %r0 +... +--- +name: test_external_global +# CHECK-LABEL: name: test_external_global +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @external_global + ; DARWIN-MOVT: [[G:%[0-9]+]] = MOV_ga_pcrel_ldr {{.*}} @external_global :: (load 4 from got) + ; DARWIN-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel_ldr {{.*}}@external_global :: (load 4 from got) + ; ELF: [[G:%[0-9]+]] = LDRLIT_ga_pcrel_ldr @external_global :: (load 4 from got) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_global) + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, implicit %r0 +... Index: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll +++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -117,8 +117,6 @@ define i32 @test_global_reloc_models() { ; This is only unsupported for the PIC, ROPI, RWPI relocation modes. -; PIC: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE -; PIC-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models ; ROPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE ; ROPI-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models ; RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE