From 83f157bc18cd9e23f88e045351665c70f283c6ad Mon Sep 17 00:00:00 2001 From: bmeurer Date: Fri, 13 Mar 2015 00:06:02 -0700 Subject: [PATCH] [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} --- src/compiler/js-builtin-reducer.cc | 36 --------------- src/compiler/js-builtin-reducer.h | 2 - src/compiler/js-intrinsic-lowering.cc | 7 +++ src/compiler/js-intrinsic-lowering.h | 1 + src/compiler/typer.cc | 1 + src/hydrogen.cc | 2 +- src/hydrogen.h | 2 +- src/math.js | 19 ++++---- src/runtime/runtime-maths.cc | 2 +- src/runtime/runtime.h | 2 +- src/x87/lithium-codegen-x87.cc | 2 +- .../compiler/js-builtin-reducer-unittest.cc | 52 ---------------------- 12 files changed, 24 insertions(+), 104 deletions(-) diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc index e2d12f0..2a032db 100644 --- a/src/compiler/js-builtin-reducer.cc +++ b/src/compiler/js-builtin-reducer.cc @@ -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: diff --git a/src/compiler/js-builtin-reducer.h b/src/compiler/js-builtin-reducer.h index 60b9e14..42221e9 100644 --- a/src/compiler/js-builtin-reducer.h +++ b/src/compiler/js-builtin-reducer.h @@ -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); diff --git a/src/compiler/js-intrinsic-lowering.cc b/src/compiler/js-intrinsic-lowering.cc index 317421f..ebe2e4e 100644 --- a/src/compiler/js-intrinsic-lowering.cc +++ b/src/compiler/js-intrinsic-lowering.cc @@ -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; diff --git a/src/compiler/js-intrinsic-lowering.h b/src/compiler/js-intrinsic-lowering.h index 493e962..3a910fd 100644 --- a/src/compiler/js-intrinsic-lowering.h +++ b/src/compiler/js-intrinsic-lowering.h @@ -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); diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 3f9b105..f3fdaad 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -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; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 810d3ff..5c6b5cd 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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(); diff --git a/src/hydrogen.h b/src/hydrogen.h index 2e7a5dd..c454a28 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -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) \ diff --git a/src/math.js b/src/math.js index d7e5f94..ed9bdbd 100644 --- a/src/math.js +++ b/src/math.js @@ -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; diff --git a/src/runtime/runtime-maths.cc b/src/runtime/runtime-maths.cc index 807791b..a4435e0 100644 --- a/src/runtime/runtime-maths.cc +++ b/src/runtime/runtime-maths.cc @@ -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(); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index ce76c6d..d820490 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -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) \ diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc index 8fd8f5b..25c8e35 100644 --- a/src/x87/lithium-codegen-x87.cc +++ b/src/x87/lithium-codegen-x87.cc @@ -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); diff --git a/test/unittests/compiler/js-builtin-reducer-unittest.cc b/test/unittests/compiler/js-builtin-reducer-unittest.cc index ee9f960..c98bc6c 100644 --- a/test/unittests/compiler/js-builtin-reducer-unittest.cc +++ b/test/unittests/compiler/js-builtin-reducer-unittest.cc @@ -62,58 +62,6 @@ Type* const kNumberTypes[] = { // ----------------------------------------------------------------------------- -// Math.abs - - -TEST_F(JSBuiltinReducerTest, MathAbs) { - Handle f = MathFunction("abs"); - - TRACED_FOREACH(Type*, t0, kNumberTypes) { - Node* p0 = Parameter(t0, 0); - Node* fun = HeapConstant(Unique::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 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 f = MathFunction("sqrt"); - - TRACED_FOREACH(Type*, t0, kNumberTypes) { - Node* p0 = Parameter(t0, 0); - Node* fun = HeapConstant(Unique::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 -- 2.7.4