-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
do-while results in redundant branching instructions when compiling via IR #15442
Comments
Yes, I can confirm that this is how it works, but unfortunately I don't think we can do much about it, at least in the short term. This a case where Yul not having jumps makes it impossible to implement it more efficiently in a general case. Since Yul has no native for {} true {} {
<body>
if iszero(<condition>) { break }
} This should give you the assembly you want, however, it will break if you put To deal with this problem, we generate this instead, which is the reason for the less efficient assembly you get via IR: let firstRun := 1
for {} true {} {
if iszero(firstRun) {
if iszero(<condition>) { break }
}
firstRun := 0
<body>
} Since this affects only code that contains We'd rather do things like this in the optimizer, and we may eventually do it, but we have many potential optimizations in the pipeline and this one does not seem like it would be high on the priority list. |
Why couldn't Yul be expanded/improved? If the goal of Yul is to be simple to compile then forcing the addition of such specialized passes in the backend seems like it'd be going against that motto? Maybe wrong venue but I'd love to learn more about how the solc team thinks about language & compiler design. |
It could be extended, but at this point we're not too keen on doing that unless there is no other way to address the issue. We want Yul to be a stable target for intermediate compilation. In this particular case the benefits are not that clear-cut. It would help only this single case, and at a relatively high cost of adding a completely new construct that has to be accounted for by every tool that processes the language. Yul is very simple and we want it to stay that way. It's actually already sub-optimal that we ended up with Addressing it in the optimizer is the much preferred option. After talking it over internally, it looks like it might be doable even in the general case - if done as control flow graph simplification rather than as a transformation of Yul code. I added it to our list of Assorted Optimizer Ideas. Having said that, there's actually a different potential Yul feature we've been considering recently, which might allow us to fix this issue as well: multi-level |
Description
When using a do-while control flow statement such as in the following code:
I expect solidity to generate the relatively straight-forward & maximally efficient assembly:
This is the case when compiling with the legacy pipeline but using the IR pipeline gives you roughly the following structure:
This structure, while correct is not efficient. Digging deeper the origin of this structure becomes more apparent when looking at the generated IR:
Environment
Steps to Reproduce
Compile the following contract with viaIR
The text was updated successfully, but these errors were encountered: