From 6470656cc2b5435ec7570bc567dc6bb24e334397 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Fri, 1 Sep 2017 11:13:39 +0000 Subject: [PATCH] [ARM] GlobalISel: Support ROPI global variables In the ROPI relocation model, read-only variables are accessed relative to the PC. We use the (MOV|LDRLIT)_ga_pcrel pseudoinstructions for this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312323 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstructionSelector.cpp | 16 ++- .../ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll | 76 +++++++++++++ .../GlobalISel/arm-select-globals-ropi-rwpi.mir | 121 +++++++++++++++++++++ test/CodeGen/ARM/GlobalISel/arm-unsupported.ll | 4 +- 4 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll create mode 100644 test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir diff --git a/lib/Target/ARM/ARMInstructionSelector.cpp b/lib/Target/ARM/ARMInstructionSelector.cpp index e2f94666252..fb5a3714954 100644 --- a/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/lib/Target/ARM/ARMInstructionSelector.cpp @@ -488,8 +488,13 @@ bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I, bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { - if (TII.getSubtarget().isROPI() || TII.getSubtarget().isRWPI()) { - DEBUG(dbgs() << "ROPI and RWPI not supported yet\n"); + 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"); return false; } @@ -527,6 +532,13 @@ bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, return true; } + bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV); + if (STI.isROPI() && isReadOnly) { + unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel; + MIB->setDesc(TII.get(Opc)); + return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); + } + if (ObjectFormat == Triple::ELF) { if (UseMovt) { MIB->setDesc(TII.get(ARM::MOVi32imm)); diff --git a/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll b/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll new file mode 100644 index 00000000000..2616540003d --- /dev/null +++ b/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll @@ -0,0 +1,76 @@ +; 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 + +@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 +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 +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 [[OFFSET:r[0-9]+]], :lower16:(internal_constant-([[ANCHOR:.L[[:alnum:]_]+]]+8) +; ROPI-MOVT-NEXT: movt [[OFFSET]], :upper16:(internal_constant-([[ANCHOR]]+8) +; ROPI-MOVT-NEXT: [[ANCHOR]]: +; ROPI-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ROPI-NOMOVT-NEXT: [[ANCHOR:.L[[:alnum:]_]+]]: +; ROPI-NEXT: add r[[ADDR:[0-9]+]], pc, [[OFFSET]] +; ROPI-NEXT: ldr r0, [r[[ADDR]]] +; ROPI-NEXT: bx lr +; ROPI-NOMOVT: [[LABEL]]: +; ROPI-NOMOVT-NEXT: .long internal_constant-([[ANCHOR]]+8) +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 [[OFFSET:r[0-9]+]], :lower16:(external_constant-([[ANCHOR:.L[[:alnum:]_]+]]+8) +; ROPI-MOVT-NEXT: movt [[OFFSET]], :upper16:(external_constant-([[ANCHOR]]+8) +; ROPI-MOVT-NEXT: [[ANCHOR]]: +; ROPI-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]] +; ROPI-NOMOVT-NEXT: [[ANCHOR:.L[[:alnum:]_]+]]: +; ROPI-NEXT: add r[[ADDR:[0-9]+]], pc, [[OFFSET]] +; ROPI-NEXT: ldr r0, [r[[ADDR]]] +; ROPI-NEXT: bx lr +; ROPI-NOMOVT: [[LABEL]]: +; ROPI-NOMOVT-NEXT: .long external_constant-([[ANCHOR]]+8) +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 + +; ROPI-NOMOVT: internal_constant: +; ROPI-NOMOVT: .long 42 +; ROPI-NOMOVT: .size internal_constant, 4 diff --git a/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir b/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir new file mode 100644 index 00000000000..fc8d3bc4152 --- /dev/null +++ b/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir @@ -0,0 +1,121 @@ +# 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 +--- | + @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' +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) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_global) + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, 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' +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) + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_global) + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, 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 + ; ROPI-MOVT: [[G:%[0-9]+]] = MOV_ga_pcrel @internal_constant + ; ROPI-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel @internal_constant + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_constant) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_constant) + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, 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 + ; ROPI-MOVT: [[G:%[0-9]+]] = MOV_ga_pcrel @external_constant + ; ROPI-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel @external_constant + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_constant) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_constant) + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, implicit %r0 +... diff --git a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll index 9d09fe0dda1..19ccc1773e3 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -116,9 +116,7 @@ define i32 @test_thread_local_global() { @a_global = external global i32 define i32 @test_global_reloc_models() { -; This is only unsupported for the PIC, ROPI, RWPI relocation modes. -; ROPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE -; ROPI-LABEL: warning: Instruction selection used fallback path for 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 -- 2.11.0