solidity icon indicating copy to clipboard operation
solidity copied to clipboard

yul optimizer: Expand rules for subtraction simplification

Open a1k0n opened this issue 3 years ago • 8 comments

The previous rules would create awkward negative constants, turning all instances of sub(x, 1) into add(x, not(0)) for example. This change expands the four (A+X)+B type rules from ruleset 7 into 24 combinations of addition/subtraction with constants.

It improves code size and quality in most test cases (diff in a comment below), except where there is a code-size regression, because it tries too hard to hold small constants on the stack (e.g., 4 where previously it would materialize a new not(3) each time instead), and the code ends up with a bunch of extra pop instructions at the end. I assume this could be improved elsewhere in the optimizer.

These rules were generated by expanding the ones used for addition, handling the sign correctly in each case. I wrote a utility to double-check correctness and auto-generate the C++ code to prevent manual transcription errors: https://gist.github.com/a1k0n/74c46ee8821a71a5ea0d1005515653e8

a1k0n avatar Jun 24 '22 20:06 a1k0n

Ah, looks like I need to update the --enforce-gas-cost tests...

a1k0n avatar Jun 24 '22 22:06 a1k0n

I have no idea why the legacy optimizer is changed at all...?

File name IR-optimized (%) Legacy-Optimized (%) Legacy (%)
constructor_inheritance_init_order.sol -0.355389 0 0
constructor_inheritance_init_order_2.sol -0.355389 0 0
constructor_with_params.sol -0.417266 0 0
constructor_with_params_diamond_inheritance.sol -0.419782 0 0
constructor_with_params_inheritance.sol -0.348438 0 0
byte_array_to_storage_cleanup.sol -0.62071 0 0
abiEncoderV1/abi_decode_v2_storage.sol -0.00344536 0 0
abiEncoderV1/abi_encode_calldata_slice.sol -0.0312448 0.790129 0
abiEncoderV1/struct/struct_storage_ptr.sol 0.00660561 0 0
libraries/using_library_mappings_public.sol 0.0100285 0 0
libraries/using_library_mappings_return.sol 0.00332585 0 0
libraries/internal_types_in_library.sol -0.0080156 0.0527426 0
immutable/multi_creation.sol -0.322903 0 0
immutable/use_scratch.sol -0.344286 0 0
smoke/constructor.sol -0.60559 0 0
userDefinedValueType/erc20.sol -0.395058 0 0
userDefinedValueType/calldata.sol -0.00491521 0.0146148 0
functionCall/creation_function_call_with_salt.sol -0.221061 0 0
functionCall/external_call_to_nonexisting.sol -0.1596 0 0
functionCall/failed_create.sol 3.67711 0.117054 0
functionCall/creation_function_call_with_args.sol -0.221246 0 0
functionCall/gas_and_value_brace_syntax.sol -0.741617 0 0
functionCall/external_call_to_nonexisting_debugstrings.sol -0.102408 0 0
functionCall/gas_and_value_basic.sol -0.741617 0 0
functionCall/mapping_array_internal_argument.sol -0.00268651 0 0
externalContracts/deposit_contract.sol -0.160283 -0.0974623 0
externalContracts/strings.sol -0.294947 0.832174 0
externalContracts/prbmath_signed.sol -0.174763 -0.0702974 0
externalContracts/FixedFeeRegistrar.sol -0.886485 0 0
externalContracts/base64.sol -0.273642 0.393186 0
externalContracts/prbmath_unsigned.sol -0.16234 -0.0747815 0
externalContracts/ramanujan_pi.sol -0.145168 0.0449773 0
inheritance/inherited_function_calldata_memory_interface.sol 0.401491 0 0
inheritance/value_for_constructor.sol -0.241301 0 0
various/value_complex.sol -0.122575 0 0
various/swap_in_storage_overwrite.sol 0.00182325 0 0
various/destructuring_assignment.sol 0.00334602 0 0
various/address_code.sol 0.263652 0 0
various/contract_binary_dependencies.sol -0.427456 0 0
various/erc20.sol -0.483879 0 0
various/staticcall_for_view_and_pure.sol -3.04758e-06 0 0
various/senders_balance.sol -0.253184 0 0
various/skip_dynamic_types_for_structs.sol 0.00391856 0 0
various/value_insane.sol 0.36593 0 0
array/create_memory_array.sol -0.00238421 0 0
array/bytes_length_member.sol -0.00271734 0 0
array/fixed_arrays_in_constructors.sol -0.336742 0 0
array/arrays_complex_from_and_to_storage.sol -0.00160629 0 0
array/function_array_cross_calls.sol -0.159507 -0.0712418 0
array/byte_array_transitional_2.sol -0.00890585 -0.0049091 0
array/constant_var_as_array_length.sol -0.152563 0 0
array/fixed_arrays_as_return_type.sol -0.178918 0 0
array/fixed_array_cleanup.sol -0.000644551 0.012837 0
array/dynamic_array_cleanup.sol -0.000577349 0.0121875 0
array/reusing_memory.sol -0.185121 0 0
array/dynamic_multi_array_cleanup.sol 0.0016257 0 0
array/dynamic_arrays_in_storage.sol -0.00269179 0 0
array/pop/array_pop_uint24_transition.sol -0.000632875 0.117708 0
array/pop/byte_array_pop_long_storage_empty.sol -0.0681293 0.0200322 0
array/pop/byte_array_pop_copy_long.sol 0 0.0826286 0
array/pop/byte_array_pop_masking_long.sol -0.0157195 0.0758676 0
array/pop/array_pop_uint16_transition.sol -0.00643901 0.0807655 0
array/pop/array_pop_array_transition.sol 0.0164464 0.0127331 0
array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol 0.409425 -0.0510999 0
array/delete/bytes_delete_element.sol -0.00144281 0.121254 0
array/push/array_push_struct.sol -0.00221887 0 0
array/push/nested_bytes_push.sol -0.00167436 0 0
array/push/array_push.sol -0.00269184 0 0
array/push/push_no_args_bytes.sol -0.0016341 0.117176 0
array/push/byte_array_push_transition.sol -0.136481 0 0
array/push/push_no_args_2d.sol -0.00786878 0.126487 0
array/push/array_push_nested_from_calldata.sol -0.00265882 0 0
array/push/array_push_struct_from_calldata.sol -0.00218831 -0.00217355 0
array/copying/array_copy_storage_storage_dynamic_dynamic.sol -0.0010991 0 0
array/copying/storage_memory_nested_struct.sol -0.00103033 0 0
array/copying/cleanup_during_multi_element_per_slot_copy.sol -0.0910045 0 0
array/copying/array_copy_storage_storage_struct.sol -0.00125685 0.0227695 0
array/copying/storage_memory_nested.sol -0.00145642 0.00567478 0
array/copying/array_nested_calldata_to_storage.sol -0.00616198 0 0
array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol -0.0283711 0 0
array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol -0.0134244 0 0
array/copying/array_of_struct_calldata_to_storage.sol -0.00250543 0 0
array/copying/copy_byte_array_to_storage.sol -0.0025087 0 0
array/copying/copy_removes_bytes_data.sol -0.00169123 0 0
array/copying/array_of_struct_memory_to_storage.sol -0.00253391 0 0
array/copying/array_copy_target_leftover.sol -0.00240467 0.133992 0
array/copying/array_of_function_external_storage_to_storage_dynamic.sol -0.0133824 0 0
array/copying/array_of_structs_containing_arrays_memory_to_storage.sol -0.00164621 0 0
array/copying/copy_byte_array_in_struct_to_storage.sol -0.00208993 0 0
array/copying/memory_dyn_2d_bytes_to_storage.sol -0.0023406 0.0301988 0
array/copying/storage_memory_nested_bytes.sol -0.152745 -0.000491553 0
array/copying/copy_function_internal_storage_array.sol -0.00979728 0 0
array/copying/array_copy_storage_storage_different_base_nested.sol -0.00158153 0 0
array/copying/storage_memory_nested_from_pointer.sol -0.00145642 0.00567464 0
array/copying/array_copy_storage_storage_dyn_dyn.sol -0.00269363 0 0
array/copying/array_copy_target_simple.sol -0.00102173 0.00894203 0
array/copying/array_nested_memory_to_storage.sol -0.000277818 0 0
array/copying/bytes_storage_to_storage.sol 1.20549 0.27568 0
array/copying/array_copy_target_simple_2.sol -0.00109819 0.00762497 0
array/copying/array_copy_clear_storage.sol -0.00223272 0 0
array/copying/array_storage_multi_items_per_slot.sol -0.00227388 0 0
array/copying/bytes_inside_mappings.sol 0.00347098 0 0
array/copying/storage_memory_packed_dyn.sol -0.00272393 0.0820188 0
array/copying/copying_bytes_multiassign.sol 0.0126324 0 0
array/copying/array_copy_including_array.sol -0.000525905 0.00117571 0
array/copying/array_copy_storage_storage_static_static.sol -0.00127076 0 0
array/copying/function_type_array_to_storage.sol -0.00954424 -0.00512632 0
array/copying/array_copy_storage_storage_different_base.sol -0.00133317 0 0
array/copying/array_copy_cleanup_uint40.sol 0.00340284 0 0
array/copying/array_copy_nested_array.sol -0.000434929 0 0
array/copying/calldata_array_dynamic_to_storage.sol 0.00180227 0 0
array/copying/array_copy_storage_storage_static_dynamic.sol -0.00243619 0 0
array/copying/array_copy_different_packing.sol -0.00288255 0.0122349 0
array/copying/array_copy_storage_to_memory_nested.sol -0.00432694 -0.000625176 0
array/copying/array_copy_calldata_storage.sol -0.000462732 0 0
viaYul/array_storage_length_access.sol -0.000246336 0 0
viaYul/array_storage_index_zeroed_test.sol -0.0136761 0.0387834 0
viaYul/array_storage_push_empty_length_address.sol -0.000308728 0 0
viaYul/array_storage_push_empty.sol -0.000546533 0.106111 0
viaYul/copy_struct_invalid_ir_bug.sol -0.00796467 0 0
viaYul/array_storage_index_access.sol -0.0237519 0.0347565 0
viaYul/array_memory_index_access.sol -0.0044255 1.02288 0
viaYul/array_storage_index_boundary_test.sol -0.00215987 0 0
viaYul/array_storage_push_pop.sol -0.191071 0 0
calldata/copy_from_calldata_removes_bytes_data.sol 0.00386703 0 0
state/blockhash_basic.sol -0.586404 0 0
abiEncoderV2/calldata_array.sol -0.0117098 0.807773 0
abiEncoderV2/abi_encode_v2.sol -0.00797731 0 0
abiEncoderV2/storage_array_encoding.sol -0.00886649 0 0
abiEncoderV2/abi_encode_calldata_slice.sol -0.0312448 0.790129 0
abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol -0.176417 0 0
isoltestTesting/balance_other_contract.sol -0.249558 0 0
abiencodedecode/abi_decode_simple_storage.sol -0.00220934 0 0
structs/structs.sol -0.00223159 0 0
structs/struct_memory_to_storage_function_ptr.sol -0.00271766 0 0
structs/memory_structs_nested_load.sol 0.00634478 0 0
structs/struct_delete_storage_nested_small.sol -0.00256189 0 0
structs/struct_delete_storage_with_array.sol -0.00246589 0 0
structs/struct_delete_storage_with_arrays_small.sol -0.00268832 0 0
structs/struct_copy_via_local.sol -0.00273438 0 0
structs/struct_containing_bytes_copy_and_delete.sol -0.00374254 0 0
structs/struct_copy.sol 0.00524875 0 0
structs/copy_struct_array_from_storage.sol -0.00199783 0 0
structs/conversion/recursive_storage_memory.sol -0.00154834 0 0
structs/calldata/calldata_struct_with_nested_array_to_storage.sol -0.0118321 -0.0103138 0
constructor/no_callvalue_check.sol -0.00249892 0 0
constructor/bytes_in_constructors_unpacker.sol -0.158045 0 0
constructor/arrays_in_constructors.sol -0.23343 0 0
constructor/constructor_static_array_argument.sol -0.249786 0 0
constructor/bytes_in_constructors_packer.sol -0.355527 0 0
constructor/constructor_arguments_external.sol -0.405459 0 0
events/event_dynamic_array_storage.sol -0.00264278 0 0
events/event_dynamic_array_storage_v2.sol -0.00264278 0 0
events/event_dynamic_nested_array_storage_v2.sol 0.00432094 -0.00162557 0
events/event_indexed_string.sol -0.000899607 0.0721075 0
events/event_emit_from_other_contract.sol -0.257244 0 0
salted_create/salted_create_with_value.sol -0.237942 0 0
storage/packed_storage_structs_bytes.sol -0.00226405 0 0

