Extract eachBlockOperand to its own visitor
Follow up for #757: - Adds a new visitor which iterates over every Place within a BasicBlock - Remove unused entryBlock binding - Comments
Lauren Tan committed
Nov 9, 2022 at 16:37 UTC
e64ef9e1e04f333f0a820cd698ff039a11efd959
2 files changed
+26
-24
compiler/forget/src/HIR/LeaveSSA.ts
+12
-23
@@ -1,11 +1,14 @@
1
-import { invariant } from "../CompilerError";
2
-import { HIRFunction, Identifier, Place } from "./HIR";
3
-import { eachInstructionOperand, eachTerminalOperand } from "./visitors";
1
+import { BasicBlock, HIRFunction, Identifier, Phi, Place } from "./HIR";
2
+import { eachBlockOperand } from "./visitors";
3
4
+/**
5
+ * Leaves SSA form by building up a mapping of SSA'd {@link Identifier}s to their original
6
+ * {@link Identifier}, then rewriting all {@link Place}s within a {@link BasicBlock} to reference
7
+ * the original id. This allows us to skip adding instruction copies when removing {@link Phi}s,
8
+ * while still allowing shadowing to work.
9
+ */
10
export default function leaveSSA(fn: HIRFunction) {
11
const ir = fn.body;
7
- const entryBlock = ir.blocks.get(ir.entry);
8
- invariant(entryBlock, "expected to find the entry basic block");
12
const originalIdMap = new Map<
13
/* SSA'd id */ Identifier,
14
/* original id*/ Identifier
@@ -25,26 +28,12 @@ export default function leaveSSA(fn: HIRFunction) {
28
return;
29
}
30
28
- function tryRewrite(place: Place) {
29
- const originalId = originalIdMap.get(place.identifier);
30
- if (originalId != null) {
31
- place.identifier = originalId;
32
- }
33
- }
34
-
31
for (const [, block] of ir.blocks) {
36
- for (const instr of block.instructions) {
37
- // LValues also need to be rewritten as they might be declaring or reassigning an identifier
38
- // that was previously SSA'd.
39
- if (instr.lvalue != null) {
40
- tryRewrite(instr.lvalue.place);
32
+ for (const place of eachBlockOperand(block)) {
33
+ const originalId = originalIdMap.get(place.identifier);
34
+ if (originalId != null) {
35
+ place.identifier = originalId;
36
}
42
- for (const place of eachInstructionOperand(instr)) {
43
- tryRewrite(place);
44
- }
45
- }
46
- for (const place of eachTerminalOperand(block.terminal)) {
47
- tryRewrite(place);
37
}
38
}
39
}
compiler/forget/src/HIR/visitors.ts
+14
-1
@@ -6,7 +6,7 @@
6
*/
7
8
import { assertExhaustive } from "../Common/utils";
9
-import { BlockId, Instruction, Place, Terminal } from "./HIR";
9
+import { BasicBlock, BlockId, Instruction, Place, Terminal } from "./HIR";
10
11
export function* eachInstructionOperand(instr: Instruction): Iterable<Place> {
12
const instrValue = instr.value;
@@ -304,3 +304,16 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {
304
}
305
}
306
}
307
+
308
+/**
309
+ * Iterates over all {@link Place}s within a {@link BasicBlock}.
310
+ */
311
+export function* eachBlockOperand(block: BasicBlock): Iterable<Place> {
312
+ for (const instr of block.instructions) {
313
+ yield* eachInstructionOperand(instr);
314
+ if (instr.lvalue != null) {
315
+ yield instr.lvalue.place;
316
+ }
317
+ }
318
+ yield* eachTerminalOperand(block.terminal);
319
+}