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:
parent
d6fd3a0767
commit
be2b1a980f
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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++) {
|
||||
|
@ -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++) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user