/*
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.graalvm.compiler.phases.contract;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.DebugCounter;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.VerificationError;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
import org.graalvm.compiler.nodes.spi.NodeCostProvider;
import org.graalvm.compiler.phases.schedule.SchedulePhase;

import jdk.vm.ci.meta.ResolvedJavaMethod;

public class NodeCostUtil {

    private static final DebugCounter sizeComputationCount = Debug.counter("GraphCostComputationCount_Size");
    private static final DebugCounter sizeVerificationCount = Debug.counter("GraphCostVerificationCount_Size");

    @SuppressWarnings("try")
    public static int computeGraphSize(StructuredGraph graph, NodeCostProvider nodeCostProvider) {
        sizeComputationCount.increment();
        int size = 0;
        for (Node n : graph.getNodes()) {
            size += nodeCostProvider.getEstimatedCodeSize(n);
        }
        assert size >= 0;
        return size;
    }

    @SuppressWarnings("try")
    public static double computeGraphCycles(StructuredGraph graph, NodeCostProvider nodeCostProvider, boolean fullSchedule) {
        Function<Block, Iterable<? extends Node>> blockToNodes;
        ControlFlowGraph cfg;
        if (fullSchedule) {
            SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
            schedule.apply(graph);
            cfg = graph.getLastSchedule().getCFG();
            blockToNodes = b -> graph.getLastSchedule().getBlockToNodesMap().get(b);
        } else {
            cfg = ControlFlowGraph.compute(graph, true, true, false, false);
            BlockMap<List<FixedNode>> nodes = new BlockMap<>(cfg);
            for (Block b : cfg.getBlocks()) {
                ArrayList<FixedNode> curNodes = new ArrayList<>();
                for (FixedNode node : b.getNodes()) {
                    curNodes.add(node);
                }
                nodes.put(b, curNodes);
            }
            blockToNodes = b -> nodes.get(b);
        }
        double weightedCycles = 0D;
        try (Debug.Scope s = Debug.scope("NodeCostSummary")) {
            for (Block block : cfg.getBlocks()) {
                for (Node n : blockToNodes.apply(block)) {
                    double probWeighted = nodeCostProvider.getEstimatedCPUCycles(n) * block.probability();
                    assert Double.isFinite(probWeighted);
                    weightedCycles += probWeighted;
                    if (Debug.isLogEnabled()) {
                        Debug.log("Node %s contributes cycles:%f size:%d to graph %s [block prob:%f]", n, nodeCostProvider.getEstimatedCPUCycles(n) * block.probability(),
                                        nodeCostProvider.getEstimatedCodeSize(n), graph, block.probability());
                    }
                }
            }
        }
        assert weightedCycles >= 0D;
        assert Double.isFinite(weightedCycles);
        return weightedCycles;
    }

    private static int deltaCompare(double a, double b, double delta) {
        if (Math.abs(a - b) <= delta) {
            return 0;
        }
        return Double.compare(a, b);
    }

    /**
     * Factor to control the "imprecision" of the before - after relation when verifying phase
     * effects. If the cost model is perfect the best theoretical value is 0.0D (Ignoring the fact
     * that profiling information is not reliable and thus the, probability based, profiling view on
     * a graph is different than the reality).
     */
    private static final double DELTA = 0.001D;

    public static void phaseFulfillsSizeContract(StructuredGraph graph, int codeSizeBefore, int codeSizeAfter, PhaseSizeContract contract) {
        sizeVerificationCount.increment();
        final double codeSizeIncrease = contract.codeSizeIncrease();
        final double graphSizeDelta = codeSizeBefore * DELTA;
        if (deltaCompare(codeSizeAfter, codeSizeBefore * codeSizeIncrease, graphSizeDelta) > 0) {
            ResolvedJavaMethod method = graph.method();
            double increase = (double) codeSizeAfter / (double) codeSizeBefore;
            throw new VerificationError("Phase %s expects to increase code size by at most a factor of %.2f but an increase of %.2f was seen (code size before: %d, after: %d)%s",
                            contract.contractorName(), codeSizeIncrease, increase, codeSizeBefore, codeSizeAfter,
                            method != null ? " when compiling method " + method.format("%H.%n(%p)") + "." : ".");
        }
    }

}
