[ssa] Patch: propagate every rewrite to function expressions

--- 

#1899 only propagated eliminated phi nodes to function expressions on the first 
iteration through blocks. However, this was buggy as later iterations could 
introduce rewrites that need to be propagated. 

[playground 
repro](https://0xeac7-forget.vercel.app/#eyJzb3VyY2UiOiJmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHggPSA0O1xuXG4gIGNvbnN0IGdldDQgPSAoKSA9PiB7XG4gICAgd2hpbGUgKGJhcigpKSB7XG4gICAgICBpZiAoYmF6KSB7XG4gICAgICAgIGJhcigpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gKCkgPT4geDtcbiAgfTtcblxuICByZXR1cm4gZ2V0NDtcbn0ifQ==). 

I manually synced #1907 to check that this fix works for the VR Store codebase.
This commit is contained in:
Mofei Zhang
2023-08-07 17:41:35 -04:00
parent ff2f2e0685
commit e33c9c43cc
4 changed files with 43 additions and 29 deletions
@@ -46,7 +46,6 @@ export function eliminateRedundantPhi(
// compare to see if any new rewrites were added in that iteration.
let size = rewrites.size;
do {
const isFirstIteration = !hasBackEdge;
size = rewrites.size;
for (const [blockId, block] of ir.blocks) {
// On the first iteration of the loop check for any back-edges.
@@ -116,10 +115,10 @@ export function eliminateRedundantPhi(
rewritePlace(place, rewrites);
}
// visit function expressions on first iteration of each block
if (isFirstIteration) {
eliminateRedundantPhi(instr.value.loweredFunc, rewrites);
}
// recursive call to:
// - eliminate phi nodes in child node
// - propagate rewrites, which may have changed between iterations
eliminateRedundantPhi(instr.value.loweredFunc, rewrites);
}
}
@@ -96,6 +96,11 @@ test("lambda-constant-propagation-of-phi-node", () => {
if (constantValue) {
noopCallback();
}
for (let i = 0; i < 5; i++) {
if (!constantValue) {
noopCallback();
}
}
const getDiv = () => <div>{x}</div>;
return getDiv();
}
@@ -2,13 +2,19 @@
## Input
```javascript
function ConstantPropagationBug() {
const x = CONSTANT1;
const createPhiNode = CONSTANT2 || 5;
function Component() {
const x = 4;
const getFoo = () => <Foo x={x} y={createPhiNode} />;
const get4 = () => {
while (bar()) {
if (baz) {
bar();
}
}
return () => x;
};
return getFoo();
return get4;
}
```
@@ -17,26 +23,24 @@ function ConstantPropagationBug() {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function ConstantPropagationBug() {
const $ = useMemoCache(2);
const createPhiNode = CONSTANT2 || 5;
function Component() {
const $ = useMemoCache(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = () => <Foo x={CONSTANT1} y={createPhiNode} />;
t0 = () => {
while (bar()) {
if (baz) {
bar();
}
}
return () => 4;
};
$[0] = t0;
} else {
t0 = $[0];
}
const getFoo = t0;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = getFoo();
$[1] = t1;
} else {
t1 = $[1];
}
return t1;
const get4 = t0;
return get4;
}
```
@@ -1,8 +1,14 @@
function ConstantPropagationBug() {
const x = CONSTANT1;
const createPhiNode = CONSTANT2 || 5;
function Component() {
const x = 4;
const getFoo = () => <Foo x={x} y={createPhiNode} />;
const get4 = () => {
while (bar()) {
if (baz) {
bar();
}
}
return () => x;
};
return getFoo();
return get4;
}