Subzero, MIPS32: lowerSelect for i1, i8, i16, i32, f32, f64
Implements lowerSelect for basic integer and float datatypes.
Support for i64 will be added as separate patch.
Crucial for running crosstests.
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/2337023003 .
Patch from Srdjan Obucina <Srdjan.Obucina@imgtec.com>.
diff --git a/src/IceInstMIPS32.cpp b/src/IceInstMIPS32.cpp
index 85cf07b..c83267d 100644
--- a/src/IceInstMIPS32.cpp
+++ b/src/IceInstMIPS32.cpp
@@ -104,7 +104,13 @@
template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
template <> const char *InstMIPS32Movf::Opcode = "movf";
+template <> const char *InstMIPS32Movn::Opcode = "movn";
+template <> const char *InstMIPS32Movn_d::Opcode = "movn.d";
+template <> const char *InstMIPS32Movn_s::Opcode = "movn.s";
template <> const char *InstMIPS32Movt::Opcode = "movt";
+template <> const char *InstMIPS32Movz::Opcode = "movz";
+template <> const char *InstMIPS32Movz_d::Opcode = "movz.d";
+template <> const char *InstMIPS32Movz_s::Opcode = "movz.s";
template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
template <> const char *InstMIPS32Mthi::Opcode = "mthi";
template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
@@ -737,7 +743,8 @@
const Type SrcType = Src->getType();
// move GP to/from FP
- if (DstType != SrcType) {
+ if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
+ (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
if (isScalarFloatingType(DstType)) {
Str << "\t"
"mtc1"
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index f993800..a466059 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -228,7 +228,13 @@
Mov_d,
Mov_s,
Movf,
+ Movn,
+ Movn_d,
+ Movn_s,
Movt,
+ Movz,
+ Movz_d,
+ Movz_s,
Mtc1,
Mthi,
Mtlo,
@@ -1078,7 +1084,13 @@
using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>;
using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>;
using InstMIPS32Movf = InstMIPS32MovConditional<InstMIPS32::Movf>;
+using InstMIPS32Movn = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn>;
+using InstMIPS32Movn_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_d>;
+using InstMIPS32Movn_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_s>;
using InstMIPS32Movt = InstMIPS32MovConditional<InstMIPS32::Movt>;
+using InstMIPS32Movz = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz>;
+using InstMIPS32Movz_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_d>;
+using InstMIPS32Movz_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_s>;
using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>;
using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>;
using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>;
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index e4f2fd0..8db2276 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -3209,12 +3209,23 @@
if (Instr->hasRetValue()) {
Operand *Src0 = Instr->getRetValue();
switch (Src0->getType()) {
+ case IceType_f32: {
+ Operand *Src0F = legalizeToReg(Src0);
+ Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_F0);
+ _mov(Reg, Src0F);
+ break;
+ }
+ case IceType_f64: {
+ Operand *Src0F = legalizeToReg(Src0);
+ Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_F0F1);
+ _mov(Reg, Src0F);
+ break;
+ }
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32: {
- // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0);
- Operand *Src0F = legalize(Src0, Legal_Reg);
+ Operand *Src0F = legalizeToReg(Src0);
Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0);
_mov(Reg, Src0F);
break;
@@ -3235,7 +3246,44 @@
}
void TargetMIPS32::lowerSelect(const InstSelect *Instr) {
- UnimplementedLoweringError(this, Instr);
+ Variable *Dest = Instr->getDest();
+ const Type DestTy = Dest->getType();
+
+ if (DestTy == IceType_i64 || isVectorType(DestTy)) {
+ UnimplementedLoweringError(this, Instr);
+ return;
+ }
+
+ Variable *DestR = legalizeToReg(Dest);
+ Variable *SrcTR = legalizeToReg(Instr->getTrueOperand());
+ Variable *SrcFR = legalizeToReg(Instr->getFalseOperand());
+
+ Variable *ConditionR = legalizeToReg(Instr->getCondition());
+
+ assert(Instr->getCondition()->getType() == IceType_i1);
+
+ switch (DestTy) {
+ case IceType_i1:
+ case IceType_i8:
+ case IceType_i16:
+ case IceType_i32:
+ _movn(SrcFR, SrcTR, ConditionR);
+ _mov(DestR, SrcFR);
+ _mov(Dest, DestR);
+ break;
+ case IceType_f32:
+ _movn_s(SrcFR, SrcTR, ConditionR);
+ _mov(DestR, SrcFR);
+ _mov(Dest, DestR);
+ break;
+ case IceType_f64:
+ _movn_d(SrcFR, SrcTR, ConditionR);
+ _mov(DestR, SrcFR);
+ _mov(Dest, DestR);
+ break;
+ default:
+ UnimplementedLoweringError(this, Instr);
+ }
}
void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) {
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 717b7d9..8029386 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -319,6 +319,18 @@
Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
}
+ void _mfc1(Variable *Dest, Variable *Src) {
+ Context.insert<InstMIPS32Mfc1>(Dest, Src);
+ }
+
+ void _mfhi(Variable *Dest, Operand *Src) {
+ Context.insert<InstMIPS32Mfhi>(Dest, Src);
+ }
+
+ void _mflo(Variable *Dest, Operand *Src) {
+ Context.insert<InstMIPS32Mflo>(Dest, Src);
+ }
+
void _mov(Variable *Dest, Operand *Src0) {
assert(Dest != nullptr);
// Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
@@ -347,20 +359,32 @@
Context.insert<InstMIPS32Movf>(Src0, Src1, FCC);
}
+ void _movn(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movn>(Dest, Src0, Src1);
+ }
+
+ void _movn_d(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movn_d>(Dest, Src0, Src1);
+ }
+
+ void _movn_s(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movn_s>(Dest, Src0, Src1);
+ }
+
void _movt(Variable *Src0, Variable *Src1, Operand *FCC) {
Context.insert<InstMIPS32Movt>(Src0, Src1, FCC);
}
- void _mfc1(Variable *Dest, Variable *Src) {
- Context.insert<InstMIPS32Mfc1>(Dest, Src);
+ void _movz(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movz>(Dest, Src0, Src1);
}
- void _mfhi(Variable *Dest, Operand *Src) {
- Context.insert<InstMIPS32Mfhi>(Dest, Src);
+ void _movz_d(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movz_d>(Dest, Src0, Src1);
}
- void _mflo(Variable *Dest, Operand *Src) {
- Context.insert<InstMIPS32Mflo>(Dest, Src);
+ void _movz_s(Variable *Dest, Variable *Src0, Variable *Src1) {
+ Context.insert<InstMIPS32Movz_s>(Dest, Src0, Src1);
}
void _mtc1(Variable *Dest, Variable *Src) {
diff --git a/tests_lit/llvm2ice_tests/fp.cmp.ll b/tests_lit/llvm2ice_tests/fp.cmp.ll
index 39c1850..55aa701 100644
--- a/tests_lit/llvm2ice_tests/fp.cmp.ll
+++ b/tests_lit/llvm2ice_tests/fp.cmp.ll
@@ -968,6 +968,9 @@
; ARM32-OM1: vmovne.f32 s{{[0-9]+}}
; ARM32-O2: vmovmi.f32 s{{[0-9]+}}
; ARM32: bx
+; MIPS32-LABEL: selectFloatVarVar
+; MIPS32: movn.s {{.*}}
+; MIPS32: mov.s {{.*}}
define internal double @selectDoubleVarVar(double %a, double %b) {
entry:
@@ -985,3 +988,6 @@
; ARM32-OM1: vmovne.f64 d{{[0-9]+}}
; ARM32-O2: vmovmi.f64 d{{[0-9]+}}
; ARM32: bx
+; MIPS32-LABEL: selectDoubleVarVar
+; MIPS32: movn.d {{.*}}
+; MIPS32: mov.d {{.*}}
diff --git a/tests_lit/llvm2ice_tests/select-opt.ll b/tests_lit/llvm2ice_tests/select-opt.ll
index aa2c4d9..9620aad 100644
--- a/tests_lit/llvm2ice_tests/select-opt.ll
+++ b/tests_lit/llvm2ice_tests/select-opt.ll
@@ -23,6 +23,20 @@
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix ARM32 --check-prefix ARM32-OM1 %s
+; RUN: %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command %p2i --filetype=asm --assemble \
+; RUN: --disassemble --target mips32 -i %s --args -Om1 \
+; RUN: -allow-externally-defined-symbols -skip-unimplemented \
+; RUN: | %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix MIPS32 %s
+
+; RUN: %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command %p2i --filetype=asm --assemble \
+; RUN: --disassemble --target mips32 -i %s --args -O2 \
+; RUN: -allow-externally-defined-symbols -skip-unimplemented \
+; RUN: | %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix MIPS32 %s
+
define internal void @testSelect(i32 %a, i32 %b) {
entry:
%cmp = icmp slt i32 %a, %b
@@ -61,6 +75,10 @@
; ARM32: bl {{.*}} useInt
; ARM32: bl {{.*}} useInt
; ARM32: bx lr
+; MIPS32-LABEL: testSelect
+; MIPS32: slt {{.*}}
+; MIPS32: movn {{.*}}
+; MIPS32: move {{.*}}
; Check for valid addressing mode in the cmp instruction when the
; operand is an immediate.
@@ -73,6 +91,9 @@
; CHECK-NOT: cmp 0x{{[0-9a-f]+}},
; ARM32-LABEL: testSelectImm32
; ARM32-NOT: cmp #{{.*}},
+; MIPS32-LABEL: testSelectImm32
+; MIPS32: movn {{.*}}
+; MIPS32: move {{.*}}
; Check for valid addressing mode in the cmp instruction when the
; operand is an immediate. There is a different x86-32 lowering
@@ -86,3 +107,4 @@
; CHECK-NOT: cmp 0x{{[0-9a-f]+}},
; ARM32-LABEL: testSelectImm64
; ARM32-NOT: cmp #{{.*}},
+; MIPS32-LABEL: testSelectImm64