From e7f4eae619cd38c829c62f5a6f869b50f7789c70 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Wed, 8 Feb 2023 10:26:31 -0500 Subject: [PATCH] Reset canonicalId mutable range if not mutated after creation --- compiler/forget/src/HIR/PrintHIR.ts | 2 +- compiler/forget/src/SSA/LeaveSSA.ts | 17 ++--- ...reeze-possibly-mutable-arguments.expect.md | 34 +++------ .../hir/infer-phi-primitive.expect.md | 21 ++--- .../obj-literal-cached-in-if-else.expect.md | 50 +++++------- .../hir/primitive-alias-mutate.expect.md | 21 ++--- .../hir/reassignment-conditional.expect.md | 38 ++++------ .../reassignment-separate-scopes.expect.md | 76 ++++++++----------- .../fixtures/hir/ssa-leave-case.expect.md | 17 ++--- .../hir/ssa-nested-partial-phi.expect.md | 17 +---- .../ssa-nested-partial-reassignment.expect.md | 31 ++------ .../fixtures/hir/ssa-renaming.expect.md | 34 +++------ .../fixtures/hir/ssa-shadowing.expect.md | 21 ++--- .../hir/switch-non-final-default.expect.md | 33 ++++---- .../__tests__/fixtures/hir/switch.expect.md | 27 +++---- 15 files changed, 160 insertions(+), 279 deletions(-) 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 = ; - $[5] = x$0; - $[6] = y; - $[7] = t0; + $[3] = y; + $[4] = t0; } else { - t0 = $[7]; + t0 = $[4]; } return t0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md index 3fadaf0fcb..f65319c67a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md @@ -56,61 +56,49 @@ function foo(a, b, c) { } else { y = $[3]; } - const c_4 = $[4] !== b; - const c_5 = $[5] !== c; - let x$0; - if (c_4 || c_5) { - x$0 = undefined; - bb3: switch (b) { - case 0: { - const c_7 = $[7] !== b; - let x$1; - if (c_7) { - x$1 = []; - x$1.push(b); - $[7] = b; - $[8] = x$1; - } else { - x$1 = $[8]; - } - x$0 = x$1; - break bb3; - } - default: { - const c_9 = $[9] !== c; - let x$2; - if (c_9) { - x$2 = []; - x$2.push(c); - $[9] = c; - $[10] = x$2; - } else { - x$2 = $[10]; - } - x$0 = x$2; + let x$0 = undefined; + bb3: switch (b) { + case 0: { + const c_4 = $[4] !== b; + let x$1; + if (c_4) { + x$1 = []; + x$1.push(b); + $[4] = b; + $[5] = x$1; + } else { + x$1 = $[5]; } + x$0 = x$1; + break bb3; + } + default: { + const c_6 = $[6] !== c; + let x$2; + if (c_6) { + x$2 = []; + x$2.push(c); + $[6] = c; + $[7] = x$2; + } else { + x$2 = $[7]; + } + x$0 = x$2; } - $[4] = b; - $[5] = c; - $[6] = x$0; - } else { - x$0 = $[6]; } - const c_11 = $[11] !== y; - const c_12 = $[12] !== x$0; + const c_8 = $[8] !== y; let t0; - if (c_11 || c_12) { + if (c_8) { t0 = (
{y} {x$0}
); - $[11] = y; - $[12] = x$0; - $[13] = t0; + $[8] = y; + $[9] = t0; } else { - t0 = $[13]; + t0 = $[9]; } return t0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-leave-case.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-leave-case.expect.md index 4c7225c6d8..ba26e228b8 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-leave-case.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-leave-case.expect.md @@ -27,11 +27,10 @@ function Component(props) { const c_0 = $[0] !== props.p0; const c_1 = $[1] !== props.p1; let x; - let y$0; if (c_0 || c_1) { x = []; const y = undefined; - y$0 = y; + let y$0 = y; if (props.p0) { x.push(props.p1); const y$1 = x; @@ -40,26 +39,22 @@ function Component(props) { $[0] = props.p0; $[1] = props.p1; $[2] = x; - $[3] = y$0; } else { x = $[2]; - y$0 = $[3]; } - const c_4 = $[4] !== x; - const c_5 = $[5] !== y$0; + const c_3 = $[3] !== x; let t0; - if (c_4 || c_5) { + if (c_3) { t0 = ( {x} {y$0} ); - $[4] = x; - $[5] = y$0; - $[6] = t0; + $[3] = x; + $[4] = t0; } else { - t0 = $[6]; + t0 = $[4]; } return t0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md index 37ffd23bc5..f6c4b97fb7 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md @@ -19,21 +19,12 @@ function foo(a, b, c) { ```javascript function foo(a, b, c) { - const $ = React.unstable_useMemoCache(); const x = a; if (b) { - const c_0 = $[0] !== c; - let x$0; - if (c_0) { - x$0 = x; - if (c) { - const x$1 = c; - x$0 = x$1; - } - $[0] = c; - $[1] = x$0; - } else { - x$0 = $[1]; + let x$0 = x; + if (c) { + const x$1 = c; + x$0 = x$1; } return x$0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md index bb07e3f0b2..735903f228 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md @@ -20,31 +20,16 @@ function foo(a, b, c, d, e) { ```javascript function foo(a, b, c, d, e) { - const $ = React.unstable_useMemoCache(); const x = null; - const c_0 = $[0] !== a; - const c_1 = $[1] !== b; - const c_2 = $[2] !== c; - const c_3 = $[3] !== d; - let x$0; - if (c_0 || c_1 || c_2 || c_3) { - x$0 = x; - if (a) { - const x$1 = b; - x$0 = x$1; - } else { - if (c) { - const x$2 = d; - x$0 = x$2; - } - } - $[0] = a; - $[1] = b; - $[2] = c; - $[3] = d; - $[4] = x$0; + let x$0 = x; + if (a) { + const x$1 = b; + x$0 = x$1; } else { - x$0 = $[4]; + if (c) { + const x$2 = d; + x$0 = x$2; + } } return x$0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming.expect.md index 01f3e8648a..8e9ec02af8 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-renaming.expect.md @@ -30,29 +30,19 @@ function foo(props) { } else { x = $[1]; } - const c_2 = $[2] !== props.cond; - const c_3 = $[3] !== props.foo; - let x$0; - if (c_2 || c_3) { - x$0 = x; - if (props.cond) { - const c_5 = $[5] !== props.foo; - let x$1; - if (c_5) { - x$1 = []; - x$1.push(props.foo); - $[5] = props.foo; - $[6] = x$1; - } else { - x$1 = $[6]; - } - x$0 = x$1; + let x$0 = x; + if (props.cond) { + const c_2 = $[2] !== props.foo; + let x$1; + if (c_2) { + x$1 = []; + x$1.push(props.foo); + $[2] = props.foo; + $[3] = x$1; + } else { + x$1 = $[3]; } - $[2] = props.cond; - $[3] = props.foo; - $[4] = x$0; - } else { - x$0 = $[4]; + x$0 = x$1; } return x$0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md index dc47c50bef..6e0b1b7f56 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md @@ -23,23 +23,14 @@ function Foo(cond) { function log() {} function Foo(cond) { - const $ = React.unstable_useMemoCache(); const str = ""; - const c_0 = $[0] !== cond; - let str$0; - if (c_0) { - str$0 = str; - if (cond) { - const str_0 = "other test"; - log(str_0); - } else { - const str$1 = "fallthrough test"; - str$0 = str$1; - } - $[0] = cond; - $[1] = str$0; + let str$0 = str; + if (cond) { + const str_0 = "other test"; + log(str_0); } else { - str$0 = $[1]; + const str$1 = "fallthrough test"; + str$0 = str$1; } log(str$0); diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md index 9ddb49f74d..9fe7363ddb 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md @@ -36,11 +36,10 @@ function Component(props) { const c_0 = $[0] !== props.p0; const c_1 = $[1] !== props.p2; let x; - let y$0; if (c_0 || c_1) { x = []; const y = undefined; - y$0 = y; + let y$0 = y; bb1: switch (props.p0) { case 1: { break bb1; @@ -48,11 +47,11 @@ function Component(props) { case true: { x.push(props.p2); let y$1; - if ($[4] === Symbol.for("react.memo_cache_sentinel")) { + if ($[3] === Symbol.for("react.memo_cache_sentinel")) { y$1 = []; - $[4] = y$1; + $[3] = y$1; } else { - y$1 = $[4]; + y$1 = $[3]; } y$0 = y$1; break bb1; @@ -68,31 +67,27 @@ function Component(props) { $[0] = props.p0; $[1] = props.p2; $[2] = x; - $[3] = y$0; } else { x = $[2]; - y$0 = $[3]; } - const c_5 = $[5] !== x; + const c_4 = $[4] !== x; let child; - if (c_5) { + if (c_4) { child = ; - $[5] = x; - $[6] = child; + $[4] = x; + $[5] = child; } else { - child = $[6]; + child = $[5]; } y$0.push(props.p4); - const c_7 = $[7] !== y$0; - const c_8 = $[8] !== child; + const c_6 = $[6] !== child; let t0; - if (c_7 || c_8) { + if (c_6) { t0 = {child}; - $[7] = y$0; - $[8] = child; - $[9] = t0; + $[6] = child; + $[7] = t0; } else { - t0 = $[9]; + t0 = $[7]; } return t0; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md index fa5f40ea80..52cac52421 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md @@ -32,11 +32,10 @@ function Component(props) { const c_1 = $[1] !== props.p2; const c_2 = $[2] !== props.p3; let x; - let y$0; if (c_0 || c_1 || c_2) { x = []; const y = undefined; - y$0 = y; + let y$0 = y; switch (props.p0) { case true: { x.push(props.p2); @@ -51,31 +50,27 @@ function Component(props) { $[1] = props.p2; $[2] = props.p3; $[3] = x; - $[4] = y$0; } else { x = $[3]; - y$0 = $[4]; } - const c_5 = $[5] !== x; + const c_4 = $[4] !== x; let child; - if (c_5) { + if (c_4) { child = ; - $[5] = x; - $[6] = child; + $[4] = x; + $[5] = child; } else { - child = $[6]; + child = $[5]; } y$0.push(props.p4); - const c_7 = $[7] !== y$0; - const c_8 = $[8] !== child; + const c_6 = $[6] !== child; let t0; - if (c_7 || c_8) { + if (c_6) { t0 = {child}; - $[7] = y$0; - $[8] = child; - $[9] = t0; + $[6] = child; + $[7] = t0; } else { - t0 = $[9]; + t0 = $[7]; } return t0; }