swc icon indicating copy to clipboard operation
swc copied to clipboard

Optimize a[n]; n++ inside loopings

Open rentalhost opened this issue 11 months ago • 3 comments

Describe the feature

In cases where we manipulate a number using ++ or -- after its use, it may be possible to use it inline, reducing a few bytes (~2 bytes per use). Currently, this feature works outside of looping.

For instance:

const a = [1, 2, 3];
let n = 0;

while (n < a.length) {
  x(a[n]);
  n++;
}

Will be (prettified):

const a = [1, 2, 3];
let n = 0;

for (; n < a.length; )
  x(a[n]), n++;

Could be:

const a=[1,2,3];
let n=0;

for(;n<a.length;)
  x(a[n++]);

So n will be post-incremented, but it will return the old value to access the index at a anyway.

It is possible to think of other variations to this rule, although most cases will be simple like the first example.

const a = [1, 2, 3];

let n = 0;
let m = 0;

while (n + m < a.length) {
  x(a[n + m]); // after: x(a[n+++m++]
  n++;
  m++;
}
// My (almost) real case:
const a = [1, 2, 3, 4, 5];

let n = 0;
let m = 2;

while (m < a.length) {
  a[m] = a[n]; // after: a[m++] = a[n++]
  m++;
  n++;
}
// My real case:
const a = [1, 2, 3, 4, 5];

let m = 2;

while (m < a.length) {
  a[m] = a[m - 2]; // after: a[m] = a[m++-2]
  m++;
}

Note: currently Terser does not support this kind of optimization.

Babel plugin or link to the feature description

No response

Additional context

No response

rentalhost avatar Mar 08 '24 01:03 rentalhost

Here is a bad case:

const a = [1, 2, 3];
let n = 0;

const x = (i) => {
  if(n !== 0) {
    console.log("---");
  }
  console.log(i);
}

for (; n < a.length; )
  x(a[n]), n++;

Result:

1
---
2
---
3

"minified":

const a = [1, 2, 3];
let n = 0;

const x = (i) => {
  if(n !== 0) {
    console.log("---");
  }
  console.log(i);
}

for (; n < a.length; )
  x(a[n++]);

Result:

---
1
---
2
---
3

magic-akari avatar Mar 08 '24 03:03 magic-akari

You are right! Maybe it can check if function has scope greater then the variable.

rentalhost avatar Mar 08 '24 15:03 rentalhost

You also need to take account exceptions/try..catch statements:

function x(a: number) {
    throw "Error";
}

let n = 5;
try {
  x(n);
  n++;
} catch { }

console.log(n);

Output: 5

function x(a: number) {
    throw "Error";
}

let n = 5;
try {
  x(n++);
} catch { }

console.log(n);

Output: 6

dotjpg3141 avatar May 10 '24 10:05 dotjpg3141