ARM: Tweak Math.exp.
authorrodolph.perfetta@gmail.com <rodolph.perfetta@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 Sep 2013 10:40:03 +0000 (10:40 +0000)
committerrodolph.perfetta@gmail.com <rodolph.perfetta@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 Sep 2013 10:40:03 +0000 (10:40 +0000)
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

src/arm/codegen-arm.cc
src/arm/codegen-arm.h
src/arm/lithium-arm.cc
test/mjsunit/lithium/MathExp.js [new file with mode: 0644]

index fbd9f6388024d7562b9727c9e1650963e3de3d64..e19c5abb00393c67837d488f4d8fcd488a6744e1 100644 (file)
@@ -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);
 }
 
index 54530d87262df1577603039e1840e5f501c0bbd7..ecbe64cbad304d8f7eb5d875f99ea3e7e5ad7a61 100644 (file)
@@ -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,
index f216a8e094d409bc80c5b492bd27744ab08d94f9..6fdbbb58934c0e852df086b589f55edab6f85905 100644 (file)
@@ -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.
diff --git a/test/mjsunit/lithium/MathExp.js b/test/mjsunit/lithium/MathExp.js
new file mode 100644 (file)
index 0000000..854ff5f
--- /dev/null
@@ -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);