[hir] Remove unreachable fallthroughs separately from shrink
shrink visits all the fallthroughs even if they are unreachable so this isn't the right place to prune unreachable blocks. This PR moves pruning into a separate pass.
Sathya Gunasekaran committed
Jan 4, 2023 at 18:09 UTC
09bdf3553f9de20ee17fe2e1fc3f6e8ba11efaef
3 files changed
+49
-6
compiler/forget/src/HIR/HIRBuilder.ts
+15
-6
@@ -162,13 +162,15 @@ export default class HIRBuilder {
162
entry: this.#entry,
163
};
164
logHIR("Build (pre-shrink)", ir);
165
- // First reduce indirections and prune unreachable blocks
165
+ // First reduce indirections
166
let shrunk = shrink(ir);
167
logHIR("Build (shrunk)", shrunk);
168
// then convert to reverse postorder
169
const rpo = reversePostorderBlocks(shrunk);
170
+ removeUnreachableFallthroughs(rpo);
171
markInstructionIds(rpo);
172
markPredecessors(rpo);
173
+
174
return rpo;
175
}
176
@@ -356,7 +358,7 @@ export default class HIRBuilder {
358
}
359
360
/**
359
- * Helper to shrink a CFG to eliminate unreachable node and eliminate jump-only blocks.
361
+ * Helper to shrink a CFG eliminate jump-only blocks.
362
*/
363
function shrink(func: HIR): HIR {
364
const gotos = new Map();
@@ -406,8 +408,17 @@ function shrink(func: HIR): HIR {
408
});
409
}
410
411
+ return { blocks, entry: func.entry };
412
+}
413
+
414
+function removeUnreachableFallthroughs(func: HIR) {
415
+ const visited: Set<BlockId> = new Set();
416
+ for (const [_, block] of func.blocks) {
417
+ visited.add(block.id);
418
+ }
419
+
420
// Cleanup any fallthrough blocks that weren't visited
410
- for (const block of blocks.values()) {
421
+ for (const [_, block] of func.blocks) {
422
if (
423
block.terminal.kind === "if" ||
424
block.terminal.kind === "switch" ||
@@ -415,15 +426,13 @@ function shrink(func: HIR): HIR {
426
) {
427
if (
428
block.terminal.fallthrough !== null &&
418
- !blocks.has(block.terminal.fallthrough)
429
+ !visited.has(block.terminal.fallthrough)
430
) {
431
block.terminal.fallthrough = null;
432
}
433
}
434
}
424
- return { blocks, entry: func.entry };
435
}
426
-
436
/**
437
* Converts the graph to reverse-postorder, with predecessor blocks appearing
438
* before successors except in the case of back links (ie loops).
compiler/forget/src/__tests__/fixtures/hir/return-conditional.expect.md
new
+27
@@ -0,0 +1,27 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function foo(a, b) {
6
+ if (a == null) {
7
+ return null;
8
+ } else {
9
+ return b;
10
+ }
11
+}
12
+
13
+```
14
+
15
+## Code
16
+
17
+```javascript
18
+function foo(a, b) {
19
+ if (a == null) {
20
+ return null;
21
+ } else {
22
+ return b;
23
+ }
24
+}
25
+
26
+```
27
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/return-conditional.js
new
+7
@@ -0,0 +1,7 @@
1
+function foo(a, b) {
2
+ if (a == null) {
3
+ return null;
4
+ } else {
5
+ return b;
6
+ }
7
+}