[ARM] GlobalISel: Select simple G_GLOBAL_VALUE instructions
Add support in the instruction selector for G_GLOBAL_VALUE for ELF and MachO for the static relocation model. We don't handle Windows yet because that's Thumb-only, and we don't handle Thumb in general at the moment. Support for PIC, ROPI, RWPI and TLS will be added in subsequent commits. Differential Revision: https://reviews.llvm.org/D35883 llvm-svn: 309927
This commit is contained in:
parent
a0beedef1c
commit
930e6ec8f3
|
@ -15,6 +15,7 @@
|
||||||
#include "ARMSubtarget.h"
|
#include "ARMSubtarget.h"
|
||||||
#include "ARMTargetMachine.h"
|
#include "ARMTargetMachine.h"
|
||||||
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
||||||
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
|
||||||
|
@ -60,6 +61,7 @@ private:
|
||||||
// Set \p DestReg to \p Constant.
|
// Set \p DestReg to \p Constant.
|
||||||
void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
|
void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
|
||||||
|
|
||||||
|
bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
|
||||||
bool selectSelect(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
|
// Check if the types match and both operands have the expected size and
|
||||||
|
@ -488,6 +490,59 @@ bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
|
||||||
return true;
|
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,
|
bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
|
||||||
MachineRegisterInfo &MRI) const {
|
MachineRegisterInfo &MRI) const {
|
||||||
auto &MBB = *MIB->getParent();
|
auto &MBB = *MIB->getParent();
|
||||||
|
@ -683,6 +738,8 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case G_GLOBAL_VALUE:
|
||||||
|
return selectGlobal(MIB, MRI);
|
||||||
case G_STORE:
|
case G_STORE:
|
||||||
case G_LOAD: {
|
case G_LOAD: {
|
||||||
const auto &MemOp = **I.memoperands_begin();
|
const auto &MemOp = **I.memoperands_begin();
|
||||||
|
|
|
@ -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
|
||||||
|
...
|
|
@ -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
|
|
@ -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
|
; 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.
|
; be unsupported on the ARM target. It should progressively shrink in size.
|
||||||
|
@ -92,4 +96,37 @@ define i32 @test_thumb(i32 %a) #0 {
|
||||||
ret i32 %a
|
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" }
|
attributes #0 = { "target-features"="+thumb-mode" }
|
||||||
|
|
Loading…
Reference in New Issue