Skip to content

Commit

Permalink
[MIPS GlobalISel] Select float and double load and store
Browse files Browse the repository at this point in the history
Select float and double load and store for MIPS32.

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

llvm-svn: 365626
  • Loading branch information
Petar Avramovic authored and Petar Avramovic committed Jul 10, 2019
1 parent 2bf04f2 commit 7b31491
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 22 deletions.
66 changes: 44 additions & 22 deletions llvm/lib/Target/Mips/MipsInstructionSelector.cpp
Expand Up @@ -139,30 +139,49 @@ bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
}

/// 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;
case 2:
return Mips::SH;
case 1:
return Mips::SB;
default:
return Opc;
}
else
// Unspecified extending load is selected into zeroExtending load.
static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
unsigned RegBank, bool isFP64) {
bool isStore = Opc == TargetOpcode::G_STORE;
if (RegBank == Mips::GPRBRegBankID) {
if (isStore)
switch (MemSizeInBytes) {
case 4:
return Mips::SW;
case 2:
return Mips::SH;
case 1:
return Mips::SB;
default:
return Opc;
}
else
// Unspecified extending load is selected into zeroExtending load.
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;
}
}

if (RegBank == Mips::FPRBRegBankID) {
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;
return isStore ? Mips::SWC1 : Mips::LWC1;
case 8:
if (isFP64)
return isStore ? Mips::SDC164 : Mips::LDC164;
else
return isStore ? Mips::SDC1 : Mips::LDC1;
default:
return Opc;
}
}
return Opc;
}

bool MipsInstructionSelector::select(MachineInstr &I,
Expand Down Expand Up @@ -262,11 +281,14 @@ bool MipsInstructionSelector::select(MachineInstr &I,
const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();

if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32)
return false;

if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64)
return false;

const unsigned NewOpc =
selectLoadStoreOpCode(I.getOpcode(), OpMemSizeInBytes);
const unsigned NewOpc = selectLoadStoreOpCode(
I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit());
if (NewOpc == I.getOpcode())
return false;

Expand Down
94 changes: 94 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load.mir
@@ -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=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP32
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP64
--- |

define void @load_i32(i32* %ptr) {entry: ret void}
define void @load_float(float* %ptr) {entry: ret void}
define void @load_double(double* %ptr) {entry: ret void}

