Add numerator check for integer divide and modulo
Implemented numerator == 0 optimization for integer divide and modulo
Change-Id: I6e3bff4a9f68d2790394f7df6106a948003a04c4
Signed-off-by: Yixin Shou <yixin.shou@intel.com>
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index cc51538..3463c54 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -607,6 +607,12 @@
rl_result = EvalLoc(rl_dest, kCoreReg, true);
if (is_div) {
LoadValueDirectFixed(rl_src, rl_result.reg);
+
+ // Check if numerator is 0
+ OpRegImm(kOpCmp, rl_result.reg, 0);
+ LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondEq);
+
+ // handle 0x80000000 / -1
OpRegImm(kOpCmp, rl_result.reg, 0x80000000);
LIR *minint_branch = NewLIR2(kX86Jcc8, 0, kX86CondEq);
@@ -615,6 +621,7 @@
// EAX already contains the right value (0x80000000),
minint_branch->target = NewLIR0(kPseudoTargetLabel);
+ branch->target = NewLIR0(kPseudoTargetLabel);
} else {
// x % -1 == 0.
LoadConstantNoClobber(rl_result.reg, 0);
@@ -627,6 +634,14 @@
RegStorage rs_temp = AllocTypedTemp(false, kCoreReg);
rl_result.reg.SetReg(rs_temp.GetReg());
}
+
+ // Check if numerator is 0
+ OpRegImm(kOpCmp, rl_src.reg, 0);
+ LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondNe);
+ LoadConstantNoClobber(rl_result.reg, 0);
+ LIR* done = NewLIR1(kX86Jmp8, 0);
+ branch->target = NewLIR0(kPseudoTargetLabel);
+
NewLIR3(kX86Lea32RM, rl_result.reg.GetReg(), rl_src.reg.GetReg(), std::abs(imm) - 1);
NewLIR2(kX86Test32RR, rl_src.reg.GetReg(), rl_src.reg.GetReg());
OpCondRegReg(kOpCmov, kCondPl, rl_result.reg, rl_src.reg);
@@ -635,6 +650,7 @@
if (imm < 0) {
OpReg(kOpNeg, rl_result.reg);
}
+ done->target = NewLIR0(kPseudoTargetLabel);
} else {
CHECK(imm <= -2 || imm >= 2);
@@ -682,6 +698,13 @@
LoadValueDirectFixed(rl_src, rs_r0);
}
+ // Check if numerator is 0
+ OpRegImm(kOpCmp, rs_r0, 0);
+ LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondNe);
+ LoadConstantNoClobber(rs_r2, 0);
+ LIR* done = NewLIR1(kX86Jmp8, 0);
+ branch->target = NewLIR0(kPseudoTargetLabel);
+
// EDX = magic.
LoadConstantNoClobber(rs_r2, magic);
@@ -730,6 +753,7 @@
// For this case, return the result in EAX.
rl_result.reg.SetReg(r0);
}
+ done->target = NewLIR0(kPseudoTargetLabel);
}
return rl_result;
@@ -761,6 +785,10 @@
GenDivZeroCheck(rs_r1);
}
+ // Check if numerator is 0
+ OpRegImm(kOpCmp, rs_r0, 0);
+ LIR* branch = NewLIR2(kX86Jcc8, 0, kX86CondEq);
+
// Have to catch 0x80000000/-1 case, or we will get an exception!
OpRegImm(kOpCmp, rs_r1, -1);
LIR *minus_one_branch = NewLIR2(kX86Jcc8, 0, kX86CondNe);
@@ -769,6 +797,8 @@
OpRegImm(kOpCmp, rs_r0, 0x80000000);
LIR * minint_branch = NewLIR2(kX86Jcc8, 0, kX86CondNe);
+ branch->target = NewLIR0(kPseudoTargetLabel);
+
// In 0x80000000/-1 case.
if (!is_div) {
// For DIV, EAX is already right. For REM, we need EDX 0.
diff --git a/test/012-math/expected.txt b/test/012-math/expected.txt
index af9708e..75a559e 100644
--- a/test/012-math/expected.txt
+++ b/test/012-math/expected.txt
@@ -30,3 +30,11 @@
f:21.0
f:3.0
f:3.0
+0
+0
+0
+0
+0
+0
+0
+0
diff --git a/test/012-math/src/Main.java b/test/012-math/src/Main.java
index a4a8c71..07b7540 100644
--- a/test/012-math/src/Main.java
+++ b/test/012-math/src/Main.java
@@ -99,7 +99,27 @@
f %= g;
System.out.println("f:" +f);
}
+ public static void math_012_numerator(int a, int b, int d, int e, int f) {
+ int c = 0;
+ c /= b;
+ System.out.println(c);
+ c %= b;
+ System.out.println(c);
+ c = a / b;
+ System.out.println(c);
+ c = a % b;
+ System.out.println(c);
+ c = c / d;
+ System.out.println(c);
+ c = c / e;
+ System.out.println(c);
+ c = c / f;
+ System.out.println(c);
+ c = c % f;
+ System.out.println(c);
+ }
public static void main(String args[]) {
math_012();
+ math_012_numerator(0, 3, -1, 4, 5);
}
}