import { Mir, Op, RValue, visitBlockSrcs } from "./mir.ts"; export function eliminateTransientVals(mir: Mir) { for (const fn of mir.fns) { for (const block of fn.blocks) { const cands: { src: RValue; consumer: Op; definition: Op }[] = []; visitBlockSrcs(block, (src, op, i) => { if (src.type !== "local") { return; } const found = block.ops.find((op, fi) => op.kind.type === "assign" && op.kind.dst === src.id && fi < i! ); if (!found) { return; } cands.push({ src, consumer: op!, definition: found! }); }); //console.log(cands); for (const { src: oldsrc, consumer, definition } of cands) { if (oldsrc.type !== "local") { throw new Error(); } if (definition.kind.type !== "assign") { throw new Error(); } const src = definition.kind.src; const k = consumer.kind; switch (k.type) { case "error": break; case "assign": k.src = src; break; case "field": if (same(k.subject, oldsrc)) { k.subject = src; } break; case "assign_field": if (same(k.subject, oldsrc)) { k.subject = src; } if (same(k.src, oldsrc)) { k.src = src; } break; case "index": if (same(k.subject, oldsrc)) { k.subject = src; } if (same(k.index, oldsrc)) { k.index = src; } break; case "assign_index": if (same(k.subject, oldsrc)) { k.subject = src; } if (same(k.index, oldsrc)) { k.index = src; } if (same(k.src, oldsrc)) { k.src = src; } break; case "call_val": if (same(k.subject, oldsrc)) { k.subject = src; } for (let i = 0; i < k.args.length; ++i) { if (same(k.args[i], oldsrc)) { k.args[i] = src; } } break; case "binary": if (same(k.left, oldsrc)) { k.left = src; } if (same(k.right, oldsrc)) { k.right = src; } break; } } } } } function same(a: RValue, b: RValue): boolean { return a.type === "local" && a.type === b.type && a.id === b.id; }