From 519807f7beec071583e5c869ac2666dac2e50542 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Mon, 19 Dec 2016 11:26:31 +0000 Subject: [PATCH] [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 --- llvm/lib/Target/ARM/ARMInstructionSelector.cpp | 24 ++++++++++++++--- llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 6 +++++ llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp | 25 ++++++++++++----- .../ARM/GlobalISel/arm-instruction-select.mir | 31 ++++++++++++++++++++++ llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir | 31 ++++++++++++++++++++++ 5 files changed, 107 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index 53298f6..c01043d 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -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); } diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp index 6567950..6680196 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -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(); diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp index 02100aa..9bd036a 100644 --- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -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}; } diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir index 41e238a..22ae8fc 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir @@ -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, _ +... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir index 228296d..f6006da 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir @@ -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, _ + +... -- 2.7.4