From c627e6af1087b31d5f0569fa597c330d3e584ba2 Mon Sep 17 00:00:00 2001 From: jaa2 <43010335+jaa2@users.noreply.github.com> Date: Wed, 28 Jul 2021 10:53:19 -0500 Subject: [PATCH] CommandLineParser: Handle --optimize-runs option in assembly mode Fixes #11708. --- Changelog.md | 1 + docs/internals/optimizer.rst | 2 + docs/yul.rst | 6 ++- solc/CommandLineInterface.cpp | 7 ++- solc/CommandLineInterface.h | 1 + solc/CommandLineParser.cpp | 2 + solc/CommandLineParser.h | 2 +- test/cmdlineTests/yul_optimize_runs/args | 1 + test/cmdlineTests/yul_optimize_runs/err | 1 + test/cmdlineTests/yul_optimize_runs/input.yul | 13 +++++ test/cmdlineTests/yul_optimize_runs/output | 52 +++++++++++++++++++ test/solc/CommandLineParser.cpp | 5 +- 12 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 test/cmdlineTests/yul_optimize_runs/args create mode 100644 test/cmdlineTests/yul_optimize_runs/err create mode 100644 test/cmdlineTests/yul_optimize_runs/input.yul create mode 100644 test/cmdlineTests/yul_optimize_runs/output diff --git a/Changelog.md b/Changelog.md index 490d054dd..3546a754f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Bugfixes: * Yul Code Generator: Fix internal compiler error when using a long literal with bitwise negation. * Yul Code Generator: Fix source location references for calls to builtin functions. * Yul Parser: Fix source location references for ``if`` statements. + * Commandline Interface: Apply ``--optimizer-runs`` option in assembly / yul mode. ### 0.8.6 (2021-06-22) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index aee7c8493..7a36b06cc 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -49,6 +49,8 @@ differences, for example, functions may be inlined, combined, or rewritten to el redundancies, etc. (compare the output between the flags ``--ir`` and ``--optimize --ir-optimized``). +.. _optimizer-parameter-runs: + Optimizer Parameter Runs ======================== diff --git a/docs/yul.rst b/docs/yul.rst index b8557475f..83ddef935 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1177,11 +1177,13 @@ intermediate states. This allows for easy debugging and verification of the opti Please refer to the general :ref:`optimizer documentation ` for more details about the different optimization stages and how to use the optimizer. -If you want to use Solidity in stand-alone Yul mode, you activate the optimizer using ``--optimize``: +If you want to use Solidity in stand-alone Yul mode, you activate the optimizer using ``--optimize`` +and optionally specify the :ref:`expected number of contract executions ` with +``--optimize-runs``: .. code-block:: sh - solc --strict-assembly --optimize + solc --strict-assembly --optimize --optimize-runs 200 In Solidity mode, the Yul optimizer is activated together with the regular optimizer. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 32224ac6e..9519e679d 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -555,6 +555,7 @@ bool CommandLineInterface::processInput() m_options.assembly.inputLanguage, m_options.assembly.targetMachine, m_options.optimizer.enabled, + m_options.optimizer.expectedExecutionsPerDeployment, m_options.optimizer.yulSteps ); } @@ -595,7 +596,8 @@ bool CommandLineInterface::compile() m_compiler->enableEwasmGeneration(m_options.compiler.outputs.ewasm); OptimiserSettings settings = m_options.optimizer.enabled ? OptimiserSettings::standard() : OptimiserSettings::minimal(); - settings.expectedExecutionsPerDeployment = m_options.optimizer.expectedExecutionsPerDeployment; + if (m_options.optimizer.expectedExecutionsPerDeployment.has_value()) + settings.expectedExecutionsPerDeployment = m_options.optimizer.expectedExecutionsPerDeployment.value(); if (m_options.optimizer.noOptimizeYul) settings.runYulOptimiser = false; @@ -941,6 +943,7 @@ bool CommandLineInterface::assemble( yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine, bool _optimize, + optional _expectedExecutionsPerDeployment, optional _yulOptimiserSteps ) { @@ -951,6 +954,8 @@ bool CommandLineInterface::assemble( for (auto const& src: m_fileReader.sourceCodes()) { OptimiserSettings settings = _optimize ? OptimiserSettings::full() : OptimiserSettings::minimal(); + if (_expectedExecutionsPerDeployment.has_value()) + settings.expectedExecutionsPerDeployment = _expectedExecutionsPerDeployment.value(); if (_yulOptimiserSteps.has_value()) settings.yulOptimiserSteps = _yulOptimiserSteps.value(); diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 8e17489a7..488ec1d71 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -78,6 +78,7 @@ private: yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine, bool _optimize, + std::optional _expectedExecutionsPerDeployment = std::nullopt, std::optional _yulOptimiserSteps = std::nullopt ); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 5a1daed1e..59972fb3b 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -967,6 +967,8 @@ General Information)").c_str(), m_options.optimizer.enabled = (m_args.count(g_strOptimize) > 0); m_options.optimizer.noOptimizeYul = (m_args.count(g_strNoOptimizeYul) > 0); + m_options.optimizer.expectedExecutionsPerDeployment = m_args.at(g_strOptimizeRuns).as(); + if (m_args.count(g_strYulOptimizations)) { if (!m_options.optimizer.enabled) diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 176966601..423dacb5f 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -159,7 +159,7 @@ struct CommandLineOptions struct { bool enabled = false; - unsigned expectedExecutionsPerDeployment = 0; + std::optional expectedExecutionsPerDeployment; bool noOptimizeYul = false; std::optional yulSteps; } optimizer; diff --git a/test/cmdlineTests/yul_optimize_runs/args b/test/cmdlineTests/yul_optimize_runs/args new file mode 100644 index 000000000..b48e7aeed --- /dev/null +++ b/test/cmdlineTests/yul_optimize_runs/args @@ -0,0 +1 @@ +--yul --yul-dialect evm --optimize --ir-optimized --optimize-runs 10000 diff --git a/test/cmdlineTests/yul_optimize_runs/err b/test/cmdlineTests/yul_optimize_runs/err new file mode 100644 index 000000000..014a1178f --- /dev/null +++ b/test/cmdlineTests/yul_optimize_runs/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/yul_optimize_runs/input.yul b/test/cmdlineTests/yul_optimize_runs/input.yul new file mode 100644 index 000000000..aeb7fd282 --- /dev/null +++ b/test/cmdlineTests/yul_optimize_runs/input.yul @@ -0,0 +1,13 @@ +object "RunsTest1" { + code { + // Deploy the contract + datacopy(0, dataoffset("Runtime"), datasize("Runtime")) + return(0, datasize("Runtime")) + } + object "Runtime" { + code { + let funcSel := shl(224, 0xabc12345) + mstore(0, funcSel) + } + } +} diff --git a/test/cmdlineTests/yul_optimize_runs/output b/test/cmdlineTests/yul_optimize_runs/output new file mode 100644 index 000000000..20196dcb5 --- /dev/null +++ b/test/cmdlineTests/yul_optimize_runs/output @@ -0,0 +1,52 @@ + +======= yul_optimize_runs/input.yul (EVM) ======= + +Pretty printed source: +object "RunsTest1" { + code { + { + let _1 := datasize("Runtime") + datacopy(0, dataoffset("Runtime"), _1) + return(0, _1) + } + } + object "Runtime" { + code { + { + mstore(0, 0xabc1234500000000000000000000000000000000000000000000000000000000) + } + } + } +} + + +Binary representation: +602480600d600039806000f3fe7fabc1234500000000000000000000000000000000000000000000000000000000600052 + +Text representation: + /* "yul_optimize_runs/input.yul":106:125 */ + dataSize(sub_0) + dup1 + /* "yul_optimize_runs/input.yul":83:104 */ + dataOffset(sub_0) + /* "yul_optimize_runs/input.yul":80:81 */ + 0x00 + /* "yul_optimize_runs/input.yul":71:126 */ + codecopy + /* "yul_optimize_runs/input.yul":145:164 */ + dup1 + /* "yul_optimize_runs/input.yul":80:81 */ + 0x00 + /* "yul_optimize_runs/input.yul":135:165 */ + return +stop + +sub_0: assembly { + /* "yul_optimize_runs/input.yul":237:257 */ + 0xabc1234500000000000000000000000000000000000000000000000000000000 + /* "yul_optimize_runs/input.yul":277:278 */ + 0x00 + /* "yul_optimize_runs/input.yul":270:288 */ + mstore +} + diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 21ef80894..8d24f97aa 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm) commandLine += vector{ "--optimize", - "--optimize-runs=1000", // Ignored in assembly mode + "--optimize-runs=1000", "--yul-optimizations=agf", }; @@ -332,7 +332,10 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) { expectedOptions.optimizer.enabled = true; expectedOptions.optimizer.yulSteps = "agf"; + expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; } + else + expectedOptions.optimizer.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; stringstream sout, serr; optional parsedOptions = parseCommandLine(commandLine, sout, serr);