mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Redundant store eliminator.
This commit is contained in:
parent
2969bc0f3e
commit
5f7751f22c
@ -43,7 +43,7 @@ struct OptimiserSettings
|
||||
|
||||
"Tpeul" // Run functional expression inliner
|
||||
"xarulrul" // Prune a bit more in SSA
|
||||
"xarrcL" // Turn into SSA again and simplify
|
||||
"xarrcSL" // Turn into SSA again and simplify
|
||||
"gvif" // Run full inliner
|
||||
"CTUcarrLsTFOtfDncarrIulc" // SSA plus simplify
|
||||
"]"
|
||||
|
@ -162,6 +162,8 @@ add_library(yul
|
||||
optimiser/ReasoningBasedSimplifier.h
|
||||
optimiser/RedundantAssignEliminator.cpp
|
||||
optimiser/RedundantAssignEliminator.h
|
||||
optimiser/RedundantStoreEliminator.cpp
|
||||
optimiser/RedundantStoreEliminator.h
|
||||
optimiser/Rematerialiser.cpp
|
||||
optimiser/Rematerialiser.h
|
||||
optimiser/SSAReverser.cpp
|
||||
|
83
libyul/optimiser/RedundantStoreEliminator.cpp
Normal file
83
libyul/optimiser/RedundantStoreEliminator.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
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
|
||||
/**
|
||||
*/
|
||||
|
||||
#include <libyul/optimiser/RedundantStoreEliminator.h>
|
||||
|
||||
#include <libyul/optimiser/Semantics.h>
|
||||
#include <libyul/AST.h>
|
||||
|
||||
#include <libsolutil/CommonData.h>
|
||||
|
||||
#include <boost/range/algorithm_ext/erase.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::yul;
|
||||
|
||||
|
||||
void RedundantStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
|
||||
{
|
||||
RedundantStoreEliminator rse{_context.dialect};
|
||||
rse(_ast);
|
||||
}
|
||||
|
||||
void RedundantStoreEliminator::operator()(Block& _block)
|
||||
{
|
||||
// TODO This is copied from DataflowAnalyzer
|
||||
size_t numScopes = m_variableScopes.size();
|
||||
pushScope(false);
|
||||
|
||||
map<YulString, size_t> latestStore;
|
||||
set<size_t> redundantStores;
|
||||
|
||||
for (size_t i = 0; i < _block.statements.size(); ++i)
|
||||
{
|
||||
Statement& statement = _block.statements.at(i);
|
||||
if (holds_alternative<ExpressionStatement>(statement))
|
||||
{
|
||||
ExpressionStatement& exprStatement = get<ExpressionStatement>(statement);
|
||||
// This mechanism relies on the way the data flow analyzer
|
||||
// handles `m_storage`.
|
||||
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, exprStatement))
|
||||
{
|
||||
if (m_storage.count(vars->first) && latestStore.count(vars->first))
|
||||
redundantStores.insert(latestStore.at(vars->first));
|
||||
latestStore[vars->first] = i;
|
||||
}
|
||||
}
|
||||
ASTModifier::visit(statement);
|
||||
}
|
||||
|
||||
popScope();
|
||||
assertThrow(numScopes == m_variableScopes.size(), OptimizerException, "");
|
||||
DataFlowAnalyzer::operator()(_block);
|
||||
if (redundantStores.empty())
|
||||
return;
|
||||
|
||||
// The arguments to sstore are identifiers and thus do not have side-effects,
|
||||
// because otherwise the statement would not have ended up in `redundantStores`.
|
||||
vector<Statement> newStatements;
|
||||
for (size_t i = 0; i < _block.statements.size(); ++i)
|
||||
{
|
||||
if (!redundantStores.count(i))
|
||||
newStatements.emplace_back(move(_block.statements.at(i)));
|
||||
}
|
||||
_block.statements = move(newStatements);
|
||||
}
|
54
libyul/optimiser/RedundantStoreEliminator.h
Normal file
54
libyul/optimiser/RedundantStoreEliminator.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
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
|
||||
/**
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libyul/ASTForward.h>
|
||||
#include <libyul/optimiser/ASTWalker.h>
|
||||
#include <libyul/optimiser/OptimiserStep.h>
|
||||
#include <libyul/optimiser/DataFlowAnalyzer.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace solidity::yul
|
||||
{
|
||||
struct Dialect;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class RedundantStoreEliminator: public DataFlowAnalyzer
|
||||
{
|
||||
public:
|
||||
static constexpr char const* name{"RedundantStoreEliminator"};
|
||||
explicit RedundantStoreEliminator(
|
||||
Dialect const& _dialect
|
||||
): DataFlowAnalyzer(_dialect) {}
|
||||
static void run(OptimiserStepContext&, Block& _ast);
|
||||
|
||||
void operator()(Block& _block);
|
||||
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -56,6 +56,7 @@
|
||||
#include <libyul/optimiser/StructuralSimplifier.h>
|
||||
#include <libyul/optimiser/SyntacticalEquality.h>
|
||||
#include <libyul/optimiser/RedundantAssignEliminator.h>
|
||||
#include <libyul/optimiser/RedundantStoreEliminator.h>
|
||||
#include <libyul/optimiser/VarNameCleaner.h>
|
||||
#include <libyul/optimiser/LoadResolver.h>
|
||||
#include <libyul/optimiser/LoopInvariantCodeMotion.h>
|
||||
@ -200,6 +201,7 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
|
||||
LoadResolver,
|
||||
LoopInvariantCodeMotion,
|
||||
RedundantAssignEliminator,
|
||||
RedundantStoreEliminator,
|
||||
ReasoningBasedSimplifier,
|
||||
Rematerialiser,
|
||||
SSAReverser,
|
||||
@ -241,6 +243,7 @@ map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
|
||||
{LoopInvariantCodeMotion::name, 'M'},
|
||||
{ReasoningBasedSimplifier::name, 'R'},
|
||||
{RedundantAssignEliminator::name, 'r'},
|
||||
{RedundantStoreEliminator::name, 'S'},
|
||||
{Rematerialiser::name, 'm'},
|
||||
{SSAReverser::name, 'V'},
|
||||
{SSATransform::name, 'a'},
|
||||
|
@ -6,20 +6,6 @@ object "object" {
|
||||
code {
|
||||
{
|
||||
let _1 := 1
|
||||
sstore(_1, _1)
|
||||
sstore(2, _1)
|
||||
sstore(3, _1)
|
||||
sstore(4, _1)
|
||||
sstore(5, _1)
|
||||
sstore(6, _1)
|
||||
sstore(7, _1)
|
||||
sstore(8, _1)
|
||||
sstore(9, _1)
|
||||
sstore(10, _1)
|
||||
sstore(11, _1)
|
||||
sstore(12, _1)
|
||||
sstore(13, _1)
|
||||
sstore(_1, _1)
|
||||
sstore(2, _1)
|
||||
sstore(3, _1)
|
||||
sstore(4, _1)
|
||||
@ -39,93 +25,11 @@ object "object" {
|
||||
|
||||
|
||||
Binary representation:
|
||||
6001808155806002558060035580600455806005558060065580600755806008558060095580600a5580600b5580600c5580600d55808155806002558060035580600455806005558060065580600755806008558060095580600a5580600b5580600c5580600d5580815550
|
||||
6001806002558060035580600455806005558060065580600755806008558060095580600a5580600b5580600c5580600d5580815550
|
||||
|
||||
Text representation:
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
0x01
|
||||
dup1
|
||||
dup2
|
||||
/* "yul_stack_opt/input.yul":129:141 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":151:160 */
|
||||
0x02
|
||||
/* "yul_stack_opt/input.yul":144:164 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":174:183 */
|
||||
0x03
|
||||
/* "yul_stack_opt/input.yul":167:187 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":197:206 */
|
||||
0x04
|
||||
/* "yul_stack_opt/input.yul":190:210 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":220:229 */
|
||||
0x05
|
||||
/* "yul_stack_opt/input.yul":213:233 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":243:252 */
|
||||
0x06
|
||||
/* "yul_stack_opt/input.yul":236:256 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":266:275 */
|
||||
0x07
|
||||
/* "yul_stack_opt/input.yul":259:279 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":289:298 */
|
||||
0x08
|
||||
/* "yul_stack_opt/input.yul":282:302 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":312:321 */
|
||||
0x09
|
||||
/* "yul_stack_opt/input.yul":305:325 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":335:344 */
|
||||
0x0a
|
||||
/* "yul_stack_opt/input.yul":328:348 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":358:368 */
|
||||
0x0b
|
||||
/* "yul_stack_opt/input.yul":351:372 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":382:392 */
|
||||
0x0c
|
||||
/* "yul_stack_opt/input.yul":375:396 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":406:416 */
|
||||
0x0d
|
||||
/* "yul_stack_opt/input.yul":399:420 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
dup2
|
||||
/* "yul_stack_opt/input.yul":129:141 */
|
||||
sstore
|
||||
/* "yul_stack_opt/input.yul":98:99 */
|
||||
dup1
|
||||
/* "yul_stack_opt/input.yul":151:160 */
|
||||
0x02
|
||||
|
@ -47,7 +47,6 @@
|
||||
// pop(keccak256(gcd(10, 15), or(gt(not(gcd(10, 15)), 1), 1)))
|
||||
// mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_3, _6), 1), _5), _4), _2), 1), 1), _1), 1)), 1), 1), 1)
|
||||
// sstore(not(gcd(10, 15)), 1)
|
||||
// sstore(0, 0)
|
||||
// sstore(2, 1)
|
||||
// extcodecopy(1, msize(), 1, 1)
|
||||
// sstore(0, 0)
|
||||
|
@ -8,7 +8,6 @@
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// sstore(4, 5)
|
||||
// sstore(4, 3)
|
||||
// sstore(8, 3)
|
||||
// }
|
||||
|
@ -20,7 +20,6 @@
|
||||
// {
|
||||
// {
|
||||
// let out1, out2 := foo(sload(32))
|
||||
// sstore(0, out1)
|
||||
// sstore(0, out2)
|
||||
// let out1_1, out2_1 := foo(sload(8))
|
||||
// }
|
||||
|
@ -16,7 +16,6 @@
|
||||
// {
|
||||
// let x, y, z := f()
|
||||
// sstore(0, x)
|
||||
// sstore(1, y)
|
||||
// sstore(1, z)
|
||||
// }
|
||||
// function f() -> x, y, z
|
||||
|
@ -22,8 +22,6 @@
|
||||
// {
|
||||
// {
|
||||
// let out1, out2 := foo(sload(32))
|
||||
// sstore(0, out1)
|
||||
// sstore(0, out2)
|
||||
// sstore(0, 0)
|
||||
// let out1_1, out2_1 := foo(sload(8))
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user