/*
 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "B3ReduceDoubleToFloat.h"

#if ENABLE(B3_JIT)

#include "B3BasicBlock.h"
#include "B3InsertionSetInlines.h"
#include "B3PhaseScope.h"
#include "B3UseCounts.h"
#include "B3ValueInlines.h"
#include <wtf/IndexSet.h>

namespace JSC { namespace B3 {

namespace {

namespace B3ReduceDoubleToFloatInternal {
static constexpr bool verbose = false;
}
bool printRemainingConversions = false;

class DoubleToFloatReduction {
public:
    DoubleToFloatReduction(Procedure& procedure)
        : m_procedure(procedure)
    {
    }

    void run()
    {
        if (!findCandidates())
            return;

        findPhisContainingFloat();

        simplify();

        cleanUp();
    }

private:
    // This step find values that are used as Double and cannot be converted to Float..
    // It flows the information backward through Phi-Upsilons.
    bool findCandidates()
    {
        bool foundConversionCandidate = false;
        Vector<Value*, 32> upsilons;

        // First, we find all values that are strictly used as double.
        // Those are values used by something else than DoubleToFloat.
        //
        // We don't know the state of Upsilons until their Phi has been
        // set. We just keep a list of them and update them next.
        for (BasicBlock* block : m_procedure) {
            for (Value* value : *block) {
                value->performSubstitution();

                if (value->opcode() == DoubleToFloat) {
                    foundConversionCandidate = true;

                    Value* child = value->child(0);
                    if (child->opcode() == FloatToDouble) {
                        // We don't really need to simplify this early but it simplifies debugging.
                        value->replaceWithIdentity(child->child(0));
                    }
                    continue;
                }

                if (value->opcode() == FloatToDouble)
                    foundConversionCandidate = true;

                if (value->opcode() == Upsilon) {
                    Value* child = value->child(0);
                    if (child->type() == Double)
                        upsilons.append(value);
                    continue;
                }

                for (Value* child : value->children()) {
                    if (child->type() == Double)
                        m_valuesUsedAsDouble.add(child);
                }
            }
        }

        if (!foundConversionCandidate)
            return false;

        // Now we just need to propagate through Phi-Upsilon.
        // A Upsilon can convert its input to float if its phi is never used as double.
        // If we modify a phi, we need to continue until all the Upsilon-Phi converge.
        bool changedPhiState;
        do {
            changedPhiState = false;
            for (Value* value : upsilons) {
                UpsilonValue* upsilon = value->as<UpsilonValue>();
                Value* phi = upsilon->phi();
                if (!m_valuesUsedAsDouble.contains(phi))
                    continue;

                Value* child = value->child(0);
                bool childChanged = m_valuesUsedAsDouble.add(child);
                if (childChanged && child->opcode() == Phi)
                    changedPhiState = true;
            }
        } while (changedPhiState);

        if (B3ReduceDoubleToFloatInternal::verbose) {
            dataLog("Conversion candidates:\n");
            for (BasicBlock* block : m_procedure) {
                for (Value* value : *block) {
                    if (value->type() == Double && !m_valuesUsedAsDouble.contains(value))
                        dataLog("    ", deepDump(m_procedure, value), "\n");
                }
            }
            dataLog("\n");
        }

        return true;
    }

    // This step finds Phis of type Double that effectively contains Float values.
    // It flows that information forward through Phi-Upsilons.
    void findPhisContainingFloat()
    {
        Vector<Value*, 32> upsilons;

        // The Double value that can be safely turned into a Float are:
        // - FloatToDouble
        // - ConstDouble with a value that converts to Float without losing precision.
        for (BasicBlock* block : m_procedure) {
            for (Value* value : *block) {
                if (value->opcode() != Upsilon)
                    continue;

                Value* child = value->child(0);
                if (child->type() != Double
                    || child->opcode() == FloatToDouble)
                    continue;

                if (child->hasDouble()) {
                    double constValue = child->asDouble();
                    if (isIdentical(static_cast<double>(static_cast<float>(constValue)), constValue))
                        continue;
                }

                if (child->opcode() == Phi) {
                    upsilons.append(value);
                    continue;
                }

                UpsilonValue* upsilon = value->as<UpsilonValue>();
                Value* phi = upsilon->phi();
                m_phisContainingDouble.add(phi);
            }
        }

        // Propagate the flags forward.
        bool changedPhiState;
        do {
            changedPhiState = false;
            for (Value* value : upsilons) {
                Value* child = value->child(0);
                if (m_phisContainingDouble.contains(child)) {
                    UpsilonValue* upsilon = value->as<UpsilonValue>();
                    Value* phi = upsilon->phi();
                    changedPhiState |= m_phisContainingDouble.add(phi);
                }
            }
        } while (changedPhiState);

        if (B3ReduceDoubleToFloatInternal::verbose) {
            dataLog("Phis containing float values:\n");
            for (BasicBlock* block : m_procedure) {
                for (Value* value : *block) {
                    if (value->opcode() == Phi
                        && value->type() == Double
                        && !m_phisContainingDouble.contains(value))
                        dataLog("    ", deepDump(m_procedure, value), "\n");
                }
            }
            dataLog("\n");
        }
    }

    bool canBeTransformedToFloat(Value* value)
    {
        if (value->opcode() == FloatToDouble)
            return true;

        if (value->hasDouble()) {
            // When comparing double and float, some range of double values will be truncated into one float.
            // So we need to ensure that this double value is one-on-one representation to the original double.
            // Let's consider the case,
            //
            //     Equal(Double: 1.1, FloatToDouble(Float: 1.1))
            //
            // This should be false. This is because
            //
            //     static_cast<double>(static_cast<float>(1.1)) != 1.1
            //
            double constValue = value->asDouble();
            return isIdentical(static_cast<double>(static_cast<float>(constValue)), constValue);
        }

        if (value->opcode() == Phi) {
            return value->type() == Float
                || (value->type() == Double && !m_phisContainingDouble.contains(value));
        }
        return false;
    }

    Value* transformToFloat(Value* value, unsigned valueIndex, InsertionSet& insertionSet)
    {
        ASSERT(canBeTransformedToFloat(value));
        if (value->opcode() == FloatToDouble)
            return value->child(0);

        if (value->hasDouble())
            return insertionSet.insert<ConstFloatValue>(valueIndex, value->origin(), static_cast<float>(value->asDouble()));

        if (value->opcode() == Phi) {
            ASSERT(value->type() == Double || value->type() == Float);
            if (value->type() == Double)
                convertPhi(value);
            return value;
        }
        RELEASE_ASSERT_NOT_REACHED();
        return nullptr;
    }

    void convertPhi(Value* phi)
    {
        ASSERT(phi->opcode() == Phi);
        ASSERT(phi->type() == Double);
        phi->setType(Float);
        m_convertedPhis.add(phi);
    }

    bool attemptTwoOperandsSimplify(Value* candidate, unsigned candidateIndex, InsertionSet& insertionSet)
    {
        Value* left = candidate->child(0);
        Value* right = candidate->child(1);
        if (!canBeTransformedToFloat(left) || !canBeTransformedToFloat(right))
            return false;

        if (left->hasDouble() && right->hasDouble()) {
            // If both inputs are constants, converting them to floats and performing
            // the same operation is incorrect. It may produce a different value
            // depending on the operation and the inputs. There are inputs where
            // casting to float and performing the operation would result in the
            // same value. Regardless, we don't prove when that is legal here since
            // it isn't profitable to do. We leave it to strength reduction to handle
            // reduce these cases.
            return false;
        }

        m_convertedValue.add(candidate);
        candidate->child(0) = transformToFloat(left, candidateIndex, insertionSet);
        candidate->child(1) = transformToFloat(right, candidateIndex, insertionSet);
        return true;
    }

    // Simplify Double operations into Float operations.
    void simplify()
    {
        Vector<Value*, 32> upsilonReferencingDoublePhi;

        InsertionSet insertionSet(m_procedure);
        for (BasicBlock* block : m_procedure) {
            for (unsigned index = 0; index < block->size(); ++index) {
                Value* value = block->at(index);

                switch (value->opcode()) {
                case Equal:
                case NotEqual:
                case LessThan:
                case GreaterThan:
                case LessEqual:
                case GreaterEqual:
                case EqualOrUnordered:
                    attemptTwoOperandsSimplify(value, index, insertionSet);
                    continue;
                case Upsilon: {
                    Value* child = value->child(0);
                    if (child->opcode() == Phi && child->type() == Double)
                        upsilonReferencingDoublePhi.append(value);
                    continue;
                }
                default:
                    break;
                }

                if (m_valuesUsedAsDouble.contains(value))
                    continue;

                switch (value->opcode()) {
                case Add:
                case Sub:
                case Mul:
                case Div:
                    if (attemptTwoOperandsSimplify(value, index, insertionSet))
                        value->setType(Float);
                    break;
                case Abs:
                case Ceil:
                case Floor:
                case Neg:
                case Sqrt: {
                    Value* child = value->child(0);
                    if (canBeTransformedToFloat(child)) {
                        value->child(0) = transformToFloat(child, index, insertionSet);
                        value->setType(Float);
                        m_convertedValue.add(value);
                    }
                    break;
                }
                case IToD: {
                    Value* iToF = insertionSet.insert<Value>(index, IToF, value->origin(), value->child(0));
                    value->setType(Float);
                    value->replaceWithIdentity(iToF);
                    m_convertedValue.add(value);
                    break;
                }
                case FloatToDouble:
                    // This happens if we round twice.
                    // Typically, this is indirect through Phi-Upsilons.
                    // The Upsilon rounds and the Phi rounds.
                    value->setType(Float);
                    value->replaceWithIdentity(value->child(0));
                    m_convertedValue.add(value);
                    break;
                case Phi:
                    // If a Phi is always converted to Float, we always make it into a float Phi-Upsilon.
                    // This is a simplistic view of things. Ideally we should keep type that will minimize
                    // the amount of conversion in the loop.
                    if (value->type() == Double)
                        convertPhi(value);
                    break;
                default:
                    break;
                }
            }
            insertionSet.execute(block);
        }

        if (!upsilonReferencingDoublePhi.isEmpty()) {
            // If a Phi contains Float values typed as Double, but is not used as Float
            // by a non-trivial operation, we did not convert it.
            //
            // We fix that now by converting the remaining phis that contains
            // float but where not converted to float.
            bool changedPhi;
            do {
                changedPhi = false;

                for (Value* value : upsilonReferencingDoublePhi) {
                    UpsilonValue* upsilon = value->as<UpsilonValue>();
                    Value* child = value->child(0);
                    Value* phi = upsilon->phi();
                    if (phi->type() == Float && child->type() == Double
                        && !m_phisContainingDouble.contains(child)) {
                        convertPhi(child);
                        changedPhi = true;
                    }
                }

            } while (changedPhi);
        }
    }

    // We are in an inconsistent state where we have
    // DoubleToFloat nodes over values producing float and Phis that are
    // float for Upsilons that are Double.
    //
    // This steps puts us back in a consistent state.
    void cleanUp()
    {
        InsertionSet insertionSet(m_procedure);

        for (BasicBlock* block : m_procedure) {
            for (unsigned index = 0; index < block->size(); ++index) {
                Value* value = block->at(index);
                if (value->opcode() == DoubleToFloat && value->child(0)->type() == Float) {
                    value->replaceWithIdentity(value->child(0));
                    continue;
                }

                if (value->opcode() == Upsilon) {
                    UpsilonValue* upsilon = value->as<UpsilonValue>();
                    Value* child = value->child(0);
                    Value* phi = upsilon->phi();

                    if (phi->type() == Float) {
                        if (child->type() == Double) {
                            Value* newChild = nullptr;
                            if (child->opcode() == FloatToDouble)
                                newChild = child->child(0);
                            else if (child->hasDouble())
                                newChild = insertionSet.insert<ConstFloatValue>(index, child->origin(), static_cast<float>(child->asDouble()));
                            else
                                newChild = insertionSet.insert<Value>(index, DoubleToFloat, upsilon->origin(), child);
                            upsilon->child(0) = newChild;
                        }
                        continue;
                    }
                }

                if (!m_convertedValue.contains(value)) {
                    // Phis can be converted from Double to Float if the value they contain
                    // is not more precise than a Float.
                    // If the value is needed as Double, it has to be converted back.
                    for (Value*& child : value->children()) {
                        if (m_convertedPhis.contains(child))
                            child = insertionSet.insert<Value>(index, FloatToDouble, value->origin(), child);
                    }
                }
            }
            insertionSet.execute(block);
        }
    }

    Procedure& m_procedure;

    // Set of all the Double values that are actually used as Double.
    // Converting any of them to Float would lose precision.
    IndexSet<Value*> m_valuesUsedAsDouble;

    // Set of all the Phi of type Double that really contains a Double.
    // Any Double Phi not in the set can be converted to Float without losing precision.
    IndexSet<Value*> m_phisContainingDouble;

    // Any value that was converted from producing a Double to producing a Float.
    // This set does not include Phi-Upsilons.
    IndexSet<Value*> m_convertedValue;

    // Any value that previously produced Double and now produce Float.
    IndexSet<Value*> m_convertedPhis;
};

void printGraphIfConverting(Procedure& procedure)
{
    if (!printRemainingConversions)
        return;

    UseCounts useCount(procedure);

    Vector<Value*> doubleToFloat;
    Vector<Value*> floatToDouble;

    for (BasicBlock* block : procedure) {
        for (Value* value : *block) {
            if (!useCount.numUses(value))
                continue;

            if (value->opcode() == DoubleToFloat)
                doubleToFloat.append(value);
            if (value->opcode() == FloatToDouble)
                floatToDouble.append(value);
        }
    }

    if (doubleToFloat.isEmpty() && floatToDouble.isEmpty())
        return;

    dataLog("Procedure with Float-Double conversion:\n", procedure, "\n");
    dataLog("Converting nodes:\n");
    for (Value* value : doubleToFloat)
        dataLog("    ", deepDump(procedure, value), "\n");
    for (Value* value : floatToDouble)
        dataLog("    ", deepDump(procedure, value), "\n");

}

} // anonymous namespace.

void reduceDoubleToFloat(Procedure& procedure)
{
    PhaseScope phaseScope(procedure, "reduceDoubleToFloat");

    if (B3ReduceDoubleToFloatInternal::verbose)
        dataLog("Before DoubleToFloatReduction:\n", procedure, "\n");

    DoubleToFloatReduction doubleToFloatReduction(procedure);
    doubleToFloatReduction.run();

    if (B3ReduceDoubleToFloatInternal::verbose)
        dataLog("After DoubleToFloatReduction:\n", procedure, "\n");

    printGraphIfConverting(procedure);
}

} } // namespace JSC::B3

#endif // ENABLE(B3_JIT)

