@samitouri / QOS-React-2 / commits / fc1320552b

[ssa] Potential improvements to ssa construction

Redo of #711 Note that one test (switch.js) is failing, i'm working on a fix.

Joseph Savona committed Oct 27, 2022 at 13:20 UTC fc1320552b0c36ce0bdbe985941398afcc43989a
14 files changed +168 -126
compiler/forget/src/HIR/SSAify.ts
+43 -16
@@ -22,11 +22,10 @@ type State = {
22 incompletePhis: IncompletePhi[];
23 };
24
25 -const unsealedPreds: Map<BasicBlock, number> = new Map();
26 -
25 class SSABuilder {
26 #states: Map<BasicBlock, State> = new Map();
27 #current: BasicBlock | null = null;
28 + unsealedPreds: Map<BasicBlock, number> = new Map();
29 #env: Environment;
30
31 constructor(env: Environment) {
@@ -73,13 +72,13 @@ class SSABuilder {
72
73 if (block.preds.size == 0) {
74 // We're at the entry block and haven't found our defintion yet.
76 - console.log(
77 - `Unable to find "${printIdentifier(oldId)}", assuming it's a global`
78 - );
75 + // console.log(
76 + // `Unable to find "${printIdentifier(oldId)}", assuming it's a global`
77 + // );
78 return oldId;
79 }
80
82 - if (unsealedPreds.get(block)! > 0) {
81 + if (this.unsealedPreds.get(block)! > 0) {
82 // We haven't visited all our predecessors, let's place an incomplete phi
83 // for now.
84 const newId = { ...oldId, id: this.nextIdentifierId };
@@ -96,17 +95,45 @@ class SSABuilder {
95 return newId;
96 }
97
99 - // There are multiple predecessors, we need a phi.
100 - const newId = { ...oldId, id: this.nextIdentifierId };
98 + // There are multiple predecessors, we may need a phi.
99 + return this.maybeAddPhi(block, oldId, state);
100 + }
101 +
102 + maybeAddPhi(block: BasicBlock, oldId: Identifier, state: State): Identifier {
103 // Adding a phi may loop back to our block if there is a loop in the CFG. We
104 // update our defs before adding the phi to terminate the recursion rather than
105 // looping infinitely.
106 + const newId = { ...oldId, id: this.nextIdentifierId };
107 state.defs.set(oldId, newId);
105 - this.addPhi(block, oldId, newId);
108
107 - // TODO(gsn): Can we just return `newPlace` rather than looking it up?
108 - // `addPhi` _can_ mutate it, but _will_ it?
109 - return state.defs.get(oldId)!;
109 + const predDefs: Map<BasicBlock, Identifier> = new Map();
110 + const predIds: Set<Identifier> = new Set();
111 + for (const predBlock of block.preds) {
112 + const predId = this.getIdAt(oldId, predBlock);
113 + predDefs.set(predBlock, predId);
114 + predIds.add(predId);
115 + }
116 +
117 + // if all predecessors have the same id, then there is no need for a phi node.
118 + // note that in the case of a loop there are guaranteed to be multiple values,
119 + // since we have already updated this block with a new identifier to terminate
120 + // the recursion
121 + if (predIds.size === 1) {
122 + // there was only a single incoming id so we don't need a phi node,
123 + // replace with that incoming id instead
124 + const predId = [...predIds][0]!;
125 + state.defs.set(oldId, predId);
126 + return predId;
127 + }
128 +
129 + const phi: Phi = {
130 + kind: "Phi",
131 + id: newId,
132 + operands: predDefs,
133 + };
134 +
135 + block.phis.add(phi);
136 + return newId;
137 }
138
139 addPhi(block: BasicBlock, oldId: Identifier, newId: Identifier) {
@@ -197,14 +224,14 @@ export default function buildSSA(func: HIRFunction, env: Environment) {
224 const outputBlocks = outputs.map((id) => func.body.blocks.get(id)!);
225 for (const output of outputBlocks) {
226 let count;
200 - if (unsealedPreds.has(output)) {
201 - count = unsealedPreds.get(output)! - 1;
227 + if (builder.unsealedPreds.has(output)) {
228 + count = builder.unsealedPreds.get(output)! - 1;
229 } else {
230 count = output.preds.size - 1;
231 }
205 - unsealedPreds.set(output, count);
232 + builder.unsealedPreds.set(output, count);
233
207 - if (count == 0 && visitedBlocks.has(output)) {
234 + if (count === 0 && visitedBlocks.has(output)) {
235 builder.fixIncompletePhis(output);
236 }
237 }
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+11 -17
@@ -44,11 +44,11 @@ bb0:
44 Goto bb1
45 bb1:
46 predecessor blocks: bb0 bb4 bb7
47 - items$33: phi(bb0: items$27, bb4: items$50, bb7: items$50)
48 - item$35: phi(bb0: item$10, bb4: item$42, bb7: item$42)
49 - seen$38: phi(bb0: seen$30, bb4: seen$41, bb7: seen$41)
50 - renderedItems$46: phi(bb0: renderedItems$29, bb4: renderedItems$45, bb7: renderedItems$45)
51 - max$48: phi(bb0: max$32, bb4: max$47, bb7: max$47)
47 + items$33: phi(bb0: items$27, bb4: items$33, bb7: items$33)
48 + item$35: phi(bb0: item$10, bb4: item$35, bb7: item$35)
49 + seen$38: phi(bb0: seen$30, bb4: seen$38, bb7: seen$38)
50 + renderedItems$46: phi(bb0: renderedItems$29, bb4: renderedItems$46, bb7: renderedItems$46)
51 + max$48: phi(bb0: max$32, bb4: max$48, bb7: max$48)
52 If (read items$33) then:bb3 else:bb2
53 bb3:
54 predecessor blocks: bb1
@@ -66,24 +66,18 @@ bb9:
66 bb7:
67 predecessor blocks: bb9 bb8
68 $40: phi(bb9: $39, bb8: $37)
69 - seen$41: phi(bb9: seen$38, bb8: seen$38)
70 - item$42: phi(bb9: item$35, bb8: item$35)
71 - renderedItems$45: phi(bb9: renderedItems$46, bb8: renderedItems$46)
72 - max$47: phi(bb9: max$48, bb8: max$48)
73 - items$50: phi(bb9: items$33, bb8: items$33)
69 If (read $40) then:bb1 else:bb4
70 bb4:
71 predecessor blocks: bb7
77 - Call mutate seen$41.add(mutate item$42)
72 + Call mutate seen$38.add(mutate item$35)
73 Const mutate $43 = "div"
79 - Const mutate $44 = JSX <read $43>{read item$42}</read $43>
80 - Call mutate renderedItems$45.push(read $44)
81 - Const mutate $49 = Binary read renderedItems$45.length >= read max$47
74 + Const mutate $44 = JSX <read $43>{read item$35}</read $43>
75 + Call mutate renderedItems$46.push(read $44)
76 + Const mutate $49 = Binary read renderedItems$46.length >= read max$48
77 If (read $49) then:bb2 else:bb1
78 bb2:
79 predecessor blocks: bb1 bb4
85 - renderedItems$51: phi(bb1: renderedItems$46, bb4: renderedItems$45)
86 - Const mutate count$52 = read renderedItems$51.length
80 + Const mutate count$52 = read renderedItems$46.length
81 Const mutate $53 = "div"
82 Const mutate $54 = "\n "
83 Const mutate $55 = "h1"
@@ -91,7 +85,7 @@ bb2:
85 Const mutate $57 = JSX <read $55>{freeze count$52}{read $56}</read $55>
86 Const mutate $58 = "\n "
87 Const mutate $59 = "\n "
94 - Const mutate $60 = JSX <read $53>{read $54}{read $57}{read $58}{freeze renderedItems$51}{read $59}</read $53>
88 + Const mutate $60 = JSX <read $53>{read $54}{read $57}{read $58}{freeze renderedItems$46}{read $59}</read $53>
89 Return read $60
90 ```
91
compiler/forget/src/__tests__/fixtures/hir/conditional-break.expect.md
+8 -12
@@ -119,10 +119,8 @@ bb2:
119 Goto bb1
120 bb1:
121 predecessor blocks: bb0 bb2
122 - a$5: phi(bb0: a$4, bb2: a$4)
123 - props$6: phi(bb0: props$3, bb2: props$3)
124 - Call mutate a$5.push(read props$6.d)
125 - Return freeze a$5
122 + Call mutate a$4.push(read props$3.d)
123 + Return freeze a$4
124 ```
125
126 ## Code
@@ -136,8 +134,8 @@ function Component$0(props$3) {
134 ("<<TODO: handle complex control flow in codegen>>");
135 }
136
139 - a$5.push(props$6.d);
140 - return a$5;
137 + a$4.push(props$3.d);
138 + return a$4;
139 }
140
141 ```
@@ -221,10 +219,8 @@ bb2:
219 Goto bb1
220 bb1:
221 predecessor blocks: bb2 bb0
224 - a$5: phi(bb2: a$4, bb0: a$4)
225 - props$6: phi(bb2: props$3, bb0: props$3)
226 - Call mutate a$5.push(read props$6.d)
227 - Return freeze a$5
222 + Call mutate a$4.push(read props$3.d)
223 + Return freeze a$4
224 ```
225
226 ## Code
@@ -234,8 +230,8 @@ function Component$0(props$3) {
230 const a$4 = [];
231 a$4.push(props$3.a);
232 if (props$3.b) {
237 - a$5.push(props$6.d);
238 - return a$5;
233 + a$4.push(props$3.d);
234 + return a$4;
235 }
236
237 a$4.push(props$3.c);
compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md
+12 -26
@@ -76,21 +76,14 @@ bb2:
76 Goto bb1
77 bb1:
78 predecessor blocks: bb0 bb2
79 - props$9: phi(bb0: props$6, bb2: props$6)
80 - b$10: phi(bb0: b$8, bb2: b$8)
81 - Foo$12: phi(bb0: Foo$4, bb2: Foo$4)
82 - a$14: phi(bb0: a$7, bb2: a$7)
83 - If (read props$9.p1) then:bb4 else:bb3
79 + If (read props$6.p1) then:bb4 else:bb3
80 bb4:
81 predecessor blocks: bb1
86 - Call mutate b$10.push(read props$9.p2)
82 + Call mutate b$8.push(read props$6.p2)
83 Goto bb3
84 bb3:
85 predecessor blocks: bb1 bb4
90 - Foo$11: phi(bb1: Foo$12, bb4: Foo$12)
91 - a$13: phi(bb1: a$14, bb4: a$14)
92 - b$15: phi(bb1: b$10, bb4: b$10)
93 - Const mutate $16 = JSX <read Foo$11 a={freeze a$13} b={freeze b$15} ></read Foo$11>
86 + Const mutate $16 = JSX <read Foo$4 a={freeze a$7} b={freeze b$8} ></read Foo$4>
87 Return read $16
88 ```
89
@@ -105,12 +98,12 @@ function Component$0(props$6) {
98 ("<<TODO: handle complex control flow in codegen>>");
99 }
100
108 - if (props$9.p1) {
109 - b$10.push(props$9.p2);
101 + if (props$6.p1) {
102 + b$8.push(props$6.p2);
103 ("<<TODO: handle complex control flow in codegen>>");
104 }
105
113 - return <Foo$11 a={a$13} b={b$15}></Foo$11>;
106 + return <Foo$4 a={a$7} b={b$8}></Foo$4>;
107 }
108
109 ```
@@ -128,21 +121,14 @@ bb2:
121 Goto bb1
122 bb1:
123 predecessor blocks: bb0 bb2
131 - props$12: phi(bb0: props$8, bb2: props$8)
132 - b$13: phi(bb0: b$10, bb2: b$10)
133 - Foo$15: phi(bb0: Foo$6, bb2: Foo$6)
134 - a$17: phi(bb0: a$9, bb2: a$9)
135 - If (read props$12.p1) then:bb4 else:bb3
124 + If (read props$8.p1) then:bb4 else:bb3
125 bb4:
126 predecessor blocks: bb1
138 - Call mutate b$13.push(read props$12.p2)
127 + Call mutate b$10.push(read props$8.p2)
128 Goto bb3
129 bb3:
130 predecessor blocks: bb1 bb4
142 - Foo$14: phi(bb1: Foo$15, bb4: Foo$15)
143 - a$16: phi(bb1: a$17, bb4: a$17)
144 - b$18: phi(bb1: b$13, bb4: b$13)
145 - Const mutate $19 = JSX <read Foo$14 a={freeze a$16} b={freeze b$18} ></read Foo$14>
131 + Const mutate $19 = JSX <read Foo$6 a={freeze a$9} b={freeze b$10} ></read Foo$6>
132 Return read $19
133 ```
134
@@ -157,12 +143,12 @@ function Component$0(props$8) {
143 ("<<TODO: handle complex control flow in codegen>>");
144 }
145
160 - if (props$12.p1) {
161 - b$13.push(props$12.p2);
146 + if (props$8.p1) {
147 + b$10.push(props$8.p2);
148 ("<<TODO: handle complex control flow in codegen>>");
149 }
150
165 - return <Foo$14 a={a$16} b={b$18}></Foo$14>;
151 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
152 }
153
154 ```
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+6 -8
@@ -40,12 +40,10 @@ bb3:
40 Goto bb1
41 bb1:
42 predecessor blocks: bb3 bb2
43 - useFreeze$13: phi(bb3: useFreeze$5, bb2: useFreeze$5)
43 a$14: phi(bb3: a$12, bb2: a$11)
45 - call$15: phi(bb3: call$6, bb2: call$6)
46 - Call read useFreeze$13(freeze a$14)
47 - Call read useFreeze$13(read a$14)
48 - Call mutate call$15(read a$14)
44 + Call read useFreeze$5(freeze a$14)
45 + Call read useFreeze$5(read a$14)
46 + Call mutate call$6(read a$14)
47 Return read a$14
48 ```
49
@@ -64,9 +62,9 @@ function Component$0(props$7) {
62 ("<<TODO: handle complex control flow in codegen>>");
63 }
64
67 - useFreeze$13(a$14);
68 - useFreeze$13(a$14);
69 - call$15(a$14);
65 + useFreeze$5(a$14);
66 + useFreeze$5(a$14);
67 + call$6(a$14);
68 return a$14;
69 }
70
compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md
+2 -5
@@ -107,10 +107,7 @@ bb2:
107 Goto bb1
108 bb1:
109 predecessor blocks: bb0 bb2
110 - Foo$11: phi(bb0: Foo$6, bb2: Foo$6)
111 - a$12: phi(bb0: a$9, bb2: a$9)
112 - b$13: phi(bb0: b$10, bb2: b$10)
113 - Const mutate $14 = JSX <read Foo$11 a={freeze a$12} b={freeze b$13} ></read Foo$11>
110 + Const mutate $14 = JSX <read Foo$6 a={freeze a$9} b={freeze b$10} ></read Foo$6>
111 Return read $14
112 ```
113
@@ -126,7 +123,7 @@ function Component$0(props$8) {
123 ("<<TODO: handle complex control flow in codegen>>");
124 }
125
129 - return <Foo$11 a={a$12} b={b$13}></Foo$11>;
126 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
127 }
128
129 ```
compiler/forget/src/__tests__/fixtures/hir/interdependent-across-if.expect.md
+2 -5
@@ -85,10 +85,7 @@ bb2:
85 Goto bb1
86 bb1:
87 predecessor blocks: bb0 bb2
88 - Foo$11: phi(bb0: Foo$6, bb2: Foo$6)
89 - a$12: phi(bb0: a$9, bb2: a$9)
90 - b$13: phi(bb0: b$10, bb2: b$10)
91 - Const mutate $14 = JSX <read Foo$11 a={freeze a$12} b={freeze b$13} ></read Foo$11>
88 + Const mutate $14 = JSX <read Foo$6 a={freeze a$9} b={freeze b$10} ></read Foo$6>
89 Return read $14
90 ```
91
@@ -103,7 +100,7 @@ function Component$0(props$8) {
100 ("<<TODO: handle complex control flow in codegen>>");
101 }
102
106 - return <Foo$11 a={a$12} b={b$13}></Foo$11>;
103 + return <Foo$6 a={a$9} b={b$10}></Foo$6>;
104 }
105
106 ```
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+1 -2
@@ -104,7 +104,6 @@ bb2:
104 b$31: phi(bb1: b$20, bb3: b$23)
105 c$32: phi(bb1: c$22, bb3: c$25)
106 d$33: phi(bb1: d$24, bb3: d$26)
107 - mutate$35: phi(bb1: mutate$27, bb3: mutate$27)
107 If (read a$30) then:bb7 else:bb7
108 bb7:
109 predecessor blocks: bb2
@@ -118,7 +117,7 @@ bb11:
117 bb13:
118 predecessor blocks: bb11
119 Const mutate $34 = null
121 - Call mutate mutate$35(mutate d$33, read $34)
120 + Call mutate mutate$27(mutate d$33, read $34)
121 Return
122 ```
123
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+6 -9
@@ -33,13 +33,10 @@ bb2:
33 Goto bb1
34 bb1:
35 predecessor blocks: bb0 bb2
36 - Component$10: phi(bb0: Component$0, bb2: Component$0)
36 x$11: phi(bb0: x$7, bb2: x$9)
38 - y$13: phi(bb0: y$8, bb2: y$8)
39 - props$14: phi(bb0: props$6, bb2: props$6)
40 - Let mutate _$12 = JSX <read Component$10 x={freeze x$11} ></read Component$10>
41 - Call read y$13.push(read props$14.p2)
42 - Const mutate $15 = JSX <read Component$10 x={read x$11} y={read y$13} ></read Component$10>
37 + Let mutate _$12 = JSX <read Component$0 x={freeze x$11} ></read Component$0>
38 + Call read y$8.push(read props$6.p2)
39 + Const mutate $15 = JSX <read Component$0 x={read x$11} y={read y$8} ></read Component$0>
40 Return read $15
41 ```
42
@@ -55,10 +52,10 @@ function Component$0(props$6) {
52 ("<<TODO: handle complex control flow in codegen>>");
53 }
54
58 - let _$12 = <Component$10 x={x$11}></Component$10>;
55 + let _$12 = <Component$0 x={x$11}></Component$0>;
56
60 - y$13.push(props$14.p2);
61 - return <Component$10 x={x$11} y={y$13}></Component$10>;
57 + y$8.push(props$6.p2);
58 + return <Component$0 x={x$11} y={y$8}></Component$0>;
59 }
60
61 ```
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-multiple-if.expect.md
+2 -3
@@ -32,10 +32,9 @@ bb2:
32 Goto bb1
33 bb1:
34 predecessor blocks: bb0 bb2
35 - y$13: phi(bb0: y$8, bb2: y$8)
35 x$17: phi(bb0: x$7, bb2: x$11)
36 Const mutate $12 = 3
38 - Const mutate $14 = Binary read y$13 === read $12
37 + Const mutate $14 = Binary read y$8 === read $12
38 If (read $14) then:bb4 else:bb3
39 bb4:
40 predecessor blocks: bb1
@@ -59,7 +58,7 @@ function foo$0() {
58 ("<<TODO: handle complex control flow in codegen>>");
59 }
60
62 - if (y$13 === 3) {
61 + if (y$8 === 3) {
62 x$15 = 5;
63 ("<<TODO: handle complex control flow in codegen>>");
64 }
compiler/forget/src/__tests__/fixtures/hir/ssa-for-of.expect.md new
+51
@@ -0,0 +1,51 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(cond) {
6 + let items = [];
7 + for (const item of items) {
8 + let y = 0;
9 + if (cond) {
10 + y = 1;
11 + }
12 + }
13 + return items;
14 +}
15 +
16 +```
17 +
18 +## HIR
19 +
20 +```
21 +bb0:
22 + Let mutate items$5 = Array []
23 + Goto bb1
24 +bb1:
25 + predecessor blocks: bb0 bb3 bb5
26 + items$6: phi(bb0: items$5, bb3: items$6, bb5: items$6)
27 + cond$8: phi(bb0: cond$4, bb3: cond$8, bb5: cond$8)
28 + If (read items$6) then:bb3 else:bb2
29 +bb3:
30 + predecessor blocks: bb1
31 + Let mutate y$7 = 0
32 + If (read cond$8) then:bb5 else:bb1
33 +bb5:
34 + predecessor blocks: bb3
35 + Reassign mutate y$9 = 1
36 + Goto bb1
37 +bb2:
38 + predecessor blocks: bb1
39 + Return freeze items$6
40 +```
41 +
42 +## Code
43 +
44 +```javascript
45 +function foo$0(cond$4) {
46 + let items$5 = [];
47 + ("<<TODO: handle complex control flow in codegen>>");
48 +}
49 +
50 +```
51 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/ssa-for-of.js new
+10
@@ -0,0 +1,10 @@
1 +function foo(cond) {
2 + let items = [];
3 + for (const item of items) {
4 + let y = 0;
5 + if (cond) {
6 + y = 1;
7 + }
8 + }
9 + return items;
10 +}
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+6 -9
@@ -53,13 +53,10 @@ bb2:
53 Goto bb1
54 bb1:
55 predecessor blocks: bb0 bb6 bb2
56 - Component$17: phi(bb0: Component$0, bb6: Component$0, bb2: Component$0)
57 - x$18: phi(bb0: x$10, bb6: x$10, bb2: x$10)
56 y$20: phi(bb0: y$11, bb6: y$15, bb2: y$16)
59 - props$21: phi(bb0: props$9, bb6: props$9, bb2: props$9)
60 - Const mutate child$19 = JSX <read Component$17 data={freeze x$18} ></read Component$17>
61 - Call read y$20.push(read props$21.p4)
62 - Const mutate $22 = JSX <read Component$17 data={freeze y$20} >{read child$19}</read Component$17>
57 + Const mutate child$19 = JSX <read Component$0 data={freeze x$10} ></read Component$0>
58 + Call read y$20.push(read props$9.p4)
59 + Const mutate $22 = JSX <read Component$0 data={freeze y$20} >{read child$19}</read Component$0>
60 Return read $22
61 ```
62
@@ -88,9 +85,9 @@ function Component$0(props$9) {
85 }
86 }
87
91 - const child$19 = <Component$17 data={x$18}></Component$17>;
92 - y$20.push(props$21.p4);
93 - return <Component$17 data={y$20}>{child$19}</Component$17>;
88 + const child$19 = <Component$0 data={x$10}></Component$0>;
89 + y$20.push(props$9.p4);
90 + return <Component$0 data={y$20}>{child$19}</Component$0>;
91 }
92
93 ```
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+8 -14
@@ -44,20 +44,14 @@ bb4:
44 Goto bb2
45 bb2:
46 predecessor blocks: bb4 bb0
47 - x$14: phi(bb4: x$9, bb0: x$9)
48 - Component$17: phi(bb4: Component$0, bb0: Component$0)
49 - props$22: phi(bb4: props$8, bb0: props$8)
50 - Reassign mutate y$15 = read x$14
47 + Reassign mutate y$15 = read x$9
48 Goto bb1
49 bb1:
50 predecessor blocks: bb2 bb0
54 - Component$16: phi(bb2: Component$17, bb0: Component$0)
55 - x$18: phi(bb2: x$14, bb0: x$9)
51 y$20: phi(bb2: y$15, bb0: y$10)
57 - props$21: phi(bb2: props$22, bb0: props$8)
58 - Const mutate child$19 = JSX <read Component$16 data={freeze x$18} ></read Component$16>
59 - Call read y$20.push(read props$21.p4)
60 - Const mutate $23 = JSX <read Component$16 data={read y$20} >{read child$19}</read Component$16>
52 + Const mutate child$19 = JSX <read Component$0 data={freeze x$9} ></read Component$0>
53 + Call read y$20.push(read props$8.p4)
54 + Const mutate $23 = JSX <read Component$0 data={read y$20} >{read child$19}</read Component$0>
55 Return read $23
56 ```
57
@@ -76,14 +70,14 @@ function Component$0(props$8) {
70 }
71
72 case false: {
79 - y$15 = x$14;
73 + y$15 = x$9;
74 ("<<TODO: handle complex control flow in codegen>>");
75 }
76 }
77
84 - const child$19 = <Component$16 data={x$18}></Component$16>;
85 - y$20.push(props$21.p4);
86 - return <Component$16 data={y$20}>{child$19}</Component$16>;
78 + const child$19 = <Component$0 data={x$9}></Component$0>;
79 + y$20.push(props$8.p4);
80 + return <Component$0 data={y$20}>{child$19}</Component$0>;
81 }
82
83 ```