[MIPS GlobalISel] Select instructions to load and store i32 on stack

Add code for selection of G_LOAD, G_STORE, G_GEP, G_FRAMEINDEX and
G_CONSTANT. Support loads and stores of i32 values.

Patch by Petar Avramovic.

Differential Revision: https://reviews.llvm.org/D48957

llvm-svn: 337168
This commit is contained in:
Petar Jovanovic 2018-07-16 13:29:32 +00:00
parent 66aa54677c
commit fd9d371096
7 changed files with 307 additions and 2 deletions

View File

@ -107,8 +107,72 @@ bool MipsInstructionSelector::select(MachineInstr &I,
if (selectImpl(I, CoverageInfo)) {
return true;
}
// We didn't select anything.
return false;
MachineInstr *MI = nullptr;
using namespace TargetOpcode;
switch (I.getOpcode()) {
case G_GEP: {
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
.add(I.getOperand(0))
.add(I.getOperand(1))
.add(I.getOperand(2));
break;
}
case G_FRAME_INDEX: {
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
.add(I.getOperand(0))
.add(I.getOperand(1))
.addImm(0);
break;
}
case G_STORE:
case G_LOAD: {
const unsigned DestReg = I.getOperand(0).getReg();
const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
return false;
const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW;
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
.add(I.getOperand(0))
.add(I.getOperand(1))
.addImm(0)
.addMemOperand(*I.memoperands_begin());
break;
}
case G_CONSTANT: {
int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue();
unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
MachineInstr *LUi, *ORi;
LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
.addDef(LUiReg)
.addImm(Imm >> 16);
ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi))
.addDef(I.getOperand(0).getReg())
.addUse(LUiReg)
.addImm(Imm & 0xFFFF);
if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
return false;
if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
return false;
I.eraseFromParent();
return true;
}
default:
return false;
}
I.eraseFromParent();
return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
}
namespace llvm {

View File

@ -20,9 +20,22 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
using namespace TargetOpcode;
const LLT s32 = LLT::scalar(32);
const LLT p0 = LLT::pointer(0, 32);
getActionDefinitionsBuilder(G_ADD).legalFor({s32});
getActionDefinitionsBuilder({G_LOAD, G_STORE})
.legalFor({{s32, p0}});
getActionDefinitionsBuilder(G_CONSTANT)
.legalFor({s32});
getActionDefinitionsBuilder(G_GEP)
.legalFor({{p0, s32}});
getActionDefinitionsBuilder(G_FRAME_INDEX)
.legalFor({p0});
computeTables();
verify(*ST.getInstrInfo());
}

View File

@ -58,6 +58,7 @@ const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
case Mips::GPR32RegClassID:
case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
case Mips::SP32RegClassID:
return getRegBank(Mips::GPRBRegBankID);
default:
llvm_unreachable("Register class not supported");
@ -80,8 +81,16 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
switch (Opc) {
case G_ADD:
case G_LOAD:
case G_STORE:
case G_GEP:
OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
break;
case G_CONSTANT:
case G_FRAME_INDEX:
OperandsMapping =
getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
break;
default:
return getInvalidInstructionMapping();
}

View File

@ -0,0 +1,65 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
declare i32 @f(i32, i32, i32, i32, i32)
define void @g(i32, i32, i32, i32, i32) {entry: ret void}
...
---
name: g
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
fixedStack:
- { id: 0, offset: 16, size: 4, alignment: 8, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
liveins: $a0, $a1, $a2, $a3
; MIPS32-LABEL: name: g
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
; MIPS32: [[COPY2:%[0-9]+]]:gpr32 = COPY $a2
; MIPS32: [[COPY3:%[0-9]+]]:gpr32 = COPY $a3
; MIPS32: [[ADDiu:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.0, 0
; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDiu]], 0 :: (load 4 from %fixed-stack.0, align 0)
; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[COPY]]
; MIPS32: $a1 = COPY [[COPY1]]
; MIPS32: $a2 = COPY [[COPY2]]
; MIPS32: $a3 = COPY [[COPY3]]
; MIPS32: [[COPY4:%[0-9]+]]:gpr32 = COPY $sp
; MIPS32: [[LUi:%[0-9]+]]:gpr32 = LUi 0
; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 16
; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY4]], [[ORi]]
; MIPS32: SW [[LW]], [[ADDu]], 0 :: (store 4 into stack + 16, align 0)
; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
; MIPS32: [[COPY5:%[0-9]+]]:gpr32 = COPY $v0
; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
; MIPS32: $v0 = COPY [[COPY5]]
; MIPS32: RetRA implicit $v0
%0:gprb(s32) = COPY $a0
%1:gprb(s32) = COPY $a1
%2:gprb(s32) = COPY $a2
%3:gprb(s32) = COPY $a3
%5:gprb(p0) = G_FRAME_INDEX %fixed-stack.0
%4:gprb(s32) = G_LOAD %5(p0) :: (load 4 from %fixed-stack.0, align 0)
ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
$a0 = COPY %0(s32)
$a1 = COPY %1(s32)
$a2 = COPY %2(s32)
$a3 = COPY %3(s32)
%7:gprb(p0) = COPY $sp
%8:gprb(s32) = G_CONSTANT i32 16
%9:gprb(p0) = G_GEP %7, %8(s32)
G_STORE %4(s32), %9(p0) :: (store 4 into stack + 16, align 0)
JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
%6:gprb(s32) = COPY $v0
ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
$v0 = COPY %6(s32)
RetRA implicit $v0
...

