Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unused return parameter pruner #10080

Closed
wants to merge 2 commits into from
Closed

Conversation

hrkrshnn
Copy link
Member

@hrkrshnn hrkrshnn commented Oct 20, 2020

Optimization rule that rewrites functions whose return parameters are not used at callsite.

TODO

  1. Tests in fullsuite
  2. Figure out how to deal with the pop case.
  3. Figure out a good sequence.

Comment on lines 44 to 47
"Tpeiul" // Run functional expression inliner
"xarulrul" // Prune a bit more in SSA
"xarrcL" // Turn into SSA again and simplify
"gvif" // Run full inliner
"gvPif" // Run full inliner
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order needs to be looked at more carefully.

It would be nice if the InlineTiny pass can have its own name. After p (unusedFunctionParameterPruner), only the InlineTiny needs to be run.

{SSATransform::name, 'a'},
{StructuralSimplifier::name, 't'},
{UnusedFunctionParameterPruner::name, 'p'},
{UnusedFunctionReturnParameterPruner::name, 'P'},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only extra line. The rest are indentation changes.

@hrkrshnn hrkrshnn force-pushed the unused-return-parameter-pruner branch 2 times, most recently from add9b96 to 7755b71 Compare October 20, 2020 14:05
@ethereum ethereum deleted a comment from stackenbotten Oct 20, 2020
@hrkrshnn hrkrshnn force-pushed the unused-return-parameter-pruner branch from 7755b71 to 03eeb5e Compare October 20, 2020 14:08
@ethereum ethereum deleted a comment from stackenbotten Oct 20, 2020
@ethereum ethereum deleted a comment from stackenbotten Oct 20, 2020
@ethereum ethereum deleted a comment from stackenbotten Oct 20, 2020
@ethereum ethereum deleted a comment from stackenbotten Oct 20, 2020
@@ -49,7 +49,7 @@
// sstore(not(gcd(10, 15)), 1)
// sstore(0, 0)
// sstore(2, 1)
// extcodecopy(1, msize(), 1, 1)
// pop(foo_singlereturn_1_78_248(calldataload(0), calldataload(3)))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check why this is happening? Does the linking function not fall into the "tiny" category in the full inliner?

Comment on lines +1 to +2
// A test to see if the optimization step can deal with pop
// Expression splitter converts `pop(f(a))` into
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work yet. Need to figure out a fix.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UnusedPruner should remove the pop(z)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnusedPruner is actually converting it back to pop(f())

{
	let a := f()
	pop(a)
	function f() -> y {
		sstore(1, sload(1))
	}
}
// ----
// step: unusedPruner
//
// {
//     pop(f())
//     function f() -> y
//     { sstore(1, sload(1)) }
// }

@hrkrshnn hrkrshnn marked this pull request as draft October 20, 2020 14:13
@@ -41,10 +41,10 @@ struct OptimiserSettings

// should have good "compilability" property here.

"Tpeul" // Run functional expression inliner
"Tpeiul" // Run functional expression inliner
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why run the full inliner? The comment only mentions the functional expression inliner.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll have to run full inliner twice. One after UnusedFunctionParameterPruner and once after this step. The sequence might have to be modified

{UnusedFunctionParameterPruner::name, 'p'},
{UnusedPruner::name, 'u'},
{VarDeclInitializer::name, 'd'},
{BlockFlattener::name, 'f'},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No whitespace-based alignment across lines is a good rule to have in the coding standard :)

/// Function name and a boolean mask, where `false` at index `i` indicates that the function
/// return-parameter at index `i` in `FunctionDefinition::parameter` is unused at every function
/// call-site.
map<YulString, vector<bool>> m_callSiteMasks;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we again rename the variable to indicate the meaning of the bool directly?

Comment on lines 89 to 90
m_callSiteMasks.at(name)[i] =
m_callSiteMasks.at(name)[i] || m_references.count(_v.variables[i].name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m_callSiteMasks.at(name)[i] =
m_callSiteMasks.at(name)[i] || m_references.count(_v.variables[i].name);
if (m_references.count(_v.variables[i].name))
m_callSiteMasks.at(name)[i] = true;

}
}

/// Returns a map with function name as key and vector of bools such that if the index `i` of the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move the documentation to the declaration?


