mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #14268 from ethereum/resurrect-yul-optimizer-cli-options
Resurrect Yul optimizer CLI options
This commit is contained in:
commit
c7372f3f22
@ -6,6 +6,7 @@ Language Features:
|
|||||||
Compiler Features:
|
Compiler Features:
|
||||||
* Commandline Interface: Add ``--ast-compact-json`` output in assembler mode.
|
* Commandline Interface: Add ``--ast-compact-json`` output in assembler mode.
|
||||||
* Commandline Interface: Add ``--ir-ast-json`` and ``--ir-optimized-ast-json`` outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR.
|
* Commandline Interface: Add ``--ir-ast-json`` and ``--ir-optimized-ast-json`` outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR.
|
||||||
|
* Commandline Interface: Respect ``--optimize-yul`` and ``--no-optimize-yul`` in compiler mode and accept them in assembler mode as well. ``--optimize --no-optimize-yul`` combination now allows enabling EVM assembly optimizer without enabling Yul optimizer.
|
||||||
* EWasm: Remove EWasm backend.
|
* EWasm: Remove EWasm backend.
|
||||||
* Parser: Introduce ``pragma experimental solidity``, which will enable an experimental language mode that in particular has no stability guarantees between non-breaking releases and is not suited for production use.
|
* Parser: Introduce ``pragma experimental solidity``, which will enable an experimental language mode that in particular has no stability guarantees between non-breaking releases and is not suited for production use.
|
||||||
* Standard JSON Interface: Add ``ast`` file-level output for Yul input.
|
* Standard JSON Interface: Add ``ast`` file-level output for Yul input.
|
||||||
|
@ -1074,9 +1074,6 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
|
|||||||
map<string, yul::YulStack> yulStacks;
|
map<string, yul::YulStack> yulStacks;
|
||||||
for (auto const& src: m_fileReader.sourceUnits())
|
for (auto const& src: m_fileReader.sourceUnits())
|
||||||
{
|
{
|
||||||
// --no-optimize-yul option is not accepted in assembly mode.
|
|
||||||
solAssert(!m_options.optimizer.noOptimizeYul);
|
|
||||||
|
|
||||||
auto& stack = yulStacks[src.first] = yul::YulStack(
|
auto& stack = yulStacks[src.first] = yul::YulStack(
|
||||||
m_options.output.evmVersion,
|
m_options.output.evmVersion,
|
||||||
m_options.output.eofVersion,
|
m_options.output.eofVersion,
|
||||||
|
@ -247,9 +247,9 @@ bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noex
|
|||||||
metadata.format == _other.metadata.format &&
|
metadata.format == _other.metadata.format &&
|
||||||
metadata.hash == _other.metadata.hash &&
|
metadata.hash == _other.metadata.hash &&
|
||||||
metadata.literalSources == _other.metadata.literalSources &&
|
metadata.literalSources == _other.metadata.literalSources &&
|
||||||
optimizer.enabled == _other.optimizer.enabled &&
|
optimizer.optimizeEvmasm == _other.optimizer.optimizeEvmasm &&
|
||||||
|
optimizer.optimizeYul == _other.optimizer.optimizeYul &&
|
||||||
optimizer.expectedExecutionsPerDeployment == _other.optimizer.expectedExecutionsPerDeployment &&
|
optimizer.expectedExecutionsPerDeployment == _other.optimizer.expectedExecutionsPerDeployment &&
|
||||||
optimizer.noOptimizeYul == _other.optimizer.noOptimizeYul &&
|
|
||||||
optimizer.yulSteps == _other.optimizer.yulSteps &&
|
optimizer.yulSteps == _other.optimizer.yulSteps &&
|
||||||
modelChecker.initialize == _other.modelChecker.initialize &&
|
modelChecker.initialize == _other.modelChecker.initialize &&
|
||||||
modelChecker.settings == _other.modelChecker.settings;
|
modelChecker.settings == _other.modelChecker.settings;
|
||||||
@ -259,13 +259,16 @@ OptimiserSettings CommandLineOptions::optimiserSettings() const
|
|||||||
{
|
{
|
||||||
OptimiserSettings settings;
|
OptimiserSettings settings;
|
||||||
|
|
||||||
if (optimizer.enabled)
|
if (optimizer.optimizeEvmasm)
|
||||||
settings = OptimiserSettings::standard();
|
settings = OptimiserSettings::standard();
|
||||||
else
|
else
|
||||||
settings = OptimiserSettings::minimal();
|
settings = OptimiserSettings::minimal();
|
||||||
|
|
||||||
if (optimizer.noOptimizeYul)
|
settings.runYulOptimiser = optimizer.optimizeYul;
|
||||||
settings.runYulOptimiser = false;
|
if (optimizer.optimizeYul)
|
||||||
|
// NOTE: Standard JSON disables optimizeStackAllocation by default when yul optimizer is disabled.
|
||||||
|
// --optimize --no-optimize-yul on the CLI does not have that effect.
|
||||||
|
settings.optimizeStackAllocation = true;
|
||||||
|
|
||||||
if (optimizer.expectedExecutionsPerDeployment.has_value())
|
if (optimizer.expectedExecutionsPerDeployment.has_value())
|
||||||
settings.expectedExecutionsPerDeployment = optimizer.expectedExecutionsPerDeployment.value();
|
settings.expectedExecutionsPerDeployment = optimizer.expectedExecutionsPerDeployment.value();
|
||||||
@ -644,21 +647,15 @@ General Information)").c_str(),
|
|||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strAssemble.c_str(),
|
g_strAssemble.c_str(),
|
||||||
("Switch to assembly mode, ignoring all options except "
|
"Switch to assembly mode and assume input is assembly."
|
||||||
"--" + g_strMachine + ", --" + g_strYulDialect + ", --" + g_strOptimize + " and --" + g_strYulOptimizations + " "
|
|
||||||
"and assumes input is assembly.").c_str()
|
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strYul.c_str(),
|
g_strYul.c_str(),
|
||||||
("Switch to Yul mode, ignoring all options except "
|
"Switch to Yul mode and assume input is Yul."
|
||||||
"--" + g_strMachine + ", --" + g_strYulDialect + ", --" + g_strOptimize + " and --" + g_strYulOptimizations + " "
|
|
||||||
"and assumes input is Yul.").c_str()
|
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strStrictAssembly.c_str(),
|
g_strStrictAssembly.c_str(),
|
||||||
("Switch to strict assembly mode, ignoring all options except "
|
"Switch to strict assembly mode and assume input is strict assembly."
|
||||||
"--" + g_strMachine + ", --" + g_strYulDialect + ", --" + g_strOptimize + " and --" + g_strYulOptimizations + " "
|
|
||||||
"and assumes input is strict assembly.").c_str()
|
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strImportAst.c_str(),
|
g_strImportAst.c_str(),
|
||||||
@ -784,7 +781,7 @@ General Information)").c_str(),
|
|||||||
optimizerOptions.add_options()
|
optimizerOptions.add_options()
|
||||||
(
|
(
|
||||||
g_strOptimize.c_str(),
|
g_strOptimize.c_str(),
|
||||||
"Enable bytecode optimizer."
|
"Enable optimizer."
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strOptimizeRuns.c_str(),
|
g_strOptimizeRuns.c_str(),
|
||||||
@ -796,16 +793,18 @@ General Information)").c_str(),
|
|||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strOptimizeYul.c_str(),
|
g_strOptimizeYul.c_str(),
|
||||||
("Legacy option, ignored. Use the general --" + g_strOptimize + " to enable Yul optimizer.").c_str()
|
("Enable Yul optimizer (independently of the EVM assembly optimizer). "
|
||||||
|
"The general --" + g_strOptimize + " option automatically enables this unless --" +
|
||||||
|
g_strNoOptimizeYul + " is specified.").c_str()
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strNoOptimizeYul.c_str(),
|
g_strNoOptimizeYul.c_str(),
|
||||||
"Disable Yul optimizer in Solidity."
|
"Disable Yul optimizer (independently of the EVM assembly optimizer)."
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strYulOptimizations.c_str(),
|
g_strYulOptimizations.c_str(),
|
||||||
po::value<string>()->value_name("steps"),
|
po::value<string>()->value_name("steps"),
|
||||||
"Forces yul optimizer to use the specified sequence of optimization steps instead of the built-in one."
|
"Forces Yul optimizer to use the specified sequence of optimization steps instead of the built-in one."
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
desc.add(optimizerOptions);
|
desc.add(optimizerOptions);
|
||||||
@ -1165,9 +1164,11 @@ void CommandLineParser::processArgs()
|
|||||||
"Options --" + g_strOptimizeYul + " and --" + g_strNoOptimizeYul + " cannot be used together."
|
"Options --" + g_strOptimizeYul + " and --" + g_strNoOptimizeYul + " cannot be used together."
|
||||||
);
|
);
|
||||||
|
|
||||||
// We deliberately ignore --optimize-yul
|
m_options.optimizer.optimizeEvmasm = (m_args.count(g_strOptimize) > 0);
|
||||||
m_options.optimizer.enabled = (m_args.count(g_strOptimize) > 0);
|
m_options.optimizer.optimizeYul = (
|
||||||
m_options.optimizer.noOptimizeYul = (m_args.count(g_strNoOptimizeYul) > 0);
|
(m_args.count(g_strOptimize) > 0 && m_args.count(g_strNoOptimizeYul) == 0) ||
|
||||||
|
m_args.count(g_strOptimizeYul) > 0
|
||||||
|
);
|
||||||
if (!m_args[g_strOptimizeRuns].defaulted())
|
if (!m_args[g_strOptimizeRuns].defaulted())
|
||||||
m_options.optimizer.expectedExecutionsPerDeployment = m_args.at(g_strOptimizeRuns).as<unsigned>();
|
m_options.optimizer.expectedExecutionsPerDeployment = m_args.at(g_strOptimizeRuns).as<unsigned>();
|
||||||
|
|
||||||
@ -1199,8 +1200,6 @@ void CommandLineParser::processArgs()
|
|||||||
g_strOutputDir,
|
g_strOutputDir,
|
||||||
g_strGas,
|
g_strGas,
|
||||||
g_strCombinedJson,
|
g_strCombinedJson,
|
||||||
g_strOptimizeYul,
|
|
||||||
g_strNoOptimizeYul,
|
|
||||||
};
|
};
|
||||||
if (countEnabledOptions(nonAssemblyModeOptions) >= 1)
|
if (countEnabledOptions(nonAssemblyModeOptions) >= 1)
|
||||||
{
|
{
|
||||||
@ -1208,9 +1207,6 @@ void CommandLineParser::processArgs()
|
|||||||
auto enabledOptions = nonAssemblyModeOptions | ranges::views::filter(optionEnabled) | ranges::to_vector;
|
auto enabledOptions = nonAssemblyModeOptions | ranges::views::filter(optionEnabled) | ranges::to_vector;
|
||||||
|
|
||||||
string message = "The following options are invalid in assembly mode: " + joinOptionNames(enabledOptions) + ".";
|
string message = "The following options are invalid in assembly mode: " + joinOptionNames(enabledOptions) + ".";
|
||||||
if (m_args.count(g_strOptimizeYul) || m_args.count(g_strNoOptimizeYul))
|
|
||||||
message += " Optimization is disabled by default and can be enabled with --" + g_strOptimize + ".";
|
|
||||||
|
|
||||||
solThrow(CommandLineValidationError, message);
|
solThrow(CommandLineValidationError, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1235,7 +1231,10 @@ void CommandLineParser::processArgs()
|
|||||||
else
|
else
|
||||||
solThrow(CommandLineValidationError, "Invalid option for --" + g_strYulDialect + ": " + dialect);
|
solThrow(CommandLineValidationError, "Invalid option for --" + g_strYulDialect + ": " + dialect);
|
||||||
}
|
}
|
||||||
if (m_options.optimizer.enabled && (m_options.assembly.inputLanguage != Input::StrictAssembly))
|
if (
|
||||||
|
(m_options.optimizer.optimizeEvmasm || m_options.optimizer.optimizeYul) &&
|
||||||
|
m_options.assembly.inputLanguage != Input::StrictAssembly
|
||||||
|
)
|
||||||
solThrow(
|
solThrow(
|
||||||
CommandLineValidationError,
|
CommandLineValidationError,
|
||||||
"Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "."
|
"Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "."
|
||||||
|
@ -223,9 +223,9 @@ struct CommandLineOptions
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool enabled = false;
|
bool optimizeEvmasm = false;
|
||||||
|
bool optimizeYul = false;
|
||||||
std::optional<unsigned> expectedExecutionsPerDeployment;
|
std::optional<unsigned> expectedExecutionsPerDeployment;
|
||||||
bool noOptimizeYul = false;
|
|
||||||
std::optional<std::string> yulSteps;
|
std::optional<std::string> yulSteps;
|
||||||
} optimizer;
|
} optimizer;
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
--strict-assembly --optimize-yul
|
|
@ -1 +0,0 @@
|
|||||||
The following options are invalid in assembly mode: --optimize-yul. Optimization is disabled by default and can be enabled with --optimize.
|
|
@ -1 +0,0 @@
|
|||||||
1
|
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
sstore(0, 1)
|
|
||||||
}
|
|
@ -140,6 +140,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
|
|||||||
"--metadata-hash=swarm",
|
"--metadata-hash=swarm",
|
||||||
"--metadata-literal",
|
"--metadata-literal",
|
||||||
"--optimize",
|
"--optimize",
|
||||||
|
"--optimize-yul",
|
||||||
"--optimize-runs=1000",
|
"--optimize-runs=1000",
|
||||||
"--yul-optimizations=agf",
|
"--yul-optimizations=agf",
|
||||||
"--model-checker-bmc-loop-iterations=2",
|
"--model-checker-bmc-loop-iterations=2",
|
||||||
@ -205,7 +206,8 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
|
|||||||
};
|
};
|
||||||
expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1;
|
expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1;
|
||||||
expectedOptions.metadata.literalSources = true;
|
expectedOptions.metadata.literalSources = true;
|
||||||
expectedOptions.optimizer.enabled = true;
|
expectedOptions.optimizer.optimizeEvmasm = true;
|
||||||
|
expectedOptions.optimizer.optimizeYul = true;
|
||||||
expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000;
|
expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000;
|
||||||
expectedOptions.optimizer.yulSteps = "agf";
|
expectedOptions.optimizer.yulSteps = "agf";
|
||||||
|
|
||||||
@ -336,7 +338,8 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
|
|||||||
expectedOptions.compiler.outputs.astCompactJson = true;
|
expectedOptions.compiler.outputs.astCompactJson = true;
|
||||||
if (expectedLanguage == YulStack::Language::StrictAssembly)
|
if (expectedLanguage == YulStack::Language::StrictAssembly)
|
||||||
{
|
{
|
||||||
expectedOptions.optimizer.enabled = true;
|
expectedOptions.optimizer.optimizeEvmasm = true;
|
||||||
|
expectedOptions.optimizer.optimizeYul = true;
|
||||||
expectedOptions.optimizer.yulSteps = "agf";
|
expectedOptions.optimizer.yulSteps = "agf";
|
||||||
expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000;
|
expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000;
|
||||||
}
|
}
|
||||||
@ -435,6 +438,39 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(optimizer_flags)
|
||||||
|
{
|
||||||
|
OptimiserSettings yulOnly = OptimiserSettings::minimal();
|
||||||
|
yulOnly.runYulOptimiser = true;
|
||||||
|
yulOnly.optimizeStackAllocation = true;
|
||||||
|
|
||||||
|
OptimiserSettings evmasmOnly = OptimiserSettings::standard();
|
||||||
|
evmasmOnly.runYulOptimiser = false;
|
||||||
|
|
||||||
|
map<vector<string>, OptimiserSettings> settingsMap = {
|
||||||
|
{{}, OptimiserSettings::minimal()},
|
||||||
|
{{"--optimize"}, OptimiserSettings::standard()},
|
||||||
|
{{"--no-optimize-yul"}, OptimiserSettings::minimal()},
|
||||||
|
{{"--optimize-yul"}, yulOnly},
|
||||||
|
{{"--optimize", "--no-optimize-yul"}, evmasmOnly},
|
||||||
|
{{"--optimize", "--optimize-yul"}, OptimiserSettings::standard()},
|
||||||
|
};
|
||||||
|
|
||||||
|
map<InputMode, string> inputModeFlagMap = {
|
||||||
|
{InputMode::Compiler, ""},
|
||||||
|
{InputMode::CompilerWithASTImport, "--import-ast"},
|
||||||
|
{InputMode::Assembler, "--strict-assembly"},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto const& [inputMode, inputModeFlag]: inputModeFlagMap)
|
||||||
|
for (auto const& [optimizerFlags, expectedOptimizerSettings]: settingsMap)
|
||||||
|
{
|
||||||
|
vector<string> commandLine = {"solc", inputModeFlag, "file"};
|
||||||
|
commandLine += optimizerFlags;
|
||||||
|
BOOST_CHECK(parseCommandLine(commandLine).optimiserSettings() == expectedOptimizerSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(default_optimiser_sequence)
|
BOOST_AUTO_TEST_CASE(default_optimiser_sequence)
|
||||||
{
|
{
|
||||||
CommandLineOptions const& commandLineOptions = parseCommandLine({"solc", "contract.sol", "--optimize"});
|
CommandLineOptions const& commandLineOptions = parseCommandLine({"solc", "contract.sol", "--optimize"});
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::CommandLineOptions)
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::CommandLineOptions)
|
||||||
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::InputMode)
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::InputMode)
|
||||||
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::OptimiserSettings)
|
||||||
|
|
||||||
namespace solidity::frontend::test
|
namespace solidity::frontend::test
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user