diff --git a/Changelog.md b/Changelog.md index 74f5979ad..50f72d19f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Compiler Features: Bugfixes: * View/Pure Checker: Properly detect state variable access through base class. * Yul analyzer: Check availability of data objects already in analysis phase. + * Yul Optimizer: Fix an issue where memory-accessing code was removed even though ``msize`` was used in the program. diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 624f9d335..1ce3af0a0 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -119,15 +119,13 @@ void UnusedPruner::operator()(Block& _block) void UnusedPruner::runUntilStabilised( Dialect const& _dialect, Block& _ast, - bool _allowMSizeOptization, + bool _allowMSizeOptimization, set const& _externallyUsedFunctions ) { - _allowMSizeOptization = !SideEffectsCollector(_dialect, _ast).containsMSize(); - while (true) { - UnusedPruner pruner(_dialect, _ast, _allowMSizeOptization, _externallyUsedFunctions); + UnusedPruner pruner(_dialect, _ast, _allowMSizeOptimization, _externallyUsedFunctions); pruner(_ast); if (!pruner.shouldRunAgain()) return; diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index 04c43905f..766b01e18 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -34,6 +34,11 @@ struct Dialect; * Optimisation stage that removes unused variables and functions and also * removes side-effect-free expression statements. * + * If msize is used, we cannot remove any statements that access memory. + * Because of that, the Unused Pruner should only be invoked on full ASTs, + * such that it can check for the presence of msize itself, or + * the `_allowMSizeOptimization` needs to be passed. + * * Note that this does not remove circular references. * * Prerequisite: Disambiguator @@ -64,7 +69,7 @@ public: static void runUntilStabilised( Dialect const& _dialect, Block& _ast, - bool _allowMSizeOptization, + bool _allowMSizeOptimization, std::set const& _externallyUsedFunctions = {} ); diff --git a/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul b/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul new file mode 100644 index 000000000..f285d6b5e --- /dev/null +++ b/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul @@ -0,0 +1,36 @@ +{ + { + let _13_71 := 1 + let _17_72 := pc() + let _22_75 := pc() + let _25_76 := pc() + let _30_80 := pc() + let _32_81 := pc() + // This should not be removed + pop(keccak256(1, 2)) + let _104 := gt(not(_17_72), _13_71) + let _105 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + mstore(lt(or(gt(_13_71, or(or(gt(or(or(or(gt(or(gt(_105, _32_81), _13_71), _30_80), lt(or(_13_71, add(_25_76, _105)), _13_71)), _22_75), _13_71), _13_71), _104), _13_71)), _13_71), _13_71), _13_71) + foo_singlereturn_1() + } + function foo_singlereturn_1() + { + extcodecopy(1, msize(), 1, 1) + } +} +// ==== +// step: stackCompressor +// ---- +// { +// let _17_72 := pc() +// let _22_75 := pc() +// let _25_76 := pc() +// let _30_80 := pc() +// let _32_81 := pc() +// pop(keccak256(1, 2)) +// let _105 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_105, _32_81), 1), _30_80), lt(or(1, add(_25_76, _105)), 1)), _22_75), 1), 1), gt(not(_17_72), 1)), 1)), 1), 1), 1) +// foo_singlereturn_1() +// function foo_singlereturn_1() +// { extcodecopy(1, msize(), 1, 1) } +// }