/*
 * 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 "DFGMovHintRemovalPhase.h"

#if ENABLE(DFG_JIT)

#include "BytecodeLivenessAnalysisInlines.h"
#include "DFGEpoch.h"
#include "DFGForAllKills.h"
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGMayExit.h"
#include "DFGPhase.h"
#include "JSCInlines.h"
#include "OperandsInlines.h"

namespace JSC { namespace DFG {

namespace {

namespace DFGMovHintRemovalPhaseInternal {
static constexpr bool verbose = false;
}

class MovHintRemovalPhase : public Phase {
public:
    MovHintRemovalPhase(Graph& graph)
        : Phase(graph, "MovHint removal")
        , m_state(OperandsLike, graph.block(0)->variablesAtHead)
        , m_changed(false)
    {
    }
    
    bool run()
    {
        if (DFGMovHintRemovalPhaseInternal::verbose) {
            dataLog("Graph before MovHint removal:\n");
            m_graph.dump();
        }
        
        for (BasicBlock* block : m_graph.blocksInNaturalOrder())
            handleBlock(block);
        
        return m_changed;
    }

private:
    void handleBlock(BasicBlock* block)
    {
        if (DFGMovHintRemovalPhaseInternal::verbose)
            dataLog("Handing block ", pointerDump(block), "\n");
        
        // A MovHint is unnecessary if the local dies before it is used. We answer this question by
        // maintaining the current exit epoch, and associating an epoch with each local. When a
        // local dies, it gets the current exit epoch. If a MovHint occurs in the same epoch as its
        // local, then it means there was no exit between the local's death and the MovHint - i.e.
        // the MovHint is unnecessary.
        
        Epoch currentEpoch = Epoch::first();
        
        m_state.fill(Epoch());
        m_graph.forAllLiveInBytecode(
            block->terminal()->origin.forExit,
            [&] (Operand reg) {
                m_state.operand(reg) = currentEpoch;
            });
        
        if (DFGMovHintRemovalPhaseInternal::verbose)
            dataLog("    Locals: ", m_state, "\n");
        
        // Assume that blocks after us exit.
        currentEpoch.bump();
        
        for (unsigned nodeIndex = block->size(); nodeIndex--;) {
            Node* node = block->at(nodeIndex);
            
            if (node->op() == MovHint) {
                Epoch localEpoch = m_state.operand(node->unlinkedOperand());
                if (DFGMovHintRemovalPhaseInternal::verbose)
                    dataLog("    At ", node, ": current = ", currentEpoch, ", local = ", localEpoch, "\n");
                if (!localEpoch || localEpoch == currentEpoch) {
                    node->setOpAndDefaultFlags(ZombieHint);
                    node->child1() = Edge();
                    m_changed = true;
                }
                m_state.operand(node->unlinkedOperand()) = Epoch();
            }
            
            if (mayExit(m_graph, node) != DoesNotExit)
                currentEpoch.bump();
            
            if (nodeIndex) {
                forAllKilledOperands(
                    m_graph, block->at(nodeIndex - 1), node,
                    [&] (Operand operand) {
                        // This function is a bit sloppy - it might claim to kill a local even if
                        // it's still live after. We need to protect against that.
                        if (!!m_state.operand(operand))
                            return;
                        
                        if (DFGMovHintRemovalPhaseInternal::verbose)
                            dataLog("    Killed operand at ", node, ": ", operand, "\n");
                        m_state.operand(operand) = currentEpoch;
                    });
            }
        }
    }
    
    Operands<Epoch> m_state;
    bool m_changed;
};

} // anonymous namespace
    
bool performMovHintRemoval(Graph& graph)
{
    return runPhase<MovHintRemovalPhase>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

