Skip to content

Commit 37413df

Browse files
committed
[JSC] FTL ArithPow should have a fast path for Math.pow(1, x)
https://bugs.webkit.org/show_bug.cgi?id=327466 rdar://189960465 Reviewed by Sosuke Suzuki. When Math.pow(1, x) is executed, if x is not NaN and not Infinity/-Infinity, then the result is 1. We are already checking NaN and +-Infinity for x, so let's check input is 1 and returning 1 quickly if true. Also, ArithPow implementation had many micro basic blocks just returning a constant. We fold them into a jumping basic block with anchoring. Test: JSTests/stress/math-pow-base-one.js * JSTests/stress/math-pow-base-one.js: Added. (shouldBe): (pow): * Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::compileArithPow): Canonical link: https://commits.webkit.org/323743@main
1 parent 1d86f80 commit 37413df

2 files changed

Lines changed: 67 additions & 35 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
function shouldBe(actual, expected, message) {
2+
if (!Object.is(actual, expected))
3+
throw new Error(message + ": expected " + expected + " but got " + actual);
4+
}
5+
6+
function pow(x, y) {
7+
return Math.pow(x, y);
8+
}
9+
noInline(pow);
10+
11+
var cases = [
12+
[1, 0.01666666753590107, 1],
13+
[1, 0.5, 1],
14+
[1, -0.5, 1],
15+
[1, 2.5, 1],
16+
[1, -2.5, 1],
17+
[1, 0, 1],
18+
[1, -0, 1],
19+
[1, 1e300, 1],
20+
[1, -1e300, 1],
21+
[1, Number.MIN_VALUE, 1],
22+
[1, NaN, NaN],
23+
[1, Infinity, NaN],
24+
[1, -Infinity, NaN],
25+
[-1, 0.5, NaN],
26+
[-1, 2.5, NaN],
27+
[-1, Infinity, NaN],
28+
[-1, -Infinity, NaN],
29+
[-1, NaN, NaN],
30+
[1.0000000000000002, 1e300, Infinity],
31+
[0.9999999999999999, 1e300, 0],
32+
[2, 0.5, Math.SQRT2],
33+
[4, -0.5, 0.5],
34+
[0, 0.5, 0],
35+
[-0, 0.5, 0],
36+
[Infinity, 0.5, Infinity],
37+
[Infinity, -0.5, 0],
38+
];
39+
40+
for (var i = 0; i < testLoopCount; ++i) {
41+
for (var [x, y, expected] of cases)
42+
shouldBe(pow(x, y), expected, "Math.pow(" + x + ", " + y + ")");
43+
}

‎Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp‎

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3625,19 +3625,16 @@ class LowerDFGToB3 {
36253625
LBasicBlock doubleExponentPowBlockEntry = m_out.newBlock();
36263626
LBasicBlock nanExceptionBaseIsOne = m_out.newBlock();
36273627
LBasicBlock nanExceptionExponentIsInfinity = m_out.newBlock();
3628+
LBasicBlock testBaseIsOne = m_out.newBlock();
36283629
LBasicBlock testExponentIsOneHalf = m_out.newBlock();
36293630
LBasicBlock handleBaseZeroExponentIsOneHalf = m_out.newBlock();
36303631
LBasicBlock handleInfinityForExponentIsOneHalf = m_out.newBlock();
36313632
LBasicBlock exponentIsOneHalfNormal = m_out.newBlock();
3632-
LBasicBlock exponentIsOneHalfInfinity = m_out.newBlock();
36333633
LBasicBlock testExponentIsNegativeOneHalf = m_out.newBlock();
36343634
LBasicBlock testBaseZeroExponentIsNegativeOneHalf = m_out.newBlock();
3635-
LBasicBlock handleBaseZeroExponentIsNegativeOneHalf = m_out.newBlock();
36363635
LBasicBlock handleInfinityForExponentIsNegativeOneHalf = m_out.newBlock();
36373636
LBasicBlock exponentIsNegativeOneHalfNormal = m_out.newBlock();
3638-
LBasicBlock exponentIsNegativeOneHalfInfinity = m_out.newBlock();
36393637
LBasicBlock powBlock = m_out.newBlock();
3640-
LBasicBlock nanExceptionResultIsNaN = m_out.newBlock();
36413638
LBasicBlock continuation = m_out.newBlock();
36423639

36433640
LValue integerExponent = m_out.doubleToInt32(exponent);
@@ -3662,7 +3659,8 @@ class LowerDFGToB3 {
36623659
exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent);
36633660
else
36643661
exponentIsNaN = m_out.booleanFalse;
3665-
m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionBaseIsOne));
3662+
ValueFromBlock nanResultExponentIsNaN = m_out.anchor(m_out.constDouble(PNaN));
3663+
m_out.branch(exponentIsNaN, rarely(continuation), usually(nanExceptionBaseIsOne));
36663664

