Reset canonicalId mutable range if not mutated after creation
Lauren Tan committed
Feb 8, 2023 at 10:26 UTC
e7f4eae619cd38c829c62f5a6f869b50f7789c70
15 files changed
+158
-277
compiler/forget/src/HIR/PrintHIR.ts
+1
-1
@@ -114,7 +114,7 @@ export function printInstruction(instr: ReactiveInstruction): string {
114
function printPhi(phi: Phi): string {
115
const items = [];
116
items.push(printIdentifier(phi.id));
117
- // items.push(printMutableRange(phi.id));
117
+ items.push(printMutableRange(phi.id));
118
items.push(printType(phi.type));
119
items.push(": phi(");
120
const phis = [];
compiler/forget/src/SSA/LeaveSSA.ts
+8
-9
@@ -174,15 +174,8 @@ export function leaveSSA(fn: HIRFunction) {
174
}
175
176
// all versions of the variable need to be remapped to the canonical id
177
- // also extend the mutable range of the canonical id based on the min/max
178
- // of the ranges of its operands
179
- let start = canonicalId.mutableRange.start as number;
180
- let end = canonicalId.mutableRange.end as number;
177
for (const [, operand] of phi.operands) {
182
- start = Math.min(start, operand.mutableRange.start);
183
- end = Math.max(end, operand.mutableRange.end);
178
reassignments.set(operand, canonicalId);
185
-
179
if (operand.mutableRange.start < terminal.id) {
180
invariant(
181
initOperand === null,
@@ -191,8 +184,6 @@ export function leaveSSA(fn: HIRFunction) {
184
initOperand = operand;
185
}
186
}
194
- canonicalId.mutableRange.start = makeInstructionId(start);
195
- canonicalId.mutableRange.end = makeInstructionId(end);
187
188
// If there are no instructions in the block then there's just a terminal
189
// node, which has no mutation, so that should be false.
@@ -203,6 +194,14 @@ export function leaveSSA(fn: HIRFunction) {
194
phi.id.mutableRange.end >
195
(phiBlock.instructions.at(0)?.id ?? phiBlock.terminal.id);
196
197
+ // If a phi is never mutated after creation, reset its mutable range to be itself
198
+ if (!isPhiMutatedAfterCreation) {
199
+ canonicalId.mutableRange.start = phiBlock.terminal.id;
200
+ canonicalId.mutableRange.end = makeInstructionId(
201
+ phiBlock.terminal.id + 1
202
+ );
203
+ }
204
+
205
// If this phi id is the canonical id we need to generate a let binding for it
206
// (otherwise, it means this phi merges into some other phi which already generated
207
// a binding
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+11
-21
@@ -29,29 +29,19 @@ function Component(props) {
29
const $ = React.unstable_useMemoCache();
30
const cond = props.cond;
31
const x = props.x;
32
- const c_0 = $[0] !== cond;
33
- const c_1 = $[1] !== x;
34
- let a;
35
- if (c_0 || c_1) {
36
- a = undefined;
37
- if (cond) {
38
- const a$0 = x;
39
- a = a$0;
32
+ let a = undefined;
33
+ if (cond) {
34
+ const a$0 = x;
35
+ a = a$0;
36
+ } else {
37
+ let a$1;
38
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
39
+ a$1 = [];
40
+ $[0] = a$1;
41
} else {
41
- let a$1;
42
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
43
- a$1 = [];
44
- $[3] = a$1;
45
- } else {
46
- a$1 = $[3];
47
- }
48
- a = a$1;
42
+ a$1 = $[0];
43
}
50
- $[0] = cond;
51
- $[1] = x;
52
- $[2] = a;
53
- } else {
54
- a = $[2];
44
+ a = a$1;
45
}
46
47
useFreeze(a);
compiler/forget/src/__tests__/fixtures/hir/infer-phi-primitive.expect.md
+6
-15
@@ -20,22 +20,13 @@ function foo(a, b) {
20
21
```javascript
22
function foo(a, b) {
23
- const $ = React.unstable_useMemoCache();
24
- const c_0 = $[0] !== a;
25
- let x;
26
- if (c_0) {
27
- x = undefined;
28
- if (a) {
29
- const x$0 = 1;
30
- x = x$0;
31
- } else {
32
- const x$1 = 2;
33
- x = x$1;
34
- }
35
- $[0] = a;
36
- $[1] = x;
23
+ let x = undefined;
24
+ if (a) {
25
+ const x$0 = 1;
26
+ x = x$0;
27
} else {
38
- x = $[1];
28
+ const x$1 = 2;
29
+ x = x$1;
30
}
31
32
const y = x;
compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md
+20
-30
@@ -20,39 +20,29 @@ function foo(a, b, c, d) {
20
```javascript
21
function foo(a, b, c, d) {
22
const $ = React.unstable_useMemoCache();
23
- const c_0 = $[0] !== b;
24
- const c_1 = $[1] !== c;
25
- let x;
26
- if (c_0 || c_1) {
27
- x = undefined;
28
- if (someVal) {
29
- const c_3 = $[3] !== b;
30
- let x$0;
31
- if (c_3) {
32
- x$0 = { b: b };
33
- $[3] = b;
34
- $[4] = x$0;
35
- } else {
36
- x$0 = $[4];
37
- }
38
- x = x$0;
23
+ let x = undefined;
24
+ if (someVal) {
25
+ const c_0 = $[0] !== b;
26
+ let x$0;
27
+ if (c_0) {
28
+ x$0 = { b: b };
29
+ $[0] = b;
30
+ $[1] = x$0;
31
} else {
40
- const c_5 = $[5] !== c;
41
- let x$1;
42
- if (c_5) {
43
- x$1 = { c: c };
44
- $[5] = c;
45
- $[6] = x$1;
46
- } else {
47
- x$1 = $[6];
48
- }
49
- x = x$1;
32
+ x$0 = $[1];
33
}
51
- $[0] = b;
52
- $[1] = c;
53
- $[2] = x;
34
+ x = x$0;
35
} else {
55
- x = $[2];
36
+ const c_2 = $[2] !== c;
37
+ let x$1;
38
+ if (c_2) {
39
+ x$1 = { c: c };
40
+ $[2] = c;
41
+ $[3] = x$1;
42
+ } else {
43
+ x$1 = $[3];
44
+ }
45
+ x = x$1;
46
}
47
return x;
48
}
compiler/forget/src/__tests__/fixtures/hir/primitive-alias-mutate.expect.md
+6
-15
@@ -20,22 +20,13 @@ function component(a) {
20
21
```javascript
22
function component(a) {
23
- const $ = React.unstable_useMemoCache();
24
- const c_0 = $[0] !== a;
25
- let x;
26
- if (c_0) {
27
- x = undefined;
28
- if (a) {
29
- const x$0 = "bar";
30
- x = x$0;
31
- } else {
32
- const x$1 = "baz";
33
- x = x$1;
34
- }
35
- $[0] = a;
36
- $[1] = x;
23
+ let x = undefined;
24
+ if (a) {
25
+ const x$0 = "bar";
26
+ x = x$0;
27
} else {
38
- x = $[1];
28
+ const x$1 = "baz";
29
+ x = x$1;
30
}
31
32
const y = x;
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+14
-24
@@ -35,37 +35,27 @@ function Component(props) {
35
x = $[1];
36
}
37
const y = x;
38
- const c_2 = $[2] !== props.p1;
39
- let x$0;
40
- if (c_2) {
41
- x$0 = x;
42
- if (props.p1) {
43
- let x$1;
44
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
45
- x$1 = [];
46
- $[4] = x$1;
47
- } else {
48
- x$1 = $[4];
49
- }
50
- x$0 = x$1;
38
+ let x$0 = x;
39
+ if (props.p1) {
40
+ let x$1;
41
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
42
+ x$1 = [];
43
+ $[2] = x$1;
44
+ } else {
45
+ x$1 = $[2];
46
}
52
- $[2] = props.p1;
53
- $[3] = x$0;
54
- } else {
55
- x$0 = $[3];
47
+ x$0 = x$1;
48
}
49
50
y.push(props.p2);
59
- const c_5 = $[5] !== x$0;
60
- const c_6 = $[6] !== y;
51
+ const c_3 = $[3] !== y;
52
let t0;
62
- if (c_5 || c_6) {
53
+ if (c_3) {
54
t0 = <Component x={x$0} y={y}></Component>;
64
- $[5] = x$0;
65
- $[6] = y;
66
- $[7] = t0;
55
+ $[3] = y;
56
+ $[4] = t0;
57
} else {
68
- t0 = $[7];
58
+ t0 = $[4];
59
}
60
return t0;
61
}
compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md
+31
-43
@@ -56,61 +56,49 @@ function foo(a, b, c) {
56
} else {
57
y = $[3];
58
}
59
- const c_4 = $[4] !== b;
60
- const c_5 = $[5] !== c;
61
- let x$0;
62
- if (c_4 || c_5) {
63
- x$0 = undefined;
64
- bb3: switch (b) {
65
- case 0: {
66
- const c_7 = $[7] !== b;
67
- let x$1;
68
- if (c_7) {
69
- x$1 = [];
70
- x$1.push(b);
71
- $[7] = b;
72
- $[8] = x$1;
73
- } else {
74
- x$1 = $[8];
75
- }
76
- x$0 = x$1;
77
- break bb3;
59
+ let x$0 = undefined;
60
+ bb3: switch (b) {
61
+ case 0: {
62
+ const c_4 = $[4] !== b;
63
+ let x$1;
64
+ if (c_4) {
65
+ x$1 = [];
66
+ x$1.push(b);
67
+ $[4] = b;
68
+ $[5] = x$1;
69
+ } else {
70
+ x$1 = $[5];
71
}
79
- default: {
80
- const c_9 = $[9] !== c;
81
- let x$2;
82
- if (c_9) {
83
- x$2 = [];
84
- x$2.push(c);
85
- $[9] = c;
86
- $[10] = x$2;
87
- } else {
88
- x$2 = $[10];
89
- }
90
- x$0 = x$2;
72
+ x$0 = x$1;
73
+ break bb3;
74
+ }
75
+ default: {
76
+ const c_6 = $[6] !== c;
77
+ let x$2;
78
+ if (c_6) {
79
+ x$2 = [];
80
+ x$2.push(c);
81
+ $[6] = c;
82
+ $[7] = x$2;
83
+ } else {
84
+ x$2 = $[7];
85
}
86
+ x$0 = x$2;
87
}
93
- $[4] = b;
94
- $[5] = c;
95
- $[6] = x$0;
96
- } else {
97
- x$0 = $[6];
88
}
99
- const c_11 = $[11] !== y;
100
- const c_12 = $[12] !== x$0;
89
+ const c_8 = $[8] !== y;
90
let t0;
102
- if (c_11 || c_12) {
91
+ if (c_8) {
92
t0 = (
93
<div>
94
{y}
95
{x$0}
96
</div>
97
);
109
- $[11] = y;
110
- $[12] = x$0;
111
- $[13] = t0;
98
+ $[8] = y;
99
+ $[9] = t0;
100
} else {
113
- t0 = $[13];
101
+ t0 = $[9];
102
}
103
return t0;
104
}
compiler/forget/src/__tests__/fixtures/hir/ssa-leave-case.expect.md
+6
-11
@@ -27,11 +27,10 @@ function Component(props) {
27
const c_0 = $[0] !== props.p0;
28
const c_1 = $[1] !== props.p1;
29
let x;
30
- let y$0;
30
if (c_0 || c_1) {
31
x = [];
32
const y = undefined;
34
- y$0 = y;
33
+ let y$0 = y;
34
if (props.p0) {
35
x.push(props.p1);
36
const y$1 = x;
@@ -40,26 +39,22 @@ function Component(props) {
39
$[0] = props.p0;
40
$[1] = props.p1;
41
$[2] = x;
43
- $[3] = y$0;
42
} else {
43
x = $[2];
46
- y$0 = $[3];
44
}
48
- const c_4 = $[4] !== x;
49
- const c_5 = $[5] !== y$0;
45
+ const c_3 = $[3] !== x;
46
let t0;
51
- if (c_4 || c_5) {
47
+ if (c_3) {
48
t0 = (
49
<Component>
50
{x}
51
{y$0}
52
</Component>
53
);
58
- $[4] = x;
59
- $[5] = y$0;
60
- $[6] = t0;
54
+ $[3] = x;
55
+ $[4] = t0;
56
} else {
62
- t0 = $[6];
57
+ t0 = $[4];
58
}
59
return t0;
60
}
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md
+4
-13
@@ -19,21 +19,12 @@ function foo(a, b, c) {
19
20
```javascript
21
function foo(a, b, c) {
22
- const $ = React.unstable_useMemoCache();
22
const x = a;
23
if (b) {
25
- const c_0 = $[0] !== c;
26
- let x$0;
27
- if (c_0) {
28
- x$0 = x;
29
- if (c) {
30
- const x$1 = c;
31
- x$0 = x$1;
32
- }
33
- $[0] = c;
34
- $[1] = x$0;
35
- } else {
36
- x$0 = $[1];
24
+ let x$0 = x;
25
+ if (c) {
26
+ const x$1 = c;
27
+ x$0 = x$1;
28
}
29
return x$0;
30
}
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md
+8
-23
@@ -20,31 +20,16 @@ function foo(a, b, c, d, e) {
20
21
```javascript
22
function foo(a, b, c, d, e) {
23
- const $ = React.unstable_useMemoCache();
23
const x = null;
25
- const c_0 = $[0] !== a;
26
- const c_1 = $[1] !== b;
27
- const c_2 = $[2] !== c;
28
- const c_3 = $[3] !== d;
29
- let x$0;
30
- if (c_0 || c_1 || c_2 || c_3) {
31
- x$0 = x;
32
- if (a) {
33
- const x$1 = b;
34
- x$0 = x$1;
35
- } else {
36
- if (c) {
37
- const x$2 = d;
38
- x$0 = x$2;
39
- }
40
- }
41
- $[0] = a;
42
- $[1] = b;
43
- $[2] = c;
44
- $[3] = d;
45
- $[4] = x$0;
24
+ let x$0 = x;
25
+ if (a) {
26
+ const x$1 = b;
27
+ x$0 = x$1;
28
} else {
47
- x$0 = $[4];
29
+ if (c) {
30
+ const x$2 = d;
31
+ x$0 = x$2;
32
+ }
33
}
34
return x$0;
35
}
compiler/forget/src/__tests__/fixtures/hir/ssa-renaming.expect.md
+12
-22
@@ -30,29 +30,19 @@ function foo(props) {
30
} else {
31
x = $[1];
32
}
33
- const c_2 = $[2] !== props.cond;
34
- const c_3 = $[3] !== props.foo;
35
- let x$0;
36
- if (c_2 || c_3) {
37
- x$0 = x;
38
- if (props.cond) {
39
- const c_5 = $[5] !== props.foo;
40
- let x$1;
41
- if (c_5) {
42
- x$1 = [];
43
- x$1.push(props.foo);
44
- $[5] = props.foo;
45
- $[6] = x$1;
46
- } else {
47
- x$1 = $[6];
48
- }
49
- x$0 = x$1;
33
+ let x$0 = x;
34
+ if (props.cond) {
35
+ const c_2 = $[2] !== props.foo;
36
+ let x$1;
37
+ if (c_2) {
38
+ x$1 = [];
39
+ x$1.push(props.foo);
40
+ $[2] = props.foo;
41
+ $[3] = x$1;
42
+ } else {
43
+ x$1 = $[3];
44
}
51
- $[2] = props.cond;
52
- $[3] = props.foo;
53
- $[4] = x$0;
54
- } else {
55
- x$0 = $[4];
45
+ x$0 = x$1;
46
}
47
return x$0;
48
}
compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md
+6
-15
@@ -23,23 +23,14 @@ function Foo(cond) {
23
function log() {}
24
25
function Foo(cond) {
26
- const $ = React.unstable_useMemoCache();
26
const str = "";
28
- const c_0 = $[0] !== cond;
29
- let str$0;
30
- if (c_0) {
31
- str$0 = str;
32
- if (cond) {
33
- const str_0 = "other test";
34
- log(str_0);
35
- } else {
36
- const str$1 = "fallthrough test";
37
- str$0 = str$1;
38
- }
39
- $[0] = cond;
40
- $[1] = str$0;
27
+ let str$0 = str;
28
+ if (cond) {
29
+ const str_0 = "other test";
30
+ log(str_0);
31
} else {
42
- str$0 = $[1];
32
+ const str$1 = "fallthrough test";
33
+ str$0 = str$1;
34
}
35
36
log(str$0);
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+14
-19
@@ -36,11 +36,10 @@ function Component(props) {
36
const c_0 = $[0] !== props.p0;
37
const c_1 = $[1] !== props.p2;
38
let x;
39
- let y$0;
39
if (c_0 || c_1) {
40
x = [];
41
const y = undefined;
43
- y$0 = y;
42
+ let y$0 = y;
43
bb1: switch (props.p0) {
44
case 1: {
45
break bb1;
@@ -48,11 +47,11 @@ function Component(props) {
47
case true: {
48
x.push(props.p2);
49
let y$1;
51
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
50
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
51
y$1 = [];
53
- $[4] = y$1;
52
+ $[3] = y$1;
53
} else {
55
- y$1 = $[4];
54
+ y$1 = $[3];
55
}
56
y$0 = y$1;
57
break bb1;
@@ -68,31 +67,27 @@ function Component(props) {
67
$[0] = props.p0;
68
$[1] = props.p2;
69
$[2] = x;
71
- $[3] = y$0;
70
} else {
71
x = $[2];
74
- y$0 = $[3];
72
}
76
- const c_5 = $[5] !== x;
73
+ const c_4 = $[4] !== x;
74
let child;
78
- if (c_5) {
75
+ if (c_4) {
76
child = <Component data={x}></Component>;
80
- $[5] = x;
81
- $[6] = child;
77
+ $[4] = x;
78
+ $[5] = child;
79
} else {
83
- child = $[6];
80
+ child = $[5];
81
}
82
y$0.push(props.p4);
86
- const c_7 = $[7] !== y$0;
87
- const c_8 = $[8] !== child;
83
+ const c_6 = $[6] !== child;
84
let t0;
89
- if (c_7 || c_8) {
85
+ if (c_6) {
86
t0 = <Component data={y$0}>{child}</Component>;
91
- $[7] = y$0;
92
- $[8] = child;
93
- $[9] = t0;
87
+ $[6] = child;
88
+ $[7] = t0;
89
} else {
95
- t0 = $[9];
90
+ t0 = $[7];
91
}
92
return t0;
93
}
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+11
-16
@@ -32,11 +32,10 @@ function Component(props) {
32
const c_1 = $[1] !== props.p2;
33
const c_2 = $[2] !== props.p3;
34
let x;
35
- let y$0;
35
if (c_0 || c_1 || c_2) {
36
x = [];
37
const y = undefined;
39
- y$0 = y;
38
+ let y$0 = y;
39
switch (props.p0) {
40
case true: {
41
x.push(props.p2);
@@ -51,31 +50,27 @@ function Component(props) {
50
$[1] = props.p2;
51
$[2] = props.p3;
52
$[3] = x;
54
- $[4] = y$0;
53
} else {
54
x = $[3];
57
- y$0 = $[4];
55
}
59
- const c_5 = $[5] !== x;
56
+ const c_4 = $[4] !== x;
57
let child;
61
- if (c_5) {
58
+ if (c_4) {
59
child = <Component data={x}></Component>;
63
- $[5] = x;
64
- $[6] = child;
60
+ $[4] = x;
61
+ $[5] = child;
62
} else {
66
- child = $[6];
63
+ child = $[5];
64
}
65
y$0.push(props.p4);
69
- const c_7 = $[7] !== y$0;
70
- const c_8 = $[8] !== child;
66
+ const c_6 = $[6] !== child;
67
let t0;
72
- if (c_7 || c_8) {
68
+ if (c_6) {
69
t0 = <Component data={y$0}>{child}</Component>;
74
- $[7] = y$0;
75
- $[8] = child;
76
- $[9] = t0;
70
+ $[6] = child;
71
+ $[7] = t0;
72
} else {
78
- t0 = $[9];
73
+ t0 = $[7];
74
}
75
return t0;
76
}