Inlining heuristics for `FunctionSpecializer`
Abstract and Motivation
This mainly came up in https://twitter.com/d1ll0nk/status/1600472867661295616. In short, for code where function pointers are used as arguments, FunctionSpecializer would end up specializing the function (because the function pointers would be constants). This may lead to code that's not ideal.
Specification
Use a similar heuristic to the FullInliner in the FunctionSpecializer. The original context for FunctionSpecializer was to handle cases that the FullInliner couldn't do. So we have to rethink and benchmark this again, especially since the inline heuristics were changed after the new Yul code transform.
For the record, I've seen the FunctionSpecializer be quite detrimental in cases without function pointers as well.
Ideally, we'd have backtracking, i.e. we could tell if specializing the function allows simplifying it and only then specialize, but that's highly non-trivial, of course...
For reference, here's the full code of the specialized functions from the example in the tweet:


The specialized bits are just
if iszero(lt(var_componentIndex, mload(var_offer_mpos))) {
mstore( 0, 1619580894)
revert(28, 4)
}
and
let var_errorHandler_functionIdentifier := 3
if iszero(lt(var_componentIndex, mload( var_offer_mpos)))
{
var_errorHandler_functionIdentifier := var_errorHandler_functionIdentifier
mstore( 0, 3216242894)
revert(28, 4)
}
so this added ~100 bytes to save a couple of stack manipulation ops.
We may want to document that in cases that are affected this, it's an option to use a custom optimizer sequence without the function specializer (see https://github.com/ethereum/solidity/issues/13858#issuecomment-1428754261) - since it may take a bit to come up with a proper solution here. A more aggressive measure would be to remove it from the default sequence until this is fixed.
Hi, any news on this? It's been high impact must have since Dec' 2022...