Select float and double load and store for MIPS32.
Differential Revision: https://reviews.llvm.org/D64419
llvm-svn: 365626
}
/// 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,
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;
--- /dev/null
+# 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
+
+...
--- /dev/null
+# 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
+
+...
%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
+}
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
+}