REGRESSION(r200208): It made 2 JSC stress tests fail on x86
[WebKit-https.git] / Source / JavaScriptCore / b3 / B3MathExtras.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "B3MathExtras.h"
28
29 #if ENABLE(B3_JIT)
30
31 #include "B3BasicBlockInlines.h"
32 #include "B3CCallValue.h"
33 #include "B3Const32Value.h"
34 #include "B3ConstDoubleValue.h"
35 #include "B3ConstPtrValue.h"
36 #include "B3ControlValue.h"
37 #include "B3UpsilonValue.h"
38 #include "B3ValueInlines.h"
39 #include "MathCommon.h"
40
41 namespace JSC { namespace B3 {
42
43 std::pair<BasicBlock*, Value*> powDoubleInt32(Procedure& procedure, BasicBlock* start, Origin origin, Value* x, Value* y)
44 {
45     BasicBlock* functionCallCase = procedure.addBlock();
46     BasicBlock* loopPreHeaderCase = procedure.addBlock();
47     BasicBlock* loopTestForEvenCase = procedure.addBlock();
48     BasicBlock* loopOdd = procedure.addBlock();
49     BasicBlock* loopEvenOdd = procedure.addBlock();
50     BasicBlock* continuation = procedure.addBlock();
51
52     Value* shouldGoSlowPath = start->appendNew<Value>(procedure, Above, origin,
53         y,
54         start->appendNew<Const32Value>(procedure, origin, maxExponentForIntegerMathPow));
55     start->appendNew<ControlValue>(
56         procedure, Branch, origin,
57         shouldGoSlowPath,
58         FrequentedBlock(functionCallCase), FrequentedBlock(loopPreHeaderCase));
59
60     // Function call.
61     Value* yAsDouble = functionCallCase->appendNew<Value>(procedure, IToD, origin, y);
62     double (*powDouble)(double, double) = pow;
63     Value* powResult = functionCallCase->appendNew<CCallValue>(
64         procedure, Double, origin,
65         functionCallCase->appendNew<ConstPtrValue>(procedure, origin, bitwise_cast<void*>(powDouble)),
66         x, yAsDouble);
67     UpsilonValue* powResultUpsilon = functionCallCase->appendNew<UpsilonValue>(procedure, origin, powResult);
68     functionCallCase->appendNew<ControlValue>(procedure, Jump, origin, FrequentedBlock(continuation));
69
70     // Loop pre-header.
71     Value* initialResult = loopPreHeaderCase->appendNew<ConstDoubleValue>(procedure, origin, 1.);
72     UpsilonValue* initialLoopValue = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, initialResult);
73     UpsilonValue* initialResultValue = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, initialResult);
74     UpsilonValue* initialSquaredInput = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, x);
75     UpsilonValue* initialLoopCounter = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, y);
76     loopPreHeaderCase->appendNew<ControlValue>(procedure, Jump, origin, FrequentedBlock(loopTestForEvenCase));
77
78     // Test if what is left of the counter is even.
79     Value* inLoopCounter = loopTestForEvenCase->appendNew<Value>(procedure, Phi, Int32, origin);
80     Value* inLoopSquaredInput = loopTestForEvenCase->appendNew<Value>(procedure, Phi, Double, origin);
81     Value* lastCounterBit = loopTestForEvenCase->appendNew<Value>(procedure, BitAnd, origin,
82         inLoopCounter,
83         loopTestForEvenCase->appendNew<Const32Value>(procedure, origin, 1));
84     loopTestForEvenCase->appendNew<ControlValue>(
85         procedure, Branch, origin,
86         lastCounterBit,
87         FrequentedBlock(loopOdd), FrequentedBlock(loopEvenOdd));
88
89     // Counter is odd.
90     Value* inLoopResult = loopOdd->appendNew<Value>(procedure, Phi, Double, origin);
91     Value* updatedResult = loopOdd->appendNew<Value>(procedure, Mul, origin, inLoopResult, inLoopSquaredInput);
92     UpsilonValue* updatedLoopResultUpsilon = loopOdd->appendNew<UpsilonValue>(procedure, origin, updatedResult);
93     initialLoopValue->setPhi(inLoopResult);
94     updatedLoopResultUpsilon->setPhi(inLoopResult);
95     UpsilonValue* updatedLoopResult = loopOdd->appendNew<UpsilonValue>(procedure, origin, updatedResult);
96
97     loopOdd->appendNew<ControlValue>(procedure, Jump, origin, FrequentedBlock(loopEvenOdd));
98
99     // Even value and following the Odd.
100     Value* squaredInput = loopEvenOdd->appendNew<Value>(procedure, Mul, origin, inLoopSquaredInput, inLoopSquaredInput);
101     UpsilonValue* squaredInputUpsilon = loopEvenOdd->appendNew<UpsilonValue>(procedure, origin, squaredInput);
102     initialSquaredInput->setPhi(inLoopSquaredInput);
103     squaredInputUpsilon->setPhi(inLoopSquaredInput);
104
105     Value* updatedCounter = loopEvenOdd->appendNew<Value>(procedure, ZShr, origin,
106         inLoopCounter,
107         loopEvenOdd->appendNew<Const32Value>(procedure, origin, 1));
108     UpsilonValue* updatedCounterUpsilon = loopEvenOdd->appendNew<UpsilonValue>(procedure, origin, updatedCounter);
109     initialLoopCounter->setPhi(inLoopCounter);
110     updatedCounterUpsilon->setPhi(inLoopCounter);
111
112     loopEvenOdd->appendNew<ControlValue>(
113         procedure, Branch, origin,
114         updatedCounter,
115         FrequentedBlock(loopTestForEvenCase), FrequentedBlock(continuation));
116
117     // Inline loop.
118     Value* finalResultPhi = continuation->appendNew<Value>(procedure, Phi, Double, origin);
119     powResultUpsilon->setPhi(finalResultPhi);
120     initialResultValue->setPhi(finalResultPhi);
121     updatedLoopResult->setPhi(finalResultPhi);
122     return std::make_pair(continuation, finalResultPhi);
123 }
124
125 } } // namespace JSC::B3
126
127 #endif // ENABLE(B3_JIT)
128