@samitouri / QOS-React-2 / commits / 178bde3495

Run LeaveSSA prior to analyzing reactive scopes

Reorders LeaveSSA so that it runs before we begin evaluating reactive scopes. Note that reactive scopes must span the full construction of each variable — for variables with a phi, this must span the declaration and all assignments of the phi operands. And that's exactly what the new LeaveSSA does! LeaveSSA removes phi nodes and ensure that all versions of a variable which flow into a phi have been assigned a single canonical identifier (with an appropriate mutable range). This PR includes this and some related changes: * Reorders the pass * Changes hir-test to print the final HIR, eg just prior to codegen * Teaches LeaveSSA to update the mutable range of the canonical identifiers it assigns, based on the min/max of the variables assigned.

Joe Savona committed Dec 20, 2022 at 15:58 UTC 178bde349598f277e1432c3c1baf72f3c535a66a
22 files changed +1053 -609
compiler/forget/src/SSA/LeaveSSA.ts
+218 -92
@@ -24,18 +24,77 @@ import {
24 } from "../HIR/visitors";
25
26 /**
27 - * Removes SSA form by creating unique variable declarations for the versions of each variables.
28 - * - Versions of a variable that do not flow into a phi node are each assigned their own const variable
29 - * declaration.
30 - * - If multiple versions of a variable flow into some phi node, then all those versions are reassigned to
31 - * the phi version. A single declaration is created at the same block scope as the phi, prior to any of the
32 - * assignments.
27 + * Removes SSA form by converting all phis into explicit bindings and assignments. There are two main categories
28 + * of phis:
29 + *
30 + * ## Reassignments (operands are independently memoizable)
31 + *
32 + * These are phis that occur after some high-level control flow such as an if, switch, or loop. These phis are rewritten
33 + * to add a new `let` binding for the phi id prior to the control flow node (ie prior to the if/switch),
34 + * and to add a reassignment to that let binding in each of the phi's predecessors.
35 + *
36 + * Example:
37 + *
38 + * ```javascript
39 + * // Input
40 + * let x1 = null;
41 + * if (a) {
42 + * x2 = b;
43 + * } else {
44 + * x3 = c;
45 + * }
46 + * x4 = phi(x2, x3);
47 + * return x4;
48 + *
49 + * // Output
50 + * const x1 = null;
51 + * let x4; // synthesized binding for the phi identifier
52 + * if (a) {
53 + * x2 = b;
54 + * x4 = x2;; // sythesized assignment to the phi identifier
55 + * } else {
56 + * x3 = c;
57 + * x4 = x3; // synthesized assignment
58 + * }
59 + * // phi removed
60 + * return x4;
61 + * ```
62 + *
63 + * ## Rewrites (operands are not independently memoizable)
64 + *
65 + * Phis that occur inside loop constructs cannot use the reassignment strategy, because there isn't an appropriate place
66 + * to add the new let binding. Instead, we select a single "canonical" id for these phis which is the operand that is
67 + * defined first. Then, all assignments and references for any of the phi ir and operands are rewritten to reference
68 + * the canonical id instead.
69 + *
70 + * Example:
71 + *
72 + * ```javascript
73 + * // Input
74 + * for (
75 + * let i1 = 0;
76 + * { i2 = phi(i1, i2); i2 < 10 }; // note the phi in the test block
77 + * i2 += 1
78 + * ) { ... }
79 + *
80 + * // Output
81 + * for (
82 + * let i1 = 0; // i1 is defined first, so it becomes the canonical id
83 + * i1 < 10; // rewritten to canonical id
84 + * i1 += 1 // rewritten to canonical id
85 + * )
86 + * ```
87 */
88 export function leaveSSA(fn: HIRFunction) {
35 - // Maps identifiers that appear as a phi or phi operand to a single canonical identifier
36 - // for all instances.
37 - const variableMapping: Map<Identifier, Identifier> = new Map();
38 - const hasDeclaration: Set<Identifier> = new Set();
89 + // For "memoizable" phis (see docblock), this maps the original identifiers to the identifier they
90 + // should be reassigned to. The keys are phi operands, and the values are the phi id to which
91 + // they are being explicitly reassigned.
92 + const reassignments: Map<Identifier, Identifier> = new Map();
93 +
94 + // For non-memoizable phis, this maps original identifiers to the identifier they should be
95 + // *rewritten* to. The keys are the original identifiers, and the value will be _either_ the
96 + // phi id or, more typically, the operand that was defined prior to the phi.
97 + const rewrites: Map<Identifier, Identifier> = new Map();
98
99 for (const [, block] of fn.body.blocks) {
100 invariant(
@@ -43,15 +102,11 @@ export function leaveSSA(fn: HIRFunction) {
102 "Expected all phis to be cleared by predecessors"
103 );
104
46 - // Identifiers (from phis) that *may* need a new `let` declaration created. If the original
47 - // variable declaration flows into the phi, then we can reuse its declaration - this is
48 - // discovered during iteration of instructions.
49 - const needsDeclaration: Set<Identifier> = new Set();
50 -
105 // Find any phi nodes which need a variable declaration in the current block
106 // This includes phis in fallthrough nodes, or blocks that form part of control flow
107 // such as for or while (and later if/switch).
54 - const phis: Array<Phi> = [];
108 + const reassignmentPhis: Array<Phi> = [];
109 + const rewritePhis: Array<Phi> = [];
110 const terminal = block.terminal;
111 if (
112 (terminal.kind === "if" ||
@@ -61,49 +116,153 @@ export function leaveSSA(fn: HIRFunction) {
116 terminal.fallthrough !== null
117 ) {
118 const fallthrough = fn.body.blocks.get(terminal.fallthrough)!;
64 - phis.push(...fallthrough.phis);
119 + reassignmentPhis.push(...fallthrough.phis);
120 fallthrough.phis.clear();
121 }
122 if (terminal.kind === "while" || terminal.kind === "for") {
123 const test = fn.body.blocks.get(terminal.test)!;
69 - phis.push(...test.phis);
124 + rewritePhis.push(...test.phis);
125 test.phis.clear();
126
127 const loop = fn.body.blocks.get(terminal.loop)!;
73 - phis.push(...loop.phis);
128 + rewritePhis.push(...loop.phis);
129 loop.phis.clear();
130 }
131 if (terminal.kind === "for") {
132 const init = fn.body.blocks.get(terminal.init)!;
78 - phis.push(...init.phis);
133 + rewritePhis.push(...init.phis);
134 init.phis.clear();
135
136 const update = fn.body.blocks.get(terminal.update)!;
82 - phis.push(...update.phis);
137 + rewritePhis.push(...update.phis);
138 update.phis.clear();
139
140 // find declarations in the for init
141 for (const instr of init.instructions) {
142 if (instr.lvalue !== null && instr.lvalue.place.memberPath === null) {
88 - hasDeclaration.add(instr.lvalue.place.identifier);
143 + // hasDeclaration.add(instr.lvalue.place.identifier);
144 }
145 }
146 }
147
93 - // For each phi, determine a canonical identifier to use for versions of the variable
94 - // that appear in the phi (as its output id and operands). If this is the first time
95 - // we're seeing the phi id, then we may need to generate a new variable declaration
96 - // Note that there can be multiple phi nodes for the same variable, we capture the
97 - // outermost scope by visiting predecessor blocks first.
98 - for (const phi of phis) {
99 - let canonicalId = variableMapping.get(phi.id);
148 + for (const phi of reassignmentPhis) {
149 + // In some cases one of the phi operands can be defined *before* the let binding
150 + // we will generate. For example, a variable that is only rebound in one branch of
151 + // an if but not another. In this case we populate the let binding with this initial
152 + // value rather than generate an extra assignment.
153 + let initOperand: Identifier | null = null;
154 +
155 + // Determine the canonical id to use for this phi. In general this is the phi id,
156 + // but if one phi flows into another as an operand, this will be the final phi.
157 + let canonicalId = reassignments.get(phi.id);
158 + if (canonicalId === undefined) {
159 + canonicalId = phi.id;
160 + canonicalId.mutableRange.start = Math.min(
161 + canonicalId.mutableRange.start,
162 + terminal.id
163 + ) as InstructionId;
164 + reassignments.set(phi.id, canonicalId);
165 + }
166 +
167 + // all versions of the variable need to be remapped to the canonical id
168 + // also extend the mutable range of the canonical id based on the min/max
169 + // of the ranges of its operands
170 + let start = canonicalId.mutableRange.start as number;
171 + let end = canonicalId.mutableRange.end as number;
172 + for (const [, operand] of phi.operands) {
173 + start = Math.min(start, operand.mutableRange.start);
174 + end = Math.max(end, operand.mutableRange.end);
175 + reassignments.set(operand, canonicalId);
176 +
177 + if (operand.mutableRange.start < terminal.id) {
178 + invariant(
179 + initOperand === null,
180 + "A phi cannot have two operands initialized before its declaration"
181 + );
182 + initOperand = operand;
183 + }
184 + }
185 + canonicalId.mutableRange.start = makeInstructionId(start);
186 + canonicalId.mutableRange.end = makeInstructionId(end);
187 +
188 + // If this phi id is the canonical id we need to generate a let binding for it
189 + // (otherwise, it means this phi merges into some other phi which already generated
190 + // a binding
191 + if (canonicalId === phi.id) {
192 + const instr: Instruction = {
193 + // NOTE: reuse the terminal id since these lets must be scoped with the terminal anyway.
194 + // the mutable range of this canonical id must by definition span from the binding (before
195 + // the if) to the phi, so it's safe to reuse the terminal's id.
196 + id: block.terminal.id,
197 + lvalue: {
198 + place: {
199 + kind: "Identifier",
200 + memberPath: null,
201 + identifier: canonicalId,
202 + effect: Effect.Mutate,
203 + loc: GeneratedSource,
204 + },
205 + kind: InstructionKind.Let,
206 + },
207 + value:
208 + initOperand !== null
209 + ? {
210 + kind: "Identifier",
211 + memberPath: null,
212 + identifier: initOperand,
213 + effect: Effect.Read,
214 + loc: GeneratedSource,
215 + }
216 + : {
217 + kind: "Primitive",
218 + // TODO: consider leaving the variable uninitialized rather than explicitly undefined.
219 + value: undefined,
220 + loc: GeneratedSource,
221 + },
222 + loc: GeneratedSource,
223 + };
224 + block.instructions.push(instr);
225 + }
226 +
227 + // Generate an assignment in each predecessor
228 + for (const [predecessor, operand] of phi.operands) {
229 + if (operand === initOperand) {
230 + continue;
231 + }
232 + const instr: Instruction = {
233 + id: predecessor.terminal.id,
234 + lvalue: {
235 + place: {
236 + kind: "Identifier",
237 + memberPath: null,
238 + identifier: canonicalId,
239 + effect: Effect.Mutate,
240 + loc: GeneratedSource,
241 + },
242 + kind: InstructionKind.Reassign,
243 + },
244 + value: {
245 + kind: "Identifier",
246 + memberPath: null,
247 + identifier: operand,
248 + effect: Effect.Read,
249 + loc: GeneratedSource,
250 + },
251 + loc: GeneratedSource,
252 + };
253 + predecessor.instructions.push(instr);
254 + }
255 + }
256 +
257 + // Similar logic for rewrite phis that occur in loops, except that instead of a new let binding
258 + // we pick one of the operands as the canonical id, and rewrite all references to the other
259 + // operands and the phi to reference this canonical id.
260 + for (const phi of rewritePhis) {
261 + let canonicalId = rewrites.get(phi.id);
262 if (canonicalId === undefined) {
101 - // Determine a new canonical id. We use the id/operand whose id is lowest,
102 - // which ensures that _if_ the original variable declaration is one of the
103 - // options we'll choose it and can reuse the declaration.
263 canonicalId = phi.id;
264 for (const [, operand] of phi.operands) {
106 - let canonicalOperand = variableMapping.get(operand) ?? operand;
265 + let canonicalOperand = rewrites.get(operand) ?? operand;
266 if (canonicalOperand.id < canonicalId.id) {
267 canonicalId = canonicalOperand;
268 }
@@ -112,10 +271,7 @@ export function leaveSSA(fn: HIRFunction) {
271 canonicalId.mutableRange.start,
272 terminal.id
273 ) as InstructionId;
115 - variableMapping.set(phi.id, canonicalId);
116 - if (!hasDeclaration.has(canonicalId)) {
117 - needsDeclaration.add(canonicalId);
118 - }
274 + rewrites.set(phi.id, canonicalId);
275 }
276
277 // all versions of the variable need to be remapped to the canonical id
@@ -126,79 +282,49 @@ export function leaveSSA(fn: HIRFunction) {
282 for (const [, operand] of phi.operands) {
283 start = Math.min(start, operand.mutableRange.start);
284 end = Math.max(end, operand.mutableRange.end);
129 - variableMapping.set(operand, canonicalId);
285 + rewrites.set(operand, canonicalId);
286 }
287 canonicalId.mutableRange.start = makeInstructionId(start);
288 canonicalId.mutableRange.end = makeInstructionId(end);
289 }
290
135 - // Visit instructions and rewrite identifiers based on the variable mapping
136 - // updated above.
291 + // Finally, iterate the instructions and perform any rewrites as well as converting
292 + // SSA variables to `const` where possible
293 for (const instr of block.instructions) {
294 const { lvalue, value } = instr;
295 if (lvalue !== null) {
140 - updatePlace(lvalue.place, variableMapping);
141 - if (lvalue.place.memberPath === null) {
142 - if (!variableMapping.has(lvalue.place.identifier)) {
143 - // This variable does not flow into a phi, therefore there
144 - // is no reassignment. Convert the declaration to a const.
145 - lvalue.kind = InstructionKind.Const;
146 - } else if (
147 - variableMapping.get(lvalue.place.identifier) ===
148 - lvalue.place.identifier
149 - ) {
150 - // This is an existing declaration we can reuse as the canonical declaration for its
151 - // phi. Note, the declaration must already be a `let` or else it would be invalid to
152 - // reassign the variable in the first place.
153 - needsDeclaration.delete(lvalue.place.identifier);
154 - }
155 - hasDeclaration.add(lvalue.place.identifier);
296 + rewritePlace(lvalue.place, rewrites);
297 + if (
298 + lvalue.kind !== InstructionKind.Const &&
299 + lvalue.place.memberPath === null &&
300 + !rewrites.has(lvalue.place.identifier) &&
301 + (!reassignments.has(lvalue.place.identifier) ||
302 + reassignments.get(lvalue.place.identifier) !==
303 + lvalue.place.identifier)
304 + ) {
305 + // Convert individual SSA reassignments into const declarations
306 + // otherwise the code would be invalid, since the SSA identifiers
307 + // aren't otherwise declared.
308 + // TODO @josephsavona: do this in EnterSSA instead?
309 + lvalue.kind = InstructionKind.Const;
310 }
311 }
158 - for (const operand of eachInstructionValueOperand(value)) {
159 - updatePlace(operand, variableMapping);
312 + for (const operand of eachInstructionValueOperand(instr.value)) {
313 + rewritePlace(operand, rewrites);
314 }
315 }
162 -
316 for (const operand of eachTerminalOperand(terminal)) {
164 - operand.identifier =
165 - variableMapping.get(operand.identifier) ?? operand.identifier;
166 - }
167 -
168 - // Generate new let declarations for any remaining phi variables
169 - for (const identifier of needsDeclaration) {
170 - const instr: Instruction = {
171 - // NOTE: reuse the terminal id since these lets must be scoped with the terminal anyway
172 - // the only reason they exist is that there is a scope that will span the control flow.
173 - id: block.terminal.id,
174 - lvalue: {
175 - place: {
176 - kind: "Identifier",
177 - memberPath: null,
178 - identifier,
179 - effect: Effect.Mutate,
180 - loc: GeneratedSource,
181 - },
182 - kind: InstructionKind.Let,
183 - },
184 - value: {
185 - kind: "Primitive",
186 - value: undefined,
187 - loc: GeneratedSource,
188 - },
189 - loc: GeneratedSource,
190 - };
191 - block.instructions.push(instr);
317 + rewritePlace(operand, rewrites);
318 }
319 }
320 }
321
196 -function updatePlace(
197 - place: Place,
198 - variableMapping: Map<Identifier, Identifier>
199 -) {
322 +// Rewrite @param place's identifier based on the given rewrite mapping, if the identifier
323 +// is present. Also expands the mutable range of the target identifier to include the
324 +// place's range.
325 +function rewritePlace(place: Place, rewrites: Map<Identifier, Identifier>) {
326 const prevIdentifier = place.identifier;
201 - const nextIdentifier = variableMapping.get(prevIdentifier);
327 + const nextIdentifier = rewrites.get(prevIdentifier);
328 if (nextIdentifier === undefined || nextIdentifier === prevIdentifier) {
329 return;
330 }
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+24 -20
@@ -55,19 +55,21 @@ bb5:
55 [12] Const mutate item$40_@0:TPrimitive[3:33] = Call read items$30.at(read i$36_@0:TPrimitive)
56 [13] Const mutate $41:TPrimitive = null
57 [14] Const mutate $42:TPrimitive = Binary read item$40_@0:TPrimitive == read $41:TPrimitive
58 - [15] Let mutate $43_@0:TPrimitive[3:33] = undefined
58 + [15] Let mutate $46_@0[3:33] = undefined
59 [15] If (read $42:TPrimitive) then:bb10 else:bb11 fallthrough=bb9
60 bb10:
61 predecessor blocks: bb5
62 - [16] Const mutate $43_@0:TPrimitive[3:33] = read $42:TPrimitive
62 + [16] Const mutate $43:TPrimitive = read $42:TPrimitive
63 + [17] Reassign mutate $46_@0[3:33] = read $43:TPrimitive
64 [17] Goto bb9
65 bb11:
66 predecessor blocks: bb5
66 - [18] Const mutate $43_@0:TPrimitive[3:33] = Call mutate seen$33_@0.has(mutate item$40_@0:TPrimitive)
67 + [18] Const mutate $45_@0[3:33] = Call mutate seen$33_@0.has(mutate item$40_@0:TPrimitive)
68 + [19] Reassign mutate $46_@0[3:33] = read $45_@0
69 [19] Goto bb9
70 bb9:
71 predecessor blocks: bb10 bb11
70 - [20] If (read $43_@0:TPrimitive) then:bb7 else:bb6 fallthrough=bb6
72 + [20] If (read $46_@0) then:bb7 else:bb6 fallthrough=bb6
73 bb7:
74 predecessor blocks: bb9
75 [21] Goto(Continue) bb4
@@ -75,8 +77,8 @@ bb6:
77 predecessor blocks: bb9
78 [22] Call mutate seen$33_@0.add(mutate item$40_@0:TPrimitive)
79 [23] Const mutate $49:TPrimitive = "div"
78 - [24] Const mutate $50_@3 = JSX <read $49:TPrimitive>{freeze item$40_@0:TPrimitive}</read $49:TPrimitive>
79 - [25] Call mutate renderedItems$32_@0.push(read $50_@3)
80 + [24] Const mutate $50_@4 = JSX <read $49:TPrimitive>{freeze item$40_@0:TPrimitive}</read $49:TPrimitive>
81 + [25] Call mutate renderedItems$32_@0.push(read $50_@4)
82 [26] Const mutate $55:TPrimitive = Binary read renderedItems$32_@0.length >= read max$35_@2:TPrimitive
83 [27] If (read $55:TPrimitive) then:bb2 else:bb12 fallthrough=bb12
84 bb12:
@@ -95,11 +97,11 @@ bb2:
97 [35] Const mutate $68 = "\n "
98 [36] Const mutate $69:TPrimitive = "h1"
99 [37] Const mutate $70 = " Items"
98 - [38] Const mutate t7$71_@4 = JSX <read $69:TPrimitive>{freeze count$66:TProp}{read $70}</read $69:TPrimitive>
100 + [38] Const mutate t7$71_@5 = JSX <read $69:TPrimitive>{freeze count$66:TProp}{read $70}</read $69:TPrimitive>
101 [39] Const mutate $72 = "\n "
102 [40] Const mutate $73 = "\n "
101 - [41] Const mutate t10$74_@5 = JSX <read $67:TPrimitive>{read $68}{read t7$71_@4}{read $72}{freeze renderedItems$32_@0:TPrimitive}{read $73}</read $67:TPrimitive>
102 - [42] Return read t10$74_@5
103 + [41] Const mutate t10$74_@6 = JSX <read $67:TPrimitive>{read $68}{read t7$71_@5}{read $72}{freeze renderedItems$32_@0:TPrimitive}{read $73}</read $67:TPrimitive>
104 + [42] Return read t10$74_@6
105 ```
106
107 ## Reactive Scopes
@@ -130,19 +132,21 @@ function Component(
132 [12] Const mutate item$40_@0:TPrimitive[3:33] = Call read items$30.at(read i$36_@0:TPrimitive)
133 [13] Const mutate $41:TPrimitive = null
134 [14] Const mutate $42:TPrimitive = Binary read item$40_@0:TPrimitive == read $41:TPrimitive
133 - [15] Let mutate $43_@0:TPrimitive[3:33] = undefined
135 + [15] Let mutate $46_@0[3:33] = undefined
136 if (read $42:TPrimitive) {
135 - [16] Const mutate $43_@0:TPrimitive[3:33] = read $42:TPrimitive
137 + [16] Const mutate $43:TPrimitive = read $42:TPrimitive
138 + [17] Reassign mutate $46_@0[3:33] = read $43:TPrimitive
139 } else {
137 - [18] Const mutate $43_@0:TPrimitive[3:33] = Call mutate seen$33_@0.has(mutate item$40_@0:TPrimitive)
140 + [18] Const mutate $45_@0[3:33] = Call mutate seen$33_@0.has(mutate item$40_@0:TPrimitive)
141 + [19] Reassign mutate $46_@0[3:33] = read $45_@0
142 }
139 - if (read $43_@0:TPrimitive) {
143 + if (read $46_@0) {
144 continue
145 }
146 [22] Call mutate seen$33_@0.add(mutate item$40_@0:TPrimitive)
147 [23] Const mutate $49:TPrimitive = "div"
144 - [24] Const mutate $50_@3 = JSX <read $49:TPrimitive>{freeze item$40_@0:TPrimitive}</read $49:TPrimitive>
145 - [25] Call mutate renderedItems$32_@0.push(read $50_@3)
148 + [24] Const mutate $50_@4 = JSX <read $49:TPrimitive>{freeze item$40_@0:TPrimitive}</read $49:TPrimitive>
149 + [25] Call mutate renderedItems$32_@0.push(read $50_@4)
150 [26] Const mutate $55:TPrimitive = Binary read renderedItems$32_@0.length >= read max$35_@2:TPrimitive
151 if (read $55:TPrimitive) {
152 break
@@ -154,15 +158,15 @@ function Component(
158 [35] Const mutate $68 = "\n "
159 [36] Const mutate $69:TPrimitive = "h1"
160 [37] Const mutate $70 = " Items"
157 - scope @4 [38:39] deps=[freeze count$66:TProp] out=[$71_@4] {
158 - [38] Const mutate $71_@4 = JSX <read $69:TPrimitive>{freeze count$66:TProp}{read $70}</read $69:TPrimitive>
161 + scope @5 [38:39] deps=[freeze count$66:TProp] out=[$71_@5] {
162 + [38] Const mutate $71_@5 = JSX <read $69:TPrimitive>{freeze count$66:TProp}{read $70}</read $69:TPrimitive>
163 }
164 [39] Const mutate $72 = "\n "
165 [40] Const mutate $73 = "\n "
162 - scope @5 [41:42] deps=[read $71_@4, freeze renderedItems$32_@0:TPrimitive] out=[$74_@5] {
163 - [41] Const mutate $74_@5 = JSX <read $67:TPrimitive>{read $68}{read $71_@4}{read $72}{freeze renderedItems$32_@0:TPrimitive}{read $73}</read $67:TPrimitive>
166 + scope @6 [41:42] deps=[read $71_@5, freeze renderedItems$32_@0:TPrimitive] out=[$74_@6] {
167 + [41] Const mutate $74_@6 = JSX <read $67:TPrimitive>{read $68}{read $71_@5}{read $72}{freeze renderedItems$32_@0:TPrimitive}{read $73}</read $67:TPrimitive>
168 }
165 - return read $74_@5
169 + return read $74_@6
170 }
171
172 ```
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+41 -25
@@ -29,22 +29,24 @@ bb0:
29 [1] Const mutate cond$8:TProp = read props$7.cond
30 [2] Const mutate x$9:TProp = read props$7.x
31 [3] Const mutate a$10:TPrimitive = undefined
32 - [4] Let mutate a$11_@0:TProp[4:9] = undefined
32 + [4] Let mutate a$14_@0[4:9] = undefined
33 [4] If (read cond$8:TProp) then:bb2 else:bb3 fallthrough=bb1
34 bb2:
35 predecessor blocks: bb0
36 - [5] Reassign mutate a$11_@0:TProp[4:9] = read x$9:TProp
36 + [5] Const mutate a$11:TProp = read x$9:TProp
37 + [6] Reassign mutate a$14_@0[4:9] = read a$11:TProp
38 [6] Goto bb1
39 bb3:
40 predecessor blocks: bb0
40 - [7] Reassign mutate a$11_@0:TProp[4:9] = Array []
41 + [7] Const mutate a$12_@1 = Array []
42 + [8] Reassign mutate a$14_@0[4:9] = read a$12_@1
43 [8] Goto bb1
44 bb1:
45 predecessor blocks: bb2 bb3
44 - [9] Call read useFreeze$5:TFunction(freeze a$11_@0:TProp)
45 - [10] Call read useFreeze$5:TFunction(read a$11_@0:TProp)
46 - [11] Call mutate call$6:TFunction(read a$11_@0:TProp)
47 - [12] Return read a$11_@0:TProp
46 + [9] Call read useFreeze$5:TFunction(freeze a$14_@0)
47 + [10] Call read useFreeze$5:TFunction(read a$14_@0)
48 + [11] Call mutate call$6:TFunction(read a$14_@0)
49 + [12] Return read a$14_@0
50 ```
51
52 ## Reactive Scopes
@@ -56,18 +58,22 @@ function Component(
58 [1] Const mutate cond$8:TProp = read props$7.cond
59 [2] Const mutate x$9:TProp = read props$7.x
60 [3] Const mutate a$10:TPrimitive = undefined
59 - scope @0 [4:9] deps=[read cond$8:TProp, read x$9:TProp] out=[a$11_@0] {
60 - [4] Let mutate a$11_@0:TProp[4:9] = undefined
61 + scope @0 [4:9] deps=[read cond$8:TProp, read x$9:TProp] out=[a$14_@0] {
62 + [4] Let mutate a$14_@0[4:9] = undefined
63 if (read cond$8:TProp) {
62 - [5] Reassign mutate a$11_@0:TProp[4:9] = read x$9:TProp
64 + [5] Const mutate a$11:TProp = read x$9:TProp
65 + [6] Reassign mutate a$14_@0[4:9] = read a$11:TProp
66 } else {
64 - [7] Reassign mutate a$11_@0:TProp[4:9] = Array []
67 + scope @1 [7:8] deps=[] out=[a$12_@1] {
68 + [7] Const mutate a$12_@1 = Array []
69 + }
70 + [8] Reassign mutate a$14_@0[4:9] = read a$12_@1
71 }
72 }
67 - [9] Call read useFreeze$5:TFunction(freeze a$11_@0:TProp)
68 - [10] Call read useFreeze$5:TFunction(read a$11_@0:TProp)
69 - [11] Call mutate call$6:TFunction(read a$11_@0:TProp)
70 - return read a$11_@0:TProp
73 + [9] Call read useFreeze$5:TFunction(freeze a$14_@0)
74 + [10] Call read useFreeze$5:TFunction(read a$14_@0)
75 + [11] Call mutate call$6:TFunction(read a$14_@0)
76 + return read a$14_@0
77 }
78
79 ```
@@ -82,27 +88,37 @@ function Component$0(props$7) {
88 const a$10 = undefined;
89 const c_0 = $[0] !== cond$8;
90 const c_1 = $[1] !== x$9;
85 - let a$11;
91 + let a$14;
92 if (c_0 || c_1) {
87 - a$11 = undefined;
93 + a$14 = undefined;
94
95 if (cond$8) {
90 - a$11 = x$9;
96 + const a$11 = x$9;
97 + a$14 = a$11;
98 } else {
92 - a$11 = [];
99 + let a$12;
100 +
101 + if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
102 + a$12 = [];
103 + $[3] = a$12;
104 + } else {
105 + a$12 = $[3];
106 + }
107 +
108 + a$14 = a$12;
109 }
110
111 $[0] = cond$8;
112 $[1] = x$9;
97 - $[2] = a$11;
113 + $[2] = a$14;
114 } else {
99 - a$11 = $[2];
115 + a$14 = $[2];
116 }
117
102 - useFreeze$5(a$11);
103 - useFreeze$5(a$11);
104 - call$6(a$11);
105 - return a$11;
118 + useFreeze$5(a$14);
119 + useFreeze$5(a$14);
120 + call$6(a$14);
121 + return a$14;
122 }
123
124 ```
compiler/forget/src/__tests__/fixtures/hir/logical-expression.expect.md
+93 -48
@@ -24,19 +24,21 @@ function g() {}
24 ```
25 bb0:
26 [1] Const mutate t0$5_@0 = Call mutate f$1:TFunction()
27 - [2] Let mutate t2$6_@1[2:7] = undefined
27 + [2] Let mutate t2$8_@1[2:7] = undefined
28 [2] If (read t0$5_@0) then:bb2 else:bb3 fallthrough=bb1
29 bb2:
30 predecessor blocks: bb0
31 - [3] Const mutate t2$6_@1[2:7] = Call mutate g$4:TFunction()
31 + [3] Const mutate t3$6_@2 = Call mutate g$4:TFunction()
32 + [4] Reassign mutate t2$8_@1[2:7] = read t3$6_@2
33 [4] Goto bb1
34 bb3:
35 predecessor blocks: bb0
35 - [5] Const mutate t2$6_@1[2:7] = read t0$5_@0
36 + [5] Const mutate $7 = read t0$5_@0
37 + [6] Reassign mutate t2$8_@1[2:7] = read $7
38 [6] Goto bb1
39 bb1:
40 predecessor blocks: bb2 bb3
39 - [7] Return freeze t2$6_@1
41 + [7] Return freeze t2$8_@1
42 ```
43
44 ## Reactive Scopes
@@ -47,15 +49,19 @@ function And(
49 scope @0 [1:2] deps=[] out=[$5_@0] {
50 [1] Const mutate $5_@0 = Call mutate f$1:TFunction()
51 }
50 - scope @1 [2:7] deps=[read $5_@0] out=[$6_@1] {
51 - [2] Let mutate $6_@1[2:7] = undefined
52 + scope @1 [2:7] deps=[read $5_@0] out=[$8_@1] {
53 + [2] Let mutate $8_@1[2:7] = undefined
54 if (read $5_@0) {
53 - [3] Const mutate $6_@1[2:7] = Call mutate g$4:TFunction()
55 + scope @2 [3:4] deps=[] out=[$6_@2] {
56 + [3] Const mutate $6_@2 = Call mutate g$4:TFunction()
57 + }
58 + [4] Reassign mutate $8_@1[2:7] = read $6_@2
59 } else {
55 - [5] Const mutate $6_@1[2:7] = read $5_@0
60 + [5] Const mutate $7 = read $5_@0
61 + [6] Reassign mutate $8_@1[2:7] = read $7
62 }
63 }
58 - return freeze $6_@1
64 + return freeze $8_@1
65 }
66
67 ```
@@ -74,24 +80,33 @@ function And$0() {
80 }
81
82 const c_1 = $[1] !== t0$5;
77 - let t2$6;
83 + let t2$8;
84
85 if (c_1) {
80 - t2$6 = undefined;
86 + t2$8 = undefined;
87
88 if (t0$5) {
83 - t2$6 = g$4();
89 + let t3$6;
90 +
91 + if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
92 + t3$6 = g$4();
93 + $[3] = t3$6;
94 + } else {
95 + t3$6 = $[3];
96 + }
97 +
98 + t2$8 = t3$6;
99 } else {
85 - t2$6 = t0$5;
100 + t2$8 = t0$5;
101 }
102
103 $[1] = t0$5;
89 - $[2] = t2$6;
104 + $[2] = t2$8;
105 } else {
91 - t2$6 = $[2];
106 + t2$8 = $[2];
107 }
108
94 - return t2$6;
109 + return t2$8;
110 }
111
112 ```
@@ -100,19 +115,21 @@ function And$0() {
115 ```
116 bb0:
117 [1] Const mutate t0$5_@0 = Call mutate f$1:TFunction()
103 - [2] Let mutate t2$6_@1[2:7] = undefined
118 + [2] Let mutate t2$8_@1[2:7] = undefined
119 [2] If (read t0$5_@0) then:bb2 else:bb3 fallthrough=bb1
120 bb2:
121 predecessor blocks: bb0
107 - [3] Const mutate t2$6_@1[2:7] = read t0$5_@0
122 + [3] Const mutate $6 = read t0$5_@0
123 + [4] Reassign mutate t2$8_@1[2:7] = read $6
124 [4] Goto bb1
125 bb3:
126 predecessor blocks: bb0
111 - [5] Const mutate t2$6_@1[2:7] = Call mutate g$4:TFunction()
127 + [5] Const mutate t3$7_@2 = Call mutate g$4:TFunction()
128 + [6] Reassign mutate t2$8_@1[2:7] = read t3$7_@2
129 [6] Goto bb1
130 bb1:
131 predecessor blocks: bb2 bb3
115 - [7] Return freeze t2$6_@1
132 + [7] Return freeze t2$8_@1
133 ```
134
135 ## Reactive Scopes
@@ -123,15 +140,19 @@ function Or(
140 scope @0 [1:2] deps=[] out=[$5_@0] {
141 [1] Const mutate $5_@0 = Call mutate f$1:TFunction()
142 }
126 - scope @1 [2:7] deps=[read $5_@0] out=[$6_@1] {
127 - [2] Let mutate $6_@1[2:7] = undefined
143 + scope @1 [2:7] deps=[read $5_@0] out=[$8_@1] {
144 + [2] Let mutate $8_@1[2:7] = undefined
145 if (read $5_@0) {
129 - [3] Const mutate $6_@1[2:7] = read $5_@0
146 + [3] Const mutate $6 = read $5_@0
147 + [4] Reassign mutate $8_@1[2:7] = read $6
148 } else {
131 - [5] Const mutate $6_@1[2:7] = Call mutate g$4:TFunction()
149 + scope @2 [5:6] deps=[] out=[$7_@2] {
150 + [5] Const mutate $7_@2 = Call mutate g$4:TFunction()
151 + }
152 + [6] Reassign mutate $8_@1[2:7] = read $7_@2
153 }
154 }
134 - return freeze $6_@1
155 + return freeze $8_@1
156 }
157
158 ```
@@ -150,24 +171,33 @@ function Or$0() {
171 }
172
173 const c_1 = $[1] !== t0$5;
153 - let t2$6;
174 + let t2$8;
175
176 if (c_1) {
156 - t2$6 = undefined;
177 + t2$8 = undefined;
178
179 if (t0$5) {
159 - t2$6 = t0$5;
180 + t2$8 = t0$5;
181 } else {
161 - t2$6 = g$4();
182 + let t3$7;
183 +
184 + if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
185 + t3$7 = g$4();
186 + $[3] = t3$7;
187 + } else {
188 + t3$7 = $[3];
189 + }
190 +
191 + t2$8 = t3$7;
192 }
193
194 $[1] = t0$5;
165 - $[2] = t2$6;
195 + $[2] = t2$8;
196 } else {
167 - t2$6 = $[2];
197 + t2$8 = $[2];
198 }
199
170 - return t2$6;
200 + return t2$8;
201 }
202
203 ```
@@ -178,19 +208,21 @@ bb0:
208 [1] Const mutate t0$9_@0:TPrimitive = Call mutate f$2:TFunction()
209 [2] Const mutate $10:TPrimitive = null
210 [3] Const mutate $11:TPrimitive = Binary read t0$9_@0:TPrimitive != read $10:TPrimitive
181 - [4] Let mutate t2$12_@1:TPrimitive[4:9] = undefined
211 + [4] Let mutate t2$14_@1[4:9] = undefined
212 [4] If (read $11:TPrimitive) then:bb2 else:bb3 fallthrough=bb1
213 bb2:
214 predecessor blocks: bb0
185 - [5] Const mutate t2$12_@1:TPrimitive[4:9] = read t0$9_@0:TPrimitive
215 + [5] Const mutate $12:TPrimitive = read t0$9_@0:TPrimitive
216 + [6] Reassign mutate t2$14_@1[4:9] = read $12:TPrimitive
217 [6] Goto bb1
218 bb3:
219 predecessor blocks: bb0
189 - [7] Const mutate t2$12_@1:TPrimitive[4:9] = Call mutate g$7:TFunction()
220 + [7] Const mutate t3$13_@2 = Call mutate g$7:TFunction()
221 + [8] Reassign mutate t2$14_@1[4:9] = read t3$13_@2
222 [8] Goto bb1
223 bb1:
224 predecessor blocks: bb2 bb3
193 - [9] Return freeze t2$12_@1:TPrimitive
225 + [9] Return freeze t2$14_@1
226 ```
227
228 ## Reactive Scopes
@@ -204,15 +236,19 @@ function QuestionQuestion(
236 }
237 [2] Const mutate $10:TPrimitive = null
238 [3] Const mutate $11:TPrimitive = Binary read $9_@0:TPrimitive != read $10:TPrimitive
207 - scope @1 [4:9] deps=[read $9_@0:TPrimitive] out=[$12_@1] {
208 - [4] Let mutate $12_@1:TPrimitive[4:9] = undefined
239 + scope @1 [4:9] deps=[read $9_@0:TPrimitive] out=[$14_@1] {
240 + [4] Let mutate $14_@1[4:9] = undefined
241 if (read $11:TPrimitive) {
210 - [5] Const mutate $12_@1:TPrimitive[4:9] = read $9_@0:TPrimitive
242 + [5] Const mutate $12:TPrimitive = read $9_@0:TPrimitive
243 + [6] Reassign mutate $14_@1[4:9] = read $12:TPrimitive
244 } else {
212 - [7] Const mutate $12_@1:TPrimitive[4:9] = Call mutate g$7:TFunction()
245 + scope @2 [7:8] deps=[] out=[$13_@2] {
246 + [7] Const mutate $13_@2 = Call mutate g$7:TFunction()
247 + }
248 + [8] Reassign mutate $14_@1[4:9] = read $13_@2
249 }
250 }
215 - return freeze $12_@1:TPrimitive
251 + return freeze $14_@1
252 }
253
254 ```
@@ -231,24 +267,33 @@ function QuestionQuestion$0(props$8) {
267 }
268
269 const c_1 = $[1] !== t0$9;
234 - let t2$12;
270 + let t2$14;
271
272 if (c_1) {
237 - t2$12 = undefined;
273 + t2$14 = undefined;
274
275 if (t0$9 != null) {
240 - t2$12 = t0$9;
276 + t2$14 = t0$9;
277 } else {
242 - t2$12 = g$7();
278 + let t3$13;
279 +
280 + if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
281 + t3$13 = g$7();
282 + $[3] = t3$13;
283 + } else {
284 + t3$13 = $[3];
285 + }
286 +
287 + t2$14 = t3$13;
288 }
289
290 $[1] = t0$9;
246 - $[2] = t2$12;
291 + $[2] = t2$14;
292 } else {
248 - t2$12 = $[2];
293 + t2$14 = $[2];
294 }
295
251 - return t2$12;
296 + return t2$14;
297 }
298
299 ```
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+73 -49
@@ -92,10 +92,14 @@ function cond$0(x$2) {}
92
93 ```
94 bb0:
95 - [1] Let mutate a$18_@0[1:23] = Object { }
96 - [2] Let mutate b$20_@0[1:23] = Object { }
97 - [3] Let mutate c$22_@0[1:23] = Object { }
98 - [4] Let mutate d$24_@0[1:23] = Object { }
95 + [1] Let mutate a$13_@0:TObject[1:23] = Object { }
96 + [2] Let mutate b$14_@0:TObject[1:23] = Object { }
97 + [3] Let mutate c$15_@0:TObject[1:23] = Object { }
98 + [4] Let mutate d$16_@0:TObject[1:23] = Object { }
99 + [5] Let mutate a$30_@0[1:23] = read a$13_@0:TObject
100 + [5] Let mutate b$31_@0[1:23] = read b$14_@0:TObject
101 + [5] Let mutate c$32_@0[1:23] = read c$15_@0:TObject
102 + [5] Let mutate d$33_@0[1:23] = read d$16_@0:TObject
103 [5] While test=bb1 loop=bb3 fallthrough=bb2
104 bb1:
105 predecessor blocks: bb0 bb4
@@ -103,33 +107,37 @@ bb1:
107 [7] If (read $17:TPrimitive) then:bb3 else:bb2 fallthrough=bb2
108 bb3:
109 predecessor blocks: bb1
106 - [8] Const mutate z$19_@0[1:23] = read a$18_@0
107 - [9] Reassign mutate a$18_@0[1:23] = read b$20_@0
108 - [10] Reassign mutate b$20_@0[1:23] = read c$22_@0
109 - [11] Reassign mutate c$22_@0[1:23] = read d$24_@0
110 - [12] Reassign mutate d$24_@0[1:23] = read z$19_@0
111 - [13] Call mutate mutate$7:TFunction(mutate a$18_@0, mutate b$20_@0)
112 - [14] Const mutate $29_@0[1:23] = Call mutate cond$8:TFunction(mutate a$18_@0)
110 + [8] Const mutate z$19_@0[1:23] = read a$13_@0:TObject
111 + [9] Reassign mutate a$13_@0:TObject[1:23] = read b$14_@0:TObject
112 + [10] Reassign mutate b$14_@0:TObject[1:23] = read c$15_@0:TObject
113 + [11] Reassign mutate c$15_@0:TObject[1:23] = read d$16_@0:TObject
114 + [12] Reassign mutate d$16_@0:TObject[1:23] = read z$19_@0
115 + [13] Call mutate mutate$7:TFunction(mutate a$13_@0:TObject, mutate b$14_@0:TObject)
116 + [14] Const mutate $29_@0[1:23] = Call mutate cond$8:TFunction(mutate a$13_@0:TObject)
117 + [15] Reassign mutate a$30_@0[1:23] = read a$13_@0:TObject
118 + [15] Reassign mutate b$31_@0[1:23] = read b$14_@0:TObject
119 + [15] Reassign mutate c$32_@0[1:23] = read c$15_@0:TObject
120 + [15] Reassign mutate d$33_@0[1:23] = read d$16_@0:TObject
121 [15] If (read $29_@0) then:bb2 else:bb4 fallthrough=bb4
122 bb4:
123 predecessor blocks: bb3
124 [16] Goto(Continue) bb1
125 bb2:
126 predecessor blocks: bb3 bb1
119 - [17] If (read a$18_@0) then:bb7 else:bb7 fallthrough=bb7
127 + [17] If (read a$30_@0) then:bb7 else:bb7 fallthrough=bb7
128 bb7:
129 predecessor blocks: bb2
122 - [18] If (read b$20_@0) then:bb9 else:bb9 fallthrough=bb9
130 + [18] If (read b$31_@0) then:bb9 else:bb9 fallthrough=bb9
131 bb9:
132 predecessor blocks: bb7
125 - [19] If (read c$22_@0) then:bb11 else:bb11 fallthrough=bb11
133 + [19] If (read c$32_@0) then:bb11 else:bb11 fallthrough=bb11
134 bb11:
135 predecessor blocks: bb9
128 - [20] If (read d$24_@0) then:bb13 else:bb13 fallthrough=bb13
136 + [20] If (read d$33_@0) then:bb13 else:bb13 fallthrough=bb13
137 bb13:
138 predecessor blocks: bb11
139 [21] Const mutate $34:TPrimitive = null
132 - [22] Call mutate mutate$7:TFunction(mutate d$24_@0, read $34:TPrimitive)
140 + [22] Call mutate mutate$7:TFunction(mutate d$33_@0, read $34:TPrimitive)
141 [23] Return
142 ```
143
@@ -139,35 +147,43 @@ bb13:
147 function Component(
148 props,
149 ) {
142 - [1] Let mutate a$18_@0[1:23] = Object { }
143 - [2] Let mutate b$20_@0[1:23] = Object { }
144 - [3] Let mutate c$22_@0[1:23] = Object { }
145 - [4] Let mutate d$24_@0[1:23] = Object { }
150 + [1] Let mutate a$13_@0:TObject[1:23] = Object { }
151 + [2] Let mutate b$14_@0:TObject[1:23] = Object { }
152 + [3] Let mutate c$15_@0:TObject[1:23] = Object { }
153 + [4] Let mutate d$16_@0:TObject[1:23] = Object { }
154 + [5] Let mutate a$30_@0[1:23] = read a$13_@0:TObject
155 + [5] Let mutate b$31_@0[1:23] = read b$14_@0:TObject
156 + [5] Let mutate c$32_@0[1:23] = read c$15_@0:TObject
157 + [5] Let mutate d$33_@0[1:23] = read d$16_@0:TObject
158 while (
159 [6] Const mutate $17:TPrimitive = true
160 read $17:TPrimitive
161 ) {
150 - [8] Const mutate z$19_@0[1:23] = read a$18_@0
151 - [9] Reassign mutate a$18_@0[1:23] = read b$20_@0
152 - [10] Reassign mutate b$20_@0[1:23] = read c$22_@0
153 - [11] Reassign mutate c$22_@0[1:23] = read d$24_@0
154 - [12] Reassign mutate d$24_@0[1:23] = read z$19_@0
155 - [13] Call mutate mutate$7:TFunction(mutate a$18_@0, mutate b$20_@0)
156 - [14] Const mutate $29_@0[1:23] = Call mutate cond$8:TFunction(mutate a$18_@0)
162 + [8] Const mutate z$19_@0[1:23] = read a$13_@0:TObject
163 + [9] Reassign mutate a$13_@0:TObject[1:23] = read b$14_@0:TObject
164 + [10] Reassign mutate b$14_@0:TObject[1:23] = read c$15_@0:TObject
165 + [11] Reassign mutate c$15_@0:TObject[1:23] = read d$16_@0:TObject
166 + [12] Reassign mutate d$16_@0:TObject[1:23] = read z$19_@0
167 + [13] Call mutate mutate$7:TFunction(mutate a$13_@0:TObject, mutate b$14_@0:TObject)
168 + [14] Const mutate $29_@0[1:23] = Call mutate cond$8:TFunction(mutate a$13_@0:TObject)
169 + [15] Reassign mutate a$30_@0[1:23] = read a$13_@0:TObject
170 + [15] Reassign mutate b$31_@0[1:23] = read b$14_@0:TObject
171 + [15] Reassign mutate c$32_@0[1:23] = read c$15_@0:TObject
172 + [15] Reassign mutate d$33_@0[1:23] = read d$16_@0:TObject
173 if (read $29_@0) {
174 break
175 }
176 }
161 - if (read a$18_@0) {
177 + if (read a$30_@0) {
178 }
163 - if (read b$20_@0) {
179 + if (read b$31_@0) {
180 }
165 - if (read c$22_@0) {
181 + if (read c$32_@0) {
182 }
167 - if (read d$24_@0) {
183 + if (read d$33_@0) {
184 }
185 [21] Const mutate $34:TPrimitive = null
170 - [22] Call mutate mutate$7:TFunction(mutate d$24_@0, read $34:TPrimitive)
186 + [22] Call mutate mutate$7:TFunction(mutate d$33_@0, read $34:TPrimitive)
187 return
188 }
189
@@ -177,36 +193,44 @@ function Component(
193
194 ```javascript
195 function Component$0(props$12) {
180 - let a$18 = {};
181 - let b$20 = {};
182 - let c$22 = {};
183 - let d$24 = {};
196 + let a$13 = {};
197 + let b$14 = {};
198 + let c$15 = {};
199 + let d$16 = {};
200 + let a$30 = a$13;
201 + let b$31 = b$14;
202 + let c$32 = c$15;
203 + let d$33 = d$16;
204 while (true) {
185 - const z$19 = a$18;
186 - a$18 = b$20;
187 - b$20 = c$22;
188 - c$22 = d$24;
189 - d$24 = z$19;
190 - mutate$7(a$18, b$20);
191 -
192 - if (cond$8(a$18)) {
205 + const z$19 = a$13;
206 + a$13 = b$14;
207 + b$14 = c$15;
208 + c$15 = d$16;
209 + d$16 = z$19;
210 + mutate$7(a$13, b$14);
211 + a$30 = a$13;
212 + b$31 = b$14;
213 + c$32 = c$15;
214 + d$33 = d$16;
215 +
216 + if (cond$8(a$13)) {
217 break;
218 }
219 }
220
197 - if (a$18) {
221 + if (a$30) {
222 }
223
200 - if (b$20) {
224 + if (b$31) {
225 }
226
203 - if (c$22) {
227 + if (c$32) {
228 }
229
206 - if (d$24) {
230 + if (d$33) {
231 }
232
209 - mutate$7(d$24, null);
233 + mutate$7(d$33, null);
234 }
235
236 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+59 -33
@@ -23,20 +23,22 @@ function Component(props) {
23
24 ```
25 bb0:
26 - [1] Let mutate x$7_@0[1:7] = Array []
26 + [1] Const mutate x$7_@0[1:3] = Array []
27 [2] Call mutate x$7_@0.push(read props$6.p0)
28 [3] Const mutate y$8 = read x$7_@0
29 + [4] Let mutate x$11_@1[1:7] = read x$7_@0
30 [4] If (read props$6.p1) then:bb2 else:bb1 fallthrough=bb1
31 bb2:
32 predecessor blocks: bb0
32 - [5] Reassign mutate x$7_@0[1:7] = Array []
33 + [5] Const mutate x$9_@2 = Array []
34 + [6] Reassign mutate x$11_@1[1:7] = read x$9_@2
35 [6] Goto bb1
36 bb1:
37 predecessor blocks: bb2 bb0
36 - [7] Const mutate _$12_@1 = JSX <read Component$0 x={freeze x$7_@0} ></read Component$0>
38 + [7] Const mutate _$12_@3 = JSX <read Component$0 x={freeze x$11_@1} ></read Component$0>
39 [8] Call read y$8.push(read props$6.p2)
38 - [9] Const mutate t5$15_@2 = JSX <read Component$0 x={read x$7_@0} y={read y$8} ></read Component$0>
39 - [10] Return read t5$15_@2
40 + [9] Const mutate t7$15_@4 = JSX <read Component$0 x={read x$11_@1} y={read y$8} ></read Component$0>
41 + [10] Return read t7$15_@4
42 ```
43
44 ## Reactive Scopes
@@ -45,20 +47,26 @@ bb1:
47 function Component(
48 props,
49 ) {
48 - scope @0 [1:7] deps=[read props$6.p0, read props$6.p1] out=[x$7_@0] {
49 - [1] Let mutate x$7_@0[1:7] = Array []
50 + scope @0 [1:3] deps=[read props$6.p0] out=[x$7_@0] {
51 + [1] Const mutate x$7_@0[1:3] = Array []
52 [2] Call mutate x$7_@0.push(read props$6.p0)
51 - [3] Const mutate y$8 = read x$7_@0
53 + }
54 + [3] Const mutate y$8 = read x$7_@0
55 + scope @1 [1:7] deps=[read props$6.p1] out=[x$11_@1] {
56 + [4] Let mutate x$11_@1[1:7] = read x$7_@0
57 if (read props$6.p1) {
53 - [5] Reassign mutate x$7_@0[1:7] = Array []
58 + scope @2 [5:6] deps=[] out=[x$9_@2] {
59 + [5] Const mutate x$9_@2 = Array []
60 + }
61 + [6] Reassign mutate x$11_@1[1:7] = read x$9_@2
62 }
63 }
56 - [7] Const mutate _$12_@1 = JSX <read Component$0 x={freeze x$7_@0} ></read Component$0>
64 + [7] Const mutate _$12_@3 = JSX <read Component$0 x={freeze x$11_@1} ></read Component$0>
65 [8] Call read y$8.push(read props$6.p2)
58 - scope @2 [9:10] deps=[read x$7_@0, read y$8] out=[$15_@2] {
59 - [9] Const mutate $15_@2 = JSX <read Component$0 x={read x$7_@0} y={read y$8} ></read Component$0>
66 + scope @4 [9:10] deps=[read x$11_@1, read y$8] out=[$15_@4] {
67 + [9] Const mutate $15_@4 = JSX <read Component$0 x={read x$11_@1} y={read y$8} ></read Component$0>
68 }
61 - return read $15_@2
69 + return read $15_@4
70 }
71
72 ```
@@ -69,41 +77,59 @@ function Component(
77 function Component$0(props$6) {
78 const $ = React.useMemoCache();
79 const c_0 = $[0] !== props$6.p0;
72 - const c_1 = $[1] !== props$6.p1;
80 let x$7;
74 - if (c_0 || c_1) {
81 + if (c_0) {
82 x$7 = [];
83 x$7.push(props$6.p0);
77 - const y$8 = x$7;
84 + $[0] = props$6.p0;
85 + $[1] = x$7;
86 + } else {
87 + x$7 = $[1];
88 + }
89 +
90 + const y$8 = x$7;
91 + const c_2 = $[2] !== props$6.p1;
92 + let x$11;
93 +
94 + if (c_2) {
95 + x$11 = x$7;
96
97 if (props$6.p1) {
80 - x$7 = [];
98 + let x$9;
99 +
100 + if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
101 + x$9 = [];
102 + $[4] = x$9;
103 + } else {
104 + x$9 = $[4];
105 + }
106 +
107 + x$11 = x$9;
108 }
109
83 - $[0] = props$6.p0;
84 - $[1] = props$6.p1;
85 - $[2] = x$7;
110 + $[2] = props$6.p1;
111 + $[3] = x$11;
112 } else {
87 - x$7 = $[2];
113 + x$11 = $[3];
114 }
115
90 - const _$12 = <Component$0 x={x$7}></Component$0>;
116 + const _$12 = <Component$0 x={x$11}></Component$0>;
117
118 y$8.push(props$6.p2);
93 - const c_3 = $[3] !== x$7;
94 - const c_4 = $[4] !== y$8;
95 - let t5$15;
96 -
97 - if (c_3 || c_4) {
98 - t5$15 = <Component$0 x={x$7} y={y$8}></Component$0>;
99 - $[3] = x$7;
100 - $[4] = y$8;
101 - $[5] = t5$15;
119 + const c_5 = $[5] !== x$11;
120 + const c_6 = $[6] !== y$8;
121 + let t7$15;
122 +
123 + if (c_5 || c_6) {
124 + t7$15 = <Component$0 x={x$11} y={y$8}></Component$0>;
125 + $[5] = x$11;
126 + $[6] = y$8;
127 + $[7] = t7$15;
128 } else {
103 - t5$15 = $[5];
129 + t7$15 = $[7];
130 }
131
106 - return t5$15;
132 + return t7$15;
133 }
134
135 ```
compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md
+65 -35
@@ -45,20 +45,22 @@ bb1:
45 [5] Const mutate $17:TPrimitive = "div"
46 [6] Const mutate y$19_@1 = JSX <read $17:TPrimitive>{freeze x$16_@0}</read $17:TPrimitive>
47 [7] Const mutate $20:TPrimitive = 0
48 - [8] Let mutate x$22_@2[8:15] = undefined
48 + [8] Let mutate x$30_@2[8:15] = undefined
49 [8] Switch (read b$14)
50 Case read $20:TPrimitive: bb5
51 Default: bb4
52 Fallthrough: bb3
53 bb5:
54 predecessor blocks: bb1
55 - [9] Reassign mutate x$22_@2[8:15] = Array []
56 - [10] Call mutate x$22_@2.push(read b$14)
55 + [9] Const mutate x$22_@3[9:11] = Array []
56 + [10] Call mutate x$22_@3.push(read b$14)
57 + [11] Reassign mutate x$30_@2[8:15] = read x$22_@3
58 [11] Goto bb3
59 bb4:
60 predecessor blocks: bb1
60 - [12] Reassign mutate x$22_@2[8:15] = Array []
61 - [13] Call mutate x$22_@2.push(read c$15)
61 + [12] Const mutate x$23_@4[12:14] = Array []
62 + [13] Call mutate x$23_@4.push(read c$15)
63 + [14] Reassign mutate x$30_@2[8:15] = read x$23_@4
64 [14] Goto bb3
65 bb3:
66 predecessor blocks: bb5 bb4
@@ -66,8 +68,8 @@ bb3:
68 [16] Const mutate $26 = "\n "
69 [17] Const mutate $27 = "\n "
70 [18] Const mutate $28 = "\n "
69 - [19] Const mutate t9$31_@3 = JSX <read $25:TPrimitive>{read $26}{read y$19_@1}{read $27}{freeze x$22_@2}{read $28}</read $25:TPrimitive>
70 - [20] Return read t9$31_@3
71 + [19] Const mutate t13$31_@5 = JSX <read $25:TPrimitive>{read $26}{read y$19_@1}{read $27}{freeze x$30_@2}{read $28}</read $25:TPrimitive>
72 + [20] Return read t13$31_@5
73 ```
74
75 ## Reactive Scopes
@@ -89,17 +91,23 @@ function foo(
91 [6] Const mutate y$19_@1 = JSX <read $17:TPrimitive>{freeze x$16_@0}</read $17:TPrimitive>
92 }
93 [7] Const mutate $20:TPrimitive = 0
92 - scope @2 [8:15] deps=[read b$14, read c$15] out=[x$22_@2] {
93 - [8] Let mutate x$22_@2[8:15] = undefined
94 + scope @2 [8:15] deps=[read b$14, read c$15] out=[x$30_@2] {
95 + [8] Let mutate x$30_@2[8:15] = undefined
96 switch (read b$14) {
97 case read $20:TPrimitive: {
96 - [9] Reassign mutate x$22_@2[8:15] = Array []
97 - [10] Call mutate x$22_@2.push(read b$14)
98 + scope @3 [9:11] deps=[read b$14] out=[x$22_@3] {
99 + [9] Const mutate x$22_@3[9:11] = Array []
100 + [10] Call mutate x$22_@3.push(read b$14)
101 + }
102 + [11] Reassign mutate x$30_@2[8:15] = read x$22_@3
103 break bb3
104 }
105 default: {
101 - [12] Reassign mutate x$22_@2[8:15] = Array []
102 - [13] Call mutate x$22_@2.push(read c$15)
106 + scope @4 [12:14] deps=[read c$15] out=[x$23_@4] {
107 + [12] Const mutate x$23_@4[12:14] = Array []
108 + [13] Call mutate x$23_@4.push(read c$15)
109 + }
110 + [14] Reassign mutate x$30_@2[8:15] = read x$23_@4
111 }
112 }
113 }
@@ -107,10 +115,10 @@ function foo(
115 [16] Const mutate $26 = "\n "
116 [17] Const mutate $27 = "\n "
117 [18] Const mutate $28 = "\n "
110 - scope @3 [19:20] deps=[read y$19_@1, freeze x$22_@2] out=[$31_@3] {
111 - [19] Const mutate $31_@3 = JSX <read $25:TPrimitive>{read $26}{read y$19_@1}{read $27}{freeze x$22_@2}{read $28}</read $25:TPrimitive>
118 + scope @5 [19:20] deps=[read y$19_@1, freeze x$30_@2] out=[$31_@5] {
119 + [19] Const mutate $31_@5 = JSX <read $25:TPrimitive>{read $26}{read y$19_@1}{read $27}{freeze x$30_@2}{read $28}</read $25:TPrimitive>
120 }
113 - return read $31_@3
121 + return read $31_@5
122 }
123
124 ```
@@ -148,50 +156,72 @@ function foo$0(a$13, b$14, c$15) {
156
157 const c_4 = $[4] !== b$14;
158 const c_5 = $[5] !== c$15;
151 - let x$22;
159 + let x$30;
160
161 if (c_4 || c_5) {
154 - x$22 = undefined;
162 + x$30 = undefined;
163
164 bb3: switch (b$14) {
165 case 0: {
158 - x$22 = [];
159 - x$22.push(b$14);
166 + const c_7 = $[7] !== b$14;
167 + let x$22;
168 +
169 + if (c_7) {
170 + x$22 = [];
171 + x$22.push(b$14);
172 + $[7] = b$14;
173 + $[8] = x$22;
174 + } else {
175 + x$22 = $[8];
176 + }
177 +
178 + x$30 = x$22;
179 break bb3;
180 }
181
182 default: {
164 - x$22 = [];
165 - x$22.push(c$15);
183 + const c_9 = $[9] !== c$15;
184 + let x$23;
185 +
186 + if (c_9) {
187 + x$23 = [];
188 + x$23.push(c$15);
189 + $[9] = c$15;
190 + $[10] = x$23;
191 + } else {
192 + x$23 = $[10];
193 + }
194 +
195 + x$30 = x$23;
196 }
197 }
198
199 $[4] = b$14;
200 $[5] = c$15;
171 - $[6] = x$22;
201 + $[6] = x$30;
202 } else {
173 - x$22 = $[6];
203 + x$30 = $[6];
204 }
205
176 - const c_7 = $[7] !== y$19;
177 - const c_8 = $[8] !== x$22;
178 - let t9$31;
206 + const c_11 = $[11] !== y$19;
207 + const c_12 = $[12] !== x$30;
208 + let t13$31;
209
180 - if (c_7 || c_8) {
181 - t9$31 = (
210 + if (c_11 || c_12) {
211 + t13$31 = (
212 <div>
213 {y$19}
184 - {x$22}
214 + {x$30}
215 </div>
216 );
187 - $[7] = y$19;
188 - $[8] = x$22;
189 - $[9] = t9$31;
217 + $[11] = y$19;
218 + $[12] = x$30;
219 + $[13] = t13$31;
220 } else {
191 - t9$31 = $[9];
221 + t13$31 = $[13];
222 }
223
194 - return t9$31;
224 + return t13$31;
225 }
226
227 ```
compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md
+40 -25
@@ -37,7 +37,7 @@ function Component(props) {
37 ```
38 bb0:
39 [1] Const mutate x$7:TPrimitive = undefined
40 - [2] Let mutate x$11_@0:TProp[2:18] = undefined
40 + [2] Let mutate x$16_@0[2:18] = undefined
41 [2] If (read props$6.cond) then:bb2 else:bb10 fallthrough=bb1
42 bb2:
43 predecessor blocks: bb0
@@ -52,30 +52,35 @@ bb2:
52 Fallthrough: bb1
53 bb8:
54 predecessor blocks: bb2
55 - [7] Reassign mutate x$11_@0:TProp[2:18] = read props$6.v0
55 + [7] Const mutate x$11:TProp = read props$6.v0
56 + [8] Reassign mutate x$16_@0[2:18] = read x$11:TProp
57 [8] Goto bb1
58 bb6:
59 predecessor blocks: bb2
59 - [9] Reassign mutate x$11_@0:TProp[2:18] = read props$6.v1
60 + [9] Const mutate x$12:TProp = read props$6.v1
61 + [10] Reassign mutate x$16_@0[2:18] = read x$12:TProp
62 [10] Goto bb1
63 bb4:
64 predecessor blocks: bb2
63 - [11] Reassign mutate x$11_@0:TProp[2:18] = read props$6.v2
65 + [11] Const mutate x$13:TProp = read props$6.v2
66 + [12] Reassign mutate x$16_@0[2:18] = read x$13:TProp
67 [12] Goto bb1
68 bb10:
69 predecessor blocks: bb0
70 [13] If (read props$6.cond2) then:bb12 else:bb13 fallthrough=bb1
71 bb12:
72 predecessor blocks: bb10
70 - [14] Reassign mutate x$11_@0:TProp[2:18] = read props$6.b
73 + [14] Const mutate x$14:TProp = read props$6.b
74 + [15] Reassign mutate x$16_@0[2:18] = read x$14:TProp
75 [15] Goto bb1
76 bb13:
77 predecessor blocks: bb10
74 - [16] Reassign mutate x$11_@0:TProp[2:18] = read props$6.c
78 + [16] Const mutate x$15:TProp = read props$6.c
79 + [17] Reassign mutate x$16_@0[2:18] = read x$15:TProp
80 [17] Goto bb1
81 bb1:
82 predecessor blocks: bb8 bb6 bb4 bb12 bb13
78 - [18] read x$11_@0:TProp
83 + [18] read x$16_@0
84 [19] Return
85 ```
86
@@ -86,36 +91,41 @@ function Component(
91 props,
92 ) {
93 [1] Const mutate x$7:TPrimitive = undefined
89 - scope @0 [2:18] deps=[read props$6.cond, read props$6.test, read props$6.v0, read props$6.v1, read props$6.v2, read props$6.cond2, read props$6.b, read props$6.c] out=[x$11_@0] {
90 - [2] Let mutate x$11_@0:TProp[2:18] = undefined
94 + scope @0 [2:18] deps=[read props$6.cond, read props$6.test, read props$6.v0, read props$6.v1, read props$6.v2, read props$6.cond2, read props$6.b, read props$6.c] out=[x$16_@0] {
95 + [2] Let mutate x$16_@0[2:18] = undefined
96 if (read props$6.cond) {
97 [3] Const mutate $8:TPrimitive = 2
98 [4] Const mutate $9:TPrimitive = 1
99 [5] Const mutate $10:TPrimitive = 0
100 switch (read props$6.test) {
101 case read $10:TPrimitive: {
97 - [7] Reassign mutate x$11_@0:TProp[2:18] = read props$6.v0
102 + [7] Const mutate x$11:TProp = read props$6.v0
103 + [8] Reassign mutate x$16_@0[2:18] = read x$11:TProp
104 break bb1
105 }
106 case read $9:TPrimitive: {
101 - [9] Reassign mutate x$11_@0:TProp[2:18] = read props$6.v1
107 + [9] Const mutate x$12:TProp = read props$6.v1
108 + [10] Reassign mutate x$16_@0[2:18] = read x$12:TProp
109 break bb1
110 }
111 case read $8:TPrimitive: {
112 }
113 default: {
107 - [11] Reassign mutate x$11_@0:TProp[2:18] = read props$6.v2
114 + [11] Const mutate x$13:TProp = read props$6.v2
115 + [12] Reassign mutate x$16_@0[2:18] = read x$13:TProp
116 }
117 }
118 } else {
119 if (read props$6.cond2) {
112 - [14] Reassign mutate x$11_@0:TProp[2:18] = read props$6.b
120 + [14] Const mutate x$14:TProp = read props$6.b
121 + [15] Reassign mutate x$16_@0[2:18] = read x$14:TProp
122 } else {
114 - [16] Reassign mutate x$11_@0:TProp[2:18] = read props$6.c
123 + [16] Const mutate x$15:TProp = read props$6.c
124 + [17] Reassign mutate x$16_@0[2:18] = read x$15:TProp
125 }
126 }
127 }
118 - [18] read x$11_@0:TProp
128 + [18] read x$16_@0
129 return
130 }
131
@@ -135,19 +145,21 @@ function Component$0(props$6) {
145 const c_5 = $[5] !== props$6.cond2;
146 const c_6 = $[6] !== props$6.b;
147 const c_7 = $[7] !== props$6.c;
138 - let x$11;
148 + let x$16;
149 if (c_0 || c_1 || c_2 || c_3 || c_4 || c_5 || c_6 || c_7) {
140 - x$11 = undefined;
150 + x$16 = undefined;
151
152 bb1: if (props$6.cond) {
153 switch (props$6.test) {
154 case 0: {
145 - x$11 = props$6.v0;
155 + const x$11 = props$6.v0;
156 + x$16 = x$11;
157 break bb1;
158 }
159
160 case 1: {
150 - x$11 = props$6.v1;
161 + const x$12 = props$6.v1;
162 + x$16 = x$12;
163 break bb1;
164 }
165
@@ -155,14 +167,17 @@ function Component$0(props$6) {
167 }
168
169 default: {
158 - x$11 = props$6.v2;
170 + const x$13 = props$6.v2;
171 + x$16 = x$13;
172 }
173 }
174 } else {
175 if (props$6.cond2) {
163 - x$11 = props$6.b;
176 + const x$14 = props$6.b;
177 + x$16 = x$14;
178 } else {
165 - x$11 = props$6.c;
179 + const x$15 = props$6.c;
180 + x$16 = x$15;
181 }
182 }
183
@@ -174,12 +189,12 @@ function Component$0(props$6) {
189 $[5] = props$6.cond2;
190 $[6] = props$6.b;
191 $[7] = props$6.c;
177 - $[8] = x$11;
192 + $[8] = x$16;
193 } else {
179 - x$11 = $[8];
194 + x$16 = $[8];
195 }
196
182 - x$11;
197 + x$16;
198 }
199
200 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-multiple-if.expect.md
+45 -22
@@ -21,27 +21,31 @@ function foo() {
21
22 ```
23 bb0:
24 - [1] Let mutate x$7_@0:TPrimitive[1:13] = 1
24 + [1] Const mutate x$7:TPrimitive = 1
25 [2] Const mutate y$8:TPrimitive = 2
26 [3] Const mutate $9:TPrimitive = 2
27 [4] Const mutate $10:TPrimitive = Binary read y$8:TPrimitive === read $9:TPrimitive
28 + [5] Let mutate x$17_@0[1:8] = read x$7:TPrimitive
29 [5] If (read $10:TPrimitive) then:bb2 else:bb1 fallthrough=bb1
30 bb2:
31 predecessor blocks: bb0
31 - [6] Reassign mutate x$7_@0:TPrimitive[1:13] = 3
32 + [6] Const mutate x$11:TPrimitive = 3
33 + [7] Reassign mutate x$17_@0[1:8] = read x$11:TPrimitive
34 [7] Goto bb1
35 bb1:
36 predecessor blocks: bb2 bb0
37 [8] Const mutate $12:TPrimitive = 3
38 [9] Const mutate $14:TPrimitive = Binary read y$8:TPrimitive === read $12:TPrimitive
39 + [10] Let mutate x$16_@1[1:13] = read x$17_@0
40 [10] If (read $14:TPrimitive) then:bb4 else:bb3 fallthrough=bb3
41 bb4:
42 predecessor blocks: bb1
40 - [11] Reassign mutate x$7_@0:TPrimitive[1:13] = 5
43 + [11] Const mutate x$15:TPrimitive = 5
44 + [12] Reassign mutate x$16_@1[1:13] = read x$15:TPrimitive
45 [12] Goto bb3
46 bb3:
47 predecessor blocks: bb4 bb1
44 - [13] Const mutate y$18 = read x$7_@0:TPrimitive
48 + [13] Const mutate y$18 = read x$16_@1
49 [14] Return
50 ```
51
@@ -50,21 +54,27 @@ bb3:
54 ```
55 function foo(
56 ) {
53 - scope @0 [1:13] deps=[] out=[x$7_@0] {
54 - [1] Let mutate x$7_@0:TPrimitive[1:13] = 1
55 - [2] Const mutate y$8:TPrimitive = 2
56 - [3] Const mutate $9:TPrimitive = 2
57 - [4] Const mutate $10:TPrimitive = Binary read y$8:TPrimitive === read $9:TPrimitive
57 + [1] Const mutate x$7:TPrimitive = 1
58 + [2] Const mutate y$8:TPrimitive = 2
59 + [3] Const mutate $9:TPrimitive = 2
60 + [4] Const mutate $10:TPrimitive = Binary read y$8:TPrimitive === read $9:TPrimitive
61 + scope @0 [1:8] deps=[] out=[x$17_@0] {
62 + [5] Let mutate x$17_@0[1:8] = read x$7:TPrimitive
63 if (read $10:TPrimitive) {
59 - [6] Reassign mutate x$7_@0:TPrimitive[1:13] = 3
64 + [6] Const mutate x$11:TPrimitive = 3
65 + [7] Reassign mutate x$17_@0[1:8] = read x$11:TPrimitive
66 }
61 - [8] Const mutate $12:TPrimitive = 3
62 - [9] Const mutate $14:TPrimitive = Binary read y$8:TPrimitive === read $12:TPrimitive
67 + }
68 + [8] Const mutate $12:TPrimitive = 3
69 + [9] Const mutate $14:TPrimitive = Binary read y$8:TPrimitive === read $12:TPrimitive
70 + scope @1 [1:13] deps=[] out=[x$16_@1] {
71 + [10] Let mutate x$16_@1[1:13] = read x$17_@0
72 if (read $14:TPrimitive) {
64 - [11] Reassign mutate x$7_@0:TPrimitive[1:13] = 5
73 + [11] Const mutate x$15:TPrimitive = 5
74 + [12] Reassign mutate x$16_@1[1:13] = read x$15:TPrimitive
75 }
76 }
67 - [13] Const mutate y$18 = read x$7_@0:TPrimitive
77 + [13] Const mutate y$18 = read x$16_@1
78 return
79 }
80
@@ -75,25 +85,38 @@ function foo(
85 ```javascript
86 function foo$0() {
87 const $ = React.useMemoCache();
78 - let x$7;
88 + const x$7 = 1;
89 + const y$8 = 2;
90 + let x$17;
91 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
80 - x$7 = 1;
81 - const y$8 = 2;
92 + x$17 = x$7;
93
94 if (y$8 === 2) {
84 - x$7 = 3;
95 + const x$11 = 3;
96 + x$17 = x$11;
97 }
98
99 + $[0] = x$17;
100 + } else {
101 + x$17 = $[0];
102 + }
103 +
104 + let x$16;
105 +
106 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
107 + x$16 = x$17;
108 +
109 if (y$8 === 3) {
88 - x$7 = 5;
110 + const x$15 = 5;
111 + x$16 = x$15;
112 }
113
91 - $[0] = x$7;
114 + $[1] = x$16;
115 } else {
93 - x$7 = $[0];
116 + x$16 = $[1];
117 }
118
96 - const y$18 = x$7;
119 + const y$18 = x$16;
120 }
121
122 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-single-if.expect.md
+23 -17
@@ -18,18 +18,20 @@ function foo() {
18
19 ```
20 bb0:
21 - [1] Let mutate x$5_@0:TPrimitive[1:8] = 1
21 + [1] Const mutate x$5:TPrimitive = 1
22 [2] Const mutate y$6:TPrimitive = 2
23 [3] Const mutate $7:TPrimitive = 2
24 [4] Const mutate $8:TPrimitive = Binary read y$6:TPrimitive === read $7:TPrimitive
25 + [5] Let mutate x$10_@0[1:8] = read x$5:TPrimitive
26 [5] If (read $8:TPrimitive) then:bb2 else:bb1 fallthrough=bb1
27 bb2:
28 predecessor blocks: bb0
28 - [6] Reassign mutate x$5_@0:TPrimitive[1:8] = 3
29 + [6] Const mutate x$9:TPrimitive = 3
30 + [7] Reassign mutate x$10_@0[1:8] = read x$9:TPrimitive
31 [7] Goto bb1
32 bb1:
33 predecessor blocks: bb2 bb0
32 - [8] Const mutate y$11 = read x$5_@0:TPrimitive
34 + [8] Const mutate y$11 = read x$10_@0
35 [9] Return
36 ```
37
@@ -38,16 +40,18 @@ bb1:
40 ```
41 function foo(
42 ) {
41 - scope @0 [1:8] deps=[] out=[x$5_@0] {
42 - [1] Let mutate x$5_@0:TPrimitive[1:8] = 1
43 - [2] Const mutate y$6:TPrimitive = 2
44 - [3] Const mutate $7:TPrimitive = 2
45 - [4] Const mutate $8:TPrimitive = Binary read y$6:TPrimitive === read $7:TPrimitive
43 + [1] Const mutate x$5:TPrimitive = 1
44 + [2] Const mutate y$6:TPrimitive = 2
45 + [3] Const mutate $7:TPrimitive = 2
46 + [4] Const mutate $8:TPrimitive = Binary read y$6:TPrimitive === read $7:TPrimitive
47 + scope @0 [1:8] deps=[] out=[x$10_@0] {
48 + [5] Let mutate x$10_@0[1:8] = read x$5:TPrimitive
49 if (read $8:TPrimitive) {
47 - [6] Reassign mutate x$5_@0:TPrimitive[1:8] = 3
50 + [6] Const mutate x$9:TPrimitive = 3
51 + [7] Reassign mutate x$10_@0[1:8] = read x$9:TPrimitive
52 }
53 }
50 - [8] Const mutate y$11 = read x$5_@0:TPrimitive
54 + [8] Const mutate y$11 = read x$10_@0
55 return
56 }
57
@@ -58,21 +62,23 @@ function foo(
62 ```javascript
63 function foo$0() {
64 const $ = React.useMemoCache();
61 - let x$5;
65 + const x$5 = 1;
66 + const y$6 = 2;
67 + let x$10;
68 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
63 - x$5 = 1;
64 - const y$6 = 2;
69 + x$10 = x$5;
70
71 if (y$6 === 2) {
67 - x$5 = 3;
72 + const x$9 = 3;
73 + x$10 = x$9;
74 }
75
70 - $[0] = x$5;
76 + $[0] = x$10;
77 } else {
72 - x$5 = $[0];
78 + x$10 = $[0];
79 }
80
75 - const y$11 = x$5;
81 + const y$11 = x$10;
82 }
83
84 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md
+45 -27
@@ -30,7 +30,7 @@ function foo(a, b, c, d) {
30 bb0:
31 [1] Const mutate x$13:TPrimitive = 0
32 [2] Const mutate $14:TPrimitive = true
33 - [3] Let mutate x$18_@0[3:20] = undefined
33 + [3] Let mutate x$23_@0[3:20] = undefined
34 [3] If (read $14:TPrimitive) then:bb2 else:bb6 fallthrough=bb1
35 bb2:
36 predecessor blocks: bb0
@@ -38,15 +38,18 @@ bb2:
38 [5] If (read $15:TPrimitive) then:bb4 else:bb5 fallthrough=bb3
39 bb4:
40 predecessor blocks: bb2
41 - [6] Reassign mutate x$18_@0[3:20] = read a$9
41 + [6] Const mutate x$16 = read a$9
42 + [7] Reassign mutate x$23_@0[3:20] = read x$16
43 [7] Goto bb3
44 bb5:
45 predecessor blocks: bb2
45 - [8] Reassign mutate x$18_@0[3:20] = read b$10
46 + [8] Const mutate x$17 = read b$10
47 + [9] Reassign mutate x$23_@0[3:20] = read x$17
48 [9] Goto bb3
49 bb3:
50 predecessor blocks: bb4 bb5
49 - [10] read x$18_@0
51 + [10] read x$18
52 + [11] Reassign mutate x$23_@0[3:20] = read x$18
53 [11] Goto bb1
54 bb6:
55 predecessor blocks: bb0
@@ -54,19 +57,22 @@ bb6:
57 [13] If (read $19:TPrimitive) then:bb8 else:bb9 fallthrough=bb7
58 bb8:
59 predecessor blocks: bb6
57 - [14] Reassign mutate x$18_@0[3:20] = read c$11
60 + [14] Const mutate x$20 = read c$11
61 + [15] Reassign mutate x$23_@0[3:20] = read x$20
62 [15] Goto bb7
63 bb9:
64 predecessor blocks: bb6
61 - [16] Reassign mutate x$18_@0[3:20] = read d$12
65 + [16] Const mutate x$21 = read d$12
66 + [17] Reassign mutate x$23_@0[3:20] = read x$21
67 [17] Goto bb7
68 bb7:
69 predecessor blocks: bb8 bb9
65 - [18] read x$18_@0
70 + [18] read x$22
71 + [19] Reassign mutate x$23_@0[3:20] = read x$22
72 [19] Goto bb1
73 bb1:
74 predecessor blocks: bb3 bb7
69 - [20] Return read x$18_@0
75 + [20] Return read x$23_@0
76 ```
77
78 ## Reactive Scopes
@@ -80,27 +86,33 @@ function foo(
86 ) {
87 [1] Const mutate x$13:TPrimitive = 0
88 [2] Const mutate $14:TPrimitive = true
83 - scope @0 [3:20] deps=[read a$9, read b$10, read c$11, read d$12] out=[x$18_@0] {
84 - [3] Let mutate x$18_@0[3:20] = undefined
89 + scope @0 [3:20] deps=[read a$9, read b$10, read c$11, read d$12] out=[x$23_@0] {
90 + [3] Let mutate x$23_@0[3:20] = undefined
91 if (read $14:TPrimitive) {
92 [4] Const mutate $15:TPrimitive = true
93 if (read $15:TPrimitive) {
88 - [6] Reassign mutate x$18_@0[3:20] = read a$9
94 + [6] Const mutate x$16 = read a$9
95 + [7] Reassign mutate x$23_@0[3:20] = read x$16
96 } else {
90 - [8] Reassign mutate x$18_@0[3:20] = read b$10
97 + [8] Const mutate x$17 = read b$10
98 + [9] Reassign mutate x$23_@0[3:20] = read x$17
99 }
92 - [10] read x$18_@0
100 + [10] read x$18
101 + [11] Reassign mutate x$23_@0[3:20] = read x$18
102 } else {
103 [12] Const mutate $19:TPrimitive = true
104 if (read $19:TPrimitive) {
96 - [14] Reassign mutate x$18_@0[3:20] = read c$11
105 + [14] Const mutate x$20 = read c$11
106 + [15] Reassign mutate x$23_@0[3:20] = read x$20
107 } else {
98 - [16] Reassign mutate x$18_@0[3:20] = read d$12
108 + [16] Const mutate x$21 = read d$12
109 + [17] Reassign mutate x$23_@0[3:20] = read x$21
110 }
100 - [18] read x$18_@0
111 + [18] read x$22
112 + [19] Reassign mutate x$23_@0[3:20] = read x$22
113 }
114 }
103 - return read x$18_@0
115 + return read x$23_@0
116 }
117
118 ```
@@ -115,38 +127,44 @@ function foo$0(a$9, b$10, c$11, d$12) {
127 const c_1 = $[1] !== b$10;
128 const c_2 = $[2] !== c$11;
129 const c_3 = $[3] !== d$12;
118 - let x$18;
130 + let x$23;
131 if (c_0 || c_1 || c_2 || c_3) {
120 - x$18 = undefined;
132 + x$23 = undefined;
133
134 if (true) {
135 if (true) {
124 - x$18 = a$9;
136 + const x$16 = a$9;
137 + x$23 = x$16;
138 } else {
126 - x$18 = b$10;
139 + const x$17 = b$10;
140 + x$23 = x$17;
141 }
142
143 x$18;
144 + x$23 = x$18;
145 } else {
146 if (true) {
132 - x$18 = c$11;
147 + const x$20 = c$11;
148 + x$23 = x$20;
149 } else {
134 - x$18 = d$12;
150 + const x$21 = d$12;
151 + x$23 = x$21;
152 }
153
137 - x$18;
154 + x$22;
155 + x$23 = x$22;
156 }
157
158 $[0] = a$9;
159 $[1] = b$10;
160 $[2] = c$11;
161 $[3] = d$12;
144 - $[4] = x$18;
162 + $[4] = x$23;
163 } else {
146 - x$18 = $[4];
164 + x$23 = $[4];
165 }
166
149 - return x$18;
167 + return x$23;
168 }
169
170 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md
+30 -10
@@ -18,18 +18,20 @@ function foo(a, b, c) {
18
19 ```
20 bb0:
21 - [1] Const mutate x$8_@0[1:8] = read a$5
21 + [1] Const mutate x$8 = read a$5
22 [2] If (read b$6) then:bb2 else:bb1 fallthrough=bb1
23 bb2:
24 predecessor blocks: bb0
25 + [3] Let mutate x$10_@0[1:6] = read x$8
26 [3] If (read c$7) then:bb4 else:bb3 fallthrough=bb3
27 bb4:
28 predecessor blocks: bb2
28 - [4] Reassign mutate x$8_@0[1:8] = read c$7
29 + [4] Const mutate x$9 = read c$7
30 + [5] Reassign mutate x$10_@0[1:6] = read x$9
31 [5] Goto bb3
32 bb3:
33 predecessor blocks: bb4 bb2
32 - [6] read x$8_@0
34 + [6] read x$10_@0
35 [7] Goto bb1
36 bb1:
37 predecessor blocks: bb3 bb0
@@ -44,12 +46,16 @@ function foo(
46 b,
47 c,
48 ) {
47 - [1] Const mutate x$8_@0[1:8] = read a$5
49 + [1] Const mutate x$8 = read a$5
50 if (read b$6) {
49 - if (read c$7) {
50 - [4] Reassign mutate x$8_@0[1:8] = read c$7
51 + scope @0 [1:6] deps=[read c$7] out=[x$10_@0] {
52 + [3] Let mutate x$10_@0[1:6] = read x$8
53 + if (read c$7) {
54 + [4] Const mutate x$9 = read c$7
55 + [5] Reassign mutate x$10_@0[1:6] = read x$9
56 + }
57 }
52 - [6] read x$8_@0
58 + [6] read x$10_@0
59 }
60 return
61 }
@@ -60,13 +66,27 @@ function foo(
66
67 ```javascript
68 function foo$0(a$5, b$6, c$7) {
69 + const $ = React.useMemoCache();
70 const x$8 = a$5;
71 if (b$6) {
65 - if (c$7) {
66 - x$8 = c$7;
72 + const c_0 = $[0] !== c$7;
73 + let x$10;
74 +
75 + if (c_0) {
76 + x$10 = x$8;
77 +
78 + if (c$7) {
79 + const x$9 = c$7;
80 + x$10 = x$9;
81 + }
82 +
83 + $[0] = c$7;
84 + $[1] = x$10;
85 + } else {
86 + x$10 = $[1];
87 }
88
69 - x$8;
89 + x$10;
90 }
91 }
92
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md
+25 -16
@@ -20,22 +20,25 @@ function foo(a, b, c, d, e) {
20
21 ```
22 bb0:
23 - [1] Let mutate x$12_@0:TPrimitive[1:8] = null
23 + [1] Const mutate x$12:TPrimitive = null
24 + [2] Let mutate x$15_@0[1:8] = read x$12:TPrimitive
25 [2] If (read a$7) then:bb2 else:bb3 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
27 - [3] Reassign mutate x$12_@0:TPrimitive[1:8] = read b$8
28 + [3] Const mutate x$13 = read b$8
29 + [4] Reassign mutate x$15_@0[1:8] = read x$13
30 [4] Goto bb1
31 bb3:
32 predecessor blocks: bb0
33 [5] If (read c$9) then:bb5 else:bb1 fallthrough=bb1
34 bb5:
35 predecessor blocks: bb3
34 - [6] Reassign mutate x$12_@0:TPrimitive[1:8] = read d$10
36 + [6] Const mutate x$14 = read d$10
37 + [7] Reassign mutate x$15_@0[1:8] = read x$14
38 [7] Goto bb1
39 bb1:
40 predecessor blocks: bb2 bb5 bb3
38 - [8] Return read x$12_@0:TPrimitive
41 + [8] Return read x$15_@0
42 ```
43
44 ## Reactive Scopes
@@ -48,17 +51,20 @@ function foo(
51 d,
52 e,
53 ) {
51 - scope @0 [1:8] deps=[read a$7, read b$8, read c$9, read d$10] out=[x$12_@0] {
52 - [1] Let mutate x$12_@0:TPrimitive[1:8] = null
54 + [1] Const mutate x$12:TPrimitive = null
55 + scope @0 [1:8] deps=[read a$7, read b$8, read c$9, read d$10] out=[x$15_@0] {
56 + [2] Let mutate x$15_@0[1:8] = read x$12:TPrimitive
57 if (read a$7) {
54 - [3] Reassign mutate x$12_@0:TPrimitive[1:8] = read b$8
58 + [3] Const mutate x$13 = read b$8
59 + [4] Reassign mutate x$15_@0[1:8] = read x$13
60 } else {
61 if (read c$9) {
57 - [6] Reassign mutate x$12_@0:TPrimitive[1:8] = read d$10
62 + [6] Const mutate x$14 = read d$10
63 + [7] Reassign mutate x$15_@0[1:8] = read x$14
64 }
65 }
66 }
61 - return read x$12_@0:TPrimitive
67 + return read x$15_@0
68 }
69
70 ```
@@ -68,19 +74,22 @@ function foo(
74 ```javascript
75 function foo$0(a$7, b$8, c$9, d$10, e$11) {
76 const $ = React.useMemoCache();
77 + const x$12 = null;
78 const c_0 = $[0] !== a$7;
79 const c_1 = $[1] !== b$8;
80 const c_2 = $[2] !== c$9;
81 const c_3 = $[3] !== d$10;
75 - let x$12;
82 + let x$15;
83 if (c_0 || c_1 || c_2 || c_3) {
77 - x$12 = null;
84 + x$15 = x$12;
85
86 if (a$7) {
80 - x$12 = b$8;
87 + const x$13 = b$8;
88 + x$15 = x$13;
89 } else {
90 if (c$9) {
83 - x$12 = d$10;
91 + const x$14 = d$10;
92 + x$15 = x$14;
93 }
94 }
95
@@ -88,12 +97,12 @@ function foo$0(a$7, b$8, c$9, d$10, e$11) {
97 $[1] = b$8;
98 $[2] = c$9;
99 $[3] = d$10;
91 - $[4] = x$12;
100 + $[4] = x$15;
101 } else {
93 - x$12 = $[4];
102 + x$15 = $[4];
103 }
104
96 - return x$12;
105 + return x$15;
106 }
107
108 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md
+40 -28
@@ -22,22 +22,26 @@ function foo() {
22
23 ```
24 bb0:
25 - [1] Let mutate x$6_@0:TPrimitive[1:10] = 1
26 - [2] Let mutate y$7_@0:TPrimitive[1:10] = 2
25 + [1] Const mutate x$6:TPrimitive = 1
26 + [2] Const mutate y$7:TPrimitive = 2
27 [3] Const mutate $8:TPrimitive = 1
28 - [4] Const mutate $9:TPrimitive = Binary read x$6_@0:TPrimitive > read $8:TPrimitive
28 + [4] Const mutate $9:TPrimitive = Binary read x$6:TPrimitive > read $8:TPrimitive
29 + [5] Let mutate x$12_@0[1:10] = read x$6:TPrimitive
30 + [5] Let mutate y$13_@0[1:10] = read y$7:TPrimitive
31 [5] If (read $9:TPrimitive) then:bb2 else:bb3 fallthrough=bb1
32 bb2:
33 predecessor blocks: bb0
32 - [6] Reassign mutate x$6_@0:TPrimitive[1:10] = 2
34 + [6] Const mutate x$10:TPrimitive = 2
35 + [7] Reassign mutate x$12_@0[1:10] = read x$10:TPrimitive
36 [7] Goto bb1
37 bb3:
38 predecessor blocks: bb0
36 - [8] Reassign mutate y$7_@0:TPrimitive[1:10] = 3
39 + [8] Const mutate y$11:TPrimitive = 3
40 + [9] Reassign mutate y$13_@0[1:10] = read y$11:TPrimitive
41 [9] Goto bb1
42 bb1:
43 predecessor blocks: bb2 bb3
40 - [10] Const mutate t$14_@2:TObject = Object { x: read x$6_@0:TPrimitive, y: read y$7_@0:TPrimitive }
44 + [10] Const mutate t$14_@2:TObject = Object { x: read x$12_@0, y: read y$13_@0 }
45 [11] Return freeze t$14_@2:TObject
46 ```
47
@@ -46,19 +50,23 @@ bb1:
50 ```
51 function foo(
52 ) {
49 - scope @0 [1:10] deps=[] out=[x$6_@0] {
50 - [1] Let mutate x$6_@0:TPrimitive[1:10] = 1
51 - [2] Let mutate y$7_@0:TPrimitive[1:10] = 2
52 - [3] Const mutate $8:TPrimitive = 1
53 - [4] Const mutate $9:TPrimitive = Binary read x$6_@0:TPrimitive > read $8:TPrimitive
53 + [1] Const mutate x$6:TPrimitive = 1
54 + [2] Const mutate y$7:TPrimitive = 2
55 + [3] Const mutate $8:TPrimitive = 1
56 + [4] Const mutate $9:TPrimitive = Binary read x$6:TPrimitive > read $8:TPrimitive
57 + scope @0 [1:10] deps=[] out=[x$12_@0] {
58 + [5] Let mutate x$12_@0[1:10] = read x$6:TPrimitive
59 + [5] Let mutate y$13_@0[1:10] = read y$7:TPrimitive
60 if (read $9:TPrimitive) {
55 - [6] Reassign mutate x$6_@0:TPrimitive[1:10] = 2
61 + [6] Const mutate x$10:TPrimitive = 2
62 + [7] Reassign mutate x$12_@0[1:10] = read x$10:TPrimitive
63 } else {
57 - [8] Reassign mutate y$7_@0:TPrimitive[1:10] = 3
64 + [8] Const mutate y$11:TPrimitive = 3
65 + [9] Reassign mutate y$13_@0[1:10] = read y$11:TPrimitive
66 }
67 }
60 - scope @2 [10:11] deps=[read x$6_@0:TPrimitive, read y$7_@0:TPrimitive] out=[t$14_@2] {
61 - [10] Const mutate t$14_@2:TObject = Object { x: read x$6_@0:TPrimitive, y: read y$7_@0:TPrimitive }
68 + scope @2 [10:11] deps=[read x$12_@0, read y$13_@0] out=[t$14_@2] {
69 + [10] Const mutate t$14_@2:TObject = Object { x: read x$12_@0, y: read y$13_@0 }
70 }
71 return freeze t$14_@2:TObject
72 }
@@ -70,33 +78,37 @@ function foo(
78 ```javascript
79 function foo$0() {
80 const $ = React.useMemoCache();
73 - let x$6;
81 + const x$6 = 1;
82 + const y$7 = 2;
83 + let x$12;
84 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
75 - x$6 = 1;
76 - let y$7 = 2;
85 + x$12 = x$6;
86 + let y$13 = y$7;
87
88 if (x$6 > 1) {
79 - x$6 = 2;
89 + const x$10 = 2;
90 + x$12 = x$10;
91 } else {
81 - y$7 = 3;
92 + const y$11 = 3;
93 + y$13 = y$11;
94 }
95
84 - $[0] = x$6;
96 + $[0] = x$12;
97 } else {
86 - x$6 = $[0];
98 + x$12 = $[0];
99 }
100
89 - const c_1 = $[1] !== x$6;
90 - const c_2 = $[2] !== y$7;
101 + const c_1 = $[1] !== x$12;
102 + const c_2 = $[2] !== y$13;
103 let t$14;
104
105 if (c_1 || c_2) {
106 t$14 = {
95 - x: x$6,
96 - y: y$7,
107 + x: x$12,
108 + y: y$13,
109 };
98 - $[1] = x$6;
99 - $[2] = y$7;
110 + $[1] = x$12;
111 + $[2] = y$13;
112 $[3] = t$14;
113 } else {
114 t$14 = $[3];
compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md
+22 -16
@@ -17,17 +17,19 @@ function foo() {
17
18 ```
19 bb0:
20 - [1] Let mutate x$4_@0:TPrimitive[1:7] = 1
20 + [1] Const mutate x$4:TPrimitive = 1
21 [2] Const mutate $5:TPrimitive = 1
22 - [3] Const mutate $6:TPrimitive = Binary read x$4_@0:TPrimitive === read $5:TPrimitive
22 + [3] Const mutate $6:TPrimitive = Binary read x$4:TPrimitive === read $5:TPrimitive
23 + [4] Let mutate x$8_@0[1:7] = read x$4:TPrimitive
24 [4] If (read $6:TPrimitive) then:bb2 else:bb1 fallthrough=bb1
25 bb2:
26 predecessor blocks: bb0
26 - [5] Reassign mutate x$4_@0:TPrimitive[1:7] = 2
27 + [5] Const mutate x$7:TPrimitive = 2
28 + [6] Reassign mutate x$8_@0[1:7] = read x$7:TPrimitive
29 [6] Goto bb1
30 bb1:
31 predecessor blocks: bb2 bb0
30 - [7] Return read x$4_@0:TPrimitive
32 + [7] Return read x$8_@0
33 ```
34
35 ## Reactive Scopes
@@ -35,15 +37,17 @@ bb1:
37 ```
38 function foo(
39 ) {
38 - scope @0 [1:7] deps=[] out=[x$4_@0] {
39 - [1] Let mutate x$4_@0:TPrimitive[1:7] = 1
40 - [2] Const mutate $5:TPrimitive = 1
41 - [3] Const mutate $6:TPrimitive = Binary read x$4_@0:TPrimitive === read $5:TPrimitive
40 + [1] Const mutate x$4:TPrimitive = 1
41 + [2] Const mutate $5:TPrimitive = 1
42 + [3] Const mutate $6:TPrimitive = Binary read x$4:TPrimitive === read $5:TPrimitive
43 + scope @0 [1:7] deps=[] out=[x$8_@0] {
44 + [4] Let mutate x$8_@0[1:7] = read x$4:TPrimitive
45 if (read $6:TPrimitive) {
43 - [5] Reassign mutate x$4_@0:TPrimitive[1:7] = 2
46 + [5] Const mutate x$7:TPrimitive = 2
47 + [6] Reassign mutate x$8_@0[1:7] = read x$7:TPrimitive
48 }
49 }
46 - return read x$4_@0:TPrimitive
50 + return read x$8_@0
51 }
52
53 ```
@@ -53,20 +57,22 @@ function foo(
57 ```javascript
58 function foo$0() {
59 const $ = React.useMemoCache();
56 - let x$4;
60 + const x$4 = 1;
61 + let x$8;
62 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
58 - x$4 = 1;
63 + x$8 = x$4;
64
65 if (x$4 === 1) {
61 - x$4 = 2;
66 + const x$7 = 2;
67 + x$8 = x$7;
68 }
69
64 - $[0] = x$4;
70 + $[0] = x$8;
71 } else {
66 - x$4 = $[0];
72 + x$8 = $[0];
73 }
74
69 - return x$4;
75 + return x$8;
76 }
77
78 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md
+19 -13
@@ -44,7 +44,8 @@ function log$0() {}
44
45 ```
46 bb0:
47 - [1] Let mutate str$6_@0:TPrimitive[1:8] = ""
47 + [1] Const mutate str$6:TPrimitive = ""
48 + [2] Let mutate str$10_@0[1:8] = read str$6:TPrimitive
49 [2] If (read cond$5) then:bb2 else:bb3 fallthrough=bb1
50 bb2:
51 predecessor blocks: bb0
@@ -53,11 +54,12 @@ bb2:
54 [5] Goto bb1
55 bb3:
56 predecessor blocks: bb0
56 - [6] Reassign mutate str$6_@0:TPrimitive[1:8] = "fallthrough test"
57 + [6] Const mutate str$8:TPrimitive = "fallthrough test"
58 + [7] Reassign mutate str$10_@0[1:8] = read str$8:TPrimitive
59 [7] Goto bb1
60 bb1:
61 predecessor blocks: bb2 bb3
60 - [8] Call mutate log$4:TFunction(read str$6_@0:TPrimitive)
62 + [8] Call mutate log$4:TFunction(read str$10_@0)
63 [9] Return
64 ```
65
@@ -67,16 +69,18 @@ bb1:
69 function Foo(
70 cond,
71 ) {
70 - scope @0 [1:8] deps=[read cond$5] out=[str$6_@0] {
71 - [1] Let mutate str$6_@0:TPrimitive[1:8] = ""
72 + [1] Const mutate str$6:TPrimitive = ""
73 + scope @0 [1:8] deps=[read cond$5] out=[str$10_@0] {
74 + [2] Let mutate str$10_@0[1:8] = read str$6:TPrimitive
75 if (read cond$5) {
76 [3] Const mutate str$7:TPrimitive = "other test"
77 [4] Call mutate log$4:TFunction(read str$7:TPrimitive)
78 } else {
76 - [6] Reassign mutate str$6_@0:TPrimitive[1:8] = "fallthrough test"
79 + [6] Const mutate str$8:TPrimitive = "fallthrough test"
80 + [7] Reassign mutate str$10_@0[1:8] = read str$8:TPrimitive
81 }
82 }
79 - [8] Call mutate log$4:TFunction(read str$6_@0:TPrimitive)
83 + [8] Call mutate log$4:TFunction(read str$10_@0)
84 return
85 }
86
@@ -87,25 +91,27 @@ function Foo(
91 ```javascript
92 function Foo$0(cond$5) {
93 const $ = React.useMemoCache();
94 + const str$6 = "";
95 const c_0 = $[0] !== cond$5;
91 - let str$6;
96 + let str$10;
97 if (c_0) {
93 - str$6 = "";
98 + str$10 = str$6;
99
100 if (cond$5) {
101 const str$7 = "other test";
102 log$4(str$7);
103 } else {
99 - str$6 = "fallthrough test";
104 + const str$8 = "fallthrough test";
105 + str$10 = str$8;
106 }
107
108 $[0] = cond$5;
103 - $[1] = str$6;
109 + $[1] = str$10;
110 } else {
105 - str$6 = $[1];
111 + str$10 = $[1];
112 }
113
108 - log$4(str$6);
114 + log$4(str$10);
115 }
116
117 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-sibling-phis.expect.md
+44 -32
@@ -34,36 +34,40 @@ bb0:
34 bb2:
35 predecessor blocks: bb0
36 [4] Const mutate $15:TPrimitive = true
37 - [5] Let mutate x$16_@0[5:10] = undefined
37 + [5] Let mutate x$18_@0[5:10] = undefined
38 [5] If (read $15:TPrimitive) then:bb4 else:bb5 fallthrough=bb3
39 bb4:
40 predecessor blocks: bb2
41 - [6] Reassign mutate x$16_@0[5:10] = read a$9
41 + [6] Const mutate x$16 = read a$9
42 + [7] Reassign mutate x$18_@0[5:10] = read x$16
43 [7] Goto bb3
44 bb5:
45 predecessor blocks: bb2
45 - [8] Reassign mutate x$16_@0[5:10] = read b$10
46 + [8] Const mutate x$17 = read b$10
47 + [9] Reassign mutate x$18_@0[5:10] = read x$17
48 [9] Goto bb3
49 bb3:
50 predecessor blocks: bb4 bb5
49 - [10] read x$16_@0
51 + [10] read x$18_@0
52 [11] Goto bb1
53 bb6:
54 predecessor blocks: bb0
55 [12] Const mutate $19:TPrimitive = true
54 - [13] Let mutate x$20_@1[13:18] = undefined
56 + [13] Let mutate x$22_@1[13:18] = undefined
57 [13] If (read $19:TPrimitive) then:bb8 else:bb9 fallthrough=bb7
58 bb8:
59 predecessor blocks: bb6
58 - [14] Reassign mutate x$20_@1[13:18] = read c$11
60 + [14] Const mutate x$20 = read c$11
61 + [15] Reassign mutate x$22_@1[13:18] = read x$20
62 [15] Goto bb7
63 bb9:
64 predecessor blocks: bb6
62 - [16] Reassign mutate x$20_@1[13:18] = read d$12
65 + [16] Const mutate x$21 = read d$12
66 + [17] Reassign mutate x$22_@1[13:18] = read x$21
67 [17] Goto bb7
68 bb7:
69 predecessor blocks: bb8 bb9
66 - [18] read x$20_@1
70 + [18] read x$22_@1
71 [19] Goto bb1
72 bb1:
73 predecessor blocks: bb3 bb7
@@ -83,26 +87,30 @@ function foo(
87 [2] Const mutate $14:TPrimitive = true
88 if (read $14:TPrimitive) {
89 [4] Const mutate $15:TPrimitive = true
86 - scope @0 [5:10] deps=[read a$9, read b$10] out=[x$16_@0] {
87 - [5] Let mutate x$16_@0[5:10] = undefined
90 + scope @0 [5:10] deps=[read a$9, read b$10] out=[x$18_@0] {
91 + [5] Let mutate x$18_@0[5:10] = undefined
92 if (read $15:TPrimitive) {
89 - [6] Reassign mutate x$16_@0[5:10] = read a$9
93 + [6] Const mutate x$16 = read a$9
94 + [7] Reassign mutate x$18_@0[5:10] = read x$16
95 } else {
91 - [8] Reassign mutate x$16_@0[5:10] = read b$10
96 + [8] Const mutate x$17 = read b$10
97 + [9] Reassign mutate x$18_@0[5:10] = read x$17
98 }
99 }
94 - [10] read x$16_@0
100 + [10] read x$18_@0
101 } else {
102 [12] Const mutate $19:TPrimitive = true
97 - scope @1 [13:18] deps=[read c$11, read d$12] out=[x$20_@1] {
98 - [13] Let mutate x$20_@1[13:18] = undefined
103 + scope @1 [13:18] deps=[read c$11, read d$12] out=[x$22_@1] {
104 + [13] Let mutate x$22_@1[13:18] = undefined
105 if (read $19:TPrimitive) {
100 - [14] Reassign mutate x$20_@1[13:18] = read c$11
106 + [14] Const mutate x$20 = read c$11
107 + [15] Reassign mutate x$22_@1[13:18] = read x$20
108 } else {
102 - [16] Reassign mutate x$20_@1[13:18] = read d$12
109 + [16] Const mutate x$21 = read d$12
110 + [17] Reassign mutate x$22_@1[13:18] = read x$21
111 }
112 }
105 - [18] read x$20_@1
113 + [18] read x$22_@1
114 }
115 return
116 }
@@ -118,47 +126,51 @@ function foo$0(a$9, b$10, c$11, d$12) {
126 if (true) {
127 const c_0 = $[0] !== a$9;
128 const c_1 = $[1] !== b$10;
121 - let x$16;
129 + let x$18;
130
131 if (c_0 || c_1) {
124 - x$16 = undefined;
132 + x$18 = undefined;
133
134 if (true) {
127 - x$16 = a$9;
135 + const x$16 = a$9;
136 + x$18 = x$16;
137 } else {
129 - x$16 = b$10;
138 + const x$17 = b$10;
139 + x$18 = x$17;
140 }
141
142 $[0] = a$9;
143 $[1] = b$10;
134 - $[2] = x$16;
144 + $[2] = x$18;
145 } else {
136 - x$16 = $[2];
146 + x$18 = $[2];
147 }
148
139 - x$16;
149 + x$18;
150 } else {
151 const c_3 = $[3] !== c$11;
152 const c_4 = $[4] !== d$12;
143 - let x$20;
153 + let x$22;
154
155 if (c_3 || c_4) {
146 - x$20 = undefined;
156 + x$22 = undefined;
157
158 if (true) {
149 - x$20 = c$11;
159 + const x$20 = c$11;
160 + x$22 = x$20;
161 } else {
151 - x$20 = d$12;
162 + const x$21 = d$12;
163 + x$22 = x$21;
164 }
165
166 $[3] = c$11;
167 $[4] = d$12;
156 - $[5] = x$20;
168 + $[5] = x$22;
169 } else {
158 - x$20 = $[5];
170 + x$22 = $[5];
171 }
172
161 - x$20;
173 + x$22;
174 }
175 }
176
compiler/forget/src/__tests__/fixtures/hir/ssa-simple-phi.expect.md
+22 -16
@@ -23,19 +23,21 @@ bb0:
23 [1] Const mutate y$5:TPrimitive = 2
24 [2] Const mutate $6:TPrimitive = 1
25 [3] Const mutate $7:TPrimitive = Binary read y$5:TPrimitive > read $6:TPrimitive
26 - [4] Let mutate y$8_@0:TPrimitive[4:9] = undefined
26 + [4] Let mutate y$10_@0[4:9] = undefined
27 [4] If (read $7:TPrimitive) then:bb2 else:bb3 fallthrough=bb1
28 bb2:
29 predecessor blocks: bb0
30 - [5] Reassign mutate y$8_@0:TPrimitive[4:9] = 1
30 + [5] Const mutate y$8:TPrimitive = 1
31 + [6] Reassign mutate y$10_@0[4:9] = read y$8:TPrimitive
32 [6] Goto bb1
33 bb3:
34 predecessor blocks: bb0
34 - [7] Reassign mutate y$8_@0:TPrimitive[4:9] = 2
35 + [7] Const mutate y$9:TPrimitive = 2
36 + [8] Reassign mutate y$10_@0[4:9] = read y$9:TPrimitive
37 [8] Goto bb1
38 bb1:
39 predecessor blocks: bb2 bb3
38 - [9] Const mutate x$11 = read y$8_@0:TPrimitive
40 + [9] Const mutate x$11 = read y$10_@0
41 [10] Return
42 ```
43
@@ -47,15 +49,17 @@ function foo(
49 [1] Const mutate y$5:TPrimitive = 2
50 [2] Const mutate $6:TPrimitive = 1
51 [3] Const mutate $7:TPrimitive = Binary read y$5:TPrimitive > read $6:TPrimitive
50 - scope @0 [4:9] deps=[] out=[y$8_@0] {
51 - [4] Let mutate y$8_@0:TPrimitive[4:9] = undefined
52 + scope @0 [4:9] deps=[] out=[y$10_@0] {
53 + [4] Let mutate y$10_@0[4:9] = undefined
54 if (read $7:TPrimitive) {
53 - [5] Reassign mutate y$8_@0:TPrimitive[4:9] = 1
55 + [5] Const mutate y$8:TPrimitive = 1
56 + [6] Reassign mutate y$10_@0[4:9] = read y$8:TPrimitive
57 } else {
55 - [7] Reassign mutate y$8_@0:TPrimitive[4:9] = 2
58 + [7] Const mutate y$9:TPrimitive = 2
59 + [8] Reassign mutate y$10_@0[4:9] = read y$9:TPrimitive
60 }
61 }
58 - [9] Const mutate x$11 = read y$8_@0:TPrimitive
62 + [9] Const mutate x$11 = read y$10_@0
63 return
64 }
65
@@ -67,22 +71,24 @@ function foo(
71 function foo$0() {
72 const $ = React.useMemoCache();
73 const y$5 = 2;
70 - let y$8;
74 + let y$10;
75 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
72 - y$8 = undefined;
76 + y$10 = undefined;
77
78 if (y$5 > 1) {
75 - y$8 = 1;
79 + const y$8 = 1;
80 + y$10 = y$8;
81 } else {
77 - y$8 = 2;
82 + const y$9 = 2;
83 + y$10 = y$9;
84 }
85
80 - $[0] = y$8;
86 + $[0] = y$10;
87 } else {
82 - y$8 = $[0];
88 + y$10 = $[0];
89 }
90
85 - const x$11 = y$8;
91 + const x$11 = y$10;
92 }
93
94 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-switch.expect.md
+28 -19
@@ -33,7 +33,7 @@ bb0:
33 [3] Const mutate $12:TPrimitive = Binary read x$10:TPrimitive === read $11:TPrimitive
34 [4] Const mutate $13:TPrimitive = 1
35 [5] Const mutate $14:TPrimitive = Binary read x$10:TPrimitive === read $13:TPrimitive
36 - [6] Let mutate x$16_@0:TPrimitive[6:16] = undefined
36 + [6] Let mutate x$21_@0[6:16] = undefined
37 [6] Switch (read x$10:TPrimitive)
38 Case read $14:TPrimitive: bb5
39 Case read $12:TPrimitive: bb3
@@ -42,21 +42,24 @@ bb0:
42 bb5:
43 predecessor blocks: bb0
44 [7] Const mutate $15:TPrimitive = 1
45 - [8] Reassign mutate x$16_@0:TPrimitive[6:16] = Binary read x$10:TPrimitive + read $15:TPrimitive
45 + [8] Const mutate x$16:TPrimitive = Binary read x$10:TPrimitive + read $15:TPrimitive
46 + [9] Reassign mutate x$21_@0[6:16] = read x$16:TPrimitive
47 [9] Goto bb1
48 bb3:
49 predecessor blocks: bb0
50 [10] Const mutate $17:TPrimitive = 2
50 - [11] Reassign mutate x$16_@0:TPrimitive[6:16] = Binary read x$10:TPrimitive + read $17:TPrimitive
51 + [11] Const mutate x$18:TPrimitive = Binary read x$10:TPrimitive + read $17:TPrimitive
52 + [12] Reassign mutate x$21_@0[6:16] = read x$18:TPrimitive
53 [12] Goto bb1
54 bb2:
55 predecessor blocks: bb0
56 [13] Const mutate $19:TPrimitive = 3
55 - [14] Reassign mutate x$16_@0:TPrimitive[6:16] = Binary read x$10:TPrimitive + read $19:TPrimitive
57 + [14] Const mutate x$20:TPrimitive = Binary read x$10:TPrimitive + read $19:TPrimitive
58 + [15] Reassign mutate x$21_@0[6:16] = read x$20:TPrimitive
59 [15] Goto bb1
60 bb1:
61 predecessor blocks: bb5 bb3 bb2
59 - [16] Const mutate y$22 = read x$16_@0:TPrimitive
62 + [16] Const mutate y$22 = read x$21_@0
63 [17] Return
64 ```
65
@@ -70,26 +73,29 @@ function foo(
73 [3] Const mutate $12:TPrimitive = Binary read x$10:TPrimitive === read $11:TPrimitive
74 [4] Const mutate $13:TPrimitive = 1
75 [5] Const mutate $14:TPrimitive = Binary read x$10:TPrimitive === read $13:TPrimitive
73 - scope @0 [6:16] deps=[] out=[x$16_@0] {
74 - [6] Let mutate x$16_@0:TPrimitive[6:16] = undefined
76 + scope @0 [6:16] deps=[] out=[x$21_@0] {
77 + [6] Let mutate x$21_@0[6:16] = undefined
78 switch (read x$10:TPrimitive) {
79 case read $14:TPrimitive: {
80 [7] Const mutate $15:TPrimitive = 1
78 - [8] Reassign mutate x$16_@0:TPrimitive[6:16] = Binary read x$10:TPrimitive + read $15:TPrimitive
81 + [8] Const mutate x$16:TPrimitive = Binary read x$10:TPrimitive + read $15:TPrimitive
82 + [9] Reassign mutate x$21_@0[6:16] = read x$16:TPrimitive
83 break bb1
84 }
85 case read $12:TPrimitive: {
86 [10] Const mutate $17:TPrimitive = 2
83 - [11] Reassign mutate x$16_@0:TPrimitive[6:16] = Binary read x$10:TPrimitive + read $17:TPrimitive
87 + [11] Const mutate x$18:TPrimitive = Binary read x$10:TPrimitive + read $17:TPrimitive
88 + [12] Reassign mutate x$21_@0[6:16] = read x$18:TPrimitive
89 break bb1
90 }
91 default: {
92 [13] Const mutate $19:TPrimitive = 3
88 - [14] Reassign mutate x$16_@0:TPrimitive[6:16] = Binary read x$10:TPrimitive + read $19:TPrimitive
93 + [14] Const mutate x$20:TPrimitive = Binary read x$10:TPrimitive + read $19:TPrimitive
94 + [15] Reassign mutate x$21_@0[6:16] = read x$20:TPrimitive
95 }
96 }
97 }
92 - [16] Const mutate y$22 = read x$16_@0:TPrimitive
98 + [16] Const mutate y$22 = read x$21_@0
99 return
100 }
101
@@ -101,32 +107,35 @@ function foo(
107 function foo$0() {
108 const $ = React.useMemoCache();
109 const x$10 = 1;
104 - let x$16;
110 + let x$21;
111 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
106 - x$16 = undefined;
112 + x$21 = undefined;
113
114 bb1: switch (x$10) {
115 case x$10 === 1: {
110 - x$16 = x$10 + 1;
116 + const x$16 = x$10 + 1;
117 + x$21 = x$16;
118 break bb1;
119 }
120
121 case x$10 === 2: {
115 - x$16 = x$10 + 2;
122 + const x$18 = x$10 + 2;
123 + x$21 = x$18;
124 break bb1;
125 }
126
127 default: {
120 - x$16 = x$10 + 3;
128 + const x$20 = x$10 + 3;
129 + x$21 = x$20;
130 }
131 }
132
124 - $[0] = x$16;
133 + $[0] = x$21;
134 } else {
126 - x$16 = $[0];
135 + x$21 = $[0];
136 }
137
129 - const y$22 = x$16;
138 + const y$22 = x$21;
139 }
140
141 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md
+22 -16
@@ -16,17 +16,19 @@ function foo() {
16
17 ```
18 bb0:
19 - [1] Let mutate x$4_@0:TPrimitive[1:7] = 1
19 + [1] Const mutate x$4:TPrimitive = 1
20 [2] Const mutate $5:TPrimitive = 1
21 - [3] Const mutate $6:TPrimitive = Binary read x$4_@0:TPrimitive === read $5:TPrimitive
21 + [3] Const mutate $6:TPrimitive = Binary read x$4:TPrimitive === read $5:TPrimitive
22 + [4] Let mutate x$8_@0[1:7] = read x$4:TPrimitive
23 [4] If (read $6:TPrimitive) then:bb2 else:bb1 fallthrough=bb1
24 bb2:
25 predecessor blocks: bb0
25 - [5] Reassign mutate x$4_@0:TPrimitive[1:7] = 2
26 + [5] Const mutate x$7:TPrimitive = 2
27 + [6] Reassign mutate x$8_@0[1:7] = read x$7:TPrimitive
28 [6] Goto bb1
29 bb1:
30 predecessor blocks: bb2 bb0
29 - [7] Throw read x$4_@0:TPrimitive
31 + [7] Throw read x$8_@0
32 ```
33
34 ## Reactive Scopes
@@ -34,15 +36,17 @@ bb1:
36 ```
37 function foo(
38 ) {
37 - scope @0 [1:7] deps=[] out=[x$4_@0] {
38 - [1] Let mutate x$4_@0:TPrimitive[1:7] = 1
39 - [2] Const mutate $5:TPrimitive = 1
40 - [3] Const mutate $6:TPrimitive = Binary read x$4_@0:TPrimitive === read $5:TPrimitive
39 + [1] Const mutate x$4:TPrimitive = 1
40 + [2] Const mutate $5:TPrimitive = 1
41 + [3] Const mutate $6:TPrimitive = Binary read x$4:TPrimitive === read $5:TPrimitive
42 + scope @0 [1:7] deps=[] out=[x$8_@0] {
43 + [4] Let mutate x$8_@0[1:7] = read x$4:TPrimitive
44 if (read $6:TPrimitive) {
42 - [5] Reassign mutate x$4_@0:TPrimitive[1:7] = 2
45 + [5] Const mutate x$7:TPrimitive = 2
46 + [6] Reassign mutate x$8_@0[1:7] = read x$7:TPrimitive
47 }
48 }
45 - throw read x$4_@0:TPrimitive
49 + throw read x$8_@0
50 }
51
52 ```
@@ -52,20 +56,22 @@ function foo(
56 ```javascript
57 function foo$0() {
58 const $ = React.useMemoCache();
55 - let x$4;
59 + const x$4 = 1;
60 + let x$8;
61 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
57 - x$4 = 1;
62 + x$8 = x$4;
63
64 if (x$4 === 1) {
60 - x$4 = 2;
65 + const x$7 = 2;
66 + x$8 = x$7;
67 }
68
63 - $[0] = x$4;
69 + $[0] = x$8;
70 } else {
65 - x$4 = $[0];
71 + x$8 = $[0];
72 }
73
68 - throw x$4;
74 + throw x$8;
75 }
76
77 ```
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+54 -35
@@ -33,10 +33,11 @@ function Component(props) {
33 ```
34 bb0:
35 [1] Const mutate x$10_@1[1:12] = Array []
36 - [2] Let mutate y$11_@1:TPrimitive[1:12] = undefined
36 + [2] Const mutate y$11:TPrimitive = undefined
37 [3] Const mutate $12:TPrimitive = false
38 [4] Const mutate $13:TPrimitive = true
39 [5] Const mutate $14:TPrimitive = 1
40 + [6] Let mutate y$20_@1[1:12] = read y$11:TPrimitive
41 [6] Switch (read props$9.p0)
42 Case read $14:TPrimitive: bb1
43 Case read $13:TPrimitive: bb6
@@ -46,18 +47,20 @@ bb0:
47 bb6:
48 predecessor blocks: bb0
49 [7] Call mutate x$10_@1.push(read props$9.p2)
49 - [8] Reassign mutate y$11_@1:TPrimitive[1:12] = Array []
50 + [8] Const mutate y$15_@2 = Array []
51 + [9] Reassign mutate y$20_@1[1:12] = read y$15_@2
52 [9] Goto bb1
53 bb2:
54 predecessor blocks: bb0
53 - [10] Reassign mutate y$11_@1:TPrimitive[1:12] = read x$10_@1
55 + [10] Const mutate y$16 = read x$10_@1
56 + [11] Reassign mutate y$20_@1[1:12] = read y$16
57 [11] Goto bb1
58 bb1:
59 predecessor blocks: bb0 bb6 bb2
57 - [12] Const mutate child$19_@2 = JSX <read Component$0 data={freeze x$10_@1} ></read Component$0>
58 - [13] Call read y$11_@1.push(read props$9.p4)
59 - [14] Const mutate t7$22_@3 = JSX <read Component$0 data={freeze y$11_@1:TPrimitive} >{read child$19_@2}</read Component$0>
60 - [15] Return read t7$22_@3
60 + [12] Const mutate child$19_@3 = JSX <read Component$0 data={freeze x$10_@1} ></read Component$0>
61 + [13] Call read y$20_@1.push(read props$9.p4)
62 + [14] Const mutate t8$22_@4 = JSX <read Component$0 data={freeze y$20_@1} >{read child$19_@3}</read Component$0>
63 + [15] Return read t8$22_@4
64 ```
65
66 ## Reactive Scopes
@@ -68,35 +71,40 @@ function Component(
71 ) {
72 scope @1 [1:12] deps=[read props$9.p0, read props$9.p2] out=[x$10_@1] {
73 [1] Const mutate x$10_@1[1:12] = Array []
71 - [2] Let mutate y$11_@1:TPrimitive[1:12] = undefined
74 + [2] Const mutate y$11:TPrimitive = undefined
75 [3] Const mutate $12:TPrimitive = false
76 [4] Const mutate $13:TPrimitive = true
77 [5] Const mutate $14:TPrimitive = 1
78 + [6] Let mutate y$20_@1[1:12] = read y$11:TPrimitive
79 switch (read props$9.p0) {
80 case read $14:TPrimitive: {
81 break bb1
82 }
83 case read $13:TPrimitive: {
84 [7] Call mutate x$10_@1.push(read props$9.p2)
81 - [8] Reassign mutate y$11_@1:TPrimitive[1:12] = Array []
85 + scope @2 [8:9] deps=[] out=[y$15_@2] {
86 + [8] Const mutate y$15_@2 = Array []
87 + }
88 + [9] Reassign mutate y$20_@1[1:12] = read y$15_@2
89 break bb1
90 }
91 default: {
92 break bb1
93 }
94 case read $12:TPrimitive: {
88 - [10] Reassign mutate y$11_@1:TPrimitive[1:12] = read x$10_@1
95 + [10] Const mutate y$16 = read x$10_@1
96 + [11] Reassign mutate y$20_@1[1:12] = read y$16
97 }
98 }
99 }
92 - scope @2 [12:13] deps=[freeze x$10_@1] out=[child$19_@2] {
93 - [12] Const mutate child$19_@2 = JSX <read Component$0 data={freeze x$10_@1} ></read Component$0>
100 + scope @3 [12:13] deps=[freeze x$10_@1] out=[child$19_@3] {
101 + [12] Const mutate child$19_@3 = JSX <read Component$0 data={freeze x$10_@1} ></read Component$0>
102 }
95 - [13] Call read y$11_@1.push(read props$9.p4)
96 - scope @3 [14:15] deps=[freeze y$11_@1:TPrimitive, read child$19_@2] out=[$22_@3] {
97 - [14] Const mutate $22_@3 = JSX <read Component$0 data={freeze y$11_@1:TPrimitive} >{read child$19_@2}</read Component$0>
103 + [13] Call read y$20_@1.push(read props$9.p4)
104 + scope @4 [14:15] deps=[freeze y$20_@1, read child$19_@3] out=[$22_@4] {
105 + [14] Const mutate $22_@4 = JSX <read Component$0 data={freeze y$20_@1} >{read child$19_@3}</read Component$0>
106 }
99 - return read $22_@3
107 + return read $22_@4
108 }
109
110 ```
@@ -111,7 +119,8 @@ function Component$0(props$9) {
119 let x$10;
120 if (c_0 || c_1) {
121 x$10 = [];
114 - let y$11 = undefined;
122 + const y$11 = undefined;
123 + let y$20 = y$11;
124
125 bb1: switch (props$9.p0) {
126 case 1: {
@@ -120,7 +129,16 @@ function Component$0(props$9) {
129
130 case true: {
131 x$10.push(props$9.p2);
123 - y$11 = [];
132 + let y$15;
133 +
134 + if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
135 + y$15 = [];
136 + $[3] = y$15;
137 + } else {
138 + y$15 = $[3];
139 + }
140 +
141 + y$20 = y$15;
142 break bb1;
143 }
144
@@ -129,7 +147,8 @@ function Component$0(props$9) {
147 }
148
149 case false: {
132 - y$11 = x$10;
150 + const y$16 = x$10;
151 + y$20 = y$16;
152 }
153 }
154
@@ -140,32 +159,32 @@ function Component$0(props$9) {
159 x$10 = $[2];
160 }
161
143 - const c_3 = $[3] !== x$10;
162 + const c_4 = $[4] !== x$10;
163 let child$19;
164
146 - if (c_3) {
165 + if (c_4) {
166 child$19 = <Component$0 data={x$10}></Component$0>;
148 - $[3] = x$10;
149 - $[4] = child$19;
167 + $[4] = x$10;
168 + $[5] = child$19;
169 } else {
151 - child$19 = $[4];
170 + child$19 = $[5];
171 }
172
154 - y$11.push(props$9.p4);
155 - const c_5 = $[5] !== y$11;
156 - const c_6 = $[6] !== child$19;
157 - let t7$22;
173 + y$20.push(props$9.p4);
174 + const c_6 = $[6] !== y$20;
175 + const c_7 = $[7] !== child$19;
176 + let t8$22;
177
159 - if (c_5 || c_6) {
160 - t7$22 = <Component$0 data={y$11}>{child$19}</Component$0>;
161 - $[5] = y$11;
162 - $[6] = child$19;
163 - $[7] = t7$22;
178 + if (c_6 || c_7) {
179 + t8$22 = <Component$0 data={y$20}>{child$19}</Component$0>;
180 + $[6] = y$20;
181 + $[7] = child$19;
182 + $[8] = t8$22;
183 } else {
165 - t7$22 = $[7];
184 + t8$22 = $[8];
185 }
186
168 - return t7$22;
187 + return t8$22;
188 }
189
190 ```
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+21 -15
@@ -28,9 +28,10 @@ function Component(props) {
28 ```
29 bb0:
30 [1] Const mutate x$9_@1[1:12] = Array []
31 - [2] Let mutate y$10_@1:TPrimitive[1:12] = undefined
31 + [2] Const mutate y$10:TPrimitive = undefined
32 [3] Const mutate $11:TPrimitive = false
33 [4] Const mutate $12:TPrimitive = true
34 + [5] Let mutate y$20_@1[1:12] = read y$10:TPrimitive
35 [5] Switch (read props$8.p0)
36 Case read $12:TPrimitive: bb4
37 Case read $11:TPrimitive: bb2
@@ -44,13 +45,14 @@ bb4:
45 [9] Goto bb2
46 bb2:
47 predecessor blocks: bb4 bb0
47 - [10] Reassign mutate y$10_@1:TPrimitive[1:12] = read x$9_@1
48 + [10] Const mutate y$15 = read x$9_@1
49 + [11] Reassign mutate y$20_@1[1:12] = read y$15
50 [11] Goto bb1
51 bb1:
52 predecessor blocks: bb2 bb0
53 [12] Const mutate child$19_@3 = JSX <read Component$0 data={freeze x$9_@1} ></read Component$0>
52 - [13] Call read y$10_@1.push(read props$8.p4)
53 - [14] Const mutate t8$23_@4 = JSX <read Component$0 data={read y$10_@1:TPrimitive} >{read child$19_@3}</read Component$0>
54 + [13] Call read y$20_@1.push(read props$8.p4)
55 + [14] Const mutate t8$23_@4 = JSX <read Component$0 data={read y$20_@1} >{read child$19_@3}</read Component$0>
56 [15] Return read t8$23_@4
57 ```
58
@@ -62,9 +64,10 @@ function Component(
64 ) {
65 scope @1 [1:12] deps=[read props$8.p0, read props$8.p2, read props$8.p3] out=[x$9_@1] {
66 [1] Const mutate x$9_@1[1:12] = Array []
65 - [2] Let mutate y$10_@1:TPrimitive[1:12] = undefined
67 + [2] Const mutate y$10:TPrimitive = undefined
68 [3] Const mutate $11:TPrimitive = false
69 [4] Const mutate $12:TPrimitive = true
70 + [5] Let mutate y$20_@1[1:12] = read y$10:TPrimitive
71 switch (read props$8.p0) {
72 case read $12:TPrimitive: {
73 [6] Call mutate x$9_@1.push(read props$8.p2)
@@ -72,16 +75,17 @@ function Component(
75 [8] Const mutate y$13_@2 = Array []
76 }
77 case read $11:TPrimitive: {
75 - [10] Reassign mutate y$10_@1:TPrimitive[1:12] = read x$9_@1
78 + [10] Const mutate y$15 = read x$9_@1
79 + [11] Reassign mutate y$20_@1[1:12] = read y$15
80 }
81 }
82 }
83 scope @3 [12:13] deps=[freeze x$9_@1] out=[child$19_@3] {
84 [12] Const mutate child$19_@3 = JSX <read Component$0 data={freeze x$9_@1} ></read Component$0>
85 }
82 - [13] Call read y$10_@1.push(read props$8.p4)
83 - scope @4 [14:15] deps=[read y$10_@1:TPrimitive, read child$19_@3] out=[$23_@4] {
84 - [14] Const mutate $23_@4 = JSX <read Component$0 data={read y$10_@1:TPrimitive} >{read child$19_@3}</read Component$0>
86 + [13] Call read y$20_@1.push(read props$8.p4)
87 + scope @4 [14:15] deps=[read y$20_@1, read child$19_@3] out=[$23_@4] {
88 + [14] Const mutate $23_@4 = JSX <read Component$0 data={read y$20_@1} >{read child$19_@3}</read Component$0>
89 }
90 return read $23_@4
91 }
@@ -99,7 +103,8 @@ function Component$0(props$8) {
103 let x$9;
104 if (c_0 || c_1 || c_2) {
105 x$9 = [];
102 - let y$10 = undefined;
106 + const y$10 = undefined;
107 + let y$20 = y$10;
108
109 switch (props$8.p0) {
110 case true: {
@@ -109,7 +114,8 @@ function Component$0(props$8) {
114 }
115
116 case false: {
112 - y$10 = x$9;
117 + const y$15 = x$9;
118 + y$20 = y$15;
119 }
120 }
121
@@ -132,14 +138,14 @@ function Component$0(props$8) {
138 child$19 = $[5];
139 }
140
135 - y$10.push(props$8.p4);
136 - const c_6 = $[6] !== y$10;
141 + y$20.push(props$8.p4);
142 + const c_6 = $[6] !== y$20;
143 const c_7 = $[7] !== child$19;
144 let t8$23;
145
146 if (c_6 || c_7) {
141 - t8$23 = <Component$0 data={y$10}>{child$19}</Component$0>;
142 - $[6] = y$10;
147 + t8$23 = <Component$0 data={y$20}>{child$19}</Component$0>;
148 + $[6] = y$20;
149 $[7] = child$19;
150 $[8] = t8$23;
151 } else {