Ignore:
Timestamp:
May 4, 2017, 4:40:46 AM (8 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Math unary functions should be handled by DFG
https://bugs.webkit.org/show_bug.cgi?id=171269

Reviewed by Saam Barati.

JSTests:

  • stress/arith-acos-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueACosNoArgument):
(testNoArgument):
(opaqueAllTypesACos):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueACosForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueACosForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueACosForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueACosWithException):
(testException):

  • stress/arith-acosh-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueACoshNoArgument):
(testNoArgument):
(opaqueAllTypesACosh):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueACoshForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueACoshForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueACoshForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueACoshWithException):
(testException):

  • stress/arith-asin-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueASinNoArgument):
(testNoArgument):
(opaqueAllTypesASin):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueASinForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueASinForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueASinForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueASinWithException):
(testException):

  • stress/arith-asinh-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueASinhNoArgument):
(testNoArgument):
(opaqueAllTypesASinh):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueASinhForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueASinhForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueASinhForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueASinhWithException):
(testException):

  • stress/arith-atan-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueATanNoArgument):
(testNoArgument):
(opaqueAllTypesATan):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueATanForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueATanForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueATanForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueATanWithException):
(testException):

  • stress/arith-atanh-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueATanhNoArgument):
(testNoArgument):
(opaqueAllTypesATanh):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueATanhForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueATanhForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueATanhForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueATanhWithException):
(testException):

  • stress/arith-cbrt-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueCbrtNoArgument):
(testNoArgument):
(opaqueAllTypesCbrt):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueCbrtForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueCbrtForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueCbrtForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueCbrtWithException):
(testException):

  • stress/arith-cosh-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueCoshNoArgument):
(testNoArgument):
(opaqueAllTypesCosh):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueCoshForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueCoshForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueCoshForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueCoshWithException):
(testException):

  • stress/arith-expm1-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueExpm1NoArgument):
(testNoArgument):
(opaqueAllTypesExpm1):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueExpm1ForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueExpm1ForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueExpm1ForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueExpm1WithException):
(testException):

  • stress/arith-log10-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueLog10NoArgument):
(testNoArgument):
(opaqueAllTypesLog10):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueLog10ForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueLog10ForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueLog10ForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueLog10WithException):
(testException):

  • stress/arith-log2-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueLog2NoArgument):
(testNoArgument):
(opaqueAllTypesLog2):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueLog2ForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueLog2ForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueLog2ForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueLog2WithException):
(testException):

  • stress/arith-sinh-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueSinhNoArgument):
(testNoArgument):
(opaqueAllTypesSinh):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueSinhForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueSinhForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueSinhForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueSinhWithException):
(testException):

  • stress/arith-tan-on-various-types.js:

(isIdentical):

  • stress/arith-tanh-on-various-types.js: Added.

(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueTanhNoArgument):
(testNoArgument):
(opaqueAllTypesTanh):
(testAllTypesCall):
(testSingleTypeCall):
(testConstant):
(opaqueTanhForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueTanhForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueTanhForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueTanhWithException):
(testException):

Source/JavaScriptCore:

ArithSin, ArithCos, and ArithLog are just calling a C runtime function.
While handling them in DFG is not very effective for performance, they
can drop some type checks & value conversions and mark them as pure
operations. It is effective if they are involved in some complex
optimization phase. Actually, ArithLog is effective in kraken.

While a few of Math functions have DFG nodes, basically math functions
are pure. And large part of these functions are just calling a C runtime
function. This patch generalizes these nodes in DFG as ArithUnary. And
we annotate many unary math functions with Intrinsics and convert them
to ArithUnary in DFG. It also cleans up duplicate code in ArithSin,
ArithCos, and ArithLog. If your math function has some good DFG / FTL
optimization rather than calling a C runtime function, you should add
a specialized DFG node, like ArithSqrt.

We also create a new namespace JSC::Math. Inside it, we collect math functions.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGArithMode.cpp:

(JSC::DFG::arithUnaryFunction):
(JSC::DFG::arithUnaryOperation):
(WTF::printInternal):

  • dfg/DFGArithMode.h:
  • dfg/DFGBackwardsPropagationPhase.cpp:

(JSC::DFG::BackwardsPropagationPhase::propagate):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasArithUnaryType):
(JSC::DFG::Node::arithUnaryType):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileArithUnary):
(JSC::DFG::SpeculativeJIT::compileArithCos): Deleted.
(JSC::DFG::SpeculativeJIT::compileArithTan): Deleted.
(JSC::DFG::SpeculativeJIT::compileArithSin): Deleted.
(JSC::DFG::SpeculativeJIT::compileArithLog): Deleted.

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileArithUnary):
(JSC::FTL::DFG::LowerDFGToB3::compileArithSin): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::compileArithCos): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::compileArithTan): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::compileArithLog): Deleted.

  • ftl/FTLOutput.cpp:

(JSC::FTL::Output::doubleUnary):
(JSC::FTL::Output::doubleSin): Deleted.
(JSC::FTL::Output::doubleCos): Deleted.
(JSC::FTL::Output::doubleTan): Deleted.
(JSC::FTL::Output::doubleLog): Deleted.

  • ftl/FTLOutput.h:
  • runtime/Intrinsic.h:
  • runtime/MathCommon.cpp:

(JSC::Math::log1p):

  • runtime/MathCommon.h:
  • runtime/MathObject.cpp:

(JSC::MathObject::finishCreation):
(JSC::mathProtoFuncACos):
(JSC::mathProtoFuncASin):
(JSC::mathProtoFuncATan):
(JSC::mathProtoFuncCos):
(JSC::mathProtoFuncExp):
(JSC::mathProtoFuncLog):
(JSC::mathProtoFuncSin):
(JSC::mathProtoFuncTan):
(JSC::mathProtoFuncACosh):
(JSC::mathProtoFuncASinh):
(JSC::mathProtoFuncATanh):
(JSC::mathProtoFuncCbrt):
(JSC::mathProtoFuncCosh):
(JSC::mathProtoFuncExpm1):
(JSC::mathProtoFuncLog1p):
(JSC::mathProtoFuncLog10):
(JSC::mathProtoFuncLog2):
(JSC::mathProtoFuncSinh):
(JSC::mathProtoFuncTanh):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp

    r215565 r216178  
    290290}
    291291
    292 LValue Output::doubleSin(LValue value)
    293 {
    294     double (*sinDouble)(double) = sin;
    295     return callWithoutSideEffects(B3::Double, sinDouble, value);
    296 }
    297 
    298 LValue Output::doubleCos(LValue value)
    299 {
    300     double (*cosDouble)(double) = cos;
    301     return callWithoutSideEffects(B3::Double, cosDouble, value);
    302 }
    303 
    304 LValue Output::doubleTan(LValue value)
    305 {
    306     double (*tanDouble)(double) = tan;
    307     return callWithoutSideEffects(B3::Double, tanDouble, value);
     292LValue Output::doubleUnary(DFG::Arith::UnaryType type, LValue value)
     293{
     294    double (*unaryFunction)(double) = DFG::arithUnaryFunction(type);
     295    return callWithoutSideEffects(B3::Double, unaryFunction, value);
    308296}
    309297
     
    327315{
    328316    return m_block->appendNew<B3::Value>(m_proc, B3::Sqrt, origin(), value);
    329 }
    330 
    331 LValue Output::doubleLog(LValue value)
    332 {
    333     double (*logDouble)(double) = log;
    334     return callWithoutSideEffects(B3::Double, logDouble, value);
    335317}
    336318
Note: See TracChangeset for help on using the changeset viewer.