Commit 83f157bc authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Use builtin inlining mechanism for Math.abs and Math.sqrt.

Reduces the amount of custom support code for Math functions in TurboFan
and allows for more general inlining (i.e. independent of parameter
types).

BUG=v8:3952
LOG=n
R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/1004083002

Cr-Commit-Position: refs/heads/master@{#27172}
parent 0c305e0b
......@@ -100,38 +100,6 @@ JSBuiltinReducer::JSBuiltinReducer(JSGraph* jsgraph)
: jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
// ECMA-262, section 15.8.2.1.
Reduction JSBuiltinReducer::ReduceMathAbs(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::Unsigned32())) {
// Math.abs(a:uint32) -> a
return Replace(r.left());
}
if (r.InputsMatchOne(Type::Number())) {
// Math.abs(a:number) -> (a > 0 ? a : 0 - a)
Node* const value = r.left();
Node* const zero = jsgraph()->ZeroConstant();
return Replace(graph()->NewNode(
common()->Select(kMachNone),
graph()->NewNode(simplified()->NumberLessThan(), zero, value), value,
graph()->NewNode(simplified()->NumberSubtract(), zero, value)));
}
return NoChange();
}
// ECMA-262, section 15.8.2.17.
Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
JSCallReduction r(node);
if (r.InputsMatchOne(Type::Number())) {
// Math.sqrt(a:number) -> Float64Sqrt(a)
Node* value = graph()->NewNode(machine()->Float64Sqrt(), r.left());
return Replace(value);
}
return NoChange();
}
// ECMA-262, section 15.8.2.11.
Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
JSCallReduction r(node);
......@@ -190,10 +158,6 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
// Dispatch according to the BuiltinFunctionId if present.
if (!r.HasBuiltinFunctionId()) return NoChange();
switch (r.GetBuiltinFunctionId()) {
case kMathAbs:
return ReplaceWithPureReduction(node, ReduceMathAbs(node));
case kMathSqrt:
return ReplaceWithPureReduction(node, ReduceMathSqrt(node));
case kMathMax:
return ReplaceWithPureReduction(node, ReduceMathMax(node));
case kMathImul:
......
......@@ -26,8 +26,6 @@ class JSBuiltinReducer FINAL : public Reducer {
Reduction Reduce(Node* node) FINAL;
private:
Reduction ReduceMathAbs(Node* node);
Reduction ReduceMathSqrt(Node* node);
Reduction ReduceMathMax(Node* node);
Reduction ReduceMathImul(Node* node);
Reduction ReduceMathFround(Node* node);
......
......@@ -42,6 +42,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceInlineIsInstanceType(node, JS_REGEXP_TYPE);
case Runtime::kInlineMathFloor:
return ReduceInlineMathFloor(node);
case Runtime::kInlineMathSqrt:
return ReduceInlineMathSqrt(node);
case Runtime::kInlineValueOf:
return ReduceInlineValueOf(node);
default:
......@@ -170,6 +172,11 @@ Reduction JSIntrinsicLowering::ReduceInlineMathFloor(Node* node) {
}
Reduction JSIntrinsicLowering::ReduceInlineMathSqrt(Node* node) {
return Change(node, machine()->Float64Sqrt());
}
Reduction JSIntrinsicLowering::ReduceInlineValueOf(Node* node) {
// if (%_IsSmi(value)) {
// return value;
......
......@@ -35,6 +35,7 @@ class JSIntrinsicLowering FINAL : public Reducer {
Reduction ReduceInlineDoubleLo(Node* node);
Reduction ReduceInlineDoubleHi(Node* node);
Reduction ReduceInlineMathFloor(Node* node);
Reduction ReduceInlineMathSqrt(Node* node);
Reduction ReduceInlineValueOf(Node* node);
Reduction Change(Node* node, const Operator* op);
......
......@@ -1511,6 +1511,7 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
return Bounds(Type::None(zone()), Type::Signed32());
case Runtime::kInlineConstructDouble:
case Runtime::kInlineMathFloor:
case Runtime::kInlineMathSqrt:
return Bounds(Type::None(zone()), Type::Number());
default:
break;
......
......@@ -12012,7 +12012,7 @@ void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
}
void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop();
......
......@@ -2213,7 +2213,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
F(DoubleHi) \
F(DoubleLo) \
F(MathFloor) \
F(MathSqrtRT) \
F(MathSqrt) \
F(MathLogRT) \
/* ES6 Collections */ \
F(MapClear) \
......
......@@ -23,10 +23,9 @@ var GlobalArray = global.Array;
// ECMA 262 - 15.8.2.1
function MathAbs(x) {
if (%_IsSmi(x)) return x >= 0 ? x : -x;
x = TO_NUMBER_INLINE(x);
if (x === 0) return 0; // To handle -0.
return x > 0 ? x : -x;
x = +x;
if (x > 0) return x;
return 0 - x;
}
// ECMA 262 - 15.8.2.2
......@@ -148,7 +147,7 @@ function MathRound(x) {
// ECMA 262 - 15.8.2.17
function MathSqrt(x) {
return %_MathSqrtRT(TO_NUMBER_INLINE(x));
return %_MathSqrt(+x);
}
// Non-standard extension.
......@@ -191,9 +190,9 @@ function MathAsinh(x) {
if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
// Idempotent for NaN, +/-0 and +/-Infinity.
if (x === 0 || !NUMBER_IS_FINITE(x)) return x;
if (x > 0) return MathLog(x + MathSqrt(x * x + 1));
if (x > 0) return MathLog(x + %_MathSqrt(x * x + 1));
// This is to prevent numerical errors caused by large negative x.
return -MathLog(-x + MathSqrt(x * x + 1));
return -MathLog(-x + %_MathSqrt(x * x + 1));
}
// ES6 draft 09-27-13, section 20.2.2.3.
......@@ -202,7 +201,7 @@ function MathAcosh(x) {
if (x < 1) return NAN;
// Idempotent for NaN and +Infinity.
if (!NUMBER_IS_FINITE(x)) return x;
return MathLog(x + MathSqrt(x + 1) * MathSqrt(x - 1));
return MathLog(x + %_MathSqrt(x + 1) * %_MathSqrt(x - 1));
}
// ES6 draft 09-27-13, section 20.2.2.7.
......@@ -244,7 +243,7 @@ function MathHypot(x, y) { // Function length is 2.
compensation = (preliminary - sum) - summand;
sum = preliminary;
}
return MathSqrt(sum) * max;
return %_MathSqrt(sum) * max;
}
// ES6 draft 09-27-13, section 20.2.2.16.
......@@ -350,9 +349,11 @@ InstallFunctions(Math, DONT_ENUM, GlobalArray(
"cbrt", MathCbrt
));
%SetInlineBuiltinFlag(MathAbs);
%SetInlineBuiltinFlag(MathCeil);
%SetInlineBuiltinFlag(MathFloor);
%SetInlineBuiltinFlag(MathRandom);
%SetInlineBuiltinFlag(MathSqrt);
// Expose to the global scope.
$abs = MathAbs;
......
......@@ -207,7 +207,7 @@ RUNTIME_FUNCTION(Runtime_RoundNumber) {
}
RUNTIME_FUNCTION(Runtime_MathSqrtRT) {
RUNTIME_FUNCTION(Runtime_MathSqrt) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
isolate->counters()->math_sqrt()->Increment();
......
......@@ -694,7 +694,7 @@ namespace internal {
F(DoubleHi, 1, 1) \
F(DoubleLo, 1, 1) \
F(MathFloor, 1, 1) \
F(MathSqrtRT, 1, 1) \
F(MathSqrt, 1, 1) \
F(MathLogRT, 1, 1) \
/* ES6 Collections */ \
F(MapClear, 1, 1) \
......
......@@ -4104,7 +4104,7 @@ void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ push(temp_result);
__ CallRuntimeSaveDoubles(Runtime::kMathSqrtRT);
__ CallRuntimeSaveDoubles(Runtime::kMathSqrt);
RecordSafepointWithRegisters(instr->pointer_map(), 1,
Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(temp_result, eax);
......
......@@ -61,58 +61,6 @@ Type* const kNumberTypes[] = {
} // namespace
// -----------------------------------------------------------------------------
// Math.abs
TEST_F(JSBuiltinReducerTest, MathAbs) {
Handle<JSFunction> f = MathFunction("abs");
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call =
graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant(), p0);
Reduction r = Reduce(call);
if (t0->Is(Type::Unsigned32())) {
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), p0);
} else {
Capture<Node*> branch;
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsSelect(kMachNone,
IsNumberLessThan(IsNumberConstant(BitEq(0.0)), p0), p0,
IsNumberSubtract(IsNumberConstant(BitEq(0.0)), p0)));
}
}
}
// -----------------------------------------------------------------------------
// Math.sqrt
TEST_F(JSBuiltinReducerTest, MathSqrt) {
Handle<JSFunction> f = MathFunction("sqrt");
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call =
graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant(), p0);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Sqrt(p0));
}
}
// -----------------------------------------------------------------------------
// Math.max
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment