mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 19:16:35 +00:00
100 lines
3.5 KiB
TypeScript
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;
|
|
}
|