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.
This commit is contained in:
Niklas Mollenhauer
2024-05-29 10:35:19 -07:00
committed by GitHub
parent 867edc6576
commit c2b45ef0dd
4 changed files with 167 additions and 4 deletions
@@ -369,6 +369,58 @@ function evaluateInstruction(
}
break;
}
case "|": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs | rhs, loc: value.loc };
}
break;
}
case "&": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs & rhs, loc: value.loc };
}
break;
}
case "^": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs ^ rhs, loc: value.loc };
}
break;
}
case "<<": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs << rhs, loc: value.loc };
}
break;
}
case ">>": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs >> rhs, loc: value.loc };
}
break;
}
case ">>>": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = {
kind: "Primitive",
value: lhs >>> rhs,
loc: value.loc,
};
}
break;
}
case "%": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs % rhs, loc: value.loc };
}
break;
}
case "**": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs ** rhs, loc: value.loc };
}
break;
}
case "<": {
if (typeof lhs === "number" && typeof rhs === "number") {
result = { kind: "Primitive", value: lhs < rhs, loc: value.loc };
@@ -22,10 +22,7 @@ export const FIXTURE_ENTRYPOINT = {
```javascript
function f() {
let x;
x = 3 >>> 1;
return x;
return 1;
}
export const FIXTURE_ENTRYPOINT = {
@@ -0,0 +1,78 @@
## Input
```javascript
import { Stringify } from "shared-runtime";
function foo() {
return (
<Stringify
value={[
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,
]}
/>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: foo,
params: [],
isComponent: false,
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime";
import { Stringify } from "shared-runtime";
function foo() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = (
<Stringify
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,
]}
/>
);
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: foo,
params: [],
isComponent: false,
};
```
### Eval output
(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>
@@ -0,0 +1,36 @@
import { Stringify } from "shared-runtime";
function foo() {
return (
<Stringify
value={[
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,
]}
/>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: foo,
params: [],
isComponent: false,
};