mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Fix EliminateRedundantPhi for cascading eliminated phis
This was the actual bug. When EliminateRedundantPhis eliminates a phi, it has to rewrite downstream usages of the phi id to the single operand id. We were correctly doing that in all but one place. When we iterate _downstream phis_, we were looking up the operands against the rewrite table, but not updating the phi operands themselves to the rewritten value. This fixes the bug, and incidentally fixes a test that has been broken for a while and nagging at me.
This commit is contained in:
@@ -57,12 +57,19 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
|
||||
|
||||
// Find any redundant phis
|
||||
phis: for (const phi of block.phis) {
|
||||
// Remap phis in case operands are from eliminated phis
|
||||
phi.operands = new Map(
|
||||
Array.from(phi.operands).map(([block, id]) => [
|
||||
block,
|
||||
rewrites.get(id) ?? id,
|
||||
])
|
||||
);
|
||||
// Find if the phi can be eliminated
|
||||
let same: Identifier | null = null;
|
||||
for (const [_, operand] of phi.operands) {
|
||||
const ident = rewrites.get(operand) ?? operand;
|
||||
if (
|
||||
(same !== null && ident.id === same.id) ||
|
||||
ident.id === phi.id.id
|
||||
(same !== null && operand.id === same.id) ||
|
||||
operand.id === phi.id.id
|
||||
) {
|
||||
// This operand is the same as the phi or is the same as the
|
||||
// previous non-phi operands
|
||||
@@ -73,7 +80,7 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
|
||||
continue phis;
|
||||
} else {
|
||||
// First non-phi operand
|
||||
same = ident;
|
||||
same = operand;
|
||||
}
|
||||
}
|
||||
invariant(same !== null, "Expected phis to be non-empty");
|
||||
|
||||
@@ -21,20 +21,23 @@ function foo(props) {
|
||||
|
||||
```javascript
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props;
|
||||
let y;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
if (c_0) {
|
||||
y = 0;
|
||||
$[0] = y;
|
||||
for (
|
||||
let x = 0;
|
||||
x > props.min && x < props.max;
|
||||
x = x + (props.cond ? props.increment : 2), x
|
||||
) {
|
||||
x = x * 2;
|
||||
y = y + x;
|
||||
}
|
||||
$[0] = props;
|
||||
$[1] = y;
|
||||
} else {
|
||||
y = $[0];
|
||||
}
|
||||
for (
|
||||
let x = 0;
|
||||
x > props.min && x < props.max;
|
||||
x = x + (props.cond ? props.increment : 2), x
|
||||
) {
|
||||
x = x * 2;
|
||||
y = $[1];
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,6 +25,7 @@ function Component(props) {
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
let x = 0;
|
||||
const c_0 = $[0] !== props;
|
||||
let values;
|
||||
if (c_0) {
|
||||
@@ -40,12 +41,11 @@ function Component(props) {
|
||||
}
|
||||
const y = t0;
|
||||
values.push(y);
|
||||
let x$0 = x;
|
||||
if (props.c) {
|
||||
x = 1;
|
||||
}
|
||||
|
||||
values.push(x$0);
|
||||
values.push(x);
|
||||
if (props.d) {
|
||||
x = 2;
|
||||
}
|
||||
Reference in New Issue
Block a user