Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize 'POP' after 'JUMPI' #15097

Open
molly-ting opened this issue May 12, 2024 · 0 comments
Open

Optimize 'POP' after 'JUMPI' #15097

molly-ting opened this issue May 12, 2024 · 0 comments
Labels

Comments

@molly-ting
Copy link

Abstract

The opcode sequence 'DUPx ... JUMPI POP' indicates that the duplicated value is redundant and not utilized. Eliminating such redundant operations could lead to gas savings.

Description

   function and(uint256 a, uint256 b) public returns(uint256) {
        if (a > b || a > 100) {
            return a - b;
        }
        return a+b;
    }

The above function will generate the following assembly code.

...
tag_7:
        /* "condition.sol":270:277  uint256 */
      0x00
        /* "condition.sol":297:298  b */
      dup2
        /* "condition.sol":293:294  a */
      dup4
        /* "condition.sol":293:298  a > b */
      gt
        /* "condition.sol":293:309  a > b || a > 100 */
      dup1
      tag_11
      jumpi
      pop
        /* "condition.sol":306:309  100 */
      0x64
        /* "condition.sol":302:303  a */
      dup4
        /* "condition.sol":302:309  a > 100 */
      gt
        /* "condition.sol":293:309  a > b || a > 100 */
    tag_11:
        /* "condition.sol":289:348  if (a > b || a > 100) {... */
      iszero
      tag_12
      jumpi
        /* "condition.sol":336:337  b */
      dup2
        /* "condition.sol":332:333  a */
      dup4
        /* "condition.sol":332:337  a - b */
      tag_13
      swap2
      swap1
      tag_14
      jump  // in
    tag_13:
        /* "condition.sol":325:337  return a - b */
      swap1
      pop
      jump(tag_10)
        /* "condition.sol":289:348  if (a > b || a > 100) {... */
    tag_12:
        /* "condition.sol":366:367  b */
      dup2
        /* "condition.sol":364:365  a */
      dup4
        /* "condition.sol":364:367  a+b */
      tag_15
      swap2
      swap1
      tag_16
      jump  // in
…

In tag_7, there is a 'POP' just after 'JUMPI', which means the DUP value is not used. Although this value is used in the other branch(tag_11), this can be optimized by changing the order of the opcodes in these two branches.

Optimization

Specifically, moving tag_12 before tag_11 would achieve this optimization. The resulting assembly code is as follows:

...
tag_7:
        /* "condition.sol":270:277  uint256 */
      0x00
        /* "condition.sol":297:298  b */
      dup2
        /* "condition.sol":293:294  a */
      dup4
        /* "condition.sol":293:298  a > b */
      gt
        /* "condition.sol":293:309  a > b || a > 100 */
      tag_11
      jumpi
        /* "condition.sol":306:309  100 */
      0x64
        /* "condition.sol":302:303  a */
      dup4
        /* "condition.sol":302:309  a > 100 */
      gt
        /* "condition.sol":293:309  a > b || a > 100 */
      tag_11
      jumpi
    tag_12:
        /* "condition.sol":366:367  b */
      dup2
        /* "condition.sol":364:365  a */
      dup4
        /* "condition.sol":364:367  a+b */
      tag_15
      swap2
      swap1
      tag_16
      jump  // in
    tag_11:
        /* "condition.sol":336:337  b */
      dup2
        /* "condition.sol":332:333  a */
      dup4
        /* "condition.sol":332:337  a - b */
      tag_13
      swap2
      swap1
      tag_14
      jump  // in
    tag_13:
        /* "condition.sol":325:337  return a - b */
      swap1
      pop
      jump(tag_10)
        /* "condition.sol":289:348  if (a > b || a > 100) {... */
…

This could save one DUP1, ISZERO, PUSH, JUMPI for the 'a > b' condition and one DUP1, POP, ISZERO for 'a <= b'. Other cases that generate POP after JUMPI, such as an external call with try/catch which generates "DUP1 ISZERO PUSH2 JUMPI POP", may also be optimized in this way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant