/ b3 / B3MathExtras.cpp
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