From b1a773be2fd0bda89b6fe7084e8c9e78f4e7984f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 17 May 2023 14:03:16 +0200 Subject: [PATCH] IRGenerator: Leave IR optimization up to the caller to avoid unnecessarily doing it twice --- Changelog.md | 1 + libsolidity/codegen/ir/IRGenerationContext.h | 4 -- libsolidity/codegen/ir/IRGenerator.cpp | 28 +------------- libsolidity/codegen/ir/IRGenerator.h | 10 +---- libsolidity/interface/CompilerStack.cpp | 37 ++++++++++++++----- test/cmdlineTests/~via_ir_equivalence/test.sh | 6 ++- 6 files changed, 36 insertions(+), 50 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9b7021996..c5625d9db 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,7 @@ Bugfixes: * Commandline Interface: It is no longer possible to specify both ``--optimize-yul`` and ``--no-optimize-yul`` at the same time. * SMTChecker: Fix encoding of side-effects inside ``if`` and ``ternary conditional``statements in the BMC engine. * SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function. + * Yul Optimizer: Fix optimized IR being unnecessarily passed through the Yul optimizer again before bytecode generation. AST Changes: * AST: Add the ``experimentalSolidity`` field to the ``SourceUnit`` nodes, which indicate whether the experimental parsing mode has been enabled via ``pragma experimental solidity``. diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 14a70a8a6..833b768a3 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -73,7 +72,6 @@ public: langutil::EVMVersion _evmVersion, ExecutionContext _executionContext, RevertStrings _revertStrings, - OptimiserSettings _optimiserSettings, std::map _sourceIndices, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider @@ -81,7 +79,6 @@ public: m_evmVersion(_evmVersion), m_executionContext(_executionContext), m_revertStrings(_revertStrings), - m_optimiserSettings(std::move(_optimiserSettings)), m_sourceIndices(std::move(_sourceIndices)), m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) @@ -176,7 +173,6 @@ private: langutil::EVMVersion m_evmVersion; ExecutionContext m_executionContext; RevertStrings m_revertStrings; - OptimiserSettings m_optimiserSettings; std::map m_sourceIndices; std::set m_usedSourceNames; ContractDefinition const* m_mostDerivedContract = nullptr; diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index bbc5ef3ac..223d712f0 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -89,36 +89,13 @@ set collectReachableCallables( } -tuple IRGenerator::run( +string IRGenerator::run( ContractDefinition const& _contract, bytes const& _cborMetadata, map const& _otherYulSources ) { - string ir = yul::reindent(generate(_contract, _cborMetadata, _otherYulSources)); - - yul::YulStack asmStack( - m_evmVersion, - m_eofVersion, - yul::YulStack::Language::StrictAssembly, - m_optimiserSettings, - m_context.debugInfoSelection() - ); - if (!asmStack.parseAndAnalyze("", ir)) - { - string errorMessage; - for (auto const& error: asmStack.errors()) - errorMessage += langutil::SourceReferenceFormatter::formatErrorInformation( - *error, - asmStack.charStream("") - ); - solAssert(false, ir + "\n\nInvalid IR generated:\n" + errorMessage + "\n"); - } - Json::Value irAst = asmStack.astJson(); - asmStack.optimize(); - Json::Value irOptAst = asmStack.astJson(); - - return {std::move(ir), std::move(irAst), asmStack.print(m_context.soliditySourceProvider()), std::move(irOptAst)}; + return yul::reindent(generate(_contract, _cborMetadata, _otherYulSources)); } string IRGenerator::generate( @@ -1116,7 +1093,6 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon m_evmVersion, _context, m_context.revertStrings(), - m_optimiserSettings, m_context.sourceIndices(), m_context.debugInfoSelection(), m_context.soliditySourceProvider() diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 9001244b2..fafe47128 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -23,7 +23,6 @@ #pragma once -#include #include #include #include @@ -50,19 +49,16 @@ public: langutil::EVMVersion _evmVersion, std::optional _eofVersion, RevertStrings _revertStrings, - OptimiserSettings _optimiserSettings, std::map _sourceIndices, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ): m_evmVersion(_evmVersion), m_eofVersion(_eofVersion), - m_optimiserSettings(_optimiserSettings), m_context( _evmVersion, ExecutionContext::Creation, _revertStrings, - std::move(_optimiserSettings), std::move(_sourceIndices), _debugInfoSelection, _soliditySourceProvider @@ -70,9 +66,8 @@ public: m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector()) {} - /// Generates and returns the IR code, in unoptimized and optimized form - /// (or just pretty-printed, depending on the optimizer settings). - std::tuple run( + /// Generates and returns (unoptimized) IR code. + std::string run( ContractDefinition const& _contract, bytes const& _cborMetadata, std::map const& _otherYulSources @@ -143,7 +138,6 @@ private: langutil::EVMVersion const m_evmVersion; std::optional const m_eofVersion; - OptimiserSettings const m_optimiserSettings; IRGenerationContext m_context; YulUtilFunctions m_utils; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index aad2bc2ba..bbebc2508 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -70,6 +70,7 @@ #include #include +#include #include @@ -1468,22 +1469,38 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) m_evmVersion, m_eofVersion, m_revertStrings, - m_optimiserSettings, sourceIndices(), m_debugInfoSelection, this ); - - tie( - compiledContract.yulIR, - compiledContract.yulIRAst, - compiledContract.yulIROptimized, - compiledContract.yulIROptimizedAst - ) = generator.run( + compiledContract.yulIR = generator.run( _contract, createCBORMetadata(compiledContract, /* _forIR */ true), otherYulSources ); + + yul::YulStack stack( + m_evmVersion, + m_eofVersion, + yul::YulStack::Language::StrictAssembly, + m_optimiserSettings, + m_debugInfoSelection + ); + if (!stack.parseAndAnalyze("", compiledContract.yulIR)) + { + string errorMessage; + for (auto const& error: stack.errors()) + errorMessage += langutil::SourceReferenceFormatter::formatErrorInformation( + *error, + stack.charStream("") + ); + solAssert(false, compiledContract.yulIR + "\n\nInvalid IR generated:\n" + errorMessage + "\n"); + } + + compiledContract.yulIRAst = stack.astJson(); + stack.optimize(); + compiledContract.yulIROptimized = stack.print(this); + compiledContract.yulIROptimizedAst = stack.astJson(); } void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) @@ -1508,8 +1525,8 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) m_optimiserSettings, m_debugInfoSelection ); - stack.parseAndAnalyze("", compiledContract.yulIROptimized); - stack.optimize(); + bool analysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIROptimized); + solAssert(analysisSuccessful); //cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl; diff --git a/test/cmdlineTests/~via_ir_equivalence/test.sh b/test/cmdlineTests/~via_ir_equivalence/test.sh index c318f262a..d663bef85 100755 --- a/test/cmdlineTests/~via_ir_equivalence/test.sh +++ b/test/cmdlineTests/~via_ir_equivalence/test.sh @@ -33,7 +33,8 @@ function test_via_ir_equivalence() for yul_file in $(find . -name "${output_file_prefix}*.yul" | sort -V); do asm_output_two_stage+=$( msg_on_error --no-stderr \ - "$SOLC" --strict-assembly --asm "${optimizer_flags[@]}" "$yul_file" | stripCLIDecorations + "$SOLC" --strict-assembly --asm "${optimizer_flags[@]}" --no-optimize-yul "$yul_file" | + stripCLIDecorations ) done @@ -50,7 +51,8 @@ function test_via_ir_equivalence() for yul_file in $(find . -name "${output_file_prefix}*.yul" | sort -V); do bin_output_two_stage+=$( msg_on_error --no-stderr \ - "$SOLC" --strict-assembly --bin "${optimizer_flags[@]}" "$yul_file" | stripCLIDecorations + "$SOLC" --strict-assembly --bin "${optimizer_flags[@]}" "$yul_file" --no-optimize-yul | + stripCLIDecorations ) done