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-runs for Yul mode #11708

Closed
Randall4 opened this issue Jul 27, 2021 · 3 comments · Fixed by #11717
Closed

--optimize-runs for Yul mode #11708

Randall4 opened this issue Jul 27, 2021 · 3 comments · Fixed by #11717

Comments

@Randall4
Copy link

Abstract

The Solidity compiler (solc) ignores the --optimize-runs parameter in Yul mode in favor of a list of Yul-specific optimizations. However, the default Yul optimizer list does not include runs-based optimizations that can improve gas efficiency, most notably for high numbers of expected runs.

Motivation

It seems that some, if not all, of the optimizations done on Solidity contracts expecting a high number of runs are not included when compiling for Yul, so those using solc to compile Yul contracts aimed at high run counts are penalized.

Remix has a "Runs" field for Yul contracts and is able to apply these optimizations. Here is one example:

object "RunsTest1" {
    code {
        // Deploy the contract
        datacopy(0, dataoffset("Runtime"), datasize("Runtime"))
        return(0, datasize("Runtime"))
    }
    object "Runtime" {
        code {
            let funcSel := shl(224, 0xabc12345)
            mstore(0, funcSel)
        }
    }
}

When compiled with Runs = 1 in Remix, the output becomes

600b80600e600039806000f350fe63abc1234560e01b600052
PUSH1 0xB DUP1 PUSH1 0xE PUSH1 0x0 CODECOPY DUP1 PUSH1 0x0 RETURN POP INVALID PUSH4 0xABC12345 PUSH1 0xE0 SHL PUSH1 0x0 MSTORE

When compiled with Runs = 100000 in Remix, the "PUSH4 0xABC12345 PUSH1 224 SHL" gets compressed into a PUSH32 for gas savings:

602480600e600039806000f350fe7fabc1234500000000000000000000000000000000000000000000000000000000600052
PUSH1 0x24 DUP1 PUSH1 0xE PUSH1 0x0 CODECOPY DUP1 PUSH1 0x0 RETURN POP INVALID PUSH32 0xABC1234500000000000000000000000000000000000000000000000000000000 PUSH1 0x0 MSTORE

Using solc does not give this result (command solc --yul --yul-dialect evm --optimize)

600b80600d600039806000f3fe63abc1234560e01b600052
PUSH1 0xB DUP1 PUSH1 0xD PUSH1 0x0 CODECOPY DUP1 PUSH1 0x0 RETURN INVALID PUSH4 0xABC12345 PUSH1 0xE0 SHL PUSH1 0x0 MSTORE

solc works better than Remix for a number of other optimizations (for instance, Remix will output multiple JUMPDESTs in succession). Nonetheless, the Yul compiler would benefit greatly if some of these high-runs optimizations could be included.

Specification

The --optimize-runs option should be made available in Yul mode. --optimize --optimize-runs 100000 for the Yul code above should contain the PUSH compression optimization given above, for example.

Backwards Compatibility

This feature will not introduce backward compatibility issues because the --optimize-runs option would be new for Yul mode.

@Randall4 Randall4 changed the title --optimize-runs for Yul contracts --optimize-runs for Yul mode Jul 27, 2021
@cameel
Copy link
Member

cameel commented Jul 28, 2021

I took a quick look at the CLI code and it's just that the --optimize-runs option is ignored in assembly mode (but the compiler does not report it as an invalid argument - we should really fix #11629).

So this should be very simple to fix - just pass the option down to assemble() in CommandLineInterface.cpp.

Fortunately this does not happen in Standard JSON mode and also this is the only optimizer option that is ignored without giving any feedback.

I'd classify it as a bug rather than a missing feature because this is a discrepancy with how Standard JSON works. It should have been changed back when the option was being added for Yul in Standard JSON.

@chriseth
Copy link
Contributor

Cool, thanks! Until recently, it would not have an effect anyway since it is mainly used by the opcode-based optimizer

@cameel
Copy link
Member

cameel commented Jul 28, 2021

I'd think so too but I was curious myself how far back it goes and checked that via Standard JSON - I can reproduce this difference as far back as 0.6.0. 0.5.17 is the last version that does not have it

jaa2 pushed a commit to jaa2/solidity that referenced this issue Jul 28, 2021
jaa2 added a commit to jaa2/solidity that referenced this issue Jul 28, 2021
jaa2 added a commit to jaa2/solidity that referenced this issue Jul 28, 2021
jaa2 added a commit to jaa2/solidity that referenced this issue Jul 28, 2021
jaa2 added a commit to jaa2/solidity that referenced this issue Jul 28, 2021
jaa2 added a commit to jaa2/solidity that referenced this issue Jul 28, 2021
jaa2 added a commit to jaa2/solidity that referenced this issue Jul 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants