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