a1k0n avatar Jun 25 '22 01:06 a1k0n

Diving into functionCall/failed_create.sol which is apparently 3% gassier...

Apparently it's just because of all the stack shuffling attempting to preserve a 4 on the stack in slot _2.

@@ -18,47 +18,48 @@
                 /// @src 0:40:335  "contract C {..."
                 let _1 := memoryguard(0x80)
                 mstore(64, _1)
-                if iszero(lt(calldatasize(), 4))
+                let _2 := 4
+                if iszero(lt(calldatasize(), _2))
                 {
-                    let _2 := 0
-                    switch shr(224, calldataload(_2))
+                    let _3 := 0
+                    switch shr(224, calldataload(_3))
                     case 0x0c55699c {
-                        if callvalue() { revert(_2, _2) }
-                        if slt(add(calldatasize(), not(3)), _2) { revert(_2, _2) }
-                        mstore(_1, sload(_2))
+                        if callvalue() { revert(_3, _3) }
+                        if slt(sub(calldatasize(), _2), _3) { revert(_3, _3) }
+                        mstore(_1, sload(_3))
                         return(_1, 32)
                     }
                     case 0xb3de648b {
-                        if callvalue() { revert(_2, _2) }
-                        if slt(add(calldatasize(), not(3)), 32) { revert(_2, _2) }
-                        let _3 := sload(_2)
-                        if eq(_3, not(0))
-                        {
-                            mstore(_2, shl(224, 0x4e487b71))
-                            mstore(4, 0x11)
-                            revert(_2, 0x24)
+                        if callvalue() { revert(_3, _3) }
+                        if slt(sub(calldatasize(), _2), 32) { revert(_3, _3) }
+                        let _4 := sload(_3)
+                        if eq(_4, not(0))
+                        {
+                            mstore(_3, shl(224, 0x4e487b71))
+                            mstore(_2, 0x11)
+                            revert(_3, 0x24)
                         }
-                        sstore(_2, add(_3, 1))
+                        sstore(_3, add(_4, 1))
                         /// @src 0:157:181  "(new D){value: amount}()"
-                        let _4 := /** @src 0:40:335  "contract C {..." */ mload(64)
+                        let _5 := /** @src 0:40:335  "contract C {..." */ mload(64)
                         /// @src 0:157:181  "(new D){value: amount}()"
-                        let _5 := datasize("D_5")
-                        let _6 := add(_4, _5)
-                        if or(gt(_6, 0xffffffffffffffff), lt(_6, _4))
+                        let _6 := datasize("D_5")
+                        let _7 := add(_5, _6)
+                        if or(gt(_7, 0xffffffffffffffff), lt(_7, _5))
                         {
                             /// @src 0:40:335  "contract C {..."
-                            mstore(_2, shl(224, 0x4e487b71))
-                            mstore(4, 0x41)
-                            revert(_2, 0x24)
+                            mstore(_3, shl(224, 0x4e487b71))
+                            mstore(_2, 0x41)
+                            revert(_3, 0x24)
                         }
                         /// @src 0:157:181  "(new D){value: amount}()"
-                        datacopy(_4, dataoffset("D_5"), _5)
-                        let expr_address := create(/** @src 0:40:335  "contract C {..." */ calldataload(4), /** @src 0:157:181  "(new D){value: amount}()" */ _4, sub(_6, _4))
+                        datacopy(_5, dataoffset("D_5"), _6)
+                        let expr_address := create(/** @src 0:40:335  "contract C {..." */ calldataload(_2), /** @src 0:157:181  "(new D){value: amount}()" */ _5, sub(_7, _5))
                         if iszero(expr_address)
                         {
                             /// @src 0:40:335  "contract C {..."
                             let pos := mload(64)
-                            returndatacopy(pos, _2, returndatasize())
+                            returndatacopy(pos, _3, returndatasize())
                             revert(pos, returndatasize())
                         }
                         let memPos := mload(64)
@@ -67,8 +68,8 @@
                         return(memPos, 32)
                     }
                     case 0xdc9031c4 {
-                        if slt(add(calldatasize(), not(3)), 32) { revert(_2, _2) }
-                        let ret := fun_stack(calldataload(4))
+                        if slt(sub(calldatasize(), _2), 32) { revert(_3, _3) }
+                        let ret := fun_stack(calldataload(_2))
                         let memPos_1 := mload(64)
                         mstore(memPos_1, and(ret, sub(shl(160, /** @src 0:157:181  "(new D){value: amount}()" */ 1), 1)))
                         /// @src 0:40:335  "contract C {..."
@@ -136,7 +137,7 @@
                     let _6 := /** @src 0:40:335  "contract C {..." */ mload(64)
                     /// @src 0:276:297  "this.stack(depth - 1)"
                     mstore(_6, /** @src 0:40:335  "contract C {..." */ shl(226, 0x37240c71))
-                    mstore(/** @src 0:276:297  "this.stack(depth - 1)" */ add(_6, 4), /** @src 0:40:335  "contract C {..." */ add(var_depth, not(0)))
+                    mstore(/** @src 0:276:297  "this.stack(depth - 1)" */ add(_6, 4), /** @src 0:40:335  "contract C {..." */ sub(var_depth, /** @src 0:295:296  "1" */ 0x01))
                     /// @src 0:263:264  "0"
                     let _7 := 0x00
                     /// @src 0:276:297  "this.stack(depth - 1)"

a1k0n avatar Jun 25 '22 01:06 a1k0n

Rebased

Updated diffstats

File name IR-optimized (%) Legacy-Optimized (%) Legacy (%)
constructor_inheritance_init_order.sol -0.355389 0 0
constructor_inheritance_init_order_2.sol -0.355389 0 0
constructor_with_params.sol -0.417266 0 0
constructor_with_params_diamond_inheritance.sol -0.419877 0 0
constructor_with_params_inheritance.sol -0.348483 0 0
byte_array_to_storage_cleanup.sol -0.62071 0 0
abiEncoderV1/abi_decode_v2_storage.sol -0.00344536 0 0
abiEncoderV1/abi_encode_calldata_slice.sol -0.0312448 0.790129 0
abiEncoderV1/struct/struct_storage_ptr.sol 0.00660561 0 0
libraries/using_library_mappings_public.sol 0.0100285 0 0
libraries/using_library_mappings_return.sol 0.00332585 0 0
libraries/internal_types_in_library.sol -0.0080156 0.0527426 0
immutable/multi_creation.sol -0.322903 0 0
immutable/use_scratch.sol -0.344286 0 0
smoke/constructor.sol -0.60559 0 0
userDefinedValueType/erc20.sol 0.97444 0 0
userDefinedValueType/calldata.sol -0.00491521 0.0146148 0
functionCall/creation_function_call_with_salt.sol -0.221061 0 0
functionCall/external_call_to_nonexisting.sol -0.155297 0 0
functionCall/failed_create.sol 3.68142 0.117629 0
functionCall/creation_function_call_with_args.sol -0.221246 0 0
functionCall/gas_and_value_brace_syntax.sol -0.741617 0 0
functionCall/external_call_to_nonexisting_debugstrings.sol -0.10083 0 0
functionCall/gas_and_value_basic.sol -0.741617 0 0
functionCall/mapping_array_internal_argument.sol -0.00268651 0 0
externalContracts/deposit_contract.sol -0.137585 -0.0978375 0
externalContracts/strings.sol -0.188338 0.818732 0
externalContracts/prbmath_signed.sol -0.174984 -0.0703374 0
externalContracts/FixedFeeRegistrar.sol -0.886485 0 0
externalContracts/base64.sol -0.275046 0.391323 0
externalContracts/prbmath_unsigned.sol -0.162481 -0.0748272 0
externalContracts/ramanujan_pi.sol -0.153277 0.0454888 0
inheritance/inherited_function_calldata_memory_interface.sol 0.401491 0 0
inheritance/value_for_constructor.sol -0.241301 0 0
various/value_complex.sol -0.122725 0 0
various/swap_in_storage_overwrite.sol 0.00182325 0 0
various/destructuring_assignment.sol 0.00334602 0 0
various/address_code.sol 0.263652 0 0
various/contract_binary_dependencies.sol -0.427456 0 0
various/erc20.sol -0.483024 0 0
various/staticcall_for_view_and_pure.sol -3.04758e-06 0 0
various/senders_balance.sol -0.253184 0 0
various/skip_dynamic_types_for_structs.sol 0.00391856 0 0
various/value_insane.sol 0.366377 0 0
array/create_memory_array.sol -0.00238421 0 0
array/bytes_length_member.sol -0.00271734 0 0
array/fixed_arrays_in_constructors.sol -0.336742 0 0
array/arrays_complex_from_and_to_storage.sol -0.00160629 0 0
array/function_array_cross_calls.sol -0.159507 -0.0712418 0
array/byte_array_transitional_2.sol -0.00890585 -0.0049091 0
array/constant_var_as_array_length.sol -0.152563 0 0
array/fixed_arrays_as_return_type.sol -0.178918 0 0
array/fixed_array_cleanup.sol -0.000644634 0.0128342 0
array/dynamic_array_cleanup.sol -0.000577489 0.0121851 0
array/reusing_memory.sol -0.185121 0 0
array/dynamic_multi_array_cleanup.sol 0.0016257 0 0
array/dynamic_arrays_in_storage.sol -0.00269179 0 0
array/pop/array_pop_uint24_transition.sol -0.00379699 0.117696 0
array/pop/byte_array_pop_long_storage_empty.sol -0.0698423 0.0204726 0
array/pop/byte_array_pop_copy_long.sol 0 0.0826286 0
array/pop/byte_array_pop_masking_long.sol -0.0157195 0.0758676 0
array/pop/array_pop_uint16_transition.sol -0.0048291 0.0807546 0
array/pop/array_pop_array_transition.sol 0.0161832 0.012733 0
array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol 0.409425 -0.0510999 0
array/delete/bytes_delete_element.sol -0.00144281 0.121254 0
array/push/array_push_struct.sol -0.00221887 0 0
array/push/nested_bytes_push.sol -0.00167436 0 0
array/push/array_push.sol -0.00269184 0 0
array/push/push_no_args_bytes.sol -0.0016341 0.117176 0
array/push/byte_array_push_transition.sol -0.136108 0 0
array/push/push_no_args_2d.sol -0.00786878 0.126487 0
array/push/array_push_nested_from_calldata.sol -0.00265882 0 0
array/push/array_push_struct_from_calldata.sol -0.00218831 -0.00217355 0
array/copying/array_copy_storage_storage_dynamic_dynamic.sol -0.0010991 0 0
array/copying/storage_memory_nested_struct.sol -0.00103033 0 0
array/copying/cleanup_during_multi_element_per_slot_copy.sol -0.0910045 0 0
array/copying/array_copy_storage_storage_struct.sol -0.00125685 0.0227695 0
array/copying/storage_memory_nested.sol -0.00145642 0.00567478 0
array/copying/array_nested_calldata_to_storage.sol -0.00616185 0 0
array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol -0.0283711 0 0
array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol -0.0134244 0 0
array/copying/array_of_struct_calldata_to_storage.sol -0.00250543 0 0
array/copying/copy_byte_array_to_storage.sol -0.0025087 0 0
array/copying/copy_removes_bytes_data.sol -0.00169123 0 0
array/copying/array_of_struct_memory_to_storage.sol -0.00253391 0 0
array/copying/array_copy_target_leftover.sol -0.00240352 0.133984 0
array/copying/array_of_function_external_storage_to_storage_dynamic.sol -0.0133824 0 0
array/copying/array_of_structs_containing_arrays_memory_to_storage.sol -0.00164621 0 0
array/copying/copy_byte_array_in_struct_to_storage.sol -0.00208993 0 0
array/copying/memory_dyn_2d_bytes_to_storage.sol -0.0023406 0.0301988 0
array/copying/storage_memory_nested_bytes.sol -0.152745 -0.000491553 0
array/copying/copy_function_internal_storage_array.sol -0.00979728 0 0
array/copying/array_copy_storage_storage_different_base_nested.sol -0.00158153 0 0
array/copying/storage_memory_nested_from_pointer.sol -0.00145642 0.00567464 0
array/copying/array_copy_storage_storage_dyn_dyn.sol -0.00269363 0 0
array/copying/array_copy_target_simple.sol -0.00102173 0.00894203 0
array/copying/array_nested_memory_to_storage.sol -0.000277809 0 0
array/copying/bytes_storage_to_storage.sol 1.20549 0.27568 0
array/copying/array_copy_target_simple_2.sol -0.00109819 0.00762497 0
array/copying/array_copy_clear_storage.sol -0.00223272 0 0
array/copying/array_storage_multi_items_per_slot.sol -0.00227388 0 0
array/copying/bytes_inside_mappings.sol 0.00347098 0 0
array/copying/storage_memory_packed_dyn.sol -0.00272393 0.0820188 0
array/copying/copying_bytes_multiassign.sol 0.0126324 0 0
array/copying/array_copy_including_array.sol -0.000525905 0.00117571 0
array/copying/array_copy_storage_storage_static_static.sol -0.00127076 0 0
array/copying/function_type_array_to_storage.sol -0.00954424 -0.00512632 0
array/copying/array_copy_storage_storage_different_base.sol -0.00133317 0 0
array/copying/array_copy_cleanup_uint40.sol 0.00340284 0 0
array/copying/array_copy_nested_array.sol -0.000434929 0 0
array/copying/calldata_array_dynamic_to_storage.sol 0.00180227 0 0
array/copying/array_copy_storage_storage_static_dynamic.sol -0.00243619 0 0
array/copying/array_copy_different_packing.sol -0.00288255 0.0122349 0
array/copying/array_copy_storage_to_memory_nested.sol -0.00432694 -0.000625176 0
array/copying/array_copy_calldata_storage.sol -0.000462732 0 0
viaYul/array_storage_length_access.sol -0.000246336 0 0
viaYul/array_storage_index_zeroed_test.sol -0.0136779 0.0387749 0
viaYul/array_storage_push_empty_length_address.sol -0.000308728 0 0
viaYul/array_storage_push_empty.sol -0.000546533 0.106111 0
viaYul/copy_struct_invalid_ir_bug.sol -0.00796467 0 0
viaYul/array_storage_index_access.sol -0.0237519 0.0347364 0
viaYul/array_memory_index_access.sol -0.0044253 1.00573 0
viaYul/array_storage_index_boundary_test.sol -0.00215987 0 0
viaYul/array_storage_push_pop.sol -0.191071 0 0
calldata/copy_from_calldata_removes_bytes_data.sol 0.00386703 0 0
state/blockhash_basic.sol -0.586404 0 0
abiEncoderV2/calldata_array.sol -0.0117098 0.807773 0
abiEncoderV2/abi_encode_v2.sol -0.00797731 0 0
abiEncoderV2/storage_array_encoding.sol -0.00886649 0 0
abiEncoderV2/abi_encode_calldata_slice.sol -0.0312448 0.790129 0
abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol -0.176417 0 0
isoltestTesting/balance_other_contract.sol -0.249558 0 0
abiencodedecode/abi_decode_simple_storage.sol -0.00220934 0 0
structs/structs.sol -0.00223159 0 0
structs/struct_memory_to_storage_function_ptr.sol -0.00271766 0 0
structs/memory_structs_nested_load.sol 0.00634478 0 0
structs/struct_delete_storage_nested_small.sol -0.00256189 0 0
structs/struct_delete_storage_with_array.sol -0.00246589 0 0
structs/struct_delete_storage_with_arrays_small.sol -0.00268832 0 0
structs/struct_copy_via_local.sol -0.00273438 0 0
structs/struct_containing_bytes_copy_and_delete.sol -0.00374254 0 0
structs/struct_copy.sol 0.00524875 0 0
structs/copy_struct_array_from_storage.sol -0.00199783 0 0
structs/conversion/recursive_storage_memory.sol -0.00154834 0 0
structs/calldata/calldata_struct_with_nested_array_to_storage.sol -0.0118321 -0.0103138 0
constructor/no_callvalue_check.sol -0.00249892 0 0
constructor/bytes_in_constructors_unpacker.sol -0.158045 0 0
constructor/arrays_in_constructors.sol -0.23343 0 0
constructor/constructor_static_array_argument.sol -0.249786 0 0
constructor/bytes_in_constructors_packer.sol -0.355527 0 0
constructor/constructor_arguments_external.sol -0.405459 0 0
events/event_dynamic_array_storage.sol -0.00264285 0 0
events/event_dynamic_array_storage_v2.sol -0.00264285 0 0
events/event_dynamic_nested_array_storage_v2.sol 0.00108023 -0.00162543 0
events/event_indexed_string.sol -0.000899607 0.0721075 0
events/event_emit_from_other_contract.sol -0.257244 0 0
salted_create/salted_create_with_value.sol -0.22781 0 0
storage/packed_storage_structs_bytes.sol -0.00226405 0 0

The regressions on the byte array loops appear to be due to a coincidence that loops have a built-in let loopEnd := and(newLen, not(31)) and the not(31) was previously being materalized from a array_allocation_size_bytes(value) - 32 expression; it would add not(31) to dataSize instead of subtracting 32 from it, and then was able to re-ise that not(31).

a1k0n avatar Jul 11 '22 17:07 a1k0n

Huh, I guess this actually does break chainlink somehow, too.

a1k0n avatar Jul 11 '22 18:07 a1k0n

I have no idea why the legacy optimizer is changed at all...?

Some bits in the legacy codegen are implemented by inserting Yul code compiled with the new pipeline. Most prominently the ABI encoding/decoding but also some cases of copying to storage. So this is normal.

Huh, I guess this actually does break chainlink somehow, too.

I think it's an upstream change. I mean, changes in the optimizer could break it but I just saw the same failure in another PR so I strongly suspect that it's not it.

cameel avatar Jul 11 '22 19:07 cameel

The main idea of the restricted rules was to eliminate subtraction to bring all arithmetics into a normal form that uses as little subtraction as possible.

It would be nice if the rules here could be either be (1) simpler, (2) auto-generated or (3) auto-checked (as part of the CI).

chriseth avatar Jul 25 '22 13:07 chriseth

It would be nice if the rules here could be either be (1) simpler, (2) auto-generated or (3) auto-checked (as part of the CI).

Agreed. I'll see what I can do.

a1k0n avatar Jul 28 '22 23:07 a1k0n

Thank you for the PR! Unfortunately review has shown that the PR actually does the opposite of what the compiler is trying to do by design. Therefore, I'm closing it for now. Please don't hesitate and reopen it (or a new one) if it does something different.

leonardoalt avatar Aug 15 '22 14:08 leonardoalt