forked from OSchip/llvm-project
[ARM GlobalISel] Support global variables for Thumb2
Add the same level of support as for ARM mode (i.e. still no TLS support). In most cases, it is sufficient to replace the opcodes with the t2-equivalent, but there are some idiosyncrasies that I decided to preserve because I don't understand the full implications: * For ARM we use LDRi12 to load from constant pools, but for Thumb we use t2LDRpci (I'm not sure if the ideal would be to use t2LDRi12 for Thumb as well, or to use LDRcp for ARM). * For Thumb we don't have an equivalent for MOV|LDRLIT_ga_pcrel_ldr, so we have to generate MOV|LDRLIT_ga_pcrel plus a load from GOT. The tests are in separate files because they're hard enough to read even without doubling the number of checks. llvm-svn: 355077
This commit is contained in:
parent
ff5e4bcad0
commit
3b7beafc77
|
@ -112,6 +112,13 @@ private:
|
||||||
unsigned TSTri;
|
unsigned TSTri;
|
||||||
unsigned Bcc;
|
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);
|
OpcodeCache(const ARMSubtarget &STI);
|
||||||
} const Opcodes;
|
} const Opcodes;
|
||||||
|
|
||||||
|
@ -312,6 +319,12 @@ ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
|
||||||
|
|
||||||
STORE_OPCODE(TSTri, TSTri);
|
STORE_OPCODE(TSTri, TSTri);
|
||||||
STORE_OPCODE(Bcc, Bcc);
|
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
|
#undef MAP_OPCODE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,7 +622,9 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
||||||
auto addOpsForConstantPoolLoad = [&MF, Alignment,
|
auto addOpsForConstantPoolLoad = [&MF, Alignment,
|
||||||
Size](MachineInstrBuilder &MIB,
|
Size](MachineInstrBuilder &MIB,
|
||||||
const GlobalValue *GV, bool IsSBREL) {
|
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 ConstPool = MF.getConstantPool();
|
||||||
auto CPIndex =
|
auto CPIndex =
|
||||||
// For SB relative entries we need a target-specific constant pool.
|
// 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)
|
ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
|
||||||
: ConstPool->getConstantPoolIndex(GV, Alignment);
|
: ConstPool->getConstantPoolIndex(GV, Alignment);
|
||||||
MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
|
MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
|
||||||
.addMemOperand(
|
.addMemOperand(MF.getMachineMemOperand(
|
||||||
MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
|
MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
|
||||||
MachineMemOperand::MOLoad, Size, Alignment))
|
Size, Alignment));
|
||||||
.addImm(0)
|
if (MIB->getOpcode() == ARM::LDRi12)
|
||||||
.add(predOps(ARMCC::AL));
|
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()) {
|
if (TM.isPositionIndependent()) {
|
||||||
bool Indirect = STI.isGVIndirectSymbol(GV);
|
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
|
// FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
|
||||||
// support it yet. See PR28229.
|
// support it yet. See PR28229.
|
||||||
unsigned Opc =
|
unsigned Opc = UseMovt && !STI.isTargetELF()
|
||||||
UseMovt && !STI.isTargetELF()
|
? (UseOpcodeThatLoads ? ARM::MOV_ga_pcrel_ldr
|
||||||
? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel)
|
: Opcodes.MOV_ga_pcrel)
|
||||||
: (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel);
|
: (UseOpcodeThatLoads ? ARM::LDRLIT_ga_pcrel_ldr
|
||||||
|
: Opcodes.LDRLIT_ga_pcrel);
|
||||||
MIB->setDesc(TII.get(Opc));
|
MIB->setDesc(TII.get(Opc));
|
||||||
|
|
||||||
int TargetFlags = ARMII::MO_NO_FLAG;
|
int TargetFlags = ARMII::MO_NO_FLAG;
|
||||||
|
@ -643,17 +674,35 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
||||||
TargetFlags |= ARMII::MO_GOT;
|
TargetFlags |= ARMII::MO_GOT;
|
||||||
MIB->getOperand(1).setTargetFlags(TargetFlags);
|
MIB->getOperand(1).setTargetFlags(TargetFlags);
|
||||||
|
|
||||||
if (Indirect)
|
if (Indirect) {
|
||||||
MIB.addMemOperand(MF.getMachineMemOperand(
|
if (!UseOpcodeThatLoads) {
|
||||||
MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
|
auto ResultReg = MIB->getOperand(0).getReg();
|
||||||
TM.getProgramPointerSize(), Alignment));
|
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);
|
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
|
bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
|
||||||
if (STI.isROPI() && isReadOnly) {
|
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));
|
MIB->setDesc(TII.get(Opc));
|
||||||
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
|
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
|
||||||
}
|
}
|
||||||
|
@ -662,19 +711,19 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
||||||
MachineInstrBuilder OffsetMIB;
|
MachineInstrBuilder OffsetMIB;
|
||||||
if (UseMovt) {
|
if (UseMovt) {
|
||||||
OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
|
OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
|
||||||
TII.get(ARM::MOVi32imm), Offset);
|
TII.get(Opcodes.MOVi32imm), Offset);
|
||||||
OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
|
OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
|
||||||
} else {
|
} else {
|
||||||
// Load the offset from the constant pool.
|
// Load the offset from the constant pool.
|
||||||
OffsetMIB =
|
OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
|
||||||
BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset);
|
TII.get(Opcodes.ConstPoolLoad), Offset);
|
||||||
addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
|
addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
|
||||||
}
|
}
|
||||||
if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
|
if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Add the offset to the SB register.
|
// Add the offset to the SB register.
|
||||||
MIB->setDesc(TII.get(ARM::ADDrr));
|
MIB->setDesc(TII.get(Opcodes.ADDrr));
|
||||||
MIB->RemoveOperand(1);
|
MIB->RemoveOperand(1);
|
||||||
MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
|
MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
|
||||||
.addReg(Offset)
|
.addReg(Offset)
|
||||||
|
@ -686,18 +735,18 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
||||||
|
|
||||||
if (STI.isTargetELF()) {
|
if (STI.isTargetELF()) {
|
||||||
if (UseMovt) {
|
if (UseMovt) {
|
||||||
MIB->setDesc(TII.get(ARM::MOVi32imm));
|
MIB->setDesc(TII.get(Opcodes.MOVi32imm));
|
||||||
} else {
|
} else {
|
||||||
// Load the global's address from the constant pool.
|
// Load the global's address from the constant pool.
|
||||||
MIB->setDesc(TII.get(ARM::LDRi12));
|
MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
|
||||||
MIB->RemoveOperand(1);
|
MIB->RemoveOperand(1);
|
||||||
addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
|
addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
|
||||||
}
|
}
|
||||||
} else if (STI.isTargetMachO()) {
|
} else if (STI.isTargetMachO()) {
|
||||||
if (UseMovt)
|
if (UseMovt)
|
||||||
MIB->setDesc(TII.get(ARM::MOVi32imm));
|
MIB->setDesc(TII.get(Opcodes.MOVi32imm));
|
||||||
else
|
else
|
||||||
MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs));
|
MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
|
||||||
} else {
|
} else {
|
||||||
LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
|
LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -139,6 +139,7 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
|
||||||
{p0, p0, 32, 8}});
|
{p0, p0, 32, 8}});
|
||||||
|
|
||||||
getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
|
getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
|
||||||
|
getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
|
||||||
|
|
||||||
auto &PhiBuilder =
|
auto &PhiBuilder =
|
||||||
getActionDefinitionsBuilder(G_PHI)
|
getActionDefinitionsBuilder(G_PHI)
|
||||||
|
@ -212,8 +213,6 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
|
|
||||||
|
|
||||||
if (ST.hasV5TOps()) {
|
if (ST.hasV5TOps()) {
|
||||||
getActionDefinitionsBuilder(G_CTLZ)
|
getActionDefinitionsBuilder(G_CTLZ)
|
||||||
.legalFor({s32, s32})
|
.legalFor({s32, s32})
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
...
|
|
@ -6,9 +6,6 @@
|
||||||
|
|
||||||
define void @test_phi_s64() #0 { ret void }
|
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" }
|
attributes #0 = { "target-features"="+vfp2" }
|
||||||
...
|
...
|
||||||
---
|
---
|
||||||
|
@ -106,26 +103,3 @@ body: |
|
||||||
$d0 = COPY %4(s64)
|
$d0 = COPY %4(s64)
|
||||||
BX_RET 14, $noreg, implicit $d0
|
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
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
...
|
|
@ -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
|
||||||
|
...
|
|
@ -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
|
||||||
|
...
|
Loading…
Reference in New Issue