From 19e21b73a7962d458b2f34c5c6becb622f13bf5c Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 3 Feb 2023 14:55:49 -0800 Subject: [PATCH] Initial pass at dead code elimination This is a first pass at DCE without having read any literate on the subject, so lemme know if there's a better approach. That said the algorithm is: * Keep a `Set` of identifiers that are used (and whose constructing logic cannot be removed). * Do a first RPO iteration of all block's phis. Any phi operand that participates in a loop is preemptively marked as "used" even if it isn't strictly used somewhere. This step is necessary bc these operands may otherwise not be used. * Do a second post-order iteration of all blocks, including iterating first their terminals, then reverse iteration of instructions, then their phis. Mark the operands of each as used as we encounter them, and prune instructions whose lvalue is never used. For now I was conservative about which types of instructions can be pruned. For example, call instructions are never pruned, even if the result of the call is never used. However one catch is that we currently prune instructions that cause values to become frozen. We had planned to add runtime calls (in dev) to freeze values for runtime enforcement, and if we want to do that we can always add these instructions back (or replace them with explicit freeze calls). There are a few potential next steps but we should discuss whether they're worth it: * Use fixpoint iteration to find exactly which operands are actually used. This would allow us to to prune cases such as `let x = 0; while (...) { x += 1 }` eg where there's a phi but the result is never used. Such cases should be rare in practice though. * Eliminate more types of instructions, eg eliminate function calls that don't have any mutable arguments. --- compiler/forget/src/CompilerPipeline.ts | 7 +- .../src/Optimization/ConstantPropagation.ts | 2 +- .../src/Optimization/DeadCodeElimination.ts | 140 ++++++++++++++++++ compiler/forget/src/Optimization/index.ts | 1 + .../_bug_expression-with-assignment.expect.md | 4 - .../src/__tests__/fixtures/hir/call.expect.md | 2 +- .../capturing-function-within-block.expect.md | 11 +- .../fixtures/hir/concise-arrow-expr.expect.md | 1 - .../hir/constant-propagation-for.expect.md | 2 +- .../hir/constant-propagation-while.expect.md | 3 +- .../hir/constant-propagation.expect.md | 10 -- .../fixtures/hir/constructor.expect.md | 2 - .../hir/dependencies-outputs.expect.md | 1 - ...or.while-with-assignment-in-test.expect.md | 2 +- .../fixtures/hir/for-logical.expect.md | 3 +- ...reeze-possibly-mutable-arguments.expect.md | 31 ++-- .../__tests__/fixtures/hir/issue852.expect.md | 15 +- .../hir/method-call-computed.expect.md | 4 - .../hir/method-call-fn-call.expect.md | 1 - .../fixtures/hir/method-call.expect.md | 1 - ...bject-computed-access-assignment.expect.md | 2 - .../fixtures/hir/object-properties.expect.md | 2 - .../hir/reassignment-conditional.expect.md | 1 - .../fixtures/hir/reassignment.expect.md | 1 - .../fixtures/hir/reverse-postorder.expect.md | 31 ++-- .../hir/sequence-expression.expect.md | 2 - .../fixtures/hir/simple-alias.expect.md | 17 +-- .../fixtures/hir/ssa-call-jsx.expect.md | 2 +- .../hir/ssa-for-trivial-update.expect.md | 2 +- .../fixtures/hir/ssa-multiple-phis.expect.md | 9 +- .../hir/ssa-objectexpression-phi.expect.md | 7 +- .../fixtures/hir/ssa-reassign.expect.md | 7 +- .../fixtures/hir/ssa-return.expect.md | 8 +- .../fixtures/hir/ssa-throw.expect.md | 8 +- .../hir/ssa-while-no-reassign.expect.md | 2 +- .../hir/switch-with-fallthrough.expect.md | 13 +- .../__tests__/fixtures/hir/switch.expect.md | 5 +- .../fixtures/hir/ternary-expression.expect.md | 2 +- .../hir/type-test-field-store.expect.md | 20 +-- .../hir/type-test-polymorphic.expect.md | 16 +- .../hir/unconditional-break-label.expect.md | 6 +- 41 files changed, 230 insertions(+), 176 deletions(-) create mode 100644 compiler/forget/src/Optimization/DeadCodeElimination.ts diff --git a/compiler/forget/src/CompilerPipeline.ts b/compiler/forget/src/CompilerPipeline.ts index 7ed34d2351..a517d3f73f 100644 --- a/compiler/forget/src/CompilerPipeline.ts +++ b/compiler/forget/src/CompilerPipeline.ts @@ -6,7 +6,6 @@ */ import { NodePath } from "@babel/traverse"; import * as t from "@babel/types"; -import { CompilerError } from "./CompilerError"; import { HIRFunction, lower, @@ -18,7 +17,7 @@ import { inferMutableRanges, inferReferenceEffects, } from "./Inference"; -import { constantPropagation } from "./Optimization"; +import { constantPropagation, deadCodeElimination } from "./Optimization"; import { alignReactiveScopesToBlockScopes, buildReactiveBlocks, @@ -71,6 +70,10 @@ export function* run( inferReferenceEffects(hir); yield log({ kind: "hir", name: "InferReferenceEffects", value: hir }); + // Note: Has to come after infer reference effects because "dead" code may still affect inference + deadCodeElimination(hir); + yield log({ kind: "hir", name: "DeadCodeElimination", value: hir }); + inferMutableRanges(hir); yield log({ kind: "hir", name: "InferMutableRanges", value: hir }); diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 139e9ebef3..74ab9b5bba 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -112,7 +112,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean { switch (terminal.kind) { case "if": { const testValue = read(constants, terminal.test); - if (testValue !== null && testValue.kind === "Primitive") { + if (testValue !== null) { hasChanges = true; const targetBlockId = Boolean(testValue.value) ? terminal.consequent diff --git a/compiler/forget/src/Optimization/DeadCodeElimination.ts b/compiler/forget/src/Optimization/DeadCodeElimination.ts new file mode 100644 index 0000000000..e97fbd70bb --- /dev/null +++ b/compiler/forget/src/Optimization/DeadCodeElimination.ts @@ -0,0 +1,140 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { + BlockId, + HIRFunction, + Identifier, + Instruction, + InstructionValue, +} from "../HIR"; +import { + eachInstructionValueOperand, + eachTerminalOperand, +} from "../HIR/visitors"; +import { assertExhaustive } from "../Utils/utils"; + +/** + * Implements dead-code elimination, eliminating instructions whose values are unused. + * + * Note that unreachable blocks are already pruned during HIR construction. + */ +export function deadCodeElimination(fn: HIRFunction): void { + const used = new Set(); + + // Find any phi operands involved in a loop, which might otherwise appear as dead + // code when using a reverse iteration. + // + // A more advanced algorithm could still prune some of these operands + // let's keep it simple for now + const seen = new Set(); + for (const [, block] of fn.body.blocks) { + for (const phi of block.phis) { + for (const [pred, operand] of phi.operands) { + if (!seen.has(pred)) { + used.add(operand); + } + } + } + seen.add(block.id); + } + + // Iterate blocks in postorder (successors before predecessors, excepting loops) + // to find usages before declarations + const reversedBlocks = [...fn.body.blocks.values()].reverse(); + for (const block of reversedBlocks) { + for (const operand of eachTerminalOperand(block.terminal)) { + used.add(operand.identifier); + } + + let nextInstructions: Array | null = null; + for (let i = block.instructions.length - 1; i >= 0; i--) { + const instr = block.instructions[i]!; + if ( + !used.has(instr.lvalue.place.identifier) && + pruneableValue(instr.value) && + // Can't prune the last value of a value block, that's its value! + !(block.kind !== "block" && i === block.instructions.length - 1) + ) { + continue; + } + used.add(instr.lvalue.place.identifier); + nextInstructions ??= []; + nextInstructions.push(instr); + for (const operand of eachInstructionValueOperand(instr.value)) { + used.add(operand.identifier); + } + } + if (nextInstructions !== null) { + nextInstructions.reverse(); + block.instructions = nextInstructions; + } + for (const phi of block.phis) { + if (used.has(phi.id)) { + for (const [, operand] of phi.operands) { + used.add(operand); + } + } else { + for (const [, operand] of phi.operands) { + if (used.has(operand)) { + used.add(phi.id); + for (const [, operand] of phi.operands) { + used.add(operand); + } + break; + } + } + } + } + } +} + +/** + * Returns true if it is safe to prune an instruction with the given value. + * Functions which may have side- + */ +function pruneableValue(value: InstructionValue): boolean { + switch (value.kind) { + case "CallExpression": + case "ComputedCall": + case "ComputedStore": + case "PropertyCall": + case "PropertyStore": { + // Mutating instructions are not safe to prune. + // TODO: we could be more precise and make this conditional on whether + // any arguments are actually modified + return false; + } + case "NewExpression": + case "UnsupportedNode": + case "TaggedTemplateExpression": { + // Potentially safe to prune, since they should just be creating new values + return false; + } + case "ArrayExpression": + case "BinaryExpression": + case "ComputedLoad": + case "ComputedStore": + case "FunctionExpression": + case "Identifier": + case "JsxExpression": + case "JsxFragment": + case "JSXText": + case "ObjectExpression": + case "Primitive": + case "PropertyLoad": + case "TemplateLiteral": + case "TypeCastExpression": + case "UnaryExpression": { + // Definitely safe to prune since they are read-only + return true; + } + default: { + assertExhaustive(value, `Unexepcted value kind '${(value as any).kind}'`); + } + } +} diff --git a/compiler/forget/src/Optimization/index.ts b/compiler/forget/src/Optimization/index.ts index 2d5e4f8956..8ee4e64f74 100644 --- a/compiler/forget/src/Optimization/index.ts +++ b/compiler/forget/src/Optimization/index.ts @@ -6,3 +6,4 @@ */ export { constantPropagation } from "./ConstantPropagation"; +export { deadCodeElimination } from "./DeadCodeElimination"; diff --git a/compiler/forget/src/__tests__/fixtures/hir/_bug_expression-with-assignment.expect.md b/compiler/forget/src/__tests__/fixtures/hir/_bug_expression-with-assignment.expect.md index 6f12db3046..4d909a7040 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/_bug_expression-with-assignment.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/_bug_expression-with-assignment.expect.md @@ -15,10 +15,6 @@ function f() { ```javascript function f() { - const x = 1; - - const x$0 = 2; - 4; return 6; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/call.expect.md index 890ddb71e7..bc102238da 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/call.expect.md @@ -28,7 +28,7 @@ function Component(props) { a = []; b = {}; foo(a, b); - const _ =
; + foo(b); $[0] = a; $[1] = b; diff --git a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md index 13e76bc544..23ba341a96 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/capturing-function-within-block.expect.md @@ -29,19 +29,18 @@ function component(a) { } else { z = $[1]; } - const x = undefined; const c_2 = $[2] !== z; - let x$0; + let x; if (c_2) { - x$0 = function () { + x = function () { z; }; $[2] = z; - $[3] = x$0; + $[3] = x; } else { - x$0 = $[3]; + x = $[3]; } - return x$0; + return x; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md b/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md index 88504d3c0b..93a89f101e 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/concise-arrow-expr.expect.md @@ -22,7 +22,6 @@ function component() { } else { t0 = $[0]; } - const x = t0[0]; const setX = t0[1]; let handler; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { diff --git a/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-for.expect.md b/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-for.expect.md index 97beb373f4..f04c6e1a74 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-for.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-for.expect.md @@ -20,7 +20,7 @@ function foo() { let y; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { y = 0; - for (const x = 100; 10, false; 100) { + for (const x = 100; false; 100) { y = y + 1; } $[0] = y; diff --git a/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-while.expect.md b/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-while.expect.md index 5af38847a7..9c8f154855 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-while.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/constant-propagation-while.expect.md @@ -18,11 +18,10 @@ function foo() { ```javascript function foo() { const $ = React.useMemoCache(); - const x = 100; let y; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { y = 0; - while ((10, false)) { + while (false) { y = y + 1; } $[0] = y; diff --git a/compiler/forget/src/__tests__/fixtures/hir/constant-propagation.expect.md b/compiler/forget/src/__tests__/fixtures/hir/constant-propagation.expect.md index b017f72463..003a163e0e 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/constant-propagation.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/constant-propagation.expect.md @@ -27,18 +27,8 @@ function foo() { ```javascript function foo() { - const a = 1; - const b = 2; - const c = 3; - const d = 3; - const e = 9; - const f = 3; - const g = -6; - console.log("foo"); - const h = -6; - const i = -6; const j = -6; return j; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md b/compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md index 1a2134d653..920ba5b91a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md @@ -28,8 +28,6 @@ function Component(props) { a = []; b = {}; new Foo(a, b); - - const _ =
; new Foo(b); $[0] = a; $[1] = b; diff --git a/compiler/forget/src/__tests__/fixtures/hir/dependencies-outputs.expect.md b/compiler/forget/src/__tests__/fixtures/hir/dependencies-outputs.expect.md index 273250bbbd..d95167c0e7 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/dependencies-outputs.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/dependencies-outputs.expect.md @@ -33,7 +33,6 @@ function foo(a, b) { } else { x = $[1]; } -
{x}
; const y = []; if (x.length) { diff --git a/compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.expect.md b/compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.expect.md index 08a6728aa7..660f28ae3f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.expect.md @@ -19,7 +19,7 @@ function f(reader) { ## Error ``` -[ReactForget] Todo: (CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare 'value$0' +[ReactForget] Todo: (CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare 'value' ``` \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md b/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md index 6545db8a51..c93f3f03ae 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/for-logical.expect.md @@ -32,10 +32,9 @@ function foo(props) { for ( let x = 0; x > props.min && x < props.max; - x = x$0 + (props.cond ? props.increment : (2, 2)), x + x = x$0 + (props.cond ? props.increment : 2), x ) { const x$0 = x * 2; - const y$1 = y + x$0; } return y; } 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 bf39ec4bf7..ae379c7747 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,36 +29,35 @@ function Component(props) { const $ = React.useMemoCache(); const cond = props.cond; const x = props.x; - const a = undefined; const c_0 = $[0] !== cond; const c_1 = $[1] !== x; - let a$0; + let a; if (c_0 || c_1) { - a$0 = undefined; + a = undefined; if (cond) { - const a$1 = x; - a$0 = a$1; + const a$0 = x; + a = a$0; } else { - let a$2; + let a$1; if ($[3] === Symbol.for("react.memo_cache_sentinel")) { - a$2 = []; - $[3] = a$2; + a$1 = []; + $[3] = a$1; } else { - a$2 = $[3]; + a$1 = $[3]; } - a$0 = a$2; + a = a$1; } $[0] = cond; $[1] = x; - $[2] = a$0; + $[2] = a; } else { - a$0 = $[2]; + a = $[2]; } - useFreeze(a$0); - useFreeze(a$0); - call(a$0); - return a$0; + useFreeze(a); + useFreeze(a); + call(a); + return a; } function useFreeze(x) {} diff --git a/compiler/forget/src/__tests__/fixtures/hir/issue852.expect.md b/compiler/forget/src/__tests__/fixtures/hir/issue852.expect.md index 15329c963d..23a621c30f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/issue852.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/issue852.expect.md @@ -15,19 +15,8 @@ function Component(c) { ```javascript function Component(c) { - const $ = React.useMemoCache(); - const c_0 = $[0] !== c; - let x; - if (c_0) { - x = { c: c }; - mutate(x); - $[0] = c; - $[1] = x; - } else { - x = $[1]; - } - const a = x; - const b = a; + const x = { c: c }; + mutate(x); } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md b/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md index 9503e94845..0266b81ac2 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/method-call-computed.expect.md @@ -41,10 +41,6 @@ function foo(a, b, c) { } else { y = $[3]; } -
- {x} - {y} -
; const c_4 = $[4] !== x; const c_5 = $[5] !== y.method; const c_6 = $[6] !== b; diff --git a/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md index 358aa0face..f5b3941181 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/method-call-fn-call.expect.md @@ -29,7 +29,6 @@ function foo(a, b, c) { } else { x = $[1]; } -
{x}
; const method = x.method; const c_2 = $[2] !== method; diff --git a/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md b/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md index 7e34d67561..4568c41289 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/method-call.expect.md @@ -28,7 +28,6 @@ function foo(a, b, c) { } else { x = $[1]; } -
{x}
; const c_2 = $[2] !== x; const c_3 = $[3] !== b; let y; diff --git a/compiler/forget/src/__tests__/fixtures/hir/object-computed-access-assignment.expect.md b/compiler/forget/src/__tests__/fixtures/hir/object-computed-access-assignment.expect.md index f897d84f1a..43de30d2a9 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/object-computed-access-assignment.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/object-computed-access-assignment.expect.md @@ -14,8 +14,6 @@ function foo(a, b, c) { ```javascript function foo(a, b, c) { a[b] = c[b]; - 1; - 2; a[3] = c[b * 4]; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/object-properties.expect.md b/compiler/forget/src/__tests__/fixtures/hir/object-properties.expect.md index 269425b77b..a5bef7d2bb 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/object-properties.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/object-properties.expect.md @@ -16,12 +16,10 @@ function foo(a, b, c) { ```javascript function foo(a, b, c) { - const x = a.x; const y = b.c.d; y.z = c.d.e; foo(a.b.c); - [a.b.c]; } ``` 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 085ed96e1d..1ffa40f0b0 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md @@ -55,7 +55,6 @@ function Component(props) { x$0 = $[3]; } - const _ = ; y.push(props.p2); const c_5 = $[5] !== x$0; const c_6 = $[6] !== y; diff --git a/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md index 280ba31389..471b39cc33 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md @@ -36,7 +36,6 @@ function Component(props) { } else { x$0 = $[3]; } - const _ = ; y.push(props.p1); $[0] = props.p0; diff --git a/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md index bd40755ff0..383b4814e5 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md @@ -37,7 +37,6 @@ function Component(props) { ```javascript function Component(props) { const $ = React.useMemoCache(); - const x = undefined; const c_0 = $[0] !== props.cond; const c_1 = $[1] !== props.test; const c_2 = $[2] !== props.v0; @@ -46,35 +45,35 @@ function Component(props) { const c_5 = $[5] !== props.cond2; const c_6 = $[6] !== props.b; const c_7 = $[7] !== props.c; - let x$0; + let x; if (c_0 || c_1 || c_2 || c_3 || c_4 || c_5 || c_6 || c_7) { - x$0 = undefined; + x = undefined; bb1: if (props.cond) { switch (props.test) { case 0: { - const x$1 = props.v0; - x$0 = x$1; + const x$0 = props.v0; + x = x$0; break bb1; } case 1: { - const x$2 = props.v1; - x$0 = x$2; + const x$1 = props.v1; + x = x$1; break bb1; } case 2: { } default: { - const x$3 = props.v2; - x$0 = x$3; + const x$2 = props.v2; + x = x$2; } } } else { if (props.cond2) { - const x$4 = props.b; - x$0 = x$4; + const x$3 = props.b; + x = x$3; } else { - const x$5 = props.c; - x$0 = x$5; + const x$4 = props.c; + x = x$4; } } $[0] = props.cond; @@ -85,11 +84,11 @@ function Component(props) { $[5] = props.cond2; $[6] = props.b; $[7] = props.c; - $[8] = x$0; + $[8] = x; } else { - x$0 = $[8]; + x = $[8]; } - x$0; + x; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/sequence-expression.expect.md b/compiler/forget/src/__tests__/fixtures/hir/sequence-expression.expect.md index 2229452ce8..623c48bc5d 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/sequence-expression.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/sequence-expression.expect.md @@ -19,7 +19,6 @@ function foo() {} ```javascript function sequence(props) { const $ = React.useMemoCache(); - null; Math.max(1, 2); let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { @@ -33,7 +32,6 @@ function sequence(props) { x = t0; while ((foo(), true)) { foo(); - 2; x = 2; } $[1] = x; diff --git a/compiler/forget/src/__tests__/fixtures/hir/simple-alias.expect.md b/compiler/forget/src/__tests__/fixtures/hir/simple-alias.expect.md index edc162220c..8496abe0a1 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/simple-alias.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/simple-alias.expect.md @@ -22,20 +22,19 @@ function foo() { function mutate() {} function foo() { const $ = React.useMemoCache(); - const a = {}; - let c$2; + let c$1; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { const b = {}; const c = {}; - const a$0 = b; - const b$1 = c; - c$2 = a$0; - mutate(a$0, b$1); - $[0] = c$2; + const a = b; + const b$0 = c; + c$1 = a; + mutate(a, b$0); + $[0] = c$1; } else { - c$2 = $[0]; + c$1 = $[0]; } - return c$2; + return c$1; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md index 22fa95c7cb..53192e7157 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md @@ -28,7 +28,7 @@ function Component(props) { a = []; b = {}; foo(a, b); - const _ =
; + foo(a, b); $[0] = a; $[1] = b; diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-for-trivial-update.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-for-trivial-update.expect.md index ed66fd2fc2..8fe5dcc42e 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-for-trivial-update.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-for-trivial-update.expect.md @@ -20,7 +20,7 @@ function foo() { let x; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { x = 1; - for (const i = 0; 10, true; 0) { + for (const i = 0; true; 0) { x = x + 1; } $[0] = x; diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md index 706f80dc12..bd69f439a1 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md @@ -28,13 +28,8 @@ function foo(a, b, c, d) { ```javascript function foo(a, b, c, d) { - const x = 0; - true; - true; - - const x$0 = a; - x$0; - return x$0; + const x = a; + return x; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md index 0482d025f0..21b4c48345 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md @@ -24,14 +24,11 @@ function foo() { function foo() { const $ = React.useMemoCache(); const x = 1; - const y = 2; - 1; - false; - const y$0 = 3; + const y = 3; let t; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t = { x: x, y: y$0 }; + t = { x: x, y: y }; $[0] = t; } else { t = $[0]; diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.expect.md index 4228828e8b..5599ea79df 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.expect.md @@ -16,11 +16,8 @@ function foo(a, b, c) { ```javascript function foo(a, b, c) { - const x = 0; - const x$0 = a; - const x$1 = b; - const x$2 = c; - return x$2; + const x = c; + return x; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md index c3d920a035..faa85fd9b2 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md @@ -17,12 +17,8 @@ function foo() { ```javascript function foo() { - const x = 1; - 1; - true; - - const x$0 = 2; - return x$0; + const x = 2; + return x; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md index 649ec96602..f3fd0c69aa 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md @@ -16,12 +16,8 @@ function foo() { ```javascript function foo() { - const x = 1; - 1; - true; - - const x$0 = 2; - throw x$0; + const x = 2; + throw x; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md index 61b8af9b58..5e69a4427a 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md @@ -18,7 +18,7 @@ function foo() { ```javascript function foo() { const x = 1; - while ((10, true)) { + while (true) { 1; 2; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch-with-fallthrough.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch-with-fallthrough.expect.md index 1fe980f5e6..2d5476f046 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch-with-fallthrough.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch-with-fallthrough.expect.md @@ -36,30 +36,29 @@ function foo(x) { ```javascript function foo(x) { - const y = undefined; bb1: switch (x) { case 0: { - const y$0 = 0; + const y = 0; } case 1: { - const y$1 = 1; + const y = 1; break bb1; } case 2: { break bb1; } case 3: { - const y$2 = 3; + const y = 3; break bb1; } case 4: { - const y$3 = 4; + const y = 4; } case 5: { - const y$4 = 5; + const y = 5; } default: { - const y$5 = 0; + const y = 0; } } } diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md index 079e07d6d9..1e3006dbf2 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md @@ -41,11 +41,10 @@ function Component(props) { case true: { x.push(props.p2); x.push(props.p3); - const y$1 = []; } case false: { - const y$2 = x; - y$0 = y$2; + const y$1 = x; + y$0 = y$1; } } $[0] = props.p0; diff --git a/compiler/forget/src/__tests__/fixtures/hir/ternary-expression.expect.md b/compiler/forget/src/__tests__/fixtures/hir/ternary-expression.expect.md index 2a6673c632..f5814bafb9 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/ternary-expression.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/ternary-expression.expect.md @@ -39,7 +39,7 @@ function ternary(props) { const c_5 = $[5] !== b; let t2; if (c_4 || c_5) { - t2 = a ? b : (null, null); + t2 = a ? b : null; $[4] = a; $[5] = b; $[6] = t2; diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md index d1729012c9..1eea2cb83f 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md @@ -16,23 +16,15 @@ function component() { ```javascript function component() { const $ = React.useMemoCache(); - let x; + const x = {}; + let q; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - x = {}; - let q; - if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - q = {}; - $[1] = q; - } else { - q = $[1]; - } - x.t = q; - $[0] = x; + q = {}; + $[0] = q; } else { - x = $[0]; + q = $[0]; } - - const z = x.t; + x.t = q; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md index 1dd78727d0..af57a0b5f8 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md @@ -30,7 +30,6 @@ function component() { } else { p = $[0]; } - p + p; let o; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { o = {}; @@ -38,19 +37,10 @@ function component() { } else { o = $[1]; } - let x; - if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - x = {}; - x.t = p; - const z = x.t; - x.t = o; - $[2] = x; - } else { - x = $[2]; - } - - const y = x.t; + const x = {}; + x.t = p; + x.t = o; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/unconditional-break-label.expect.md b/compiler/forget/src/__tests__/fixtures/hir/unconditional-break-label.expect.md index ffaa70d6e3..46200d32a1 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/unconditional-break-label.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/unconditional-break-label.expect.md @@ -17,10 +17,8 @@ function foo(a) { ```javascript function foo(a) { - const x = 0; - - const x$0 = 1; - return a + x$0; + const x = 1; + return a + x; } ```