65e3276d044551fb806ac1384e11bb425c379919
[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
40 namespace JSC { namespace B3 {
41
42 std::pair<BasicBlock*, Value*> powDoubleInt32(Procedure& procedure, BasicBlock* start, Origin origin, Value* x, Value* y)
43 {
44     BasicBlock* functionCallCase = procedure.addBlock();
45     BasicBlock* loopPreHeaderCase = procedure.addBlock();
46     BasicBlock* loopTestForEvenCase = procedure.addBlock();
47     BasicBlock* loopOdd = procedure.addBlock();
48     BasicBlock* loopEvenOdd = procedure.addBlock();
49     BasicBlock* continuation = procedure.addBlock();
50
51     Value* shouldGoSlowPath = start->appendNew<Value>(procedure, Above, origin,
52         y,
53         start->appendNew<Const32Value>(procedure, origin, 1000));
54     start->appendNew<ControlValue>(
55         procedure, Branch, origin,
56         shouldGoSlowPath,
57         FrequentedBlock(functionCallCase), FrequentedBlock(loopPreHeaderCase));
58
59     // Function call.
60     Value* yAsDouble = functionCallCase->appendNew<Value>(procedure, IToD, origin, y);
61     double (*powDouble)(double, double) = pow;
62     Value* powResult = functionCallCase->appendNew<CCallValue>(
63         procedure, Double, origin,
64         functionCallCase->appendNew<ConstPtrValue>(procedure, origin, bitwise_cast<void*>(powDouble)),
65         x, yAsDouble);
66     UpsilonValue* powResultUpsilon = functionCallCase->appendNew<UpsilonValue>(procedure, origin, powResult);
67     functionCallCase->appendNew<ControlValue>(procedure, Jump, origin, FrequentedBlock(continuation));
68
69     // Loop pre-header.
70     Value* initialResult = loopPreHeaderCase->appendNew<ConstDoubleValue>(procedure, origin, 1.);
71     UpsilonValue* initialLoopValue = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, initialResult);
72     UpsilonValue* initialResultValue = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, initialResult);
73     UpsilonValue* initialSquaredInput = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, x);
74     UpsilonValue* initialLoopCounter = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, y);
75     loopPreHeaderCase->appendNew<ControlValue>(procedure, Jump, origin, FrequentedBlock(loopTestForEvenCase));
76
77     // Test if what is left of the counter is even.
78     Value* inLoopCounter = loopTestForEvenCase->appendNew<Value>(procedure, Phi, Int32, origin);
79     Value* inLoopSquaredInput = loopTestForEvenCase->appendNew<Value>(procedure, Phi, Double, origin);
80     Value* lastCounterBit = loopTestForEvenCase->appendNew<Value>(procedure, BitAnd, origin,
81         inLoopCounter,
82         loopTestForEvenCase->appendNew<Const32Value>(procedure, origin, 1));
83     loopTestForEvenCase->appendNew<ControlValue>(
84         procedure, Branch, origin,
85         lastCounterBit,
86         FrequentedBlock(loopOdd), FrequentedBlock(loopEvenOdd));
87
88     // Counter is odd.
89     Value* inLoopResult = loopOdd->appendNew<Value>(procedure, Phi, Double, origin);
90     Value* updatedResult = loopOdd->appendNew<Value>(procedure, Mul, origin, inLoopResult, inLoopSquaredInput);
91     UpsilonValue* updatedLoopResultUpsilon = loopOdd->appendNew<UpsilonValue>(procedure, origin, updatedResult);
92     initialLoopValue->setPhi(inLoopResult);
93     updatedLoopResultUpsilon->setPhi(inLoopResult);
94     UpsilonValue* updatedLoopResult = loopOdd->appendNew<UpsilonValue>(procedure, origin, updatedResult);
95
96     loopOdd->appendNew<ControlValue>(procedure, Jump, origin, FrequentedBlock(loopEvenOdd));
97
98     // Even value and following the Odd.
99     Value* squaredInput = loopEvenOdd->appendNew<Value>(procedure, Mul, origin, inLoopSquaredInput, inLoopSquaredInput);
100     UpsilonValue* squaredInputUpsilon = loopEvenOdd->appendNew<UpsilonValue>(procedure, origin, squaredInput);
101     initialSquaredInput->setPhi(inLoopSquaredInput);
102     squaredInputUpsilon->setPhi(inLoopSquaredInput);
103
104     Value* updatedCounter = loopEvenOdd->appendNew<Value>(procedure, ZShr, origin,
105         inLoopCounter,
106         loopEvenOdd->appendNew<Const32Value>(procedure, origin, 1));
107     UpsilonValue* updatedCounterUpsilon = loopEvenOdd->appendNew<UpsilonValue>(procedure, origin, updatedCounter);
108     initialLoopCounter->setPhi(inLoopCounter);
109     updatedCounterUpsilon->setPhi(inLoopCounter);
110
111     loopEvenOdd->appendNew<ControlValue>(
112         procedure, Branch, origin,
113         updatedCounter,
114         FrequentedBlock(loopTestForEvenCase), FrequentedBlock(continuation));
115
116     // Inline loop.
117     Value* finalResultPhi = continuation->appendNew<Value>(procedure, Phi, Double, origin);
118     powResultUpsilon->setPhi(finalResultPhi);
119     initialResultValue->setPhi(finalResultPhi);
120     updatedLoopResult->setPhi(finalResultPhi);
121     return std::make_pair(continuation, finalResultPhi);
122 }
123
124 } } // namespace JSC::B3
125
126 #endif // ENABLE(B3_JIT)
127