ARM: Tweak Math.exp.
Avoid corrupting the input and small assembly tuning. BUG=none TEST=test/mjsunit/lithium/MathExp.js R=ulan@chromium.org Review URL: https://codereview.chromium.org/24278004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16913 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f26bcd9fef
commit
6d8f4d52bf
@ -775,50 +775,65 @@ void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
|
||||
ASSERT(!temp2.is(temp3));
|
||||
ASSERT(ExternalReference::math_exp_constants(0).address() != NULL);
|
||||
|
||||
Label done;
|
||||
Label zero, infinity, done;
|
||||
|
||||
__ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
|
||||
|
||||
__ vldr(double_scratch1, ExpConstant(0, temp3));
|
||||
__ vmov(result, kDoubleRegZero);
|
||||
__ VFPCompareAndSetFlags(double_scratch1, input);
|
||||
__ b(ge, &done);
|
||||
__ b(ge, &zero);
|
||||
|
||||
__ vldr(double_scratch2, ExpConstant(1, temp3));
|
||||
__ VFPCompareAndSetFlags(input, double_scratch2);
|
||||
__ vldr(result, ExpConstant(2, temp3));
|
||||
__ b(ge, &done);
|
||||
__ b(ge, &infinity);
|
||||
|
||||
__ vldr(double_scratch1, ExpConstant(3, temp3));
|
||||
__ vldr(result, ExpConstant(4, temp3));
|
||||
__ vmul(double_scratch1, double_scratch1, input);
|
||||
__ vadd(double_scratch1, double_scratch1, result);
|
||||
__ vmov(temp2, temp1, double_scratch1);
|
||||
__ VmovLow(temp2, double_scratch1);
|
||||
__ vsub(double_scratch1, double_scratch1, result);
|
||||
__ vldr(result, ExpConstant(6, temp3));
|
||||
__ vldr(double_scratch2, ExpConstant(5, temp3));
|
||||
__ vmul(double_scratch1, double_scratch1, double_scratch2);
|
||||
__ vsub(double_scratch1, double_scratch1, input);
|
||||
__ vsub(result, result, double_scratch1);
|
||||
__ vmul(input, double_scratch1, double_scratch1);
|
||||
__ vmul(result, result, input);
|
||||
__ mov(temp1, Operand(temp2, LSR, 11));
|
||||
__ vmul(double_scratch2, double_scratch1, double_scratch1);
|
||||
__ vmul(result, result, double_scratch2);
|
||||
__ vldr(double_scratch2, ExpConstant(7, temp3));
|
||||
__ vmul(result, result, double_scratch2);
|
||||
__ vsub(result, result, double_scratch1);
|
||||
__ vldr(double_scratch2, ExpConstant(8, temp3));
|
||||
// Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
|
||||
ASSERT(*reinterpret_cast<double*>
|
||||
(ExternalReference::math_exp_constants(8).address()) == 1);
|
||||
__ vmov(double_scratch2, 1);
|
||||
__ vadd(result, result, double_scratch2);
|
||||
__ movw(ip, 0x7ff);
|
||||
__ and_(temp2, temp2, Operand(ip));
|
||||
__ mov(temp1, Operand(temp2, LSR, 11));
|
||||
__ Ubfx(temp2, temp2, 0, 11);
|
||||
__ add(temp1, temp1, Operand(0x3ff));
|
||||
__ mov(temp1, Operand(temp1, LSL, 20));
|
||||
|
||||
// Must not call ExpConstant() after overwriting temp3!
|
||||
__ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
|
||||
__ ldr(ip, MemOperand(temp3, temp2, LSL, 3));
|
||||
__ add(temp3, temp3, Operand(kPointerSize));
|
||||
__ ldr(temp2, MemOperand(temp3, temp2, LSL, 3));
|
||||
__ orr(temp1, temp1, temp2);
|
||||
__ vmov(input, ip, temp1);
|
||||
__ vmul(result, result, input);
|
||||
__ add(temp3, temp3, Operand(temp2, LSL, 3));
|
||||
__ ldm(ia, temp3, temp2.bit() | temp3.bit());
|
||||
// The first word is loaded is the lower number register.
|
||||
if (temp2.code() < temp3.code()) {
|
||||
__ orr(temp1, temp3, Operand(temp1, LSL, 20));
|
||||
__ vmov(double_scratch1, temp2, temp1);
|
||||
} else {
|
||||
__ orr(temp1, temp2, Operand(temp1, LSL, 20));
|
||||
__ vmov(double_scratch1, temp3, temp1);
|
||||
}
|
||||
__ vmul(result, result, double_scratch1);
|
||||
__ b(&done);
|
||||
|
||||
__ bind(&zero);
|
||||
__ vmov(result, kDoubleRegZero);
|
||||
__ b(&done);
|
||||
|
||||
__ bind(&infinity);
|
||||
__ vldr(result, ExpConstant(2, temp3));
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,7 @@ class StringCharLoadGenerator : public AllStatic {
|
||||
|
||||
class MathExpGenerator : public AllStatic {
|
||||
public:
|
||||
// Register input isn't modified. All other registers are clobbered.
|
||||
static void EmitMathExp(MacroAssembler* masm,
|
||||
DwVfpRegister input,
|
||||
DwVfpRegister result,
|
||||
|
@ -1240,7 +1240,7 @@ LInstruction* LChunkBuilder::DoMathTan(HUnaryMathOperation* instr) {
|
||||
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
|
||||
ASSERT(instr->representation().IsDouble());
|
||||
ASSERT(instr->value()->representation().IsDouble());
|
||||
LOperand* input = UseTempRegister(instr->value());
|
||||
LOperand* input = UseRegister(instr->value());
|
||||
LOperand* temp1 = TempRegister();
|
||||
LOperand* temp2 = TempRegister();
|
||||
LOperand* double_temp = FixedTemp(d3); // Chosen by fair dice roll.
|
||||
|
39
test/mjsunit/lithium/MathExp.js
Normal file
39
test/mjsunit/lithium/MathExp.js
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
function foo(x) {
|
||||
return Math.exp(x);
|
||||
}
|
||||
|
||||
foo(12.3);
|
||||
var r1 = foo(12.3);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
var r2 = foo(12.3);
|
||||
|
||||
assertEquals(r1, r2);
|
Loading…
Reference in New Issue
Block a user