Ignore:
Timestamp:
Apr 21, 2016, 9:46:53 PM (9 years ago)
Author:
[email protected]
Message:

[JSC] Commute FDiv-by-constant into FMul-by-reciprocal when it is safe
https://bugs.webkit.org/show_bug.cgi?id=156871

Patch by Benjamin Poulain <[email protected]> on 2016-04-21
Reviewed by Filip Pizlo.

FMul is significantly faster than FDiv.
For example, on Haswell, FMul has a latency of 5, a throughput of 1
while FDiv has latency 10-24, throughput 8-18.

Fortunately for us, Sunspider and Kraken have plenty of division
by a simple power of 2 constant. Those are just exponent operations
and can be easily reversed to use FMul instead of FDiv.

LLVM does something similar in InstCombine.

  • dfg/DFGStrengthReductionPhase.cpp:

(JSC::DFG::StrengthReductionPhase::handleNode):

  • jit/JITDivGenerator.cpp:

(JSC::JITDivGenerator::loadOperand):
(JSC::JITDivGenerator::generateFastPath):

  • jit/SnippetOperand.h:

(JSC::SnippetOperand::asConstNumber):

  • runtime/MathCommon.h:

(JSC::safeReciprocalForDivByConst):

  • tests/stress/floating-point-div-to-mul.js: Added.

(opaqueDivBy2):
(opaqueDivBy3):
(opaqueDivBy4):
(opaqueDivBySafeMaxMinusOne):
(opaqueDivBySafeMax):
(opaqueDivBySafeMaxPlusOne):
(opaqueDivBySafeMin):
(opaqueDivBySafeMinMinusOne):
(i.catch):
(i.result.opaqueDivBySafeMin.valueOf):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/MathCommon.h

    r187819 r199866  
    11/*
    2  * Copyright (C) 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828
    2929#include "JITOperations.h"
     30#include <wtf/Optional.h>
    3031
    3132#ifndef JIT_OPERATION
     
    5556}
    5657
     58inline Optional<double> safeReciprocalForDivByConst(double constant)
     59{
     60    // No "weird" numbers (NaN, Denormal, etc).
     61    if (!constant || !isnormal(constant))
     62        return Nullopt;
     63
     64    int exponent;
     65    if (frexp(constant, &exponent) != 0.5)
     66        return Nullopt;
     67
     68    // Note that frexp() returns the value divided by two
     69    // so we to offset this exponent by one.
     70    exponent -= 1;
     71
     72    // A double exponent is between -1022 and 1023.
     73    // Nothing we can do to invert 1023.
     74    if (exponent == 1023)
     75        return Nullopt;
     76
     77    double reciprocal = ldexp(1, -exponent);
     78    ASSERT(isnormal(reciprocal));
     79    ASSERT(1. / constant == reciprocal);
     80    ASSERT(constant == 1. / reciprocal);
     81    ASSERT(1. == constant * reciprocal);
     82
     83    return reciprocal;
     84}
     85
    5786extern "C" {
    5887double JIT_OPERATION jsRound(double value) REFERENCED_FROM_ASM WTF_INTERNAL;
Note: See TracChangeset for help on using the changeset viewer.