View File

@ -0,0 +1,62 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
declare i32 @f(i32, i32, i32, i32, i32)
define void @g(i32, i32, i32, i32, i32) {entry: ret void}
...
---
name: g
alignment: 2
tracksRegLiveness: true
fixedStack:
- { id: 0, offset: 16, size: 4, alignment: 8, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
liveins: $a0, $a1, $a2, $a3
; MIPS32-LABEL: name: g
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0)
; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[COPY]](s32)
; MIPS32: $a1 = COPY [[COPY1]](s32)
; MIPS32: $a2 = COPY [[COPY2]](s32)
; MIPS32: $a3 = COPY [[COPY3]](s32)
; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32)
; MIPS32: G_STORE [[LOAD]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0)
; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0
; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
; MIPS32: $v0 = COPY [[COPY5]](s32)
; MIPS32: RetRA implicit $v0
%0:_(s32) = COPY $a0
%1:_(s32) = COPY $a1
%2:_(s32) = COPY $a2
%3:_(s32) = COPY $a3
%5:_(p0) = G_FRAME_INDEX %fixed-stack.0
%4:_(s32) = G_LOAD %5(p0) :: (load 4 from %fixed-stack.0, align 0)
ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
$a0 = COPY %0(s32)
$a1 = COPY %1(s32)
$a2 = COPY %2(s32)
$a3 = COPY %3(s32)
%7:_(p0) = COPY $sp
%8:_(s32) = G_CONSTANT i32 16
%9:_(p0) = G_GEP %7, %8(s32)
G_STORE %4(s32), %9(p0) :: (store 4 into stack + 16, align 0)
JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
%6:_(s32) = COPY $v0
ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
$v0 = COPY %6(s32)
RetRA implicit $v0
...

View File

@ -0,0 +1,29 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
declare i32 @f(i32, i32, i32, i32, i32)
define i32 @g(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5){
; MIPS32-LABEL: g:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: addiu $sp, $sp, -32
; MIPS32-NEXT: .cfi_def_cfa_offset 32
; MIPS32-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill
; MIPS32-NEXT: .cfi_offset 31, -4
; MIPS32-NEXT: addiu $1, $sp, 48
; MIPS32-NEXT: lw $1, 0($1)
; MIPS32-NEXT: move $2, $sp
; MIPS32-NEXT: lui $3, 0
; MIPS32-NEXT: ori $3, $3, 16
; MIPS32-NEXT: addu $2, $2, $3
; MIPS32-NEXT: sw $1, 0($2)
; MIPS32-NEXT: jal f
; MIPS32-NEXT: nop
; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload
; MIPS32-NEXT: addiu $sp, $sp, 32
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%call = call i32 @f(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5)
ret i32 %call
}

View File

@ -0,0 +1,63 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
declare i32 @f(i32, i32, i32, i32, i32)
define void @g(i32, i32, i32, i32, i32) {entry: ret void}
...
---
name: g
alignment: 2
legalized: true
tracksRegLiveness: true
fixedStack:
- { id: 0, offset: 16, size: 4, alignment: 8, stack-id: 0, isImmutable: true }
body: |
bb.1.entry:
liveins: $a0, $a1, $a2, $a3
; MIPS32-LABEL: name: g
; MIPS32: liveins: $a0, $a1, $a2, $a3
; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0
; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1
; MIPS32: [[COPY2:%[0-9]+]]:gprb(s32) = COPY $a2
; MIPS32: [[COPY3:%[0-9]+]]:gprb(s32) = COPY $a3
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %fixed-stack.0
; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0)
; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
; MIPS32: $a0 = COPY [[COPY]](s32)
; MIPS32: $a1 = COPY [[COPY1]](s32)
; MIPS32: $a2 = COPY [[COPY2]](s32)
; MIPS32: $a3 = COPY [[COPY3]](s32)
; MIPS32: [[COPY4:%[0-9]+]]:gprb(p0) = COPY $sp
; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 16
; MIPS32: [[GEP:%[0-9]+]]:gprb(p0) = G_GEP [[COPY4]], [[C]](s32)
; MIPS32: G_STORE [[LOAD]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0)
; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
; MIPS32: [[COPY5:%[0-9]+]]:gprb(s32) = COPY $v0
; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
; MIPS32: $v0 = COPY [[COPY5]](s32)
; MIPS32: RetRA implicit $v0
%0:_(s32) = COPY $a0
%1:_(s32) = COPY $a1
%2:_(s32) = COPY $a2
%3:_(s32) = COPY $a3
%5:_(p0) = G_FRAME_INDEX %fixed-stack.0
%4:_(s32) = G_LOAD %5(p0) :: (load 4 from %fixed-stack.0, align 0)
ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
$a0 = COPY %0(s32)
$a1 = COPY %1(s32)
$a2 = COPY %2(s32)
$a3 = COPY %3(s32)
%7:_(p0) = COPY $sp
%8:_(s32) = G_CONSTANT i32 16
%9:_(p0) = G_GEP %7, %8(s32)
G_STORE %4(s32), %9(p0) :: (store 4 into stack + 16, align 0)
JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
%6:_(s32) = COPY $v0
ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
$v0 = COPY %6(s32)
RetRA implicit $v0
...