Add and use eachTerminalSuccessor()
Joe Savona committed
Nov 8, 2022 at 14:45 UTC
2a049044bbd0ed76ccc88f6c9d34783158b444b3
25 files changed
+101
-109
compiler/forget/src/HIR/EnterSSA.ts
+7
-17
@@ -2,7 +2,6 @@ import { assertExhaustive } from "../Common/utils";
2
import { invariant } from "../CompilerError";
3
import {
4
BasicBlock,
5
- BlockId,
5
HIRFunction,
6
Identifier,
7
Instruction,
@@ -11,6 +10,7 @@ import {
10
} from "./HIR";
11
import { Environment } from "./HIRBuilder";
12
import { printIdentifier } from "./PrintHIR";
13
+import { eachTerminalSuccessor } from "./visitors";
14
15
type IncompletePhi = {
16
oldId: Identifier;
@@ -186,7 +186,7 @@ export default function enterSSA(func: HIRFunction, env: Environment) {
186
}
187
188
for (const instr of block.instructions) {
189
- rewriteUses(instr, builder);
189
+ rewriteInstructionUses(instr, builder);
190
191
if (instr.lvalue != null) {
192
const oldPlace = instr.lvalue.place;
@@ -200,9 +200,9 @@ export default function enterSSA(func: HIRFunction, env: Environment) {
200
}
201
}
202
203
- const outputs = rewriteUsesAndCollectOutputs(block, builder);
204
- const outputBlocks = outputs.map((id) => func.body.blocks.get(id)!);
205
- for (const output of outputBlocks) {
203
+ rewriteTerminalOperands(block, builder);
204
+ for (const outputId of eachTerminalSuccessor(block.terminal)) {
205
+ const output = func.body.blocks.get(outputId)!;
206
let count;
207
if (builder.unsealedPreds.has(output)) {
208
count = builder.unsealedPreds.get(output)! - 1;
@@ -218,11 +218,7 @@ export default function enterSSA(func: HIRFunction, env: Environment) {
218
}
219
}
220
221
-function rewriteUsesAndCollectOutputs(
222
- block: BasicBlock,
223
- builder: SSABuilder
224
-): Array<BlockId> {
225
- const outputs: Array<BlockId> = [];
221
+function rewriteTerminalOperands(block: BasicBlock, builder: SSABuilder): void {
222
const { terminal } = block;
223
switch (terminal.kind) {
224
case "return":
@@ -233,14 +229,11 @@ function rewriteUsesAndCollectOutputs(
229
break;
230
}
231
case "goto": {
236
- outputs.push(terminal.block);
232
break;
233
}
234
case "if": {
235
const { consequent, alternate } = terminal;
236
terminal.test = builder.getPlace(terminal.test);
242
- outputs.push(alternate);
243
- outputs.push(consequent);
237
break;
238
}
239
case "switch": {
@@ -250,7 +243,6 @@ function rewriteUsesAndCollectOutputs(
243
if (case_.test) {
244
case_.test = builder.getPlace(case_.test);
245
}
253
- outputs.push(case_.block);
246
}
247
break;
248
}
@@ -261,11 +253,9 @@ function rewriteUsesAndCollectOutputs(
253
);
254
}
255
}
264
-
265
- return outputs;
256
}
257
268
-function rewriteUses(instr: Instruction, builder: SSABuilder) {
258
+function rewriteInstructionUses(instr: Instruction, builder: SSABuilder) {
259
const instrValue = instr.value;
260
261
switch (instrValue.kind) {
compiler/forget/src/HIR/HIRBuilder.ts
+3
-29
@@ -19,7 +19,7 @@ import {
19
Terminal,
20
} from "./HIR";
21
import { printInstruction } from "./PrintHIR";
22
-import { mapTerminalSuccessors } from "./visitors";
22
+import { eachTerminalSuccessor, mapTerminalSuccessors } from "./visitors";
23
24
// *******************************************************************************************
25
// *******************************************************************************************
@@ -512,34 +512,8 @@ function markPredecessors(func: HIR) {
512
513
const { terminal } = block;
514
515
- switch (terminal.kind) {
516
- case "return":
517
- case "throw": {
518
- break;
519
- }
520
- case "goto": {
521
- visit(terminal.block, block);
522
- break;
523
- }
524
- case "if": {
525
- const { consequent, alternate } = terminal;
526
- visit(alternate, block);
527
- visit(consequent, block);
528
- break;
529
- }
530
- case "switch": {
531
- const { cases } = terminal;
532
- for (const case_ of [...cases]) {
533
- visit(case_.block, block);
534
- }
535
- break;
536
- }
537
- default: {
538
- assertExhaustive(
539
- terminal,
540
- `Unexpected terminal kind '${(terminal as any).kind}'`
541
- );
542
- }
515
+ for (const successor of eachTerminalSuccessor(terminal)) {
516
+ visit(successor, block);
517
}
518
}
519
visit(func.entry, null);
compiler/forget/src/HIR/InferReferenceEffects.ts
+5
-14
@@ -16,15 +16,14 @@ import {
16
InstructionValue,
17
Phi,
18
Place,
19
- Terminal,
19
ValueKind,
20
} from "./HIR";
21
+import { printMixedHIR, printPlace, printSourceLocation } from "./PrintHIR";
22
import {
23
eachInstructionOperand,
24
eachTerminalOperand,
25
- mapTerminalSuccessors,
25
+ eachTerminalSuccessor,
26
} from "./visitors";
27
-import { printMixedHIR, printPlace, printSourceLocation } from "./PrintHIR";
27
28
/**
29
* For every usage of a value in the given function, infers the effect or action
@@ -137,17 +136,9 @@ export default function inferReferenceEffects(fn: HIRFunction) {
136
const environment = incomingEnvironment.clone();
137
inferBlock(environment, block);
138
140
- // TODO: add a `forEachTerminalSuccessor` helper, we don't actually want the result
141
- // here
142
- const _ = mapTerminalSuccessors(
143
- block.terminal,
144
- (nextBlockId, isFallthrough) => {
145
- if (!isFallthrough) {
146
- queue(nextBlockId, environment);
147
- }
148
- return nextBlockId;
149
- }
150
- );
139
+ for (const nextBlockId of eachTerminalSuccessor(block.terminal)) {
140
+ queue(nextBlockId, environment);
141
+ }
142
}
143
}
144
}
compiler/forget/src/HIR/visitors.ts
+37
@@ -129,6 +129,43 @@ export function mapTerminalSuccessors(
129
}
130
}
131
132
+/**
133
+ * Iterates over the successor block ids of the provided terminal. The function is called
134
+ * specifically for the successors that define the standard control flow, and not
135
+ * pseduo-successors such as fallthroughs.
136
+ */
137
+export function* eachTerminalSuccessor(terminal: Terminal): Iterable<BlockId> {
138
+ switch (terminal.kind) {
139
+ case "goto": {
140
+ yield terminal.block;
141
+ break;
142
+ }
143
+ case "if": {
144
+ yield terminal.consequent;
145
+ yield terminal.alternate;
146
+ break;
147
+ }
148
+ case "switch": {
149
+ for (const case_ of terminal.cases) {
150
+ yield case_.block;
151
+ }
152
+ break;
153
+ }
154
+ case "return": {
155
+ break;
156
+ }
157
+ case "throw": {
158
+ break;
159
+ }
160
+ default: {
161
+ assertExhaustive(
162
+ terminal,
163
+ `Unexpected terminal kind '${(terminal as any as Terminal).kind}'`
164
+ );
165
+ }
166
+ }
167
+}
168
+
169
export function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {
170
switch (terminal.kind) {
171
case "if": {
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+4
-4
@@ -43,7 +43,7 @@ bb0:
43
[6] Const mutate max$32 = Call mutate Math$8.max(read $31, read maxItems$28)
44
Goto bb1
45
bb1:
46
- predecessor blocks: bb0 bb4 bb7
46
+ predecessor blocks: bb0 bb7 bb4
47
If (read items$27) then:bb3 else:bb2
48
bb3:
49
predecessor blocks: bb1
@@ -59,8 +59,8 @@ bb9:
59
[10] Const mutate $39 = Call mutate seen$30.has(mutate item$10)
60
Goto bb7
61
bb7:
62
- predecessor blocks: bb9 bb8
63
- $40: phi(bb9: $39, bb8: $37)
62
+ predecessor blocks: bb8 bb9
63
+ $40: phi(bb8: $37, bb9: $39)
64
If (read $40) then:bb1 else:bb4
65
bb4:
66
predecessor blocks: bb7
@@ -71,7 +71,7 @@ bb4:
71
[15] Const mutate $49 = Binary read renderedItems$29.length >= read max$32
72
If (read $49) then:bb2 else:bb1
73
bb2:
74
- predecessor blocks: bb1 bb4
74
+ predecessor blocks: bb4 bb1
75
[16] Const mutate count$52 = read renderedItems$29.length
76
[17] Const mutate $53 = "div"
77
[18] Const mutate $54 = "\n "
compiler/forget/src/__tests__/fixtures/hir/conditional-break.expect.md
+2
-2
@@ -118,7 +118,7 @@ bb2:
118
[3] Call mutate a$4.push(read props$3.c)
119
Goto bb1
120
bb1:
121
- predecessor blocks: bb0 bb2
121
+ predecessor blocks: bb2 bb0
122
[4] Call mutate a$4.push(read props$3.d)
123
Return freeze a$4
124
```
@@ -218,7 +218,7 @@ bb2:
218
[3] Call mutate a$4.push(read props$3.c)
219
Goto bb1
220
bb1:
221
- predecessor blocks: bb2 bb0
221
+ predecessor blocks: bb0 bb2
222
[4] Call mutate a$4.push(read props$3.d)
223
Return freeze a$4
224
```
compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md
+4
-4
@@ -75,14 +75,14 @@ bb2:
75
[3] Call mutate a$7.push(read props$6.p0)
76
Goto bb1
77
bb1:
78
- predecessor blocks: bb0 bb2
78
+ predecessor blocks: bb2 bb0
79
If (read props$6.p1) then:bb4 else:bb3
80
bb4:
81
predecessor blocks: bb1
82
[4] Call mutate b$8.push(read props$6.p2)
83
Goto bb3
84
bb3:
85
- predecessor blocks: bb1 bb4
85
+ predecessor blocks: bb4 bb1
86
[5] Const mutate $16 = JSX <read Foo$4 a={freeze a$7} b={freeze b$8} ></read Foo$4>
87
Return read $16
88
```
@@ -120,14 +120,14 @@ bb2:
120
[4] Call mutate a$9.push(read props$8.p0)
121
Goto bb1
122
bb1:
123
- predecessor blocks: bb0 bb2
123
+ predecessor blocks: bb2 bb0
124
If (read props$8.p1) then:bb4 else:bb3
125
bb4:
126
predecessor blocks: bb1
127
[5] Call mutate b$10.push(read props$8.p2)
128
Goto bb3
129
bb3:
130
- predecessor blocks: bb1 bb4
130
+ predecessor blocks: bb4 bb1
131
[6] Const mutate $19 = JSX <read Foo$6 a={freeze a$9} b={freeze b$10} ></read Foo$6>
132
Return read $19
133
```
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+2
-2
@@ -39,8 +39,8 @@ bb3:
39
[5] Reassign mutate a$12 = Array []
40
Goto bb1
41
bb1:
42
- predecessor blocks: bb3 bb2
43
- a$14: phi(bb3: a$12, bb2: a$11)
42
+ predecessor blocks: bb2 bb3
43
+ a$14: phi(bb2: a$11, bb3: a$12)
44
[6] Call read useFreeze$5(freeze a$14)
45
[7] Call read useFreeze$5(read a$14)
46
[8] Call mutate call$6(read a$14)
compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md
+1
-1
@@ -106,7 +106,7 @@ bb2:
106
[4] Call mutate mutate$5(mutate b$10)
107
Goto bb1
108
bb1:
109
- predecessor blocks: bb0 bb2
109
+ predecessor blocks: bb2 bb0
110
[5] Const mutate $14 = JSX <read Foo$6 a={freeze a$9} b={freeze b$10} ></read Foo$6>
111
Return read $14
112
```
compiler/forget/src/__tests__/fixtures/hir/interdependent-across-if.expect.md
+1
-1
@@ -84,7 +84,7 @@ bb2:
84
[3] Call mutate foo$5(mutate a$9, mutate b$10)
85
Goto bb1
86
bb1:
87
- predecessor blocks: bb0 bb2
87
+ predecessor blocks: bb2 bb0
88
[4] Const mutate $14 = JSX <read Foo$6 a={freeze a$9} b={freeze b$10} ></read Foo$6>
89
Return read $14
90
```
compiler/forget/src/__tests__/fixtures/hir/logical-expression.expect.md
+6
-6
@@ -34,8 +34,8 @@ bb3:
34
[3] Const mutate $7 = read $5
35
Goto bb1
36
bb1:
37
- predecessor blocks: bb3 bb2
38
- $8: phi(bb3: $7, bb2: $6)
37
+ predecessor blocks: bb2 bb3
38
+ $8: phi(bb2: $6, bb3: $7)
39
Return freeze $8
40
```
41
@@ -67,8 +67,8 @@ bb3:
67
[3] Const mutate $7 = Call mutate g$4()
68
Goto bb1
69
bb1:
70
- predecessor blocks: bb3 bb2
71
- $8: phi(bb3: $7, bb2: $6)
70
+ predecessor blocks: bb2 bb3
71
+ $8: phi(bb2: $6, bb3: $7)
72
Return freeze $8
73
```
74
@@ -102,8 +102,8 @@ bb3:
102
[5] Const mutate $13 = Call mutate g$7()
103
Goto bb1
104
bb1:
105
- predecessor blocks: bb3 bb2
106
- $14: phi(bb3: $13, bb2: $12)
105
+ predecessor blocks: bb2 bb3
106
+ $14: phi(bb2: $12, bb3: $13)
107
Return freeze $14
108
```
109
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+5
-5
@@ -97,11 +97,11 @@ bb3:
97
[12] Const mutate $29 = Call mutate cond$8(mutate a$21)
98
If (read $29) then:bb2 else:bb1
99
bb2:
100
- predecessor blocks: bb1 bb3
101
- a$30: phi(bb1: a$18, bb3: a$21)
102
- b$31: phi(bb1: b$20, bb3: b$23)
103
- c$32: phi(bb1: c$22, bb3: c$25)
104
- d$33[-1:14]: phi(bb1: d$24, bb3: d$26)
100
+ predecessor blocks: bb3 bb1
101
+ a$30: phi(bb3: a$21, bb1: a$18)
102
+ b$31: phi(bb3: b$23, bb1: b$20)
103
+ c$32: phi(bb3: c$25, bb1: c$22)
104
+ d$33[-1:14]: phi(bb3: d$26, bb1: d$24)
105
If (read a$30) then:bb7 else:bb7
106
bb7:
107
predecessor blocks: bb2
compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md
+1
-1
@@ -83,7 +83,7 @@ bb3:
83
[7] Const mutate $21 = Call mutate cond$7(mutate a$12)
84
If (read $21) then:bb2 else:bb1
85
bb2:
86
- predecessor blocks: bb1 bb3
86
+ predecessor blocks: bb3 bb1
87
If (read a$12) then:bb7 else:bb7
88
bb7:
89
predecessor blocks: bb2
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+2
-2
@@ -32,8 +32,8 @@ bb2:
32
[4] Reassign mutate x$9 = Array []
33
Goto bb1
34
bb1:
35
- predecessor blocks: bb0 bb2
36
- x$11: phi(bb0: x$7, bb2: x$9)
35
+ predecessor blocks: bb2 bb0
36
+ x$11: phi(bb2: x$9, bb0: x$7)
37
[5] Let mutate _$12 = JSX <read Component$0 x={freeze x$11} ></read Component$0>
38
[6] Call read y$8.push(read props$6.p2)
39
[7] Const mutate $15 = JSX <read Component$0 x={read x$11} y={read y$8} ></read Component$0>
compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md
+2
-2
@@ -72,8 +72,8 @@ bb13:
72
[9] Reassign mutate x$15 = read props$6.c
73
Goto bb1
74
bb1:
75
- predecessor blocks: bb13 bb12 bb8 bb6 bb4
76
- x$16: phi(bb13: x$15, bb12: x$14, bb8: x$11, bb6: x$12, bb4: x$13)
75
+ predecessor blocks: bb8 bb6 bb4 bb12 bb13
76
+ x$16: phi(bb8: x$11, bb6: x$12, bb4: x$13, bb12: x$14, bb13: x$15)
77
[10] read x$16
78
Return
79
```
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx-2.expect.md
+1
-1
@@ -48,7 +48,7 @@ bb2:
48
[6] Let mutate _$15 = JSX <read $14 a={freeze a$11} ></read $14>
49
Goto bb1
50
bb1:
51
- predecessor blocks: bb0 bb2
51
+ predecessor blocks: bb2 bb0
52
[7] Call mutate foo$4(read a$11, mutate b$12)
53
[8] Const mutate $19 = "div"
54
[9] Const mutate $20 = JSX <read $19 a={freeze a$11} b={freeze b$12} ></read $19>
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-multiple-if.expect.md
+4
-4
@@ -31,8 +31,8 @@ bb2:
31
[5] Reassign mutate x$11 = 3
32
Goto bb1
33
bb1:
34
- predecessor blocks: bb0 bb2
35
- x$17: phi(bb0: x$7, bb2: x$11)
34
+ predecessor blocks: bb2 bb0
35
+ x$17: phi(bb2: x$11, bb0: x$7)
36
[6] Const mutate $12 = 3
37
[7] Const mutate $14 = Binary read y$8 === read $12
38
If (read $14) then:bb4 else:bb3
@@ -41,8 +41,8 @@ bb4:
41
[8] Reassign mutate x$15 = 5
42
Goto bb3
43
bb3:
44
- predecessor blocks: bb1 bb4
45
- x$16: phi(bb1: x$17, bb4: x$15)
44
+ predecessor blocks: bb4 bb1
45
+ x$16: phi(bb4: x$15, bb1: x$17)
46
[9] Reassign mutate y$18 = read x$16
47
Return
48
```
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-single-if.expect.md
+2
-2
@@ -28,8 +28,8 @@ bb2:
28
[5] Reassign mutate x$9 = 3
29
Goto bb1
30
bb1:
31
- predecessor blocks: bb0 bb2
32
- x$10: phi(bb0: x$5, bb2: x$9)
31
+ predecessor blocks: bb2 bb0
32
+ x$10: phi(bb2: x$9, bb0: x$5)
33
[6] Reassign mutate y$11 = read x$10
34
Return
35
```
compiler/forget/src/__tests__/fixtures/hir/ssa-for-of.expect.md
+1
-1
@@ -22,7 +22,7 @@ bb0:
22
[1] Let mutate items$5 = Array []
23
Goto bb1
24
bb1:
25
- predecessor blocks: bb0 bb3 bb5
25
+ predecessor blocks: bb0 bb5 bb3
26
If (read items$5) then:bb3 else:bb2
27
bb3:
28
predecessor blocks: bb1
compiler/forget/src/__tests__/fixtures/hir/ssa-if-else.expect.md
+1
-1
@@ -31,7 +31,7 @@ bb3:
31
[4] Let mutate z$8 = read x$5
32
Goto bb1
33
bb1:
34
- predecessor blocks: bb3 bb2
34
+ predecessor blocks: bb2 bb3
35
Return
36
```
37
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md
+3
-3
@@ -36,9 +36,9 @@ bb3:
36
[6] Reassign mutate y$11 = 3
37
Goto bb1
38
bb1:
39
- predecessor blocks: bb3 bb2
40
- x$12: phi(bb3: x$6, bb2: x$10)
41
- y$13: phi(bb3: y$11, bb2: y$7)
39
+ predecessor blocks: bb2 bb3
40
+ x$12: phi(bb2: x$10, bb3: x$6)
41
+ y$13: phi(bb2: y$7, bb3: y$11)
42
[7] Let mutate t$14 = Object { x: read x$12, y: read y$13 }
43
Return freeze t$14
44
```
compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md
+2
-2
@@ -26,8 +26,8 @@ bb2:
26
[4] Reassign mutate x$7 = 2
27
Goto bb1
28
bb1:
29
- predecessor blocks: bb0 bb2
30
- x$8: phi(bb0: x$4, bb2: x$7)
29
+ predecessor blocks: bb2 bb0
30
+ x$8: phi(bb2: x$7, bb0: x$4)
31
Return read x$8
32
```
33
compiler/forget/src/__tests__/fixtures/hir/ssa-simple-phi.expect.md
+2
-2
@@ -33,8 +33,8 @@ bb3:
33
[5] Reassign mutate y$9 = 2
34
Goto bb1
35
bb1:
36
- predecessor blocks: bb3 bb2
37
- y$10: phi(bb3: y$9, bb2: y$8)
36
+ predecessor blocks: bb2 bb3
37
+ y$10: phi(bb2: y$8, bb3: y$9)
38
[6] Let mutate x$11 = read y$10
39
Return
40
```
compiler/forget/src/__tests__/fixtures/hir/ssa-single-if.expect.md
+1
-1
@@ -25,7 +25,7 @@ bb2:
25
[3] Let mutate z$6 = Binary read x$4 + read y$5
26
Goto bb1
27
bb1:
28
- predecessor blocks: bb0 bb2
28
+ predecessor blocks: bb2 bb0
29
Return
30
```
31
compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md
+2
-2
@@ -25,8 +25,8 @@ bb2:
25
[4] Reassign mutate x$7 = 2
26
Goto bb1
27
bb1:
28
- predecessor blocks: bb0 bb2
29
- x$8: phi(bb0: x$4, bb2: x$7)
28
+ predecessor blocks: bb2 bb0
29
+ x$8: phi(bb2: x$7, bb0: x$4)
30
Throw read x$8
31
```
32