[builtins] Introduce proper base::ieee754::log.
This switches Math.log to use an fdlibm based version of log, imported as base::ieee754::log, and use that consistently everywhere, i.e. change the Float64Log TurboFan operators on Intel to use the C++ implementation as well (same for Crankshaft). R=yangguo@chromium.org BUG=v8:5065,v8:5086 Review-Url: https://codereview.chromium.org/2053893003 Cr-Commit-Position: refs/heads/master@{#36880}
This commit is contained in:
parent
e5760c0808
commit
d0c7775d7c
2
BUILD.gn
2
BUILD.gn
@ -1898,6 +1898,8 @@ v8_source_set("v8_libbase") {
|
||||
"src/base/functional.cc",
|
||||
"src/base/functional.h",
|
||||
"src/base/hashmap.h",
|
||||
"src/base/ieee754.cc",
|
||||
"src/base/ieee754.h",
|
||||
"src/base/iterator.h",
|
||||
"src/base/lazy-instance.h",
|
||||
"src/base/logging.cc",
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "src/api.h"
|
||||
#include "src/base/cpu.h"
|
||||
#include "src/base/functional.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/base/lazy-instance.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
@ -1027,7 +1028,7 @@ void ExternalReference::InitializeMathExpData() {
|
||||
// The rest is black magic. Do not attempt to understand it. It is
|
||||
// loosely based on the "expd" function published at:
|
||||
// http://herumi.blogspot.com/2011/08/fast-double-precision-exponential.html
|
||||
const double constant3 = (1 << kTableSizeBits) / std::log(2.0);
|
||||
const double constant3 = (1 << kTableSizeBits) / base::ieee754::log(2.0);
|
||||
math_exp_constants_array[3] = constant3;
|
||||
math_exp_constants_array[4] =
|
||||
static_cast<double>(static_cast<int64_t>(3) << 51);
|
||||
@ -1647,13 +1648,9 @@ ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
|
||||
|
||||
#endif // V8_INTERPRETED_REGEXP
|
||||
|
||||
|
||||
ExternalReference ExternalReference::math_log_double_function(
|
||||
Isolate* isolate) {
|
||||
typedef double (*d2d)(double x);
|
||||
return ExternalReference(Redirect(isolate,
|
||||
FUNCTION_ADDR(static_cast<d2d>(std::log)),
|
||||
BUILTIN_FP_CALL));
|
||||
ExternalReference ExternalReference::ieee754_log_function(Isolate* isolate) {
|
||||
return ExternalReference(
|
||||
Redirect(isolate, FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1035,7 +1035,8 @@ class ExternalReference BASE_EMBEDDED {
|
||||
static ExternalReference address_of_the_hole_nan();
|
||||
static ExternalReference address_of_uint32_bias();
|
||||
|
||||
static ExternalReference math_log_double_function(Isolate* isolate);
|
||||
// IEEE 754 functions.
|
||||
static ExternalReference ieee754_log_function(Isolate* isolate);
|
||||
|
||||
static ExternalReference math_exp_constants(int constant_index);
|
||||
static ExternalReference math_exp_log_table();
|
||||
|
197
src/base/ieee754.cc
Normal file
197
src/base/ieee754.cc
Normal file
@ -0,0 +1,197 @@
|
||||
// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunSoft, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
// The original source code covered by the above license above has been
|
||||
// modified significantly by Google Inc.
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
|
||||
#include "src/base/ieee754.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "src/base/build_config.h"
|
||||
#include "src/base/macros.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
namespace ieee754 {
|
||||
|
||||
namespace {
|
||||
|
||||
union Float64 {
|
||||
double v;
|
||||
uint64_t w;
|
||||
struct {
|
||||
#if V8_TARGET_LITTLE_ENDIAN
|
||||
uint32_t lw;
|
||||
uint32_t hw;
|
||||
#else
|
||||
uint32_t hw;
|
||||
uint32_t lw;
|
||||
#endif
|
||||
} words;
|
||||
};
|
||||
|
||||
// Extract the less significant 32-bit word from a double.
|
||||
V8_INLINE uint32_t extractLowWord32(double v) {
|
||||
Float64 f;
|
||||
f.v = v;
|
||||
return f.words.lw;
|
||||
}
|
||||
|
||||
// Extract the most significant 32-bit word from a double.
|
||||
V8_INLINE uint32_t extractHighWord32(double v) {
|
||||
Float64 f;
|
||||
f.v = v;
|
||||
return f.words.hw;
|
||||
}
|
||||
|
||||
// Insert the most significant 32-bit word into a double.
|
||||
V8_INLINE double insertHighWord32(double v, uint32_t hw) {
|
||||
Float64 f;
|
||||
f.v = v;
|
||||
f.words.hw = hw;
|
||||
return f.v;
|
||||
}
|
||||
|
||||
double const kLn2Hi = 6.93147180369123816490e-01; // 3fe62e42 fee00000
|
||||
double const kLn2Lo = 1.90821492927058770002e-10; // 3dea39ef 35793c76
|
||||
double const kTwo54 = 1.80143985094819840000e+16; // 43500000 00000000
|
||||
double const kLg1 = 6.666666666666735130e-01; // 3FE55555 55555593
|
||||
double const kLg2 = 3.999999999940941908e-01; // 3FD99999 9997FA04
|
||||
double const kLg3 = 2.857142874366239149e-01; // 3FD24924 94229359
|
||||
double const kLg4 = 2.222219843214978396e-01; // 3FCC71C5 1D8E78AF
|
||||
double const kLg5 = 1.818357216161805012e-01; // 3FC74664 96CB03DE
|
||||
double const kLg6 = 1.531383769920937332e-01; // 3FC39A09 D078C69F
|
||||
double const kLg7 = 1.479819860511658591e-01; // 3FC2F112 DF3E5244
|
||||
|
||||
} // namespace
|
||||
|
||||
/* log(x)
|
||||
* Return the logrithm of x
|
||||
*
|
||||
* Method :
|
||||
* 1. Argument Reduction: find k and f such that
|
||||
* x = 2^k * (1+f),
|
||||
* where sqrt(2)/2 < 1+f < sqrt(2) .
|
||||
*
|
||||
* 2. Approximation of log(1+f).
|
||||
* Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
|
||||
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
|
||||
* = 2s + s*R
|
||||
* We use a special Reme algorithm on [0,0.1716] to generate
|
||||
* a polynomial of degree 14 to approximate R The maximum error
|
||||
* of this polynomial approximation is bounded by 2**-58.45. In
|
||||
* other words,
|
||||
* 2 4 6 8 10 12 14
|
||||
* R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
|
||||
* (the values of Lg1 to Lg7 are listed in the program)
|
||||
* and
|
||||
* | 2 14 | -58.45
|
||||
* | Lg1*s +...+Lg7*s - R(z) | <= 2
|
||||
* | |
|
||||
* Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
|
||||
* In order to guarantee error in log below 1ulp, we compute log
|
||||
* by
|
||||
* log(1+f) = f - s*(f - R) (if f is not too large)
|
||||
* log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
|
||||
*
|
||||
* 3. Finally, log(x) = k*ln2 + log(1+f).
|
||||
* = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
|
||||
* Here ln2 is split into two floating point number:
|
||||
* ln2_hi + ln2_lo,
|
||||
* where n*ln2_hi is always exact for |n| < 2000.
|
||||
*
|
||||
* Special cases:
|
||||
* log(x) is NaN with signal if x < 0 (including -INF) ;
|
||||
* log(+INF) is +INF; log(0) is -INF with signal;
|
||||
* log(NaN) is that NaN with no signal.
|
||||
*
|
||||
* Accuracy:
|
||||
* according to an error analysis, the error is always less than
|
||||
* 1 ulp (unit in the last place).
|
||||
*
|
||||
* Constants:
|
||||
* The hexadecimal values are the intended ones for the following
|
||||
* constants. The decimal values may be used, provided that the
|
||||
* compiler will convert from decimal to binary accurately enough
|
||||
* to produce the hexadecimal values shown.
|
||||
*/
|
||||
double log(double x) {
|
||||
double hfsq, f, s, z, r, w, t1, t2, dk;
|
||||
int32_t k = 0, i, j;
|
||||
int32_t hx = extractHighWord32(x);
|
||||
uint32_t lx = extractLowWord32(x);
|
||||
|
||||
if (hx < 0x00100000) { /* x < 2**-1022 */
|
||||
if (((hx & 0x7fffffff) | lx) == 0) {
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (hx < 0) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
k -= 54;
|
||||
x *= kTwo54; /* subnormal number, scale up x */
|
||||
hx = extractHighWord32(x);
|
||||
}
|
||||
if (hx >= 0x7ff00000) return x + x;
|
||||
k += (hx >> 20) - 1023;
|
||||
hx &= 0x000fffff;
|
||||
i = (hx + 0x95f64) & 0x100000;
|
||||
x = insertHighWord32(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
|
||||
k += (i >> 20);
|
||||
f = x - 1.0;
|
||||
if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */
|
||||
if (f == 0.0) {
|
||||
if (k == 0) {
|
||||
return 0.0;
|
||||
} else {
|
||||
dk = static_cast<double>(k);
|
||||
return dk * kLn2Hi + dk * kLn2Lo;
|
||||
}
|
||||
}
|
||||
r = f * f * (0.5 - 0.33333333333333333 * f);
|
||||
if (k == 0) {
|
||||
return f - r;
|
||||
} else {
|
||||
dk = static_cast<double>(k);
|
||||
return dk * kLn2Hi - ((r - dk * kLn2Lo) - f);
|
||||
}
|
||||
}
|
||||
s = f / (2.0 + f);
|
||||
dk = static_cast<double>(k);
|
||||
z = s * s;
|
||||
i = hx - 0x6147a;
|
||||
w = z * z;
|
||||
j = 0x6b851 - hx;
|
||||
t1 = w * (kLg2 + w * (kLg4 + w * kLg6));
|
||||
t2 = z * (kLg1 + w * (kLg3 + w * (kLg5 + w * kLg7)));
|
||||
i |= j;
|
||||
r = t2 + t1;
|
||||
if (i > 0) {
|
||||
hfsq = 0.5 * f * f;
|
||||
if (k == 0) {
|
||||
return f - (hfsq - s * (hfsq + r));
|
||||
} else {
|
||||
return dk * kLn2Hi - ((hfsq - (s * (hfsq + r) + dk * kLn2Lo)) - f);
|
||||
}
|
||||
} else {
|
||||
if (k == 0) {
|
||||
return f - s * (f - r);
|
||||
} else {
|
||||
return dk * kLn2Hi - ((s * (f - r) - dk * kLn2Lo) - f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ieee754
|
||||
} // namespace base
|
||||
} // namespace v8
|
19
src/base/ieee754.h
Normal file
19
src/base/ieee754.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_BASE_IEEE754_H_
|
||||
#define V8_BASE_IEEE754_H_
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
namespace ieee754 {
|
||||
|
||||
// Returns the natural logarithm of |x|.
|
||||
double log(double x);
|
||||
|
||||
} // namespace ieee754
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_BASE_IEEE754_H_
|
@ -674,6 +674,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ add(i.OutputRegister(0), base, Operand(offset.offset()));
|
||||
break;
|
||||
}
|
||||
case kIeee754Float64Log: {
|
||||
// TODO(bmeurer): We should really get rid of this special instruction,
|
||||
// and generate a CallAddress instruction instead.
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputFloat64Register(0));
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
|
||||
1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputFloat64Register());
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
}
|
||||
case kArmAdd:
|
||||
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
|
||||
i.OutputSBit());
|
||||
@ -998,19 +1011,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
}
|
||||
case kArmVlogF64: {
|
||||
// TODO(bmeurer): We should really get rid of this special instruction,
|
||||
// and generate a CallAddress instruction instead.
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputFloat64Register(0));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputFloat64Register());
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
}
|
||||
case kArmVsqrtF64:
|
||||
__ vsqrt(i.OutputFloat64Register(), i.InputFloat64Register(0));
|
||||
break;
|
||||
|
@ -71,7 +71,6 @@ namespace compiler {
|
||||
V(ArmVdivF64) \
|
||||
V(ArmVmodF64) \
|
||||
V(ArmVabsF64) \
|
||||
V(ArmVlogF64) \
|
||||
V(ArmVnegF64) \
|
||||
V(ArmVsqrtF64) \
|
||||
V(ArmVrintmF32) \
|
||||
|
@ -73,7 +73,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArmVdivF64:
|
||||
case kArmVmodF64:
|
||||
case kArmVabsF64:
|
||||
case kArmVlogF64:
|
||||
case kArmVnegF64:
|
||||
case kArmVsqrtF64:
|
||||
case kArmVrintmF32:
|
||||
|
@ -1395,7 +1395,8 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitFloat64Log(Node* node) {
|
||||
ArmOperandGenerator g(this);
|
||||
Emit(kArmVlogF64, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
|
||||
Emit(kIeee754Float64Log, g.DefineAsFixed(node, d0),
|
||||
g.UseFixed(node->InputAt(0), d0))
|
||||
->MarkAsCall();
|
||||
}
|
||||
|
||||
|
@ -792,6 +792,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ Add(i.OutputRegister(0), base, Operand(offset.offset()));
|
||||
break;
|
||||
}
|
||||
case kIeee754Float64Log: {
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
DCHECK(d0.is(i.InputDoubleRegister(0)));
|
||||
DCHECK(d0.is(i.OutputDoubleRegister()));
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
|
||||
1);
|
||||
break;
|
||||
}
|
||||
case kArm64Float32RoundDown:
|
||||
__ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
|
||||
break;
|
||||
@ -1250,16 +1258,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArm64Float64Abs:
|
||||
__ Fabs(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
case kArm64Float64Log: {
|
||||
// TODO(dcarney): implement directly. See note in lithium-codegen-arm64.cc
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
DCHECK(d0.is(i.InputDoubleRegister(0)));
|
||||
DCHECK(d0.is(i.OutputDoubleRegister()));
|
||||
// TODO(dcarney): make sure this saves all relevant registers.
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
break;
|
||||
}
|
||||
case kArm64Float64Neg:
|
||||
__ Fneg(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
|
@ -104,7 +104,6 @@ namespace compiler {
|
||||
V(Arm64Float64Max) \
|
||||
V(Arm64Float64Min) \
|
||||
V(Arm64Float64Abs) \
|
||||
V(Arm64Float64Log) \
|
||||
V(Arm64Float64Neg) \
|
||||
V(Arm64Float64Sqrt) \
|
||||
V(Arm64Float64RoundDown) \
|
||||
|
@ -97,7 +97,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArm64Float64Max:
|
||||
case kArm64Float64Min:
|
||||
case kArm64Float64Abs:
|
||||
case kArm64Float64Log:
|
||||
case kArm64Float64Neg:
|
||||
case kArm64Float64Sqrt:
|
||||
case kArm64Float64RoundDown:
|
||||
|
@ -1689,7 +1689,7 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitFloat64Log(Node* node) {
|
||||
Arm64OperandGenerator g(this);
|
||||
Emit(kArm64Float64Log, g.DefineAsFixed(node, d0),
|
||||
Emit(kIeee754Float64Log, g.DefineAsFixed(node, d0),
|
||||
g.UseFixed(node->InputAt(0), d0))
|
||||
->MarkAsCall();
|
||||
}
|
||||
|
@ -617,6 +617,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ lea(i.OutputRegister(), Operand(base, offset.offset()));
|
||||
break;
|
||||
}
|
||||
case kIeee754Float64Log: {
|
||||
// Pass one double as argument on the stack.
|
||||
__ PrepareCallCFunction(2, eax);
|
||||
__ movsd(Operand(esp, 0 * kDoubleSize), i.InputDoubleRegister(0));
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
|
||||
// Return value is in st(0) on ia32.
|
||||
// Store it into the result register.
|
||||
__ sub(esp, Immediate(kDoubleSize));
|
||||
__ fstp_d(Operand(esp, 0));
|
||||
__ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
|
||||
__ add(esp, Immediate(kDoubleSize));
|
||||
break;
|
||||
}
|
||||
case kIA32Add:
|
||||
if (HasImmediateInput(instr, 1)) {
|
||||
__ add(i.InputOperand(0), i.InputImmediate(1));
|
||||
@ -820,16 +833,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kIA32Popcnt:
|
||||
__ Popcnt(i.OutputRegister(), i.InputOperand(0));
|
||||
break;
|
||||
case kX87Float64Log:
|
||||
__ sub(esp, Immediate(kDoubleSize));
|
||||
__ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
|
||||
__ fldln2();
|
||||
__ fld_d(Operand(esp, 0));
|
||||
__ fyl2x();
|
||||
__ fstp_d(Operand(esp, 0));
|
||||
__ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
|
||||
__ add(esp, Immediate(kDoubleSize));
|
||||
break;
|
||||
case kSSEFloat32Cmp:
|
||||
__ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
|
||||
break;
|
||||
|
@ -43,7 +43,6 @@ namespace compiler {
|
||||
V(IA32Lzcnt) \
|
||||
V(IA32Tzcnt) \
|
||||
V(IA32Popcnt) \
|
||||
V(X87Float64Log) \
|
||||
V(SSEFloat32Cmp) \
|
||||
V(SSEFloat32Add) \
|
||||
V(SSEFloat32Sub) \
|
||||
|
@ -46,7 +46,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kIA32Tzcnt:
|
||||
case kIA32Popcnt:
|
||||
case kIA32Lea:
|
||||
case kX87Float64Log:
|
||||
case kSSEFloat32Cmp:
|
||||
case kSSEFloat32Add:
|
||||
case kSSEFloat32Sub:
|
||||
|
@ -1015,7 +1015,10 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitFloat64Log(Node* node) {
|
||||
VisitRR(this, node, kX87Float64Log);
|
||||
IA32OperandGenerator g(this);
|
||||
Emit(kIeee754Float64Log, g.DefineSameAsFirst(node),
|
||||
g.UseRegister(node->InputAt(0)))
|
||||
->MarkAsCall();
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitFloat32Sqrt(Node* node) {
|
||||
|
@ -88,7 +88,8 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
|
||||
V(AtomicLoadWord32) \
|
||||
V(AtomicStoreWord8) \
|
||||
V(AtomicStoreWord16) \
|
||||
V(AtomicStoreWord32)
|
||||
V(AtomicStoreWord32) \
|
||||
V(Ieee754Float64Log)
|
||||
|
||||
#define ARCH_OPCODE_LIST(V) \
|
||||
COMMON_ARCH_OPCODE_LIST(V) \
|
||||
|
@ -224,6 +224,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
|
||||
case kArchStackSlot:
|
||||
case kArchDebugBreak:
|
||||
case kArchComment:
|
||||
case kIeee754Float64Log:
|
||||
return kNoOpcodeFlags;
|
||||
|
||||
case kArchStackPointer:
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/division-by-constant.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/codegen.h"
|
||||
#include "src/compiler/diamond.h"
|
||||
#include "src/compiler/graph.h"
|
||||
@ -384,7 +385,7 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
|
||||
}
|
||||
case IrOpcode::kFloat64Log: {
|
||||
Float64Matcher m(node->InputAt(0));
|
||||
if (m.HasValue()) return ReplaceFloat64(std::log(m.Value()));
|
||||
if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kChangeFloat32ToFloat64: {
|
||||
|
@ -718,6 +718,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
Operand(offset.offset()));
|
||||
break;
|
||||
}
|
||||
case kIeee754Float64Log: {
|
||||
// TODO(bmeurer): We should really get rid of this special instruction,
|
||||
// and generate a CallAddress instruction instead.
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0));
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
|
||||
1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
}
|
||||
case kMipsAdd:
|
||||
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
|
||||
break;
|
||||
@ -1037,18 +1049,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kMipsAbsD:
|
||||
__ abs_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
case kMipsLogD: {
|
||||
// TODO(bmeurer): We should really get rid of this special instruction,
|
||||
// and generate a CallAddress instruction instead.
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
}
|
||||
case kMipsSqrtD: {
|
||||
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
|
@ -60,7 +60,6 @@ namespace compiler {
|
||||
V(MipsDivD) \
|
||||
V(MipsModD) \
|
||||
V(MipsAbsD) \
|
||||
V(MipsLogD) \
|
||||
V(MipsSqrtD) \
|
||||
V(MipsMaxD) \
|
||||
V(MipsMinD) \
|
||||
|
@ -878,7 +878,8 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitFloat64Log(Node* node) {
|
||||
MipsOperandGenerator g(this);
|
||||
Emit(kMipsLogD, g.DefineAsFixed(node, f0), g.UseFixed(node->InputAt(0), f12))
|
||||
Emit(kIeee754Float64Log, g.DefineAsFixed(node, f0),
|
||||
g.UseFixed(node->InputAt(0), f12))
|
||||
->MarkAsCall();
|
||||
}
|
||||
|
||||
|
@ -727,6 +727,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
Operand(offset.offset()));
|
||||
break;
|
||||
}
|
||||
case kIeee754Float64Log: {
|
||||
// TODO(bmeurer): We should really get rid of this special instruction,
|
||||
// and generate a CallAddress instruction instead.
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0));
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
|
||||
1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
}
|
||||
case kMips64Add:
|
||||
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
|
||||
break;
|
||||
@ -1185,18 +1197,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kMips64AbsD:
|
||||
__ abs_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
case kMips64LogD: {
|
||||
// TODO(bmeurer): We should really get rid of this special instruction,
|
||||
// and generate a CallAddress instruction instead.
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
}
|
||||
case kMips64SqrtD: {
|
||||
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
|
@ -75,7 +75,6 @@ namespace compiler {
|
||||
V(Mips64DivD) \
|
||||
V(Mips64ModD) \
|
||||
V(Mips64AbsD) \
|
||||
V(Mips64LogD) \
|
||||
V(Mips64SqrtD) \
|
||||
V(Mips64MaxD) \
|
||||
V(Mips64MinD) \
|
||||
|
@ -1284,7 +1284,7 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitFloat64Log(Node* node) {
|
||||
Mips64OperandGenerator g(this);
|
||||
Emit(kMips64LogD, g.DefineAsFixed(node, f0),
|
||||
Emit(kIeee754Float64Log, g.DefineAsFixed(node, f0),
|
||||
g.UseFixed(node->InputAt(0), f12))
|
||||
->MarkAsCall();
|
||||
}
|
||||
|
@ -436,16 +436,15 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
||||
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ASSEMBLE_FLOAT_LOG() \
|
||||
do { \
|
||||
FrameScope scope(masm(), StackFrame::MANUAL); \
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg); \
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0)); \
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()), \
|
||||
0, 1); \
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister()); \
|
||||
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
||||
#define ASSEMBLE_FLOAT_LOG() \
|
||||
do { \
|
||||
FrameScope scope(masm(), StackFrame::MANUAL); \
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg); \
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0)); \
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, \
|
||||
1); \
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister()); \
|
||||
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
||||
} while (0)
|
||||
|
||||
#define ASSEMBLE_FLOAT_MAX(scratch_reg) \
|
||||
|
@ -1225,8 +1225,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
FrameScope scope(masm(), StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(0, 1, kScratchReg);
|
||||
__ MovToFloatParameter(i.InputDoubleRegister(0));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0,
|
||||
1);
|
||||
// Move the result in the double result register.
|
||||
__ MovFromFloatResult(i.OutputDoubleRegister());
|
||||
break;
|
||||
|
@ -840,6 +840,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ leaq(i.OutputRegister(), Operand(base, offset.offset()));
|
||||
break;
|
||||
}
|
||||
case kIeee754Float64Log:
|
||||
__ PrepareCallCFunction(1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 1);
|
||||
break;
|
||||
case kX64Add32:
|
||||
ASSEMBLE_BINOP(addl);
|
||||
break;
|
||||
@ -1008,16 +1012,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ Popcntl(i.OutputRegister(), i.InputOperand(0));
|
||||
}
|
||||
break;
|
||||
case kX87Float64Log:
|
||||
__ subq(rsp, Immediate(kDoubleSize));
|
||||
__ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
|
||||
__ fldln2();
|
||||
__ fld_d(Operand(rsp, 0));
|
||||
__ fyl2x();
|
||||
__ fstp_d(Operand(rsp, 0));
|
||||
__ Movsd(i.OutputDoubleRegister(), Operand(rsp, 0));
|
||||
__ addq(rsp, Immediate(kDoubleSize));
|
||||
break;
|
||||
case kSSEFloat32Cmp:
|
||||
ASSEMBLE_SSE_BINOP(Ucomiss);
|
||||
break;
|
||||
|
@ -56,7 +56,6 @@ namespace compiler {
|
||||
V(X64Tzcnt32) \
|
||||
V(X64Popcnt) \
|
||||
V(X64Popcnt32) \
|
||||
V(X87Float64Log) \
|
||||
V(SSEFloat32Cmp) \
|
||||
V(SSEFloat32Add) \
|
||||
V(SSEFloat32Sub) \
|
||||
|
@ -58,7 +58,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kX64Tzcnt32:
|
||||
case kX64Popcnt:
|
||||
case kX64Popcnt32:
|
||||
case kX87Float64Log:
|
||||
case kSSEFloat32Cmp:
|
||||
case kSSEFloat32Add:
|
||||
case kSSEFloat32Sub:
|
||||
|
@ -1356,7 +1356,10 @@ void InstructionSelector::VisitFloat64Abs(Node* node) {
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitFloat64Log(Node* node) {
|
||||
VisitRR(this, node, kX87Float64Log);
|
||||
X64OperandGenerator g(this);
|
||||
Emit(kIeee754Float64Log, g.DefineAsFixed(node, xmm0),
|
||||
g.UseFixed(node->InputAt(0), xmm0))
|
||||
->MarkAsCall();
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitFloat64Sqrt(Node* node) {
|
||||
|
@ -3557,8 +3557,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
__ PrepareCallCFunction(0, 1, scratch0());
|
||||
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
|
||||
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
|
||||
}
|
||||
|
||||
|
@ -3736,8 +3736,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
DCHECK(instr->IsMarkedAsCall());
|
||||
DCHECK(ToDoubleRegister(instr->value()).is(d0));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
|
||||
DCHECK(ToDoubleRegister(instr->result()).Is(d0));
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "src/crankshaft/hydrogen-instructions.h"
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/base/safe_math.h"
|
||||
#include "src/crankshaft/hydrogen-infer-representation.h"
|
||||
#include "src/double.h"
|
||||
@ -3425,7 +3426,7 @@ HInstruction* HUnaryMathOperation::New(Isolate* isolate, Zone* zone,
|
||||
lazily_initialize_fast_exp(isolate);
|
||||
return H_CONSTANT_DOUBLE(fast_exp(d, isolate));
|
||||
case kMathLog:
|
||||
return H_CONSTANT_DOUBLE(std::log(d));
|
||||
return H_CONSTANT_DOUBLE(base::ieee754::log(d));
|
||||
case kMathSqrt:
|
||||
lazily_initialize_fast_sqrt(isolate);
|
||||
return H_CONSTANT_DOUBLE(fast_sqrt(d, isolate));
|
||||
|
@ -3400,31 +3400,18 @@ void LCodeGen::DoPower(LPower* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
DCHECK(instr->value()->Equals(instr->result()));
|
||||
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
||||
XMMRegister xmm_scratch = double_scratch0();
|
||||
Label positive, done, zero;
|
||||
__ xorps(xmm_scratch, xmm_scratch);
|
||||
__ ucomisd(input_reg, xmm_scratch);
|
||||
__ j(above, &positive, Label::kNear);
|
||||
__ j(not_carry, &zero, Label::kNear);
|
||||
__ pcmpeqd(input_reg, input_reg);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&zero);
|
||||
ExternalReference ninf =
|
||||
ExternalReference::address_of_negative_infinity();
|
||||
__ movsd(input_reg, Operand::StaticVariable(ninf));
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&positive);
|
||||
__ fldln2();
|
||||
__ sub(Operand(esp), Immediate(kDoubleSize));
|
||||
__ movsd(Operand(esp, 0), input_reg);
|
||||
__ fld_d(Operand(esp, 0));
|
||||
__ fyl2x();
|
||||
XMMRegister input = ToDoubleRegister(instr->value());
|
||||
XMMRegister result = ToDoubleRegister(instr->result());
|
||||
// Pass one double as argument on the stack.
|
||||
__ PrepareCallCFunction(2, eax);
|
||||
__ movsd(Operand(esp, 0 * kDoubleSize), input);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
|
||||
// Return value is in st(0) on ia32.
|
||||
// Store it into the result register.
|
||||
__ sub(esp, Immediate(kDoubleSize));
|
||||
__ fstp_d(Operand(esp, 0));
|
||||
__ movsd(input_reg, Operand(esp, 0));
|
||||
__ add(Operand(esp), Immediate(kDoubleSize));
|
||||
__ bind(&done);
|
||||
__ movsd(result, Operand(esp, 0));
|
||||
__ add(esp, Immediate(kDoubleSize));
|
||||
}
|
||||
|
||||
|
||||
|
@ -3509,8 +3509,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
__ PrepareCallCFunction(0, 1, scratch0());
|
||||
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
|
||||
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
|
||||
}
|
||||
|
||||
|
@ -3712,8 +3712,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
__ PrepareCallCFunction(0, 1, scratch0());
|
||||
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
|
||||
0, 1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
|
||||
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
|
||||
}
|
||||
|
||||
|
@ -3791,8 +3791,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
__ PrepareCallCFunction(0, 1, scratch0());
|
||||
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
|
||||
1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
|
||||
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
|
||||
}
|
||||
|
||||
|
@ -3685,8 +3685,7 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
__ PrepareCallCFunction(0, 1, scratch0());
|
||||
__ MovToFloatParameter(ToDoubleRegister(instr->value()));
|
||||
__ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
|
||||
1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
|
||||
__ MovFromFloatResult(ToDoubleRegister(instr->result()));
|
||||
}
|
||||
|
||||
|
@ -3612,32 +3612,10 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoMathLog(LMathLog* instr) {
|
||||
DCHECK(instr->value()->Equals(instr->result()));
|
||||
XMMRegister input_reg = ToDoubleRegister(instr->value());
|
||||
XMMRegister xmm_scratch = double_scratch0();
|
||||
Label positive, done, zero;
|
||||
__ Xorpd(xmm_scratch, xmm_scratch);
|
||||
__ Ucomisd(input_reg, xmm_scratch);
|
||||
__ j(above, &positive, Label::kNear);
|
||||
__ j(not_carry, &zero, Label::kNear);
|
||||
__ Pcmpeqd(input_reg, input_reg);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&zero);
|
||||
ExternalReference ninf =
|
||||
ExternalReference::address_of_negative_infinity();
|
||||
Operand ninf_operand = masm()->ExternalOperand(ninf);
|
||||
__ Movsd(input_reg, ninf_operand);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&positive);
|
||||
__ fldln2();
|
||||
__ subp(rsp, Immediate(kDoubleSize));
|
||||
__ Movsd(Operand(rsp, 0), input_reg);
|
||||
__ fld_d(Operand(rsp, 0));
|
||||
__ fyl2x();
|
||||
__ fstp_d(Operand(rsp, 0));
|
||||
__ Movsd(input_reg, Operand(rsp, 0));
|
||||
__ addp(rsp, Immediate(kDoubleSize));
|
||||
__ bind(&done);
|
||||
DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
|
||||
DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
|
||||
__ PrepareCallCFunction(1);
|
||||
__ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1155,8 +1155,9 @@ LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
|
||||
LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
|
||||
DCHECK(instr->representation().IsDouble());
|
||||
DCHECK(instr->value()->representation().IsDouble());
|
||||
LOperand* input = UseRegisterAtStart(instr->value());
|
||||
return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
|
||||
LOperand* input = UseFixedDouble(instr->value(), xmm0);
|
||||
return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), xmm0),
|
||||
instr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,8 +67,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
"power_double_double_function");
|
||||
Add(ExternalReference::power_double_int_function(isolate).address(),
|
||||
"power_double_int_function");
|
||||
Add(ExternalReference::math_log_double_function(isolate).address(),
|
||||
"std::log");
|
||||
Add(ExternalReference::ieee754_log_function(isolate).address(),
|
||||
"base::ieee754::log");
|
||||
Add(ExternalReference::store_buffer_top(isolate).address(),
|
||||
"store_buffer_top");
|
||||
Add(ExternalReference::address_of_the_hole_nan().address(), "the_hole_nan");
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include "src/api.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "src/frames-inl.h"
|
||||
#include "src/heap/heap.h"
|
||||
@ -27,7 +28,7 @@ intptr_t SamplingAllocationObserver::GetNextSampleInterval(uint64_t rate) {
|
||||
return static_cast<intptr_t>(rate);
|
||||
}
|
||||
double u = random_->NextDouble();
|
||||
double next = (-std::log(u)) * rate;
|
||||
double next = (-base::ieee754::log(u)) * rate;
|
||||
return next < kPointerSize
|
||||
? kPointerSize
|
||||
: (next > INT_MAX ? INT_MAX : static_cast<intptr_t>(next));
|
||||
|
@ -1680,6 +1680,8 @@
|
||||
'base/functional.cc',
|
||||
'base/functional.h',
|
||||
'base/hashmap.h',
|
||||
'base/ieee754.cc',
|
||||
'base/ieee754.h',
|
||||
'base/iterator.h',
|
||||
'base/lazy-instance.h',
|
||||
'base/logging.cc',
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <limits>
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "src/codegen.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
@ -5507,7 +5508,7 @@ TEST(RunFloat64Log) {
|
||||
CHECK_DOUBLE_EQ(0.0, m.Call(1.0));
|
||||
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
||||
m.Call(std::numeric_limits<double>::infinity()));
|
||||
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(std::log(*i), m.Call(*i)); }
|
||||
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::log(*i), m.Call(*i)); }
|
||||
}
|
||||
|
||||
static double two_30 = 1 << 30; // 2^30 is a smi boundary.
|
||||
|
@ -111,6 +111,7 @@ class ValueHelper {
|
||||
-4.30175e-14f,
|
||||
-5.27385e-15f,
|
||||
-1.48084e-15f,
|
||||
-2.220446049250313e-16f,
|
||||
-1.05755e-19f,
|
||||
-3.2995e-21f,
|
||||
-1.67354e-23f,
|
||||
@ -177,6 +178,7 @@ class ValueHelper {
|
||||
static std::vector<double> float64_vector() {
|
||||
static const double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
static const double values[] = {-2e66,
|
||||
-2.220446049250313e-16,
|
||||
-9223373136366403584.0,
|
||||
-9223372036854775808.0, // INT64_MIN
|
||||
-2147483649.5,
|
||||
|
@ -2,10 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/machine-operator-reducer.h"
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/division-by-constant.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/machine-operator-reducer.h"
|
||||
#include "src/compiler/typer.h"
|
||||
#include "src/conversions-inl.h"
|
||||
#include "test/unittests/compiler/graph-unittest.h"
|
||||
@ -1408,7 +1409,7 @@ TEST_F(MachineOperatorReducerTest, Float64LogWithConstant) {
|
||||
Reduce(graph()->NewNode(machine()->Float64Log(), Float64Constant(x)));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsFloat64Constant(NanSensitiveDoubleEq(std::log(x))));
|
||||
IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log(x))));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user