@samitouri / QOS-React-1 / commits / 7d9861e706

[compiler][hir] Correctly remove non-existent terminal preds when pruning labels

Missed this initially in `pruneUnusedLabelsHIR`. It wasn't an active bug as `preds` wasn't referenced by later passes, until #30079 ghstack-source-id: 3e151b74c31554299e870f001c0ac3f72706318c Pull Request resolved: https://github.com/facebook/react/pull/30076

Mofei Zhang committed Jun 25, 2024 at 16:06 UTC 7d9861e70642719b120a5236ade5124912e42a92
4 files changed +38 -2
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts
+3
@@ -13,6 +13,7 @@ import {
13 HIRFunction,
14 ReactiveFunction,
15 assertConsistentIdentifiers,
16 + assertTerminalPredsExist,
17 assertTerminalSuccessorsExist,
18 assertValidBlockNesting,
19 assertValidMutableRanges,
@@ -303,6 +304,8 @@ function* runWithEnvironment(
304 name: "FlattenScopesWithHooksOrUseHIR",
305 value: hir,
306 });
307 + assertTerminalSuccessorsExist(hir);
308 + assertTerminalPredsExist(hir);
309 }
310
311 const reactiveFunction = buildReactiveFunction(hir);
compiler/packages/babel-plugin-react-compiler/src/HIR/AssertTerminalBlocksExist.ts renamed
+21 -1
@@ -8,7 +8,7 @@
8 import { CompilerError } from "../CompilerError";
9 import { GeneratedSource, HIRFunction } from "./HIR";
10 import { printTerminal } from "./PrintHIR";
11 -import { mapTerminalSuccessors } from "./visitors";
11 +import { eachTerminalSuccessor, mapTerminalSuccessors } from "./visitors";
12
13 export function assertTerminalSuccessorsExist(fn: HIRFunction): void {
14 for (const [, block] of fn.body.blocks) {
@@ -25,3 +25,23 @@ export function assertTerminalSuccessorsExist(fn: HIRFunction): void {
25 });
26 }
27 }
28 +
29 +export function assertTerminalPredsExist(fn: HIRFunction): void {
30 + for (const [, block] of fn.body.blocks) {
31 + for (const pred of block.preds) {
32 + const predBlock = fn.body.blocks.get(pred);
33 + CompilerError.invariant(predBlock != null, {
34 + reason: "Expected predecessor block to exist",
35 + description: `Block ${block.id} references non-existent ${pred}`,
36 + loc: GeneratedSource,
37 + });
38 + CompilerError.invariant(
39 + [...eachTerminalSuccessor(predBlock.terminal)].includes(block.id),
40 + {
41 + reason: "Terminal successor does not reference correct predecessor",
42 + loc: GeneratedSource,
43 + }
44 + );
45 + }
46 + }
47 +}
compiler/packages/babel-plugin-react-compiler/src/HIR/PruneUnusedLabelsHIR.ts
+10
@@ -67,4 +67,14 @@ export function pruneUnusedLabelsHIR(fn: HIRFunction): void {
67 fn.body.blocks.delete(fallthroughId);
68 rewrites.set(fallthroughId, labelId);
69 }
70 +
71 + for (const [_, block] of fn.body.blocks) {
72 + for (const pred of block.preds) {
73 + const rewritten = rewrites.get(pred);
74 + if (rewritten != null) {
75 + block.preds.delete(pred);
76 + block.preds.add(rewritten);
77 + }
78 + }
79 + }
80 }
compiler/packages/babel-plugin-react-compiler/src/HIR/index.ts
+4 -1
@@ -6,7 +6,10 @@
6 */
7
8 export { assertConsistentIdentifiers } from "./AssertConsistentIdentifiers";
9 -export { assertTerminalSuccessorsExist } from "./AssertTerminalSuccessorsExist";
9 +export {
10 + assertTerminalSuccessorsExist,
11 + assertTerminalPredsExist,
12 +} from "./AssertTerminalBlocksExist";
13 export { assertValidBlockNesting } from "./AssertValidBlockNesting";
14 export { assertValidMutableRanges } from "./AssertValidMutableRanges";
15 export { lower } from "./BuildHIR";