[MIPS GlobalISel] Select zero extending and sign extending load

Select zero extending and sign extending load for MIPS32.
Use size from MachineMemOperand to determine number of bytes to load.

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

llvm-svn: 352038
This commit is contained in:
Petar Avramovic 2019-01-24 10:27:21 +00:00
parent b5a939d246
commit 79df859685
7 changed files with 505 additions and 2 deletions

View File

@ -90,6 +90,28 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
return true;
}
/// Returning Opc indicates that we failed to select MIPS instruction opcode.
static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes) {
if (Opc == TargetOpcode::G_STORE)
switch (MemSizeInBytes) {
case 4:
return Mips::SW;
default:
return Opc;
}
else
switch (MemSizeInBytes) {
case 4:
return Mips::LW;
case 2:
return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
case 1:
return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
default:
return Opc;
}
}
bool MipsInstructionSelector::select(MachineInstr &I,
CodeGenCoverage &CoverageInfo) const {
@ -127,15 +149,21 @@ bool MipsInstructionSelector::select(MachineInstr &I,
break;
}
case G_STORE:
case G_LOAD: {
case G_LOAD:
case G_ZEXTLOAD:
case G_SEXTLOAD: {
const unsigned DestReg = I.getOperand(0).getReg();
const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
return false;
const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW;
const unsigned NewOpc =
selectLoadStoreOpCode(I.getOpcode(), OpMemSizeInBytes);
if (NewOpc == I.getOpcode())
return false;
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
.add(I.getOperand(0))

View File

@ -34,6 +34,11 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
getActionDefinitionsBuilder({G_LOAD, G_STORE})
.legalForCartesianProduct({p0, s32}, {p0});
getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
.legalForTypesWithMemSize({{s32, p0, 8},
{s32, p0, 16}})
.minScalar(0, s32);
getActionDefinitionsBuilder(G_SELECT)
.legalForCartesianProduct({p0, s32}, {s32})
.minScalar(0, s32)

View File

@ -85,6 +85,8 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case G_ADD:
case G_LOAD:
case G_STORE:
case G_ZEXTLOAD:
case G_SEXTLOAD:
case G_GEP:
case G_AND:
case G_OR:

View File

@ -0,0 +1,98 @@
# 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
--- |
define void @load1_s8_to_zextLoad1_s32(i8* %px) {entry: ret void}
define void @load2_s16_to_zextLoad2_s32(i16* %px) {entry: ret void}
define void @load1_s8_to_sextLoad1_s32(i8* %px) {entry: ret void}
define void @load2_s16_to_sextLoad2_s32(i16* %px) {entry: ret void}
...
---
name: load1_s8_to_zextLoad1_s32
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_zextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32: [[LBu:%[0-9]+]]:gpr32 = LBu [[COPY]], 0 :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[LBu]]
; MIPS32: RetRA implicit $v0
%0:gprb(p0) = COPY $a0
%2:gprb(s32) = G_ZEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load2_s16_to_zextLoad2_s32
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load2_s16_to_zextLoad2_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32: [[LHu:%[0-9]+]]:gpr32 = LHu [[COPY]], 0 :: (load 2 from %ir.px)
; MIPS32: $v0 = COPY [[LHu]]
; MIPS32: RetRA implicit $v0
%0:gprb(p0) = COPY $a0
%2:gprb(s32) = G_ZEXTLOAD %0(p0) :: (load 2 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_sextLoad1_s32
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_sextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32: [[LB:%[0-9]+]]:gpr32 = LB [[COPY]], 0 :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[LB]]
; MIPS32: RetRA implicit $v0
%0:gprb(p0) = COPY $a0
%2:gprb(s32) = G_SEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load2_s16_to_sextLoad2_s32
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load2_s16_to_sextLoad2_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32: [[LH:%[0-9]+]]:gpr32 = LH [[COPY]], 0 :: (load 2 from %ir.px)
; MIPS32: $v0 = COPY [[LH]]
; MIPS32: RetRA implicit $v0
%0:gprb(p0) = COPY $a0
%2:gprb(s32) = G_SEXTLOAD %0(p0) :: (load 2 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...

View File

@ -0,0 +1,178 @@
# 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
--- |
define void @load1_s8_to_zextLoad1_s32(i8* %px) {entry: ret void}
define void @load2_s16_to_zextLoad2_s32(i16* %px) {entry: ret void}
define void @load1_s8_to_zextLoad1_s16(i8* %px) {entry: ret void}
define void @load1_s8_to_zextLoad1_s16_to_zextLoad1_s32(i8* %px) {entry: ret void}
define void @load1_s8_to_sextLoad1_s32(i8* %px) {entry: ret void}
define void @load2_s16_to_sextLoad2_s32(i16* %px) {entry: ret void}
define void @load1_s8_to_sextLoad1_s16(i8* %px) {entry: ret void}
define void @load1_s8_to_sextLoad1_s16_to_sextLoad1_s32(i8* %px) {entry: ret void}
...
---
name: load1_s8_to_zextLoad1_s32
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_zextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[ZEXTLOAD:%[0-9]+]]:_(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[ZEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_ZEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load2_s16_to_zextLoad2_s32
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load2_s16_to_zextLoad2_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[ZEXTLOAD:%[0-9]+]]:_(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 2 from %ir.px)
; MIPS32: $v0 = COPY [[ZEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_ZEXTLOAD %0(p0) :: (load 2 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_zextLoad1_s16
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_zextLoad1_s16
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[ZEXTLOAD:%[0-9]+]]:_(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY [[ZEXTLOAD]](s32)
; MIPS32: $v0 = COPY [[COPY1]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s16) = G_ZEXTLOAD %0(p0) :: (load 1 from %ir.px)
%3:_(s32) = G_ANYEXT %2(s16)
$v0 = COPY %3(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_zextLoad1_s16_to_zextLoad1_s32
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_zextLoad1_s16_to_zextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[ZEXTLOAD:%[0-9]+]]:_(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[ZEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%3:_(s32) = G_ZEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %3(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_sextLoad1_s32
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_sextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[SEXTLOAD:%[0-9]+]]:_(s32) = G_SEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[SEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_SEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load2_s16_to_sextLoad2_s32
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load2_s16_to_sextLoad2_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[SEXTLOAD:%[0-9]+]]:_(s32) = G_SEXTLOAD [[COPY]](p0) :: (load 2 from %ir.px)
; MIPS32: $v0 = COPY [[SEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_SEXTLOAD %0(p0) :: (load 2 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_sextLoad1_s16
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_sextLoad1_s16
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[SEXTLOAD:%[0-9]+]]:_(s32) = G_SEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY [[SEXTLOAD]](s32)
; MIPS32: $v0 = COPY [[COPY1]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s16) = G_SEXTLOAD %0(p0) :: (load 1 from %ir.px)
%3:_(s32) = G_ANYEXT %2(s16)
$v0 = COPY %3(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_sextLoad1_s16_to_sextLoad1_s32
alignment: 2
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_sextLoad1_s16_to_sextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
; MIPS32: [[SEXTLOAD:%[0-9]+]]:_(s32) = G_SEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[SEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%3:_(s32) = G_SEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %3(s32)
RetRA implicit $v0
...

View File

@ -0,0 +1,98 @@
; 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
define i32 @load1_s8_to_zextLoad1_s32(i8* %px) {
; MIPS32-LABEL: load1_s8_to_zextLoad1_s32:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lbu $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i8, i8* %px
%conv = zext i8 %0 to i32
ret i32 %conv
}
define i32 @load2_s16_to_zextLoad2_s32(i16* %px) {
; MIPS32-LABEL: load2_s16_to_zextLoad2_s32:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lhu $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i16, i16* %px
%conv = zext i16 %0 to i32
ret i32 %conv
}
define i16 @load1_s8_to_zextLoad1_s16(i8* %px) {
; MIPS32-LABEL: load1_s8_to_zextLoad1_s16:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lbu $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i8, i8* %px
%conv = zext i8 %0 to i16
ret i16 %conv
}
define zeroext i16 @load1_s8_to_zextLoad1_s16_to_zextLoad1_s32(i8* %px) {
; MIPS32-LABEL: load1_s8_to_zextLoad1_s16_to_zextLoad1_s32:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lbu $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i8, i8* %px
%conv = zext i8 %0 to i16
ret i16 %conv
}
define i32 @load1_s8_to_sextLoad1_s32(i8* %px) {
; MIPS32-LABEL: load1_s8_to_sextLoad1_s32:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lb $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i8, i8* %px
%conv = sext i8 %0 to i32
ret i32 %conv
}
define i32 @load2_s16_to_sextLoad2_s32(i16* %px) {
; MIPS32-LABEL: load2_s16_to_sextLoad2_s32:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lh $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i16, i16* %px
%conv = sext i16 %0 to i32
ret i32 %conv
}
define i16 @load1_s8_to_sextLoad1_s16(i8* %px) {
; MIPS32-LABEL: load1_s8_to_sextLoad1_s16:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lb $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i8, i8* %px
%conv = sext i8 %0 to i16
ret i16 %conv
}
define signext i16 @load1_s8_to_sextLoad1_s16_to_sextLoad1_s32(i8* %px) {
; MIPS32-LABEL: load1_s8_to_sextLoad1_s16_to_sextLoad1_s32:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lb $2, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load i8, i8* %px
%conv = sext i8 %0 to i16
ret i16 %conv
}

View File

@ -0,0 +1,94 @@
# 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
--- |
define void @load1_s8_to_zextLoad1_s32(i8* %px) {entry: ret void}
define void @load2_s16_to_zextLoad2_s32(i16* %px) {entry: ret void}
define void @load1_s8_to_sextLoad1_s32(i8* %px) {entry: ret void}
define void @load2_s16_to_sextLoad2_s32(i16* %px) {entry: ret void}
...
---
name: load1_s8_to_zextLoad1_s32
alignment: 2
legalized: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_zextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
; MIPS32: [[ZEXTLOAD:%[0-9]+]]:gprb(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[ZEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_ZEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load2_s16_to_zextLoad2_s32
alignment: 2
legalized: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load2_s16_to_zextLoad2_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
; MIPS32: [[ZEXTLOAD:%[0-9]+]]:gprb(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 2 from %ir.px)
; MIPS32: $v0 = COPY [[ZEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_ZEXTLOAD %0(p0) :: (load 2 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load1_s8_to_sextLoad1_s32
alignment: 2
legalized: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load1_s8_to_sextLoad1_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
; MIPS32: [[SEXTLOAD:%[0-9]+]]:gprb(s32) = G_SEXTLOAD [[COPY]](p0) :: (load 1 from %ir.px)
; MIPS32: $v0 = COPY [[SEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_SEXTLOAD %0(p0) :: (load 1 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...
---
name: load2_s16_to_sextLoad2_s32
alignment: 2
legalized: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32-LABEL: name: load2_s16_to_sextLoad2_s32
; MIPS32: liveins: $a0
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
; MIPS32: [[SEXTLOAD:%[0-9]+]]:gprb(s32) = G_SEXTLOAD [[COPY]](p0) :: (load 2 from %ir.px)
; MIPS32: $v0 = COPY [[SEXTLOAD]](s32)
; MIPS32: RetRA implicit $v0
%0:_(p0) = COPY $a0
%2:_(s32) = G_SEXTLOAD %0(p0) :: (load 2 from %ir.px)
$v0 = COPY %2(s32)
RetRA implicit $v0
...