36673665
// If abs(x) is 1 and y is +infinity, the result is NaN.
36683666
// If abs(x) is 1 and y is -infinity, the result is NaN.
@@ -3671,13 +3669,19 @@ class LowerDFGToB3 {
36713669
m_out.appendTo(nanExceptionBaseIsOne, nanExceptionExponentIsInfinity);
36723670
LValue absoluteBase = m_out.doubleAbs(base);
36733671
LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1));
3674-
m_out.branch(absoluteBaseIsOne, rarely(nanExceptionExponentIsInfinity), usually(testExponentIsOneHalf));
3672+
m_out.branch(absoluteBaseIsOne, unsure(nanExceptionExponentIsInfinity), unsure(testExponentIsOneHalf));
36753673

36763674
// Test if abs(y) == Infinity.
3677-
m_out.appendTo(nanExceptionExponentIsInfinity, testExponentIsOneHalf);
3675+
m_out.appendTo(nanExceptionExponentIsInfinity, testBaseIsOne);
36783676
LValue absoluteExponent = m_out.doubleAbs(exponent);
36793677
LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits<double>::infinity()));
3680-
m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionResultIsNaN), usually(testExponentIsOneHalf));
3678+
ValueFromBlock nanResultExponentIsInfinity = m_out.anchor(m_out.constDouble(PNaN));
3679+
m_out.branch(absoluteExponentIsInfinity, rarely(continuation), usually(testBaseIsOne));
3680+
3681+
// If x == 1 and y is neither NaN nor infinite, the result is 1.
3682+
m_out.appendTo(testBaseIsOne, testExponentIsOneHalf);
3683+
ValueFromBlock baseIsOneResult = m_out.anchor(m_out.constDouble(1));
3684+
m_out.branch(m_out.doubleEqual(base, m_out.constDouble(1)), unsure(continuation), unsure(testExponentIsOneHalf));
36813685

36823686
// If y == 0.5 or y == -0.5, handle it through SQRT.
36833687
// We have be carefuly with -0 and -Infinity.
@@ -3693,61 +3697,46 @@ class LowerDFGToB3 {
36933697
ValueFromBlock zeroResultExponentIsOneHalf = m_out.anchor(m_out.doubleZero);
36943698
m_out.branch(baseIsZeroExponentIsOneHalf, rarely(continuation), usually(handleInfinityForExponentIsOneHalf));
36953699

3696-
// Test if abs(x) == Infinity.
3700+
// Test if abs(x) == Infinity. If so, the result is always infinite.
36973701
m_out.appendTo(handleInfinityForExponentIsOneHalf, exponentIsOneHalfNormal);
36983702
LValue absoluteBaseIsInfinityOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits<double>::infinity()));
3699-
m_out.branch(absoluteBaseIsInfinityOneHalf, rarely(exponentIsOneHalfInfinity), usually(exponentIsOneHalfNormal));
3703+
ValueFromBlock sqrtInfinityResult = m_out.anchor(m_out.constDouble(std::numeric_limits<double>::infinity()));
3704+
m_out.branch(absoluteBaseIsInfinityOneHalf, rarely(continuation), usually(exponentIsOneHalfNormal));
37003705

37013706
// The exponent is 0.5, the base is finite or NaN, we can use SQRT.
3702-
m_out.appendTo(exponentIsOneHalfNormal, exponentIsOneHalfInfinity);
3707+
m_out.appendTo(exponentIsOneHalfNormal, testExponentIsNegativeOneHalf);
37033708
ValueFromBlock sqrtResult = m_out.anchor(m_out.doubleSqrt(base));
37043709
m_out.jump(continuation);
37053710

3706-
// The exponent is 0.5, the base is infinite, the result is always infinite.
3707-
m_out.appendTo(exponentIsOneHalfInfinity, testExponentIsNegativeOneHalf);
3708-
ValueFromBlock sqrtInfinityResult = m_out.anchor(m_out.constDouble(std::numeric_limits<double>::infinity()));
3709-
m_out.jump(continuation);
3710-
37113711
// Test if y == -0.5
37123712
m_out.appendTo(testExponentIsNegativeOneHalf, testBaseZeroExponentIsNegativeOneHalf);
37133713
LValue exponentIsNegativeOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(-0.5));
37143714
m_out.branch(exponentIsNegativeOneHalf, rarely(testBaseZeroExponentIsNegativeOneHalf), usually(powBlock));
37153715

