import { createCfg } from "./cfg.ts";
import { Block, Mir } from "./mir.ts";

export function eliminateOnlyChildsBlocks(mir: Mir) {
    for (const fn of mir.fns) {
        const cfg = createCfg(fn);

        const candidates: { parent: Block; child: Block }[] = [];

        for (const block of fn.blocks) {
            const children = cfg.children(block);
            if (children.length !== 1) {
                continue;
            }
            if (cfg.parents(children[0]).length !== 1) {
                continue;
            }
            candidates.push({ parent: block, child: children[0] });
        }

        const elimIndices: number[] = [];

        for (const { parent, child } of candidates) {
            parent.ops.push(...child.ops);
            parent.ter = child.ter;
            elimIndices.push(cfg.index(child));
        }

        for (const i of elimIndices.toReversed()) {
            fn.blocks.splice(i, 1);
        }
    }
}

export function eliminateUnreachableBlocks(mir: Mir) {
    for (const fn of mir.fns) {
        const cfg = createCfg(fn);

        const candidates: Block[] = [];

        for (const block of fn.blocks) {
            if (block.id === fn.entry) {
                continue;
            }
            if (cfg.parents(block).length !== 0) {
                continue;
            }
            candidates.push(block);
        }

        for (
            const i of candidates
                .map((block) => cfg.index(block))
                .toReversed()
        ) {
            fn.blocks.splice(i, 1);
        }
    }
}