diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index fb5a37149548..13245895a377 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -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) diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll b/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll index 2616540003d5..f52fb769c1ef 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll @@ -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 diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir index fc8d3bc4152d..c31893cf2299 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir @@ -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) diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll b/llvm/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll index 19ccc1773e3b..bdba53563905 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -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" }