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;
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
}
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.
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;
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);
}
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)
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;
{p0, p0, 32, 8}});
getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
+ getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
auto &PhiBuilder =
getActionDefinitionsBuilder(G_PHI)
return;
}
- getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
-
if (ST.hasV5TOps()) {
getActionDefinitionsBuilder(G_CTLZ)
.legalFor({s32, s32})
--- /dev/null
+# 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
+
+...
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" }
...
---
$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
-
-...
--- /dev/null
+; 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
--- /dev/null
+; 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
--- /dev/null
+; 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
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...