slige/compiler/middle/elim_transient_vals.ts
2025-01-17 11:50:14 +01:00

100 lines
3.5 KiB
TypeScript

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;
}