Added optimization for div/mod by constant power of 2.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 12 Feb 2010 13:37:10 +0000 (13:37 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 12 Feb 2010 13:37:10 +0000 (13:37 +0000)
Review URL: http://codereview.chromium.org/597059

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

src/ia32/codegen-ia32.cc
test/mjsunit/div-mod.js

index 9d7319c..9fbdbf6 100644 (file)
@@ -1848,6 +1848,39 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
       break;
     }
 
+    case Token::DIV:
+      if (!reversed && int_value == 2) {
+        operand->ToRegister();
+        frame_->Spill(operand->reg());
+
+        DeferredInlineSmiOperation* deferred =
+            new DeferredInlineSmiOperation(op,
+                                           operand->reg(),
+                                           operand->reg(),
+                                           smi_value,
+                                           overwrite_mode);
+        // Check that lowest log2(value) bits of operand are zero, and test
+        // smi tag at the same time.
+        ASSERT_EQ(0, kSmiTag);
+        ASSERT_EQ(1, kSmiTagSize);
+        __ test(operand->reg(), Immediate(3));
+        deferred->Branch(not_zero);  // Branch if non-smi or odd smi.
+        __ sar(operand->reg(), 1);
+        deferred->BindExit();
+        answer = *operand;
+      } else {
+        // Cannot fall through MOD to default case, so we duplicate the
+        // default case here.
+        Result constant_operand(value);
+        if (reversed) {
+          answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
+                                            overwrite_mode);
+        } else {
+          answer = LikelySmiBinaryOperation(op, operand, &constant_operand,
+                                            overwrite_mode);
+        }
+      }
+      break;
     // Generate inline code for mod of powers of 2 and negative powers of 2.
     case Token::MOD:
       if (!reversed &&
index b3c77e1..1d352b5 100644 (file)
@@ -154,4 +154,18 @@ function compute_mod(dividend, divisor) {
       doTest(-a,-b);
     }
   }
-})()
+})();
+
+
+(function () {
+  // Edge cases
+  var zero = 0;
+  var minsmi32 = -0x40000000;
+  var minsmi64 = -0x80000000;
+  var somenum = 3532;
+  assertEquals(-0, zero / -1, "0 / -1");
+  assertEquals(1, minsmi32 / -0x40000000, "minsmi/minsmi-32");
+  assertEquals(1, minsmi64 / -0x80000000, "minsmi/minsmi-64");
+  assertEquals(somenum, somenum % -0x40000000, "%minsmi-32");
+  assertEquals(somenum, somenum % -0x80000000, "%minsmi-64");
+})();