B3MathExtras.cpp
1 /* 2 * Copyright (C) 2015-2020 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 "B3UpsilonValue.h" 37 #include "B3ValueInlines.h" 38 #include "JSCPtrTag.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<Value>(procedure, Branch, origin, shouldGoSlowPath); 56 start->setSuccessors(FrequentedBlock(functionCallCase), FrequentedBlock(loopPreHeaderCase)); 57 58 // Function call. 59 Value* yAsDouble = functionCallCase->appendNew<Value>(procedure, IToD, origin, y); 60 Value* powResult = functionCallCase->appendNew<CCallValue>( 61 procedure, Double, origin, 62 functionCallCase->appendNew<ConstPtrValue>(procedure, origin, bitwise_cast<void*>(tagCFunction<OperationPtrTag>(Math::stdPowDouble))), 63 x, yAsDouble); 64 UpsilonValue* powResultUpsilon = functionCallCase->appendNew<UpsilonValue>(procedure, origin, powResult); 65 functionCallCase->appendNew<Value>(procedure, Jump, origin); 66 functionCallCase->setSuccessors(FrequentedBlock(continuation)); 67 68 // Loop pre-header. 69 Value* initialResult = loopPreHeaderCase->appendNew<ConstDoubleValue>(procedure, origin, 1.); 70 UpsilonValue* initialLoopValue = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, initialResult); 71 UpsilonValue* initialResultValue = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, initialResult); 72 UpsilonValue* initialSquaredInput = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, x); 73 UpsilonValue* initialLoopCounter = loopPreHeaderCase->appendNew<UpsilonValue>(procedure, origin, y); 74 loopPreHeaderCase->appendNew<Value>(procedure, Jump, origin); 75 loopPreHeaderCase->setSuccessors(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<Value>(procedure, Branch, origin, lastCounterBit); 84 loopTestForEvenCase->setSuccessors(FrequentedBlock(loopOdd), FrequentedBlock(loopEvenOdd)); 85 86 // Counter is odd. 87 Value* inLoopResult = loopOdd->appendNew<Value>(procedure, Phi, Double, origin); 88 Value* updatedResult = loopOdd->appendNew<Value>(procedure, Mul, origin, inLoopResult, inLoopSquaredInput); 89 UpsilonValue* updatedLoopResultUpsilon = loopOdd->appendNew<UpsilonValue>(procedure, origin, updatedResult); 90 initialLoopValue->setPhi(inLoopResult); 91 updatedLoopResultUpsilon->setPhi(inLoopResult); 92 UpsilonValue* updatedLoopResult = loopOdd->appendNew<UpsilonValue>(procedure, origin, updatedResult); 93 94 loopOdd->appendNew<Value>(procedure, Jump, origin); 95 loopOdd->setSuccessors(FrequentedBlock(loopEvenOdd)); 96 97 // Even value and following the Odd. 98 Value* squaredInput = loopEvenOdd->appendNew<Value>(procedure, Mul, origin, inLoopSquaredInput, inLoopSquaredInput); 99 UpsilonValue* squaredInputUpsilon = loopEvenOdd->appendNew<UpsilonValue>(procedure, origin, squaredInput); 100 initialSquaredInput->setPhi(inLoopSquaredInput); 101 squaredInputUpsilon->setPhi(inLoopSquaredInput); 102 103 Value* updatedCounter = loopEvenOdd->appendNew<Value>(procedure, ZShr, origin, 104 inLoopCounter, 105 loopEvenOdd->appendNew<Const32Value>(procedure, origin, 1)); 106 UpsilonValue* updatedCounterUpsilon = loopEvenOdd->appendNew<UpsilonValue>(procedure, origin, updatedCounter); 107 initialLoopCounter->setPhi(inLoopCounter); 108 updatedCounterUpsilon->setPhi(inLoopCounter); 109 110 loopEvenOdd->appendNew<Value>(procedure, Branch, origin, updatedCounter); 111 loopEvenOdd->setSuccessors(FrequentedBlock(loopTestForEvenCase), FrequentedBlock(continuation)); 112 113 // Inline loop. 114 Value* finalResultPhi = continuation->appendNew<Value>(procedure, Phi, Double, origin); 115 powResultUpsilon->setPhi(finalResultPhi); 116 initialResultValue->setPhi(finalResultPhi); 117 updatedLoopResult->setPhi(finalResultPhi); 118 return std::make_pair(continuation, finalResultPhi); 119 } 120 121 } } // namespace JSC::B3 122 123 #endif // ENABLE(B3_JIT) 124