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) ...@@ -100,38 +100,6 @@ JSBuiltinReducer::JSBuiltinReducer(JSGraph* jsgraph)
: jsgraph_(jsgraph), simplified_(jsgraph->zone()) {} : 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. // ECMA-262, section 15.8.2.11.
Reduction JSBuiltinReducer::ReduceMathMax(Node* node) { Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
JSCallReduction r(node); JSCallReduction r(node);
...@@ -190,10 +158,6 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { ...@@ -190,10 +158,6 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
// Dispatch according to the BuiltinFunctionId if present. // Dispatch according to the BuiltinFunctionId if present.
if (!r.HasBuiltinFunctionId()) return NoChange(); if (!r.HasBuiltinFunctionId()) return NoChange();
switch (r.GetBuiltinFunctionId()) { switch (r.GetBuiltinFunctionId()) {
case kMathAbs:
return ReplaceWithPureReduction(node, ReduceMathAbs(node));
case kMathSqrt:
return ReplaceWithPureReduction(node, ReduceMathSqrt(node));
case kMathMax: case kMathMax:
return ReplaceWithPureReduction(node, ReduceMathMax(node)); return ReplaceWithPureReduction(node, ReduceMathMax(node));
case kMathImul: case kMathImul:
......
...@@ -26,8 +26,6 @@ class JSBuiltinReducer FINAL : public Reducer { ...@@ -26,8 +26,6 @@ class JSBuiltinReducer FINAL : public Reducer {
Reduction Reduce(Node* node) FINAL; Reduction Reduce(Node* node) FINAL;
private: private:
Reduction ReduceMathAbs(Node* node);
Reduction ReduceMathSqrt(Node* node);
Reduction ReduceMathMax(Node* node); Reduction ReduceMathMax(Node* node);
Reduction ReduceMathImul(Node* node); Reduction ReduceMathImul(Node* node);
Reduction ReduceMathFround(Node* node); Reduction ReduceMathFround(Node* node);
......
...@@ -42,6 +42,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) { ...@@ -42,6 +42,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceInlineIsInstanceType(node, JS_REGEXP_TYPE); return ReduceInlineIsInstanceType(node, JS_REGEXP_TYPE);
case Runtime::kInlineMathFloor: case Runtime::kInlineMathFloor:
return ReduceInlineMathFloor(node); return ReduceInlineMathFloor(node);
case Runtime::kInlineMathSqrt:
return ReduceInlineMathSqrt(node);
case Runtime::kInlineValueOf: case Runtime::kInlineValueOf:
return ReduceInlineValueOf(node); return ReduceInlineValueOf(node);
default: default:
...@@ -170,6 +172,11 @@ Reduction JSIntrinsicLowering::ReduceInlineMathFloor(Node* node) { ...@@ -170,6 +172,11 @@ Reduction JSIntrinsicLowering::ReduceInlineMathFloor(Node* node) {
} }
Reduction JSIntrinsicLowering::ReduceInlineMathSqrt(Node* node) {
return Change(node, machine()->Float64Sqrt());
}
Reduction JSIntrinsicLowering::ReduceInlineValueOf(Node* node) { Reduction JSIntrinsicLowering::ReduceInlineValueOf(Node* node) {
// if (%_IsSmi(value)) { // if (%_IsSmi(value)) {
// return value; // return value;
......
...@@ -35,6 +35,7 @@ class JSIntrinsicLowering FINAL : public Reducer { ...@@ -35,6 +35,7 @@ class JSIntrinsicLowering FINAL : public Reducer {
Reduction ReduceInlineDoubleLo(Node* node); Reduction ReduceInlineDoubleLo(Node* node);
Reduction ReduceInlineDoubleHi(Node* node); Reduction ReduceInlineDoubleHi(Node* node);
Reduction ReduceInlineMathFloor(Node* node); Reduction ReduceInlineMathFloor(Node* node);
Reduction ReduceInlineMathSqrt(Node* node);
Reduction ReduceInlineValueOf(Node* node); Reduction ReduceInlineValueOf(Node* node);
Reduction Change(Node* node, const Operator* op); Reduction Change(Node* node, const Operator* op);
......
...@@ -1511,6 +1511,7 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { ...@@ -1511,6 +1511,7 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
return Bounds(Type::None(zone()), Type::Signed32()); return Bounds(Type::None(zone()), Type::Signed32());
case Runtime::kInlineConstructDouble: case Runtime::kInlineConstructDouble:
case Runtime::kInlineMathFloor: case Runtime::kInlineMathFloor:
case Runtime::kInlineMathSqrt:
return Bounds(Type::None(zone()), Type::Number()); return Bounds(Type::None(zone()), Type::Number());
default: default:
break; break;
......
...@@ -12012,7 +12012,7 @@ void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) { ...@@ -12012,7 +12012,7 @@ void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
} }
void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1); DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop(); HValue* value = Pop();
......
...@@ -2213,7 +2213,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2213,7 +2213,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
F(DoubleHi) \ F(DoubleHi) \
F(DoubleLo) \ F(DoubleLo) \
F(MathFloor) \ F(MathFloor) \
F(MathSqrtRT) \ F(MathSqrt) \
F(MathLogRT) \ F(MathLogRT) \
/* ES6 Collections */ \ /* ES6 Collections */ \
F(MapClear) \ F(MapClear) \
......
...@@ -23,10 +23,9 @@ var GlobalArray = global.Array; ...@@ -23,10 +23,9 @@ var GlobalArray = global.Array;
// ECMA 262 - 15.8.2.1 // ECMA 262 - 15.8.2.1
function MathAbs(x) { function MathAbs(x) {
if (%_IsSmi(x)) return x >= 0 ? x : -x; x = +x;
x = TO_NUMBER_INLINE(x); if (x > 0) return x;
if (x === 0) return 0; // To handle -0. return 0 - x;
return x > 0 ? x : -x;
} }
// ECMA 262 - 15.8.2.2 // ECMA 262 - 15.8.2.2
...@@ -148,7 +147,7 @@ function MathRound(x) { ...@@ -148,7 +147,7 @@ function MathRound(x) {
// ECMA 262 - 15.8.2.17 // ECMA 262 - 15.8.2.17
function MathSqrt(x) { function MathSqrt(x) {
return %_MathSqrtRT(TO_NUMBER_INLINE(x)); return %_MathSqrt(+x);
} }
// Non-standard extension. // Non-standard extension.
...@@ -191,9 +190,9 @@ function MathAsinh(x) { ...@@ -191,9 +190,9 @@ function MathAsinh(x) {
if (!IS_NUMBER(x)) x = NonNumberToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
// Idempotent for NaN, +/-0 and +/-Infinity. // Idempotent for NaN, +/-0 and +/-Infinity.
if (x === 0 || !NUMBER_IS_FINITE(x)) return x; 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. // 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. // ES6 draft 09-27-13, section 20.2.2.3.
...@@ -202,7 +201,7 @@ function MathAcosh(x) { ...@@ -202,7 +201,7 @@ function MathAcosh(x) {
if (x < 1) return NAN; if (x < 1) return NAN;
// Idempotent for NaN and +Infinity. // Idempotent for NaN and +Infinity.
if (!NUMBER_IS_FINITE(x)) return x; 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. // ES6 draft 09-27-13, section 20.2.2.7.
...@@ -244,7 +243,7 @@ function MathHypot(x, y) { // Function length is 2. ...@@ -244,7 +243,7 @@ function MathHypot(x, y) { // Function length is 2.
compensation = (preliminary - sum) - summand; compensation = (preliminary - sum) - summand;
sum = preliminary; sum = preliminary;
} }
return MathSqrt(sum) * max; return %_MathSqrt(sum) * max;
} }
// ES6 draft 09-27-13, section 20.2.2.16. // ES6 draft 09-27-13, section 20.2.2.16.
...@@ -350,9 +349,11 @@ InstallFunctions(Math, DONT_ENUM, GlobalArray( ...@@ -350,9 +349,11 @@ InstallFunctions(Math, DONT_ENUM, GlobalArray(
"cbrt", MathCbrt "cbrt", MathCbrt
)); ));
%SetInlineBuiltinFlag(MathAbs);
%SetInlineBuiltinFlag(MathCeil); %SetInlineBuiltinFlag(MathCeil);
%SetInlineBuiltinFlag(MathFloor); %SetInlineBuiltinFlag(MathFloor);
%SetInlineBuiltinFlag(MathRandom); %SetInlineBuiltinFlag(MathRandom);
%SetInlineBuiltinFlag(MathSqrt);
// Expose to the global scope. // Expose to the global scope.
$abs = MathAbs; $abs = MathAbs;
......
...@@ -207,7 +207,7 @@ RUNTIME_FUNCTION(Runtime_RoundNumber) { ...@@ -207,7 +207,7 @@ RUNTIME_FUNCTION(Runtime_RoundNumber) {
} }
RUNTIME_FUNCTION(Runtime_MathSqrtRT) { RUNTIME_FUNCTION(Runtime_MathSqrt) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
isolate->counters()->math_sqrt()->Increment(); isolate->counters()->math_sqrt()->Increment();
......
...@@ -694,7 +694,7 @@ namespace internal { ...@@ -694,7 +694,7 @@ namespace internal {
F(DoubleHi, 1, 1) \ F(DoubleHi, 1, 1) \
F(DoubleLo, 1, 1) \ F(DoubleLo, 1, 1) \
F(MathFloor, 1, 1) \ F(MathFloor, 1, 1) \
F(MathSqrtRT, 1, 1) \ F(MathSqrt, 1, 1) \
F(MathLogRT, 1, 1) \ F(MathLogRT, 1, 1) \
/* ES6 Collections */ \ /* ES6 Collections */ \
F(MapClear, 1, 1) \ F(MapClear, 1, 1) \
......
...@@ -4104,7 +4104,7 @@ void LCodeGen::DoMathSqrt(LMathSqrt* instr) { ...@@ -4104,7 +4104,7 @@ void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ push(temp_result); __ push(temp_result);
__ CallRuntimeSaveDoubles(Runtime::kMathSqrtRT); __ CallRuntimeSaveDoubles(Runtime::kMathSqrt);
RecordSafepointWithRegisters(instr->pointer_map(), 1, RecordSafepointWithRegisters(instr->pointer_map(), 1,
Safepoint::kNoLazyDeopt); Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(temp_result, eax); __ StoreToSafepointRegisterSlot(temp_result, eax);
......
...@@ -61,58 +61,6 @@ Type* const kNumberTypes[] = { ...@@ -61,58 +61,6 @@ Type* const kNumberTypes[] = {
} // namespace } // 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 // 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