Optimize adjacent DROPs
Clarification and motivation
We would like to optimize adjacent DROP
instructions by merging them into a single DROP n
. We have adjacentDrops
rule for that. However, currently it can optimize only sequence of 2 DROPs
and that's not very useful. Optimizing longer sequences is more beneficial (though these sentences appear less often).
The problem is that when we see DROP; DROP; DROP
we will optimize it to DROP 2; DROP
and then won't recognize this pattern. So obviously we need a pattern like this one: Seq (DROPN (SS (SS SZ))) DROP -> Just (DROPN (SS $ SS $ SS SZ))
. Unfortunately it doesn't compile for some reason. I think there is some trick using which we can make it compile, but I couldn't come up with it quickly, hence this issue.
We have a workaround for it in one private repo:
optimizeDrops
:: forall parameter storage.
ContractCode parameter storage -> ContractCode parameter storage
optimizeDrops =
doOptimize rule2 .
doOptimize rule3 .
doOptimize rule4
where
doOptimize ::
Optimizer.Rule -> ContractCode parameter storage -> ContractCode parameter storage
doOptimize rule =
optimizeLorentzWithConf Optimizer.OptimizerConf
{ gotoValues = True
, ruleset = Optimizer.defaultRules `Optimizer.orSimpleRule` rule
}
rule2 :: Optimizer.Rule
rule2 = \case
Seq DROP DROP -> Just (DROPN (SS $ SS SZ))
Seq DROP (Seq DROP c) -> Just (DROPN (SS $ SS SZ) `Seq` c)
_ -> Nothing
rule3 :: Optimizer.Rule
rule3 = \case
Seq DROP (Seq DROP DROP) -> Just (DROPN (SS $ SS $ SS SZ))
Seq DROP (Seq DROP (Seq DROP c)) -> Just (DROPN (SS $ SS $ SS SZ) `Seq` c)
_ -> Nothing
rule4 :: Optimizer.Rule
rule4 = \case
Seq DROP (Seq DROP (Seq DROP DROP)) ->
Just (DROPN (SS $ SS $ SS $ SS SZ))
Seq DROP (Seq DROP (Seq DROP (Seq DROP c))) ->
Just (DROPN (SS $ SS $ SS $ SS SZ) `Seq` c)
_ -> Nothing
The idea is to match 4 DROPs first, then try 3, then 2. It seems to work fine, but looks a bit ugly and scales poorly (we have to write ruleI
for all I ≤ N
where N
is the maximal length of DROPs
we support). I think this workaround is more or less acceptable, but it'd be nice to avoid it. Also it won't optimize DROP 2; DROP 2
for example.
Acceptance criteria
After applying our optimize
instruction all adjacent DROP
s in a contract are squashed. DROP n
should be considered as well. So DROP [n]; DROP [m]; DROP [l]…
should be squashed into single DROP s
.