diff --git a/src/plugins/eva/domains/multidim/multidim_domain.ml b/src/plugins/eva/domains/multidim/multidim_domain.ml index 2b2bb6301f28d2a3547714dce4c2c3e10f5314e9..2924a23612871f2dbbaa59c831ce7710cbb83180 100644 --- a/src/plugins/eva/domains/multidim/multidim_domain.ml +++ b/src/plugins/eva/domains/multidim/multidim_domain.ml @@ -611,7 +611,8 @@ struct let narrow = join ~cache ~symmetric:false ~idempotent:true ~decide in fun (m1,t1) (m2,t2) -> `Value (narrow m1 m2, join_tracked t1 t2) - let join' ~oracle (m1,t1) (m2,t2) = + (* Precise join with oracle, but cannot be cached. *) + let precise_join ~oracle m1 m2 = let open BaseMap in let cache = Hptmap_sig.NoCache and decide _ x1 x2 = @@ -619,8 +620,27 @@ struct and m2,r2 = Option.value ~default:V.top x2 in Memory.join ~oracle m1 m2, Referers.union r1 r2 (* TODO: Remove tops *) in - generic_join ~cache ~symmetric:false ~idempotent:true ~decide m1 m2, - join_tracked t1 t2 + generic_join ~cache ~symmetric:false ~idempotent:true ~decide m1 m2 + + (* Optimized join without oracle. *) + let fast_join = + let open BaseMap in + let oracle _ _ = Int_val.top in + let cache = cache_name "fast_join" + and decide _ x1 x2 = + let m1, r1 = Option.value ~default:V.top x1 + and m2, r2 = Option.value ~default:V.top x2 in + Memory.join ~oracle m1 m2, Referers.union r1 r2 (* TODO: Remove tops *) + in + generic_join ~cache ~symmetric:true ~idempotent:true ~decide + + let join' ~oracle (m1, t1) (m2, t2) = + let m = + if Parameters.MultidimFastImprecise.get () + then fast_join m1 m2 + else precise_join ~oracle m1 m2 + in + m, join_tracked t1 t2 let join s1 s2 = let oracle = mk_bioracle s1 s2 in @@ -890,21 +910,16 @@ struct let relate _kf _bases _state = Base.SetLattice.empty - let filter _kind bases (base_map,tracked : t) = - BaseMap.filter (fun elt -> Base.Hptset.mem elt bases) base_map, + let filter _kind bases (base_map, tracked : t) = + BaseMap.inter_with_shape bases base_map, Option.map (Tracking.inter bases) tracked - let reuse _kf bases = - let open BaseMap in - let cache = Hptmap_sig.NoCache in - let decide_both _key _v1 v2 = Some v2 in - let decide_left key v1 = - if Base.Hptset.mem key bases then None else Some v1 - in - let reuse = merge ~cache ~symmetric:false ~idempotent:true - ~decide_both ~decide_left:(Traversing decide_left) ~decide_right:Neutral - in - fun ~current_input:(m1,t1) ~previous_output:(m2,t2) -> + let reuse = + let cache = cache_name "reuse" in + let decide _key _v1 v2 = v2 in + let reuse = BaseMap.join ~cache ~symmetric:false ~idempotent:true ~decide in + fun _kf bases ~current_input:(m1,t1) ~previous_output:(m2,t2) -> + let m1 = BaseMap.diff_with_shape bases m1 in reuse m1 m2, join_tracked t1 t2 end @@ -923,15 +938,22 @@ let multidim_hook (module Abstract: Abstractions.S) : (module Abstractions.S) = let join a b = let r = join (set key Domain.top a) (set key Domain.top b) in - let oracle state exp = (* TODO: cache results *) - let v, _alarms = Eval.evaluate state exp in - match v with - | `Bottom -> Cvalue.V.top - | `Value (_valuation,v) -> get_cval v + let oracle state = + let valuation_ref = ref Eval.Valuation.empty in + fun exp -> + let valuation = !valuation_ref in + let v, _alarms = Eval.evaluate ~valuation state exp in + match v with + | `Bottom -> Cvalue.V.top + | `Value (valuation, v) -> + valuation_ref := valuation; + get_cval v in + let left_oracle = oracle a + and right_oracle = oracle b in let oracle = function - | Abstract_memory.Left -> convert_oracle (oracle a) - | Abstract_memory.Right -> convert_oracle (oracle b) + | Abstract_memory.Left -> convert_oracle left_oracle + | Abstract_memory.Right -> convert_oracle right_oracle in let multidim = Domain.join' ~oracle (get_multidim a) (get_multidim b) in set key multidim r diff --git a/src/plugins/eva/domains/multidim/segmentation.ml b/src/plugins/eva/domains/multidim/segmentation.ml index 475933251eaa60f4d2ca7ea589200eeeb63ce19b..3a9f3ce61ec69cf8c416f50c9e5e732ba2d5e920 100644 --- a/src/plugins/eva/domains/multidim/segmentation.ml +++ b/src/plugins/eva/domains/multidim/segmentation.ml @@ -288,21 +288,25 @@ struct let eq ?(oracle=no_oracle) b1 b2 = cmp ~oracle b1 b2 = Equal + let missing_bound kind b = + (* Do not warn when -eva-multidim-fast-imprecise is set, as it is expected + that bounds cannot be retrieved in this case. *) + if not (Parameters.MultidimFastImprecise.get ()) + then + Self.warning ~current:true ~once:true + "Multidim domain: cannot retrieve %s for %a" + kind pretty b; + `Top + let lower_integer ~oracle b = match Int_val.min_int (to_int_val ~oracle b) with | Some l -> `Value l - | None -> - Self.warning ~current:true "cannot retrieve a lower bound for %a" - pretty b; - `Top + | None -> missing_bound "a lower bound" b let upper_integer ~oracle b = match Int_val.max_int (to_int_val ~oracle b) with | Some u -> `Value u - | None -> - Self.warning ~current:true "cannot retrieve an upper bound for %a" - pretty b; - `Top + | None -> missing_bound "an upper bound" b let lower_bound ~oracle b1 b2 = if b1 == b2 || eq b1 b2 then `Value b1 else @@ -870,8 +874,8 @@ struct | `Value m -> m | `Bottom -> assert false | `Top -> - Self.warning ~current:true - "failed to introduce %a inside the array segmentation" + Self.warning ~current:true ~once:true + "Multidim domain: failed to introduce %a inside the array segmentation" Bound.pretty b; m in diff --git a/src/plugins/eva/parameters.ml b/src/plugins/eva/parameters.ml index 6bd34e41303c915de0220d07de608ce1c0222721..9900dd5cc70f953e69095e7a1a3e02c8453f7105 100644 --- a/src/plugins/eva/parameters.ml +++ b/src/plugins/eva/parameters.ml @@ -355,6 +355,15 @@ module MultidimDisjunctiveInvariants = False end) let () = add_precision_dep MultidimDisjunctiveInvariants.parameter +let () = Parameter_customize.set_group domains +let () = Parameter_customize.is_invisible () +module MultidimFastImprecise = False + (struct + let option_name = "-eva-multidim-fast-imprecise" + let help = "Makes the multidim domain faster but less precise: \ + the domain can lose more information when joining states." + end) +let () = add_precision_dep MultidimFastImprecise.parameter (* -------------------------------------------------------------------------- *) (* --- Performance options --- *) diff --git a/src/plugins/eva/parameters.mli b/src/plugins/eva/parameters.mli index d477b8af08ab8777ec7c2e534df5b8a522707a1e..7fa79238485ed73982558724e55d2687172c97ae 100644 --- a/src/plugins/eva/parameters.mli +++ b/src/plugins/eva/parameters.mli @@ -45,6 +45,7 @@ module TracesProject: Parameter_sig.Bool module MultidimSegmentLimit: Parameter_sig.Int module MultidimDisjunctiveInvariants: Parameter_sig.Bool +module MultidimFastImprecise: Parameter_sig.Bool module AutomaticContextMaxDepth: Parameter_sig.Int module AutomaticContextMaxWidth: Parameter_sig.Int