Skip to content

Commit 8fdc2b7

Browse files
committed
Update on "[compiler] Optimize emission in normal (non-value) blocks"
In #29863 I tried to find a clean way to share code for emitting instructions between value blocks and regular blocks. The catch is that value blocks have special meaning for their final instruction — that's the value of the block — so reordering can't change the last instruction. However, in finding a clean way to share code for these two categories of code, i also inadvertently reduced the effectiveness of the optimization. This PR updates to use different strategies for these two kinds of blocks: value blocks use the code from #29863 where we first emit all non-reorderable instructions in their original order, _then_ try to emit reorderable values. The reason this is suboptimal, though, is that we want to move instructions closer to their dependencies so that they can invalidate (merge) together. Emitting the reorderable values last prevents this. So for normal blocks, we now emit terminal operands first. This will invariably cause _some_ of the non-reorderable instructions to be emitted, but it will intersperse reoderable instructions in between, right after their dependencies. This maximizes our ability to merge scopes. I think the complexity cost of two strategies is worth the benefit, though i still need to double-check all the output changes. [ghstack-poisoned]
2 parents 13a5a77 + b6bbb0e commit 8fdc2b7

File tree

4 files changed

+38
-47
lines changed

4 files changed

+38
-47
lines changed

compiler/packages/babel-plugin-react-compiler/src/Optimization/InstructionReordering.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ function getDepth(env: Environment, nodes: Nodes, id: IdentifierId): number {
379379
return node.depth;
380380
}
381381
node.depth = 0; // in case of cycles
382-
let depth = node.reorderability === Reorderability.Reorderable ? 0 : 1;
382+
let depth = node.reorderability === Reorderability.Reorderable ? 1 : 10;
383383
for (const dep of node.dependencies) {
384384
depth += getDepth(env, nodes, dep);
385385
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-memo-value-not-promoted-to-outer-scope-static.expect.md

+6-13
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,24 @@ function Component(props) {
2121
```javascript
2222
import { c as _c } from "react/compiler-runtime";
2323
function Component(props) {
24-
const $ = _c(2);
24+
const $ = _c(1);
2525
let t0;
2626
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2727
const count = new MaybeMutable();
2828

29-
t0 = <span>{maybeMutate(count)}</span>;
30-
$[0] = t0;
31-
} else {
32-
t0 = $[0];
33-
}
34-
let t1;
35-
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
36-
t1 = (
29+
t0 = (
3730
<View>
3831
<View>
3932
<span>Text</span>
40-
{t0}
33+
<span>{maybeMutate(count)}</span>
4134
</View>
4235
</View>
4336
);
44-
$[1] = t1;
37+
$[0] = t0;
4538
} else {
46-
t1 = $[1];
39+
t0 = $[0];
4740
}
48-
return t1;
41+
return t0;
4942
}
5043

5144
```

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-preserve-whitespace.expect.md

+11-21
Original file line numberDiff line numberDiff line change
@@ -36,39 +36,29 @@ import { c as _c } from "react/compiler-runtime";
3636
import { StaticText1 } from "shared-runtime";
3737

3838
function Component() {
39-
const $ = _c(3);
39+
const $ = _c(1);
4040
let t0;
4141
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
42-
t0 = <StaticText1 />;
43-
$[0] = t0;
44-
} else {
45-
t0 = $[0];
46-
}
47-
let t1;
48-
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
49-
t1 = <StaticText1 />;
50-
$[1] = t1;
51-
} else {
52-
t1 = $[1];
53-
}
54-
let t2;
55-
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
56-
t2 = (
42+
t0 = (
5743
<div>
58-
Before text{t0}Middle text
44+
Before text
45+
<StaticText1 />
46+
Middle text
5947
<StaticText1>
60-
Inner before text{t1}Inner middle text
48+
Inner before text
49+
<StaticText1 />
50+
Inner middle text
6151
<StaticText1 />
6252
Inner after text
6353
</StaticText1>
6454
After text
6555
</div>
6656
);
67-
$[2] = t2;
57+
$[0] = t0;
6858
} else {
69-
t2 = $[2];
59+
t0 = $[0];
7060
}
71-
return t2;
61+
return t0;
7262
}
7363

7464
export const FIXTURE_ENTRYPOINT = {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-instruction-from-merge-consecutive-scopes.expect.md

+20-12
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,39 @@ import { c as _c } from "react/compiler-runtime";
2929
import { Stringify } from "shared-runtime";
3030

3131
function Component(t0) {
32-
const $ = _c(3);
32+
const $ = _c(5);
3333
const { id } = t0;
3434

3535
const t1 = id ? true : false;
3636
let t2;
37-
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
38-
t2 = <Stringify title={undefined} />;
39-
$[0] = t2;
37+
if ($[0] !== t1) {
38+
t2 = <Stringify title={t1} />;
39+
$[0] = t1;
40+
$[1] = t2;
4041
} else {
41-
t2 = $[0];
42+
t2 = $[1];
4243
}
4344
let t3;
44-
if ($[1] !== t1) {
45-
t3 = (
45+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
46+
t3 = <Stringify title={undefined} />;
47+
$[2] = t3;
48+
} else {
49+
t3 = $[2];
50+
}
51+
let t4;
52+
if ($[3] !== t2) {
53+
t4 = (
4654
<>
55+
{t3}
4756
{t2}
48-
<Stringify title={t1} />
4957
</>
5058
);
51-
$[1] = t1;
52-
$[2] = t3;
59+
$[3] = t2;
60+
$[4] = t4;
5361
} else {
54-
t3 = $[2];
62+
t4 = $[4];
5563
}
56-
return t3;
64+
return t4;
5765
}
5866

5967
export const FIXTURE_ENTRYPOINT = {

0 commit comments

Comments
 (0)