Index: lib/Target/ARM/ARMInstructionSelector.cpp =================================================================== --- lib/Target/ARM/ARMInstructionSelector.cpp +++ lib/Target/ARM/ARMInstructionSelector.cpp @@ -15,6 +15,7 @@ #include "ARMSubtarget.h" #include "ARMTargetMachine.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" @@ -60,6 +61,7 @@ // Set \p DestReg to \p Constant. void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const; + bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const; bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const; // Check if the types match and both operands have the expected size and @@ -488,6 +490,59 @@ return true; } +bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, + MachineRegisterInfo &MRI) const { + if (TII.getSubtarget().isROPI() || TII.getSubtarget().isRWPI()) { + DEBUG(dbgs() << "ROPI and RWPI not supported yet\n"); + return false; + } + if (TM.isPositionIndependent()) { + DEBUG(dbgs() << "PIC not supported yet\n"); + return false; + } + + auto GV = MIB->getOperand(1).getGlobal(); + if (GV->isThreadLocal()) { + DEBUG(dbgs() << "TLS variables not supported yet\n"); + return false; + } + + auto &MBB = *MIB->getParent(); + auto &MF = *MBB.getParent(); + + auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat(); + bool UseMovt = TII.getSubtarget().useMovt(MF); + + if (ObjectFormat == Triple::ELF) { + if (UseMovt) { + MIB->setDesc(TII.get(ARM::MOVi32imm)); + } else { + // Load the global's address from the constant pool. + MIB->setDesc(TII.get(ARM::LDRi12)); + MIB->RemoveOperand(1); + unsigned Alignment = 4; + 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)); + } + } else if (ObjectFormat == Triple::MachO) { + if (UseMovt) + MIB->setDesc(TII.get(ARM::MOVi32imm)); + else + MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); + } else { + DEBUG(dbgs() << "Object format not supported yet\n"); + return false; + } + + return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); +} + bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { auto &MBB = *MIB->getParent(); @@ -683,6 +738,8 @@ break; } + case G_GLOBAL_VALUE: + return selectGlobal(MIB, MRI); case G_STORE: case G_LOAD: { const auto &MemOp = **I.memoperands_begin(); Index: test/CodeGen/ARM/GlobalISel/arm-instruction-select-globals.mir =================================================================== --- /dev/null +++ test/CodeGen/ARM/GlobalISel/arm-instruction-select-globals.mir @@ -0,0 +1,71 @@ +# RUN: llc -O0 -mtriple arm-linux -relocation-model=static -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF-NOMOVT +# RUN: llc -O0 -mtriple arm-linux -relocation-model=static -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,ELF-MOVT +# RUN: llc -O0 -mtriple arm-darwin -relocation-model=static -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN-NOMOVT +# RUN: llc -O0 -mtriple arm-darwin -relocation-model=static -mattr=-no-movt,+v8m -global-isel -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]+]] = MOVi32imm @internal_global + ; ELF-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool) + ; DARWIN-MOVT: [[G:%[0-9]+]] = MOVi32imm @internal_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_abs @internal_global + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ + + %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 } +# 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]+]] = MOVi32imm @external_global + ; ELF-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool) + ; DARWIN-MOVT: [[G:%[0-9]+]] = MOVi32imm @external_global + ; DARWIN-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_abs @external_global + + %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global) + ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ + + %r0 = COPY %1(s32) + ; CHECK: %r0 = COPY [[V]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, implicit %r0 +... Index: test/CodeGen/ARM/GlobalISel/arm-isel-globals.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/GlobalISel/arm-isel-globals.ll @@ -0,0 +1,50 @@ +; RUN: llc -mtriple armv7-linux -relocation-model=static -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF,ELF-MOVT +; RUN: llc -mtriple armv7-linux -relocation-model=static -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ELF,ELF-NOMOVT +; RUN: llc -mtriple armv7-darwin -relocation-model=static -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,DARWIN,DARWIN-MOVT +; RUN: llc -mtriple armv7-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 Index: test/CodeGen/ARM/GlobalISel/arm-unsupported.ll =================================================================== --- test/CodeGen/ARM/GlobalISel/arm-unsupported.ll +++ test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -1,4 +1,8 @@ -; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' %s -o - 2>&1 | FileCheck %s +; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' %s -o - 2>&1 | FileCheck %s -check-prefixes=CHECK +; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=pic %s -o - 2>&1 | FileCheck %s -check-prefixes=PIC +; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=ropi %s -o - 2>&1 | FileCheck %s -check-prefixes=ROPI +; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=rwpi %s -o - 2>&1 | FileCheck %s -check-prefixes=RWPI +; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=ropi-rwpi %s -o - 2>&1 | FileCheck %s -check-prefixes=ROPI-RWPI ; This file checks that we use the fallback path for things that are known to ; be unsupported on the ARM target. It should progressively shrink in size. @@ -92,4 +96,37 @@ ret i32 %a } +@thread_local_global = thread_local global i32 42 + +define i32 @test_thread_local_global() { +; CHECK: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; CHECK-LABEL: warning: Instruction selection used fallback path for test_thread_local_global +; PIC: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; PIC-LABEL: warning: Instruction selection used fallback path for test_thread_local_global +; ROPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; ROPI-LABEL: warning: Instruction selection used fallback path for test_thread_local_global +; RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; RWPI-LABEL: warning: Instruction selection used fallback path for test_thread_local_global +; ROPI-RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; ROPI-RWPI-LABEL: warning: Instruction selection used fallback path for test_thread_local_global + %v = load i32, i32* @thread_local_global + ret i32 %v +} + +@a_global = external global i32 + +define i32 @test_global_reloc_models() { +; This is only unsupported for the PIC, ROPI, RWPI relocation modes. +; PIC: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; PIC-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models +; ROPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE +; ROPI-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models +; 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" }