mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use stack optimizations.
This commit is contained in:
parent
ca34335d07
commit
6d1ed93247
@ -4,6 +4,7 @@ Language Features:
|
||||
|
||||
|
||||
Compiler Features:
|
||||
* Yul Optimizer: Enable stack allocation optimization by default if yul optimizer is active (disable in yulDetails).
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
@ -216,8 +216,12 @@ Input Description
|
||||
// It can only be activated through the details here.
|
||||
// This feature is still considered experimental.
|
||||
"yul": false,
|
||||
// Future tuning options, currently unused.
|
||||
"yulDetails": {}
|
||||
// Tuning options for the Yul optimizer.
|
||||
"yulDetails": {
|
||||
// Improve allocation of stack slots for variables, can free up stack slots early.
|
||||
// Activated by default if the Yul optimizer is activated.
|
||||
"stackAllocation": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"evmVersion": "byzantium", // Version of the EVM to compile for. Affects type checking and code generation. Can be homestead, tangerineWhistle, spuriousDragon, byzantium, constantinople or petersburg
|
||||
|
@ -331,7 +331,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
vector<string> const& _localVariables,
|
||||
set<string> const& _externallyUsedFunctions,
|
||||
bool _system,
|
||||
bool _optimise
|
||||
OptimiserSettings const& _optimiserSettings
|
||||
)
|
||||
{
|
||||
int startStackHeight = stackHeight();
|
||||
@ -422,7 +422,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
|
||||
// Several optimizer steps cannot handle externally supplied stack variables,
|
||||
// so we essentially only optimize the ABI functions.
|
||||
if (_optimise && _localVariables.empty())
|
||||
if (_optimiserSettings.runYulOptimiser && _localVariables.empty())
|
||||
{
|
||||
yul::OptimiserSuite::run(
|
||||
yul::EVMDialect::strictAssemblyForEVM(m_evmVersion),
|
||||
@ -445,7 +445,15 @@ void CompilerContext::appendInlineAssembly(
|
||||
reportError("Failed to analyze inline assembly block.");
|
||||
|
||||
solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block.");
|
||||
yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, m_evmVersion, identifierAccess, _system, _optimise);
|
||||
yul::CodeGenerator::assemble(
|
||||
*parserResult,
|
||||
analysisInfo,
|
||||
*m_asm,
|
||||
m_evmVersion,
|
||||
identifierAccess,
|
||||
_system,
|
||||
_optimiserSettings.optimizeStackAllocation
|
||||
);
|
||||
|
||||
// Reset the source location to the one of the node (instead of the CODEGEN source location)
|
||||
updateSourceLocation();
|
||||
|
@ -217,7 +217,7 @@ public:
|
||||
std::vector<std::string> const& _localVariables = std::vector<std::string>(),
|
||||
std::set<std::string> const& _externallyUsedFunctions = std::set<std::string>(),
|
||||
bool _system = false,
|
||||
bool _optimise = false
|
||||
OptimiserSettings const& _optimiserSettings = OptimiserSettings::none()
|
||||
);
|
||||
|
||||
/// Appends arbitrary data to the end of the bytecode.
|
||||
|
@ -720,7 +720,9 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
*_inlineAssembly.annotation().analysisInfo,
|
||||
*m_context.assemblyPtr(),
|
||||
m_context.evmVersion(),
|
||||
identifierAccess
|
||||
identifierAccess,
|
||||
false,
|
||||
m_optimiserSettings.optimizeStackAllocation
|
||||
);
|
||||
m_context.setStackOffset(startStackHeight);
|
||||
return false;
|
||||
@ -983,7 +985,7 @@ void ContractCompiler::appendMissingFunctions()
|
||||
{},
|
||||
abiFunctions.second,
|
||||
true,
|
||||
m_optimiserSettings.runYulOptimiser
|
||||
m_optimiserSettings
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -993,7 +993,11 @@ string CompilerStack::createMetadata(Contract const& _contract) const
|
||||
details["cse"] = m_optimiserSettings.runCSE;
|
||||
details["constantOptimizer"] = m_optimiserSettings.runConstantOptimiser;
|
||||
details["yul"] = m_optimiserSettings.runYulOptimiser;
|
||||
details["yulDetails"] = Json::objectValue;
|
||||
if (m_optimiserSettings.runYulOptimiser)
|
||||
{
|
||||
details["yulDetails"] = Json::objectValue;
|
||||
details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation;
|
||||
}
|
||||
|
||||
meta["settings"]["optimizer"]["details"] = std::move(details);
|
||||
}
|
||||
|
@ -54,15 +54,17 @@ struct OptimiserSettings
|
||||
s.runDeduplicate = true;
|
||||
s.runCSE = true;
|
||||
s.runConstantOptimiser = true;
|
||||
// The only disabled one
|
||||
// The only disabled ones
|
||||
s.optimizeStackAllocation = false;
|
||||
s.runYulOptimiser = false;
|
||||
s.expectedExecutionsPerDeployment = 200;
|
||||
return s;
|
||||
}
|
||||
/// Standard optimisations plus yul optimiser.
|
||||
/// Standard optimisations plus yul and stack optimiser.
|
||||
static OptimiserSettings full()
|
||||
{
|
||||
OptimiserSettings s = enabled();
|
||||
s.optimizeStackAllocation = true;
|
||||
s.runYulOptimiser = true;
|
||||
return s;
|
||||
}
|
||||
@ -76,6 +78,7 @@ struct OptimiserSettings
|
||||
runDeduplicate == _other.runDeduplicate &&
|
||||
runCSE == _other.runCSE &&
|
||||
runConstantOptimiser == _other.runConstantOptimiser &&
|
||||
optimizeStackAllocation == _other.optimizeStackAllocation &&
|
||||
runYulOptimiser == _other.runYulOptimiser &&
|
||||
expectedExecutionsPerDeployment == _other.expectedExecutionsPerDeployment;
|
||||
}
|
||||
@ -94,6 +97,8 @@ struct OptimiserSettings
|
||||
/// Constant optimizer, which tries to find better representations that satisfy the given
|
||||
/// size/cost-trade-off.
|
||||
bool runConstantOptimiser = false;
|
||||
/// Perform more efficient stack allocation for variables during code generation from Yul to bytecode.
|
||||
bool optimizeStackAllocation = false;
|
||||
/// Yul optimiser with default settings. Will only run on certain parts of the code for now.
|
||||
bool runYulOptimiser = false;
|
||||
/// This specifies an estimate on how often each opcode in this assembly will be executed,
|
||||
|
@ -399,12 +399,17 @@ boost::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Valu
|
||||
return *error;
|
||||
if (auto error = checkOptimizerDetail(details, "yul", settings.runYulOptimiser))
|
||||
return *error;
|
||||
if (settings.runYulOptimiser)
|
||||
settings.optimizeStackAllocation = true;
|
||||
if (details.isMember("yulDetails"))
|
||||
{
|
||||
if (!_jsonInput["yulDetails"].isObject())
|
||||
return formatFatalError("JSONError", "The \"yulDetails\" optimizer setting has to be a JSON object.");
|
||||
if (!_jsonInput["yulDetails"].getMemberNames().empty())
|
||||
return formatFatalError("JSONError", "The \"yulDetails\" optimizer setting cannot have any settings yet.");
|
||||
if (!settings.runYulOptimiser)
|
||||
return formatFatalError("JSONError", "\"Providing yulDetails requires Yul optimizer to be enabled.");
|
||||
|
||||
if (auto result = checkKeys(details["yulDetails"], {"stackAllocation"}, "settings.optimizer.details.yulDetails"))
|
||||
return *result;
|
||||
if (auto error = checkOptimizerDetail(details["yulDetails"], "stackAllocation", settings.optimizeStackAllocation))
|
||||
return *error;
|
||||
}
|
||||
}
|
||||
return std::move(settings);
|
||||
|
@ -180,7 +180,7 @@ void CodeGenerator::assemble(
|
||||
langutil::EVMVersion _evmVersion,
|
||||
ExternalIdentifierAccess const& _identifierAccess,
|
||||
bool _useNamedLabelsForFunctions,
|
||||
bool _optimize
|
||||
bool _optimizeStackAllocation
|
||||
)
|
||||
{
|
||||
EthAssemblyAdapter assemblyAdapter(_assembly);
|
||||
@ -190,7 +190,7 @@ void CodeGenerator::assemble(
|
||||
_analysisInfo,
|
||||
_parsedData,
|
||||
*dialect,
|
||||
_optimize,
|
||||
_optimizeStackAllocation,
|
||||
false,
|
||||
_identifierAccess,
|
||||
_useNamedLabelsForFunctions
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
langutil::EVMVersion _evmVersion,
|
||||
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess(),
|
||||
bool _useNamedLabelsForFunctions = false,
|
||||
bool _optimize = false
|
||||
bool _optimizeStackAllocation = false
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -907,6 +907,7 @@ bool CommandLineInterface::processInput()
|
||||
OptimiserSettings settings = m_args.count(g_argOptimize) ? OptimiserSettings::enabled() : OptimiserSettings::minimal();
|
||||
settings.expectedExecutionsPerDeployment = m_args[g_argOptimizeRuns].as<unsigned>();
|
||||
settings.runYulOptimiser = m_args.count(g_strOptimizeYul);
|
||||
settings.optimizeStackAllocation = settings.runYulOptimiser;
|
||||
m_compiler->setOptimiserSettings(settings);
|
||||
|
||||
bool successful = m_compiler->compile();
|
||||
|
@ -10,7 +10,7 @@
|
||||
"settings":
|
||||
{
|
||||
"optimizer": {
|
||||
"details": { "yulDetails": 7 }
|
||||
"details": { "yul": true, "yulDetails": 7 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"The \"yulDetails\" optimizer setting has to be a JSON object.","message":"The \"yulDetails\" optimizer setting has to be a JSON object.","severity":"error","type":"JSONError"}]}
|
||||
{"errors":[{"component":"general","formattedMessage":"\"settings.optimizer.details.yulDetails\" must be an object","message":"\"settings.optimizer.details.yulDetails\" must be an object","severity":"error","type":"JSONError"}]}
|
||||
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
},
|
||||
"settings":
|
||||
{
|
||||
"optimizer": {
|
||||
"details": { "yulDetails": 7 }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"\"Providing yulDetails requires Yul optimizer to be enabled.","message":"\"Providing yulDetails requires Yul optimizer to be enabled.","severity":"error","type":"JSONError"}]}
|
@ -1010,7 +1010,10 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different)
|
||||
BOOST_CHECK(optimizer["details"]["jumpdestRemover"].asBool() == true);
|
||||
BOOST_CHECK(optimizer["details"]["orderLiterals"].asBool() == false);
|
||||
BOOST_CHECK(optimizer["details"]["peephole"].asBool() == true);
|
||||
BOOST_CHECK(optimizer["details"]["yul"].asBool() == true);
|
||||
BOOST_CHECK(optimizer["details"]["yulDetails"].isObject());
|
||||
BOOST_CHECK(optimizer["details"]["yulDetails"].getMemberNames() == vector<string>{"stackAllocation"});
|
||||
BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].asBool() == true);
|
||||
BOOST_CHECK_EQUAL(optimizer["details"].getMemberNames().size(), 8);
|
||||
BOOST_CHECK(optimizer["runs"].asUInt() == 600);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user