ARM: Optimize truncating division and fix sim
authorm.m.capewell@googlemail.com <m.m.capewell@googlemail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 2 Jan 2014 16:36:21 +0000 (16:36 +0000)
committerm.m.capewell@googlemail.com <m.m.capewell@googlemail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 2 Jan 2014 16:36:21 +0000 (16:36 +0000)
Optimize code generated for DivI Lithium instruction when handling division
where the result is int32. Also, fix the ARM simulator to give the correct
answer for kMinInt / -1.

TEST=Division tests added to test-assembler-arm.cc
BUG=
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/102623003

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

src/arm/lithium-codegen-arm.cc
src/arm/simulator-arm.cc
test/cctest/test-assembler-arm.cc

index 7e91af3..0463ce4 100644 (file)
@@ -1408,7 +1408,11 @@ void LCodeGen::DoDivI(LDivI* instr) {
   }
 
   // Check for (kMinInt / -1).
-  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow) &&
+      (!CpuFeatures::IsSupported(SUDIV) ||
+       !instr->hydrogen()->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+    // We don't need to check for overflow when truncating with sdiv
+    // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
     __ cmp(left, Operand(kMinInt));
     __ cmp(right, Operand(-1), eq);
     DeoptimizeIf(eq, instr->environment());
index 461d032..131a1bb 100644 (file)
@@ -2733,7 +2733,11 @@ void Simulator::DecodeType3(Instruction* instr) {
                int32_t rs_val = get_register(rs);
                int32_t ret_val = 0;
                ASSERT(rs_val != 0);
-               ret_val = rm_val/rs_val;
+               if ((rm_val == kMinInt) && (rs_val == -1)) {
+                 ret_val = kMinInt;
+               } else {
+                 ret_val = rm_val / rs_val;
+               }
                set_register(rn, ret_val);
                return;
              }
index 69ea6f4..b21dc34 100644 (file)
@@ -1439,6 +1439,72 @@ TEST(17) {
 }
 
 
+#define TEST_SDIV(expected_, dividend_, divisor_) \
+    t.dividend = dividend_; \
+    t.divisor = divisor_; \
+    t.result = 0; \
+    dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
+    CHECK_EQ(expected_, t.result);
+
+
+TEST(18) {
+  // Test the sdiv.
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+
+  typedef struct {
+    uint32_t dividend;
+    uint32_t divisor;
+    uint32_t result;
+  } T;
+  T t;
+
+  Assembler assm(isolate, NULL, 0);
+
+  if (CpuFeatures::IsSupported(SUDIV)) {
+    CpuFeatureScope scope(&assm, SUDIV);
+
+    __ mov(r3, Operand(r0));
+
+    __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
+    __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
+
+    __ sdiv(r2, r0, r1);
+    __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
+
+  __ bx(lr);
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = isolate->heap()->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Code>())->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    Object* dummy;
+    TEST_SDIV(1073741824, kMinInt, -2);
+    TEST_SDIV(kMinInt, kMinInt, -1);
+    TEST_SDIV(5, 10, 2);
+    TEST_SDIV(3, 10, 3);
+    TEST_SDIV(-5, 10, -2);
+    TEST_SDIV(-3, 10, -3);
+    TEST_SDIV(-5, -10, 2);
+    TEST_SDIV(-3, -10, 3);
+    TEST_SDIV(5, -10, -2);
+    TEST_SDIV(3, -10, -3);
+    USE(dummy);
+  }
+}
+
+
+#undef TEST_SDIV
+
+
 TEST(code_relative_offset) {
   // Test extracting the offset of a label from the beginning of the code
   // in a register.