Open
Description
Description
Not a bug, but rather an issue. In the following example, it is known at compile time that the else
branch is unreachable. If the loop is commented out, the legacy pipeline optimizer successfully eliminates the dead code; however, with the loop in place, the optimizer fails to do so.
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
contract Test {
function foo() external payable returns (uint256) {
if (true) {
return 0xbeef;
} else {
for (uint256 i; i < 1; ++i) {}
return 0xdead;
}
}
}
Assembly listing
Output of the command: solc --optimize --optimize-runs=250 --no-cbor-metadata --asm Test.sol
:
EVM assembly:
/* "Test.sol":756:979 contract Test {... */
mstore(0x40, 0x80)
callvalue
dup1
iszero
tag_1
jumpi
revert(0x00, 0x00)
tag_1:
pop
dataSize(sub_0)
dup1
dataOffset(sub_0)
0x00
codecopy
0x00
return
stop
sub_0: assembly {
/* "Test.sol":756:979 contract Test {... */
mstore(0x40, 0x80)
jumpi(tag_1, lt(calldatasize, 0x04))
shr(0xe0, calldataload(0x00))
dup1
0xc2985578
eq
tag_2
jumpi
tag_1:
revert(0x00, 0x00)
/* "Test.sol":776:977 function foo() external payable returns (uint256) {... */
tag_2:
/* "Test.sol":867:873 0xbeef */
0xbeef
/* "Test.sol":776:977 function foo() external payable returns (uint256) {... */
mload(0x40)
/* "#utility.yul":160:185 */
swap1
dup2
mstore
/* "#utility.yul":148:150 */
0x20
/* "#utility.yul":133:151 */
add
/* "Test.sol":776:977 function foo() external payable returns (uint256) {... */
mload(0x40)
dup1
swap2
sub
swap1
return
/* "Test.sol":904:934 for (uint256 i; i < 1; ++i) {} */
tag_10:
/* "Test.sol":924:925 1 */
0x01
/* "Test.sol":920:921 i */
dup2
/* "Test.sol":920:925 i < 1 */
lt
/* "Test.sol":904:934 for (uint256 i; i < 1; ++i) {} */
iszero
tag_11
jumpi
/* "Test.sol":927:930 ++i */
0x01
add
/* "Test.sol":904:934 for (uint256 i; i < 1; ++i) {} */
jump(tag_10)
tag_11:
pop
/* "Test.sol":954:960 0xdead */
0xdead
/* "Test.sol":947:960 return 0xdead */
swap1
pop
/* "Test.sol":776:977 function foo() external payable returns (uint256) {... */
swap1
jump // out
}
In the listing above the tags tag_10
and tag_11
are unreachable. However, tag_10
(the loop) references both itself and tag_11
, which likely prevents both tags from being removed by the legacy pipeline.
Environment
- Compiler version: 0.8.24-0.8.29
- Compilation pipeline (legacy, IR, EOF): legacy
- Target EVM version (as per compiler settings): default
- Framework/IDE (e.g. Foundry, Hardhat, Remix): N/A
- EVM execution environment / backend / blockchain client: N/A
- Operating system: Linux
Steps to Reproduce
Compile the example given at the beginning of the issue with following command:
solc --optimize --optimize-runs=250 --no-cbor-metadata --asm Test.sol