diff --git a/Changelog.md b/Changelog.md index c14ce604c24a..62dd46b621ed 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,7 +3,11 @@ Language Features: Compiler Features: +* Commandline Interface: `--optimize-runs` now also accepts values from the interval [INT64_MAX, UINT64_MAX]. +* General: Speed up SHA-256 hashing (`picosha2`). +* General: Remove support for the experimental EOF (EVM Object Format) backend. * SMTChecker: Emit a deprecation warning for the BMC engine. +* Yul Optimizer: Split large switch statements into a binary search tree of smaller switches, reducing dispatch cost from linear to logarithmic. Bugfixes: * Code Generator: Fix ICE on parenthesized custom error construction in require statement. diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index fe8288aac18f..12034614f8ec 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -43,7 +43,7 @@ struct OptimiserSettings static char constexpr DefaultYulOptimiserSteps[] = "dfDvulfnTUtnIf" // None of these can make stack problems worse - "xa[r]EscLM" // Turn into SSA and simplify + "xBa[r]EscLM" // Turn into SSA and simplify "Vcul [j]" // Reverse SSA // should have good "compilability" property here. @@ -55,7 +55,7 @@ struct OptimiserSettings "scCTUt" "vifM" // Run full inliner - "x[scCTUt] TOntnfDIul" // Perform structural simplification + "x[scCTUtB] TOntnfDIul" // Perform structural simplification "vifM" // Run full inliner "jmul[jul] VcTOcul jmul"; // Make source short and pretty diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index fbfadcde163e..8e259df55b24 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -245,6 +245,8 @@ add_library(yul optimiser/StackToMemoryMover.h optimiser/StructuralSimplifier.cpp optimiser/StructuralSimplifier.h + optimiser/SwitchSplitter.cpp + optimiser/SwitchSplitter.h optimiser/Substitution.cpp optimiser/Substitution.h optimiser/Suite.cpp diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 2c2dfe1128a1..df0183578d87 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,7 @@ std::map> const& OptimiserSuite::all SSAReverser, SSATransform, StructuralSimplifier, + SwitchSplitter, UnusedFunctionParameterPruner, UnusedPruner, VarDeclInitializer @@ -301,6 +303,7 @@ std::map const& OptimiserSuite::stepNameToAbbreviationMap() {SSAReverser::name, 'V'}, {SSATransform::name, 'a'}, {StructuralSimplifier::name, 't'}, + {SwitchSplitter::name, 'B'}, {UnusedFunctionParameterPruner::name, 'p'}, {UnusedPruner::name, 'u'}, {VarDeclInitializer::name, 'd'}, diff --git a/libyul/optimiser/SwitchSplitter.cpp b/libyul/optimiser/SwitchSplitter.cpp new file mode 100644 index 000000000000..640623ba059a --- /dev/null +++ b/libyul/optimiser/SwitchSplitter.cpp @@ -0,0 +1,185 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::yul; + +using OptionalStatements = std::optional>; + +void SwitchSplitter::run(OptimiserStepContext& _context, Block& _ast) +{ + SwitchSplitter{_context}(_ast); +} + +SwitchSplitter::SwitchSplitter(OptimiserStepContext const& _context): + // nullopt means creation code + m_runs(_context.expectedExecutionsPerDeployment.value_or(1)), + m_isCreation(!_context.expectedExecutionsPerDeployment) +{ + if (auto const* evmDialect = dynamic_cast(&_context.dialect)) + { + m_gtHandle = evmDialect->findBuiltin("gt"); + m_evmVersion = evmDialect->evmVersion(); + } +} + +void SwitchSplitter::operator()(Block& _block) +{ + simplify(_block.statements); +} + +void SwitchSplitter::simplify(std::vector& _statements) +{ + iterateReplacing( + _statements, + [&](Statement& _stmt) -> OptionalStatements + { + if (auto* sw = std::get_if(&_stmt)) + if (auto result = tryTransform(*sw)) + { + simplify(*result); + return result; + } + this->visit(_stmt); + return {}; + } + ); +} + +std::optional> SwitchSplitter::tryTransform(Switch& _switch) +{ + if (!m_gtHandle) + return {}; + + // Only switches on a simple identifier are transformed; without ExpressionSplitter + // having run first, more complex expressions are left untouched here. + auto const* exprIdent = std::get_if(_switch.expression.get()); + if (!exprIdent) + return {}; + + // Separate literal cases from the default case. + std::vector literalCases; + Block const* defaultBody = nullptr; + static Block const emptyBlock{}; + + for (auto const& c: _switch.cases) + if (c.value) + literalCases.push_back(&c); + else + defaultBody = &c.body; + + if (!defaultBody) + defaultBody = &emptyBlock; + + std::sort(literalCases.begin(), literalCases.end(), [](Case const* _a, Case const* _b) { + return _a->value->value.value() < _b->value->value.value(); + }); + + // Only transform if the top-level split is profitable. + if (!shouldSplit(literalCases, *defaultBody)) + return {}; + + return buildTree(literalCases, *exprIdent, *defaultBody, _switch.debugData); +} + +std::vector SwitchSplitter::buildTree( + std::span _cases, + Identifier const& _expr, + Block const& _defaultBody, + langutil::DebugData::ConstPtr _debugData +) +{ + size_t n = _cases.size(); + bool const hasDefault = !_defaultBody.statements.empty(); + + if (!shouldSplit(_cases, _defaultBody)) + { + // Leaf: small switch; default case added only when present. + std::vector switchCases; + switchCases.reserve(n + (hasDefault ? 1 : 0)); + for (auto const* c: _cases) + switchCases.push_back(Case{ + c->debugData, + std::make_unique(*c->value), + ASTCopier{}.translate(c->body) + }); + if (hasDefault) + switchCases.push_back(Case{_debugData, nullptr, ASTCopier{}.translate(_defaultBody)}); + std::vector result; + result.emplace_back(Switch{_debugData, std::make_unique(_expr), std::move(switchCases)}); + return result; + } + + // Split: pivot stays in lower half → switch gt(expr, pivot) case 1 { upper } default { lower }. + size_t pivotIdx = (n - 1) / 2; + Case const* pivot = _cases[pivotIdx]; + + auto lowerStmts = buildTree(_cases.subspan(0, pivotIdx + 1), _expr, _defaultBody, _debugData); + auto upperStmts = buildTree(_cases.subspan(pivotIdx + 1), _expr, _defaultBody, _debugData); + + std::vector switchCases; + switchCases.reserve(2); + switchCases.push_back(Case{ + _debugData, + std::make_unique(Literal{_debugData, LiteralKind::Number, LiteralValue{u256(1)}}), + Block{_debugData, std::move(upperStmts)} + }); + switchCases.push_back(Case{_debugData, nullptr, Block{_debugData, std::move(lowerStmts)}}); + + std::vector result; + result.emplace_back(Switch{ + _debugData, + std::make_unique(FunctionCall{ + _debugData, + BuiltinName{_debugData, *m_gtHandle}, + {Expression{_expr}, Expression{*pivot->value}} + }), + std::move(switchCases) + }); + return result; +} + +bool SwitchSplitter::shouldSplit(std::span _cases, Block const& _defaultBody) const +{ + size_t const n = _cases.size(); + if (n <= 4) + return false; + + // Overhead scales with the fulcrum's actual encoding size. + size_t const pivotIdx = (n - 1) / 2; + unsigned const fulcrumSize = numberEncodingSize(_cases[pivotIdx]->value->value.value()); + uint64_t const overhead = 13 + fulcrumSize + CodeSize::codeSize(_defaultBody); + return m_runs * 6 * (n - 4) > evmasm::GasMeter::dataGas(overhead, m_isCreation, m_evmVersion); +} diff --git a/libyul/optimiser/SwitchSplitter.h b/libyul/optimiser/SwitchSplitter.h new file mode 100644 index 000000000000..01dd9cc1a040 --- /dev/null +++ b/libyul/optimiser/SwitchSplitter.h @@ -0,0 +1,98 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace solidity::yul +{ + +/** + * Transforms a large Yul switch statement into a binary search tree of nested switches, + * reducing runtime dispatch from O(n) to O(log n). + * + * The transformation is applied only when the runtime gas savings over + * expectedExecutionsPerDeployment executions outweigh the extra code size (creation gas): + * runs * 6 * (n - 4) > (13 + f + k) * createDataGas + * where f is the encoding size in bytes of the fulcrum (pivot) literal and k is the + * CodeSize estimate for the default body (proxy for bytecode size). The 13-byte base + * overhead comes from the gt-switch structure; k accounts for each split duplicating + * the default body into one additional leaf. + * + * This mirrors the formula ContractCompiler::appendInternalSelector uses to decide + * whether to binary-split the legacy function selector dispatch (ContractCompiler.cpp, + * see the comment above that function for the full per-opcode derivation of the 6 and 4 + * constants). That formula fixes the split overhead at 17 bytes because selectors are + * always 4-byte literals; here the fulcrum can be any literal, so the fixed 4 is broken + * out into f and the remaining 13-byte base overhead is unchanged (13 + 4 == 17). + * + * Applied recursively: each sub-slice re-evaluates the formula. + * The default case body is duplicated into each leaf branch when present. + * + * Prerequisite: Disambiguator. + * + * ExpressionSplitter is recommended, though not required for correctness: this step only + * transforms switches whose expression is already a simple identifier, so without + * ExpressionSplitter having run first, switches with more complex expressions are simply + * left untouched rather than causing incorrect output. + * + * Important: Can only be used on EVM code. + */ +class SwitchSplitter: public ASTModifier +{ +public: + static constexpr char const* name{"SwitchSplitter"}; + static void run(OptimiserStepContext& _context, Block& _ast); + + using ASTModifier::operator(); + void operator()(Block& _block) override; + +private: + explicit SwitchSplitter(OptimiserStepContext const& _context); + + void simplify(std::vector& _statements); + + // Returns replacement statements if the switch should be transformed, nullopt otherwise. + std::optional> tryTransform(Switch& _switch); + + // Recursively builds the binary search tree for a sorted, non-empty slice of literal cases. + std::vector buildTree( + std::span _cases, + Identifier const& _expr, + Block const& _defaultBody, + langutil::DebugData::ConstPtr _debugData + ); + + bool shouldSplit(std::span _cases, Block const& _defaultBody) const; + + std::optional m_gtHandle; + size_t m_runs = 0; + bool m_isCreation = false; + langutil::EVMVersion m_evmVersion; +}; + +} diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index c26038e0b971..c73348250828 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -44,6 +44,7 @@ function zeppelin_test local repo="https://github.com/OpenZeppelin/openzeppelin-contracts.git" local ref="" local config_file="hardhat.config.js" + local extra_optimizer_settings="runs: 175" local compile_only_presets=( #ir-no-optimize # Compilation fails with "Contract initcode size is 49410 bytes and exceeds 49152 bytes (a limit introduced in Shanghai)." @@ -129,13 +130,13 @@ EOF neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" - force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" + force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "" "$CURRENT_EVM_VERSION" "" "$extra_optimizer_settings" npm install npm install hardhat replace_version_pragmas for preset in $SELECTED_PRESETS; do - hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn + hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "" "" "$extra_optimizer_settings" store_benchmark_report hardhat zeppelin "$repo" "$preset" done } diff --git a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol index f66e7fa46dcf..787eee693f0c 100644 --- a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol @@ -41,10 +41,10 @@ contract c { // ---- // getLengths() -> 0, 0 // setLengths(uint256,uint256): 48, 49 -> -// gas irOptimized: 112674 +// gas irOptimized: 112710 // gas legacy: 108272 // gas legacyOptimized: 100268 -// gas ssaCFGOptimized: 112668 +// gas ssaCFGOptimized: 112699 // getLengths() -> 48, 49 // setIDStatic(uint256): 11 -> // getID(uint256): 2 -> 11 diff --git a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol index 1454e3ebe507..a23caf51807e 100644 --- a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol +++ b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol @@ -40,19 +40,19 @@ contract C { // copyFromStorageShort() // x() -> 0x20, 3, 0x6162630000000000000000000000000000000000000000000000000000000000 // copyFromStorageLong() -// gas irOptimized: 121092 +// gas irOptimized: 120863 // gas legacy: 121904 // gas legacyOptimized: 121393 -// gas ssaCFGOptimized: 121077 +// gas ssaCFGOptimized: 120849 // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // copyToStorage() // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // y() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // del() -// gas irOptimized: 29404 +// gas irOptimized: 29292 // x() -> 0x20, 0x00 // invalidateXLong() -// gas irOptimized: 47028 +// gas irOptimized: 46985 // x() -> FAILURE, hex"4e487b71", 0x22 // abiEncode() -> FAILURE, hex"4e487b71", 0x22 // abiEncodePacked() -> FAILURE, hex"4e487b71", 0x22 diff --git a/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol index ca46ecc7e0bf..a03d10075487 100644 --- a/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol +++ b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol @@ -88,10 +88,10 @@ contract C { // arrayLength() -> 0 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // fillArray() -// gas irOptimized: 197352 +// gas irOptimized: 197292 // gas legacy: 220574 // gas legacyOptimized: 206839 -// gas ssaCFGOptimized: 197540 +// gas ssaCFGOptimized: 197481 // arrayLength() -> 96 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // getArrayBytes(uint256,uint256): 0, 5 -> 0x20, 5, 0x0102030405000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 422373e37cdd..b6764e3ea00f 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -74,17 +74,17 @@ contract FixedFeeRegistrar is Registrar { } // ---- // constructor() -// gas irOptimized: 78076 -// gas irOptimized code: 307400 +// gas irOptimized: 77804 +// gas irOptimized code: 309400 // gas legacy: 115395 // gas legacy code: 792400 // gas legacyOptimized: 84598 // gas legacyOptimized code: 388000 -// gas ssaCFGOptimized: 78844 -// gas ssaCFGOptimized code: 321800 +// gas ssaCFGOptimized: 79092 +// gas ssaCFGOptimized code: 325200 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 -// gas irOptimized: 45741 +// gas irOptimized: 45769 // gas legacy: 46698 // gas legacyOptimized: 45948 // owner(string): 0x20, 3, "abc" -> 0x1212121212121212121212121212120000000012 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_constructor_switch.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_constructor_switch.sol new file mode 100644 index 000000000000..283232c9bb4f --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_constructor_switch.sol @@ -0,0 +1,29 @@ +==== ExternalSource: _prbmath/PRBMathCommon.sol ==== +==== ExternalSource: _prbmath/PRBMathUD60x18.sol ==== +==== Source: prbmath.sol ==== +import "_prbmath/PRBMathUD60x18.sol"; + +// Regression test for SwitchSplitter's handling of switches inside creation code: +// PRBMathUD60x18.log10 contains a 39-case switch, only ever called here from the +// constructor, so its dispatch is compiled as part of the creation code rather than +// the runtime code. +contract test { + using PRBMathUD60x18 for uint256; + + uint256 public immutable result; + + constructor(uint256 x) { + result = x.log10(); + } +} +// ---- +// constructor(): 1000000000000000000000 +// gas irOptimized: 108615 +// gas irOptimized code: 18600 +// gas legacy: 118230 +// gas legacy code: 29800 +// gas legacyOptimized: 109471 +// gas legacyOptimized code: 19600 +// gas ssaCFGOptimized: 105833 +// gas ssaCFGOptimized code: 17200 +// result() -> 3000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index b94076ac543e..d3cb2450e342 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -48,51 +48,51 @@ contract test { } // ---- // constructor() -// gas irOptimized: 177903 -// gas irOptimized code: 1674400 +// gas irOptimized: 183786 +// gas irOptimized code: 1760800 // gas legacy: 209723 // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 -// gas ssaCFGOptimized: 175028 -// gas ssaCFGOptimized code: 1639200 +// gas ssaCFGOptimized: 180903 +// gas ssaCFGOptimized code: 1725000 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 -// gas irOptimized: 22045 +// gas irOptimized: 22073 // gas legacy: 22736 // gas legacyOptimized: 22264 // exp(int256): 3141592653589793238 -> 23140692632779268978 -// gas irOptimized: 24452 +// gas irOptimized: 24370 // gas legacy: 25124 // gas legacyOptimized: 24351 // exp2(int256): 3141592653589793238 -> 8824977827076287620 -// gas irOptimized: 24162 +// gas irOptimized: 24081 // gas legacy: 24787 // gas legacyOptimized: 24105 // gm(int256,int256): 3141592653589793238, 88714123 -> 16694419339601 -// gas irOptimized: 22805 +// gas irOptimized: 22724 // gas legacy: 23202 // gas legacyOptimized: 22685 // log10(int256): 3141592653589793238 -> 4971498726941338506 -// gas irOptimized: 30300 +// gas irOptimized: 28859 // gas legacy: 32841 // gas legacyOptimized: 30249 // log2(int256): 3141592653589793238 -> 1651496129472318782 -// gas irOptimized: 28566 +// gas irOptimized: 28485 // gas legacy: 30979 // gas legacyOptimized: 28357 // mul(int256,int256): 3141592653589793238, 88714123 -> 278703637 -// gas irOptimized: 22147 +// gas irOptimized: 22066 // gas legacy: 22775 // gas legacyOptimized: 22288 // pow(int256,uint256): 3141592653589793238, 5 -> 306019684785281453040 -// gas irOptimized: 22488 +// gas irOptimized: 22516 // gas legacy: 23453 // gas legacyOptimized: 22921 // sqrt(int256): 3141592653589793238 -> 1772453850905516027 -// gas irOptimized: 22458 +// gas irOptimized: 22486 // gas legacy: 22784 // gas legacyOptimized: 22420 // benchmark(int256): 3141592653589793238 -> 998882724338592125, 1000000000000000000, 1000000000000000000 -// gas irOptimized: 34893 +// gas irOptimized: 34921 // gas legacy: 35244 // gas legacyOptimized: 33996 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index d9f5d75fea9d..789be5d9d833 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -48,51 +48,51 @@ contract test { } // ---- // constructor() -// gas irOptimized: 170626 -// gas irOptimized code: 1577400 +// gas irOptimized: 175855 +// gas irOptimized code: 1650800 // gas legacy: 195206 // gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 -// gas ssaCFGOptimized: 167591 -// gas ssaCFGOptimized code: 1544400 +// gas ssaCFGOptimized: 173407 +// gas ssaCFGOptimized code: 1621000 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 -// gas irOptimized: 21912 +// gas irOptimized: 21831 // gas legacy: 22475 // gas legacyOptimized: 21998 // exp(uint256): 3141592653589793238 -> 23140692632779268978 -// gas irOptimized: 24334 +// gas irOptimized: 24261 // gas legacy: 25026 // gas legacyOptimized: 24253 // exp2(uint256): 3141592653589793238 -> 8824977827076287620 -// gas irOptimized: 24115 +// gas irOptimized: 24042 // gas legacy: 24738 // gas legacyOptimized: 24058 // gm(uint256,uint256): 3141592653589793238, 88714123 -> 16694419339601 -// gas irOptimized: 22786 +// gas irOptimized: 22819 // gas legacy: 23244 // gas legacyOptimized: 22727 // log10(uint256): 3141592653589793238 -> 0x44fe4fc084a52b8a -// gas irOptimized: 30079 +// gas irOptimized: 28518 // gas legacy: 32808 // gas legacyOptimized: 29912 // log2(uint256): 3141592653589793238 -> 1651496129472318782 -// gas irOptimized: 28107 +// gas irOptimized: 28143 // gas legacy: 30900 // gas legacyOptimized: 27994 // mul(uint256,uint256): 3141592653589793238, 88714123 -> 278703637 -// gas irOptimized: 21988 +// gas irOptimized: 21915 // gas legacy: 22581 // gas legacyOptimized: 22089 // pow(uint256,uint256): 3141592653589793238, 5 -> 306019684785281453040 -// gas irOptimized: 22316 +// gas irOptimized: 22352 // gas legacy: 23196 // gas legacyOptimized: 22652 // sqrt(uint256): 3141592653589793238 -> 1772453850905516027 -// gas irOptimized: 22481 +// gas irOptimized: 22517 // gas legacy: 22803 // gas legacyOptimized: 22439 // benchmark(uint256): 3141592653589793238 -> 998882724338592125, 1000000000000000000, 1000000000000000000 -// gas irOptimized: 33961 +// gas irOptimized: 33997 // gas legacy: 34006 // gas legacyOptimized: 32724 diff --git a/test/libsolidity/semanticTests/externalContracts/switchsplitter_constructor_switch.sol b/test/libsolidity/semanticTests/externalContracts/switchsplitter_constructor_switch.sol new file mode 100644 index 000000000000..6235c62230b3 --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/switchsplitter_constructor_switch.sol @@ -0,0 +1,72 @@ +// Regression test: a switch reached only from the constructor, with enough small +// literal cases that SwitchSplitter should split it even in creation code. +contract test { + uint256 public immutable result; + + constructor(uint256 x) { + uint256 r; + assembly { + switch x + case 1 { r := 10 } + case 2 { r := 20 } + case 3 { r := 30 } + case 4 { r := 40 } + case 5 { r := 50 } + case 6 { r := 60 } + case 7 { r := 70 } + case 8 { r := 80 } + case 9 { r := 90 } + case 10 { r := 100 } + case 11 { r := 110 } + case 12 { r := 120 } + case 13 { r := 130 } + case 14 { r := 140 } + case 15 { r := 150 } + case 16 { r := 160 } + case 17 { r := 170 } + case 18 { r := 180 } + case 19 { r := 190 } + case 20 { r := 200 } + case 21 { r := 210 } + case 22 { r := 220 } + case 23 { r := 230 } + case 24 { r := 240 } + case 25 { r := 250 } + case 26 { r := 260 } + case 27 { r := 270 } + case 28 { r := 280 } + case 29 { r := 290 } + case 30 { r := 300 } + case 31 { r := 310 } + case 32 { r := 320 } + case 33 { r := 330 } + case 34 { r := 340 } + case 35 { r := 350 } + case 36 { r := 360 } + case 37 { r := 370 } + case 38 { r := 380 } + case 39 { r := 390 } + case 40 { r := 400 } + case 41 { r := 410 } + case 42 { r := 420 } + case 43 { r := 430 } + case 44 { r := 440 } + case 45 { r := 450 } + case 46 { r := 460 } + case 47 { r := 470 } + case 48 { r := 480 } + } + result = r; + } +} +// ---- +// constructor(): 24 +// gas irOptimized: 70450 +// gas irOptimized code: 18600 +// gas legacy: 72499 +// gas legacy code: 29800 +// gas legacyOptimized: 70165 +// gas legacyOptimized code: 19600 +// gas ssaCFGOptimized: 68966 +// gas ssaCFGOptimized code: 17200 +// result() -> 240 diff --git a/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol b/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol index c75fb7ccba22..3f9972ac30fb 100644 --- a/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol +++ b/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol @@ -68,17 +68,17 @@ contract C { // getSourceAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // getDestAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fillSource() -// gas irOptimized: 135018 +// gas irOptimized: 134959 // gas legacy: 146851 // gas legacyOptimized: 137549 -// gas ssaCFGOptimized: 137978 +// gas ssaCFGOptimized: 137919 // canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // getSourceAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 // fillDest() -// gas irOptimized: 248706 +// gas irOptimized: 248731 // gas legacy: 272468 // gas legacyOptimized: 253871 -// gas ssaCFGOptimized: 254266 +// gas ssaCFGOptimized: 254291 // canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // getSourceAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 // getDestAsUint() -> 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol index 64427e6e3f74..9d3a2c977f2e 100644 --- a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol @@ -98,92 +98,92 @@ contract C { // ---- // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -// gas irOptimized: 113169 +// gas irOptimized: 113102 // gas legacy: 120742 // gas legacyOptimized: 112518 -// gas ssaCFGOptimized: 113252 +// gas ssaCFGOptimized: 113190 // destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -// gas irOptimized: 113078 +// gas irOptimized: 113098 // gas legacy: 120738 // gas legacyOptimized: 112505 -// gas ssaCFGOptimized: 113161 +// gas ssaCFGOptimized: 113186 // fillBoundaryArray() -// gas irOptimized: 912522 +// gas irOptimized: 912455 // gas legacy: 930728 // gas legacyOptimized: 916628 -// gas ssaCFGOptimized: 915317 +// gas ssaCFGOptimized: 915255 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true -// gas irOptimized: 113169 +// gas irOptimized: 113102 // gas legacy: 120742 // gas legacyOptimized: 112518 -// gas ssaCFGOptimized: 113252 +// gas ssaCFGOptimized: 113190 // destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -// gas irOptimized: 113078 +// gas irOptimized: 113098 // gas legacy: 120738 // gas legacyOptimized: 112505 -// gas ssaCFGOptimized: 113161 +// gas ssaCFGOptimized: 113186 // copyFromBoundary() -// gas irOptimized: 994579 +// gas irOptimized: 994599 // gas legacy: 1023407 // gas legacyOptimized: 994746 -// gas ssaCFGOptimized: 996288 +// gas ssaCFGOptimized: 996313 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true -// gas irOptimized: 113169 +// gas irOptimized: 113102 // gas legacy: 120742 // gas legacyOptimized: 112518 -// gas ssaCFGOptimized: 113252 +// gas ssaCFGOptimized: 113190 // destArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true -// gas irOptimized: 113078 +// gas irOptimized: 113098 // gas legacy: 120738 // gas legacyOptimized: 112505 -// gas ssaCFGOptimized: 113161 +// gas ssaCFGOptimized: 113186 // fillDestArray() -// gas irOptimized: 200426 +// gas irOptimized: 200443 // gas legacy: 218746 // gas legacyOptimized: 204648 -// gas ssaCFGOptimized: 203221 +// gas ssaCFGOptimized: 203193 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true -// gas irOptimized: 113169 +// gas irOptimized: 113102 // gas legacy: 120742 // gas legacyOptimized: 112518 -// gas ssaCFGOptimized: 113252 +// gas ssaCFGOptimized: 113190 // destArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true -// gas irOptimized: 113078 +// gas irOptimized: 113098 // gas legacy: 120738 // gas legacyOptimized: 112505 -// gas ssaCFGOptimized: 113161 +// gas ssaCFGOptimized: 113186 // copyToBoundary() -// gas irOptimized: 282623 +// gas irOptimized: 282556 // gas legacy: 311362 // gas legacyOptimized: 282712 -// gas ssaCFGOptimized: 284332 +// gas ssaCFGOptimized: 284270 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true -// gas irOptimized: 113169 +// gas irOptimized: 113102 // gas legacy: 120742 // gas legacyOptimized: 112518 -// gas ssaCFGOptimized: 113252 +// gas ssaCFGOptimized: 113190 // destArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true -// gas irOptimized: 113078 +// gas irOptimized: 113098 // gas legacy: 120738 // gas legacyOptimized: 112505 -// gas ssaCFGOptimized: 113161 +// gas ssaCFGOptimized: 113186 // deleteBoundaryArray() -// gas irOptimized: 177968 +// gas irOptimized: 177913 // gas legacy: 180995 // gas legacyOptimized: 178182 -// gas ssaCFGOptimized: 177963 +// gas ssaCFGOptimized: 177913 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -// gas irOptimized: 113169 +// gas irOptimized: 113102 // gas legacy: 120742 // gas legacyOptimized: 112518 -// gas ssaCFGOptimized: 113252 +// gas ssaCFGOptimized: 113190 // destArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true -// gas irOptimized: 113078 +// gas irOptimized: 113098 // gas legacy: 120738 // gas legacyOptimized: 112505 -// gas ssaCFGOptimized: 113161 +// gas ssaCFGOptimized: 113186 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol index 7e12cd6a6a1b..1453e4ef722b 100644 --- a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol @@ -92,42 +92,42 @@ contract C { // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fillBoundaryArray() -// gas irOptimized: 688719 +// gas irOptimized: 688652 // gas legacy: 700075 // gas legacyOptimized: 691605 -// gas ssaCFGOptimized: 688794 +// gas ssaCFGOptimized: 688732 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 // destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // copyFromBoundary() -// gas irOptimized: 748779 +// gas irOptimized: 748799 // gas legacy: 767297 // gas legacyOptimized: 748756 -// gas ssaCFGOptimized: 748798 +// gas ssaCFGOptimized: 748823 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 // destArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 // fillDestArray() -// gas irOptimized: 175623 +// gas irOptimized: 175640 // gas legacy: 187093 // gas legacyOptimized: 178625 -// gas ssaCFGOptimized: 175698 +// gas ssaCFGOptimized: 175580 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 // destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 // copyToBoundary() -// gas irOptimized: 235823 +// gas irOptimized: 235756 // gas legacy: 254252 // gas legacyOptimized: 235722 -// gas ssaCFGOptimized: 235842 +// gas ssaCFGOptimized: 235780 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 // destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 // deleteBoundaryArray() -// gas irOptimized: 137824 +// gas irOptimized: 137769 // gas legacy: 137971 // gas legacyOptimized: 137750 -// gas ssaCFGOptimized: 137819 +// gas ssaCFGOptimized: 137769 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol index 13c4634fb1ad..0b364e5b129d 100644 --- a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol @@ -96,18 +96,18 @@ contract C { // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fillBoundaryArray() -// gas irOptimized: 248990 +// gas irOptimized: 248923 // gas legacy: 272856 // gas legacyOptimized: 253856 -// gas ssaCFGOptimized: 254545 +// gas ssaCFGOptimized: 254483 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 // destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // copyFromBoundary() -// gas irOptimized: 274279 +// gas irOptimized: 274299 // gas legacy: 298927 // gas legacyOptimized: 272256 -// gas ssaCFGOptimized: 275618 +// gas ssaCFGOptimized: 275643 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 // destArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 @@ -118,10 +118,10 @@ contract C { // destArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 // gas legacy: 59729 // copyToBoundary() -// gas irOptimized: 103323 +// gas irOptimized: 103256 // gas legacy: 127882 // gas legacyOptimized: 101222 -// gas ssaCFGOptimized: 104662 +// gas ssaCFGOptimized: 104600 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 // destArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol index 168c67b6de02..8dfa48c0d469 100644 --- a/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol @@ -31,10 +31,10 @@ contract D is A, B, C layout at 42 { } // ---- // test() -> 1, 2, 3, 5 -// gas irOptimized: 110112 +// gas irOptimized: 110052 // gas legacy: 111881 // gas legacyOptimized: 110945 -// gas ssaCFGOptimized: 110209 +// gas ssaCFGOptimized: 110150 // x() -> 1 // y() -> 2 // w() -> 3 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol index 4127e47934fc..2ba4333d39b3 100644 --- a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol @@ -34,18 +34,18 @@ contract C is A layout at 42 { } // ---- // initA() -> 1, 2, 3 -// gas irOptimized: 111986 +// gas irOptimized: 111926 // gas legacy: 111679 // gas legacyOptimized: 111150 -// gas ssaCFGOptimized: 111949 +// gas ssaCFGOptimized: 111890 // arrayA(uint256): 0 -> 1 // arrayALength() -> 3 // arrayCLength() -> 0 // initCFromAInReverse() -> 3, 2, 1 -// gas irOptimized: 121281 +// gas irOptimized: 121309 // gas legacy: 121937 // gas legacyOptimized: 120853 -// gas ssaCFGOptimized: 121205 +// gas ssaCFGOptimized: 121233 // clearA() -> // arrayC(uint256): 0 -> 3 // arrayALength() -> 0 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 23cb720ade00..bad614d35fe7 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -113,38 +113,38 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 121322 -// gas irOptimized code: 234600 +// gas irOptimized: 121410 +// gas irOptimized code: 236600 // gas legacy: 163350 // gas legacy code: 671400 // gas legacyOptimized: 127464 // gas legacyOptimized code: 285400 -// gas ssaCFGOptimized: 121536 -// gas ssaCFGOptimized code: 237200 +// gas ssaCFGOptimized: 121688 +// gas ssaCFGOptimized code: 240000 // totalSupply() -> 20 -// gas irOptimized: 23334 +// gas irOptimized: 23370 // gas legacy: 23645 // gas legacyOptimized: 23367 // transfer(address,uint256): 2, 5 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x05 -// gas irOptimized: 50997 +// gas irOptimized: 50946 // gas legacy: 52323 // gas legacyOptimized: 51380 // decreaseAllowance(address,uint256): 2, 0 -> true // ~ emit Approval(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x00 -// gas irOptimized: 26054 +// gas irOptimized: 26003 // gas legacy: 27165 // gas legacyOptimized: 26320 // decreaseAllowance(address,uint256): 2, 1 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 23954 +// gas irOptimized: 23903 // gas legacy: 24500 // gas legacyOptimized: 24076 // transfer(address,uint256): 2, 14 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x0e -// gas irOptimized: 33897 +// gas irOptimized: 33846 // gas legacy: 35223 // gas legacyOptimized: 34280 // transfer(address,uint256): 2, 2 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 23990 +// gas irOptimized: 23939 // gas legacy: 24483 // gas legacyOptimized: 24072 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index e68abd8864e6..563c25c22b0e 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -96,38 +96,38 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 121632 -// gas irOptimized code: 236800 +// gas irOptimized: 121762 +// gas irOptimized code: 238800 // gas legacy: 159957 // gas legacy code: 647600 // gas legacyOptimized: 126934 // gas legacyOptimized code: 282000 -// gas ssaCFGOptimized: 122072 -// gas ssaCFGOptimized code: 241600 +// gas ssaCFGOptimized: 122266 +// gas ssaCFGOptimized code: 244400 // totalSupply() -> 20 -// gas irOptimized: 23334 +// gas irOptimized: 23370 // gas legacy: 23519 // gas legacyOptimized: 23367 // transfer(address,uint256): 2, 5 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x05 -// gas irOptimized: 51054 +// gas irOptimized: 51003 // gas legacy: 52073 // gas legacyOptimized: 51298 // decreaseAllowance(address,uint256): 2, 0 -> true // ~ emit Approval(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x00 -// gas irOptimized: 26087 +// gas irOptimized: 26036 // gas legacy: 26977 // gas legacyOptimized: 26279 // decreaseAllowance(address,uint256): 2, 1 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 23981 +// gas irOptimized: 23930 // gas legacy: 24462 // gas legacyOptimized: 24056 // transfer(address,uint256): 2, 14 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x0e -// gas irOptimized: 33954 +// gas irOptimized: 33903 // gas legacy: 34973 // gas legacyOptimized: 34198 // transfer(address,uint256): 2, 2 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 24020 +// gas irOptimized: 23969 // gas legacy: 24445 // gas legacyOptimized: 24052 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol index 62d4efa01130..4dda52b9a697 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol @@ -64,14 +64,14 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 67028 -// gas irOptimized code: 175400 +// gas irOptimized: 67200 +// gas irOptimized code: 177400 // gas legacy: 76227 // gas legacy code: 298200 // gas legacyOptimized: 66516 // gas legacyOptimized code: 168000 -// gas ssaCFGOptimized: 66800 -// gas ssaCFGOptimized code: 172400 +// gas ssaCFGOptimized: 67103 +// gas ssaCFGOptimized code: 175800 // exists() -> false // test_create_and_terminate() -> // exists() -> false diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index 091aa86f65b2..2b4cf78db95b 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -82,24 +82,24 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 132974 -// gas irOptimized code: 293800 +// gas irOptimized: 133122 +// gas irOptimized code: 295800 // gas legacy: 151236 // gas legacy code: 533800 // gas legacyOptimized: 131436 // gas legacyOptimized code: 276600 -// gas ssaCFGOptimized: 132039 -// gas ssaCFGOptimized code: 282000 +// gas ssaCFGOptimized: 132299 +// gas ssaCFGOptimized code: 285400 // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 96528 +// gas irOptimized: 96469 // gas irOptimized code: 20800 // gas legacy: 97788 // gas legacy code: 20800 // gas legacyOptimized: 96043 // gas legacyOptimized code: 20800 -// gas ssaCFGOptimized: 96391 +// gas ssaCFGOptimized: 96332 // gas ssaCFGOptimized code: 20800 // exists() -> false // deploy_create2() -> @@ -110,7 +110,7 @@ contract D { // test_balance_after_selfdestruct() -> // exists() -> true // deploy_create2() -> FAILURE -// gas irOptimized: 96903654 +// gas irOptimized: 96903655 // gas legacy: 96903658 // gas legacyOptimized: 96903639 -// gas ssaCFGOptimized: 96903647 +// gas ssaCFGOptimized: 96903648 diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index cd54318c19ef..138d4dfcf181 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -369,6 +370,13 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(std::shared_ptr _ob StructuralSimplifier::run(*m_context, block); return block; }}, + {"switchSplitter", [&]() { + auto block = disambiguate(); + updateContext(block); + ExpressionSplitter::run(*m_context, block); + SwitchSplitter::run(*m_context, block); + return block; + }}, {"equivalentFunctionCombiner", [&]() { auto block = disambiguate(); updateContext(block); diff --git a/test/libyul/yulOptimizerTests/switchSplitter/nested_switch.yul b/test/libyul/yulOptimizerTests/switchSplitter/nested_switch.yul new file mode 100644 index 000000000000..5658181b7f40 --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/nested_switch.yul @@ -0,0 +1,111 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { + let inner := calldataload(32) + switch inner + case 10 { sstore(1, 10) } + case 11 { sstore(1, 11) } + case 12 { sstore(1, 12) } + case 13 { sstore(1, 13) } + case 14 { sstore(1, 14) } + case 15 { sstore(1, 15) } + case 16 { sstore(1, 16) } + } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch gt(sel, 4) +// case 1 { +// switch sel +// case 5 { +// let _10 := 32 +// let inner := calldataload(_10) +// switch gt(inner, 13) +// case 1 { +// switch inner +// case 14 { +// let _19 := 14 +// let _20 := 1 +// sstore(_20, _19) +// } +// case 15 { +// let _21 := 15 +// let _22 := 1 +// sstore(_22, _21) +// } +// case 16 { +// let _23 := 16 +// let _24 := 1 +// sstore(_24, _23) +// } +// } +// default { +// switch inner +// case 10 { +// let _11 := 10 +// let _12 := 1 +// sstore(_12, _11) +// } +// case 11 { +// let _13 := 11 +// let _14 := 1 +// sstore(_14, _13) +// } +// case 12 { +// let _15 := 12 +// let _16 := 1 +// sstore(_16, _15) +// } +// case 13 { +// let _17 := 13 +// let _18 := 1 +// sstore(_18, _17) +// } +// } +// } +// case 6 { +// let _25 := 6 +// let _26 := 0 +// sstore(_26, _25) +// } +// case 7 { +// let _27 := 7 +// let _28 := 0 +// sstore(_28, _27) +// } +// } +// default { +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/no_split_few_cases.yul b/test/libyul/yulOptimizerTests/switchSplitter/no_split_few_cases.yul new file mode 100644 index 000000000000..6301d7f2642f --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/no_split_few_cases.yul @@ -0,0 +1,48 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// case 5 { +// let _10 := 5 +// let _11 := 0 +// sstore(_11, _10) +// } +// case 6 { +// let _12 := 6 +// let _13 := 0 +// sstore(_13, _12) +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/no_split_large_default.yul b/test/libyul/yulOptimizerTests/switchSplitter/no_split_large_default.yul new file mode 100644 index 000000000000..81c334ed3f16 --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/no_split_large_default.yul @@ -0,0 +1,70 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } + default { + mstore(0, 0x08c379a0) + mstore(4, 0x20) + revert(0, 0x44) + } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// case 5 { +// let _10 := 5 +// let _11 := 0 +// sstore(_11, _10) +// } +// case 6 { +// let _12 := 6 +// let _13 := 0 +// sstore(_13, _12) +// } +// case 7 { +// let _14 := 7 +// let _15 := 0 +// sstore(_15, _14) +// } +// default { +// let _16 := 0x08c379a0 +// let _17 := 0 +// mstore(_17, _16) +// let _18 := 0x20 +// let _19 := 4 +// mstore(_19, _18) +// let _20 := 0x44 +// let _21 := 0 +// revert(_21, _20) +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/split_complex_expression.yul b/test/libyul/yulOptimizerTests/switchSplitter/split_complex_expression.yul new file mode 100644 index 000000000000..d8ee0ac9901a --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/split_complex_expression.yul @@ -0,0 +1,61 @@ +{ + switch add(calldataload(0), 1) + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 1 +// let _2 := 0 +// let _3 := calldataload(_2) +// let _4 := add(_3, _1) +// switch gt(_4, 4) +// case 1 { +// switch _4 +// case 5 { +// let _13 := 5 +// let _14 := 0 +// sstore(_14, _13) +// } +// case 6 { +// let _15 := 6 +// let _16 := 0 +// sstore(_16, _15) +// } +// case 7 { +// let _17 := 7 +// let _18 := 0 +// sstore(_18, _17) +// } +// } +// default { +// switch _4 +// case 1 { +// let _5 := 1 +// let _6 := 0 +// sstore(_6, _5) +// } +// case 2 { +// let _7 := 2 +// let _8 := 0 +// sstore(_8, _7) +// } +// case 3 { +// let _9 := 3 +// let _10 := 0 +// sstore(_10, _9) +// } +// case 4 { +// let _11 := 4 +// let _12 := 0 +// sstore(_12, _11) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/split_eight_cases.yul b/test/libyul/yulOptimizerTests/switchSplitter/split_eight_cases.yul new file mode 100644 index 000000000000..77e337740ba4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/split_eight_cases.yul @@ -0,0 +1,66 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } + case 8 { sstore(0, 8) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch gt(sel, 4) +// case 1 { +// switch sel +// case 5 { +// let _10 := 5 +// let _11 := 0 +// sstore(_11, _10) +// } +// case 6 { +// let _12 := 6 +// let _13 := 0 +// sstore(_13, _12) +// } +// case 7 { +// let _14 := 7 +// let _15 := 0 +// sstore(_15, _14) +// } +// case 8 { +// let _16 := 8 +// let _17 := 0 +// sstore(_17, _16) +// } +// } +// default { +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/split_seven_cases.yul b/test/libyul/yulOptimizerTests/switchSplitter/split_seven_cases.yul new file mode 100644 index 000000000000..8bcd9922c6e6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/split_seven_cases.yul @@ -0,0 +1,60 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch gt(sel, 4) +// case 1 { +// switch sel +// case 5 { +// let _10 := 5 +// let _11 := 0 +// sstore(_11, _10) +// } +// case 6 { +// let _12 := 6 +// let _13 := 0 +// sstore(_13, _12) +// } +// case 7 { +// let _14 := 7 +// let _15 := 0 +// sstore(_15, _14) +// } +// } +// default { +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/split_sixteen_cases.yul b/test/libyul/yulOptimizerTests/switchSplitter/split_sixteen_cases.yul new file mode 100644 index 000000000000..dad4579ef763 --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/split_sixteen_cases.yul @@ -0,0 +1,126 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } + case 8 { sstore(0, 8) } + case 9 { sstore(0, 9) } + case 10 { sstore(0, 10) } + case 11 { sstore(0, 11) } + case 12 { sstore(0, 12) } + case 13 { sstore(0, 13) } + case 14 { sstore(0, 14) } + case 15 { sstore(0, 15) } + case 16 { sstore(0, 16) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch gt(sel, 8) +// case 1 { +// switch gt(sel, 12) +// case 1 { +// switch sel +// case 13 { +// let _26 := 13 +// let _27 := 0 +// sstore(_27, _26) +// } +// case 14 { +// let _28 := 14 +// let _29 := 0 +// sstore(_29, _28) +// } +// case 15 { +// let _30 := 15 +// let _31 := 0 +// sstore(_31, _30) +// } +// case 16 { +// let _32 := 16 +// let _33 := 0 +// sstore(_33, _32) +// } +// } +// default { +// switch sel +// case 9 { +// let _18 := 9 +// let _19 := 0 +// sstore(_19, _18) +// } +// case 10 { +// let _20 := 10 +// let _21 := 0 +// sstore(_21, _20) +// } +// case 11 { +// let _22 := 11 +// let _23 := 0 +// sstore(_23, _22) +// } +// case 12 { +// let _24 := 12 +// let _25 := 0 +// sstore(_25, _24) +// } +// } +// } +// default { +// switch gt(sel, 4) +// case 1 { +// switch sel +// case 5 { +// let _10 := 5 +// let _11 := 0 +// sstore(_11, _10) +// } +// case 6 { +// let _12 := 6 +// let _13 := 0 +// sstore(_13, _12) +// } +// case 7 { +// let _14 := 7 +// let _15 := 0 +// sstore(_15, _14) +// } +// case 8 { +// let _16 := 8 +// let _17 := 0 +// sstore(_17, _16) +// } +// } +// default { +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/switchSplitter/split_with_default.yul b/test/libyul/yulOptimizerTests/switchSplitter/split_with_default.yul new file mode 100644 index 000000000000..41da2e16def4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/switchSplitter/split_with_default.yul @@ -0,0 +1,83 @@ +{ + let sel := calldataload(0) + switch sel + case 1 { sstore(0, 1) } + case 2 { sstore(0, 2) } + case 3 { sstore(0, 3) } + case 4 { sstore(0, 4) } + case 5 { sstore(0, 5) } + case 6 { sstore(0, 6) } + case 7 { sstore(0, 7) } + case 8 { sstore(0, 8) } + case 9 { sstore(0, 9) } + default { sstore(0, 99) } +} +// ---- +// step: switchSplitter +// +// { +// let _1 := 0 +// let sel := calldataload(_1) +// switch gt(sel, 5) +// case 1 { +// switch sel +// case 6 { +// let _12 := 6 +// let _13 := 0 +// sstore(_13, _12) +// } +// case 7 { +// let _14 := 7 +// let _15 := 0 +// sstore(_15, _14) +// } +// case 8 { +// let _16 := 8 +// let _17 := 0 +// sstore(_17, _16) +// } +// case 9 { +// let _18 := 9 +// let _19 := 0 +// sstore(_19, _18) +// } +// default { +// let _20 := 99 +// let _21 := 0 +// sstore(_21, _20) +// } +// } +// default { +// switch sel +// case 1 { +// let _2 := 1 +// let _3 := 0 +// sstore(_3, _2) +// } +// case 2 { +// let _4 := 2 +// let _5 := 0 +// sstore(_5, _4) +// } +// case 3 { +// let _6 := 3 +// let _7 := 0 +// sstore(_7, _6) +// } +// case 4 { +// let _8 := 4 +// let _9 := 0 +// sstore(_9, _8) +// } +// case 5 { +// let _10 := 5 +// let _11 := 0 +// sstore(_11, _10) +// } +// default { +// let _20 := 99 +// let _21 := 0 +// sstore(_21, _20) +// } +// } +// } diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index 5503de1bfe34..e40b6cf8c03b 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(output_operator_should_create_concise_and_unambiguous_strin BOOST_TEST(chromosome.length() == allSteps.size()); BOOST_TEST(chromosome.optimisationSteps() == allSteps); - BOOST_TEST(toString(chromosome) == "flcCUnDEvejsxIOoighFTLMmVatrpuSd"); + BOOST_TEST(toString(chromosome) == "flcCUnDEvejsxIOoighFTLMmVatBrpuSd"); } BOOST_AUTO_TEST_CASE(optimisationSteps_should_translate_chromosomes_genes_to_optimisation_step_names)