mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12272 from ethereum/equalStoreEliminator
Equal store eliminator.
This commit is contained in:
commit
c16867cb83
@ -5,6 +5,7 @@ Language Features:
|
|||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Yul Optimizer: Remove ``mstore`` and ``sstore`` operations if the slot already contains the same value.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -290,6 +290,7 @@ on the individual steps and their sequence below.
|
|||||||
- :ref:`conditional-unsimplifier`.
|
- :ref:`conditional-unsimplifier`.
|
||||||
- :ref:`control-flow-simplifier`.
|
- :ref:`control-flow-simplifier`.
|
||||||
- :ref:`dead-code-eliminator`.
|
- :ref:`dead-code-eliminator`.
|
||||||
|
- :ref:`equal-store-eliminator`.
|
||||||
- :ref:`equivalent-function-combiner`.
|
- :ref:`equivalent-function-combiner`.
|
||||||
- :ref:`expression-joiner`.
|
- :ref:`expression-joiner`.
|
||||||
- :ref:`expression-simplifier`.
|
- :ref:`expression-simplifier`.
|
||||||
@ -938,6 +939,22 @@ we require ForLoopInitRewriter to run before this step.
|
|||||||
|
|
||||||
Prerequisite: ForLoopInitRewriter, Function Hoister, Function Grouper
|
Prerequisite: ForLoopInitRewriter, Function Hoister, Function Grouper
|
||||||
|
|
||||||
|
.. _equal-store-eliminator:
|
||||||
|
|
||||||
|
EqualStoreEliminator
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This steps removes ``mstore(k, v)`` and ``sstore(k, v)`` calls if
|
||||||
|
there was a previous call to ``mstore(k, v)`` / ``sstore(k, v)``,
|
||||||
|
no other store in between and the values of ``k`` and ``v`` did not change.
|
||||||
|
|
||||||
|
This simple step is effective if run after the SSA transform and the
|
||||||
|
Common Subexpression Eliminator, because SSA will make sure that the variables
|
||||||
|
will not change and the Common Subexpression Eliminator re-uses exactly the same
|
||||||
|
variable if the value is known to be the same.
|
||||||
|
|
||||||
|
Prerequisites: Disambiguator, ForLoopInitRewriter
|
||||||
|
|
||||||
.. _unused-pruner:
|
.. _unused-pruner:
|
||||||
|
|
||||||
UnusedPruner
|
UnusedPruner
|
||||||
|
@ -44,7 +44,7 @@ struct OptimiserSettings
|
|||||||
static char constexpr DefaultYulOptimiserSteps[] =
|
static char constexpr DefaultYulOptimiserSteps[] =
|
||||||
"dhfoDgvulfnTUtnIf" // None of these can make stack problems worse
|
"dhfoDgvulfnTUtnIf" // None of these can make stack problems worse
|
||||||
"["
|
"["
|
||||||
"xa[r]scLM" // Turn into SSA and simplify
|
"xa[r]EscLM" // Turn into SSA and simplify
|
||||||
"cCTUtTOntnfDIul" // Perform structural simplification
|
"cCTUtTOntnfDIul" // Perform structural simplification
|
||||||
"Lcul" // Simplify again
|
"Lcul" // Simplify again
|
||||||
"Vcul [j]" // Reverse SSA
|
"Vcul [j]" // Reverse SSA
|
||||||
|
@ -120,6 +120,8 @@ add_library(yul
|
|||||||
optimiser/DeadCodeEliminator.h
|
optimiser/DeadCodeEliminator.h
|
||||||
optimiser/Disambiguator.cpp
|
optimiser/Disambiguator.cpp
|
||||||
optimiser/Disambiguator.h
|
optimiser/Disambiguator.h
|
||||||
|
optimiser/EqualStoreEliminator.cpp
|
||||||
|
optimiser/EqualStoreEliminator.h
|
||||||
optimiser/EquivalentFunctionDetector.cpp
|
optimiser/EquivalentFunctionDetector.cpp
|
||||||
optimiser/EquivalentFunctionDetector.h
|
optimiser/EquivalentFunctionDetector.h
|
||||||
optimiser/EquivalentFunctionCombiner.cpp
|
optimiser/EquivalentFunctionCombiner.cpp
|
||||||
|
70
libyul/optimiser/EqualStoreEliminator.cpp
Normal file
70
libyul/optimiser/EqualStoreEliminator.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/**
|
||||||
|
* Optimisation stage that removes mstore and sstore operations if they store the same
|
||||||
|
* value that is already known to be in that slot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libyul/optimiser/EqualStoreEliminator.h>
|
||||||
|
|
||||||
|
#include <libyul/optimiser/CallGraphGenerator.h>
|
||||||
|
#include <libyul/optimiser/OptimizerUtilities.h>
|
||||||
|
#include <libyul/optimiser/Semantics.h>
|
||||||
|
#include <libyul/AST.h>
|
||||||
|
#include <libyul/Utilities.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace solidity;
|
||||||
|
using namespace solidity::util;
|
||||||
|
using namespace solidity::evmasm;
|
||||||
|
using namespace solidity::yul;
|
||||||
|
|
||||||
|
void EqualStoreEliminator::run(OptimiserStepContext const& _context, Block& _ast)
|
||||||
|
{
|
||||||
|
EqualStoreEliminator eliminator{
|
||||||
|
_context.dialect,
|
||||||
|
SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast))
|
||||||
|
};
|
||||||
|
eliminator(_ast);
|
||||||
|
|
||||||
|
StatementRemover remover{eliminator.m_pendingRemovals};
|
||||||
|
remover(_ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EqualStoreEliminator::visit(Statement& _statement)
|
||||||
|
{
|
||||||
|
// No need to consider potential changes through complex arguments since
|
||||||
|
// isSimpleStore only returns something if the arguments are identifiers.
|
||||||
|
if (ExpressionStatement const* expression = get_if<ExpressionStatement>(&_statement))
|
||||||
|
{
|
||||||
|
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, *expression))
|
||||||
|
{
|
||||||
|
if (auto const* currentValue = valueOrNullptr(m_storage, vars->first))
|
||||||
|
if (*currentValue == vars->second)
|
||||||
|
m_pendingRemovals.insert(&_statement);
|
||||||
|
}
|
||||||
|
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, *expression))
|
||||||
|
{
|
||||||
|
if (auto const* currentValue = valueOrNullptr(m_memory, vars->first))
|
||||||
|
if (*currentValue == vars->second)
|
||||||
|
m_pendingRemovals.insert(&_statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataFlowAnalyzer::visit(_statement);
|
||||||
|
}
|
60
libyul/optimiser/EqualStoreEliminator.h
Normal file
60
libyul/optimiser/EqualStoreEliminator.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/**
|
||||||
|
* Optimisation stage that removes mstore and sstore operations if they store the same
|
||||||
|
* value that is already known to be in that slot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libyul/optimiser/DataFlowAnalyzer.h>
|
||||||
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
|
|
||||||
|
namespace solidity::yul
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimisation stage that removes mstore and sstore operations if they store the same
|
||||||
|
* value that is already known to be in that slot.
|
||||||
|
*
|
||||||
|
* Works best if the code is in SSA form - without literal arguments.
|
||||||
|
*
|
||||||
|
* Prerequisite: Disambiguator, ForLoopInitRewriter.
|
||||||
|
*/
|
||||||
|
class EqualStoreEliminator: public DataFlowAnalyzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr char const* name{"EqualStoreEliminator"};
|
||||||
|
static void run(OptimiserStepContext const&, Block& _ast);
|
||||||
|
|
||||||
|
private:
|
||||||
|
EqualStoreEliminator(
|
||||||
|
Dialect const& _dialect,
|
||||||
|
std::map<YulString, SideEffects> _functionSideEffects
|
||||||
|
):
|
||||||
|
DataFlowAnalyzer(_dialect, std::move(_functionSideEffects))
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using ASTModifier::visit;
|
||||||
|
void visit(Statement& _statement) override;
|
||||||
|
|
||||||
|
std::set<Statement const*> m_pendingRemovals;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -57,3 +57,18 @@ optional<evmasm::Instruction> yul::toEVMInstruction(Dialect const& _dialect, Yul
|
|||||||
return builtin->instruction;
|
return builtin->instruction;
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatementRemover::operator()(Block& _block)
|
||||||
|
{
|
||||||
|
util::iterateReplacing(
|
||||||
|
_block.statements,
|
||||||
|
[&](Statement& _statement) -> std::optional<vector<Statement>>
|
||||||
|
{
|
||||||
|
if (m_toRemove.count(&_statement))
|
||||||
|
return {vector<Statement>{}};
|
||||||
|
else
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
ASTModifier::operator()(_block);
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <libyul/ASTForward.h>
|
#include <libyul/ASTForward.h>
|
||||||
#include <libyul/Dialect.h>
|
#include <libyul/Dialect.h>
|
||||||
#include <libyul/YulString.h>
|
#include <libyul/YulString.h>
|
||||||
|
#include <libyul/optimiser/ASTWalker.h>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
@ -48,4 +49,14 @@ bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifie
|
|||||||
/// Helper function that returns the instruction, if the `_name` is a BuiltinFunction
|
/// Helper function that returns the instruction, if the `_name` is a BuiltinFunction
|
||||||
std::optional<evmasm::Instruction> toEVMInstruction(Dialect const& _dialect, YulString const& _name);
|
std::optional<evmasm::Instruction> toEVMInstruction(Dialect const& _dialect, YulString const& _name);
|
||||||
|
|
||||||
|
class StatementRemover: public ASTModifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit StatementRemover(std::set<Statement const*> const& _toRemove): m_toRemove(_toRemove) {}
|
||||||
|
|
||||||
|
void operator()(Block& _block) override;
|
||||||
|
private:
|
||||||
|
std::set<Statement const*> const& m_toRemove;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <libyul/optimiser/DeadCodeEliminator.h>
|
#include <libyul/optimiser/DeadCodeEliminator.h>
|
||||||
#include <libyul/optimiser/FunctionGrouper.h>
|
#include <libyul/optimiser/FunctionGrouper.h>
|
||||||
#include <libyul/optimiser/FunctionHoister.h>
|
#include <libyul/optimiser/FunctionHoister.h>
|
||||||
|
#include <libyul/optimiser/EqualStoreEliminator.h>
|
||||||
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
||||||
#include <libyul/optimiser/ExpressionSplitter.h>
|
#include <libyul/optimiser/ExpressionSplitter.h>
|
||||||
#include <libyul/optimiser/ExpressionJoiner.h>
|
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||||
@ -204,6 +205,7 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
|
|||||||
ConditionalUnsimplifier,
|
ConditionalUnsimplifier,
|
||||||
ControlFlowSimplifier,
|
ControlFlowSimplifier,
|
||||||
DeadCodeEliminator,
|
DeadCodeEliminator,
|
||||||
|
EqualStoreEliminator,
|
||||||
EquivalentFunctionCombiner,
|
EquivalentFunctionCombiner,
|
||||||
ExpressionInliner,
|
ExpressionInliner,
|
||||||
ExpressionJoiner,
|
ExpressionJoiner,
|
||||||
@ -244,6 +246,7 @@ map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
|
|||||||
{ConditionalUnsimplifier::name, 'U'},
|
{ConditionalUnsimplifier::name, 'U'},
|
||||||
{ControlFlowSimplifier::name, 'n'},
|
{ControlFlowSimplifier::name, 'n'},
|
||||||
{DeadCodeEliminator::name, 'D'},
|
{DeadCodeEliminator::name, 'D'},
|
||||||
|
{EqualStoreEliminator::name, 'E'},
|
||||||
{EquivalentFunctionCombiner::name, 'v'},
|
{EquivalentFunctionCombiner::name, 'v'},
|
||||||
{ExpressionInliner::name, 'e'},
|
{ExpressionInliner::name, 'e'},
|
||||||
{ExpressionJoiner::name, 'j'},
|
{ExpressionJoiner::name, 'j'},
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <libyul/optimiser/UnusedAssignEliminator.h>
|
#include <libyul/optimiser/UnusedAssignEliminator.h>
|
||||||
|
|
||||||
#include <libyul/optimiser/Semantics.h>
|
#include <libyul/optimiser/Semantics.h>
|
||||||
|
#include <libyul/optimiser/OptimizerUtilities.h>
|
||||||
#include <libyul/AST.h>
|
#include <libyul/AST.h>
|
||||||
|
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
|
@ -156,18 +156,3 @@ void UnusedStoreBase::merge(TrackedStores& _target, vector<TrackedStores>&& _sou
|
|||||||
merge(_target, move(ts));
|
merge(_target, move(ts));
|
||||||
_source.clear();
|
_source.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatementRemover::operator()(Block& _block)
|
|
||||||
{
|
|
||||||
util::iterateReplacing(
|
|
||||||
_block.statements,
|
|
||||||
[&](Statement& _statement) -> std::optional<vector<Statement>>
|
|
||||||
{
|
|
||||||
if (m_toRemove.count(&_statement))
|
|
||||||
return {vector<Statement>{}};
|
|
||||||
else
|
|
||||||
return nullopt;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
ASTModifier::operator()(_block);
|
|
||||||
}
|
|
||||||
|
@ -105,14 +105,4 @@ protected:
|
|||||||
size_t m_forLoopNestingDepth = 0;
|
size_t m_forLoopNestingDepth = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StatementRemover: public ASTModifier
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit StatementRemover(std::set<Statement const*> const& _toRemove): m_toRemove(_toRemove) {}
|
|
||||||
|
|
||||||
void operator()(Block& _block) override;
|
|
||||||
private:
|
|
||||||
std::set<Statement const*> const& m_toRemove;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ contract DepositContract is IDepositContract, ERC165 {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// constructor()
|
// constructor()
|
||||||
// gas irOptimized: 1558001
|
// gas irOptimized: 1557137
|
||||||
// gas legacy: 2436584
|
// gas legacy: 2436584
|
||||||
// gas legacyOptimized: 1776483
|
// gas legacyOptimized: 1776483
|
||||||
// supportsInterface(bytes4): 0x0 -> 0
|
// supportsInterface(bytes4): 0x0 -> 0
|
||||||
|
@ -20,7 +20,7 @@ contract test {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// set(uint8,uint8,uint8,uint8,uint8): 1, 21, 22, 42, 43 -> 0, 0, 0, 0
|
// set(uint8,uint8,uint8,uint8,uint8): 1, 21, 22, 42, 43 -> 0, 0, 0, 0
|
||||||
// gas irOptimized: 111965
|
// gas irOptimized: 111896
|
||||||
// gas legacy: 113806
|
// gas legacy: 113806
|
||||||
// gas legacyOptimized: 111781
|
// gas legacyOptimized: 111781
|
||||||
// get(uint8): 1 -> 21, 22, 42, 43
|
// get(uint8): 1 -> 21, 22, 42, 43
|
||||||
|
@ -38,12 +38,12 @@ contract c {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// set(uint256): 7 -> true
|
// set(uint256): 7 -> true
|
||||||
// gas irOptimized: 110011
|
// gas irOptimized: 110119
|
||||||
// gas legacy: 110616
|
// gas legacy: 110616
|
||||||
// gas legacyOptimized: 110006
|
// gas legacyOptimized: 110006
|
||||||
// retrieve(uint256): 7 -> 1, 3, 4, 2
|
// retrieve(uint256): 7 -> 1, 3, 4, 2
|
||||||
// copy(uint256,uint256): 7, 8 -> true
|
// copy(uint256,uint256): 7, 8 -> true
|
||||||
// gas irOptimized: 118707
|
// gas irOptimized: 118698
|
||||||
// gas legacy: 119166
|
// gas legacy: 119166
|
||||||
// gas legacyOptimized: 118622
|
// gas legacyOptimized: 118622
|
||||||
// retrieve(uint256): 7 -> 1, 3, 4, 2
|
// retrieve(uint256): 7 -> 1, 3, 4, 2
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <libyul/optimiser/ConditionalUnsimplifier.h>
|
#include <libyul/optimiser/ConditionalUnsimplifier.h>
|
||||||
#include <libyul/optimiser/ConditionalSimplifier.h>
|
#include <libyul/optimiser/ConditionalSimplifier.h>
|
||||||
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
||||||
|
#include <libyul/optimiser/EqualStoreEliminator.h>
|
||||||
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
||||||
#include <libyul/optimiser/ExpressionSplitter.h>
|
#include <libyul/optimiser/ExpressionSplitter.h>
|
||||||
#include <libyul/optimiser/FunctionGrouper.h>
|
#include <libyul/optimiser/FunctionGrouper.h>
|
||||||
@ -236,6 +237,11 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
|
|||||||
ForLoopInitRewriter::run(*m_context, *m_ast);
|
ForLoopInitRewriter::run(*m_context, *m_ast);
|
||||||
UnusedAssignEliminator::run(*m_context, *m_ast);
|
UnusedAssignEliminator::run(*m_context, *m_ast);
|
||||||
}},
|
}},
|
||||||
|
{"equalStoreEliminator", [&]() {
|
||||||
|
disambiguate();
|
||||||
|
ForLoopInitRewriter::run(*m_context, *m_ast);
|
||||||
|
EqualStoreEliminator::run(*m_context, *m_ast);
|
||||||
|
}},
|
||||||
{"ssaPlusCleanup", [&]() {
|
{"ssaPlusCleanup", [&]() {
|
||||||
disambiguate();
|
disambiguate();
|
||||||
ForLoopInitRewriter::run(*m_context, *m_ast);
|
ForLoopInitRewriter::run(*m_context, *m_ast);
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
let a := calldataload(0)
|
||||||
|
let b := 20
|
||||||
|
sstore(a, b)
|
||||||
|
if calldataload(32) {
|
||||||
|
sstore(a, b)
|
||||||
|
pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||||
|
sstore(a, b)
|
||||||
|
}
|
||||||
|
sstore(a, b)
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=byzantium
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let a := calldataload(0)
|
||||||
|
// let b := 20
|
||||||
|
// sstore(a, b)
|
||||||
|
// if calldataload(32)
|
||||||
|
// {
|
||||||
|
// pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||||
|
// }
|
||||||
|
// }
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
let x := calldataload(0)
|
||||||
|
let y := calldataload(1)
|
||||||
|
|
||||||
|
sstore(x, y)
|
||||||
|
for {let a := 1} lt(a, 10) {a := add(a, 1) } {
|
||||||
|
sstore(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let x := calldataload(0)
|
||||||
|
// let y := calldataload(1)
|
||||||
|
// sstore(x, y)
|
||||||
|
// let a := 1
|
||||||
|
// for { } lt(a, 10) { a := add(a, 1) }
|
||||||
|
// { sstore(x, y) }
|
||||||
|
// }
|
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
f(calldataload(0), calldataload(32))
|
||||||
|
h(calldataload(64), calldataload(96))
|
||||||
|
|
||||||
|
function f(a, b) {
|
||||||
|
// gets removed
|
||||||
|
sstore(a, b)
|
||||||
|
g()
|
||||||
|
sstore(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
function g() {
|
||||||
|
pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
function h(a_, b_) {
|
||||||
|
// cannot be removed
|
||||||
|
sstore(a_, b_)
|
||||||
|
i()
|
||||||
|
sstore(a_, b_)
|
||||||
|
}
|
||||||
|
|
||||||
|
function i() {
|
||||||
|
pop(delegatecall(0, 0, 0, 0, 0, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=byzantium
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// f(calldataload(0), calldataload(32))
|
||||||
|
// h(calldataload(64), calldataload(96))
|
||||||
|
// function f(a, b)
|
||||||
|
// {
|
||||||
|
// sstore(a, b)
|
||||||
|
// g()
|
||||||
|
// }
|
||||||
|
// function g()
|
||||||
|
// {
|
||||||
|
// pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||||
|
// }
|
||||||
|
// function h(a_, b_)
|
||||||
|
// {
|
||||||
|
// sstore(a_, b_)
|
||||||
|
// i()
|
||||||
|
// sstore(a_, b_)
|
||||||
|
// }
|
||||||
|
// function i()
|
||||||
|
// {
|
||||||
|
// pop(delegatecall(0, 0, 0, 0, 0, 0))
|
||||||
|
// }
|
||||||
|
// }
|
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
let x := calldataload(0)
|
||||||
|
let y := sload(x)
|
||||||
|
// both of these can be removed
|
||||||
|
sstore(x, y)
|
||||||
|
sstore(x, y)
|
||||||
|
|
||||||
|
let a := x
|
||||||
|
let b := mload(a)
|
||||||
|
// both of these can be removed
|
||||||
|
mstore(a, b)
|
||||||
|
mstore(a, b)
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=byzantium
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let x := calldataload(0)
|
||||||
|
// let y := sload(x)
|
||||||
|
// let a := x
|
||||||
|
// let b := mload(a)
|
||||||
|
// }
|
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
let var_k := calldataload(0)
|
||||||
|
let _1 := 0x00
|
||||||
|
let _2 := 0x20
|
||||||
|
mstore(_1, var_k)
|
||||||
|
mstore(_2, _1)
|
||||||
|
sstore(keccak256(_1, 0x40), 0x01)
|
||||||
|
mstore(_1, var_k)
|
||||||
|
mstore(_2, _1)
|
||||||
|
sstore(add(keccak256(_1, 0x40), 0x01), 0x03)
|
||||||
|
mstore(_1, var_k)
|
||||||
|
mstore(_2, _1)
|
||||||
|
sstore(add(keccak256(_1, 0x40), 2), 0x04)
|
||||||
|
mstore(_1, var_k)
|
||||||
|
mstore(_2, _1)
|
||||||
|
sstore(add(keccak256(_1, 0x40), 0x03), 2)
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let var_k := calldataload(0)
|
||||||
|
// let _1 := 0x00
|
||||||
|
// let _2 := 0x20
|
||||||
|
// mstore(_1, var_k)
|
||||||
|
// mstore(_2, _1)
|
||||||
|
// sstore(keccak256(_1, 0x40), 0x01)
|
||||||
|
// sstore(add(keccak256(_1, 0x40), 0x01), 0x03)
|
||||||
|
// sstore(add(keccak256(_1, 0x40), 2), 0x04)
|
||||||
|
// sstore(add(keccak256(_1, 0x40), 0x03), 2)
|
||||||
|
// }
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
let x := calldataload(0)
|
||||||
|
let y := calldataload(32)
|
||||||
|
sstore(x, y)
|
||||||
|
y := calldataload(64)
|
||||||
|
// cannot be removed
|
||||||
|
sstore(x, y)
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let x := calldataload(0)
|
||||||
|
// let y := calldataload(32)
|
||||||
|
// sstore(x, y)
|
||||||
|
// y := calldataload(64)
|
||||||
|
// sstore(x, y)
|
||||||
|
// }
|
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
let a := calldataload(0)
|
||||||
|
let b := 20
|
||||||
|
sstore(a, b)
|
||||||
|
if calldataload(32) {
|
||||||
|
sstore(a, b)
|
||||||
|
pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||||
|
verbatim_0i_0o("xyz")
|
||||||
|
}
|
||||||
|
sstore(a, b)
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=byzantium
|
||||||
|
// ----
|
||||||
|
// step: equalStoreEliminator
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let a := calldataload(0)
|
||||||
|
// let b := 20
|
||||||
|
// sstore(a, b)
|
||||||
|
// if calldataload(32)
|
||||||
|
// {
|
||||||
|
// pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||||
|
// verbatim_0i_0o("xyz")
|
||||||
|
// }
|
||||||
|
// sstore(a, b)
|
||||||
|
// }
|
@ -55,7 +55,6 @@
|
|||||||
// sstore(0, 0)
|
// sstore(0, 0)
|
||||||
// sstore(2, _1)
|
// sstore(2, _1)
|
||||||
// extcodecopy(_1, msize(), _1, _1)
|
// extcodecopy(_1, msize(), _1, _1)
|
||||||
// sstore(0, 0)
|
|
||||||
// sstore(3, _1)
|
// sstore(3, _1)
|
||||||
// }
|
// }
|
||||||
// function gcd(_a, _b) -> out
|
// function gcd(_a, _b) -> out
|
||||||
|
@ -20,9 +20,7 @@
|
|||||||
// f()
|
// f()
|
||||||
// sstore(0, 1)
|
// sstore(0, 1)
|
||||||
// f()
|
// f()
|
||||||
// sstore(0, 1)
|
|
||||||
// f()
|
// f()
|
||||||
// sstore(0, 1)
|
|
||||||
// }
|
// }
|
||||||
// function f()
|
// function f()
|
||||||
// {
|
// {
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
// f()
|
// f()
|
||||||
// sstore(0, 1)
|
// sstore(0, 1)
|
||||||
// f()
|
// f()
|
||||||
// sstore(0, 1)
|
|
||||||
// f()
|
// f()
|
||||||
// sstore(0, 1)
|
|
||||||
// }
|
// }
|
||||||
// function f()
|
// function f()
|
||||||
// {
|
// {
|
||||||
|
@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(output_operator_should_create_concise_and_unambiguous_strin
|
|||||||
|
|
||||||
BOOST_TEST(chromosome.length() == allSteps.size());
|
BOOST_TEST(chromosome.length() == allSteps.size());
|
||||||
BOOST_TEST(chromosome.optimisationSteps() == allSteps);
|
BOOST_TEST(chromosome.optimisationSteps() == allSteps);
|
||||||
BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighFTLMRmVatrpud");
|
BOOST_TEST(toString(chromosome) == "flcCUnDEvejsxIOoighFTLMRmVatrpud");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(optimisationSteps_should_translate_chromosomes_genes_to_optimisation_step_names)
|
BOOST_AUTO_TEST_CASE(optimisationSteps_should_translate_chromosomes_genes_to_optimisation_step_names)
|
||||||
|
Loading…
Reference in New Issue
Block a user