Skip to content

Commit 95b71d6

Browse files
committed
Added new logic under the PromoteUsedTemporaries file
1 parent 57d9058 commit 95b71d6

5 files changed

Lines changed: 46 additions & 45 deletions

File tree

compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
markInstructionIds,
2424
markPredecessors,
2525
mergeConsecutiveBlocks,
26-
promoteTemporaryJsxTag,
2726
reversePostorderBlocks,
2827
} from '../HIR';
2928
import {
@@ -63,12 +62,7 @@ export function constantPropagation(fn: HIRFunction): void {
6362

6463
function constantPropagationImpl(fn: HIRFunction, constants: Constants): void {
6564
while (true) {
66-
const jsxTagIdentifiers = collectJsxTagIdentifiers(fn);
67-
const haveTerminalsChanged = applyConstantPropagation(
68-
fn,
69-
constants,
70-
jsxTagIdentifiers,
71-
);
65+
const haveTerminalsChanged = applyConstantPropagation(fn, constants);
7266
if (!haveTerminalsChanged) {
7367
break;
7468
}
@@ -112,7 +106,6 @@ function constantPropagationImpl(fn: HIRFunction, constants: Constants): void {
112106
function applyConstantPropagation(
113107
fn: HIRFunction,
114108
constants: Constants,
115-
jsxTagIdentifiers: Set<IdentifierId>,
116109
): boolean {
117110
let hasChanges = false;
118111
for (const [, block] of fn.body.blocks) {
@@ -137,7 +130,7 @@ function applyConstantPropagation(
137130
continue;
138131
}
139132
const instr = block.instructions[i]!;
140-
const value = evaluateInstruction(constants, instr, jsxTagIdentifiers);
133+
const value = evaluateInstruction(constants, instr);
141134
if (value !== null) {
142135
constants.set(instr.lvalue.identifier.id, value);
143136
}
@@ -246,7 +239,6 @@ function evaluatePhi(phi: Phi, constants: Constants): Constant | null {
246239
function evaluateInstruction(
247240
constants: Constants,
248241
instr: Instruction,
249-
jsxTagIdentifiers: Set<IdentifierId>,
250242
): Constant | null {
251243
const value = instr.value;
252244
switch (value.kind) {
@@ -601,14 +593,6 @@ function evaluateInstruction(
601593
case 'LoadLocal': {
602594
const placeValue = read(constants, value.place);
603595
if (placeValue !== null) {
604-
if (
605-
instr.lvalue != null &&
606-
jsxTagIdentifiers.has(instr.lvalue.identifier.id) &&
607-
placeValue.kind === 'LoadGlobal' &&
608-
instr.lvalue.identifier.name == null
609-
) {
610-
promoteTemporaryJsxTag(instr.lvalue.identifier);
611-
}
612596
instr.value = placeValue;
613597
}
614598
return placeValue;
@@ -655,19 +639,3 @@ function read(constants: Constants, place: Place): Constant | null {
655639

656640
type Constant = Primitive | LoadGlobal;
657641
type Constants = Map<IdentifierId, Constant>;
658-
659-
function collectJsxTagIdentifiers(fn: HIRFunction): Set<IdentifierId> {
660-
const identifiers = new Set<IdentifierId>();
661-
662-
for (const [, block] of fn.body.blocks) {
663-
for (const instr of block.instructions) {
664-
if (
665-
instr.value.kind === 'JsxExpression' &&
666-
instr.value.tag.kind === 'Identifier'
667-
) {
668-
identifiers.add(instr.value.tag.identifier.id);
669-
}
670-
}
671-
}
672-
return identifiers;
673-
}

compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PromoteUsedTemporaries.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,39 @@ import {eachInstructionValueLValue, eachPatternOperand} from '../HIR/visitors';
3131
* Phase 2: Promote identifiers which are used in a place that requires a named variable.
3232
*/
3333
class PromoteTemporaries extends ReactiveFunctionVisitor<State> {
34+
/*
35+
* Only promote LoadGlobal temps when the JSX tag identifier's name differs
36+
* from the referenced module-local binding. This preserves direct uses like
37+
* <StaticText1 /> while still emitting stable temps for aliases such as
38+
* const Tag = StaticText1; return <Tag />;.
39+
*/
40+
override visitInstruction(
41+
instruction: ReactiveInstruction,
42+
state: State,
43+
): void {
44+
const binding =
45+
instruction.value.kind === 'LoadGlobal'
46+
? instruction.value.binding
47+
: null;
48+
const lvalue = instruction.lvalue;
49+
const tagName =
50+
lvalue != null
51+
? (state.tagNames.get(lvalue.identifier.declarationId) ?? null)
52+
: null;
53+
if (
54+
binding != null &&
55+
binding.kind === 'ModuleLocal' &&
56+
lvalue != null &&
57+
lvalue.identifier.name == null &&
58+
tagName !== null &&
59+
tagName !== binding.name &&
60+
state.tags.has(lvalue.identifier.declarationId)
61+
) {
62+
promoteIdentifier(lvalue.identifier, state);
63+
}
64+
this.traverseInstruction(instruction, state);
65+
}
66+
3467
override visitScope(scopeBlock: ReactiveScopeBlock, state: State): void {
3568
for (const dep of scopeBlock.scope.dependencies) {
3669
const {identifier} = dep;
@@ -172,6 +205,7 @@ class PromoteAllInstancedOfPromotedTemporaries extends ReactiveFunctionVisitor<S
172205
type JsxExpressionTags = Set<DeclarationId>;
173206
type State = {
174207
tags: JsxExpressionTags;
208+
tagNames: Map<DeclarationId, string | null>;
175209
promoted: Set<DeclarationId>;
176210
pruned: Map<
177211
DeclarationId,
@@ -205,7 +239,10 @@ class CollectPromotableTemporaries extends ReactiveFunctionVisitor<State> {
205239
): void {
206240
this.traverseValue(id, value, state);
207241
if (value.kind === 'JsxExpression' && value.tag.kind === 'Identifier') {
208-
state.tags.add(value.tag.identifier.declarationId);
242+
const identifier = value.tag.identifier;
243+
state.tags.add(identifier.declarationId);
244+
const name = identifier.name != null ? identifier.name.value : null;
245+
state.tagNames.set(identifier.declarationId, name);
209246
}
210247
}
211248

@@ -432,6 +469,7 @@ class PromoteInterposedTemporaries extends ReactiveFunctionVisitor<InterState> {
432469
export function promoteUsedTemporaries(fn: ReactiveFunction): void {
433470
const state: State = {
434471
tags: new Set(),
472+
tagNames: new Map(),
435473
promoted: new Set(),
436474
pruned: new Map(),
437475
};

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.expect.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ function useFoo() {
3737
return t0;
3838
}
3939
function _temp() {
40-
const T0 = Stringify;
41-
return <T0 value={4} />;
40+
return <Stringify value={4} />;
4241
}
4342

4443
export const FIXTURE_ENTRYPOINT = {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-tag-evaluation-order.expect.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,21 @@ import { StaticText1, StaticText2 } from "shared-runtime";
3131
function Component(props) {
3232
const $ = _c(3);
3333

34-
const T0 = StaticText1;
3534
const t0 = props.value;
36-
const T1 = StaticText2;
3735
let t1;
3836
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
39-
t1 = <T1 />;
37+
t1 = <StaticText2 />;
4038
$[0] = t1;
4139
} else {
4240
t1 = $[0];
4341
}
4442
let t2;
4543
if ($[1] !== t0) {
4644
t2 = (
47-
<T0>
45+
<StaticText1>
4846
{t0}
4947
{t1}
50-
</T0>
48+
</StaticText1>
5149
);
5250
$[1] = t0;
5351
$[2] = t2;

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-jsx-dynamic-tag-alias.expect.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ const base = "div";
2727

2828
const TestComponent: React.FC = () => {
2929
const $ = _c(1);
30-
31-
const T0 = base;
3230
let t0;
3331
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
34-
t0 = <T0 />;
32+
t0 = <base />;
3533
$[0] = t0;
3634
} else {
3735
t0 = $[0];

0 commit comments

Comments
 (0)