Skip to content

Commit 4f80cbb

Browse files
committed
Update on "[compiler] Infer phi types, extend mutable ranges to account for Store effects"
Redo of an earlier (pre-OSS) PR to infer types of phi nodes. There are a few pieces to this: 1. Update InferTypes to infer the type of `phi.id.type`, not the unused `phi.type`. 2. Update the algorithm to verify that all the phi types are actually equal, not just have the same kind. 3. Handle circular types by removing the cycle. However, that reveals another issue: InferMutableRanges currently infers the results of `Store` effects _after_ its fixpoint loop. That was fine when a Store could never occur on a phi (since they wouldn't have a type to get a function signature from). Now though, we can have Store effects occur on phis, and we need to ensure that this correctly updates the mutable range of the phi operands - recursively. See new test that fails without the fixpoint loop. [ghstack-poisoned]
1 parent 8ac0bba commit 4f80cbb

10 files changed

+141
-46
lines changed

compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableRanges.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,10 @@ export function inferMutableRanges(ir: HIRFunction): void {
5050
// Re-infer mutable ranges for all values
5151
inferMutableLifetimes(ir, true);
5252

53-
// Re-infer mutable ranges for aliases
53+
// Re-infer mutable ranges for aliases, but *not* for stores
5454
prevAliases = aliases.canonicalize();
5555
while (true) {
5656
inferMutableRangesForAlias(ir, aliases);
57-
inferAliasForStores(ir, aliases);
5857
inferAliasForPhis(ir, aliases);
5958
const nextAliases = aliases.canonicalize();
6059
if (areEqualMaps(prevAliases, nextAliases)) {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-push-effect.expect.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { c as _c } from "react/compiler-runtime"; // arrayInstance.push should h
2323
// - read on all args (rest parameter)
2424
// - mutate on receiver
2525
function Component(props) {
26-
const $ = _c(7);
26+
const $ = _c(8);
2727
let t0;
2828
if ($[0] !== props.x) {
2929
t0 = foo(props.x);
@@ -45,7 +45,14 @@ function Component(props) {
4545
let arr;
4646
if ($[4] !== x || $[5] !== y) {
4747
arr = [];
48-
arr.push({});
48+
let t2;
49+
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
50+
t2 = {};
51+
$[7] = t2;
52+
} else {
53+
t2 = $[7];
54+
}
55+
arr.push(t2);
4956
arr.push(x, y);
5057
$[4] = x;
5158
$[5] = y;

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps.expect.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { c as _c } from "react/compiler-runtime";
4040
import { identity } from "shared-runtime";
4141

4242
function useFoo(t0) {
43-
const $ = _c(7);
43+
const $ = _c(9);
4444
const { input, cond, hasAB } = t0;
4545
let x;
4646
let t1;
@@ -53,9 +53,6 @@ function useFoo(t0) {
5353
t1 = null;
5454
break bb0;
5555
}
56-
57-
x.push(identity(input.a.b));
58-
} else {
5956
let t2;
6057
if ($[5] !== input.a.b) {
6158
t2 = identity(input.a.b);
@@ -65,6 +62,16 @@ function useFoo(t0) {
6562
t2 = $[6];
6663
}
6764
x.push(t2);
65+
} else {
66+
let t2;
67+
if ($[7] !== input.a.b) {
68+
t2 = identity(input.a.b);
69+
$[7] = input.a.b;
70+
$[8] = t2;
71+
} else {
72+
t2 = $[8];
73+
}
74+
x.push(t2);
6875
}
6976
}
7077
$[0] = cond;

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps1.expect.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { c as _c } from "react/compiler-runtime";
4141
import { identity } from "shared-runtime";
4242

4343
function useFoo(t0) {
44-
const $ = _c(7);
44+
const $ = _c(11);
4545
const { input, cond, hasAB } = t0;
4646
let x;
4747
let t1;
@@ -54,18 +54,33 @@ function useFoo(t0) {
5454
t1 = null;
5555
break bb0;
5656
} else {
57-
x.push(identity(input.a.b));
57+
let t2;
58+
if ($[5] !== input.a.b) {
59+
t2 = identity(input.a.b);
60+
$[5] = input.a.b;
61+
$[6] = t2;
62+
} else {
63+
t2 = $[6];
64+
}
65+
x.push(t2);
5866
}
59-
60-
x.push(identity(input.a.b));
67+
let t2;
68+
if ($[7] !== input.a.b) {
69+
t2 = identity(input.a.b);
70+
$[7] = input.a.b;
71+
$[8] = t2;
72+
} else {
73+
t2 = $[8];
74+
}
75+
x.push(t2);
6176
} else {
6277
let t2;
63-
if ($[5] !== input.a.b) {
78+
if ($[9] !== input.a.b) {
6479
t2 = identity(input.a.b);
65-
$[5] = input.a.b;
66-
$[6] = t2;
80+
$[9] = input.a.b;
81+
$[10] = t2;
6782
} else {
68-
t2 = $[6];
83+
t2 = $[10];
6984
}
7085
x.push(t2);
7186
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps.expect.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { c as _c } from "react/compiler-runtime";
3131
import { identity } from "shared-runtime";
3232

3333
function useFoo(t0) {
34-
const $ = _c(7);
34+
const $ = _c(9);
3535
const { input, hasAB, returnNull } = t0;
3636
let x;
3737
let t1;
@@ -40,19 +40,27 @@ function useFoo(t0) {
4040
bb0: {
4141
x = [];
4242
if (!hasAB) {
43-
x.push(identity(input.a));
43+
let t2;
44+
if ($[5] !== input.a) {
45+
t2 = identity(input.a);
46+
$[5] = input.a;
47+
$[6] = t2;
48+
} else {
49+
t2 = $[6];
50+
}
51+
x.push(t2);
4452
if (!returnNull) {
4553
t1 = null;
4654
break bb0;
4755
}
4856
} else {
4957
let t2;
50-
if ($[5] !== input.a.b) {
58+
if ($[7] !== input.a.b) {
5159
t2 = identity(input.a.b);
52-
$[5] = input.a.b;
53-
$[6] = t2;
60+
$[7] = input.a.b;
61+
$[8] = t2;
5462
} else {
55-
t2 = $[6];
63+
t2 = $[8];
5664
}
5765
x.push(t2);
5866
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps1.expect.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { c as _c } from "react/compiler-runtime";
4141
import { identity } from "shared-runtime";
4242

4343
function useFoo(t0) {
44-
const $ = _c(7);
44+
const $ = _c(11);
4545
const { input, cond2, cond1 } = t0;
4646
let x;
4747
let t1;
@@ -51,20 +51,36 @@ function useFoo(t0) {
5151
x = [];
5252
if (cond1) {
5353
if (!cond2) {
54-
x.push(identity(input.a.b));
54+
let t2;
55+
if ($[5] !== input.a.b) {
56+
t2 = identity(input.a.b);
57+
$[5] = input.a.b;
58+
$[6] = t2;
59+
} else {
60+
t2 = $[6];
61+
}
62+
x.push(t2);
5563
t1 = null;
5664
break bb0;
5765
} else {
58-
x.push(identity(input.a.b));
66+
let t2;
67+
if ($[7] !== input.a.b) {
68+
t2 = identity(input.a.b);
69+
$[7] = input.a.b;
70+
$[8] = t2;
71+
} else {
72+
t2 = $[8];
73+
}
74+
x.push(t2);
5975
}
6076
} else {
6177
let t2;
62-
if ($[5] !== input.a.b) {
78+
if ($[9] !== input.a.b) {
6379
t2 = identity(input.a.b);
64-
$[5] = input.a.b;
65-
$[6] = t2;
80+
$[9] = input.a.b;
81+
$[10] = t2;
6682
} else {
67-
t2 = $[6];
83+
t2 = $[10];
6884
}
6985
x.push(t2);
7086
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/reduce-if-exhaustive-poisoned-deps.expect.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { c as _c } from "react/compiler-runtime";
3232
import { identity } from "shared-runtime";
3333

3434
function useFoo(t0) {
35-
const $ = _c(7);
35+
const $ = _c(11);
3636
const { input, inputHasAB, inputHasABC } = t0;
3737
let x;
3838
let t1;
@@ -41,21 +41,36 @@ function useFoo(t0) {
4141
bb0: {
4242
x = [];
4343
if (!inputHasABC) {
44-
x.push(identity(input.a));
44+
let t2;
45+
if ($[5] !== input.a) {
46+
t2 = identity(input.a);
47+
$[5] = input.a;
48+
$[6] = t2;
49+
} else {
50+
t2 = $[6];
51+
}
52+
x.push(t2);
4553
if (!inputHasAB) {
4654
t1 = null;
4755
break bb0;
4856
}
49-
50-
x.push(identity(input.a.b));
57+
let t3;
58+
if ($[7] !== input.a.b) {
59+
t3 = identity(input.a.b);
60+
$[7] = input.a.b;
61+
$[8] = t3;
62+
} else {
63+
t3 = $[8];
64+
}
65+
x.push(t3);
5166
} else {
5267
let t2;
53-
if ($[5] !== input.a.b.c) {
68+
if ($[9] !== input.a.b.c) {
5469
t2 = identity(input.a.b.c);
55-
$[5] = input.a.b.c;
56-
$[6] = t2;
70+
$[9] = input.a.b.c;
71+
$[10] = t2;
5772
} else {
58-
t2 = $[6];
73+
t2 = $[10];
5974
}
6075
x.push(t2);
6176
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-if.expect.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,28 @@ export const FIXTURE_ENTRYPOINT = {
2727
```javascript
2828
import { c as _c } from "react/compiler-runtime";
2929
function foo(a) {
30-
const $ = _c(3);
30+
const $ = _c(4);
3131
let x;
3232
if ($[0] !== a) {
3333
x = {};
3434
if (a) {
35-
const y = {};
36-
x.y = y;
37-
} else {
3835
let t0;
3936
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
4037
t0 = {};
4138
$[2] = t0;
4239
} else {
4340
t0 = $[2];
4441
}
42+
const y = t0;
43+
x.y = y;
44+
} else {
45+
let t0;
46+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
47+
t0 = {};
48+
$[3] = t0;
49+
} else {
50+
t0 = $[3];
51+
}
4552
const z = t0;
4653
x.z = z;
4754
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.expect.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,19 @@ import { c as _c } from "react/compiler-runtime";
2828
const { shallowCopy, throwErrorWithMessage } = require("shared-runtime");
2929

3030
function Component(props) {
31-
const $ = _c(2);
31+
const $ = _c(3);
3232
let x;
3333
if ($[0] !== props.a) {
3434
x = [];
3535
try {
36-
x.push(throwErrorWithMessage("oops"));
36+
let t0;
37+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
38+
t0 = throwErrorWithMessage("oops");
39+
$[2] = t0;
40+
} else {
41+
t0 = $[2];
42+
}
43+
x.push(t0);
3744
} catch {
3845
x.push(shallowCopy({ a: props.a }));
3946
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.expect.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,28 @@ import { c as _c } from "react/compiler-runtime";
2929
const { throwErrorWithMessage, shallowCopy } = require("shared-runtime");
3030

3131
function Component(props) {
32-
const $ = _c(2);
32+
const $ = _c(4);
3333
let x;
3434
if ($[0] !== props.value) {
3535
x = [];
3636
try {
37-
x.push(throwErrorWithMessage("oops"));
37+
let t0;
38+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
39+
t0 = throwErrorWithMessage("oops");
40+
$[2] = t0;
41+
} else {
42+
t0 = $[2];
43+
}
44+
x.push(t0);
3845
} catch {
39-
x.push(shallowCopy({}));
46+
let t0;
47+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
48+
t0 = shallowCopy({});
49+
$[3] = t0;
50+
} else {
51+
t0 = $[3];
52+
}
53+
x.push(t0);
4054
}
4155

4256
x.push(props.value);

0 commit comments

Comments
 (0)