Reviewers: ulan, Benedikt Meurer,

Message:
On ARM there is no reason for the division to always overwrite its left input.

Minor clean up on deoptimisation code too.

Description:
ARM: Tweak the integer division operation.

BUG=none
TEST=test/mjsunit/lithium/DivI.js

Please review this at https://codereview.chromium.org/23536045/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+51, -27 lines):
  M src/arm/lithium-arm.cc
  M src/arm/lithium-codegen-arm.cc
  A + test/mjsunit/lithium/DivI.js


Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 7f504ea4ad4452d7da59d63bb192172fd021abee..d3ac5e0dfebf67c4ed54481d8669852b842c1c83 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1373,9 +1373,8 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
       LOperand* value = UseRegisterAtStart(instr->left());
-      LDivI* div =
-          new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
-      return AssignEnvironment(DefineSameAsFirst(div));
+ LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL);
+      return AssignEnvironment(DefineAsRegister(div));
     }
     LOperand* dividend = UseRegister(instr->left());
     LOperand* divisor = UseRegister(instr->right());
Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index b7fc3b6055c67704f1065e3f232f039aa52bb745..b01f840c63140aff23c46f227798c2592a52db22 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -1383,7 +1383,8 @@ void LCodeGen::EmitSignedIntegerDivisionByConstant(

 void LCodeGen::DoDivI(LDivI* instr) {
   if (instr->hydrogen()->HasPowerOf2Divisor()) {
-    Register dividend = ToRegister(instr->left());
+    const Register dividend = ToRegister(instr->left());
+    const Register result = ToRegister(instr->result());
     int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant();
     int32_t test_value = 0;
     int32_t power = 0;
@@ -1394,7 +1395,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
     } else {
       // Check for (0 / -x) that will produce negative zero.
       if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-        __ tst(dividend, Operand(dividend));
+        __ cmp(dividend, Operand::Zero());
         DeoptimizeIf(eq, instr->environment());
       }
       // Check for (kMinInt / -1).
@@ -1409,20 +1410,26 @@ void LCodeGen::DoDivI(LDivI* instr) {
     if (test_value != 0) {
       if (instr->hydrogen()->CheckFlag(
           HInstruction::kAllUsesTruncatingToInt32)) {
-        __ cmp(dividend, Operand(0));
-        __ rsb(dividend, dividend, Operand(0), LeaveCC, lt);
-        __ mov(dividend, Operand(dividend, ASR, power));
- if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); - if (divisor < 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, gt);
+        __ sub(result, dividend, Operand::Zero(), SetCC);
+        __ rsb(result, result, Operand::Zero(), LeaveCC, lt);
+        __ mov(result, Operand(result, ASR, power));
+ if (divisor > 0) __ rsb(result, result, Operand::Zero(), LeaveCC, lt); + if (divisor < 0) __ rsb(result, result, Operand::Zero(), LeaveCC, gt);
         return;  // Don't fall through to "__ rsb" below.
       } else {
         // Deoptimize if remainder is not 0.
         __ tst(dividend, Operand(test_value));
         DeoptimizeIf(ne, instr->environment());
-        __ mov(dividend, Operand(dividend, ASR, power));
+        __ mov(result, Operand(dividend, ASR, power));
+        if (divisor < 0) __ rsb(result, result, Operand(0));
+      }
+    } else {
+      if (divisor < 0) {
+        __ rsb(result, dividend, Operand(0));
+      } else {
+        __ Move(result, dividend);
       }
     }
-    if (divisor < 0) __ rsb(dividend, dividend, Operand(0));

     return;
   }
@@ -1439,12 +1446,15 @@ void LCodeGen::DoDivI(LDivI* instr) {

   // Check for (0 / -x) that will produce negative zero.
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    Label left_not_zero;
+    Label positive;
+    if (!instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+      // Do the test only if it hadn't be done above.
+      __ cmp(right, Operand::Zero());
+    }
+    __ b(pl, &positive);
     __ cmp(left, Operand::Zero());
-    __ b(ne, &left_not_zero);
-    __ cmp(right, Operand::Zero());
-    DeoptimizeIf(mi, instr->environment());
-    __ bind(&left_not_zero);
+    DeoptimizeIf(eq, instr->environment());
+    __ bind(&positive);
   }

   // Check for (kMinInt / -1).
Index: test/mjsunit/lithium/DivI.js
diff --git a/test/mjsunit/constant-compare-nil-value.js b/test/mjsunit/lithium/DivI.js
similarity index 73%
copy from test/mjsunit/constant-compare-nil-value.js
copy to test/mjsunit/lithium/DivI.js
index 9f5b2adb063abc0c7920d8dee30edb7ee6eb1ff9..5420d8c8d0ab0adc715683fd95f41a34e9373fc0 100644
--- a/test/mjsunit/constant-compare-nil-value.js
+++ b/test/mjsunit/lithium/DivI.js
@@ -25,18 +25,33 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-// Flags: --allow-natives-syntax
+// Flags: --allow-natives-syntax --no-use-osr

-function inlined() {
-    return 1;
+function foo(a, b) {
+  var result = a / 35;
+  result += 50 / b;
+  result += a / b;
+  result += a / -1;
+  result += a / 1;
+  result += a / 4;
+  result += a / -4;
+  return result / b;
 }

-function foo() {
-    if ((inlined() + 0.5) == null) return "null";
-    return "non-null";
+foo(700, 5);
+var r1 = foo(700, 5);
+%OptimizeFunctionOnNextCall(foo);
+var r2 = foo(700, 5);
+
+assertEquals(r1, r2);
+
+function boo(value) {
+  return value / -1;
 }

-assertEquals("non-null", foo());
-assertEquals("non-null", foo());
-%OptimizeFunctionOnNextCall(foo);
-assertEquals("non-null", foo());
+// Test deoptimization of MinInt / -1.
+assertEquals(2147483600, boo(-2147483600));
+assertEquals(2147483600, boo(-2147483600));
+%OptimizeFunctionOnNextCall(boo);
+assertEquals(2147483600, boo(-2147483600));
+assertEquals(2147483648, boo(-2147483648));


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to