package cd.transform.optimizers;

import cd.ir.Ast;
import cd.ir.BasicBlock;
import cd.ir.ControlFlowGraph;

import java.util.ListIterator;

public class BlockRemoval implements IOptimizer {
	@Override
	public boolean go(ControlFlowGraph cfg) {
		boolean changed = false;
		ListIterator<BasicBlock> iterator = cfg.allBlocks.listIterator();
		while (iterator.hasNext()) {
			BasicBlock block = iterator.next();

			if (block == cfg.start || block == cfg.end)
				continue;

			if (block.condition == null
					&& (block.stmts.isEmpty() || (block.stmts.size() == 1
					&& block.stmts.get(0) instanceof Ast.Nop))) {
				// The block is empty or has a Nop, there is no branch
				// Therefore the predecessors can be directly linked to the successor
				BasicBlock successor = block.successors.get(0);
				boolean cancelDeletion = false;
				for (BasicBlock pred : block.predecessors) {
					if (pred.condition != null) {
						cancelDeletion = true;
						break;
					}
					int posInPred = pred.successors.indexOf(block);
					pred.successors.set(posInPred, successor);
				}
				if (cancelDeletion) continue;
				for (BasicBlock succ : block.successors) {
					succ.predecessors.remove(block);
					succ.predecessors.addAll(block.predecessors);
				}
				iterator.remove();
				changed = true;
			} else if (block.condition != null
					&& block.trueSuccessor() == block.falseSuccessor()) {
				// There is a condition and both successors are equal, therefore we can remove it
				BasicBlock successor = block.trueSuccessor();
				block.successors.clear();
				block.successors.add(successor);
				block.condition = null;
				changed = true;
			}
		}

		return changed;
	}
}
