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

"ValueBlock" for while test node

The instructions of a while test node cannot just be pushed to the previous block. This creates a new block for the test node and then during code gen converts the statements pushed to the "value block" into expressions.

Jan Kassens committed Dec 6, 2022 at 11:28 UTC db740366f821c10350d3eb94b384ef8911dedefd
10 files changed +79 -24
compiler/forget/src/HIR/Codegen.ts
+23
@@ -100,6 +100,10 @@ class CodegenVisitor
100 this.depth++;
101 return [];
102 }
103 + enterValueBlock(): t.Statement[] {
104 + this.depth++;
105 + return [];
106 + }
107 visitValue(value: InstructionValue): t.Expression {
108 return codegenInstructionValue(this.temp, value);
109 }
@@ -237,6 +241,25 @@ class CodegenVisitor
241 this.depth--;
242 return t.blockStatement(block);
243 }
244 + leaveValueBlock(block: t.Statement[], place: t.Expression): t.Expression {
245 + this.depth--;
246 + if (block.length === 0) {
247 + return place;
248 + }
249 + const expressions = block.map((stmt) => {
250 + switch (stmt.type) {
251 + case "ExpressionStatement":
252 + return stmt.expression;
253 + default:
254 + todoInvariant(
255 + false,
256 + `Handle conversion of ${stmt.type} to expression`
257 + );
258 + }
259 + });
260 + expressions.push(place);
261 + return t.sequenceExpression(expressions);
262 + }
263 }
264
265 function codegenLabel(id: BlockId): string {
compiler/forget/src/HIR/HIRTreeVisitor.ts
+16 -7
@@ -239,15 +239,20 @@ class Driver<TBlock, TValue, TItem, TCase> {
239 testTerminal.kind === "if",
240 "Expected while loop test block to end in an if"
241 );
242 - // const bodyLength = blockValue.length;
242 + const testValueBlock = this.visitor.enterValueBlock();
243 for (const instr of testBlock.instructions) {
244 - this.visitInstr(instr, blockValue);
244 + const value = this.visitor.visitValue(instr.value, instr.id);
245 + const item = this.visitor.visitInstruction(instr, value);
246 + this.visitor.appendBlock(testValueBlock, item);
247 }
246 - // invariant(
247 - // body.length === bodyLength,
248 - // "Expected test to produce only temporaries"
249 - // );
250 - const testValue = this.visitPlace(testTerminal.test, terminal.id);
248 + const testValueLast = this.visitor.visitValue(
249 + testTerminal.test,
250 + testTerminal.id
251 + );
252 + const testValue = this.visitor.leaveValueBlock(
253 + testValueBlock,
254 + testValueLast
255 + );
256 const fallthroughId =
257 terminal.fallthrough !== null &&
258 !this.cx.isScheduled(terminal.fallthrough)
@@ -644,6 +649,10 @@ export interface Visitor<TBlock, TValue, TItem, TCase> {
649 */
650 enterBlock(): TBlock;
651
652 + enterValueBlock(): TBlock;
653 +
654 + leaveValueBlock(block: TBlock, value: TValue): TValue;
655 +
656 /**
657 * Convert an InstructionValue into the visitor's own representation
658 * of a value.
compiler/forget/src/HIR/InferReactiveScopeDependencies.ts
+4
@@ -189,8 +189,12 @@ class ScopeDependenciesVisitor
189 }
190
191 enterBlock(): void {}
192 + enterValueBlock(): void {}
193 visitImplicitTerminal(): void | null {}
194 visitCase(test: InstructionValue, block: void): void {}
195 appendBlock(block: void, item: void, label?: BlockId | undefined): void {}
196 leaveBlock(block: void): void {}
197 + leaveValueBlock(block: void, value: InstructionValue): InstructionValue {
198 + return value;
199 + }
200 }
compiler/forget/src/HIR/InferReactiveScopes.ts
+14
@@ -254,6 +254,12 @@ class MergeOverlappingReactiveScopesVisitor
254 enterBlock(): void {
255 this.scopes.push(new BlockScope());
256 }
257 + enterValueBlock(): void {
258 + this.enterBlock();
259 + }
260 + leaveValueBlock(block: void, value: void): void {
261 + this.leaveBlock();
262 + }
263 visitValue(value: InstructionValue, id: InstructionId): void {
264 this.visitId(id);
265 for (const operand of eachInstructionValueOperand(value)) {
@@ -355,6 +361,14 @@ class AlignReactiveScopesToBlockScopeRangeVisitor
361 }
362 }
363
364 + enterValueBlock(): void {
365 + this.enterBlock();
366 + }
367 +
368 + leaveValueBlock(block: void, value: void): void {
369 + this.leaveBlock();
370 + }
371 +
372 visitInstruction(instruction: Instruction, value: void): void {
373 const scope = getInstructionScope(instruction);
374 if (scope !== null) {
compiler/forget/src/HIR/PrintHIRTree.ts
+6
@@ -32,6 +32,12 @@ class PrintVisitor implements Visitor<Array<string>, string, string, string> {
32 this.depth++;
33 return [];
34 }
35 + enterValueBlock(): string[] {
36 + return this.enterBlock();
37 + }
38 + leaveValueBlock(block: string[], value: string): string {
39 + return this.leaveBlock(block);
40 + }
41 visitValue(value: InstructionValue): string {
42 return printMixedHIR(value);
43 }
compiler/forget/src/__tests__/fixtures/hir/_bug_while-with-assignment.expect.md
+4 -5
@@ -31,7 +31,7 @@ bb1:
31 sum$21_@3[0:14]: phi(bb0: sum$16_@3, bb3: sum$22_@3)
32 [8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
33 [9] Const mutate $19_@6 = null
34 - [10] Const mutate $20_@7[10:14] = Binary read value$18_@3 != read $19_@6
34 + [10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
35 [11] If (read $20_@7) then:bb3 else:bb2
36 bb3:
37 predecessor blocks: bb1
@@ -40,7 +40,7 @@ bb3:
40 bb2:
41 predecessor blocks: bb1
42 [14] Return read sum$21_@3
43 -scope7 [10:14]:
43 +scope7 [10:12]:
44 - read $19_@6
45 ```
46
@@ -64,7 +64,7 @@ flowchart TB
64 bb1_instrs["
65 [8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
66 [9] Const mutate $19_@6 = null
67 - [10] Const mutate $20_@7[10:14] = Binary read value$18_@3 != read $19_@6
67 + [10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
68 "]
69 bb1_instrs --> bb1_terminal(["If (read $20_@7)"])
70 end
@@ -95,8 +95,7 @@ function f$0(reader$1) {
95 const queue$2 = [1, 2, 3];
96 let value$6 = 0;
97 let sum$7 = 0;
98 - value$6 = queue$2.pop();
99 - bb2: while (value$6 != null) {
98 + bb2: while (((value$6 = queue$2.pop()), value$6 != null)) {
99 sum$7 = sum$7 + value$6;
100 }
101
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+2 -2
@@ -108,7 +108,7 @@ bb1:
108 b$20_@0[0:23]: phi(bb0: b$14_@0, bb4: b$23_@0)
109 c$22_@0[0:23]: phi(bb0: c$15_@0, bb4: c$25_@0)
110 d$24_@0[0:23]: phi(bb0: d$16_@0, bb4: d$26_@0)
111 - [6] Const mutate $17_@1[6:17] = true
111 + [6] Const mutate $17_@1[6:8] = true
112 [7] If (read $17_@1) then:bb3 else:bb2
113 bb3:
114 predecessor blocks: bb1
@@ -163,7 +163,7 @@ flowchart TB
163 end
164 subgraph bb1
165 bb1_instrs["
166 - [6] Const mutate $17_@1[6:17] = true
166 + [6] Const mutate $17_@1[6:8] = true
167 "]
168 bb1_instrs --> bb1_terminal(["If (read $17_@1)"])
169 end
compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md
+2 -2
@@ -99,7 +99,7 @@ bb0:
99 [5] While test=bb1 loop=bb3 fallthrough=bb2
100 bb1:
101 predecessor blocks: bb0 bb4
102 - [6] Const mutate $16_@2[6:12] = true
102 + [6] Const mutate $16_@2[6:8] = true
103 [7] If (read $16_@2) then:bb3 else:bb2
104 bb3:
105 predecessor blocks: bb1
@@ -145,7 +145,7 @@ flowchart TB
145 end
146 subgraph bb1
147 bb1_instrs["
148 - [6] Const mutate $16_@2[6:12] = true
148 + [6] Const mutate $16_@2[6:8] = true
149 "]
150 bb1_instrs --> bb1_terminal(["If (read $16_@2)"])
151 end
compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md
+5 -5
@@ -17,12 +17,12 @@ function foo() {
17
18 ```
19 bb0:
20 - [1] Let mutate x$5_@0[1:3] = 1
20 + [1] Let mutate x$5_@0 = 1
21 [2] While test=bb1 loop=bb3 fallthrough=bb2
22 bb1:
23 predecessor blocks: bb0 bb3
24 [3] Const mutate $6_@1 = 10
25 - [4] Const mutate $8_@2[4:9] = Binary read x$5_@0 < read $6_@1
25 + [4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
26 [5] If (read $8_@2) then:bb3 else:bb2
27 bb3:
28 predecessor blocks: bb1
@@ -32,7 +32,7 @@ bb3:
32 bb2:
33 predecessor blocks: bb1
34 [9] Return read x$5_@0
35 -scope2 [4:9]:
35 +scope2 [4:6]:
36 - read x$5_@0
37 - read $6_@1
38 scope3 [6:7]:
@@ -46,14 +46,14 @@ flowchart TB
46 %% Basic Blocks
47 subgraph bb0
48 bb0_instrs["
49 - [1] Let mutate x$5_@0[1:3] = 1
49 + [1] Let mutate x$5_@0 = 1
50 "]
51 bb0_instrs --> bb0_terminal(["While"])
52 end
53 subgraph bb1
54 bb1_instrs["
55 [3] Const mutate $6_@1 = 10
56 - [4] Const mutate $8_@2[4:9] = Binary read x$5_@0 < read $6_@1
56 + [4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
57 "]
58 bb1_instrs --> bb1_terminal(["If (read $8_@2)"])
59 end
compiler/forget/src/__tests__/fixtures/hir/ssa-while.expect.md
+3 -3
@@ -23,7 +23,7 @@ bb1:
23 predecessor blocks: bb0 bb3
24 x$7_@0[0:9]: phi(bb0: x$5_@0, bb3: x$10_@0)
25 [3] Const mutate $6_@1 = 10
26 - [4] Const mutate $8_@2[4:9] = Binary read x$7_@0 < read $6_@1
26 + [4] Const mutate $8_@2[4:6] = Binary read x$7_@0 < read $6_@1
27 [5] If (read $8_@2) then:bb3 else:bb2
28 bb3:
29 predecessor blocks: bb1
@@ -33,7 +33,7 @@ bb3:
33 bb2:
34 predecessor blocks: bb1
35 [9] Return read x$7_@0
36 -scope2 [4:9]:
36 +scope2 [4:6]:
37 - read $6_@1
38 ```
39
@@ -51,7 +51,7 @@ flowchart TB
51 subgraph bb1
52 bb1_instrs["
53 [3] Const mutate $6_@1 = 10
54 - [4] Const mutate $8_@2[4:9] = Binary read x$7_@0 < read $6_@1
54 + [4] Const mutate $8_@2[4:6] = Binary read x$7_@0 < read $6_@1
55 "]
56 bb1_instrs --> bb1_terminal(["If (read $8_@2)"])
57 end