forked from OSchip/llvm-project
[ARM] GlobalISel: Support global variables for RWPI
In RWPI code, globals that are not read-only are accessed relative to the SB register (R9). This is achieved by explicitly generating an ADD instruction between SB and an offset that we either load from a constant pool or movw + movt into a register. llvm-svn: 312521
This commit is contained in:
parent
c228d790af
commit
abb088691b
|
@ -488,13 +488,8 @@ bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
|
|||
|
||||
bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
||||
MachineRegisterInfo &MRI) const {
|
||||
if (TII.getSubtarget().isRWPI()) {
|
||||
DEBUG(dbgs() << "RWPI not supported yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (STI.isROPI() && !STI.isTargetELF()) {
|
||||
DEBUG(dbgs() << "ROPI only supported for ELF\n");
|
||||
if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
|
||||
DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -510,7 +505,29 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
|||
auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat();
|
||||
bool UseMovt = TII.getSubtarget().useMovt(MF);
|
||||
|
||||
unsigned Size = TM.getPointerSize();
|
||||
unsigned Alignment = 4;
|
||||
|
||||
auto addOpsForConstantPoolLoad = [&MF, Alignment,
|
||||
Size](MachineInstrBuilder &MIB,
|
||||
const GlobalValue *GV, bool IsSBREL) {
|
||||
assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction");
|
||||
auto ConstPool = MF.getConstantPool();
|
||||
auto CPIndex =
|
||||
// For SB relative entries we need a target-specific constant pool.
|
||||
// Otherwise, just use a regular constant pool entry.
|
||||
IsSBREL
|
||||
? ConstPool->getConstantPoolIndex(
|
||||
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));
|
||||
};
|
||||
|
||||
if (TM.isPositionIndependent()) {
|
||||
bool Indirect = TII.getSubtarget().isGVIndirectSymbol(GV);
|
||||
// FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
|
||||
|
@ -538,6 +555,32 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
|||
MIB->setDesc(TII.get(Opc));
|
||||
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
|
||||
}
|
||||
if (STI.isRWPI() && !isReadOnly) {
|
||||
auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
|
||||
MachineInstrBuilder OffsetMIB;
|
||||
if (UseMovt) {
|
||||
OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
|
||||
TII.get(ARM::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);
|
||||
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->RemoveOperand(1);
|
||||
MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
|
||||
.addReg(Offset)
|
||||
.add(predOps(ARMCC::AL))
|
||||
.add(condCodeOp());
|
||||
|
||||
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
|
||||
}
|
||||
|
||||
if (ObjectFormat == Triple::ELF) {
|
||||
if (UseMovt) {
|
||||
|
@ -546,14 +589,7 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
|
|||
// Load the global's address from the constant pool.
|
||||
MIB->setDesc(TII.get(ARM::LDRi12));
|
||||
MIB->RemoveOperand(1);
|
||||
MIB.addConstantPoolIndex(
|
||||
MF.getConstantPool()->getConstantPoolIndex(GV, Alignment),
|
||||
/* Offset */ 0, /* TargetFlags */ 0)
|
||||
.addMemOperand(MF.getMachineMemOperand(
|
||||
MachinePointerInfo::getConstantPool(MF),
|
||||
MachineMemOperand::MOLoad, TM.getPointerSize(), Alignment))
|
||||
.addImm(0)
|
||||
.add(predOps(ARMCC::AL));
|
||||
addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
|
||||
}
|
||||
} else if (ObjectFormat == Triple::MachO) {
|
||||
if (UseMovt)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
; RUN: llc -mtriple armv7-linux -relocation-model=ropi -mattr=-no-movt,+v8m -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-MOVT,RW-DEFAULT,ROPI-MOVT,ROPI
|
||||
; RUN: llc -mtriple armv7-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 armv7-linux -relocation-model=rwpi -mattr=-no-movt,+v8m -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RO-DEFAULT-MOVT,RO-DEFAULT,RWPI-MOVT,RWPI
|
||||
; RUN: llc -mtriple armv7-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 armv7-linux -relocation-model=ropi-rwpi -mattr=-no-movt,+v8m -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ROPI-MOVT,ROPI,RWPI-MOVT,RWPI
|
||||
; RUN: llc -mtriple armv7-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() {
|
||||
|
@ -11,6 +15,15 @@ define i32 @test_internal_global() {
|
|||
; RW-DEFAULT-NEXT: bx lr
|
||||
; RW-DEFAULT-NOMOVT: [[LABEL]]:
|
||||
; RW-DEFAULT-NOMOVT-NEXT: .long internal_global
|
||||
|
||||
; RWPI-MOVT: movw [[OFFSET:r[0-9]+]], :lower16:internal_global(sbrel)
|
||||
; RWPI-MOVT-NEXT: movt [[OFFSET]], :upper16:internal_global(sbrel)
|
||||
; RWPI-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]]
|
||||
; RWPI-NEXT: add r[[ADDR:[0-9]+]], r9, [[OFFSET]]
|
||||
; 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
|
||||
|
@ -26,6 +39,15 @@ define i32 @test_external_global() {
|
|||
; RW-DEFAULT-NEXT: bx lr
|
||||
; RW-DEFAULT-NOMOVT: [[LABEL]]:
|
||||
; RW-DEFAULT-NOMOVT: .long external_global
|
||||
|
||||
; RWPI-MOVT: movw [[OFFSET:r[0-9]+]], :lower16:external_global(sbrel)
|
||||
; RWPI-MOVT-NEXT: movt [[OFFSET]], :upper16:external_global(sbrel)
|
||||
; RWPI-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]]
|
||||
; RWPI-NEXT: add r[[ADDR:[0-9]+]], r9, [[OFFSET]]
|
||||
; 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
|
||||
|
@ -44,6 +66,14 @@ define i32 @test_internal_constant() {
|
|||
; ROPI-NEXT: bx lr
|
||||
; ROPI-NOMOVT: [[LABEL]]:
|
||||
; ROPI-NOMOVT-NEXT: .long internal_constant-([[ANCHOR]]+8)
|
||||
|
||||
; 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
|
||||
|
@ -62,6 +92,14 @@ define i32 @test_external_constant() {
|
|||
; ROPI-NEXT: bx lr
|
||||
; ROPI-NOMOVT: [[LABEL]]:
|
||||
; ROPI-NOMOVT-NEXT: .long external_constant-([[ANCHOR]]+8)
|
||||
|
||||
; 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
|
||||
|
@ -71,6 +109,14 @@ entry:
|
|||
; 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
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-MOVT,RW-DEFAULT,ROPI-MOVT,ROPI
|
||||
# RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-NOMOVT,RW-DEFAULT,ROPI-NOMOVT,ROPI
|
||||
# RUN: llc -O0 -mtriple arm-linux -relocation-model=rwpi -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-MOVT,RWPI,RO-DEFAULT-MOVT,RO-DEFAULT
|
||||
# RUN: llc -O0 -mtriple arm-linux -relocation-model=rwpi -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-NOMOVT,RWPI,RO-DEFAULT-NOMOVT,RO-DEFAULT
|
||||
# RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi-rwpi -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-MOVT,RWPI,ROPI-MOVT,ROPI
|
||||
# RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi-rwpi -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-NOMOVT,RWPI,ROPI-NOMOVT,ROPI
|
||||
--- |
|
||||
@internal_global = internal global i32 42
|
||||
define void @test_internal_global() { ret void }
|
||||
|
@ -26,11 +30,17 @@ registers:
|
|||
# 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]+]] = MOVi32imm @internal_global
|
||||
; RW-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
|
||||
; RWPI-MOVT: [[OFF:%[0-9]+]] = MOVi32imm {{.*}} @internal_global
|
||||
; RWPI-NOMOVT: [[OFF:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
|
||||
; RWPI: [[G:%[0-9]+]] = ADDrr %r9, [[OFF]], 14, _, _
|
||||
|
||||
%1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global)
|
||||
; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_global)
|
||||
|
@ -54,11 +64,17 @@ registers:
|
|||
# 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]+]] = MOVi32imm @external_global
|
||||
; RW-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
|
||||
; RWPI-MOVT: [[OFF:%[0-9]+]] = MOVi32imm {{.*}} @external_global
|
||||
; RWPI-NOMOVT: [[OFF:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
|
||||
; RWPI: [[G:%[0-9]+]] = ADDrr %r9, [[OFF]], 14, _, _
|
||||
|
||||
%1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global)
|
||||
; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_global)
|
||||
|
@ -79,11 +95,16 @@ selected: false
|
|||
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]+]] = MOV_ga_pcrel @internal_constant
|
||||
; ROPI-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel @internal_constant
|
||||
; RO-DEFAULT-MOVT: [[G:%[0-9]+]] = MOVi32imm @internal_constant
|
||||
; RO-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
|
||||
|
||||
%1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_constant)
|
||||
; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_constant)
|
||||
|
@ -104,11 +125,16 @@ selected: false
|
|||
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]+]] = MOV_ga_pcrel @external_constant
|
||||
; ROPI-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel @external_constant
|
||||
; RO-DEFAULT-MOVT: [[G:%[0-9]+]] = MOVi32imm @external_constant
|
||||
; RO-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
|
||||
|
||||
%1(s32) = G_LOAD %0(p0) :: (load 4 from @external_constant)
|
||||
; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_constant)
|
||||
|
|
|
@ -113,16 +113,4 @@ define i32 @test_thread_local_global() {
|
|||
ret i32 %v
|
||||
}
|
||||
|
||||
@a_global = external global i32
|
||||
|
||||
define i32 @test_global_reloc_models() {
|
||||
; This is only unsupported for the RWPI relocation modes.
|
||||
; RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
||||
; RWPI-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models
|
||||
; ROPI-RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
||||
; ROPI-RWPI-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models
|
||||
%v = load i32, i32* @a_global
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="+thumb-mode" }
|
||||
|
|
Loading…
Reference in New Issue