/// Returns a map with function name as key and vector of bools such that if the index `i` of the
/// vector is false, then the function's `i`-th return parameter is unused at *all* callsites.
map<YulString, vector<bool>> FindFunctionsWithUnusedReturns::functions()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe turn this into a static function and make the constructor private? We don't want to have this run twice if we can avoid it.

@@ -264,6 +265,24 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
LiteralRematerialiser::run(*m_context, *m_object->code);
UnusedFunctionParameterPruner::run(*m_context, *m_object->code);
}
else if (m_optimizerStep == "unusedFunctionReturnParameterPruner")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use this step to test only the unused function return parameter pruner (this can be used to test that it does not modify small enough functions) and only use the "fullSuite" to test that it works efficiently?

// let a, b, c := f_6(sload(0))
// function f(d)
// {
// let x, y, z
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be better to declare them separately?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do that, however I think it's better to minimize inserting to the front to the vector FunctionDefinition.body.statements. Don't you think a single VariableDeclaration would be better from this perspective?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say it is more important that the optimizer can deal nicely with the variables.

@hrkrshnn hrkrshnn force-pushed the unused-return-parameter-pruner branch 2 times, most recently from 918339e to e32984f Compare November 20, 2020 16:28
Optimization rule that rewrites functions whose return parameters are not used at callsite.
@hrkrshnn hrkrshnn force-pushed the unused-return-parameter-pruner branch from e32984f to 15eeddd Compare November 20, 2020 16:36
ret += ret;
else
ret += std::move(_b);
assert(&_a != &_b);
Copy link
Member Author

@hrkrshnn hrkrshnn Nov 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the other version it was not possible to call this operator if T was not copyable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no solution that works in all cases?

// sstore(x, x)
// if calldataload(0) { leave }
// }
// }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is not working now.

// }
// function f_17(x) -> y
// { f(x) }
// }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inliner is not inlining f_17. Not sure why.

{
let a := sload(1)
let z := f(a)
pop(z)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The step currently removes all pop(identifier) at the beginning. So this test works.

@hrkrshnn hrkrshnn force-pushed the unused-return-parameter-pruner branch from 15eeddd to 03cbc5f Compare November 20, 2020 16:47
@@ -45,6 +45,7 @@ struct OptimiserSettings
"xarulrul" // Prune a bit more in SSA
"xarrcL" // Turn into SSA again and simplify
"gvif" // Run full inliner
"xaTPrci" // Prune unused return values and inline
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to introduce so many additional steps?

* A helper class that removes expressions of the form `pop(a)` where a is an identifier. Generally,
* pop can be the discard function.
*/
class PopRemover: public ASTModifier
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we use the UnusedPruner for that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more general step would be "remove ExpressionStatements that are movable".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we use the UnusedPruner for that?

Because of this: #10080 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It acutally does remove pop(a), but it also removes let a in let a := f(). Since the result of f has to be used somehow, it is turned into pop(f()).

@@ -45,6 +45,7 @@ struct OptimiserSettings
"xarulrul" // Prune a bit more in SSA
"xarrcL" // Turn into SSA again and simplify
"gvif" // Run full inliner
"xaTPrci" // Prune unused return values and inline
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cameel Can you help to determine a good sequence for this, perhaps with the help of yul-phaser? I was expecting the gas cost test test/libsolidity/gasTests/abiv2_optimised.sol to go down. Maybe there is a better sequence.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this sounds like a good opportunity to try out the phaser. Which other input files would you recommend besides test/libsolidity/gasTests/abiv2_optimised.sol?

A metric will be a problem though. Right now I only have a code size metric and even with that weights need some tuning. So I'm not sure if this will be good for finding sequences that specifically remove unused return values.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe test/libsolidity/gasTests/abiv2_optimised.sol is enough to start with.

The code size metric should work, I think.

Copy link
Member

@cameel cameel Feb 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tl;dr

I tried the phaser today and here's what I found:

  • The new optimizer step crashes which interferes with the search. The best sequences I found do not include P at all.
  • It's hard to tell if these sequences are actually any better. I think they're just stealing steps that would be used later anyway.
  • Phaser is not good at looking for better fragments in the middle of the sequence. I could try to improve it. Adding a --suffix option to be able to test with a full sequence might help.

Running the phaser

solc --ir test/libsolidity/gasTests/abiv2_optimised.sol | grep -v 'IR:' > abiv2_optimised.yul

yul-phaser abiv2_optimised.yul \
    --show-initial-population \
    --min-chromosome-length 1 \
    --max-chromosome-length 10 \
    --prefix NdhfoDgvulfnTUtnIfxarrscLMcCTUtTOntnfDIulLculVculjjTpeulxarulrulxarrcLgvif
    --random-population 10 \
    --population xaTPrci \
    --population P

This creates the initial population out of 10 random optimization sequences plus xaTPrci. Also tells the phaser to pre-optimize each program with NdhfoDgvulfnTUtnIfxarrscLMcCTUtTOntnfDIulLculVculjjTpeulxarulrulxarrcLgvif and only then apply and rate sequences from the population.

Note:

  • ReasoningBasedSimplifier is very slow. I had to locally remove it from step list in Chromosome::allStepNames() to get reasonable speed. With it, every round takes minutes (even on a RelWithDebInfo build). Without it, it's less than a second per round.
  • Command-line input validations for some options are incomplete so it can sometimes crash on invalid input. For example make sure you always specify the population and do not use step abbreviations that do not exist. I need to make them more robust.

Phaser output

I did a few runs and selected those that managed to run the longest. Unfortunately there seems to be a bug in this new optimization step and phaser crashes sooner or later (more about it below).

Note that the fitness values are relative to the size of the original program (1000 means no change, 500 means half the size, etc.).

First run (without P in population)

---------- INITIAL POPULATION ----------
353 TcMrsppPtu
541 lT
841 ojTDV
1000 f
1000 vre
1000 hihcdOMgL
1001 eNvihpcnDg
1135 tmPgthU
1166 xaTPrci
1167 IdOaLI
1286 rhUgfarDm
---------- ROUND 219 [round: 0.2 s, total: 38.2 s] ----------
227 vcrsujOmLTu
227 vcrsujOmTLu
227 vcrsujOmTOu
227 vcrsujOmTTu
227 vcrsujOmThu
227 vcrsujOmTsu
231 vcrsujOmLhu
251 vcrsupOmThu
261 vcrsvjOosTu
540 nslnxsP
663 vhrsuVOmTOx
1000 L
Segmentation fault (core dumped)

Second run

---------- INITIAL POPULATION ----------
290 PLppOmhuON
496 gurcdhtmf
541 lof
1000 P
1000 T
1000 Vo
1013 jToiNIeta
1030 fC
1136 DoNogmtp
1149 OTUim
1166 xaTPrci
1197 acnC
---------- ROUND 928 [round: 0.3 s, total: 261.1 s] ----------
226 crTvmsuOj
226 crNTvmsuOj
226 crOTvmsuOj
226 crTDvmsuOj
226 crTIvmsuOj
226 crTLvmsuOj
249 crOvvsuuj
583 crTvmslOj
998 NstM
1000 oD
1000 hMrv
1030 C
Segmentation fault (core dumped)

Optimized programs

If you want to see the optimized programs, you can use this command:

yul-phaser abiv2_optimised.yul \
    --mode print-optimised-programs \
    --rounds 0 \
    --show-initial-population \
    --prefix NdhfoDgvulfnTUtnIfxarrscLMcCTUtTOntnfDIulLculVculjjTpeulxarulrulxarrcLgvif \
    --population <your sequence> \

Here's the output from some of the sequences for convenience:

Analysis

First, your sequence got a score of 1166 which means that it actually makes the optimized program longer (at least for this input file). P alone is 1000. This means that it will be easily outcompeted and P will quickly disappear from the sequence.

If there is a combination of steps where P works better, it might reappear but for that I'd have to tweak algorithm settings to make it converge a bit slower - so that it can try more random things before the single best sequence and its mutations take over the whole population.

I see that the best sequences win by reaching for steps from the "CTUcarrLsTOtfDncarrIulc" // SSA plus simplify part. And they mostly don't contain P. These other steps seem to have much bigger influence than P.

One extra factor to P's disadvantage is the crash - phaser does not crash when P is not in the population so naturally the longest runs are likely not to have P in the winning sequence.

There are some interesting sequences in the output that do contain P, though they are actually just random mutations that happened to be in the population snapshots I grabbed and would disappear in the next round:

  • nslnxsP is much shorter mostly because it removes unused functions. Apart from that there are just a handful of places where calculations were replaced by a constant.
  • PLppOmhuON has a lot more removed and simplified but it's hard for me to tell how much of it is due to P.

Overall, I think that finding a good sequence for this with phaser won't be possible without some modifications:

  • A --suffix option (similar to the current --prefix) would prevent phaser from trying to include steps from the later part of our current sequence.
  • Maybe some constraints on which steps should be used.
  • Having a better metric might help too.

Crash

This reproduces it immediately for me:

yul-phaser test/libyul/yulOptimizerTests/fullSuite/aztec.yul --population 'P'

Here's the relevant part of the stack trace:

Program received signal SIGSEGV, Segmentation fault.

(...)

#0  FindFunctionsWithUnusedReturns::operator() (this=0x7fffffffd470, _v=...) at /usr/include/c++/10.2.0/variant:1554

(...)

#17 solidity::yul::ASTWalker::operator() (this=this@entry=0x7fffffffd470, _block=...) at /projects/solidity/libyul/optimiser/ASTWalker.cpp:89
#18 0x000055555568df81 in FindFunctionsWithUnusedReturns::functions (_dialect=..., _references=..., _block=...) at /projects/solidity/libyul/optimiser/UnusedFunctionReturnParameterPruner.cpp:168
#19 0x000055555568e5d8 in solidity::yul::UnusedFunctionReturnParameterPruner::run (_context=..., _ast=...) at /projects/solidity/libyul/optimiser/UnusedFunctionReturnParameterPruner.cpp:187
#20 0x00005555555f7ee2 in solidity::phaser::Program::applyOptimisationSteps (_dialect=..., _nameDispenser=..., _ast=std::unique_ptr<solidity::yul::Block> = {...}, _optimisationSteps=...) at /projects/solidity/tools/yulPhaser/Program.cpp:206
#21 0x00005555555f7fb9 in solidity::phaser::Program::optimise (this=this@entry=0x7fffffffdc80, _optimisationSteps=std::vector of length 1, capacity 1 = {...}) at /usr/include/c++/10.2.0/bits/unique_ptr.h:172

(...)

So it basically happens several levels deep in the AST walker code that runs when FindFunctionsWithUnusedReturns gets created and its operator () called.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That --suffix option should be a pretty simple modification so let me know when you deal with the crash. I'll give it another shot.

@hrkrshnn
Copy link
Member Author

Closing this for now. The step doesn't seem to reduce costs that much. I'll potentially come back to this in the future

Click for a table of gas differences
file name IR-Opti Legacy-Opti Legacy
interface_inheritance_conversions.sol 18.709% 0.000% 0.000%
abiEncoderV1/abi_decode_v2_storage.sol 0.037% 0.000% 0.000%
abiEncoderV1/abi_encode_calldata_slice.sol 0.415% 0.000% 0.000%
abiEncoderV1/struct/struct_storage_ptr.sol 0.086% 0.000% 0.000%
abiEncoderV2/abi_encode_calldata_slice.sol 0.415% 0.000% 0.000%
abiEncoderV2/abi_encode_v2.sol 0.062% 0.000% 0.000%
abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol 6.860% 0.000% 0.000%
abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol 9.042% 0.000% 0.000%
abiEncoderV2/storage_array_encoding.sol 0.051% 0.000% 0.000%
abiEncoderV2/calldata_array.sol 0.060% 0.000% 0.000%
abiencodedecode/abi_decode_simple_storage.sol 0.055% 0.000% 0.000%
array/arrays_complex_from_and_to_storage.sol 0.036% 0.000% 0.000%
array/byte_array_storage_layout.sol 0.053% 0.000% 0.000%
array/byte_array_transitional_2.sol 0.011% 0.000% 0.000%
array/bytes_length_member.sol 0.069% 0.000% 0.000%
array/create_memory_array.sol 0.047% 0.000% 0.000%
array/dynamic_array_cleanup.sol 0.012% 0.000% 0.000%
array/fixed_array_cleanup.sol 0.017% 0.000% 0.000%
array/fixed_arrays_as_return_type.sol 12.468% 0.000% 0.000%
array/function_array_cross_calls.sol 2.777% 0.000% 0.000%
array/reusing_memory.sol 1.347% 0.000% 0.000%
array/dynamic_arrays_in_storage.sol -0.202% 0.000% 0.000%
array/dynamic_multi_array_cleanup.sol -0.937% 0.000% 0.000%
array/copying/array_copy_calldata_storage.sol 0.012% 0.000% 0.000%
array/copying/array_copy_cleanup_uint128.sol 0.099% 0.000% 0.000%
array/copying/array_copy_cleanup_uint40.sol 0.030% 0.000% 0.000%
array/copying/array_copy_clear_storage.sol 0.044% 0.000% 0.000%
array/copying/array_copy_clear_storage_packed.sol 0.066% 0.000% 0.000%
array/copying/array_copy_different_packing.sol 0.075% 0.000% 0.000%
array/copying/array_copy_storage_storage_different_base.sol 0.030% 0.000% 0.000%
array/copying/array_copy_storage_storage_different_base_nested.sol 0.037% 0.000% 0.000%
array/copying/array_copy_storage_storage_dynamic_dynamic.sol 0.027% 0.000% 0.000%
array/copying/array_copy_storage_storage_static_dynamic.sol 0.072% 0.000% 0.000%
array/copying/array_copy_storage_storage_static_static.sol 0.061% 0.000% 0.000%
array/copying/array_copy_target_leftover.sol 0.032% 0.000% 0.000%
array/copying/array_copy_target_leftover2.sol 0.066% 0.000% 0.000%
array/copying/array_copy_target_simple.sol 0.025% 0.000% 0.000%
array/copying/array_copy_target_simple_2.sol 0.027% 0.000% 0.000%
array/copying/array_storage_multi_items_per_slot.sol 0.075% 0.000% 0.000%
array/copying/arrays_from_and_to_storage.sol 0.059% 0.000% 0.000%
array/copying/bytes_inside_mappings.sol 0.053% 0.000% 0.000%
array/copying/bytes_storage_to_storage.sol 0.019% 0.000% 0.000%
array/copying/calldata_array_dynamic_to_storage.sol 0.067% 0.000% 0.000%
array/copying/copy_byte_array_in_struct_to_storage.sol 0.041% 0.000% 0.000%
array/copying/copy_byte_array_to_storage.sol 0.026% 0.000% 0.000%
array/copying/copy_function_storage_array.sol 0.080% 0.000% 0.000%
array/copying/copy_removes_bytes_data.sol 0.043% 0.000% 0.000%
array/copying/storage_memory_nested_bytes.sol 0.036% 0.000% 0.000%
array/copying/storage_memory_packed_dyn.sol 0.034% 0.000% 0.000%
array/copying/array_copy_including_array.sol -0.035% 0.000% 0.000%
array/copying/array_copy_nested_array.sol -0.004% 0.000% 0.000%
array/copying/array_copy_storage_storage_struct.sol -0.314% 0.000% 0.000%
array/copying/array_copy_storage_to_memory_nested.sol -0.074% 0.000% 0.000%
array/copying/array_nested_calldata_to_storage.sol -0.130% 0.000% 0.000%
array/copying/array_nested_memory_to_storage.sol -0.028% 0.000% 0.000%
array/copying/array_of_struct_calldata_to_storage.sol -0.001% 0.000% 0.000%
array/copying/array_of_struct_memory_to_storage.sol -0.001% 0.000% 0.000%
array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol -0.126% 0.000% 0.000%
array/copying/array_of_structs_containing_arrays_memory_to_storage.sol -0.035% 0.000% 0.000%
array/copying/memory_dyn_2d_bytes_to_storage.sol -0.250% 0.000% 0.000%
array/copying/storage_memory_nested.sol -0.206% 0.000% 0.000%
array/copying/storage_memory_nested_from_pointer.sol -0.206% 0.000% 0.000%
array/copying/storage_memory_nested_struct.sol -0.148% 0.000% 0.000%
array/delete/bytes_delete_element.sol 0.013% 0.000% 0.000%
array/delete/delete_storage_array_packed.sol 0.070% 0.000% 0.000%
array/pop/array_pop_uint16_transition.sol 0.013% 0.000% 0.000%
array/pop/array_pop_uint24_transition.sol 0.019% 0.000% 0.000%
array/pop/byte_array_pop_copy_long.sol 0.043% 0.000% 0.000%
array/pop/byte_array_pop_long_storage_empty.sol 0.016% 0.000% 0.000%
array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol 0.024% 0.000% 0.000%
array/pop/byte_array_pop_masking_long.sol 0.044% 0.000% 0.000%
array/pop/array_pop_array_transition.sol 0.000% 0.000% 0.000%
array/push/array_push.sol 0.050% 0.000% 0.000%
array/push/array_push_packed_array.sol 0.063% 0.000% 0.000%
array/push/byte_array_push_transition.sol 0.009% 0.000% 0.000%
array/push/push_no_args_bytes.sol 0.017% 0.000% 0.000%
array/push/array_push_nested_from_calldata.sol 0.004% 0.000% 0.000%
array/push/array_push_struct.sol -0.017% 0.000% 0.000%
array/push/array_push_struct_from_calldata.sol -0.015% 0.000% 0.000%
array/push/push_no_args_2d.sol -0.313% 0.000% 0.000%
array/concat/bytes_concat_different_types.sol 0.000% 0.000% 0.000%
constructor/arrays_in_constructors.sol 2.883% 0.000% 0.000%
constructor/bytes_in_constructors_packer.sol 5.710% 0.000% 0.000%
constructor/no_callvalue_check.sol 0.057% 0.000% 0.000%
functionCall/mapping_array_internal_argument.sol -0.017% 0.000% 0.000%
functionTypes/store_function.sol 11.057% 0.000% 0.000%
immutable/multi_creation.sol 1.590% 0.000% 0.000%
salted_create/salted_create.sol 0.000% 0.000% 0.000%
salted_create/salted_create_with_value.sol 11.335% 0.000% 0.000%
storage/packed_storage_structs_bytes.sol 0.059% 0.000% 0.000%
structs/struct_containing_bytes_copy_and_delete.sol 0.057% 0.000% 0.000%
structs/struct_copy.sol 0.069% 0.000% 0.000%
structs/struct_copy_via_local.sol -2.976% 0.000% 0.000%
structs/struct_delete_storage_with_array.sol 0.057% 0.000% 0.000%
structs/struct_delete_storage_with_arrays_small.sol 0.060% 0.000% 0.000%
structs/struct_memory_to_storage_function_ptr.sol 0.065% 0.000% 0.000%
structs/structs.sol 0.055% 0.000% 0.000%
structs/memory_structs_nested_load.sol 0.041% 0.000% 0.000%
structs/struct_delete_storage_nested_small.sol -0.148% 0.000% 0.000%
structs/calldata/calldata_struct_with_nested_array_to_storage.sol 0.036% 0.000% 0.000%
structs/conversion/recursive_storage_memory.sol 0.065% 0.000% 0.000%
various/staticcall_for_view_and_pure.sol 0.000% 0.000% 0.000%
various/swap_in_storage_overwrite.sol 0.070% 0.000% 0.000%
various/destructuring_assignment.sol -0.019% 0.000% 0.000%
various/skip_dynamic_types_for_structs.sol 0.076% 0.000% 0.000%
viaYul/array_memory_index_access.sol 0.042% 0.000% 0.000%
viaYul/array_storage_index_boundary_test.sol 0.010% 0.000% 0.000%
viaYul/array_storage_length_access.sol 0.002% 0.000% 0.000%
viaYul/array_storage_push_empty.sol -1.113% 0.000% 0.000%
viaYul/array_storage_push_empty_length_address.sol 0.002% 0.000% 0.000%
viaYul/array_storage_push_pop.sol 0.001% 0.000% 0.000%
viaYul/array_storage_index_access.sol -0.249% 0.000% 0.000%
viaYul/array_storage_index_zeroed_test.sol -5.096% 0.000% 0.000%
externalContracts/deposit_contract.sol 0.650% 0.000% 0.000%
externalContracts/snark.sol -0.677% 0.000% 0.000%
inheritance/address_overload_resolution.sol 14.062% 0.000% 0.000%
inheritance/inherited_function_calldata_calldata_interface.sol 13.440% 0.000% 0.000%
inheritance/inherited_function_calldata_memory_interface.sol 12.222% 0.000% 0.000%

@hrkrshnn hrkrshnn closed this Apr 20, 2021
@chriseth
Copy link
Contributor

Do you think it may be more useful in combination with #11246 ?

@hrkrshnn
Copy link
Member Author

Do you think it may be more useful in combination with #11246 ?

I don't think it should help. But I will rebase and check the costs again once it's merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants