Redundant store eliminator.

This commit is contained in:
chriseth 2020-12-02 19:08:57 +01:00
parent 2969bc0f3e
commit 5f7751f22c
11 changed files with 144 additions and 104 deletions

View File

@ -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
"]"

View File

@ -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

View 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);
}

View 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:
};
}

View File

@ -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'},

View File

@ -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

View File

@ -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)

View File

@ -8,7 +8,6 @@
//
// {
// {
// sstore(4, 5)
// sstore(4, 3)
// sstore(8, 3)
// }

View File

@ -20,7 +20,6 @@
// {
// {
// let out1, out2 := foo(sload(32))
// sstore(0, out1)
// sstore(0, out2)
// let out1_1, out2_1 := foo(sload(8))
// }

View File

@ -16,7 +16,6 @@
// {
// let x, y, z := f()
// sstore(0, x)
// sstore(1, y)
// sstore(1, z)
// }
// function f() -> x, y, z

View File

@ -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))
// }