[ARM] GlobalISel: Support loading from the stack

Add support for selecting simple G_LOAD and G_FRAME_INDEX instructions (32-bit
scalars only). This will be useful for functions that need to pass arguments on
the stack.

First part of https://reviews.llvm.org/D27195.

llvm-svn: 290096
This commit is contained in:
Diana Picus 2016-12-19 11:26:31 +00:00
parent b29a15ecad
commit 519807f7be
5 changed files with 107 additions and 10 deletions

View File

@ -75,11 +75,27 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
return true;
}
if (I.getOpcode() == TargetOpcode::G_ADD) {
MachineInstrBuilder MIB{MF, I};
using namespace TargetOpcode;
switch (I.getOpcode()) {
case G_ADD:
I.setDesc(TII.get(ARM::ADDrr));
AddDefaultCC(AddDefaultPred(MachineInstrBuilder(MF, I)));
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
AddDefaultCC(AddDefaultPred(MIB));
break;
case G_FRAME_INDEX:
// Add 0 to the given frame index and hope it will eventually be folded into
// the user(s).
I.setDesc(TII.get(ARM::ADDri));
AddDefaultCC(AddDefaultPred(MIB.addImm(0)));
break;
case G_LOAD:
I.setDesc(TII.get(ARM::LDRi12));
AddDefaultPred(MIB.addImm(0));
break;
default:
return false;
}
return false;
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}

View File

@ -25,8 +25,14 @@ using namespace llvm;
ARMLegalizerInfo::ARMLegalizerInfo() {
using namespace TargetOpcode;
const LLT p0 = LLT::pointer(0, 32);
const LLT s32 = LLT::scalar(32);
setAction({G_FRAME_INDEX, p0}, Legal);
setAction({G_LOAD, s32}, Legal);
setAction({G_LOAD, 1, p0}, Legal);
setAction({G_ADD, s32}, Legal);
computeTables();

View File

@ -103,12 +103,25 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
return Mapping;
}
if (Opc == TargetOpcode::G_ADD) {
unsigned NumOperands = MI.getNumOperands();
ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
NumOperands};
using namespace TargetOpcode;
unsigned NumOperands = MI.getNumOperands();
const ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
switch (Opc) {
case G_ADD:
case G_LOAD:
// FIXME: We're abusing the fact that everything lives in a GPR for now; in
// the real world we would use different mappings.
OperandsMapping = &ARM::ValueMappings[0];
break;
case G_FRAME_INDEX:
OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
break;
default:
return InstructionMapping{};
}
return InstructionMapping{};
return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
NumOperands};
}

View File

@ -1,6 +1,7 @@
# RUN: llc -O0 -mtriple arm-- -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
--- |
define void @test_adds32() { ret void }
define void @test_load_from_stack() { ret void }
...
---
name: test_adds32
@ -35,3 +36,33 @@ body: |
BX_RET 14, _, implicit %r0
; CHECK: BX_RET 14, _, implicit %r0
...
---
name: test_load_from_stack
# CHECK-LABEL: name: test_load_from_stack
legalized: true
regBankSelected: true
selected: false
# CHECK: selected: true
registers:
- { id: 0, class: gprb }
- { id: 1, class: gprb }
- { id: 2, class: gprb }
- { id: 3, class: gprb }
fixedStack:
- { id: 0, offset: 0, size: 4, alignment: 4, isImmutable: true, isAliased: false }
- { id: 1, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false }
- { id: 2, offset: 8, size: 4, alignment: 4, isImmutable: true, isAliased: false }
# CHECK: id: [[FRAME_INDEX:[0-9]+]], offset: 8
body: |
bb.0:
liveins: %r0, %r1, %r2, %r3
%0(p0) = G_FRAME_INDEX %fixed-stack.2
; CHECK: [[FIVREG:%[0-9]+]] = ADDri %fixed-stack.[[FRAME_INDEX]], 0, 14, _, _
%1(s32) = G_LOAD %0(p0)
; CHECK: {{%[0-9]+}} = LDRi12 [[FIVREG]], 0, 14, _
BX_RET 14, _
; CHECK: BX_RET 14, _
...

View File

@ -1,6 +1,7 @@
# RUN: llc -mtriple arm-- -global-isel -run-pass=legalizer %s -o - | FileCheck %s
--- |
define void @test_add_s32() { ret void }
define void @test_load_from_stack() { ret void }
...
---
name: test_add_s32
@ -27,3 +28,33 @@ body: |
BX_RET 14, _, implicit %r0
...
---
name: test_load_from_stack
# CHECK-LABEL: name: test_load_from_stack
legalized: false
# CHECK: legalized: true
regBankSelected: false
selected: false
tracksRegLiveness: true
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
- { id: 3, class: _ }
fixedStack:
- { id: 0, offset: 0, size: 4, alignment: 4, isImmutable: true, isAliased: false }
- { id: 1, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false }
- { id: 2, offset: 8, size: 4, alignment: 4, isImmutable: true, isAliased: false }
# CHECK: id: [[FRAME_INDEX:[0-9]+]], offset: 8
body: |
bb.0:
liveins: %r0, %r1, %r2, %r3
; This is legal, so we should find it unchanged in the output
; CHECK: [[FIVREG:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[FRAME_INDEX]]
; CHECK: {{%[0-9]+}}(s32) = G_LOAD [[FIVREG]](p0)
%0(p0) = G_FRAME_INDEX %fixed-stack.2
%1(s32) = G_LOAD %0(p0)
BX_RET 14, _
...