Merge branch 'feature/babylon-optimizer' into 'dev'
Update optimizer for Babylon See merge request ligolang/ligo!158
This commit is contained in:
commit
76ecd56e3d
@ -14,13 +14,44 @@ open Tezos_utils.Michelson
|
|||||||
without effects other than gas consumption. It must never fail. *)
|
without effects other than gas consumption. It must never fail. *)
|
||||||
|
|
||||||
let arity : prim -> int option = function
|
let arity : prim -> int option = function
|
||||||
|
(* stack things *)
|
||||||
|
| I_DIP -> None
|
||||||
|
| I_DROP -> None
|
||||||
|
| I_DUP -> None
|
||||||
|
| I_SWAP -> None
|
||||||
|
| I_DIG -> None
|
||||||
|
| I_DUG -> None
|
||||||
|
(* control *)
|
||||||
|
| I_FAILWITH -> None
|
||||||
|
| I_EXEC -> None
|
||||||
|
| I_IF -> None
|
||||||
|
| I_IF_CONS -> None
|
||||||
|
| I_IF_LEFT -> None
|
||||||
|
| I_IF_NONE -> None
|
||||||
|
| I_LOOP -> None
|
||||||
|
| I_MAP -> None
|
||||||
|
| I_ITER -> None
|
||||||
|
| I_LOOP_LEFT -> None
|
||||||
|
(* internal ops *)
|
||||||
|
| I_CREATE_ACCOUNT -> None
|
||||||
|
| I_CREATE_CONTRACT -> None
|
||||||
|
| I_TRANSFER_TOKENS -> None
|
||||||
|
| I_SET_DELEGATE -> None
|
||||||
|
(* tez arithmetic (can fail) *)
|
||||||
|
| I_ADD -> None
|
||||||
|
| I_MUL -> None
|
||||||
|
| I_SUB -> None (* can fail for tez *)
|
||||||
|
(* etc *)
|
||||||
|
| I_CONCAT -> None (* sometimes 1, sometimes 2 :( *)
|
||||||
|
| I_CAST -> None
|
||||||
|
| I_RENAME -> None
|
||||||
|
(* stuff *)
|
||||||
| I_PACK -> Some 1
|
| I_PACK -> Some 1
|
||||||
| I_UNPACK -> Some 1
|
| I_UNPACK -> Some 1
|
||||||
| I_BLAKE2B -> Some 1
|
| I_BLAKE2B -> Some 1
|
||||||
| I_SHA256 -> Some 1
|
| I_SHA256 -> Some 1
|
||||||
| I_SHA512 -> Some 1
|
| I_SHA512 -> Some 1
|
||||||
| I_ABS -> Some 1
|
| I_ABS -> Some 1
|
||||||
| I_ADD -> None (* can fail for tez *)
|
|
||||||
| I_AMOUNT -> Some 0
|
| I_AMOUNT -> Some 0
|
||||||
| I_AND -> Some 2
|
| I_AND -> Some 2
|
||||||
| I_BALANCE -> Some 0
|
| I_BALANCE -> Some 0
|
||||||
@ -28,39 +59,24 @@ let arity : prim -> int option = function
|
|||||||
| I_CDR -> Some 1
|
| I_CDR -> Some 1
|
||||||
| I_CHECK_SIGNATURE -> Some 3
|
| I_CHECK_SIGNATURE -> Some 3
|
||||||
| I_COMPARE -> Some 2
|
| I_COMPARE -> Some 2
|
||||||
| I_CONCAT -> None (* sometimes 1, sometimes 2 :( *)
|
|
||||||
| I_CONS -> Some 2
|
| I_CONS -> Some 2
|
||||||
| I_CREATE_ACCOUNT -> None (* effects, kind of *)
|
|
||||||
| I_CREATE_CONTRACT -> None (* effects, kind of *)
|
|
||||||
| I_IMPLICIT_ACCOUNT -> Some 1
|
| I_IMPLICIT_ACCOUNT -> Some 1
|
||||||
| I_DIP -> None
|
|
||||||
| I_DROP -> None
|
|
||||||
| I_DUP -> None
|
|
||||||
| I_EDIV -> Some 2
|
| I_EDIV -> Some 2
|
||||||
| I_EMPTY_MAP -> Some 0
|
| I_EMPTY_MAP -> Some 0
|
||||||
| I_EMPTY_SET -> Some 0
|
| I_EMPTY_SET -> Some 0
|
||||||
| I_EQ -> Some 1
|
| I_EQ -> Some 1
|
||||||
| I_EXEC -> None (* effects *)
|
|
||||||
| I_FAILWITH -> None
|
|
||||||
| I_GE -> Some 1
|
| I_GE -> Some 1
|
||||||
| I_GET -> Some 2
|
| I_GET -> Some 2
|
||||||
| I_GT -> Some 1
|
| I_GT -> Some 1
|
||||||
| I_HASH_KEY -> Some 1
|
| I_HASH_KEY -> Some 1
|
||||||
| I_IF -> None
|
|
||||||
| I_IF_CONS -> None
|
|
||||||
| I_IF_LEFT -> None
|
|
||||||
| I_IF_NONE -> None
|
|
||||||
| I_INT -> Some 1
|
| I_INT -> Some 1
|
||||||
| I_LAMBDA -> Some 0
|
| I_LAMBDA -> Some 0
|
||||||
| I_LE -> Some 1
|
| I_LE -> Some 1
|
||||||
| I_LEFT -> Some 1
|
| I_LEFT -> Some 1
|
||||||
| I_LOOP -> None
|
|
||||||
| I_LSL -> Some 1
|
| I_LSL -> Some 1
|
||||||
| I_LSR -> Some 1
|
| I_LSR -> Some 1
|
||||||
| I_LT -> Some 1
|
| I_LT -> Some 1
|
||||||
| I_MAP -> None
|
|
||||||
| I_MEM -> Some 2
|
| I_MEM -> Some 2
|
||||||
| I_MUL -> None (* can fail for tez *)
|
|
||||||
| I_NEG -> Some 1
|
| I_NEG -> Some 1
|
||||||
| I_NEQ -> Some 1
|
| I_NEQ -> Some 1
|
||||||
| I_NIL -> Some 0
|
| I_NIL -> Some 0
|
||||||
@ -78,26 +94,17 @@ let arity : prim -> int option = function
|
|||||||
| I_SELF -> Some 0
|
| I_SELF -> Some 0
|
||||||
| I_SLICE -> Some 3
|
| I_SLICE -> Some 3
|
||||||
| I_STEPS_TO_QUOTA -> Some 0
|
| I_STEPS_TO_QUOTA -> Some 0
|
||||||
| I_SUB -> None (* can fail for tez *)
|
|
||||||
| I_SWAP -> None
|
|
||||||
| I_TRANSFER_TOKENS -> None (* effects, kind of *)
|
|
||||||
| I_SET_DELEGATE -> None (* effects, kind of *)
|
|
||||||
| I_UNIT -> Some 0
|
| I_UNIT -> Some 0
|
||||||
| I_UPDATE -> Some 3
|
| I_UPDATE -> Some 3
|
||||||
| I_XOR -> Some 2
|
| I_XOR -> Some 2
|
||||||
| I_ITER -> None
|
|
||||||
| I_LOOP_LEFT -> None
|
|
||||||
| I_ADDRESS -> Some 1
|
| I_ADDRESS -> Some 1
|
||||||
| I_CONTRACT -> Some 1
|
| I_CONTRACT -> Some 1
|
||||||
| I_ISNAT -> Some 1
|
| I_ISNAT -> Some 1
|
||||||
| I_CAST -> None
|
|
||||||
| I_RENAME -> None
|
|
||||||
| I_CHAIN_ID -> Some 0
|
| I_CHAIN_ID -> Some 0
|
||||||
| I_EMPTY_BIG_MAP -> Some 0
|
| I_EMPTY_BIG_MAP -> Some 0
|
||||||
| I_APPLY -> None
|
| I_APPLY -> Some 2
|
||||||
| I_DIG -> None
|
|
||||||
| I_DUG -> None
|
|
||||||
|
|
||||||
|
(* not instructions *)
|
||||||
| K_parameter
|
| K_parameter
|
||||||
| K_storage
|
| K_storage
|
||||||
| K_code
|
| K_code
|
||||||
@ -271,15 +278,15 @@ let rec iterate_optimizer (f : michelson -> bool * michelson) : michelson -> mic
|
|||||||
|
|
||||||
let opt_drop2 : peep2 = function
|
let opt_drop2 : peep2 = function
|
||||||
(* nullary_op ; DROP ↦ *)
|
(* nullary_op ; DROP ↦ *)
|
||||||
| Prim (_, p, _, _), Prim (_, I_DROP, _, _) when is_nullary_op p -> Some []
|
| Prim (_, p, _, _), Prim (_, I_DROP, [], _) when is_nullary_op p -> Some []
|
||||||
(* DUP ; DROP ↦ *)
|
(* DUP ; DROP ↦ *)
|
||||||
| Prim (_, I_DUP, _, _), Prim (_, I_DROP, _, _) -> Some []
|
| Prim (_, I_DUP, _, _), Prim (_, I_DROP, [], _) -> Some []
|
||||||
(* unary_op ; DROP ↦ DROP *)
|
(* unary_op ; DROP ↦ DROP *)
|
||||||
| Prim (_, p, _, _), Prim (_, I_DROP, _, _) when is_unary_op p -> Some [i_drop]
|
| Prim (_, p, _, _), Prim (_, I_DROP, [], _) when is_unary_op p -> Some [i_drop]
|
||||||
(* binary_op ; DROP ↦ DROP ; DROP *)
|
(* binary_op ; DROP ↦ DROP ; DROP *)
|
||||||
| Prim (_, p, _, _), Prim (_, I_DROP, _, _) when is_binary_op p -> Some [i_drop; i_drop]
|
| Prim (_, p, _, _), Prim (_, I_DROP, [], _) when is_binary_op p -> Some [i_drop; i_drop]
|
||||||
(* ternary_op ; DROP ↦ DROP ; DROP ; DROP *)
|
(* ternary_op ; DROP ↦ DROP ; DROP ; DROP *)
|
||||||
| Prim (_, p, _, _), Prim (_, I_DROP, _, _) when is_ternary_op p -> Some [i_drop; i_drop; i_drop]
|
| Prim (_, p, _, _), Prim (_, I_DROP, [], _) when is_ternary_op p -> Some [i_drop; i_drop; i_drop]
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
let opt_drop4 : peep4 = function
|
let opt_drop4 : peep4 = function
|
||||||
@ -287,7 +294,7 @@ let opt_drop4 : peep4 = function
|
|||||||
| Prim (_, I_DUP, _, _),
|
| Prim (_, I_DUP, _, _),
|
||||||
(Prim (_, p, _, _) as unary_op),
|
(Prim (_, p, _, _) as unary_op),
|
||||||
Prim (_, I_SWAP, _, _),
|
Prim (_, I_SWAP, _, _),
|
||||||
Prim (_, I_DROP, _, _)
|
Prim (_, I_DROP, [], _)
|
||||||
when is_unary_op p ->
|
when is_unary_op p ->
|
||||||
Some [unary_op]
|
Some [unary_op]
|
||||||
| _ -> None
|
| _ -> None
|
||||||
@ -301,19 +308,6 @@ let opt_dip1 : peep1 = function
|
|||||||
(* DIP { unary_op } ↦ SWAP ; unary_op ; SWAP *)
|
(* DIP { unary_op } ↦ SWAP ; unary_op ; SWAP *)
|
||||||
| Prim (_, I_DIP, [Seq (_, [(Prim (_, p, _, _) as unary_op)])], _) when is_unary_op p ->
|
| Prim (_, I_DIP, [Seq (_, [(Prim (_, p, _, _) as unary_op)])], _) when is_unary_op p ->
|
||||||
Some [i_swap ; unary_op ; i_swap]
|
Some [i_swap ; unary_op ; i_swap]
|
||||||
(* saves 5 bytes *)
|
|
||||||
(* DIP { DROP } ↦ SWAP ; DROP *)
|
|
||||||
| Prim (_, I_DIP, [Seq (_, [Prim (_, I_DROP, _, _)])], _) ->
|
|
||||||
Some [i_swap; i_drop]
|
|
||||||
(* saves 3 bytes *)
|
|
||||||
(* DIP { DROP ; DROP } ↦ SWAP ; DROP ; SWAP ; DROP *)
|
|
||||||
| Prim (_, I_DIP, [Seq (_, [Prim (_, I_DROP, _, _) ; Prim (_, I_DROP, _, _)])], _) ->
|
|
||||||
Some [i_swap; i_drop; i_swap; i_drop]
|
|
||||||
(* still saves 1 byte *)
|
|
||||||
(* DIP { DROP ; DROP ; DROP } ↦ SWAP ; DROP ; SWAP ; DROP ; SWAP ; DROP *)
|
|
||||||
| Prim (_, I_DIP, [Seq (_, [Prim (_, I_DROP, _, _) ; Prim (_, I_DROP, _, _) ; Prim (_, I_DROP, _, _)])], _) ->
|
|
||||||
Some [i_swap; i_drop; i_swap; i_drop; i_swap; i_drop]
|
|
||||||
(* after this, DIP { DROP ; ... } is smaller *)
|
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
let opt_dip2 : peep2 = function
|
let opt_dip2 : peep2 = function
|
||||||
@ -323,16 +317,16 @@ let opt_dip2 : peep2 = function
|
|||||||
| Prim (_, I_DIP, [Seq (_, code1)], _), Prim (_, I_DIP, [Seq (_, code2)], _) ->
|
| Prim (_, I_DIP, [Seq (_, code1)], _), Prim (_, I_DIP, [Seq (_, code2)], _) ->
|
||||||
Some [Prim (0, I_DIP, [Seq (0, code1 @ code2)], [])]
|
Some [Prim (0, I_DIP, [Seq (0, code1 @ code2)], [])]
|
||||||
(* DIP { code } ; DROP ↦ DROP ; code *)
|
(* DIP { code } ; DROP ↦ DROP ; code *)
|
||||||
| Prim (_, I_DIP, code, _), (Prim (_, I_DROP, _, _) as drop) ->
|
| Prim (_, I_DIP, [Seq (_, code)], _), (Prim (_, I_DROP, [], _) as drop) ->
|
||||||
Some (drop :: code)
|
Some (drop :: code)
|
||||||
(* nullary_op ; DIP { code } ↦ code ; nullary_op *)
|
(* nullary_op ; DIP { code } ↦ code ; nullary_op *)
|
||||||
| (Prim (_, p, _, _) as nullary_op), Prim (_, I_DIP, [Seq (_, code)], _) when is_nullary_op p ->
|
| (Prim (_, p, _, _) as nullary_op), Prim (_, I_DIP, [Seq (_, code)], _) when is_nullary_op p ->
|
||||||
Some (code @ [nullary_op])
|
Some (code @ [nullary_op])
|
||||||
(* DIP { code } ; unary_op ↦ unary_op ; DIP { code } *)
|
(* DIP { code } ; unary_op ↦ unary_op ; DIP { code } *)
|
||||||
| (Prim (_, I_DIP, _, _) as dip), (Prim (_, p, _, _) as unary_op) when is_unary_op p ->
|
| (Prim (_, I_DIP, [Seq _], _) as dip), (Prim (_, p, _, _) as unary_op) when is_unary_op p ->
|
||||||
Some [unary_op; dip]
|
Some [unary_op; dip]
|
||||||
(* unary_op ; DIP { code } ↦ DIP { code } ; unary_op *)
|
(* unary_op ; DIP { code } ↦ DIP { code } ; unary_op *)
|
||||||
(* | (Prim (_, p, _, _) as unary_op), (Prim (_, I_DIP, _, _) as dip) when is_unary_op p ->
|
(* | (Prim (_, p, _, _) as unary_op), (Prim (_, I_DIP, [Seq _], _) as dip) when is_unary_op p ->
|
||||||
* Some [dip; unary_op] *)
|
* Some [dip; unary_op] *)
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
@ -378,6 +372,24 @@ let rec opt_tail_fail : michelson -> michelson =
|
|||||||
Prim (l, p, List.map opt_tail_fail args, annot)
|
Prim (l, p, List.map opt_tail_fail args, annot)
|
||||||
| x -> x
|
| x -> x
|
||||||
|
|
||||||
|
let rec opt_combine_drops (x : michelson) : michelson =
|
||||||
|
let rec combine : michelson list -> michelson list = function
|
||||||
|
| [] -> []
|
||||||
|
| Prim (_, I_DROP, [], []) :: xs ->
|
||||||
|
let xs' = combine xs in
|
||||||
|
begin match xs' with
|
||||||
|
| [] -> [Prim (-1, I_DROP, [], [])]
|
||||||
|
| Prim (_, I_DROP, [], []) :: xs' -> Prim (-1, I_DROP, [Int (-1, Z.of_int 2)], []) :: xs'
|
||||||
|
| Prim (_, I_DROP, [Int (_, n)], []) :: xs' -> Prim (-1, I_DROP, [Int (-1, Z.of_int (1 + Z.to_int n))], []) :: xs'
|
||||||
|
| x' :: xs' -> Prim (-1, I_DROP, [], []) :: x' :: xs'
|
||||||
|
end
|
||||||
|
| x :: xs -> x :: combine xs in
|
||||||
|
match x with
|
||||||
|
| Seq (l, args) -> Seq (l, combine (List.map opt_combine_drops args))
|
||||||
|
| Prim (l, p, args, annot) ->
|
||||||
|
Prim (l, p, List.map opt_combine_drops args, annot)
|
||||||
|
| x -> x
|
||||||
|
|
||||||
let optimize : michelson -> michelson =
|
let optimize : michelson -> michelson =
|
||||||
fun x ->
|
fun x ->
|
||||||
let x = use_lambda_instr x in
|
let x = use_lambda_instr x in
|
||||||
@ -391,4 +403,5 @@ let optimize : michelson -> michelson =
|
|||||||
peephole @@ peep2 opt_swap2 ;
|
peephole @@ peep2 opt_swap2 ;
|
||||||
] in
|
] in
|
||||||
let x = iterate_optimizer (sequence_optimizers optimizers) x in
|
let x = iterate_optimizer (sequence_optimizers optimizers) x in
|
||||||
|
let x = opt_combine_drops x in
|
||||||
x
|
x
|
||||||
|
@ -58,6 +58,7 @@ let i_some = prim I_SOME
|
|||||||
let i_lambda arg ret body = prim ~children:[arg;ret;body] I_LAMBDA
|
let i_lambda arg ret body = prim ~children:[arg;ret;body] I_LAMBDA
|
||||||
let i_empty_map src dst = prim ~children:[src;dst] I_EMPTY_MAP
|
let i_empty_map src dst = prim ~children:[src;dst] I_EMPTY_MAP
|
||||||
let i_drop = prim I_DROP
|
let i_drop = prim I_DROP
|
||||||
|
let i_dropn n = prim I_DROP ~children:[int (Z.of_int n)]
|
||||||
let i_exec = prim I_EXEC
|
let i_exec = prim I_EXEC
|
||||||
|
|
||||||
let i_if a b = prim ~children:[seq [a] ; seq[b]] I_IF
|
let i_if a b = prim ~children:[seq [a] ; seq[b]] I_IF
|
||||||
|
Loading…
Reference in New Issue
Block a user