/*
 * Copyright (C) 2014 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 "DFGIntegerCheckCombiningPhase.h"

#if ENABLE(DFG_JIT)

#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGPredictionPropagationPhase.h"
#include "DFGVariableAccessDataDump.h"
#include "JSCInlines.h"
#include <unordered_map>
#include <wtf/HashMethod.h>

namespace JSC { namespace DFG {

namespace {

static const bool verbose = false;

enum RangeKind {
    InvalidRangeKind,
    
    // This means we did ArithAdd with CheckOverflow.
    Addition,
    
    // This means we did CheckInBounds on some length.
    ArrayBounds
};

struct RangeKey {
    RangeKey()
        : m_kind(InvalidRangeKind)
        , m_key(nullptr)
    {
    }
    
    static RangeKey addition(Edge edge)
    {
        RangeKey result;
        result.m_kind = Addition;
        result.m_source = edge.sanitized();
        result.m_key = 0;
        return result;
    }
    
    static RangeKey arrayBounds(Edge edge, Node* key)
    {
        RangeKey result;
        result.m_kind = ArrayBounds;
        result.m_source = edge.sanitized();
        result.m_key = key;
        return result;
    }
    
    bool operator!() const { return m_kind == InvalidRangeKind; }
    
    unsigned hash() const
    {
        return m_kind + m_source.hash() + PtrHash<Node*>::hash(m_key);
    }
    
    bool operator==(const RangeKey& other) const
    {
        return m_kind == other.m_kind
            && m_source == other.m_source
            && m_key == other.m_key;
    }
    
    void dump(PrintStream& out) const
    {
        switch (m_kind) {
        case InvalidRangeKind:
            out.print("InvalidRangeKind(");
            break;
        case Addition:
            out.print("Addition(");
            break;
        case ArrayBounds:
            out.print("ArrayBounds(");
            break;
        }
        out.print(m_source, ", ", m_key, ")");
    }
    
    RangeKind m_kind;
    Edge m_source;
    Node* m_key;
};

struct RangeKeyAndAddend {
    RangeKeyAndAddend()
        : m_addend(0)
    {
    }
    
    RangeKeyAndAddend(RangeKey key, int32_t addend)
        : m_key(key)
        , m_addend(addend)
    {
    }
    
    bool operator!() const { return !m_key && !m_addend; }
    
    void dump(PrintStream& out) const
    {
        out.print(m_key, " + ", m_addend);
    }
    
    RangeKey m_key;
    int32_t m_addend;
};

struct Range {
    Range()
        : m_minBound(0)
        , m_maxBound(0)
        , m_count(0)
        , m_hoisted(false)
    {
    }
    
    void dump(PrintStream& out) const
    {
        out.print("(", m_minBound, " @", m_minOrigin, ") .. (", m_maxBound, " @", m_maxOrigin, "), count = ", m_count, ", hoisted = ", m_hoisted);
    }
    
    int32_t m_minBound;
    CodeOrigin m_minOrigin;
    int32_t m_maxBound;
    CodeOrigin m_maxOrigin;
    unsigned m_count; // If this is zero then the bounds won't necessarily make sense.
    bool m_hoisted;
};

} // anonymous namespace

class IntegerCheckCombiningPhase : public Phase {
public:
    IntegerCheckCombiningPhase(Graph& graph)
        : Phase(graph, "integer check combining")
        , m_insertionSet(graph)
    {
    }
    
    bool run()
    {
        ASSERT(m_graph.m_form == SSA);
        
        m_changed = false;
        
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;)
            handleBlock(blockIndex);
        
        return m_changed;
    }

private:
    void handleBlock(BlockIndex blockIndex)
    {
        BasicBlock* block = m_graph.block(blockIndex);
        if (!block)
            return;
        
        m_map.clear();
        
        // First we collect Ranges. If operations within the range have enough redundancy,
        // we hoist. And then we remove additions and checks that fall within the max range.
        
        for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
            Node* node = block->at(nodeIndex);
            RangeKeyAndAddend data = rangeKeyAndAddend(node);
            if (verbose)
                dataLog("For ", node, ": ", data, "\n");
            if (!data)
                continue;
            
            Range& range = m_map[data.m_key];
            if (verbose)
                dataLog("    Range: ", range, "\n");
            if (range.m_count) {
                if (data.m_addend > range.m_maxBound) {
                    range.m_maxBound = data.m_addend;
                    range.m_maxOrigin = node->origin.semantic;
                } else if (data.m_addend < range.m_minBound) {
                    range.m_minBound = data.m_addend;
                    range.m_minOrigin = node->origin.semantic;
                }
            } else {
                range.m_maxBound = data.m_addend;
                range.m_minBound = data.m_addend;
                range.m_minOrigin = node->origin.semantic;
                range.m_maxOrigin = node->origin.semantic;
            }
            range.m_count++;
            if (verbose)
                dataLog("    New range: ", range, "\n");
        }
        
        for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
            Node* node = block->at(nodeIndex);
            RangeKeyAndAddend data = rangeKeyAndAddend(node);
            if (!data)
                continue;
            Range range = m_map[data.m_key];
            if (!isValid(data.m_key, range))
                continue;
            
            // Do the hoisting.
            if (!range.m_hoisted) {
                switch (data.m_key.m_kind) {
                case Addition: {
                    if (range.m_minBound < 0) {
                        insertMustAdd(
                            nodeIndex, NodeOrigin(range.m_minOrigin, node->origin.forExit),
                            data.m_key.m_source, range.m_minBound);
                    }
                    if (range.m_maxBound > 0) {
                        insertMustAdd(
                            nodeIndex, NodeOrigin(range.m_maxOrigin, node->origin.forExit),
                            data.m_key.m_source, range.m_maxBound);
                    }
                    break;
                }
                
                case ArrayBounds: {
                    Node* minNode;
                    Node* maxNode;
                    
                    if (!data.m_key.m_source) {
                        minNode = 0;
                        maxNode = m_insertionSet.insertConstant(
                            nodeIndex, range.m_maxOrigin, jsNumber(range.m_maxBound));
                    } else {
                        minNode = insertAdd(
                            nodeIndex, NodeOrigin(range.m_minOrigin, node->origin.forExit),
                            data.m_key.m_source, range.m_minBound, Arith::Unchecked);
                        maxNode = insertAdd(
                            nodeIndex, NodeOrigin(range.m_maxOrigin, node->origin.forExit),
                            data.m_key.m_source, range.m_maxBound, Arith::Unchecked);
                    }
                    
                    if (minNode) {
                        m_insertionSet.insertNode(
                            nodeIndex, SpecNone, CheckInBounds, node->origin,
                            Edge(minNode, Int32Use), Edge(data.m_key.m_key, Int32Use));
                    }
                    m_insertionSet.insertNode(
                        nodeIndex, SpecNone, CheckInBounds, node->origin,
                        Edge(maxNode, Int32Use), Edge(data.m_key.m_key, Int32Use));
                    break;
                }
                
                default:
                    RELEASE_ASSERT_NOT_REACHED();
                }
                
                m_changed = true;
                m_map[data.m_key].m_hoisted = true;
            }
            
            // Do the elimination.
            switch (data.m_key.m_kind) {
            case Addition:
                node->setArithMode(Arith::Unchecked);
                m_changed = true;
                break;
                
            case ArrayBounds:
                node->convertToPhantom();
                m_changed = true;
                break;
                
            default:
                RELEASE_ASSERT_NOT_REACHED();
            }
        }
        
        m_insertionSet.execute(block);
    }
    
    RangeKeyAndAddend rangeKeyAndAddend(Node* node)
    {
        switch (node->op()) {
        case ArithAdd: {
            if (node->arithMode() != Arith::CheckOverflow
                && node->arithMode() != Arith::CheckOverflowAndNegativeZero)
                break;
            if (!node->child2()->isInt32Constant())
                break;
            return RangeKeyAndAddend(
                RangeKey::addition(node->child1()),
                node->child2()->asInt32());
        }
                
        case CheckInBounds: {
            Edge source;
            int32_t addend;
            Node* key = node->child2().node();
            
            Edge index = node->child1();
            
            if (index->isInt32Constant()) {
                source = Edge();
                addend = index->asInt32();
            } else if (
                index->op() == ArithAdd
                && index->isBinaryUseKind(Int32Use)
                && index->child2()->isInt32Constant()) {
                source = index->child1();
                addend = index->child2()->asInt32();
            } else {
                source = index;
                addend = 0;
            }
            
            return RangeKeyAndAddend(RangeKey::arrayBounds(source, key), addend);
        }
            
        default:
            break;
        }
        
        return RangeKeyAndAddend();
    }
    
    bool isValid(const RangeKey& key, const Range& range)
    {
        if (range.m_count < 2)
            return false;
        
        switch (key.m_kind) {
        case ArrayBounds:
            return (range.m_maxBound - range.m_minBound) >= 0;
            
        default:
            return true;
        }
    }
    
    Node* insertAdd(
        unsigned nodeIndex, NodeOrigin origin, Edge source, int32_t addend,
        Arith::Mode arithMode = Arith::CheckOverflow)
    {
        if (!addend)
            return source.node();
        return m_insertionSet.insertNode(
            nodeIndex, source->prediction(), source->result(),
            ArithAdd, origin, OpInfo(arithMode), source,
            m_insertionSet.insertConstantForUse(
                nodeIndex, origin, jsNumber(addend), source.useKind()));
    }
    
    Node* insertMustAdd(
        unsigned nodeIndex, NodeOrigin origin, Edge source, int32_t addend)
    {
        Node* result = insertAdd(nodeIndex, origin, source, addend);
        m_insertionSet.insertNode(
            nodeIndex, SpecNone, HardPhantom, origin, result->defaultEdge());
        return result;
    }
    
    typedef std::unordered_map<RangeKey, Range, HashMethod<RangeKey>> RangeMap;
    RangeMap m_map;
    
    InsertionSet m_insertionSet;
    bool m_changed;
};
    
bool performIntegerCheckCombining(Graph& graph)
{
    SamplingRegion samplingRegion("DFG Integer Check Combining Phase");
    return runPhase<IntegerCheckCombiningPhase>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

