diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index 091f1ff807d9..ec61677736b3 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -112,6 +112,13 @@ private: unsigned TSTri; unsigned Bcc; + // Used for G_GLOBAL_VALUE + unsigned MOVi32imm; + unsigned ConstPoolLoad; + unsigned MOV_ga_pcrel; + unsigned LDRLIT_ga_pcrel; + unsigned LDRLIT_ga_abs; + OpcodeCache(const ARMSubtarget &STI); } const Opcodes; @@ -312,6 +319,12 @@ ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) { STORE_OPCODE(TSTri, TSTri); STORE_OPCODE(Bcc, Bcc); + + STORE_OPCODE(MOVi32imm, MOVi32imm); + ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12; + STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel); + LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel; + LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs; #undef MAP_OPCODE } @@ -609,7 +622,9 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, auto addOpsForConstantPoolLoad = [&MF, Alignment, Size](MachineInstrBuilder &MIB, const GlobalValue *GV, bool IsSBREL) { - assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction"); + assert((MIB->getOpcode() == ARM::LDRi12 || + MIB->getOpcode() == ARM::t2LDRpci) && + "Unsupported instruction"); auto ConstPool = MF.getConstantPool(); auto CPIndex = // For SB relative entries we need a target-specific constant pool. @@ -619,21 +634,37 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment) : ConstPool->getConstantPoolIndex(GV, Alignment); MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0) - .addMemOperand( - MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), - MachineMemOperand::MOLoad, Size, Alignment)) - .addImm(0) - .add(predOps(ARMCC::AL)); + .addMemOperand(MF.getMachineMemOperand( + MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad, + Size, Alignment)); + if (MIB->getOpcode() == ARM::LDRi12) + MIB.addImm(0); + MIB.add(predOps(ARMCC::AL)); + }; + + auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) { + MIB.addMemOperand(MF.getMachineMemOperand( + MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, + TM.getProgramPointerSize(), Alignment)); }; if (TM.isPositionIndependent()) { bool Indirect = STI.isGVIndirectSymbol(GV); + + // For ARM mode, we have different pseudoinstructions for direct accesses + // and indirect accesses, and the ones for indirect accesses include the + // load from GOT. For Thumb mode, we use the same pseudoinstruction for both + // direct and indirect accesses, and we need to manually generate the load + // from GOT. + bool UseOpcodeThatLoads = Indirect && !STI.isThumb(); + // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't // support it yet. See PR28229. - unsigned Opc = - UseMovt && !STI.isTargetELF() - ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel) - : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel); + unsigned Opc = UseMovt && !STI.isTargetELF() + ? (UseOpcodeThatLoads ? ARM::MOV_ga_pcrel_ldr + : Opcodes.MOV_ga_pcrel) + : (UseOpcodeThatLoads ? ARM::LDRLIT_ga_pcrel_ldr + : Opcodes.LDRLIT_ga_pcrel); MIB->setDesc(TII.get(Opc)); int TargetFlags = ARMII::MO_NO_FLAG; @@ -643,17 +674,35 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, TargetFlags |= ARMII::MO_GOT; MIB->getOperand(1).setTargetFlags(TargetFlags); - if (Indirect) - MIB.addMemOperand(MF.getMachineMemOperand( - MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, - TM.getProgramPointerSize(), Alignment)); + if (Indirect) { + if (!UseOpcodeThatLoads) { + auto ResultReg = MIB->getOperand(0).getReg(); + auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass); + + MIB->getOperand(0).setReg(AddressReg); + + auto InsertBefore = std::next(MIB->getIterator()); + auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(), + TII.get(Opcodes.LOAD32)) + .addDef(ResultReg) + .addReg(AddressReg) + .addImm(0) + .add(predOps(ARMCC::AL)); + addGOTMemOperand(MIBLoad); + + if (!constrainSelectedInstRegOperands(*MIBLoad, TII, TRI, RBI)) + return false; + } else { + addGOTMemOperand(MIB); + } + } return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV); if (STI.isROPI() && isReadOnly) { - unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel; + unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel; MIB->setDesc(TII.get(Opc)); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } @@ -662,19 +711,19 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, MachineInstrBuilder OffsetMIB; if (UseMovt) { OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(), - TII.get(ARM::MOVi32imm), Offset); + TII.get(Opcodes.MOVi32imm), Offset); OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL); } else { // Load the offset from the constant pool. - OffsetMIB = - BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset); + OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(), + TII.get(Opcodes.ConstPoolLoad), Offset); addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true); } if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI)) return false; // Add the offset to the SB register. - MIB->setDesc(TII.get(ARM::ADDrr)); + MIB->setDesc(TII.get(Opcodes.ADDrr)); MIB->RemoveOperand(1); MIB.addReg(ARM::R9) // FIXME: don't hardcode R9 .addReg(Offset) @@ -686,18 +735,18 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, if (STI.isTargetELF()) { if (UseMovt) { - MIB->setDesc(TII.get(ARM::MOVi32imm)); + MIB->setDesc(TII.get(Opcodes.MOVi32imm)); } else { // Load the global's address from the constant pool. - MIB->setDesc(TII.get(ARM::LDRi12)); + MIB->setDesc(TII.get(Opcodes.ConstPoolLoad)); MIB->RemoveOperand(1); addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false); } } else if (STI.isTargetMachO()) { if (UseMovt) - MIB->setDesc(TII.get(ARM::MOVi32imm)); + MIB->setDesc(TII.get(Opcodes.MOVi32imm)); else - MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); + MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs)); } else { LLVM_DEBUG(dbgs() << "Object format not supported yet\n"); return false; diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp index 29413a4d1c56..26c7a98c2075 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -139,6 +139,7 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { {p0, p0, 32, 8}}); getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0}); + getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0}); auto &PhiBuilder = getActionDefinitionsBuilder(G_PHI) @@ -212,8 +213,6 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { return; } - getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0}); - if (ST.hasV5TOps()) { getActionDefinitionsBuilder(G_CTLZ) .legalFor({s32, s32}) diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-globals.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-globals.mir new file mode 100644 index 000000000000..52ac76886f65 --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-globals.mir @@ -0,0 +1,29 @@ +# RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple thumb-- -mattr=+v6t2 -run-pass=legalizer %s -o - | FileCheck %s +--- | + @a_global = global i32 42 + define void @test_global_variable() { ret void } +... +--- +name: test_global_variable +# CHECK-LABEL: name: test_global_variable +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + %1(p0) = G_GLOBAL_VALUE @a_global + ; G_GLOBAL_VALUE is legal, so we should find it unchanged in the output + ; CHECK: {{%[0-9]+}}:_(p0) = G_GLOBAL_VALUE @a_global + $r0 = COPY %1(p0) + BX_RET 14, $noreg, implicit $r0 + +... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir index 1d77b7936bff..ae4e94904ec9 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir @@ -6,9 +6,6 @@ define void @test_phi_s64() #0 { ret void } - @a_global = global i32 42 - define void @test_global_variable() { ret void } - attributes #0 = { "target-features"="+vfp2" } ... --- @@ -106,26 +103,3 @@ body: | $d0 = COPY %4(s64) BX_RET 14, $noreg, implicit $d0 ... ---- -name: test_global_variable -# CHECK-LABEL: name: test_global_variable -legalized: false -# CHECK: legalized: true -regBankSelected: false -selected: false -tracksRegLiveness: true -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } -body: | - bb.0: - liveins: $r0 - - %0(s32) = COPY $r0 - %1(p0) = G_GLOBAL_VALUE @a_global - ; G_GLOBAL_VALUE is legal, so we should find it unchanged in the output - ; CHECK: {{%[0-9]+}}:_(p0) = G_GLOBAL_VALUE @a_global - $r0 = COPY %1(p0) - BX_RET 14, $noreg, implicit $r0 - -... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-pic.ll b/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-pic.ll new file mode 100644 index 000000000000..85058506824c --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-pic.ll @@ -0,0 +1,114 @@ +; RUN: llc -mtriple thumbv7-linux -relocation-model=pic -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +; RUN: llc -mtriple thumbv7-linux -relocation-model=pic -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +; RUN: llc -mtriple thumbv7-darwin -relocation-model=pic -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN,DARWIN-MOVT +; RUN: llc -mtriple thumbv7-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 r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ELF: [[ANCHOR:.L[[:alnum:]_]+]]: +; DARWIN-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; DARWIN-MOVT: movw r[[ADDR:[0-9]+]], :lower16:(_internal_global-([[ANCHOR:L[[:alnum:]_]+]]+4)) +; DARWIN-MOVT-NEXT: movt r[[ADDR]], :upper16:(_internal_global-([[ANCHOR]]+4)) +; DARWIN: [[ANCHOR:L[[:alnum:]_]+]]: +; CHECK-NEXT: add r[[ADDR:[0-9]+]], pc +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF: [[LABEL]]: +; ELF-NEXT: .long internal_global-([[ANCHOR]]+4) +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT-NEXT: .long _internal_global-([[ANCHOR]]+4) +; 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 r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ELF: [[ANCHOR:.L[[:alnum:]_]+]]: +; DARWIN-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; DARWIN-MOVT: movw r[[ADDR:[0-9]+]], :lower16:(L_external_global$non_lazy_ptr-([[ANCHOR:L[[:alnum:]_]+]]+4)) +; DARWIN-MOVT: movt r[[ADDR]], :upper16:(L_external_global$non_lazy_ptr-([[ANCHOR]]+4)) +; DARWIN: [[ANCHOR:L[[:alnum:]_]+]]: +; CHECK-NEXT: add r[[ADDR:[0-9]+]], pc +; CHECK-NEXT: ldr r[[ADDR:[0-9]+]], [r[[ADDR]]] +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF: [[LABEL]]: +; ELF: [[TMPLABEL:.L[[:alnum:]_]+]]: +; ELF: .long external_global(GOT_PREL)-(([[ANCHOR]]+4)-[[TMPLABEL]]) +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT: .long L_external_global$non_lazy_ptr-([[ANCHOR]]+4) +; DARWIN-NOMOVT-NOT: .long L_external_global +entry: + %v = load i32, i32* @external_global + ret i32 %v +} + +@internal_constant = internal constant i32 42 +define i32 @test_internal_constant() { +; CHECK-LABEL: test_internal_constant: +; ELF: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ELF: [[ANCHOR:.L[[:alnum:]_]+]]: +; DARWIN-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; DARWIN-MOVT: movw r[[ADDR:[0-9]+]], :lower16:(_internal_constant-([[ANCHOR:L[[:alnum:]_]+]]+4)) +; DARWIN-MOVT-NEXT: movt r[[ADDR]], :upper16:(_internal_constant-([[ANCHOR]]+4)) +; DARWIN: [[ANCHOR:L[[:alnum:]_]+]]: +; CHECK-NEXT: add r[[ADDR:[0-9]+]], pc +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF: [[LABEL]]: +; ELF-NEXT: .long internal_constant-([[ANCHOR]]+4) +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT-NEXT: .long _internal_constant-([[ANCHOR]]+4) +; DARWIN-MOVT-NOT: .long _internal_constant + +entry: + %v = load i32, i32* @internal_constant + ret i32 %v +} + +@external_constant = external constant i32 +define i32 @test_external_constant() { +; CHECK-LABEL: test_external_constant: +; ELF: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ELF: [[ANCHOR:.L[[:alnum:]_]+]]: +; DARWIN-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; DARWIN-MOVT: movw r[[ADDR:[0-9]+]], :lower16:(L_external_constant$non_lazy_ptr-([[ANCHOR:L[[:alnum:]_]+]]+4)) +; DARWIN-MOVT: movt r[[ADDR]], :upper16:(L_external_constant$non_lazy_ptr-([[ANCHOR]]+4)) +; DARWIN: [[ANCHOR:L[[:alnum:]_]+]]: +; CHECK-NEXT: add r[[ADDR:[0-9]+]], pc +; CHECK-NEXT: ldr r[[ADDR:[0-9]+]], [r[[ADDR]]] +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF: [[LABEL]]: +; ELF: [[TMPLABEL:.L[[:alnum:]_]+]]: +; ELF: .long external_constant(GOT_PREL)-(([[ANCHOR]]+4)-[[TMPLABEL]]) +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT: .long L_external_constant$non_lazy_ptr-([[ANCHOR]]+4) +; DARWIN-NOMOVT-NOT: .long L_external_constant +entry: + %v = load i32, i32* @external_constant + ret i32 %v +} + +; ELF: internal_global: +; DARWIN: _internal_global: +; CHECK: .long 42 +; ELF: .size internal_global, 4 + +; ELF: internal_constant: +; DARWIN: _internal_constant: +; CHECK: .long 42 +; ELF: .size internal_constant, 4 + +; DARWIN-DAG: L_external_global$non_lazy_ptr: +; DARWIN-DAG: .indirect_symbol _external_global + +; DARWIN-DAG: L_external_constant$non_lazy_ptr: +; DARWIN-DAG: .indirect_symbol _external_constant diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-ropi-rwpi.ll b/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-ropi-rwpi.ll new file mode 100644 index 000000000000..2fbdc2f9e614 --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-ropi-rwpi.ll @@ -0,0 +1,122 @@ +; RUN: llc -mtriple thumbv7-linux -relocation-model=ropi -mattr=-no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-MOVT,RW-DEFAULT,ROPI-MOVT,ROPI +; RUN: llc -mtriple thumbv7-linux -relocation-model=ropi -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-NOMOVT,RW-DEFAULT,ROPI-NOMOVT,ROPI +; RUN: llc -mtriple thumbv7-linux -relocation-model=rwpi -mattr=-no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RO-DEFAULT-MOVT,RO-DEFAULT,RWPI-MOVT,RWPI +; RUN: llc -mtriple thumbv7-linux -relocation-model=rwpi -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RO-DEFAULT-NOMOVT,RO-DEFAULT,RWPI-NOMOVT,RWPI +; RUN: llc -mtriple thumbv7-linux -relocation-model=ropi-rwpi -mattr=-no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ROPI-MOVT,ROPI,RWPI-MOVT,RWPI +; RUN: llc -mtriple thumbv7-linux -relocation-model=ropi-rwpi -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ROPI-NOMOVT,ROPI,RWPI-NOMOVT,RWPI + +@internal_global = internal global i32 42 +define i32 @test_internal_global() { +; CHECK-LABEL: test_internal_global: +; RW-DEFAULT-MOVT: movw r[[ADDR:[0-9]+]], :lower16:internal_global +; RW-DEFAULT-MOVT-NEXT: movt r[[ADDR]], :upper16:internal_global +; RW-DEFAULT-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; RW-DEFAULT-NEXT: ldr r0, [r[[ADDR]]] +; RW-DEFAULT-NEXT: bx lr +; RW-DEFAULT-NOMOVT: [[LABEL]]: +; RW-DEFAULT-NOMOVT-NEXT: .long internal_global + +; RWPI-MOVT: movw r[[ADDR:[0-9]+]], :lower16:internal_global(sbrel) +; RWPI-MOVT-NEXT: movt r[[ADDR]], :upper16:internal_global(sbrel) +; RWPI-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; RWPI-NEXT: add r[[ADDR:[0-9]+]], r9 +; RWPI-NEXT: ldr r0, [r[[ADDR]]] +; RWPI-NEXT: bx lr +; RWPI-NOMOVT: [[LABEL]]: +; RWPI-NOMOVT-NEXT: .long internal_global(sbrel) +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: +; RW-DEFAULT-MOVT: movw r[[ADDR:[0-9]+]], :lower16:external_global +; RW-DEFAULT-MOVT-NEXT: movt r[[ADDR]], :upper16:external_global +; RW-DEFAULT-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; RW-DEFAULT-NEXT: ldr r0, [r[[ADDR]]] +; RW-DEFAULT-NEXT: bx lr +; RW-DEFAULT-NOMOVT: [[LABEL]]: +; RW-DEFAULT-NOMOVT: .long external_global + +; RWPI-MOVT: movw r[[ADDR:[0-9]+]], :lower16:external_global(sbrel) +; RWPI-MOVT-NEXT: movt r[[ADDR]], :upper16:external_global(sbrel) +; RWPI-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; RWPI-NEXT: add r[[ADDR:[0-9]+]], r9 +; RWPI-NEXT: ldr r0, [r[[ADDR]]] +; RWPI-NEXT: bx lr +; RWPI-NOMOVT: [[LABEL]]: +; RWPI-NOMOVT-NEXT: .long external_global(sbrel) +entry: + %v = load i32, i32* @external_global + ret i32 %v +} + +@internal_constant = internal constant i32 42 +define i32 @test_internal_constant() { +; CHECK-LABEL: test_internal_constant: +; ROPI-MOVT: movw r[[ADDR:[0-9]+]], :lower16:(internal_constant-([[ANCHOR:.L[[:alnum:]_]+]]+4) +; ROPI-MOVT-NEXT: movt r[[ADDR]], :upper16:(internal_constant-([[ANCHOR]]+4) +; ROPI-MOVT-NEXT: [[ANCHOR]]: +; ROPI-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ROPI-NOMOVT-NEXT: [[ANCHOR:.L[[:alnum:]_]+]]: +; ROPI-NEXT: add r[[ADDR:[0-9]+]], pc +; ROPI-NEXT: ldr r0, [r[[ADDR]]] +; ROPI-NEXT: bx lr +; ROPI-NOMOVT: [[LABEL]]: +; ROPI-NOMOVT-NEXT: .long internal_constant-([[ANCHOR]]+4) + +; RO-DEFAULT-MOVT: movw r[[ADDR:[0-9]+]], :lower16:internal_constant +; RO-DEFAULT-MOVT-NEXT: movt r[[ADDR]], :upper16:internal_constant +; RO-DEFAULT-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; RO-DEFAULT-NEXT: ldr r0, [r[[ADDR]]] +; RO-DEFAULT-NEXT: bx lr +; RO-DEFAULT-NOMOVT: [[LABEL]]: +; RO-DEFAULT-NOMOVT-NEXT: .long internal_constant +entry: + %v = load i32, i32* @internal_constant + ret i32 %v +} + +@external_constant = external constant i32 +define i32 @test_external_constant() { +; CHECK-LABEL: test_external_constant: +; ROPI-MOVT: movw r[[ADDR:[0-9]+]], :lower16:(external_constant-([[ANCHOR:.L[[:alnum:]_]+]]+4) +; ROPI-MOVT-NEXT: movt r[[ADDR]], :upper16:(external_constant-([[ANCHOR]]+4) +; ROPI-MOVT-NEXT: [[ANCHOR]]: +; ROPI-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ROPI-NOMOVT-NEXT: [[ANCHOR:.L[[:alnum:]_]+]]: +; ROPI-NEXT: add r[[ADDR:[0-9]+]], pc +; ROPI-NEXT: ldr r0, [r[[ADDR]]] +; ROPI-NEXT: bx lr +; ROPI-NOMOVT: [[LABEL]]: +; ROPI-NOMOVT-NEXT: .long external_constant-([[ANCHOR]]+4) + +; RO-DEFAULT-MOVT: movw r[[ADDR:[0-9]+]], :lower16:external_constant +; RO-DEFAULT-MOVT-NEXT: movt r[[ADDR]], :upper16:external_constant +; RO-DEFAULT-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; RO-DEFAULT-NEXT: ldr r0, [r[[ADDR]]] +; RO-DEFAULT-NEXT: bx lr +; RO-DEFAULT-NOMOVT: [[LABEL]]: +; RO-DEFAULT-NOMOVT: .long external_constant +entry: + %v = load i32, i32* @external_constant + ret i32 %v +} + +; RW-DEFAULT-NOMOVT: internal_global: +; RW-DEFAULT-NOMOVT: .long 42 +; RW-DEFAULT-NOMOVT: .size internal_global, 4 + +; RWPI-NOMOVT: internal_global: +; RWPI-NOMOVT: .long 42 +; RWPI-NOMOVT: .size internal_global, 4 + +; ROPI-NOMOVT: internal_constant: +; ROPI-NOMOVT: .long 42 +; ROPI-NOMOVT: .size internal_constant, 4 + +; RO-DEFAULT-NOMOVT: internal_constant: +; RO-DEFAULT-NOMOVT: .long 42 +; RO-DEFAULT-NOMOVT: .size internal_constant, 4 diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-static.ll b/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-static.ll new file mode 100644 index 000000000000..53819b92acfb --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-isel-globals-static.ll @@ -0,0 +1,50 @@ +; RUN: llc -mtriple thumbv7-linux -relocation-model=static -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF,ELF-MOVT +; RUN: llc -mtriple thumbv7-linux -relocation-model=static -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF,ELF-NOMOVT +; RUN: llc -mtriple thumbv7-darwin -relocation-model=static -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN,DARWIN-MOVT +; RUN: llc -mtriple thumbv7-darwin -relocation-model=static -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-MOVT: movw r[[ADDR:[0-9]+]], :lower16:internal_global +; ELF-MOVT-NEXT: movt r[[ADDR]], :upper16:internal_global +; ELF-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; DARWIN-MOVT: movw r[[ADDR:[0-9]+]], :lower16:_internal_global +; DARWIN-MOVT-NEXT: movt r[[ADDR]], :upper16:_internal_global +; DARWIN-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF-NOMOVT: [[LABEL]]: +; ELF-NOMOVT-NEXT: .long internal_global +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT-NEXT: .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-MOVT: movw r[[ADDR:[0-9]+]], :lower16:external_global +; ELF-MOVT-NEXT: movt r[[ADDR]], :upper16:external_global +; ELF-NOMOVT: ldr r[[ADDR:[0-9]+]], [[CONST_POOL:.L[[:alnum:]_]+]] +; DARWIN-MOVT: movw r[[ADDR:[0-9]+]], :lower16:_external_global +; DARWIN-MOVT: movt r[[ADDR]], :upper16:_external_global +; DARWIN-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:L[[:alnum:]_]+]] +; CHECK-NEXT: ldr r0, [r[[ADDR]]] +; CHECK-NEXT: bx lr +; ELF-NOMOVT: [[CONST_POOL]]: +; ELF-NOMOVT: .long external_global +; DARWIN-NOMOVT: [[LABEL]]: +; DARWIN-NOMOVT: .long _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 diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-pic.mir b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-pic.mir new file mode 100644 index 000000000000..ca76220bd062 --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-pic.mir @@ -0,0 +1,127 @@ +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=pic -mattr=+v6t2,+no-movt -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +# RUN: llc -O0 -mtriple thumb-linux-linux -relocation-model=pic -mattr=+v6t2,-no-movt -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF +# RUN: llc -O0 -mtriple thumb-linux-darwin -relocation-model=pic -mattr=+v6t2,+no-movt -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN-NOMOVT +# RUN: llc -O0 -mtriple thumb-linux-darwin -relocation-model=pic -mattr=+v6t2,-no-movt -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 } + + @internal_constant = internal constant i32 42 + define void @test_internal_constant() { ret void } + + @external_constant = external constant i32 + define void @test_external_constant() { 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]+]]:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @internal_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel target-flags(arm-nonlazy) @internal_global + ; ELF: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel @internal_global + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @internal_global) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, 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_GOT:%[0-9]+]]:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @external_global + ; DARWIN-MOVT: [[G:%[0-9]+]]:gpr = t2LDRi12 [[G_GOT]], 0, 14, $noreg :: (load 4 from got) + ; DARWIN-NOMOVT: [[G_GOT:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel target-flags(arm-nonlazy) @external_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRi12 [[G_GOT]], 0, 14, $noreg :: (load 4 from got) + ; ELF: [[G_GOT:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel target-flags(arm-got) @external_global + ; ELF: [[G:%[0-9]+]]:gpr = t2LDRi12 [[G_GOT]], 0, 14, $noreg :: (load 4 from got) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @external_global) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +... +--- +name: test_internal_constant +# CHECK-LABEL: name: test_internal_constant +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_constant + ; DARWIN-MOVT: [[G:%[0-9]+]]:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @internal_constant + ; DARWIN-NOMOVT: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel target-flags(arm-nonlazy) @internal_constant + ; ELF: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel @internal_constant + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_constant) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @internal_constant) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +... +--- +name: test_external_constant +# CHECK-LABEL: name: test_external_constant +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_constant + ; DARWIN-MOVT: [[G_GOT:%[0-9]+]]:rgpr = t2MOV_ga_pcrel target-flags(arm-nonlazy) @external_constant + ; DARWIN-MOVT: [[G:%[0-9]+]]:gpr = t2LDRi12 [[G_GOT]], 0, 14, $noreg :: (load 4 from got) + ; DARWIN-NOMOVT: [[G_GOT:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel target-flags(arm-nonlazy) @external_constant + ; DARWIN-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRi12 [[G_GOT]], 0, 14, $noreg :: (load 4 from got) + ; ELF: [[G_GOT:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel target-flags(arm-got) @external_constant + ; ELF: [[G:%[0-9]+]]:gpr = t2LDRi12 [[G_GOT]], 0, 14, $noreg :: (load 4 from got) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_constant) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @external_constant) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-ropi-rwpi.mir b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-ropi-rwpi.mir new file mode 100644 index 000000000000..cbe99f93aa6a --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-ropi-rwpi.mir @@ -0,0 +1,147 @@ +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=ropi -mattr=-no-movt,+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-MOVT,ROPI-MOVT +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=ropi -mattr=+no-movt,+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-NOMOVT,ROPI-NOMOVT +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=rwpi -mattr=-no-movt,+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-MOVT,RWPI,RO-DEFAULT-MOVT +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=rwpi -mattr=+no-movt,+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-NOMOVT,RWPI,RO-DEFAULT-NOMOVT +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=ropi-rwpi -mattr=-no-movt,+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-MOVT,RWPI,ROPI-MOVT +# RUN: llc -O0 -mtriple thumb-linux -relocation-model=ropi-rwpi -mattr=+no-movt,+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-NOMOVT,RWPI,ROPI-NOMOVT +--- | + @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 } + + @internal_constant = internal constant i32 42 + define void @test_internal_constant() { ret void } + + @external_constant = external constant i32 + define void @test_external_constant() { 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 } +# RW-DEFAULT-NOMOVT: constants: +# RW-DEFAULT-NOMOVT: id: 0 +# RW-DEFAULT-NOMOVT: value: 'i32* @internal_global' +# RWPI-NOMOVT: constants: +# RWPI-NOMOVT: id: 0 +# RWPI-NOMOVT: value: 'internal_global(SBREL)' +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @internal_global + ; RW-DEFAULT-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @internal_global + ; RW-DEFAULT-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + ; RWPI-MOVT: [[OFF:%[0-9]+]]:rgpr = t2MOVi32imm target-flags(arm-sbrel) @internal_global + ; RWPI-NOMOVT: [[OFF:%[0-9]+]]:rgpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + ; RWPI: [[G:%[0-9]+]]:gprnopc = t2ADDrr $r9, [[OFF]], 14, $noreg, $noreg + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @internal_global) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, 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 } +# RW-DEFAULT-NOMOVT: constants: +# RW-DEFAULT-NOMOVT: id: 0 +# RW-DEFAULT-NOMOVT: value: 'i32* @external_global' +# RWPI-NOMOVT: constants: +# RWPI-NOMOVT: id: 0 +# RWPI-NOMOVT: value: 'external_global(SBREL)' +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @external_global + ; RW-DEFAULT-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @external_global + ; RW-DEFAULT-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + ; RWPI-MOVT: [[OFF:%[0-9]+]]:rgpr = t2MOVi32imm target-flags(arm-sbrel) @external_global + ; RWPI-NOMOVT: [[OFF:%[0-9]+]]:rgpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + ; RWPI: [[G:%[0-9]+]]:gprnopc = t2ADDrr $r9, [[OFF]], 14, $noreg, $noreg + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @external_global) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +... +--- +name: test_internal_constant +# CHECK-LABEL: name: test_internal_constant +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } +# RO-DEFAULT-NOMOVT: constants: +# RO-DEFAULT-NOMOVT: id: 0 +# RO-DEFAULT-NOMOVT: value: 'i32* @internal_constant' +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @internal_constant + ; ROPI-MOVT: [[G:%[0-9]+]]:rgpr = t2MOV_ga_pcrel @internal_constant + ; ROPI-NOMOVT: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel @internal_constant + ; RO-DEFAULT-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @internal_constant + ; RO-DEFAULT-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_constant) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @internal_constant) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +... +--- +name: test_external_constant +# CHECK-LABEL: name: test_external_constant +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } +# RO-DEFAULT-NOMOVT: constants: +# RO-DEFAULT-NOMOVT: id: 0 +# RO-DEFAULT-NOMOVT: value: 'i32* @external_constant' +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @external_constant + ; ROPI-MOVT: [[G:%[0-9]+]]:rgpr = t2MOV_ga_pcrel @external_constant + ; ROPI-NOMOVT: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_pcrel @external_constant + ; RO-DEFAULT-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @external_constant + ; RO-DEFAULT-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_constant) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @external_constant) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-static.mir b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-static.mir new file mode 100644 index 000000000000..6e1e991fc7ec --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-globals-static.mir @@ -0,0 +1,71 @@ +# RUN: llc -O0 -mtriple thumb-linux -mattr=+v6t2 -relocation-model=static -mattr=+no-movt -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF-NOMOVT +# RUN: llc -O0 -mtriple thumb-linux -mattr=+v6t2 -relocation-model=static -mattr=-no-movt,+v8m -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF-MOVT +# RUN: llc -O0 -mtriple thumb-darwin -mattr=+v6t2 -relocation-model=static -mattr=+no-movt -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN-NOMOVT +# RUN: llc -O0 -mtriple thumb-darwin -mattr=+v6t2 -relocation-model=static -mattr=-no-movt,+v8m -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 } +# ELF-NOMOVT: constants: +# ELF-NOMOVT: id: 0 +# ELF-NOMOVT: value: 'i32* @internal_global' +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @internal_global + ; ELF-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @internal_global + ; ELF-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + ; DARWIN-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @internal_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_abs @internal_global + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @internal_global) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, 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 } +# ELF-NOMOVT: constants: +# ELF-NOMOVT: id: 0 +# ELF-NOMOVT: value: 'i32* @external_global' +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @external_global + ; ELF-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @external_global + ; ELF-NOMOVT: [[G:%[0-9]+]]:gpr = t2LDRpci %const.0, 14, $noreg :: (load 4 from constant-pool) + ; DARWIN-MOVT: [[G:%[0-9]+]]:rgpr = t2MOVi32imm @external_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]]:tgpr = tLDRLIT_ga_abs @external_global + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global) + ; CHECK: [[V:%[0-9]+]]:gpr = t2LDRi12 [[G]], 0, 14, $noreg :: (load 4 from @external_global) + + $r0 = COPY %1(s32) + ; CHECK: $r0 = COPY [[V]] + + tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET 14, $noreg, implicit $r0 +...