/*
 * Copyright 2016-2020 Arm Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "spirv_cfg.hpp"
#include "spirv_cross.hpp"
#include <algorithm>
#include <assert.h>

using namespace std;

namespace SPIRV_CROSS_NAMESPACE
{
CFG::CFG(Compiler &compiler_, const SPIRFunction &func_)
    : compiler(compiler_)
    , func(func_)
{
	build_post_order_visit_order();
	build_immediate_dominators();
}

uint32_t CFG::find_common_dominator(uint32_t a, uint32_t b) const
{
	while (a != b)
	{
		if (get_visit_order(a) < get_visit_order(b))
			a = get_immediate_dominator(a);
		else
			b = get_immediate_dominator(b);
	}
	return a;
}

void CFG::build_immediate_dominators()
{
	// Traverse the post-order in reverse and build up the immediate dominator tree.
	immediate_dominators.clear();
	immediate_dominators[func.entry_block] = func.entry_block;

	for (auto i = post_order.size(); i; i--)
	{
		uint32_t block = post_order[i - 1];
		auto &pred = preceding_edges[block];
		if (pred.empty()) // This is for the entry block, but we've already set up the dominators.
			continue;

		for (auto &edge : pred)
		{
			if (immediate_dominators[block])
			{
				assert(immediate_dominators[edge]);
				immediate_dominators[block] = find_common_dominator(immediate_dominators[block], edge);
			}
			else
				immediate_dominators[block] = edge;
		}
	}
}

bool CFG::is_back_edge(uint32_t to) const
{
	// We have a back edge if the visit order is set with the temporary magic value 0.
	// Crossing edges will have already been recorded with a visit order.
	auto itr = visit_order.find(to);
	return itr != end(visit_order) && itr->second.get() == 0;
}

bool CFG::has_visited_forward_edge(uint32_t to) const
{
	// If > 0, we have visited the edge already, and this is not a back edge branch.
	auto itr = visit_order.find(to);
	return itr != end(visit_order) && itr->second.get() > 0;
}

bool CFG::post_order_visit(uint32_t block_id)
{
	// If we have already branched to this block (back edge), stop recursion.
	// If our branches are back-edges, we do not record them.
	// We have to record crossing edges however.
	if (has_visited_forward_edge(block_id))
		return true;
	else if (is_back_edge(block_id))
		return false;

	// Block back-edges from recursively revisiting ourselves.
	visit_order[block_id].get() = 0;

	auto &block = compiler.get<SPIRBlock>(block_id);

	// If this is a loop header, add an implied branch to the merge target.
	// This is needed to avoid annoying cases with do { ... } while(false) loops often generated by inliners.
	// To the CFG, this is linear control flow, but we risk picking the do/while scope as our dominating block.
	// This makes sure that if we are accessing a variable outside the do/while, we choose the loop header as dominator.
	// We could use has_visited_forward_edge, but this break code-gen where the merge block is unreachable in the CFG.

	// Make a point out of visiting merge target first. This is to make sure that post visit order outside the loop
	// is lower than inside the loop, which is going to be key for some traversal algorithms like post-dominance analysis.
	// For selection constructs true/false blocks will end up visiting the merge block directly and it works out fine,
	// but for loops, only the header might end up actually branching to merge block.
	if (block.merge == SPIRBlock::MergeLoop && post_order_visit(block.merge_block))
		add_branch(block_id, block.merge_block);

	// First visit our branch targets.
	switch (block.terminator)
	{
	case SPIRBlock::Direct:
		if (post_order_visit(block.next_block))
			add_branch(block_id, block.next_block);
		break;

	case SPIRBlock::Select:
		if (post_order_visit(block.true_block))
			add_branch(block_id, block.true_block);
		if (post_order_visit(block.false_block))
			add_branch(block_id, block.false_block);
		break;

	case SPIRBlock::MultiSelect:
		for (auto &target : block.cases)
		{
			if (post_order_visit(target.block))
				add_branch(block_id, target.block);
		}
		if (block.default_block && post_order_visit(block.default_block))
			add_branch(block_id, block.default_block);
		break;

	default:
		break;
	}

	// If this is a selection merge, add an implied branch to the merge target.
	// This is needed to avoid cases where an inner branch dominates the outer branch.
	// This can happen if one of the branches exit early, e.g.:
	// if (cond) { ...; break; } else { var = 100 } use_var(var);
	// We can use the variable without a Phi since there is only one possible parent here.
	// However, in this case, we need to hoist out the inner variable to outside the branch.
	// Use same strategy as loops.
	if (block.merge == SPIRBlock::MergeSelection && post_order_visit(block.next_block))
	{
		// If there is only one preceding edge to the merge block and it's not ourselves, we need a fixup.
		// Add a fake branch so any dominator in either the if (), or else () block, or a lone case statement
		// will be hoisted out to outside the selection merge.
		// If size > 1, the variable will be automatically hoisted, so we should not mess with it.
		// The exception here is switch blocks, where we can have multiple edges to merge block,
		// all coming from same scope, so be more conservative in this case.
		// Adding fake branches unconditionally breaks parameter preservation analysis,
		// which looks at how variables are accessed through the CFG.
		auto pred_itr = preceding_edges.find(block.next_block);
		if (pred_itr != end(preceding_edges))
		{
			auto &pred = pred_itr->second;
			auto succ_itr = succeeding_edges.find(block_id);
			size_t num_succeeding_edges = 0;
			if (succ_itr != end(succeeding_edges))
				num_succeeding_edges = succ_itr->second.size();

			if (block.terminator == SPIRBlock::MultiSelect && num_succeeding_edges == 1)
			{
				// Multiple branches can come from the same scope due to "break;", so we need to assume that all branches
				// come from same case scope in worst case, even if there are multiple preceding edges.
				// If we have more than one succeeding edge from the block header, it should be impossible
				// to have a dominator be inside the block.
				// Only case this can go wrong is if we have 2 or more edges from block header and
				// 2 or more edges to merge block, and still have dominator be inside a case label.
				if (!pred.empty())
					add_branch(block_id, block.next_block);
			}
			else
			{
				if (pred.size() == 1 && *pred.begin() != block_id)
					add_branch(block_id, block.next_block);
			}
		}
		else
		{
			// If the merge block does not have any preceding edges, i.e. unreachable, hallucinate it.
			// We're going to do code-gen for it, and domination analysis requires that we have at least one preceding edge.
			add_branch(block_id, block.next_block);
		}
	}

	// Then visit ourselves. Start counting at one, to let 0 be a magic value for testing back vs. crossing edges.
	visit_order[block_id].get() = ++visit_count;
	post_order.push_back(block_id);
	return true;
}

void CFG::build_post_order_visit_order()
{
	uint32_t block = func.entry_block;
	visit_count = 0;
	visit_order.clear();
	post_order.clear();
	post_order_visit(block);
}

void CFG::add_branch(uint32_t from, uint32_t to)
{
	const auto add_unique = [](SmallVector<uint32_t> &l, uint32_t value) {
		auto itr = find(begin(l), end(l), value);
		if (itr == end(l))
			l.push_back(value);
	};
	add_unique(preceding_edges[to], from);
	add_unique(succeeding_edges[from], to);
}

uint32_t CFG::find_loop_dominator(uint32_t block_id) const
{
	while (block_id != SPIRBlock::NoDominator)
	{
		auto itr = preceding_edges.find(block_id);
		if (itr == end(preceding_edges))
			return SPIRBlock::NoDominator;
		if (itr->second.empty())
			return SPIRBlock::NoDominator;

		uint32_t pred_block_id = SPIRBlock::NoDominator;
		bool ignore_loop_header = false;

		// If we are a merge block, go directly to the header block.
		// Only consider a loop dominator if we are branching from inside a block to a loop header.
		// NOTE: In the CFG we forced an edge from header to merge block always to support variable scopes properly.
		for (auto &pred : itr->second)
		{
			auto &pred_block = compiler.get<SPIRBlock>(pred);
			if (pred_block.merge == SPIRBlock::MergeLoop && pred_block.merge_block == ID(block_id))
			{
				pred_block_id = pred;
				ignore_loop_header = true;
				break;
			}
			else if (pred_block.merge == SPIRBlock::MergeSelection && pred_block.next_block == ID(block_id))
			{
				pred_block_id = pred;
				break;
			}
		}

		// No merge block means we can just pick any edge. Loop headers dominate the inner loop, so any path we
		// take will lead there.
		if (pred_block_id == SPIRBlock::NoDominator)
			pred_block_id = itr->second.front();

		block_id = pred_block_id;

		if (!ignore_loop_header && block_id)
		{
			auto &block = compiler.get<SPIRBlock>(block_id);
			if (block.merge == SPIRBlock::MergeLoop)
				return block_id;
		}
	}

	return block_id;
}

bool CFG::node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) const
{
	// Walk backwards, starting from "to" block.
	// Only follow pred edges if they have a 1:1 relationship, or a merge relationship.
	// If we cannot find a path to "from", we must assume that to is inside control flow in some way.

	auto &from_block = compiler.get<SPIRBlock>(from);
	BlockID ignore_block_id = 0;
	if (from_block.merge == SPIRBlock::MergeLoop)
		ignore_block_id = from_block.merge_block;

	while (to != from)
	{
		auto pred_itr = preceding_edges.find(to);
		if (pred_itr == end(preceding_edges))
			return false;

		DominatorBuilder builder(*this);
		for (auto &edge : pred_itr->second)
			builder.add_block(edge);

		uint32_t dominator = builder.get_dominator();
		if (dominator == 0)
			return false;

		auto &dom = compiler.get<SPIRBlock>(dominator);

		bool true_path_ignore = false;
		bool false_path_ignore = false;
		if (ignore_block_id && dom.terminator == SPIRBlock::Select)
		{
			auto &true_block = compiler.get<SPIRBlock>(dom.true_block);
			auto &false_block = compiler.get<SPIRBlock>(dom.false_block);
			auto &ignore_block = compiler.get<SPIRBlock>(ignore_block_id);
			true_path_ignore = compiler.execution_is_branchless(true_block, ignore_block);
			false_path_ignore = compiler.execution_is_branchless(false_block, ignore_block);
		}

		if ((dom.merge == SPIRBlock::MergeSelection && dom.next_block == to) ||
		    (dom.merge == SPIRBlock::MergeLoop && dom.merge_block == to) ||
		    (dom.terminator == SPIRBlock::Direct && dom.next_block == to) ||
		    (dom.terminator == SPIRBlock::Select && dom.true_block == to && false_path_ignore) ||
		    (dom.terminator == SPIRBlock::Select && dom.false_block == to && true_path_ignore))
		{
			// Allow walking selection constructs if the other branch reaches out of a loop construct.
			// It cannot be in-scope anymore.
			to = dominator;
		}
		else
			return false;
	}

	return true;
}

DominatorBuilder::DominatorBuilder(const CFG &cfg_)
    : cfg(cfg_)
{
}

void DominatorBuilder::add_block(uint32_t block)
{
	if (!cfg.get_immediate_dominator(block))
	{
		// Unreachable block via the CFG, we will never emit this code anyways.
		return;
	}

	if (!dominator)
	{
		dominator = block;
		return;
	}

	if (block != dominator)
		dominator = cfg.find_common_dominator(block, dominator);
}

void DominatorBuilder::lift_continue_block_dominator()
{
	// It is possible for a continue block to be the dominator of a variable is only accessed inside the while block of a do-while loop.
	// We cannot safely declare variables inside a continue block, so move any variable declared
	// in a continue block to the entry block to simplify.
	// It makes very little sense for a continue block to ever be a dominator, so fall back to the simplest
	// solution.

	if (!dominator)
		return;

	auto &block = cfg.get_compiler().get<SPIRBlock>(dominator);
	auto post_order = cfg.get_visit_order(dominator);

	// If we are branching to a block with a higher post-order traversal index (continue blocks), we have a problem
	// since we cannot create sensible GLSL code for this, fallback to entry block.
	bool back_edge_dominator = false;
	switch (block.terminator)
	{
	case SPIRBlock::Direct:
		if (cfg.get_visit_order(block.next_block) > post_order)
			back_edge_dominator = true;
		break;

	case SPIRBlock::Select:
		if (cfg.get_visit_order(block.true_block) > post_order)
			back_edge_dominator = true;
		if (cfg.get_visit_order(block.false_block) > post_order)
			back_edge_dominator = true;
		break;

	case SPIRBlock::MultiSelect:
		for (auto &target : block.cases)
		{
			if (cfg.get_visit_order(target.block) > post_order)
				back_edge_dominator = true;
		}
		if (block.default_block && cfg.get_visit_order(block.default_block) > post_order)
			back_edge_dominator = true;
		break;

	default:
		break;
	}

	if (back_edge_dominator)
		dominator = cfg.get_function().entry_block;
}
} // namespace SPIRV_CROSS_NAMESPACE
