Use stack optimizations.

This commit is contained in:
chriseth
2019-03-14 15:34:23 +01:00
parent ca34335d07
commit 6d1ed93247
16 changed files with 70 additions and 20 deletions
+11 -3
View File
@@ -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();
+1 -1
View File
@@ -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.
+4 -2
View File
@@ -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
);
}
+5 -1
View File
@@ -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);
}
+7 -2
View File
@@ -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,
+9 -4
View File
@@ -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);