From d6aabbdcc736a87695b79c670a650fb51962e195 Mon Sep 17 00:00:00 2001 From: "m.m.capewell@googlemail.com" Date: Thu, 2 Jan 2014 16:36:21 +0000 Subject: [PATCH] ARM: Optimize truncating division and fix sim 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 | 6 +++- src/arm/simulator-arm.cc | 6 +++- test/cctest/test-assembler-arm.cc | 66 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 7e91af3..0463ce4 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -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()); diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc index 461d032..131a1bb 100644 --- a/src/arm/simulator-arm.cc +++ b/src/arm/simulator-arm.cc @@ -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; } diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc index 69ea6f4..b21dc34 100644 --- a/test/cctest/test-assembler-arm.cc +++ b/test/cctest/test-assembler-arm.cc @@ -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())->ToObjectChecked(); + CHECK(code->IsCode()); +#ifdef DEBUG + Code::cast(code)->Print(); +#endif + F3 f = FUNCTION_CAST(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. -- 2.7.4