@samitouri / QOS-React / commits / 9a25b5a12a

Fix previous examples, alias across phis

Within the InferMutableRanges fixpoint iteration, we need to alias phi operands with the phi id if the phi id is later mutated.

Joe Savona committed Feb 21, 2023 at 15:29 UTC 9a25b5a12aa3b8c4874f31c53ce614f7eb039dfe
5 files changed +30 -38
compiler/forget/src/Inference/InferMutableRanges.ts
+2 -2
@@ -24,7 +24,7 @@ export function inferMutableRanges(ir: HIRFunction) {
24 do {
25 size = aliases.size;
26 // Infer mutable ranges for aliases that are not fields
27 - inferMutableRangesForAlias(aliases);
27 + inferMutableRangesForAlias(ir, aliases);
28
29 // Update aliasing information of fields
30 inferAliasForStores(ir, aliases);
@@ -34,5 +34,5 @@ export function inferMutableRanges(ir: HIRFunction) {
34 inferMutableLifetimes(ir, true);
35
36 // Re-infer mutable ranges for aliases
37 - inferMutableRangesForAlias(aliases);
37 + inferMutableRangesForAlias(ir, aliases);
38 }
compiler/forget/src/Inference/InferMutableRangesForAlias.ts
+18 -2
@@ -1,7 +1,23 @@
1 +import { HIRFunction, Identifier, InstructionId } from "../HIR/HIR";
2 import DisjointSet from "../Utils/DisjointSet";
2 -import { Identifier, InstructionId } from "../HIR/HIR";
3
4 -export function inferMutableRangesForAlias(aliases: DisjointSet<Identifier>) {
4 +export function inferMutableRangesForAlias(
5 + fn: HIRFunction,
6 + aliases: DisjointSet<Identifier>
7 +) {
8 + for (const [_, block] of fn.body.blocks) {
9 + for (const phi of block.phis) {
10 + const isPhiMutatedAfterCreation: boolean =
11 + phi.id.mutableRange.end >
12 + (block.instructions.at(0)?.id ?? block.terminal.id);
13 + if (isPhiMutatedAfterCreation) {
14 + for (const [, operand] of phi.operands) {
15 + aliases.union([phi.id, operand]);
16 + }
17 + }
18 + }
19 + }
20 +
21 const aliasSets = aliases.buildSets();
22 for (const aliasSet of aliasSets) {
23 // Update mutableRange.end only if the identifiers have actually been
compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-if-else-with-alias.expect.md
+2 -8
@@ -22,19 +22,13 @@ function foo(a, b, c, d) {
22
23 ```javascript
24 function foo(a, b, c, d) {
25 - const $ = React.unstable_useMemoCache(3);
25 + const $ = React.unstable_useMemoCache(2);
26 const c_0 = $[0] !== a;
27 let x;
28 if (c_0) {
29 x = someObj();
30 if (a) {
31 - let y;
32 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
33 - y = someObj();
34 - $[2] = y;
35 - } else {
36 - y = $[2];
37 - }
31 + const y = someObj();
32 const z = y;
33 x = z;
34 } else {
compiler/forget/src/__tests__/fixtures/hir/obj-mutated-after-nested-if-else-with-alias.expect.md
+3 -14
@@ -28,7 +28,7 @@ function foo(a, b, c, d) {
28
29 ```javascript
30 function foo(a, b, c, d) {
31 - const $ = React.unstable_useMemoCache(5);
31 + const $ = React.unstable_useMemoCache(3);
32 const c_0 = $[0] !== a;
33 const c_1 = $[1] !== b;
34 let x;
@@ -37,21 +37,10 @@ function foo(a, b, c, d) {
37 if (a) {
38 let z = undefined;
39 if (b) {
40 - let w;
41 - if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
42 - w = someObj();
43 - $[3] = w;
44 - } else {
45 - w = $[3];
46 - }
40 + const w = someObj();
41 z = w;
42 } else {
49 - if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
50 - z = someObj();
51 - $[4] = z;
52 - } else {
53 - z = $[4];
54 - }
43 + z = someObj();
44 }
45
46 x = z;
compiler/forget/src/__tests__/fixtures/hir/sequence-expression.expect.md
+5 -12
@@ -18,25 +18,18 @@ function foo() {}
18
19 ```javascript
20 function sequence(props) {
21 - const $ = React.unstable_useMemoCache(2);
21 + const $ = React.unstable_useMemoCache(1);
22 Math.max(1, 2);
23 - let t0;
24 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 - t0 = foo();
26 - $[0] = t0;
27 - } else {
28 - t0 = $[0];
29 - }
23 let x;
31 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
32 - x = t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + x = foo();
26 while ((foo(), true)) {
27 foo();
28 x = 2;
29 }
37 - $[1] = x;
30 + $[0] = x;
31 } else {
39 - x = $[1];
32 + x = $[0];
33 }
34 return x;
35 }