Skip to content

Commit c2b45ef

Browse files
authored
feat(compiler): Implement constant folding for more binary expressions (#29650)
## Summary There are already most arithmetic operators in constant propagation: `+`, `-`, `*`, `/`. We could add more, namely: `|`, `&`, `^`, `<<`, `>>`, `>>>` and `%`: Input: ```js function f() { return [ 123.45 | 0, 123.45 & 0, 123.45 ^ 0, 123 << 0, 123 >> 0, 123 >>> 0, 123.45 | 1, 123.45 & 1, 123.45 ^ 1, 123 << 1, 123 >> 1, 123 >>> 1, 3 ** 2, 3 ** 2.5, 3.5 ** 2, 2 ** 3 ** 0.5, 4 % 2, 4 % 2.5, 4 % 3, 4.5 % 2, ]; } ``` Output: ```js function f() { return [ 123, 0, 123, 123, 123, 123, 123, 1, 122, 246, 61, 61, 9, 15.588457268119896, 12.25, 3.3219970854839125, 0, 1.5, 1, 0.5, ]; } ``` Resolves #29649 ## How did you test this change? See tests. Note: This PR was done without waiting for approval in #29649, so feel free to just close it without any comment.
1 parent 867edc6 commit c2b45ef

File tree

4 files changed

+167
-4
lines changed

4 files changed

+167
-4
lines changed

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,58 @@ function evaluateInstruction(
369369
}
370370
break;
371371
}
372+
case "|": {
373+
if (typeof lhs === "number" && typeof rhs === "number") {
374+
result = { kind: "Primitive", value: lhs | rhs, loc: value.loc };
375+
}
376+
break;
377+
}
378+
case "&": {
379+
if (typeof lhs === "number" && typeof rhs === "number") {
380+
result = { kind: "Primitive", value: lhs & rhs, loc: value.loc };
381+
}
382+
break;
383+
}
384+
case "^": {
385+
if (typeof lhs === "number" && typeof rhs === "number") {
386+
result = { kind: "Primitive", value: lhs ^ rhs, loc: value.loc };
387+
}
388+
break;
389+
}
390+
case "<<": {
391+
if (typeof lhs === "number" && typeof rhs === "number") {
392+
result = { kind: "Primitive", value: lhs << rhs, loc: value.loc };
393+
}
394+
break;
395+
}
396+
case ">>": {
397+
if (typeof lhs === "number" && typeof rhs === "number") {
398+
result = { kind: "Primitive", value: lhs >> rhs, loc: value.loc };
399+
}
400+
break;
401+
}
402+
case ">>>": {
403+
if (typeof lhs === "number" && typeof rhs === "number") {
404+
result = {
405+
kind: "Primitive",
406+
value: lhs >>> rhs,
407+
loc: value.loc,
408+
};
409+
}
410+
break;
411+
}
412+
case "%": {
413+
if (typeof lhs === "number" && typeof rhs === "number") {
414+
result = { kind: "Primitive", value: lhs % rhs, loc: value.loc };
415+
}
416+
break;
417+
}
418+
case "**": {
419+
if (typeof lhs === "number" && typeof rhs === "number") {
420+
result = { kind: "Primitive", value: lhs ** rhs, loc: value.loc };
421+
}
422+
break;
423+
}
372424
case "<": {
373425
if (typeof lhs === "number" && typeof rhs === "number") {
374426
result = { kind: "Primitive", value: lhs < rhs, loc: value.loc };

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations.expect.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ export const FIXTURE_ENTRYPOINT = {
2222

2323
```javascript
2424
function f() {
25-
let x;
26-
27-
x = 3 >>> 1;
28-
return x;
25+
return 1;
2926
}
3027

3128
export const FIXTURE_ENTRYPOINT = {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
2+
## Input
3+
4+
```javascript
5+
import { Stringify } from "shared-runtime";
6+
7+
function foo() {
8+
return (
9+
<Stringify
10+
value={[
11+
123.45 | 0,
12+
123.45 & 0,
13+
123.45 ^ 0,
14+
123 << 0,
15+
123 >> 0,
16+
123 >>> 0,
17+
123.45 | 1,
18+
123.45 & 1,
19+
123.45 ^ 1,
20+
123 << 1,
21+
123 >> 1,
22+
123 >>> 1,
23+
3 ** 2,
24+
3 ** 2.5,
25+
3.5 ** 2,
26+
2 ** (3 ** 0.5),
27+
4 % 2,
28+
4 % 2.5,
29+
4 % 3,
30+
4.5 % 2,
31+
]}
32+
/>
33+
);
34+
}
35+
36+
export const FIXTURE_ENTRYPOINT = {
37+
fn: foo,
38+
params: [],
39+
isComponent: false,
40+
};
41+
42+
```
43+
44+
## Code
45+
46+
```javascript
47+
import { c as _c } from "react/compiler-runtime";
48+
import { Stringify } from "shared-runtime";
49+
50+
function foo() {
51+
const $ = _c(1);
52+
let t0;
53+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
54+
t0 = (
55+
<Stringify
56+
value={[
57+
123, 0, 123, 123, 123, 123, 123, 1, 122, 246, 61, 61, 9,
58+
15.588457268119896, 12.25, 3.3219970854839125, 0, 1.5, 1, 0.5,
59+
]}
60+
/>
61+
);
62+
$[0] = t0;
63+
} else {
64+
t0 = $[0];
65+
}
66+
return t0;
67+
}
68+
69+
export const FIXTURE_ENTRYPOINT = {
70+
fn: foo,
71+
params: [],
72+
isComponent: false,
73+
};
74+
75+
```
76+
77+
### Eval output
78+
(kind: ok) <div>{"value":[123,0,123,123,123,123,123,1,122,246,61,61,9,15.588457268119896,12.25,3.3219970854839125,0,1.5,1,0.5]}</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Stringify } from "shared-runtime";
2+
3+
function foo() {
4+
return (
5+
<Stringify
6+
value={[
7+
123.45 | 0,
8+
123.45 & 0,
9+
123.45 ^ 0,
10+
123 << 0,
11+
123 >> 0,
12+
123 >>> 0,
13+
123.45 | 1,
14+
123.45 & 1,
15+
123.45 ^ 1,
16+
123 << 1,
17+
123 >> 1,
18+
123 >>> 1,
19+
3 ** 2,
20+
3 ** 2.5,
21+
3.5 ** 2,
22+
2 ** (3 ** 0.5),
23+
4 % 2,
24+
4 % 2.5,
25+
4 % 3,
26+
4.5 % 2,
27+
]}
28+
/>
29+
);
30+
}
31+
32+
export const FIXTURE_ENTRYPOINT = {
33+
fn: foo,
34+
params: [],
35+
isComponent: false,
36+
};

0 commit comments

Comments
 (0)