37163716
// Handle x == -0.
3717-
m_out.appendTo(testBaseZeroExponentIsNegativeOneHalf, handleBaseZeroExponentIsNegativeOneHalf);
3717+
m_out.appendTo(testBaseZeroExponentIsNegativeOneHalf, handleInfinityForExponentIsNegativeOneHalf);
37183718
LValue baseIsZeroExponentIsNegativeOneHalf = m_out.doubleEqual(base, m_out.doubleZero);
3719-
m_out.branch(baseIsZeroExponentIsNegativeOneHalf, rarely(handleBaseZeroExponentIsNegativeOneHalf), usually(handleInfinityForExponentIsNegativeOneHalf));
3720-
3721-
m_out.appendTo(handleBaseZeroExponentIsNegativeOneHalf, handleInfinityForExponentIsNegativeOneHalf);
37223719
ValueFromBlock oneOverSqrtZeroResult = m_out.anchor(m_out.constDouble(std::numeric_limits<double>::infinity()));
3723-
m_out.jump(continuation);
3720+
m_out.branch(baseIsZeroExponentIsNegativeOneHalf, rarely(continuation), usually(handleInfinityForExponentIsNegativeOneHalf));
37243721

3725-
// Test if abs(x) == Infinity.
3722+
// Test if abs(x) == Infinity. If so, the result is always zero.
37263723
m_out.appendTo(handleInfinityForExponentIsNegativeOneHalf, exponentIsNegativeOneHalfNormal);
37273724
LValue absoluteBaseIsInfinityNegativeOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits<double>::infinity()));
3728-
m_out.branch(absoluteBaseIsInfinityNegativeOneHalf, rarely(exponentIsNegativeOneHalfInfinity), usually(exponentIsNegativeOneHalfNormal));
3725+
ValueFromBlock oneOverSqrtInfinityResult = m_out.anchor(m_out.doubleZero);
3726+
m_out.branch(absoluteBaseIsInfinityNegativeOneHalf, rarely(continuation), usually(exponentIsNegativeOneHalfNormal));
37293727

37303728
// The exponent is -0.5, the base is finite or NaN, we can use 1/SQRT.
3731-
m_out.appendTo(exponentIsNegativeOneHalfNormal, exponentIsNegativeOneHalfInfinity);
3729+
m_out.appendTo(exponentIsNegativeOneHalfNormal, powBlock);
37323730
LValue sqrtBase = m_out.doubleSqrt(base);
37333731
ValueFromBlock oneOverSqrtResult = m_out.anchor(m_out.div(m_out.constDouble(1.), sqrtBase));
37343732
m_out.jump(continuation);
37353733

3736-
// The exponent is -0.5, the base is infinite, the result is always zero.
3737-
m_out.appendTo(exponentIsNegativeOneHalfInfinity, powBlock);
3738-
ValueFromBlock oneOverSqrtInfinityResult = m_out.anchor(m_out.doubleZero);
3739-
m_out.jump(continuation);
3740-
3741-
m_out.appendTo(powBlock, nanExceptionResultIsNaN);
3734+
m_out.appendTo(powBlock, continuation);
37423735
ValueFromBlock powResult = m_out.anchor(m_out.doubleStdPow(base, exponent));
37433736
m_out.jump(continuation);
37443737

3745-
m_out.appendTo(nanExceptionResultIsNaN, continuation);
3746-
ValueFromBlock pureNan = m_out.anchor(m_out.constDouble(PNaN));
3747-
m_out.jump(continuation);
3748-
37493738
m_out.appendTo(continuation, lastNext);
3750-
setDouble(m_out.phi(Double, powDoubleIntResult, zeroResultExponentIsOneHalf, sqrtResult, sqrtInfinityResult, oneOverSqrtZeroResult, oneOverSqrtResult, oneOverSqrtInfinityResult, powResult, pureNan));
3739+
setDouble(m_out.phi(Double, powDoubleIntResult, nanResultExponentIsNaN, nanResultExponentIsInfinity, baseIsOneResult, zeroResultExponentIsOneHalf, sqrtResult, sqrtInfinityResult, oneOverSqrtZeroResult, oneOverSqrtResult, oneOverSqrtInfinityResult, powResult));
37513740
}
37523741
}
37533742

0 commit comments

Comments
 (0)