diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts
index 32d4a3ead4..a8137ba25a 100644
--- a/compiler/forget/src/HIR/PrintHIR.ts
+++ b/compiler/forget/src/HIR/PrintHIR.ts
@@ -114,7 +114,7 @@ export function printInstruction(instr: ReactiveInstruction): string {
function printPhi(phi: Phi): string {
const items = [];
items.push(printIdentifier(phi.id));
- // items.push(printMutableRange(phi.id));
+ items.push(printMutableRange(phi.id));
items.push(printType(phi.type));
items.push(": phi(");
const phis = [];
diff --git a/compiler/forget/src/SSA/LeaveSSA.ts b/compiler/forget/src/SSA/LeaveSSA.ts
index 14afaf59cd..532d84e8d9 100644
--- a/compiler/forget/src/SSA/LeaveSSA.ts
+++ b/compiler/forget/src/SSA/LeaveSSA.ts
@@ -174,15 +174,8 @@ export function leaveSSA(fn: HIRFunction) {
}
// all versions of the variable need to be remapped to the canonical id
- // also extend the mutable range of the canonical id based on the min/max
- // of the ranges of its operands
- let start = canonicalId.mutableRange.start as number;
- let end = canonicalId.mutableRange.end as number;
for (const [, operand] of phi.operands) {
- start = Math.min(start, operand.mutableRange.start);
- end = Math.max(end, operand.mutableRange.end);
reassignments.set(operand, canonicalId);
-
if (operand.mutableRange.start < terminal.id) {
invariant(
initOperand === null,
@@ -191,8 +184,6 @@ export function leaveSSA(fn: HIRFunction) {
initOperand = operand;
}
}
- canonicalId.mutableRange.start = makeInstructionId(start);
- canonicalId.mutableRange.end = makeInstructionId(end);
// If there are no instructions in the block then there's just a terminal
// node, which has no mutation, so that should be false.
@@ -203,6 +194,14 @@ export function leaveSSA(fn: HIRFunction) {
phi.id.mutableRange.end >
(phiBlock.instructions.at(0)?.id ?? phiBlock.terminal.id);
+ // If a phi is never mutated after creation, reset its mutable range to be itself
+ if (!isPhiMutatedAfterCreation) {
+ canonicalId.mutableRange.start = phiBlock.terminal.id;
+ canonicalId.mutableRange.end = makeInstructionId(
+ phiBlock.terminal.id + 1
+ );
+ }
+
// If this phi id is the canonical id we need to generate a let binding for it
// (otherwise, it means this phi merges into some other phi which already generated
// a binding
diff --git a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
index 3e20cfff28..5c66dadd3e 100644
--- a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+++ b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
@@ -29,29 +29,19 @@ function Component(props) {
const $ = React.unstable_useMemoCache();
const cond = props.cond;
const x = props.x;
- const c_0 = $[0] !== cond;
- const c_1 = $[1] !== x;
- let a;
- if (c_0 || c_1) {
- a = undefined;
- if (cond) {
- const a$0 = x;
- a = a$0;
- } else {
- let a$1;
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
- a$1 = [];
- $[3] = a$1;
- } else {
- a$1 = $[3];
- }
- a = a$1;
- }
- $[0] = cond;
- $[1] = x;
- $[2] = a;
+ let a = undefined;
+ if (cond) {
+ const a$0 = x;
+ a = a$0;
} else {
- a = $[2];
+ let a$1;
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+ a$1 = [];
+ $[0] = a$1;
+ } else {
+ a$1 = $[0];
+ }
+ a = a$1;
}
useFreeze(a);
diff --git a/compiler/forget/src/__tests__/fixtures/hir/infer-phi-primitive.expect.md b/compiler/forget/src/__tests__/fixtures/hir/infer-phi-primitive.expect.md
index 8089a133a3..5c2a1044ae 100644
--- a/compiler/forget/src/__tests__/fixtures/hir/infer-phi-primitive.expect.md
+++ b/compiler/forget/src/__tests__/fixtures/hir/infer-phi-primitive.expect.md
@@ -20,22 +20,13 @@ function foo(a, b) {
```javascript
function foo(a, b) {
- const $ = React.unstable_useMemoCache();
- const c_0 = $[0] !== a;
- let x;
- if (c_0) {
- x = undefined;
- if (a) {
- const x$0 = 1;
- x = x$0;
- } else {
- const x$1 = 2;
- x = x$1;
- }
- $[0] = a;
- $[1] = x;
+ let x = undefined;
+ if (a) {
+ const x$0 = 1;
+ x = x$0;
} else {
- x = $[1];
+ const x$1 = 2;
+ x = x$1;
}
const y = x;
diff --git a/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md b/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md
index e3f4ed85c8..02a22b8c47 100644
--- a/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md
+++ b/compiler/forget/src/__tests__/fixtures/hir/obj-literal-cached-in-if-else.expect.md
@@ -20,39 +20,29 @@ function foo(a, b, c, d) {
```javascript
function foo(a, b, c, d) {
const $ = React.unstable_useMemoCache();
- const c_0 = $[0] !== b;
- const c_1 = $[1] !== c;
- let x;
- if (c_0 || c_1) {
- x = undefined;
- if (someVal) {
- const c_3 = $[3] !== b;
- let x$0;
- if (c_3) {
- x$0 = { b: b };
- $[3] = b;
- $[4] = x$0;
- } else {
- x$0 = $[4];
- }
- x = x$0;
+ let x = undefined;
+ if (someVal) {
+ const c_0 = $[0] !== b;
+ let x$0;
+ if (c_0) {
+ x$0 = { b: b };
+ $[0] = b;
+ $[1] = x$0;
} else {
- const c_5 = $[5] !== c;
- let x$1;
- if (c_5) {
- x$1 = { c: c };
- $[5] = c;
- $[6] = x$1;
- } else {
- x$1 = $[6];
- }
- x = x$1;
+ x$0 = $[1];
}
- $[0] = b;
- $[1] = c;
- $[2] = x;
+ x = x$0;
} else {
- x = $[2];
+ const c_2 = $[2] !== c;
+ let x$1;
+ if (c_2) {
+ x$1 = { c: c };
+ $[2] = c;
+ $[3] = x$1;
+ } else {
+ x$1 = $[3];
+ }
+ x = x$1;
}
return x;
}
diff --git a/compiler/forget/src/__tests__/fixtures/hir/primitive-alias-mutate.expect.md b/compiler/forget/src/__tests__/fixtures/hir/primitive-alias-mutate.expect.md
index 448ab5ba68..0014449a79 100644
--- a/compiler/forget/src/__tests__/fixtures/hir/primitive-alias-mutate.expect.md
+++ b/compiler/forget/src/__tests__/fixtures/hir/primitive-alias-mutate.expect.md
@@ -20,22 +20,13 @@ function component(a) {
```javascript
function component(a) {
- const $ = React.unstable_useMemoCache();
- const c_0 = $[0] !== a;
- let x;
- if (c_0) {
- x = undefined;
- if (a) {
- const x$0 = "bar";
- x = x$0;
- } else {
- const x$1 = "baz";
- x = x$1;
- }
- $[0] = a;
- $[1] = x;
+ let x = undefined;
+ if (a) {
+ const x$0 = "bar";
+ x = x$0;
} else {
- x = $[1];
+ const x$1 = "baz";
+ x = x$1;
}
const y = x;
diff --git a/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
index 5925eeeeca..eb87414d0c 100644
--- a/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
@@ -35,37 +35,27 @@ function Component(props) {
x = $[1];
}
const y = x;
- const c_2 = $[2] !== props.p1;
- let x$0;
- if (c_2) {
- x$0 = x;
- if (props.p1) {
- let x$1;
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
- x$1 = [];
- $[4] = x$1;
- } else {
- x$1 = $[4];
- }
- x$0 = x$1;
+ let x$0 = x;
+ if (props.p1) {
+ let x$1;
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
+ x$1 = [];
+ $[2] = x$1;
+ } else {
+ x$1 = $[2];
}
- $[2] = props.p1;
- $[3] = x$0;
- } else {
- x$0 = $[3];
+ x$0 = x$1;
}
y.push(props.p2);
- const c_5 = $[5] !== x$0;
- const c_6 = $[6] !== y;
+ const c_3 = $[3] !== y;
let t0;
- if (c_5 || c_6) {
+ if (c_3) {
t0 =