/*
 * 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.
 */

/*
 * At your option, you may choose to accept this material under either:
 *  1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
 *  2. The MIT License, found at <http://opensource.org/licenses/MIT>.
 * SPDX-License-Identifier: Apache-2.0 OR MIT.
 */

#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
