Improve integer division on ARM in favor of power of 2 constant divisor

BUG=none
TEST=none

Review URL: https://chromiumcodereview.appspot.com/12052032
Patch from Rajeev R Krithivasan <rkrithiv@codeaurora.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13819 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ulan@chromium.org 2013-03-05 08:47:59 +00:00
parent d6fd3a0767
commit be2b1a980f
5 changed files with 45 additions and 6 deletions

View File

@ -1226,6 +1226,13 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
} else if (instr->representation().IsInteger32()) {
if (instr->HasPowerOf2Divisor()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
LDivI* div =
new(zone()) LDivI(value, UseOrConstant(instr->right()));
return AssignEnvironment(DefineSameAsFirst(div));
}
// TODO(1042) The fixed register allocation
// is needed because we call TypeRecordingBinaryOpStub from
// the generated code, which requires registers r0

View File

@ -1411,6 +1411,42 @@ void LCodeGen::DoDivI(LDivI* instr) {
LDivI* instr_;
};
if (instr->hydrogen()->HasPowerOf2Divisor()) {
Register dividend = ToRegister(instr->left());
int32_t divisor =
HConstant::cast(instr->hydrogen()->right())->Integer32Value();
int32_t test_value = 0;
int32_t power = 0;
if (divisor > 0) {
test_value = divisor - 1;
power = WhichPowerOf2(divisor);
} else {
// Check for (0 / -x) that will produce negative zero.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ tst(dividend, Operand(dividend));
DeoptimizeIf(eq, instr->environment());
}
// Check for (kMinInt / -1).
if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
__ cmp(dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr->environment());
}
test_value = - divisor - 1;
power = WhichPowerOf2(-divisor);
}
if (test_value != 0) {
// Deoptimize if remainder is not 0.
__ tst(dividend, Operand(test_value));
DeoptimizeIf(ne, instr->environment());
__ mov(dividend, Operand(dividend, ASR, power));
}
if (divisor < 0) __ rsb(dividend, dividend, Operand(0));
return;
}
const Register left = ToRegister(instr->left());
const Register right = ToRegister(instr->right());
const Register scratch = scratch0();

View File

@ -184,7 +184,7 @@ test_div();
%OptimizeFunctionOnNextCall(test_div);
test_div();
// Test for ia32/x64 flooring correctness.
// Test for flooring correctness.
var values2 = [1, 3, 10, 99, 100, 101, 0x7fffffff];
function test_div2() {
for (var i = 0; i < values2.length; i++) {

View File

@ -184,7 +184,7 @@ test_div();
%OptimizeFunctionOnNextCall(test_div);
test_div();
// Test for ia32/x64 flooring correctness.
// Test for flooring correctness.
var values2 = [1, 3, 10, 99, 100, 101, 0x7fffffff];
function test_div2() {
for (var i = 0; i < values2.length; i++) {

View File

@ -80,10 +80,6 @@ generated-transition-stub: PASS, SKIP if $mode == debug
d8-os: PASS, SKIP if ($isolates || $arch == android_arm || $arch == android_ia32)
tools/tickprocessor: PASS, SKIP if ($arch == android_arm || $arch == android_ia32)
##############################################################################
# This test is the same as math-floor-of-div for non ARM architectures.
math-floor-of-div-nosudiv: PASS, SKIP if ($arch != arm && $arch != android_arm)
##############################################################################
# Long running test that reproduces memory leak and should be run manually.
regress/regress-2073: SKIP