Subzero, MIPS32: Implements integer division instructions sdiv, udiv, srem, urem

This patch adds support for missing integer division instruction sdiv, udiv, srem, urem.

R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1989303002 .

Patch from Srdjan Obucina <Srdjan.Obucina@imgtec.com>.
diff --git a/src/IceInstMIPS32.cpp b/src/IceInstMIPS32.cpp
index 043c2ca..f9a4793 100644
--- a/src/IceInstMIPS32.cpp
+++ b/src/IceInstMIPS32.cpp
@@ -57,6 +57,8 @@
 template <> const char *InstMIPS32Addu::Opcode = "addu";
 template <> const char *InstMIPS32And::Opcode = "and";
 template <> const char *InstMIPS32Andi::Opcode = "andi";
+template <> const char *InstMIPS32Div::Opcode = "div";
+template <> const char *InstMIPS32Divu::Opcode = "divu";
 template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
 template <> const char *InstMIPS32Mflo::Opcode = "mflo";
 template <> const char *InstMIPS32Mthi::Opcode = "mthi";
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index 85f268e..8a23136 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -124,6 +124,8 @@
     Andi,
     Br,
     Call,
+    Div,
+    Divu,
     La,
     Label,
     Lui,
@@ -470,6 +472,8 @@
 using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
 using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
 using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
+using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>;
+using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>;
 using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>;
 using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
 using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index a2e82b2..ce1f810 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -692,10 +692,6 @@
   switch (Instr->getOp()) {
   default:
     break;
-  case InstArithmetic::Udiv:
-  case InstArithmetic::Sdiv:
-  case InstArithmetic::Urem:
-  case InstArithmetic::Srem:
   case InstArithmetic::Fadd:
   case InstArithmetic::Fsub:
   case InstArithmetic::Fmul:
@@ -754,14 +750,34 @@
     _mov(Dest, T);
     return;
   }
-  case InstArithmetic::Udiv:
-    break;
-  case InstArithmetic::Sdiv:
-    break;
-  case InstArithmetic::Urem:
-    break;
-  case InstArithmetic::Srem:
-    break;
+  case InstArithmetic::Udiv: {
+    auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO);
+    _divu(T_Zero, Src0R, Src1R);
+    _mflo(T, T_Zero);
+    _mov(Dest, T);
+    return;
+  }
+  case InstArithmetic::Sdiv: {
+    auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO);
+    _div(T_Zero, Src0R, Src1R);
+    _mflo(T, T_Zero);
+    _mov(Dest, T);
+    return;
+  }
+  case InstArithmetic::Urem: {
+    auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO);
+    _divu(T_Zero, Src0R, Src1R);
+    _mfhi(T, T_Zero);
+    _mov(Dest, T);
+    return;
+  }
+  case InstArithmetic::Srem: {
+    auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO);
+    _div(T_Zero, Src0R, Src1R);
+    _mfhi(T, T_Zero);
+    _mov(Dest, T);
+    return;
+  }
   case InstArithmetic::Fadd:
     break;
   case InstArithmetic::Fsub:
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index a90311a..e9f11a3 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -164,6 +164,14 @@
     Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
   }
 
+  void _div(Variable *Dest, Variable *Src0, Variable *Src1) {
+    Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
+  }
+
+  void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
+    Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
+  }
+
   void _lui(Variable *Dest, uint32_t Imm) {
     Context.insert<InstMIPS32Lui>(Dest, Imm);
   }
diff --git a/tests_lit/llvm2ice_tests/arith.ll b/tests_lit/llvm2ice_tests/arith.ll
index ed34a60..73ed882 100644
--- a/tests_lit/llvm2ice_tests/arith.ll
+++ b/tests_lit/llvm2ice_tests/arith.ll
@@ -171,6 +171,8 @@
 ; ARM32HWDIV: sdiv
 
 ; MIPS32-LABEL: Sdiv
+; MIPS32: div
+; MIPS32: mflo
 
 define internal i32 @SdivConst(i32 %a) {
 entry:
@@ -189,6 +191,8 @@
 ; ARM32HWDIV: sdiv
 
 ; MIPS32-LABEL: SdivConst
+; MIPS32: div
+; MIPS32: mflo
 
 define internal i32 @Srem(i32 %a, i32 %b) {
 entry:
@@ -210,6 +214,8 @@
 ; ARM32HWDIV: mls
 
 ; MIPS32-LABEL: Srem
+; MIPS32: div
+; MIPS32: mfhi
 
 define internal i32 @Udiv(i32 %a, i32 %b) {
 entry:
@@ -229,6 +235,8 @@
 ; ARM32HWDIV: udiv
 
 ; MIPS32-LABEL: Udiv
+; MIPS32: divu
+; MIPS32: mflo
 
 define internal i32 @Urem(i32 %a, i32 %b) {
 entry:
@@ -249,6 +257,8 @@
 ; ARM32HWDIV: mls
 
 ; MIPS32-LABEL: Urem
+; MIPS32: divu
+; MIPS32: mfhi
 
 ; The following tests check that shift instructions don't try to use a
 ; ConstantRelocatable as an immediate operand.