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.