summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Bauereiss2019-03-25 18:56:46 +0000
committerThomas Bauereiss2019-03-26 16:13:02 +0000
commit02af1340fe4dcd5da307c9bec6c42982a1f9d969 (patch)
treeee1cde9e4b1863fa6f340f98d6c7667e047b202b /src
parentd9b592b89bd2c47622aa9dbcd0843936322322e3 (diff)
Constant-fold __size calls if possible
Diffstat (limited to 'src')
-rw-r--r--src/constant_propagation.ml19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/constant_propagation.ml b/src/constant_propagation.ml
index 1a39b2a1..6caa5ecd 100644
--- a/src/constant_propagation.ml
+++ b/src/constant_propagation.ml
@@ -622,8 +622,16 @@ let const_props defs ref_vars =
(interpreter-based) constant folding.
Boolean connectives are special-cased to support short-circuiting when one
argument has a suitable value (even if the other one is not constant).
+ Moreover, calls to a __size function (in particular generated by sizeof
+ rewriting) with a known-constant return type are replaced by that constant;
+ e.g., (length(op : bits(32)) : int(32)) becomes 32 even if op is not constant.
*)
and const_prop_try_fn env (id, args) (l, annot) =
+ let exp = E_aux (E_app (id, args), (l, annot)) in
+ let rec is_overload_of f =
+ Env.get_overloads f env
+ |> List.exists (fun id' -> Id.compare id id' = 0 || is_overload_of id')
+ in
match (string_of_id id, args) with
| "and_bool", ([E_aux (E_lit (L_aux (L_false, _)), _) as e_false; _] |
[_; E_aux (E_lit (L_aux (L_false, _)), _) as e_false]) ->
@@ -631,9 +639,14 @@ let const_props defs ref_vars =
| "or_bool", ([E_aux (E_lit (L_aux (L_true, _)), _) as e_true; _] |
[_; E_aux (E_lit (L_aux (L_true, _)), _) as e_true]) ->
e_true
- | _ ->
- let exp = (E_aux (E_app (id, args), (l, annot))) in
- if List.for_all Constant_fold.is_constant args then const_fold exp else exp
+ | _, _ when List.for_all Constant_fold.is_constant args ->
+ const_fold exp
+ | _, [arg] when is_overload_of (mk_id "__size") ->
+ (match destruct_atom_nexp env (typ_of exp) with
+ | Some (Nexp_aux (Nexp_constant i, _)) ->
+ E_aux (E_lit (mk_lit (L_num i)), (l, annot))
+ | _ -> exp)
+ | _ -> exp
and can_match_with_env env (E_aux (e,(l,annot)) as exp0) cases (substs,ksubsts) assigns =
let rec findpat_generic check_pat description assigns = function