From 1f5b874eafa2763c92b3d81e172533bac4f966f3 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Thu, 11 Mar 2021 12:42:59 +0100 Subject: [PATCH 1/9] Optimizer context has parameter expectedExecutionsPerDeployment --- libsolidity/codegen/CompilerContext.cpp | 1 + libyul/AssemblyStack.cpp | 5 ++++- libyul/backends/wasm/EVMToEwasmTranslator.cpp | 10 +++++++++- libyul/optimiser/OptimiserStep.h | 2 ++ libyul/optimiser/Suite.cpp | 3 ++- libyul/optimiser/Suite.h | 7 +++++-- test/libyul/YulOptimizerTestCommon.cpp | 12 ++++++++++-- test/tools/yulopti.cpp | 9 ++++++++- tools/yulPhaser/Program.cpp | 9 ++++++++- 9 files changed, 49 insertions(+), 9 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 88b7770ad..cddeea472 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -548,6 +548,7 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ _object, _optimiserSettings.optimizeStackAllocation, _optimiserSettings.yulOptimiserSteps, + isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment), _externalIdentifiers ); diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 500ae6cb2..9a3f41b68 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -44,6 +44,7 @@ #include #include +#include using namespace std; using namespace solidity; @@ -185,7 +186,9 @@ void AssemblyStack::optimize(Object& _object, bool _isCreation) meter.get(), _object, m_optimiserSettings.optimizeStackAllocation, - m_optimiserSettings.yulOptimiserSteps + m_optimiserSettings.yulOptimiserSteps, + _isCreation ? nullopt : make_optional(m_optimiserSettings.expectedExecutionsPerDeployment), + {} ); } diff --git a/libyul/backends/wasm/EVMToEwasmTranslator.cpp b/libyul/backends/wasm/EVMToEwasmTranslator.cpp index 3ba58e73e..a2723533d 100644 --- a/libyul/backends/wasm/EVMToEwasmTranslator.cpp +++ b/libyul/backends/wasm/EVMToEwasmTranslator.cpp @@ -42,6 +42,8 @@ #include #include +#include + // The following headers are generated from the // yul files placed in libyul/backends/wasm/polyfill. @@ -68,7 +70,13 @@ Object EVMToEwasmTranslator::run(Object const& _object) Block ast = std::get(Disambiguator(m_dialect, *_object.analysisInfo)(*_object.code)); set reservedIdentifiers; NameDispenser nameDispenser{m_dialect, ast, reservedIdentifiers}; - OptimiserStepContext context{m_dialect, nameDispenser, reservedIdentifiers}; + // expectedExecutionsPerDeployment is currently unused. + OptimiserStepContext context{ + m_dialect, + nameDispenser, + reservedIdentifiers, + frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment + }; FunctionHoister::run(context, ast); FunctionGrouper::run(context, ast); diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index 7dc2d3ea2..e3e5fe4c6 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -37,6 +37,8 @@ struct OptimiserStepContext Dialect const& dialect; NameDispenser& dispenser; std::set const& reservedIdentifiers; + /// The value nullopt represents creation code + std::optional expectedExecutionsPerDeployment; }; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index f11a02860..8f676e335 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -88,6 +88,7 @@ void OptimiserSuite::run( Object& _object, bool _optimizeStackAllocation, string const& _optimisationSequence, + optional _expectedExecutionsPerDeployment, set const& _externallyUsedIdentifiers ) { @@ -101,7 +102,7 @@ void OptimiserSuite::run( )(*_object.code)); Block& ast = *_object.code; - OptimiserSuite suite(_dialect, reservedIdentifiers, Debug::None, ast); + OptimiserSuite suite(_dialect, reservedIdentifiers, Debug::None, ast, _expectedExecutionsPerDeployment); // Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 9ae0ada58..fa7b06bd0 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -58,12 +58,14 @@ public: PrintStep, PrintChanges }; + /// The value nullopt for `_expectedExecutionsPerDeployment` represents creation code. static void run( Dialect const& _dialect, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, std::string const& _optimisationSequence, + std::optional _expectedExecutionsPerDeployment, std::set const& _externallyUsedIdentifiers = {} ); @@ -88,10 +90,11 @@ private: Dialect const& _dialect, std::set const& _externallyUsedIdentifiers, Debug _debug, - Block& _ast + Block& _ast, + std::optional expectedExecutionsPerDeployment ): m_dispenser{_dialect, _ast, _externallyUsedIdentifiers}, - m_context{_dialect, m_dispenser, _externallyUsedIdentifiers}, + m_context{_dialect, m_dispenser, _externallyUsedIdentifiers, expectedExecutionsPerDeployment}, m_debug(_debug) {} diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 2f8334eef..c2e836e45 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -317,7 +317,14 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( }}, {"fullSuite", [&]() { GasMeter meter(dynamic_cast(*m_dialect), false, 200); - OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps); + OptimiserSuite::run( + *m_dialect, + &meter, + *m_object, + true, + frontend::OptimiserSettings::DefaultYulOptimiserSteps, + frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment + ); }}, {"stackLimitEvader", [&]() { disambiguate(); @@ -434,6 +441,7 @@ void YulOptimizerTestCommon::updateContext() m_context = make_unique(OptimiserStepContext{ *m_dialect, *m_nameDispenser, - m_reservedIdentifiers + m_reservedIdentifiers, + frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }); } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 469d7964a..594d4c19c 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -43,6 +43,8 @@ #include +#include + #include #include #include @@ -191,7 +193,12 @@ public: char option = static_cast(readStandardInputChar()); cout << ' ' << option << endl; - OptimiserStepContext context{m_dialect, *m_nameDispenser, reservedIdentifiers}; + OptimiserStepContext context{ + m_dialect, + *m_nameDispenser, + reservedIdentifiers, + solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment + }; auto abbreviationAndName = abbreviationMap.find(option); if (abbreviationAndName != abbreviationMap.end()) diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index c7b96bd21..e01581d6a 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -41,6 +41,8 @@ #include +#include + #include #include @@ -201,7 +203,12 @@ unique_ptr Program::applyOptimisationSteps( // An empty set of reserved identifiers. It could be a constructor parameter but I don't // think it would be useful in this tool. Other tools (like yulopti) have it empty too. set const externallyUsedIdentifiers = {}; - OptimiserStepContext context{_dialect, _nameDispenser, externallyUsedIdentifiers}; + OptimiserStepContext context{ + _dialect, + _nameDispenser, + externallyUsedIdentifiers, + frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment + }; for (string const& step: _optimisationSteps) OptimiserSuite::allSteps().at(step)->run(context, *_ast); From dd6300a53ee14d8e4fc3a2f563b6e0490e4908be Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 12 Apr 2021 12:24:42 +0200 Subject: [PATCH 2/9] GasMeter can now account for gas of Keccak-256 --- libyul/backends/evm/EVMMetrics.cpp | 3 +++ libyul/backends/evm/EVMMetrics.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index ce8d8f31e..de28792d3 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -117,6 +117,9 @@ void GasMeterVisitor::instructionCostsInternal(evmasm::Instruction _instruction) { if (_instruction == evmasm::Instruction::EXP) m_runGas += evmasm::GasCosts::expGas + evmasm::GasCosts::expByteGas(m_dialect.evmVersion()); + else if (_instruction == evmasm::Instruction::KECCAK256) + // Assumes that Keccak-256 is computed on a single word (rounded up). + m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas; else m_runGas += evmasm::GasMeter::runGas(_instruction); m_dataGas += singleByteDataGas(); diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index 00dad153b..ec59976f7 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -36,6 +36,8 @@ struct EVMDialect; * * Assumes that EXP is not used with exponents larger than a single byte. * Is not particularly exact for anything apart from arithmetic. + * + * Assumes that Keccak-256 is computed on a single word (rounded up). */ class GasMeter { From 94f9410abee0030c97fcd6aff517530f2561e87c Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 19 Apr 2021 12:51:07 +0200 Subject: [PATCH 3/9] Added hashFunction to Dialect. For EVMDialect, it is keccak256 In a later PR, the functions `storageLoadFunction`, `storageStoreFunctions`, etc will be refactored to return a YulString instead of a pointer to a BuiltinFunction. --- libyul/Dialect.h | 1 + libyul/backends/evm/EVMDialect.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libyul/Dialect.h b/libyul/Dialect.h index ef8c56909..8c8891ee6 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -79,6 +79,7 @@ struct Dialect: boost::noncopyable virtual BuiltinFunction const* memoryLoadFunction(YulString /* _type */) const { return nullptr; } virtual BuiltinFunction const* storageStoreFunction(YulString /* _type */) const { return nullptr; } virtual BuiltinFunction const* storageLoadFunction(YulString /* _type */) const { return nullptr; } + virtual YulString hashFunction(YulString /* _type */ ) const { return YulString{}; } /// Check whether the given type is legal for the given literal value. /// Should only be called if the type exists in the dialect at all. diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 1672c623c..e7a39f19a 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -81,6 +81,7 @@ struct EVMDialect: public Dialect BuiltinFunctionForEVM const* memoryLoadFunction(YulString /*_type*/) const override { return builtin("mload"_yulstring); } BuiltinFunctionForEVM const* storageStoreFunction(YulString /*_type*/) const override { return builtin("sstore"_yulstring); } BuiltinFunctionForEVM const* storageLoadFunction(YulString /*_type*/) const override { return builtin("sload"_yulstring); } + YulString hashFunction(YulString /*_type*/) const override { return "keccak256"_yulstring; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version); From 011f8d3ff7319121ac99e92ba92b58f2dc2aa483 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 19 Apr 2021 13:08:19 +0200 Subject: [PATCH 4/9] Changed the type of gas calculation to bigint instead of size_t Since the gas calculation can involve multiplication by ``--optimize-runs``, it is possible that `size_t` is not enough to represent the total gas. --- libyul/backends/evm/ConstantOptimiser.h | 2 +- libyul/backends/evm/EVMMetrics.cpp | 16 ++++++++-------- libyul/backends/evm/EVMMetrics.h | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 52d78be86..e95a152c8 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -58,7 +58,7 @@ public: struct Representation { std::unique_ptr expression; - size_t cost = size_t(-1); + bigint cost; }; private: diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index de28792d3..dfb716c19 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -37,23 +37,23 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -size_t GasMeter::costs(Expression const& _expression) const +bigint GasMeter::costs(Expression const& _expression) const { return combineCosts(GasMeterVisitor::costs(_expression, m_dialect, m_isCreation)); } -size_t GasMeter::instructionCosts(evmasm::Instruction _instruction) const +bigint GasMeter::instructionCosts(evmasm::Instruction _instruction) const { return combineCosts(GasMeterVisitor::instructionCosts(_instruction, m_dialect, m_isCreation)); } -size_t GasMeter::combineCosts(std::pair _costs) const +bigint GasMeter::combineCosts(std::pair _costs) const { return _costs.first * m_runs + _costs.second; } -pair GasMeterVisitor::costs( +pair GasMeterVisitor::costs( Expression const& _expression, EVMDialect const& _dialect, bool _isCreation @@ -64,7 +64,7 @@ pair GasMeterVisitor::costs( return {gmv.m_runGas, gmv.m_dataGas}; } -pair GasMeterVisitor::instructionCosts( +pair GasMeterVisitor::instructionCosts( evmasm::Instruction _instruction, EVMDialect const& _dialect, bool _isCreation @@ -92,11 +92,11 @@ void GasMeterVisitor::operator()(Literal const& _lit) m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1); m_dataGas += singleByteDataGas() + - static_cast(evmasm::GasMeter::dataGas( + evmasm::GasMeter::dataGas( toCompactBigEndian(valueOfLiteral(_lit), 1), m_isCreation, m_dialect.evmVersion() - )); + ); } void GasMeterVisitor::operator()(Identifier const&) @@ -105,7 +105,7 @@ void GasMeterVisitor::operator()(Identifier const&) m_dataGas += singleByteDataGas(); } -size_t GasMeterVisitor::singleByteDataGas() const +bigint GasMeterVisitor::singleByteDataGas() const { if (m_isCreation) return evmasm::GasCosts::txDataNonZeroGas(m_dialect.evmVersion()); diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index ec59976f7..19702b8f3 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -42,36 +42,36 @@ struct EVMDialect; class GasMeter { public: - GasMeter(EVMDialect const& _dialect, bool _isCreation, size_t _runs): + GasMeter(EVMDialect const& _dialect, bool _isCreation, bigint _runs): m_dialect(_dialect), m_isCreation{_isCreation}, m_runs(_isCreation? 1 : _runs) {} /// @returns the full combined costs of deploying and evaluating the expression. - size_t costs(Expression const& _expression) const; + bigint costs(Expression const& _expression) const; /// @returns the combined costs of deploying and running the instruction, not including /// the costs for its arguments. - size_t instructionCosts(evmasm::Instruction _instruction) const; + bigint instructionCosts(evmasm::Instruction _instruction) const; private: - size_t combineCosts(std::pair _costs) const; + bigint combineCosts(std::pair _costs) const; EVMDialect const& m_dialect; bool m_isCreation = false; - size_t m_runs; + bigint m_runs; }; class GasMeterVisitor: public ASTWalker { public: - static std::pair costs( + static std::pair costs( Expression const& _expression, EVMDialect const& _dialect, bool _isCreation ); - static std::pair instructionCosts( + static std::pair instructionCosts( evmasm::Instruction _instruction, EVMDialect const& _dialect, bool _isCreation = false @@ -88,7 +88,7 @@ public: void operator()(Identifier const& _identifier) override; private: - size_t singleByteDataGas() const; + bigint singleByteDataGas() const; /// Computes the cost of storing and executing the single instruction (excluding its arguments). /// For EXP, it assumes that the exponent is at most 255. /// Does not work particularly exact for anything apart from arithmetic. @@ -96,8 +96,8 @@ private: EVMDialect const& m_dialect; bool m_isCreation = false; - size_t m_runGas = 0; - size_t m_dataGas = 0; + bigint m_runGas = 0; + bigint m_dataGas = 0; }; } From 3bc4f5708a9b45be5ba1a2feafb6e522f84a686e Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 1 Mar 2021 19:05:59 +0100 Subject: [PATCH 5/9] Evaluate `keccak(a, const)` if value at memory location `a` is known Here the value of constant can be at most 32. --- libyul/optimiser/DataFlowAnalyzer.cpp | 10 +++- libyul/optimiser/DataFlowAnalyzer.h | 5 ++ libyul/optimiser/LoadResolver.cpp | 74 ++++++++++++++++++++++++++- libyul/optimiser/LoadResolver.h | 18 ++++++- 4 files changed, 103 insertions(+), 4 deletions(-) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 2a90ee9b2..1150da659 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -388,6 +389,14 @@ bool DataFlowAnalyzer::inScope(YulString _variableName) const return false; } +optional DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) +{ + if (m_value.count(_name)) + if (Literal const* literal = get_if(m_value.at(_name).value)) + return valueOfLiteral(*literal); + return nullopt; +} + std::optional> DataFlowAnalyzer::isSimpleStore( StoreLoadLocation _location, ExpressionStatement const& _statement @@ -412,4 +421,3 @@ std::optional DataFlowAnalyzer::isSimpleLoad( return key->name; return {}; } - diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 7cbbe63b7..deaa71f89 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -29,6 +29,8 @@ #include // Needed for m_zero below. #include +#include + #include #include @@ -134,6 +136,9 @@ protected: /// Returns true iff the variable is in scope. bool inScope(YulString _variableName) const; + /// Returns the literal value of the identifier, if it exists. + std::optional valueOfIdentifier(YulString const& _name); + enum class StoreLoadLocation { Memory = 0, Storage = 1, diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 99d3f4ffc..f73cd48bc 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -23,13 +23,23 @@ #include #include +#include #include #include #include #include +#include + +#include +#include +#include + +#include using namespace std; using namespace solidity; +using namespace solidity::util; +using namespace solidity::evmasm; using namespace solidity::yul; void LoadResolver::run(OptimiserStepContext& _context, Block& _ast) @@ -38,7 +48,8 @@ void LoadResolver::run(OptimiserStepContext& _context, Block& _ast) LoadResolver{ _context.dialect, SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)), - !containsMSize + !containsMSize, + _context.expectedExecutionsPerDeployment }(_ast); } @@ -47,12 +58,17 @@ void LoadResolver::visit(Expression& _e) DataFlowAnalyzer::visit(_e); if (FunctionCall const* funCall = std::get_if(&_e)) + { for (auto location: { StoreLoadLocation::Memory, StoreLoadLocation::Storage }) if (funCall->functionName.name == m_loadFunctionName[static_cast(location)]) { tryResolve(_e, location, funCall->arguments); break; } + + if (funCall->functionName.name == m_dialect.hashFunction({})) + tryEvaluateKeccak(_e, funCall->arguments); + } } void LoadResolver::tryResolve( @@ -76,3 +92,59 @@ void LoadResolver::tryResolve( if (inScope(*value)) _e = Identifier{locationOf(_e), *value}; } + +void LoadResolver::tryEvaluateKeccak( + Expression& _e, + std::vector const& _arguments +) +{ + // The costs are only correct for hashes of 32 bytes or 1 word (when rounded up). + GasMeter gasMeter{ + dynamic_cast(m_dialect), + !m_expectedExecutionsPerDeployment, + m_expectedExecutionsPerDeployment ? *m_expectedExecutionsPerDeployment : 1 + }; + + bigint costOfKeccak = gasMeter.costs(_e); + bigint costOfLiteral = gasMeter.costs( + Literal{ + {}, + LiteralKind::Number, + // a dummy 256-bit number to represent the Keccak256 hash. + YulString{numeric_limits::max().str()}, + {} + } + ); + + // We skip if there are no net gas savings. + // Note that for default `m_runs = 200`, the values are + // `costOfLiteral = 7200` and `costOfKeccak = 9000` for runtime context. + // For creation context: `costOfLiteral = 531` and `costOfKeccak = 90`. + if (costOfLiteral > costOfKeccak) + return; + + yulAssert(_arguments.size() == 2, ""); + Identifier const* memoryKey = std::get_if(&_arguments.at(0)); + Identifier const* length = std::get_if(&_arguments.at(1)); + + if (!memoryKey || !length) + return; + + auto memoryValue = util::valueOrNullptr(m_memory, memoryKey->name); + if (memoryValue && inScope(*memoryValue)) + { + optional memoryContent = valueOfIdentifier(*memoryValue); + optional byteLength = valueOfIdentifier(length->name); + if (memoryContent && byteLength && *byteLength <= 32) + { + bytes contentAsBytes = toBigEndian(*memoryContent); + contentAsBytes.resize(static_cast(*byteLength)); + _e = Literal{ + locationOf(_e), + LiteralKind::Number, + YulString{u256(keccak256(contentAsBytes)).str()}, + m_dialect.defaultType + }; + } + } +} diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index a376ab059..e1758bf6b 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -32,6 +32,9 @@ namespace solidity::yul * Optimisation stage that replaces expressions of type ``sload(x)`` and ``mload(x)`` by the value * currently stored in storage resp. memory, if known. * + * Also evaluates simple ``keccak256(a, c)`` when the value at memory location `a` is known and `c` + * is a constant `<= 32`. + * * Works best if the code is in SSA form. * * Prerequisite: Disambiguator, ForLoopInitRewriter. @@ -47,10 +50,12 @@ private: LoadResolver( Dialect const& _dialect, std::map _functionSideEffects, - bool _optimizeMLoad + bool _optimizeMLoad, + std::optional _expectedExecutionsPerDeployment ): DataFlowAnalyzer(_dialect, std::move(_functionSideEffects)), - m_optimizeMLoad(_optimizeMLoad) + m_optimizeMLoad(_optimizeMLoad), + m_expectedExecutionsPerDeployment(std::move(_expectedExecutionsPerDeployment)) {} protected: @@ -63,7 +68,16 @@ protected: std::vector const& _arguments ); + /// Evaluates simple ``keccak256(a, c)`` when the value at memory location ``a`` is known and + /// `c` is a constant `<= 32`. + void tryEvaluateKeccak( + Expression& _e, + std::vector const& _arguments + ); + bool m_optimizeMLoad = false; + /// The --optimize-runs parameter. Value `nullopt` represents creation code. + std::optional m_expectedExecutionsPerDeployment; }; } From 221292c2789e07dda18db2a46c8119a3f15a194d Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 19 Apr 2021 11:33:04 +0200 Subject: [PATCH 6/9] Tests and changelog --- Changelog.md | 1 + .../cmdlineTests/optimizer_array_sload/output | 2 +- .../keccak_yul_optimization.sol | 35 ++++++++++++++ .../static_array_slot_computation.yul | 46 +++++++++++++++++++ .../yulOptimizerTests/loadResolver/keccak.yul | 16 +++++++ .../loadResolver/keccak_fail1.yul | 18 ++++++++ .../loadResolver/keccak_fail2.yul | 16 +++++++ .../loadResolver/keccak_short.yul | 31 +++++++++++++ .../loadResolver/keccak_string_literal.yul | 22 +++++++++ .../loadResolver/keccak_symbolic_memory.yul | 22 +++++++++ 10 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol create mode 100644 test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul diff --git a/Changelog.md b/Changelog.md index 410ab1d31..4b997c391 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Yul Optimizer: Evaluate ``keccak256(a, c)``, when the value at memory location ``a`` is known at compile time and ``c`` is a constant ``<= 32``. Bugfixes: diff --git a/test/cmdlineTests/optimizer_array_sload/output b/test/cmdlineTests/optimizer_array_sload/output index 9e277fb17..0576e2890 100644 --- a/test/cmdlineTests/optimizer_array_sload/output +++ b/test/cmdlineTests/optimizer_array_sload/output @@ -38,7 +38,7 @@ object "Arraysum_34" { } { mstore(_1, _1) - let _3 := sload(add(keccak256(_1, 0x20), var_i)) + let _3 := sload(add(18569430475105882587588266137607568536673111973893317399460219858819262702947, var_i)) if gt(var_sum, not(_3)) { panic_error_0x11() } var_sum := add(var_sum, _3) } diff --git a/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol b/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol new file mode 100644 index 000000000..f0d9aa8fe --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol @@ -0,0 +1,35 @@ +contract C { + function g() public returns (uint ret) { + uint x = type(uint).max; + assembly { + mstore(0x20, x) + // both old and new optimizer should be able to evaluate this + ret := keccak256(0x20, 16) + } + } + + function f() public returns (uint ret) { + uint x = type(uint).max; + assembly { + mstore(0x20, x) + // For Yul optimizer, load resolver and loop invariant code motion + // would take the Keccak-256 outside the loop. For the old-optimizer, + // this is not possible. + // Net savings approximately: 20 * cost of Keccak-256 = 572 + for {let i := 0} lt(i, 20) { i := add(i, 1) } { + ret := keccak256(0x20, 16) + } + } + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0xcdb56c384a9682c600315e3470157a4cf7638d0d33e9dae5c40ffd2644fc5a80 +// gas irOptimized: 22521 +// gas legacy: 23385 +// gas legacyOptimized: 23092 +// g() -> 0xcdb56c384a9682c600315e3470157a4cf7638d0d33e9dae5c40ffd2644fc5a80 +// gas irOptimized: 21391 +// gas legacy: 21462 +// gas legacyOptimized: 21256 diff --git a/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul b/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul new file mode 100644 index 000000000..c5f4aa466 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul @@ -0,0 +1,46 @@ +// The yul code for the following contract +// contract C { +// uint256[] x; +// function f() public { x[10] = 5; } +// } + +{ + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + if iszero(lt(0x0a, sload(_1))) + { + mstore(_1, shl(224, 0x4e487b71)) + mstore(4, 0x32) + revert(_1, 0x24) + } + mstore(_1, _1) + // The hash should be evaluated here + sstore(add(keccak256(_1, 0x20), 0x0a), 0x05) + } +} +// ==== +// EVMVersion: >=constantinople +// ---- +// step: fullSuite +// +// { +// { +// let _1 := 0 +// if eq(0x26121ff0, shr(224, calldataload(_1))) +// { +// if callvalue() { revert(_1, _1) } +// if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } +// if iszero(lt(0x0a, sload(_1))) +// { +// mstore(_1, shl(224, 0x4e487b71)) +// mstore(4, 0x32) +// revert(_1, 0x24) +// } +// mstore(_1, _1) +// sstore(0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d, 0x05) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak.yul new file mode 100644 index 000000000..97b468e5f --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak.yul @@ -0,0 +1,16 @@ +{ + mstore(0, 10) + /// >>> int.from_bytes(web3.Web3.keccak(int.to_bytes(10, 32, byteorder='big')), byteorder='big') + /// 89717814153306320011181716697424560163256864414616650038987186496166826726056 + let val := keccak256(0, 32) + sstore(0, val) +} +// ---- +// step: loadResolver +// +// { +// let _1 := 10 +// let _2 := 0 +// mstore(_2, _1) +// sstore(_2, 89717814153306320011181716697424560163256864414616650038987186496166826726056) +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul new file mode 100644 index 000000000..e1157f21d --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail1.yul @@ -0,0 +1,18 @@ +{ + mstore(0, 30) + if calldataload(0) { + mstore(0, 20) + } + let val := keccak256(0, 32) + sstore(0, val) +} +// ---- +// step: loadResolver +// +// { +// let _1 := 30 +// let _2 := 0 +// mstore(_2, _1) +// if calldataload(_2) { mstore(_2, 20) } +// sstore(_2, keccak256(_2, 32)) +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul new file mode 100644 index 000000000..61a2eefb2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_fail2.yul @@ -0,0 +1,16 @@ +{ + mstore(100, 10) + mstore(132, 5) + // Won't be evaluated, even though the value is known + let val := keccak256(10, 33) + sstore(0, val) +} +// ---- +// step: loadResolver +// +// { +// let _1 := 10 +// mstore(100, _1) +// mstore(132, 5) +// sstore(0, keccak256(_1, 33)) +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul new file mode 100644 index 000000000..d1761b7ce --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul @@ -0,0 +1,31 @@ +// import web3 +// >>> asBytes = int(10).to_bytes(32, byteorder='big') +// >>> int.from_bytes(web3.Web3.keccak(asBytes[:31]), byteorder='big') +// 9948786400348073077032572701554570401043517428989726124163377057770909578447 +// >>> int.from_bytes(web3.Web3.keccak(asBytes[:30]), byteorder='big') +// 110945455955148346822663466543669633859020391897956790847617069135813044810108 +// >>> int.from_bytes(web3.Web3.keccak(asBytes[:1]), byteorder='big') +// 85131057757245807317576516368191972321038229705283732634690444270750521936266 +// >>> int.from_bytes(web3.Web3.keccak(b''), byteorder='big') +// 89477152217924674838424037953991966239322087453347756267410168184682657981552 +{ + mstore(0, 10) + sstore(0, keccak256(0, 31)) + sstore(1, keccak256(0, 30)) + sstore(2, keccak256(0, 1)) + sstore(2, keccak256(0, 0)) +} +// ---- +// step: loadResolver +// +// { +// let _1 := 10 +// let _2 := 0 +// mstore(_2, _1) +// sstore(_2, 9948786400348073077032572701554570401043517428989726124163377057770909578447) +// sstore(1, 110945455955148346822663466543669633859020391897956790847617069135813044810108) +// let _13 := 85131057757245807317576516368191972321038229705283732634690444270750521936266 +// let _14 := 2 +// sstore(_14, _13) +// sstore(_14, 89477152217924674838424037953991966239322087453347756267410168184682657981552) +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul new file mode 100644 index 000000000..279a23959 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_string_literal.yul @@ -0,0 +1,22 @@ +{ + let converted := 14 + let _1 := 50 + mstore(_1, "abcdefghijklmn") + // >>> int.from_bytes(web3.Web3.keccak(text="abcdefghijklmn"), byteorder='big') + // 51246744213555520563123611275127692828770413530219146609532820042079541949502 + + sstore(0, keccak256(_1, converted)) + sstore(0, add(mload(_1), 1)) +} +// ---- +// step: loadResolver +// +// { +// let _1 := 50 +// let _2 := "abcdefghijklmn" +// mstore(_1, _2) +// let _3 := 51246744213555520563123611275127692828770413530219146609532820042079541949502 +// let _4 := 0 +// sstore(_4, _3) +// sstore(_4, add(_2, 1)) +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul new file mode 100644 index 000000000..c18af0c8d --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_symbolic_memory.yul @@ -0,0 +1,22 @@ +// Test where the location of the memory offset is not known at compile time +// >>> import web3 +// >>> asBytes = int(500).to_bytes(32, byteorder='big') +// >>> int.from_bytes(web3.Web3.keccak(asBytes), byteorder='big') +// 92647596584187651892918913434663110448935397770592030057655219009846081465370 +// >>> int.from_bytes(web3.Web3.keccak(asBytes[:16]), byteorder='big') +// 110620294328144418057589324861608220015688365608948720310623173341503153578932 +{ + let offset := calldataload(0) + mstore(offset, 500) + sstore(0, keccak256(offset, 32)) + sstore(1, keccak256(offset, 16)) +} +// ---- +// step: loadResolver +// +// { +// let _1 := 0 +// mstore(calldataload(_1), 500) +// sstore(_1, 92647596584187651892918913434663110448935397770592030057655219009846081465370) +// sstore(1, 110620294328144418057589324861608220015688365608948720310623173341503153578932) +// } From b636ef881e9f93b50888963e65732a541e2e96aa Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Fri, 12 Mar 2021 18:05:05 +0100 Subject: [PATCH 7/9] Added command line tests for keccak optimization with low runs The value of keccak256(0, 32) should not be replaced by the big constant --- .../keccak_optimization_deploy_code/args | 1 + .../keccak_optimization_deploy_code/err | 1 + .../keccak_optimization_deploy_code/exit | 1 + .../keccak_optimization_deploy_code/input.sol | 21 ++++++++++++ .../keccak_optimization_deploy_code/output | 32 +++++++++++++++++++ .../keccak_optimization_low_runs/args | 1 + .../keccak_optimization_low_runs/err | 1 + .../keccak_optimization_low_runs/exit | 1 + .../keccak_optimization_low_runs/input.sol | 12 +++++++ .../keccak_optimization_low_runs/output | 30 +++++++++++++++++ 10 files changed, 101 insertions(+) create mode 100644 test/cmdlineTests/keccak_optimization_deploy_code/args create mode 100644 test/cmdlineTests/keccak_optimization_deploy_code/err create mode 100644 test/cmdlineTests/keccak_optimization_deploy_code/exit create mode 100644 test/cmdlineTests/keccak_optimization_deploy_code/input.sol create mode 100644 test/cmdlineTests/keccak_optimization_deploy_code/output create mode 100644 test/cmdlineTests/keccak_optimization_low_runs/args create mode 100644 test/cmdlineTests/keccak_optimization_low_runs/err create mode 100644 test/cmdlineTests/keccak_optimization_low_runs/exit create mode 100644 test/cmdlineTests/keccak_optimization_low_runs/input.sol create mode 100644 test/cmdlineTests/keccak_optimization_low_runs/output diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/args b/test/cmdlineTests/keccak_optimization_deploy_code/args new file mode 100644 index 000000000..c5da41705 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_deploy_code/args @@ -0,0 +1 @@ +--ir-optimized --optimize --optimize-runs 50000 diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/err b/test/cmdlineTests/keccak_optimization_deploy_code/err new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_deploy_code/err @@ -0,0 +1 @@ + diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/exit b/test/cmdlineTests/keccak_optimization_deploy_code/exit new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_deploy_code/exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/input.sol b/test/cmdlineTests/keccak_optimization_deploy_code/input.sol new file mode 100644 index 000000000..671351e67 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_deploy_code/input.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-v3 +pragma solidity >= 0.0.0; + +contract C { + constructor() { + assembly { + mstore(0, 100) + // because this is part of deploy code, the keccak will not be evaluated + sstore(0, keccak256(0, 32)) + } + } + + fallback() external { + assembly { + mstore(0, 100) + // The keccak here would be evaluated + sstore(0, keccak256(0, 32)) + } + + } +} diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/output b/test/cmdlineTests/keccak_optimization_deploy_code/output new file mode 100644 index 000000000..5bdfaf647 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_deploy_code/output @@ -0,0 +1,32 @@ +Optimized IR: +/******************************************************* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *******************************************************/ + +object "C_12" { + code { + { + mstore(64, 128) + if callvalue() { revert(0, 0) } + mstore(0, 100) + sstore(0, keccak256(0, 32)) + let _1 := datasize("C_12_deployed") + codecopy(0, dataoffset("C_12_deployed"), _1) + return(0, _1) + } + } + object "C_12_deployed" { + code { + { + mstore(64, 128) + if callvalue() { revert(0, 0) } + mstore(0, 100) + sstore(0, 17385872270140913825666367956517731270094621555228275961425792378517567244498) + stop() + } + } + } +} diff --git a/test/cmdlineTests/keccak_optimization_low_runs/args b/test/cmdlineTests/keccak_optimization_low_runs/args new file mode 100644 index 000000000..3e162407f --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_low_runs/args @@ -0,0 +1 @@ +--ir-optimized --optimize --optimize-runs 1 diff --git a/test/cmdlineTests/keccak_optimization_low_runs/err b/test/cmdlineTests/keccak_optimization_low_runs/err new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_low_runs/err @@ -0,0 +1 @@ + diff --git a/test/cmdlineTests/keccak_optimization_low_runs/exit b/test/cmdlineTests/keccak_optimization_low_runs/exit new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_low_runs/exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/keccak_optimization_low_runs/input.sol b/test/cmdlineTests/keccak_optimization_low_runs/input.sol new file mode 100644 index 000000000..cc791b364 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_low_runs/input.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-v3 +pragma solidity >= 0.0.0; + +contract C { + fallback() external { + assembly { + mstore(0, 100) + // because of the low runs value, the constant will not be optimized + sstore(0, keccak256(0, 32)) + } + } +} diff --git a/test/cmdlineTests/keccak_optimization_low_runs/output b/test/cmdlineTests/keccak_optimization_low_runs/output new file mode 100644 index 000000000..ab6027035 --- /dev/null +++ b/test/cmdlineTests/keccak_optimization_low_runs/output @@ -0,0 +1,30 @@ +Optimized IR: +/******************************************************* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *******************************************************/ + +object "C_7" { + code { + { + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize("C_7_deployed") + codecopy(0, dataoffset("C_7_deployed"), _1) + return(0, _1) + } + } + object "C_7_deployed" { + code { + { + mstore(64, 128) + if callvalue() { revert(0, 0) } + mstore(0, 100) + sstore(0, keccak256(0, 32)) + stop() + } + } + } +} From 3d29ae73e7c4de7a1e58a4651112935d3d20f2cb Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 12 Apr 2021 12:53:09 +0200 Subject: [PATCH 8/9] Isoltest: updated the gas tests. --- .../abiEncoderV1/abi_decode_v2_storage.sol | 2 +- .../abiEncoderV1/struct/struct_storage_ptr.sol | 2 +- .../semanticTests/abiEncoderV2/abi_encode_v2.sol | 2 +- .../abiEncoderV2/storage_array_encoding.sol | 2 +- .../abi_decode_simple_storage.sol | 2 +- .../array/arrays_complex_from_and_to_storage.sol | 2 +- .../array/byte_array_storage_layout.sol | 2 +- .../array/byte_array_transitional_2.sol | 2 +- .../semanticTests/array/bytes_length_member.sol | 2 +- .../copying/array_copy_calldata_storage.sol | 2 +- .../array/copying/array_copy_cleanup_uint128.sol | 2 +- .../array/copying/array_copy_cleanup_uint40.sol | 2 +- .../array/copying/array_copy_clear_storage.sol | 2 +- .../copying/array_copy_clear_storage_packed.sol | 4 ++-- .../copying/array_copy_different_packing.sol | 2 +- .../array/copying/array_copy_including_array.sol | 4 ++-- .../array/copying/array_copy_nested_array.sol | 2 +- ...array_copy_storage_storage_different_base.sol | 2 +- ...rray_copy_storage_storage_dynamic_dynamic.sol | 2 +- ...array_copy_storage_storage_static_dynamic.sol | 2 +- .../array_copy_storage_storage_struct.sol | 2 +- .../array_copy_storage_to_memory_nested.sol | 2 +- .../copying/array_nested_calldata_to_storage.sol | 6 +++--- .../copying/array_nested_memory_to_storage.sol | 4 ++-- .../array_of_struct_calldata_to_storage.sol | 2 +- .../array_of_struct_memory_to_storage.sol | 2 +- ...cts_containing_arrays_calldata_to_storage.sol | 2 +- ...ructs_containing_arrays_memory_to_storage.sol | 2 +- .../array/copying/arrays_from_and_to_storage.sol | 2 +- .../array/copying/bytes_storage_to_storage.sol | 8 ++++---- .../calldata_array_dynamic_to_storage.sol | 2 +- .../copy_byte_array_in_struct_to_storage.sol | 2 +- .../array/copying/copy_byte_array_to_storage.sol | 2 +- .../copying/copy_function_storage_array.sol | 2 +- .../array/copying/copy_removes_bytes_data.sol | 2 +- .../copying/memory_dyn_2d_bytes_to_storage.sol | 2 +- .../array/copying/storage_memory_nested.sol | 2 +- .../copying/storage_memory_nested_bytes.sol | 2 +- .../storage_memory_nested_from_pointer.sol | 2 +- .../copying/storage_memory_nested_struct.sol | 2 +- .../array/copying/storage_memory_packed_dyn.sol | 2 +- .../array/delete/bytes_delete_element.sol | 2 +- .../array/delete/delete_storage_array_packed.sol | 2 +- .../array/dynamic_array_cleanup.sol | 2 +- .../array/dynamic_arrays_in_storage.sol | 2 +- .../array/dynamic_multi_array_cleanup.sol | 2 +- .../array/pop/array_pop_array_transition.sol | 2 +- .../array/pop/array_pop_uint16_transition.sol | 2 +- .../array/pop/array_pop_uint24_transition.sol | 2 +- .../array/pop/byte_array_pop_copy_long.sol | 2 +- .../pop/byte_array_pop_long_storage_empty.sol | 2 +- ..._array_pop_long_storage_empty_garbage_ref.sol | 2 +- .../array/pop/byte_array_pop_masking_long.sol | 2 +- .../semanticTests/array/push/array_push.sol | 2 +- .../push/array_push_nested_from_calldata.sol | 2 +- .../array/push/array_push_packed_array.sol | 2 +- .../array/push/array_push_struct.sol | 2 +- .../push/array_push_struct_from_calldata.sol | 2 +- .../array/push/byte_array_push_transition.sol | 2 +- .../semanticTests/array/push/push_no_args_2d.sol | 4 ++-- .../array/push/push_no_args_bytes.sol | 2 +- .../constructor/arrays_in_constructors.sol | 2 +- .../constructor/bytes_in_constructors_packer.sol | 2 +- ...ldata_struct_with_nested_array_to_storage.sol | 2 +- .../struct_containing_bytes_copy_and_delete.sol | 2 +- .../struct_delete_storage_nested_small.sol | 2 +- .../structs/struct_delete_storage_with_array.sol | 2 +- .../struct_delete_storage_with_arrays_small.sol | 2 +- .../various/destructuring_assignment.sol | 2 +- .../various/skip_dynamic_types_for_structs.sol | 2 +- .../viaYul/array_storage_index_access.sol | 16 ++++++++-------- .../viaYul/array_storage_index_boundary_test.sol | 4 ++-- .../viaYul/array_storage_index_zeroed_test.sol | 8 ++++---- .../viaYul/array_storage_push_empty.sol | 4 ++-- .../array_storage_push_empty_length_address.sol | 6 +++--- .../viaYul/array_storage_push_pop.sol | 6 +++--- 76 files changed, 101 insertions(+), 101 deletions(-) diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol index f95d8f6a2..6b77d15e4 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol @@ -24,6 +24,6 @@ contract C { // compileViaYul: also // ---- // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb -// gas irOptimized: 193626 +// gas irOptimized: 193543 // gas legacy: 196426 // gas legacyOptimized: 193405 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol index 726f327d5..1291cc08c 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol @@ -26,6 +26,6 @@ contract C { // ---- // library: L // f() -> 8, 7, 1, 2, 7, 12 -// gas irOptimized: 165112 +// gas irOptimized: 164899 // gas legacy: 164775 // gas legacyOptimized: 162697 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index d075fa91c..b84bdbd48 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -53,6 +53,6 @@ contract C { // f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 -// gas irOptimized: 110400 +// gas irOptimized: 110283 // gas legacy: 111328 // gas legacyOptimized: 109206 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 0452817f6..1481743e2 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -19,7 +19,7 @@ contract C { // compileViaYul: also // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 172488 +// gas irOptimized: 172410 // gas legacy: 175929 // gas legacyOptimized: 172504 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol index 25b085a4b..95af83be3 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol @@ -11,6 +11,6 @@ contract C { // compileViaYul: also // ---- // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" -// gas irOptimized: 130136 +// gas irOptimized: 130053 // gas legacy: 131690 // gas legacyOptimized: 130582 diff --git a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol index 519f20f6f..1b81915c6 100644 --- a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol @@ -14,7 +14,7 @@ contract Test { // compileViaYul: also // ---- // set(uint24[3][]): 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06 -// gas irOptimized: 199732 +// gas irOptimized: 199693 // gas legacy: 278685 // gas legacyOptimized: 273594 // data(uint256,uint256): 0x02, 0x02 -> 0x09 diff --git a/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol b/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol index 014df1adc..317cab5cb 100644 --- a/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol +++ b/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol @@ -47,7 +47,7 @@ contract c { // gas legacyOptimized: 109706 // storage: nonempty // test_long() -> 67 -// gas irOptimized: 134403 +// gas irOptimized: 134320 // gas legacy: 213590 // gas legacyOptimized: 211044 // storage: nonempty diff --git a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol index 2c55c5912..d8899aefc 100644 --- a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol +++ b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol @@ -19,6 +19,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0 -// gas irOptimized: 310785 +// gas irOptimized: 309167 // gas legacy: 483915 // gas legacyOptimized: 478672 diff --git a/test/libsolidity/semanticTests/array/bytes_length_member.sol b/test/libsolidity/semanticTests/array/bytes_length_member.sol index 17cb0c10f..c3cad2849 100644 --- a/test/libsolidity/semanticTests/array/bytes_length_member.sol +++ b/test/libsolidity/semanticTests/array/bytes_length_member.sol @@ -15,7 +15,7 @@ contract c { // ---- // getLength() -> 0 // set(): 1, 2 -> true -// gas irOptimized: 103032 +// gas irOptimized: 102993 // gas legacy: 103126 // gas legacyOptimized: 102967 // getLength() -> 68 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol index c85917002..4ce4d0406 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol @@ -22,7 +22,7 @@ contract c { // compileViaYul: also // ---- // store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32 -// gas irOptimized: 612299 +// gas irOptimized: 612216 // gas legacy: 817315 // gas legacyOptimized: 816813 // retrieve() -> 9, 28, 9, 28, 4, 3, 32 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol index 1222ccc91..41b801f23 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol @@ -23,6 +23,6 @@ contract C { // compileViaYul: also // ---- // f() -> true -// gas irOptimized: 107700 +// gas irOptimized: 107258 // gas legacy: 107335 // gas legacyOptimized: 105857 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol index 029c51515..83459475b 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol @@ -48,6 +48,6 @@ contract C { // compileViaYul: also // ---- // f() -> true -// gas irOptimized: 233831 +// gas irOptimized: 231941 // gas legacy: 239061 // gas legacyOptimized: 235988 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol index 031fcfab4..1bbf5f41b 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol @@ -15,6 +15,6 @@ contract C { // compileViaYul: also // ---- // f() -> 0 -// gas irOptimized: 139474 +// gas irOptimized: 139105 // gas legacy: 138913 // gas legacyOptimized: 137448 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol index 29344623d..fbbc1d106 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol @@ -42,11 +42,11 @@ contract C { // compileViaYul: also // ---- // f() -> 0 -// gas irOptimized: 107703 +// gas irOptimized: 107266 // gas legacy: 107306 // gas legacyOptimized: 105861 // g() -> 0 // h() -> 0 -// gas irOptimized: 107749 +// gas irOptimized: 107312 // gas legacy: 107328 // gas legacyOptimized: 105903 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol index 1117fa485..8aa33533c 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol @@ -21,6 +21,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x05000000000000000000000000000000000000000000000000 -// gas irOptimized: 246670 +// gas irOptimized: 245944 // gas legacy: 276683 // gas legacyOptimized: 275534 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol index 699411df9..ccb9ec2af 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -37,12 +37,12 @@ contract c { // compileViaYul: also // ---- // test() -> 0x02000202 -// gas irOptimized: 2471556 +// gas irOptimized: 2470372 // gas legacy: 2288641 // gas legacyOptimized: 2258654 // storage: empty // clear() -> 0, 0 -// gas irOptimized: 1854143 +// gas irOptimized: 1852821 // gas legacy: 1727169 // gas legacyOptimized: 1698931 // storage: empty diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol index 99a548fb8..ce3537056 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol @@ -15,6 +15,6 @@ contract c { // compileViaYul: also // ---- // test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10 -// gas irOptimized: 610560 +// gas irOptimized: 610177 // gas legacy: 604268 // gas legacyOptimized: 603688 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol index e33c75973..28efcc6e2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol @@ -19,6 +19,6 @@ contract c { // compileViaYul: also // ---- // test() -> 5, 4 -// gas irOptimized: 235127 +// gas irOptimized: 234667 // gas legacy: 237001 // gas legacyOptimized: 235316 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol index f7554a911..7053988fa 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol @@ -20,6 +20,6 @@ contract c { // compileViaYul: also // ---- // test() -> 5, 4 -// gas irOptimized: 265126 +// gas irOptimized: 264686 // gas legacy: 264734 // gas legacyOptimized: 263160 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol index db7ae7377..3c7bfc618 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol @@ -14,4 +14,4 @@ contract c { // compileViaYul: also // ---- // test() -> 9, 4 -// gas irOptimized: 99186 +// gas irOptimized: 99075 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol index e52f71a90..57ffa7090 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol @@ -19,7 +19,7 @@ contract c { // compileViaYul: also // ---- // test() -> 4, 5 -// gas irOptimized: 258946 +// gas irOptimized: 257752 // gas legacy: 255936 // gas legacyOptimized: 254359 // storage: empty diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol index 35b008c96..5a0c10696 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol @@ -17,6 +17,6 @@ contract C { // compileViaYul: also // ---- // f() -> 0x20, 2, 0x40, 0xa0, 2, 0, 1, 2, 2, 3 -// gas irOptimized: 168812 +// gas irOptimized: 166791 // gas legacy: 163978 // gas legacyOptimized: 158155 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol index 8a8244a90..acf55aba2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol @@ -38,10 +38,10 @@ contract c { // compileViaYul: true // ---- // test1(uint256[][]): 0x20, 2, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 179354 +// gas irOptimized: 179148 // test2(uint256[][2]): 0x20, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 154106 +// gas irOptimized: 153938 // test3(uint256[2][]): 0x20, 2, 23, 42, 23, 42 -> 2, 65 -// gas irOptimized: 132579 +// gas irOptimized: 132378 // test4(uint256[2][2]): 23, 42, 23, 42 -> 65 // gas irOptimized: 105395 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol index 09bfac30a..ab68d90d5 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol @@ -40,12 +40,12 @@ contract Test { // compileViaYul: also // ---- // test() -> 24 -// gas irOptimized: 216453 +// gas irOptimized: 216291 // gas legacy: 215533 // gas legacyOptimized: 214947 // test1() -> 3 // test2() -> 6 // test3() -> 24 -// gas irOptimized: 122996 +// gas irOptimized: 122838 // gas legacy: 122795 // gas legacyOptimized: 121883 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol index 5c529be53..e553c01c2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol @@ -17,4 +17,4 @@ contract C { // compileViaYul: true // ---- // f((uint128,uint64,uint128)[]): 0x20, 3, 0, 0, 12, 0, 11, 0, 10, 0, 0 -> 10, 11, 12 -// gas irOptimized: 123029 +// gas irOptimized: 122861 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol index ee51af895..75536e681 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol @@ -19,4 +19,4 @@ contract C { // compileViaYul: true // ---- // f() -> 10, 11, 12 -// gas irOptimized: 122025 +// gas irOptimized: 121857 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol index 00cfd3b04..7c756ac18 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol @@ -23,4 +23,4 @@ contract C { // compileViaYul: true // ---- // f((uint256[])[]): 0x20, 3, 0x60, 0x60, 0x60, 0x20, 3, 1, 2, 3 -> 3, 1 -// gas irOptimized: 353951 +// gas irOptimized: 352878 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol index 17e9498fb..915b91c05 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol @@ -26,4 +26,4 @@ contract C { // compileViaYul: true // ---- // f() -> 3, 3, 3, 1 -// gas irOptimized: 187586 +// gas irOptimized: 187277 diff --git a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol index 231cd2271..e20fa1097 100644 --- a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol @@ -12,7 +12,7 @@ contract Test { // compileViaYul: also // ---- // set(uint24[]): 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 -> 18 -// gas irOptimized: 120898 +// gas irOptimized: 120859 // gas legacy: 125815 // gas legacyOptimized: 123614 // data(uint256): 7 -> 8 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index 518096be6..3089f00d7 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -23,21 +23,21 @@ contract c { // gas legacy: 255464 // gas legacyOptimized: 250998 // f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 -// gas irOptimized: 232312 +// gas irOptimized: 229335 // gas legacy: 267931 // gas legacyOptimized: 263329 // f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 241107 +// gas irOptimized: 238042 // gas legacy: 277538 // gas legacyOptimized: 272818 // f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 -// gas irOptimized: 354417 +// gas irOptimized: 348712 // gas legacy: 423428 // gas legacyOptimized: 414868 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 // gas legacy: 106445 // gas legacyOptimized: 104379 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 -// gas irOptimized: 813872 +// gas irOptimized: 802359 // gas legacy: 954517 // gas legacyOptimized: 937521 diff --git a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol index 06a958de9..fa94e781f 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol @@ -11,6 +11,6 @@ contract C { // compileViaYul: also // ---- // f(uint256[]): 0x20, 0x03, 0x1, 0x2, 0x3 -> 0x1 -// gas irOptimized: 105262 +// gas irOptimized: 105184 // gas legacy: 105365 // gas legacyOptimized: 105147 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index bcf0043b6..4a4acad3c 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -37,7 +37,7 @@ contract C { // compileViaYul: also // ---- // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 -// gas irOptimized: 172401 +// gas irOptimized: 172318 // gas legacy: 174794 // gas legacyOptimized: 174188 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol index 2b7228ca2..f9d60b1ac 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol @@ -48,6 +48,6 @@ contract C { // compileViaYul: also // ---- // f() -> 0xff -// gas irOptimized: 136320 +// gas irOptimized: 136164 // gas legacy: 137645 // gas legacyOptimized: 134376 diff --git a/test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol b/test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol index d03084d6d..430d48fda 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_function_storage_array.sol @@ -18,6 +18,6 @@ contract C { // compileViaYul: also // ---- // test() -> 7 -// gas irOptimized: 134158 +// gas irOptimized: 133946 // gas legacy: 211296 // gas legacyOptimized: 211087 diff --git a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol index a8d13f056..354eee307 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol @@ -9,7 +9,7 @@ contract c { // compileViaYul: also // ---- // set(): 1, 2, 3, 4, 5 -> true -// gas irOptimized: 163719 +// gas irOptimized: 163680 // gas legacy: 163756 // gas legacyOptimized: 163596 // storage: nonempty diff --git a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol index 9fceb5596..002801ea7 100644 --- a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol @@ -20,6 +20,6 @@ contract C { // compileViaYul: also // ---- // f() -> 3 -// gas irOptimized: 174188 +// gas irOptimized: 173135 // gas legacy: 179707 // gas legacyOptimized: 178763 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol index 7619e1fda..14ad10b79 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol @@ -19,6 +19,6 @@ contract C { // compileViaYul: also // ---- // f() -> 1, 2, 3, 4, 5, 6, 7 -// gas irOptimized: 212646 +// gas irOptimized: 212108 // gas legacy: 223725 // gas legacyOptimized: 222886 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol index c519bc50d..d20d7b3b1 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol @@ -13,6 +13,6 @@ contract C { // compileViaYul: also // ---- // f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000 -// gas irOptimized: 198396 +// gas irOptimized: 198279 // gas legacy: 199159 // gas legacyOptimized: 198137 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol index 02bb25b12..a6c41a277 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol @@ -20,6 +20,6 @@ contract C { // compileViaYul: also // ---- // f() -> 1, 2, 3, 4, 5, 6, 7 -// gas irOptimized: 212646 +// gas irOptimized: 212108 // gas legacy: 223730 // gas legacyOptimized: 222891 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol index f12955480..dd2b9fa66 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol @@ -26,6 +26,6 @@ contract C { // compileViaYul: also // ---- // f() -> 11, 0x0c, 1, 0x15, 22, 4 -// gas irOptimized: 289252 +// gas irOptimized: 288695 // gas legacy: 296916 // gas legacyOptimized: 283163 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol index 20a4a6d27..c2dd880db 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol @@ -15,6 +15,6 @@ contract C { // compileViaYul: also // ---- // f() -> 2, 3, 4 -// gas irOptimized: 209796 +// gas irOptimized: 208083 // gas legacy: 241549 // gas legacyOptimized: 236002 diff --git a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol index d333e70ef..b0589ef4b 100644 --- a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol +++ b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol @@ -18,6 +18,6 @@ contract c { // compileViaYul: also // ---- // test1() -> true -// gas irOptimized: 532255 +// gas irOptimized: 527501 // gas legacy: 613377 // gas legacyOptimized: 606411 diff --git a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol index 3d914e681..96bc13051 100644 --- a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol +++ b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol @@ -16,4 +16,4 @@ contract C { // compileViaYul: also // ---- // f() -> 0, 0, 0 -// gas irOptimized: 101573 +// gas irOptimized: 101279 diff --git a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol index f614d04ef..24efe49ba 100644 --- a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol @@ -16,7 +16,7 @@ contract c { // ---- // storage: empty // fill() -> -// gas irOptimized: 535917 +// gas irOptimized: 535098 // gas legacy: 504373 // gas legacyOptimized: 499648 // storage: nonempty diff --git a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol index bcd034c67..9f23c9fae 100644 --- a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol @@ -44,7 +44,7 @@ contract c { // ---- // getLengths() -> 0, 0 // setLengths(uint256,uint256): 48, 49 -> -// gas irOptimized: 275838 +// gas irOptimized: 273726 // gas legacy: 308271 // gas legacyOptimized: 300117 // getLengths() -> 48, 49 diff --git a/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol index 1f7eaa582..79ce756ed 100644 --- a/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol @@ -18,7 +18,7 @@ contract c { // ---- // storage: empty // fill() -> 8 -// gas irOptimized: 170102 +// gas irOptimized: 168980 // gas legacy: 165456 // gas legacyOptimized: 164387 // storage: nonempty diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol index 641ebe994..8ef94a432 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol @@ -25,7 +25,7 @@ contract c { // compileViaYul: also // ---- // test() -> 1, 2, 3 -// gas irOptimized: 2461941 +// gas irOptimized: 2455497 // gas legacy: 2416722 // gas legacyOptimized: 2405396 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol index ce8b56f0c..375487d97 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol @@ -20,7 +20,7 @@ contract c { // compileViaYul: also // ---- // test() -> 38, 28, 18 -// gas irOptimized: 532515 +// gas irOptimized: 527367 // gas legacy: 454080 // gas legacyOptimized: 443170 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol index 71e13a88a..e849e2c91 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol @@ -20,7 +20,7 @@ contract c { // compileViaYul: also // ---- // test() -> 20, 10 -// gas irOptimized: 369849 +// gas irOptimized: 367121 // gas legacy: 320859 // gas legacyOptimized: 314681 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol index a0722f597..5e9c9d60d 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol @@ -12,6 +12,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0x20, 29, 0x0303030303030303030303030303030303030303030303030303030303000000 -// gas irOptimized: 162592 +// gas irOptimized: 162426 // gas legacy: 245809 // gas legacyOptimized: 242636 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol index 54a4949e9..103563b2a 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol @@ -18,7 +18,7 @@ contract c { // compileViaYul: also // ---- // test() -> true -// gas irOptimized: 447028 +// gas irOptimized: 445718 // gas legacy: 552064 // gas legacyOptimized: 533164 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol index 61720d0aa..0e8bda56c 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol @@ -17,7 +17,7 @@ contract c { // compileViaYul: also // ---- // test() -> -// gas irOptimized: 291984 +// gas irOptimized: 291114 // gas legacy: 372763 // gas legacyOptimized: 366846 // storage: empty diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol index e5b28c92d..b11950fd6 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol @@ -12,6 +12,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 159929 +// gas irOptimized: 159714 // gas legacy: 243287 // gas legacyOptimized: 240361 diff --git a/test/libsolidity/semanticTests/array/push/array_push.sol b/test/libsolidity/semanticTests/array/push/array_push.sol index 4ad82d666..a2733ece1 100644 --- a/test/libsolidity/semanticTests/array/push/array_push.sol +++ b/test/libsolidity/semanticTests/array/push/array_push.sol @@ -18,6 +18,6 @@ contract c { // compileViaYul: also // ---- // test() -> 5, 4, 3, 3 -// gas irOptimized: 110915 +// gas irOptimized: 110669 // gas legacy: 111938 // gas legacyOptimized: 110528 diff --git a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol index fec11262b..db2ef2a55 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol @@ -14,6 +14,6 @@ contract C { // compileViaYul: also // ---- // f(uint120[]): 0x20, 3, 1, 2, 3 -> 1 -// gas irOptimized: 116340 +// gas irOptimized: 116184 // gas legacy: 116886 // gas legacyOptimized: 116699 diff --git a/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol b/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol index 4e9d2af1c..5565eb34b 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol @@ -16,6 +16,6 @@ contract c { // compileViaYul: also // ---- // test() -> 1, 2, 3, 4 -// gas irOptimized: 112009 +// gas irOptimized: 111583 // gas legacy: 107098 // gas legacyOptimized: 106362 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct.sol b/test/libsolidity/semanticTests/array/push/array_push_struct.sol index 3704adfd6..a1bed199e 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct.sol @@ -22,6 +22,6 @@ contract c { // compileViaYul: also // ---- // test() -> 2, 3, 4, 5 -// gas irOptimized: 146470 +// gas irOptimized: 146270 // gas legacy: 190684 // gas legacyOptimized: 188256 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol index dbfa16ab4..07b135f68 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol @@ -18,6 +18,6 @@ contract c { // compileViaYul: also // ---- // test((uint16,uint16,uint16[3],uint16[])): 0x20, 2, 3, 0, 0, 4, 0xC0, 4, 0, 0, 5, 0, 0 -> 2, 3, 4, 5 -// gas irOptimized: 148198 +// gas irOptimized: 147998 // gas legacy: 152444 // gas legacyOptimized: 146671 diff --git a/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol b/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol index 227d605d0..eabef2776 100644 --- a/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol +++ b/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol @@ -17,6 +17,6 @@ contract c { // compileViaYul: also // ---- // test() -> 0 -// gas irOptimized: 396502 +// gas irOptimized: 394087 // gas legacy: 565428 // gas legacyOptimized: 552524 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol index 694af34ac..56e35874a 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol @@ -29,14 +29,14 @@ contract C { // ---- // l() -> 0 // f(uint256,uint256): 42, 64 -> -// gas irOptimized: 202660 +// gas irOptimized: 202621 // gas legacy: 163034 // gas legacyOptimized: 157045 // l() -> 1 // ll(uint256): 0 -> 43 // a(uint256,uint256): 0, 42 -> 64 // f(uint256,uint256): 84, 128 -> -// gas irOptimized: 298876 +// gas irOptimized: 298837 // gas legacy: 222080 // gas legacyOptimized: 210631 // l() -> 2 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol index 94d308e48..933e5c13a 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol @@ -23,7 +23,7 @@ contract C { // ---- // l() -> 0 // g(uint256): 70 -> -// gas irOptimized: 430584 +// gas irOptimized: 428829 // gas legacy: 419791 // gas legacyOptimized: 415408 // l() -> 70 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index d28d20da9..d448f55c8 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 469081 +// gas irOptimized: 474619 // gas legacy: 570900 // gas legacyOptimized: 436724 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index d9e4d27a9..12b9beeb2 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 325793 +// gas irOptimized: 330923 // gas legacy: 414850 // gas legacyOptimized: 292281 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol index c17722a54..7a2ab84fb 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol @@ -18,6 +18,6 @@ contract C { // compileViaYul: also // ---- // f(uint32,(uint128,uint256[][2],uint32)): 55, 0x40, 77, 0x60, 88, 0x40, 0x40, 2, 1, 2 -> 55, 77, 1, 2, 88 -// gas irOptimized: 197936 +// gas irOptimized: 197768 // gas legacy: 205149 // gas legacyOptimized: 196983 diff --git a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol index 97c551032..363a44023 100644 --- a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol +++ b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol @@ -25,7 +25,7 @@ contract c { // ---- // storage: empty // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true -// gas irOptimized: 124266 +// gas irOptimized: 124227 // gas legacy: 124736 // gas legacyOptimized: 124179 // test(uint256): 32 -> "3" diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol index a5bc43be5..57102e996 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol @@ -33,4 +33,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0, 0, 0 -// gas irOptimized: 124110 +// gas irOptimized: 123854 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol index f771b1962..45b63742a 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol @@ -44,7 +44,7 @@ contract C { // compileViaYul: also // ---- // f() -> -// gas irOptimized: 123095 +// gas irOptimized: 122810 // gas legacy: 126832 // gas legacyOptimized: 125500 // g() -> diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol index ab2f82db8..f94729325 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol @@ -27,4 +27,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0 -// gas irOptimized: 118035 +// gas irOptimized: 117902 diff --git a/test/libsolidity/semanticTests/various/destructuring_assignment.sol b/test/libsolidity/semanticTests/various/destructuring_assignment.sol index 9d2413c2d..03b302cb0 100644 --- a/test/libsolidity/semanticTests/various/destructuring_assignment.sol +++ b/test/libsolidity/semanticTests/various/destructuring_assignment.sol @@ -36,6 +36,6 @@ contract C { // compileViaYul: also // ---- // f(bytes): 0x20, 0x5, "abcde" -> 0 -// gas irOptimized: 241858 +// gas irOptimized: 241342 // gas legacy: 239258 // gas legacyOptimized: 238582 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index 1f16c1c2a..e61ff84c9 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -22,6 +22,6 @@ contract C { // compileViaYul: also // ---- // g() -> 2, 6 -// gas irOptimized: 169848 +// gas irOptimized: 169804 // gas legacy: 172490 // gas legacyOptimized: 171209 diff --git a/test/libsolidity/semanticTests/viaYul/array_storage_index_access.sol b/test/libsolidity/semanticTests/viaYul/array_storage_index_access.sol index a271622d3..3ec0d9d60 100644 --- a/test/libsolidity/semanticTests/viaYul/array_storage_index_access.sol +++ b/test/libsolidity/semanticTests/viaYul/array_storage_index_access.sol @@ -18,33 +18,33 @@ contract C { // ---- // test_indices(uint256): 1 -> // test_indices(uint256): 129 -> -// gas irOptimized: 3457322 +// gas irOptimized: 3442268 // gas legacy: 3340105 // gas legacyOptimized: 3280773 // test_indices(uint256): 5 -> -// gas irOptimized: 474246 +// gas irOptimized: 467656 // gas legacy: 458941 // gas legacyOptimized: 455849 // test_indices(uint256): 10 -> // test_indices(uint256): 15 -> -// gas irOptimized: 110435 +// gas irOptimized: 109070 // test_indices(uint256): 0xFF -> -// gas irOptimized: 4338190 +// gas irOptimized: 4308940 // gas legacy: 4107867 // gas legacyOptimized: 3991807 // test_indices(uint256): 1000 -> -// gas irOptimized: 21240617 +// gas irOptimized: 21133562 // gas legacy: 20360399 // gas legacyOptimized: 19921344 // test_indices(uint256): 129 -> -// gas irOptimized: 3654995 +// gas irOptimized: 3601383 // gas legacy: 3472135 // gas legacyOptimized: 3415947 // test_indices(uint256): 128 -> -// gas irOptimized: 658131 +// gas irOptimized: 648097 // gas legacy: 556972 // gas legacyOptimized: 508124 // test_indices(uint256): 1 -> -// gas irOptimized: 464827 +// gas irOptimized: 458399 // gas legacy: 452407 // gas legacyOptimized: 450811 diff --git a/test/libsolidity/semanticTests/viaYul/array_storage_index_boundary_test.sol b/test/libsolidity/semanticTests/viaYul/array_storage_index_boundary_test.sol index 24c751472..d40970f22 100644 --- a/test/libsolidity/semanticTests/viaYul/array_storage_index_boundary_test.sol +++ b/test/libsolidity/semanticTests/viaYul/array_storage_index_boundary_test.sol @@ -18,11 +18,11 @@ contract C { // test_boundary_check(uint256,uint256): 1, 1 -> FAILURE, hex"4e487b71", 0x32 // test_boundary_check(uint256,uint256): 10, 10 -> FAILURE, hex"4e487b71", 0x32 // test_boundary_check(uint256,uint256): 256, 256 -> FAILURE, hex"4e487b71", 0x32 -// gas irOptimized: 677730 +// gas irOptimized: 668136 // gas legacy: 648515 // gas legacyOptimized: 628739 // test_boundary_check(uint256,uint256): 256, 255 -> 0 -// gas irOptimized: 678750 +// gas irOptimized: 669117 // gas legacy: 649549 // gas legacyOptimized: 629633 // test_boundary_check(uint256,uint256): 256, 0xFFFF -> FAILURE, hex"4e487b71", 0x32 diff --git a/test/libsolidity/semanticTests/viaYul/array_storage_index_zeroed_test.sol b/test/libsolidity/semanticTests/viaYul/array_storage_index_zeroed_test.sol index e650bb15c..8a64afa27 100644 --- a/test/libsolidity/semanticTests/viaYul/array_storage_index_zeroed_test.sol +++ b/test/libsolidity/semanticTests/viaYul/array_storage_index_zeroed_test.sol @@ -54,18 +54,18 @@ contract C { // ---- // test_zeroed_indicies(uint256): 1 -> // test_zeroed_indicies(uint256): 5 -> -// gas irOptimized: 198357 +// gas irOptimized: 196818 // gas legacy: 191267 // gas legacyOptimized: 188486 // test_zeroed_indicies(uint256): 10 -> -// gas irOptimized: 289249 +// gas irOptimized: 286446 // gas legacy: 276129 // gas legacyOptimized: 271024 // test_zeroed_indicies(uint256): 15 -> -// gas irOptimized: 358284 +// gas irOptimized: 354256 // gas legacy: 339254 // gas legacyOptimized: 331904 // test_zeroed_indicies(uint256): 0xFF -> -// gas irOptimized: 8808359 +// gas irOptimized: 8736366 // gas legacy: 8477449 // gas legacyOptimized: 8343774 diff --git a/test/libsolidity/semanticTests/viaYul/array_storage_push_empty.sol b/test/libsolidity/semanticTests/viaYul/array_storage_push_empty.sol index 73e3c6b5d..3813477dd 100644 --- a/test/libsolidity/semanticTests/viaYul/array_storage_push_empty.sol +++ b/test/libsolidity/semanticTests/viaYul/array_storage_push_empty.sol @@ -13,11 +13,11 @@ contract C { // compileViaYul: also // ---- // pushEmpty(uint256): 128 -// gas irOptimized: 630896 +// gas irOptimized: 620912 // gas legacy: 607287 // gas legacyOptimized: 589048 // pushEmpty(uint256): 256 -// gas irOptimized: 861040 +// gas irOptimized: 846064 // gas legacy: 828983 // gas legacyOptimized: 802808 // pushEmpty(uint256): 32768 -> FAILURE # out-of-gas # diff --git a/test/libsolidity/semanticTests/viaYul/array_storage_push_empty_length_address.sol b/test/libsolidity/semanticTests/viaYul/array_storage_push_empty_length_address.sol index 73797e552..bbd3e55f8 100644 --- a/test/libsolidity/semanticTests/viaYul/array_storage_push_empty_length_address.sol +++ b/test/libsolidity/semanticTests/viaYul/array_storage_push_empty_length_address.sol @@ -18,15 +18,15 @@ contract C { // set_get_length(uint256): 10 -> 10 // set_get_length(uint256): 20 -> 20 // set_get_length(uint256): 0 -> 0 -// gas irOptimized: 110079 +// gas irOptimized: 109299 // gas legacy: 107830 // gas legacyOptimized: 107262 // set_get_length(uint256): 0xFF -> 0xFF -// gas irOptimized: 701506 +// gas irOptimized: 691561 // gas legacy: 882337 // gas legacyOptimized: 650704 // set_get_length(uint256): 0xFFF -> 0xFFF -// gas irOptimized: 10226863 +// gas irOptimized: 10077103 // gas legacy: 12945874 // gas legacyOptimized: 9462646 // set_get_length(uint256): 0xFFFF -> FAILURE # Out-of-gas # diff --git a/test/libsolidity/semanticTests/viaYul/array_storage_push_pop.sol b/test/libsolidity/semanticTests/viaYul/array_storage_push_pop.sol index b78a5d2f0..d98940d07 100644 --- a/test/libsolidity/semanticTests/viaYul/array_storage_push_pop.sol +++ b/test/libsolidity/semanticTests/viaYul/array_storage_push_pop.sol @@ -15,15 +15,15 @@ contract C { // set_get_length(uint256): 1 -> 0 // set_get_length(uint256): 10 -> 0 // set_get_length(uint256): 20 -> 0 -// gas irOptimized: 162505 +// gas irOptimized: 160945 // gas legacy: 141922 // gas legacyOptimized: 139708 // set_get_length(uint256): 0xFF -> 0 -// gas irOptimized: 1790350 +// gas irOptimized: 1770460 // gas legacy: 1524427 // gas legacyOptimized: 1500358 // set_get_length(uint256): 0xFFF -> 0 -// gas irOptimized: 28390042 +// gas irOptimized: 28070632 // gas legacy: 24115159 // gas legacyOptimized: 23733970 // set_get_length(uint256): 0xFFFF -> FAILURE # Out-of-gas # From b599235b8d8495866110f990b71187e5055d3689 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Wed, 14 Apr 2021 17:04:26 +0200 Subject: [PATCH 9/9] Skip resolving Keccak if AST contains msize. Also a refactoring changing `m_optimizeMLoad` to `m_containsMSize`. --- libyul/optimiser/LoadResolver.cpp | 6 +++--- libyul/optimiser/LoadResolver.h | 7 ++++--- .../loadResolver/keccak_with_msize.yul | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index f73cd48bc..3ef080155 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -48,7 +48,7 @@ void LoadResolver::run(OptimiserStepContext& _context, Block& _ast) LoadResolver{ _context.dialect, SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)), - !containsMSize, + containsMSize, _context.expectedExecutionsPerDeployment }(_ast); } @@ -66,7 +66,7 @@ void LoadResolver::visit(Expression& _e) break; } - if (funCall->functionName.name == m_dialect.hashFunction({})) + if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction({})) tryEvaluateKeccak(_e, funCall->arguments); } } @@ -87,7 +87,7 @@ void LoadResolver::tryResolve( if (inScope(*value)) _e = Identifier{locationOf(_e), *value}; } - else if (m_optimizeMLoad && _location == StoreLoadLocation::Memory) + else if (!m_containsMSize && _location == StoreLoadLocation::Memory) if (auto value = util::valueOrNullptr(m_memory, key)) if (inScope(*value)) _e = Identifier{locationOf(_e), *value}; diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index e1758bf6b..93d37d779 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -50,11 +50,11 @@ private: LoadResolver( Dialect const& _dialect, std::map _functionSideEffects, - bool _optimizeMLoad, + bool _containsMSize, std::optional _expectedExecutionsPerDeployment ): DataFlowAnalyzer(_dialect, std::move(_functionSideEffects)), - m_optimizeMLoad(_optimizeMLoad), + m_containsMSize(_containsMSize), m_expectedExecutionsPerDeployment(std::move(_expectedExecutionsPerDeployment)) {} @@ -75,7 +75,8 @@ protected: std::vector const& _arguments ); - bool m_optimizeMLoad = false; + /// If the AST contains `msize`, then we skip resolving `mload` and `keccak256`. + bool m_containsMSize = false; /// The --optimize-runs parameter. Value `nullopt` represents creation code. std::optional m_expectedExecutionsPerDeployment; }; diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul new file mode 100644 index 000000000..fdc1e8836 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_with_msize.yul @@ -0,0 +1,19 @@ +{ + sstore(0, msize()) + mstore(0, 10) + // Keccak-256 should not be evaluated because of the msize. + // Even though, though the code is likely equivalent, + // we skip steps if `msize` is present + let val := keccak256(0, 32) + sstore(1, val) +} +// ---- +// step: loadResolver +// +// { +// let _1 := msize() +// let _2 := 0 +// sstore(_2, _1) +// mstore(_2, 10) +// sstore(1, keccak256(_2, 32)) +// }