MIPS: Re-work DoModI.
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 17 Nov 2011 13:33:56 +0000 (13:33 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 17 Nov 2011 13:33:56 +0000 (13:33 +0000)
Changes:
-separated the two code-paths (constant power of 2 divisor similar to ARM and everything else)
-replaced a bailout condition with faster handling (negative modulo result)
-removed a possibly useless mov instruction from one path
-replaced the IsConstantOperand condition with the more meaningful HasPowerOf2Divisor (although in this specific case they're equivalent)

BUG=
TEST=

Review URL: http://codereview.chromium.org/8591002
Patch from Gergely Kis <gergely@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10016 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/mips/lithium-codegen-mips.cc

index ca1d2b5..36ee47b 100644 (file)
@@ -874,52 +874,47 @@ void LCodeGen::DoModI(LModI* instr) {
   const Register left = ToRegister(instr->InputAt(0));
   const Register result = ToRegister(instr->result());
 
-  // p2constant holds the right side value if it's a power of 2 constant.
-  // In other cases it is 0.
-  int32_t p2constant = 0;
-
-  if (instr->InputAt(1)->IsConstantOperand()) {
-      p2constant = ToInteger32(LConstantOperand::cast(instr->InputAt(1)));
-      if (p2constant % 2 != 0) {
-        p2constant = 0;
-      }
-      // Result always takes the sign of the dividend (left).
-      p2constant = abs(p2constant);
-  }
-
-  // div runs in the background while we check for special cases.
-  Register right = EmitLoadRegister(instr->InputAt(1), scratch);
-  __ div(left, right);
+  Label done;
 
-  // Check for x % 0.
-  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
-    DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
-  }
+  if (instr->hydrogen()->HasPowerOf2Divisor()) {
+    Register scratch = scratch0();
+    ASSERT(!left.is(scratch));
+    __ mov(scratch, left);
+    int32_t p2constant = HConstant::cast(
+        instr->hydrogen()->right())->Integer32Value();
+    ASSERT(p2constant != 0);
+    // Result always takes the sign of the dividend (left).
+    p2constant = abs(p2constant);
 
-  Label skip_div, do_div;
-  if (p2constant != 0) {
-    // Fall back to the result of the div instruction if we could have sign
-    // problems.
-    __ Branch(&do_div, lt, left, Operand(zero_reg));
-    // Modulo by masking.
-    __ And(scratch, left, p2constant - 1);
-    __ Branch(&skip_div);
-  }
+    Label positive_dividend;
+    __ Branch(USE_DELAY_SLOT, &positive_dividend, ge, left, Operand(zero_reg));
+    __ subu(result, zero_reg, left);
+    __ And(result, result, p2constant - 1);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
+    }
+    __ Branch(USE_DELAY_SLOT, &done);
+    __ subu(result, zero_reg, result);
+    __ bind(&positive_dividend);
+    __ And(result, scratch, p2constant - 1);
+  } else {
+    // div runs in the background while we check for special cases.
+    Register right = EmitLoadRegister(instr->InputAt(1), scratch);
+    __ div(left, right);
 
-  __ bind(&do_div);
-  __ mfhi(scratch);
-  __ bind(&skip_div);
+    // Check for x % 0.
+    if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+      DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
+    }
 
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    // Result always takes the sign of the dividend (left).
-    Label done;
     __ Branch(USE_DELAY_SLOT, &done, ge, left, Operand(zero_reg));
-    __ mov(result, scratch);
-    DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
-    __ bind(&done);
-  } else {
-    __ Move(result, scratch);
+    __ mfhi(result);
+
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
+    }
   }
+  __ bind(&done);
 }