Leave SSA form
Alternative approach to #750. We now store the original identifier on the Phi node, then rewrite every BasicBlock's identifiers to reference the original id instead of the SSA'd id. This solves the shadowing problem and also lets us omit adding copies of instructions.
Lauren Tan committed
Nov 9, 2022 at 15:12 UTC
74e6ffc4a2e0a99bd6e2cdbc9a05c4d481c58dd0
23 files changed
+295
-184
compiler/forget/src/HIR/EnterSSA.ts
+1
@@ -121,6 +121,7 @@ class SSABuilder {
121
const phi: Phi = {
122
kind: "Phi",
123
id: newId,
124
+ oldId,
125
operands: predDefs,
126
};
127
compiler/forget/src/HIR/HIR.ts
+1
@@ -193,6 +193,7 @@ export type InstructionValue =
193
export type Phi = {
194
kind: "Phi";
195
id: Identifier;
196
+ oldId: Identifier;
197
operands: Map<BasicBlock, Identifier>;
198
};
199
compiler/forget/src/HIR/LeaveSSA.ts
new
+50
@@ -0,0 +1,50 @@
1
+import { invariant } from "../CompilerError";
2
+import { HIRFunction, Identifier, Place } from "./HIR";
3
+import { eachInstructionOperand, eachTerminalOperand } from "./visitors";
4
+
5
+export default function leaveSSA(fn: HIRFunction) {
6
+ const ir = fn.body;
7
+ const entryBlock = ir.blocks.get(ir.entry);
8
+ invariant(entryBlock, "expected to find the entry basic block");
9
+ const originalIdMap = new Map<
10
+ /* SSA'd id */ Identifier,
11
+ /* original id*/ Identifier
12
+ >();
13
+
14
+ for (const [, block] of ir.blocks) {
15
+ for (const phi of block.phis) {
16
+ originalIdMap.set(phi.id, phi.oldId);
17
+ for (const [, ssaId] of phi.operands) {
18
+ originalIdMap.set(ssaId, phi.oldId);
19
+ }
20
+ }
21
+ block.phis.clear();
22
+ }
23
+
24
+ if (originalIdMap.size === 0) {
25
+ return;
26
+ }
27
+
28
+ function tryRewrite(place: Place) {
29
+ const originalId = originalIdMap.get(place.identifier);
30
+ if (originalId != null) {
31
+ place.identifier = originalId;
32
+ }
33
+ }
34
+
35
+ 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);
41
+ }
42
+ for (const place of eachInstructionOperand(instr)) {
43
+ tryRewrite(place);
44
+ }
45
+ }
46
+ for (const place of eachTerminalOperand(block.terminal)) {
47
+ tryRewrite(place);
48
+ }
49
+ }
50
+}
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+3
-4
@@ -52,16 +52,15 @@ bb3:
52
If (read $36) then:bb8 else:bb9
53
bb8:
54
predecessor blocks: bb3
55
- [9] Const mutate $37 = read $36
55
+ [9] Const mutate $13 = read $36
56
Goto bb7
57
bb9:
58
predecessor blocks: bb3
59
- [10] Const mutate $39 = Call mutate seen$30.has(mutate item$10)
59
+ [10] Const mutate $13 = Call mutate seen$30.has(mutate item$10)
60
Goto bb7
61
bb7:
62
predecessor blocks: bb8 bb9
63
- $40: phi(bb8: $37, bb9: $39)
64
- If (read $40) then:bb1 else:bb4
63
+ If (read $13) then:bb1 else:bb4
64
bb4:
65
predecessor blocks: bb7
66
[11] Call mutate seen$30.add(mutate item$10)
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+12
-13
@@ -32,19 +32,18 @@ bb0:
32
If (read cond$8) then:bb2 else:bb3
33
bb2:
34
predecessor blocks: bb0
35
- [4] Reassign mutate a$11 = read x$9
35
+ [4] Reassign mutate a$4 = read x$9
36
Goto bb1
37
bb3:
38
predecessor blocks: bb0
39
- [5] Reassign mutate a$12 = Array []
39
+ [5] Reassign mutate a$4 = Array []
40
Goto bb1
41
bb1:
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)
47
- Return read a$14
43
+ [6] Call read useFreeze$5(freeze a$4)
44
+ [7] Call read useFreeze$5(read a$4)
45
+ [8] Call mutate call$6(read a$4)
46
+ Return read a$4
47
```
48
49
## Code
@@ -55,15 +54,15 @@ function Component$0(props$7) {
54
const x$9 = props$7.x;
55
let a$10 = undefined;
56
bb1: if (cond$8) {
58
- a$11 = x$9;
57
+ a$4 = x$9;
58
} else {
60
- a$12 = [];
59
+ a$4 = [];
60
}
61
63
- useFreeze$5(a$14);
64
- useFreeze$5(a$14);
65
- call$6(a$14);
66
- return a$14;
62
+ useFreeze$5(a$4);
63
+ useFreeze$5(a$4);
64
+ call$6(a$4);
65
+ return a$4;
66
}
67
68
```
compiler/forget/src/__tests__/fixtures/hir/logical-expression.expect.md
+12
-15
@@ -27,16 +27,15 @@ bb0:
27
If (read $5) then:bb2 else:bb3
28
bb2:
29
predecessor blocks: bb0
30
- [2] Const mutate $6 = Call mutate g$4()
30
+ [2] Const mutate $3 = Call mutate g$4()
31
Goto bb1
32
bb3:
33
predecessor blocks: bb0
34
- [3] Const mutate $7 = read $5
34
+ [3] Const mutate $3 = read $5
35
Goto bb1
36
bb1:
37
predecessor blocks: bb2 bb3
38
- $8: phi(bb2: $6, bb3: $7)
39
- Return freeze $8
38
+ Return freeze $3
39
```
40
41
## Code
@@ -46,7 +45,7 @@ function And$0() {
45
bb1: if (f$1()) {
46
} else {
47
}
49
- return t8;
48
+ return f$1();
49
}
50
51
```
@@ -58,16 +57,15 @@ bb0:
57
If (read $5) then:bb2 else:bb3
58
bb2:
59
predecessor blocks: bb0
61
- [2] Const mutate $6 = read $5
60
+ [2] Const mutate $3 = read $5
61
Goto bb1
62
bb3:
63
predecessor blocks: bb0
65
- [3] Const mutate $7 = Call mutate g$4()
64
+ [3] Const mutate $3 = Call mutate g$4()
65
Goto bb1
66
bb1:
67
predecessor blocks: bb2 bb3
69
- $8: phi(bb2: $6, bb3: $7)
70
- Return freeze $8
68
+ Return freeze $3
69
```
70
71
## Code
@@ -77,7 +75,7 @@ function Or$0() {
75
bb1: if (f$1()) {
76
} else {
77
}
80
- return t8;
78
+ return g$4();
79
}
80
81
```
@@ -91,16 +89,15 @@ bb0:
89
If (read $11) then:bb2 else:bb3
90
bb2:
91
predecessor blocks: bb0
94
- [4] Const mutate $12 = read $9
92
+ [4] Const mutate $6 = read $9
93
Goto bb1
94
bb3:
95
predecessor blocks: bb0
98
- [5] Const mutate $13 = Call mutate g$7()
96
+ [5] Const mutate $6 = Call mutate g$7()
97
Goto bb1
98
bb1:
99
predecessor blocks: bb2 bb3
102
- $14: phi(bb2: $12, bb3: $13)
103
- Return freeze $14
100
+ Return freeze $6
101
```
102
103
## Code
@@ -110,7 +107,7 @@ function QuestionQuestion$0(props$8) {
107
bb1: if (f$2() != null) {
108
} else {
109
}
113
- return t14;
110
+ return g$7();
111
}
112
113
```
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+20
-28
@@ -73,49 +73,41 @@ function cond$0(x$2) {
73
74
```
75
bb0:
76
- [1] Let mutate a$13 = Object { }
77
- [2] Let mutate b$14 = Object { }
78
- [3] Let mutate c$15 = Object { }
79
- [4] Let mutate d$16 = Object { }
76
+ [1] Let mutate a$2 = Object { }
77
+ [2] Let mutate b$3 = Object { }
78
+ [3] Let mutate c$4 = Object { }
79
+ [4] Let mutate d$5 = Object { }
80
Goto bb1
81
bb1:
82
predecessor blocks: bb0 bb3
83
- a$18: phi(bb0: a$13, bb3: a$21)
84
- b$20: phi(bb0: b$14, bb3: b$23)
85
- c$22: phi(bb0: c$15, bb3: c$25)
86
- d$24: phi(bb0: d$16, bb3: d$26)
83
[5] Const mutate $17 = true
84
If (read $17) then:bb3 else:bb2
85
bb3:
86
predecessor blocks: bb1
91
- [6] Let mutate z$19 = read a$18
92
- [7] Reassign mutate a$21[7:12] = read b$20
93
- [8] Reassign mutate b$23[8:11] = read c$22
94
- [9] Reassign mutate c$25 = read d$24
95
- [10] Reassign mutate d$26 = read z$19
96
- [11] Call mutate mutate$7(mutate a$21, mutate b$23)
97
- [12] Const mutate $29 = Call mutate cond$8(mutate a$21)
87
+ [6] Let mutate z$19 = read a$2
88
+ [7] Reassign mutate a$2 = read b$3
89
+ [8] Reassign mutate b$3 = read c$4
90
+ [9] Reassign mutate c$4 = read d$5
91
+ [10] Reassign mutate d$5 = read z$19
92
+ [11] Call mutate mutate$7(mutate a$2, mutate b$3)
93
+ [12] Const mutate $29 = Call mutate cond$8(mutate a$2)
94
If (read $29) then:bb2 else:bb1
95
bb2:
96
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
97
+ If (read a$2) then:bb7 else:bb7
98
bb7:
99
predecessor blocks: bb2
108
- If (read b$31) then:bb9 else:bb9
100
+ If (read b$3) then:bb9 else:bb9
101
bb9:
102
predecessor blocks: bb7
111
- If (read c$32) then:bb11 else:bb11
103
+ If (read c$4) then:bb11 else:bb11
104
bb11:
105
predecessor blocks: bb9
114
- If (read d$33) then:bb13 else:bb13
106
+ If (read d$5) then:bb13 else:bb13
107
bb13:
108
predecessor blocks: bb11
109
[13] Const mutate $34 = null
118
- [14] Call mutate mutate$7(mutate d$33, read $34)
110
+ [14] Call mutate mutate$7(mutate d$5, read $34)
111
Return
112
```
113
@@ -123,10 +115,10 @@ bb13:
115
116
```javascript
117
function Component$0(props$12) {
126
- let a$13 = {};
127
- let b$14 = {};
128
- let c$15 = {};
129
- let d$16 = {};
118
+ let a$2 = {};
119
+ let b$3 = {};
120
+ let c$4 = {};
121
+ let d$5 = {};
122
}
123
124
```
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+12
-13
@@ -23,20 +23,19 @@ function Component(props) {
23
24
```
25
bb0:
26
- [1] Let mutate x$7[1:2] = Array []
27
- [2] Call mutate x$7.push(read props$6.p0)
28
- [3] Let mutate y$8 = read x$7
26
+ [1] Let mutate x$2 = Array []
27
+ [2] Call mutate x$2.push(read props$6.p0)
28
+ [3] Let mutate y$8 = read x$2
29
If (read props$6.p1) then:bb2 else:bb1
30
bb2:
31
predecessor blocks: bb0
32
- [4] Reassign mutate x$9 = Array []
32
+ [4] Reassign mutate x$2 = Array []
33
Goto bb1
34
bb1:
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>
36
+ [5] Let mutate _$12 = JSX <read Component$0 x={freeze x$2} ></read Component$0>
37
[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>
38
+ [7] Const mutate $15 = JSX <read Component$0 x={read x$2} y={read y$8} ></read Component$0>
39
Return read $15
40
```
41
@@ -44,17 +43,17 @@ bb1:
43
44
```javascript
45
function Component$0(props$6) {
47
- let x$7 = [];
48
- x$7.push(props$6.p0);
49
- let y$8 = x$7;
46
+ let x$2 = [];
47
+ x$2.push(props$6.p0);
48
+ let y$8 = x$2;
49
bb1: if (props$6.p1) {
51
- x$9 = [];
50
+ x$2 = [];
51
}
52
54
- let _$12 = <Component$0 x={x$11}></Component$0>;
53
+ let _$12 = <Component$0 x={x$2}></Component$0>;
54
55
y$8.push(props$6.p2);
57
- return <Component$0 x={x$11} y={y$8}></Component$0>;
56
+ return <Component$0 x={x$2} y={y$8}></Component$0>;
57
}
58
59
```
compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md
+12
-13
@@ -50,31 +50,30 @@ bb2:
50
Default: bb4
51
bb8:
52
predecessor blocks: bb2
53
- [5] Reassign mutate x$11 = read props$6.v0
53
+ [5] Reassign mutate x$2 = read props$6.v0
54
Goto bb1
55
bb6:
56
predecessor blocks: bb2
57
- [6] Reassign mutate x$12 = read props$6.v1
57
+ [6] Reassign mutate x$2 = read props$6.v1
58
Goto bb1
59
bb4:
60
predecessor blocks: bb2
61
- [7] Reassign mutate x$13 = read props$6.v2
61
+ [7] Reassign mutate x$2 = read props$6.v2
62
Goto bb1
63
bb10:
64
predecessor blocks: bb0
65
If (read props$6.cond2) then:bb12 else:bb13
66
bb12:
67
predecessor blocks: bb10
68
- [8] Reassign mutate x$14 = read props$6.b
68
+ [8] Reassign mutate x$2 = read props$6.b
69
Goto bb1
70
bb13:
71
predecessor blocks: bb10
72
- [9] Reassign mutate x$15 = read props$6.c
72
+ [9] Reassign mutate x$2 = read props$6.c
73
Goto bb1
74
bb1:
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
76
+ [10] read x$2
77
Return
78
```
79
@@ -86,12 +85,12 @@ function Component$0(props$6) {
85
bb1: if (props$6.cond) {
86
switch (props$6.test) {
87
case 0: {
89
- x$11 = props$6.v0;
88
+ x$2 = props$6.v0;
89
break bb1;
90
}
91
92
case 1: {
94
- x$12 = props$6.v1;
93
+ x$2 = props$6.v1;
94
break bb1;
95
}
96
@@ -99,18 +98,18 @@ function Component$0(props$6) {
98
}
99
100
default: {
102
- x$13 = props$6.v2;
101
+ x$2 = props$6.v2;
102
}
103
}
104
} else {
105
if (props$6.cond2) {
107
- x$14 = props$6.b;
106
+ x$2 = props$6.b;
107
} else {
109
- x$15 = props$6.c;
108
+ x$2 = props$6.c;
109
}
110
}
111
113
- x$16;
112
+ x$2;
113
return;
114
}
115
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-multiple-if.expect.md
+8
-10
@@ -21,29 +21,27 @@ function foo() {
21
22
```
23
bb0:
24
- [1] Let mutate x$7 = 1
24
+ [1] Let mutate x$1 = 1
25
[2] Let mutate y$8 = 2
26
[3] Const mutate $9 = 2
27
[4] Const mutate $10 = Binary read y$8 === read $9
28
If (read $10) then:bb2 else:bb1
29
bb2:
30
predecessor blocks: bb0
31
- [5] Reassign mutate x$11 = 3
31
+ [5] Reassign mutate x$1 = 3
32
Goto bb1
33
bb1:
34
predecessor blocks: bb2 bb0
35
- x$17: phi(bb2: x$11, bb0: x$7)
35
[6] Const mutate $12 = 3
36
[7] Const mutate $14 = Binary read y$8 === read $12
37
If (read $14) then:bb4 else:bb3
38
bb4:
39
predecessor blocks: bb1
41
- [8] Reassign mutate x$15 = 5
40
+ [8] Reassign mutate x$1 = 5
41
Goto bb3
42
bb3:
43
predecessor blocks: bb4 bb1
45
- x$16: phi(bb4: x$15, bb1: x$17)
46
- [9] Reassign mutate y$18 = read x$16
44
+ [9] Reassign mutate y$18 = read x$1
45
Return
46
```
47
@@ -51,17 +49,17 @@ bb3:
49
50
```javascript
51
function foo$0() {
54
- let x$7 = 1;
52
+ let x$1 = 1;
53
let y$8 = 2;
54
bb1: if (y$8 === 2) {
57
- x$11 = 3;
55
+ x$1 = 3;
56
}
57
58
bb3: if (y$8 === 3) {
61
- x$15 = 5;
59
+ x$1 = 5;
60
}
61
64
- y$18 = x$16;
62
+ y$18 = x$1;
63
return;
64
}
65
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-single-if.expect.md
+6
-7
@@ -18,19 +18,18 @@ function foo() {
18
19
```
20
bb0:
21
- [1] Let mutate x$5 = 1
21
+ [1] Let mutate x$1 = 1
22
[2] Let mutate y$6 = 2
23
[3] Const mutate $7 = 2
24
[4] Const mutate $8 = Binary read y$6 === read $7
25
If (read $8) then:bb2 else:bb1
26
bb2:
27
predecessor blocks: bb0
28
- [5] Reassign mutate x$9 = 3
28
+ [5] Reassign mutate x$1 = 3
29
Goto bb1
30
bb1:
31
predecessor blocks: bb2 bb0
32
- x$10: phi(bb2: x$9, bb0: x$5)
33
- [6] Reassign mutate y$11 = read x$10
32
+ [6] Reassign mutate y$11 = read x$1
33
Return
34
```
35
@@ -38,13 +37,13 @@ bb1:
37
38
```javascript
39
function foo$0() {
41
- let x$5 = 1;
40
+ let x$1 = 1;
41
let y$6 = 2;
42
bb1: if (y$6 === 2) {
44
- x$9 = 3;
43
+ x$1 = 3;
44
}
45
47
- y$11 = x$10;
46
+ y$11 = x$1;
47
return;
48
}
49
compiler/forget/src/__tests__/fixtures/hir/ssa-for.expect.md
+5
-6
@@ -16,29 +16,28 @@ function foo() {
16
17
```
18
bb0:
19
- [1] Let mutate x$5 = 0
19
+ [1] Let mutate x$1 = 0
20
Goto bb1
21
bb1:
22
predecessor blocks: bb0 bb4
23
- x$7: phi(bb0: x$5, bb4: x$10)
23
[2] Const mutate $6 = 10
25
- [3] Const mutate $8 = Binary read x$7 < read $6
24
+ [3] Const mutate $8 = Binary read x$1 < read $6
25
If (read $8) then:bb4 else:bb2
26
bb4:
27
predecessor blocks: bb1
28
[4] Const mutate $9 = 1
30
- [5] Reassign mutate x$10 = Binary read x$7 + read $9
29
+ [5] Reassign mutate x$1 = Binary read x$1 + read $9
30
Goto bb1
31
bb2:
32
predecessor blocks: bb1
34
- Return read x$7
33
+ Return read x$1
34
```
35
36
## Code
37
38
```javascript
39
function foo$0() {
41
- let x$5 = 0;
40
+ let x$1 = 0;
41
}
42
43
```
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md
+13
-15
@@ -22,24 +22,22 @@ function foo() {
22
23
```
24
bb0:
25
- [1] Let mutate x$6 = 1
26
- [2] Let mutate y$7 = 2
25
+ [1] Let mutate x$1 = 1
26
+ [2] Let mutate y$2 = 2
27
[3] Const mutate $8 = 1
28
- [4] Const mutate $9 = Binary read x$6 > read $8
28
+ [4] Const mutate $9 = Binary read x$1 > read $8
29
If (read $9) then:bb2 else:bb3
30
bb2:
31
predecessor blocks: bb0
32
- [5] Reassign mutate x$10 = 2
32
+ [5] Reassign mutate x$1 = 2
33
Goto bb1
34
bb3:
35
predecessor blocks: bb0
36
- [6] Reassign mutate y$11 = 3
36
+ [6] Reassign mutate y$2 = 3
37
Goto bb1
38
bb1:
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 }
40
+ [7] Let mutate t$14 = Object { x: read x$1, y: read y$2 }
41
Return freeze t$14
42
```
43
@@ -47,17 +45,17 @@ bb1:
45
46
```javascript
47
function foo$0() {
50
- let x$6 = 1;
51
- let y$7 = 2;
52
- bb1: if (x$6 > 1) {
53
- x$10 = 2;
48
+ let x$1 = 1;
49
+ let y$2 = 2;
50
+ bb1: if (x$1 > 1) {
51
+ x$1 = 2;
52
} else {
55
- y$11 = 3;
53
+ y$2 = 3;
54
}
55
56
let t$14 = {
59
- x: x$12,
60
- y: y$13,
57
+ x: x$1,
58
+ y: y$2,
59
};
60
return t$14;
61
}
compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md
+8
-9
@@ -17,30 +17,29 @@ function foo() {
17
18
```
19
bb0:
20
- [1] Let mutate x$4 = 1
20
+ [1] Let mutate x$1 = 1
21
[2] Const mutate $5 = 1
22
- [3] Const mutate $6 = Binary read x$4 === read $5
22
+ [3] Const mutate $6 = Binary read x$1 === read $5
23
If (read $6) then:bb2 else:bb1
24
bb2:
25
predecessor blocks: bb0
26
- [4] Reassign mutate x$7 = 2
26
+ [4] Reassign mutate x$1 = 2
27
Goto bb1
28
bb1:
29
predecessor blocks: bb2 bb0
30
- x$8: phi(bb2: x$7, bb0: x$4)
31
- Return read x$8
30
+ Return read x$1
31
```
32
33
## Code
34
35
```javascript
36
function foo$0() {
38
- let x$4 = 1;
39
- bb1: if (x$4 === 1) {
40
- x$7 = 2;
37
+ let x$1 = 1;
38
+ bb1: if (x$1 === 1) {
39
+ x$1 = 2;
40
}
41
43
- return x$8;
42
+ return x$1;
43
}
44
45
```
compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md
new
+73
@@ -0,0 +1,73 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function log() {}
6
+
7
+function Foo(cond) {
8
+ let str = "";
9
+ if (cond) {
10
+ let str = "other test";
11
+ log(str);
12
+ } else {
13
+ str = "fallthrough test";
14
+ }
15
+ log(str);
16
+}
17
+
18
+```
19
+
20
+## HIR
21
+
22
+```
23
+bb0:
24
+ Return
25
+```
26
+
27
+## Code
28
+
29
+```javascript
30
+function log$0() {
31
+ return;
32
+}
33
+
34
+```
35
+## HIR
36
+
37
+```
38
+bb0:
39
+ [1] Let mutate str$2 = ""
40
+ If (read cond$5) then:bb2 else:bb3
41
+bb2:
42
+ predecessor blocks: bb0
43
+ [2] Let mutate str$7 = "other test"
44
+ [3] Call mutate log$4(read str$7)
45
+ Goto bb1
46
+bb3:
47
+ predecessor blocks: bb0
48
+ [4] Reassign mutate str$2 = "fallthrough test"
49
+ Goto bb1
50
+bb1:
51
+ predecessor blocks: bb2 bb3
52
+ [5] Call mutate log$4(read str$2)
53
+ Return
54
+```
55
+
56
+## Code
57
+
58
+```javascript
59
+function Foo$0(cond$5) {
60
+ let str$2 = "";
61
+ bb1: if (cond$5) {
62
+ let str$7 = "other test";
63
+ log$4(str$7);
64
+ } else {
65
+ str$2 = "fallthrough test";
66
+ }
67
+
68
+ log$4(str$2);
69
+ return;
70
+}
71
+
72
+```
73
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.js
new
+12
@@ -0,0 +1,12 @@
1
+function log() {}
2
+
3
+function Foo(cond) {
4
+ let str = "";
5
+ if (cond) {
6
+ let str = "other test";
7
+ log(str);
8
+ } else {
9
+ str = "fallthrough test";
10
+ }
11
+ log(str);
12
+}
compiler/forget/src/__tests__/fixtures/hir/ssa-simple-phi.expect.md
+6
-7
@@ -26,16 +26,15 @@ bb0:
26
If (read $7) then:bb2 else:bb3
27
bb2:
28
predecessor blocks: bb0
29
- [4] Reassign mutate y$8 = 1
29
+ [4] Reassign mutate y$1 = 1
30
Goto bb1
31
bb3:
32
predecessor blocks: bb0
33
- [5] Reassign mutate y$9 = 2
33
+ [5] Reassign mutate y$1 = 2
34
Goto bb1
35
bb1:
36
predecessor blocks: bb2 bb3
37
- y$10: phi(bb2: y$8, bb3: y$9)
38
- [6] Let mutate x$11 = read y$10
37
+ [6] Let mutate x$11 = read y$1
38
Return
39
```
40
@@ -45,12 +44,12 @@ bb1:
44
function foo$0() {
45
let y$5 = 2;
46
bb1: if (y$5 > 1) {
48
- y$8 = 1;
47
+ y$1 = 1;
48
} else {
50
- y$9 = 2;
49
+ y$1 = 2;
50
}
51
53
- let x$11 = y$10;
52
+ let x$11 = y$1;
53
return;
54
}
55
compiler/forget/src/__tests__/fixtures/hir/ssa-switch.expect.md
+8
-9
@@ -40,22 +40,21 @@ bb0:
40
bb5:
41
predecessor blocks: bb0
42
[6] Const mutate $15 = 1
43
- [7] Reassign mutate x$16 = Binary read x$10 + read $15
43
+ [7] Reassign mutate x$1 = Binary read x$10 + read $15
44
Goto bb1
45
bb3:
46
predecessor blocks: bb0
47
[8] Const mutate $17 = 2
48
- [9] Reassign mutate x$18 = Binary read x$10 + read $17
48
+ [9] Reassign mutate x$1 = Binary read x$10 + read $17
49
Goto bb1
50
bb2:
51
predecessor blocks: bb0
52
[10] Const mutate $19 = 3
53
- [11] Reassign mutate x$20 = Binary read x$10 + read $19
53
+ [11] Reassign mutate x$1 = Binary read x$10 + read $19
54
Goto bb1
55
bb1:
56
predecessor blocks: bb5 bb3 bb2
57
- x$21: phi(bb5: x$16, bb3: x$18, bb2: x$20)
58
- [12] Let mutate y$22 = read x$21
57
+ [12] Let mutate y$22 = read x$1
58
Return
59
```
60
@@ -66,21 +65,21 @@ function foo$0() {
65
let x$10 = 1;
66
bb1: switch (x$10) {
67
case x$10 === 1: {
69
- x$16 = x$10 + 1;
68
+ x$1 = x$10 + 1;
69
break bb1;
70
}
71
72
case x$10 === 2: {
74
- x$18 = x$10 + 2;
73
+ x$1 = x$10 + 2;
74
break bb1;
75
}
76
77
default: {
79
- x$20 = x$10 + 3;
78
+ x$1 = x$10 + 3;
79
}
80
}
81
83
- let y$22 = x$21;
82
+ let y$22 = x$1;
83
return;
84
}
85
compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md
+8
-9
@@ -16,30 +16,29 @@ function foo() {
16
17
```
18
bb0:
19
- [1] Let mutate x$4 = 1
19
+ [1] Let mutate x$1 = 1
20
[2] Const mutate $5 = 1
21
- [3] Const mutate $6 = Binary read x$4 === read $5
21
+ [3] Const mutate $6 = Binary read x$1 === read $5
22
If (read $6) then:bb2 else:bb1
23
bb2:
24
predecessor blocks: bb0
25
- [4] Reassign mutate x$7 = 2
25
+ [4] Reassign mutate x$1 = 2
26
Goto bb1
27
bb1:
28
predecessor blocks: bb2 bb0
29
- x$8: phi(bb2: x$7, bb0: x$4)
30
- Throw read x$8
29
+ Throw read x$1
30
```
31
32
## Code
33
34
```javascript
35
function foo$0() {
37
- let x$4 = 1;
38
- bb1: if (x$4 === 1) {
39
- x$7 = 2;
36
+ let x$1 = 1;
37
+ bb1: if (x$1 === 1) {
38
+ x$1 = 2;
39
}
40
42
- throw x$8;
41
+ throw x$1;
42
}
43
44
```
compiler/forget/src/__tests__/fixtures/hir/ssa-while.expect.md
+5
-6
@@ -17,29 +17,28 @@ function foo() {
17
18
```
19
bb0:
20
- [1] Let mutate x$5 = 1
20
+ [1] Let mutate x$1 = 1
21
Goto bb1
22
bb1:
23
predecessor blocks: bb0 bb3
24
- x$7: phi(bb0: x$5, bb3: x$10)
24
[2] Const mutate $6 = 10
26
- [3] Const mutate $8 = Binary read x$7 < read $6
25
+ [3] Const mutate $8 = Binary read x$1 < read $6
26
If (read $8) then:bb3 else:bb2
27
bb3:
28
predecessor blocks: bb1
29
[4] Const mutate $9 = 1
31
- [5] Reassign mutate x$10 = Binary read x$7 + read $9
30
+ [5] Reassign mutate x$1 = Binary read x$1 + read $9
31
Goto bb1
32
bb2:
33
predecessor blocks: bb1
35
- Return read x$7
34
+ Return read x$1
35
```
36
37
## Code
38
39
```javascript
40
function foo$0() {
42
- let x$5 = 1;
41
+ let x$1 = 1;
42
}
43
44
```
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+10
-11
@@ -33,7 +33,7 @@ function Component(props) {
33
```
34
bb0:
35
[1] Let mutate x$10[1:6] = Array []
36
- [2] Let mutate y$11 = undefined
36
+ [2] Let mutate y$3 = undefined
37
[3] Const mutate $12 = false
38
[4] Const mutate $13 = true
39
[5] Const mutate $14 = 1
@@ -45,18 +45,17 @@ bb0:
45
bb6:
46
predecessor blocks: bb0
47
[6] Call mutate x$10.push(read props$9.p2)
48
- [7] Reassign mutate y$15 = Array []
48
+ [7] Reassign mutate y$3 = Array []
49
Goto bb1
50
bb2:
51
predecessor blocks: bb0
52
- [8] Reassign mutate y$16 = read x$10
52
+ [8] Reassign mutate y$3 = read x$10
53
Goto bb1
54
bb1:
55
predecessor blocks: bb0 bb6 bb2
56
- y$20: phi(bb0: y$11, bb6: y$15, bb2: y$16)
56
[9] Const mutate child$19 = JSX <read Component$0 data={freeze x$10} ></read Component$0>
58
- [10] Call read y$20.push(read props$9.p4)
59
- [11] Const mutate $22 = JSX <read Component$0 data={freeze y$20} >{read child$19}</read Component$0>
57
+ [10] Call read y$3.push(read props$9.p4)
58
+ [11] Const mutate $22 = JSX <read Component$0 data={freeze y$3} >{read child$19}</read Component$0>
59
Return read $22
60
```
61
@@ -65,7 +64,7 @@ bb1:
64
```javascript
65
function Component$0(props$9) {
66
let x$10 = [];
68
- let y$11 = undefined;
67
+ let y$3 = undefined;
68
bb1: switch (props$9.p0) {
69
case 1: {
70
break bb1;
@@ -73,7 +72,7 @@ function Component$0(props$9) {
72
73
case true: {
74
x$10.push(props$9.p2);
76
- y$15 = [];
75
+ y$3 = [];
76
break bb1;
77
}
78
@@ -82,13 +81,13 @@ function Component$0(props$9) {
81
}
82
83
case false: {
85
- y$16 = x$10;
84
+ y$3 = x$10;
85
}
86
}
87
88
const child$19 = <Component$0 data={x$10}></Component$0>;
90
- y$20.push(props$9.p4);
91
- return <Component$0 data={y$20}>{child$19}</Component$0>;
89
+ y$3.push(props$9.p4);
90
+ return <Component$0 data={y$3}>{child$19}</Component$0>;
91
}
92
93
```
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+8
-9
@@ -29,7 +29,7 @@ function Component(props) {
29
```
30
bb0:
31
[1] Let mutate x$9[1:6] = Array []
32
- [2] Let mutate y$10 = undefined
32
+ [2] Let mutate y$3 = undefined
33
[3] Const mutate $11 = false
34
[4] Const mutate $12 = true
35
Switch (read props$8.p0)
@@ -44,14 +44,13 @@ bb4:
44
Goto bb2
45
bb2:
46
predecessor blocks: bb4 bb0
47
- [8] Reassign mutate y$15 = read x$9
47
+ [8] Reassign mutate y$3 = read x$9
48
Goto bb1
49
bb1:
50
predecessor blocks: bb2 bb0
51
- y$20: phi(bb2: y$15, bb0: y$10)
51
[9] Const mutate child$19 = JSX <read Component$0 data={freeze x$9} ></read Component$0>
53
- [10] Call read y$20.push(read props$8.p4)
54
- [11] Const mutate $23 = JSX <read Component$0 data={read y$20} >{read child$19}</read Component$0>
52
+ [10] Call read y$3.push(read props$8.p4)
53
+ [11] Const mutate $23 = JSX <read Component$0 data={read y$3} >{read child$19}</read Component$0>
54
Return read $23
55
```
56
@@ -60,7 +59,7 @@ bb1:
59
```javascript
60
function Component$0(props$8) {
61
let x$9 = [];
63
- let y$10 = undefined;
62
+ let y$3 = undefined;
63
bb1: switch (props$8.p0) {
64
case true: {
65
x$9.push(props$8.p2);
@@ -69,13 +68,13 @@ function Component$0(props$8) {
68
}
69
70
case false: {
72
- y$15 = x$9;
71
+ y$3 = x$9;
72
}
73
}
74
75
const child$19 = <Component$0 data={x$9}></Component$0>;
77
- y$20.push(props$8.p4);
78
- return <Component$0 data={y$20}>{child$19}</Component$0>;
76
+ y$3.push(props$8.p4);
77
+ return <Component$0 data={y$3}>{child$19}</Component$0>;
78
}
79
80
```
compiler/forget/src/__tests__/hir-test.ts
+2
@@ -22,6 +22,7 @@ import { HIRFunction } from "../HIR/HIR";
22
import { Environment } from "../HIR/HIRBuilder";
23
import { inferMutableRanges } from "../HIR/InferMutableLifetimes";
24
import inferReferenceEffects from "../HIR/InferReferenceEffects";
25
+import leaveSSA from "../HIR/LeaveSSA";
26
import printHIR from "../HIR/PrintHIR";
27
import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures";
28
@@ -68,6 +69,7 @@ describe("React Forget (HIR version)", () => {
69
eliminateRedundantPhi(ir);
70
inferReferenceEffects(ir);
71
inferMutableRanges(ir);
72
+ leaveSSA(ir);
73
// const lifetimeGraph = buildDefUseGraph(ir);
74
const textHIR = printHIR(ir.body);
75
// const textLifetimeGraph = printGraph(lifetimeGraph);