...
---
name: load_i32
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32FP32-LABEL: name: load_i32
; MIPS32FP32: liveins: $a0
; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP32: [[LW:%[0-9]+]]:gpr32 = LW [[COPY]], 0 :: (load 4 from %ir.ptr)
; MIPS32FP32: $v0 = COPY [[LW]]
; MIPS32FP32: RetRA implicit $v0
; MIPS32FP64-LABEL: name: load_i32
; MIPS32FP64: liveins: $a0
; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP64: [[LW:%[0-9]+]]:gpr32 = LW [[COPY]], 0 :: (load 4 from %ir.ptr)
; MIPS32FP64: $v0 = COPY [[LW]]
; MIPS32FP64: RetRA implicit $v0
%0:gprb(p0) = COPY $a0
%1:gprb(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
$v0 = COPY %1(s32)
RetRA implicit $v0
...
---
name: load_float
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32FP32-LABEL: name: load_float
; MIPS32FP32: liveins: $a0
; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP32: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 0 :: (load 4 from %ir.ptr)
; MIPS32FP32: $f0 = COPY [[LWC1_]]
; MIPS32FP32: RetRA implicit $f0
; MIPS32FP64-LABEL: name: load_float
; MIPS32FP64: liveins: $a0
; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP64: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 0 :: (load 4 from %ir.ptr)
; MIPS32FP64: $f0 = COPY [[LWC1_]]
; MIPS32FP64: RetRA implicit $f0
%0:gprb(p0) = COPY $a0
%1:fprb(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
$f0 = COPY %1(s32)
RetRA implicit $f0
...
---
name: load_double
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0
; MIPS32FP32-LABEL: name: load_double
; MIPS32FP32: liveins: $a0
; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP32: [[LDC1_:%[0-9]+]]:afgr64 = LDC1 [[COPY]], 0 :: (load 8 from %ir.ptr)
; MIPS32FP32: $d0 = COPY [[LDC1_]]
; MIPS32FP32: RetRA implicit $d0
; MIPS32FP64-LABEL: name: load_double
; MIPS32FP64: liveins: $a0
; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP64: [[LDC164_:%[0-9]+]]:fgr64 = LDC164 [[COPY]], 0 :: (load 8 from %ir.ptr)
; MIPS32FP64: $d0 = COPY [[LDC164_]]
; MIPS32FP64: RetRA implicit $d0
%0:gprb(p0) = COPY $a0
%1:fprb(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr)
$d0 = COPY %1(s64)
RetRA implicit $d0
...
94 changes: 94 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/instruction-select/store.mir
@@ -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=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP32
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP64
--- |

define void @store_i32(i32* %ptr) { entry: ret void }
define void @store_float(float* %ptr) { entry: ret void }
define void @store_double(double* %ptr) { entry: ret void }

...
---
name: store_i32
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a0, $a1
; MIPS32FP32-LABEL: name: store_i32
; MIPS32FP32: liveins: $a0, $a1
; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
; MIPS32FP32: SW [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
; MIPS32FP32: RetRA
; MIPS32FP64-LABEL: name: store_i32
; MIPS32FP64: liveins: $a0, $a1
; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
; MIPS32FP64: SW [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
; MIPS32FP64: RetRA
%0:gprb(s32) = COPY $a0
%1:gprb(p0) = COPY $a1
G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
RetRA
...
---
name: store_float
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a1, $f12
; MIPS32FP32-LABEL: name: store_float
; MIPS32FP32: liveins: $a1, $f12
; MIPS32FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
; MIPS32FP32: SWC1 [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
; MIPS32FP32: RetRA
; MIPS32FP64-LABEL: name: store_float
; MIPS32FP64: liveins: $a1, $f12
; MIPS32FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
; MIPS32FP64: SWC1 [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
; MIPS32FP64: RetRA
%0:fprb(s32) = COPY $f12
%1:gprb(p0) = COPY $a1
G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
RetRA
...
---
name: store_double
alignment: 2
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $a2, $d6
; MIPS32FP32-LABEL: name: store_double
; MIPS32FP32: liveins: $a2, $d6
; MIPS32FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2
; MIPS32FP32: SDC1 [[COPY]], [[COPY1]], 0 :: (store 8 into %ir.ptr)
; MIPS32FP32: RetRA
; MIPS32FP64-LABEL: name: store_double
; MIPS32FP64: liveins: $a2, $d6
; MIPS32FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2
; MIPS32FP64: SDC164 [[COPY]], [[COPY1]], 0 :: (store 8 into %ir.ptr)
; MIPS32FP64: RetRA
%0:fprb(s64) = COPY $d6
%1:gprb(p0) = COPY $a2
G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr)
RetRA
...
22 changes: 22 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll
Expand Up @@ -25,3 +25,25 @@ entry:
%0 = load i64, i64* %ptr
ret i64 %0
}

define float @load_float(float* %ptr) {
; MIPS32-LABEL: load_float:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lwc1 $f0, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load float, float* %ptr
ret float %0
}

define double @load_double(double* %ptr) {
; MIPS32-LABEL: load_double:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: ldc1 $f0, 0($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
%0 = load double, double* %ptr
ret double %0
}
22 changes: 22 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll
Expand Up @@ -25,3 +25,25 @@ entry:
store i64 %val, i64* %ptr
ret void
}

define void @store_float(float %val, float* %ptr) {
; MIPS32-LABEL: store_float:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: swc1 $f12, 0($5)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
store float %val, float* %ptr
ret void
}

define void @store_double(double %val, double* %ptr) {
; MIPS32-LABEL: store_double:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: sdc1 $f12, 0($6)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
store double %val, double* %ptr
ret void
}

0 comments on commit 7b31491

Please sign in to comment.