Skip to content

Commit 8cb50d4

Browse files
authored
Merge pull request #364 from goblint/td3-solve-tf-abort
TD3: optimize destabilization by aborting transfer function when unchanged
2 parents b72dfe4 + 1aea84c commit 8cb50d4

File tree

11 files changed

+348
-57
lines changed

11 files changed

+348
-57
lines changed

scripts/creduce-abort-verify.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
gcc -c -Werror=implicit-function-declaration ./abort-verify.c
6+
7+
GOBLINTDIR="/mnt/goblint-svcomp/sv-comp/goblint"
8+
OPTS="--conf $GOBLINTDIR/conf/svcomp.json --enable exp.solver.td3.abort --enable exp.solver.td3.abort-verify --sets ana.specification /mnt/goblint-svcomp/benchexec/sv-benchmarks/c/properties/unreach-call.prp --sets exp.architecture 64bit ./abort-verify.c"
9+
INTERESTING="TD3 abort verify: should not abort"
10+
OUTDIR="creduce-abort-verify"
11+
12+
13+
mkdir -p $OUTDIR
14+
15+
LOG="$OUTDIR/out.log"
16+
$GOBLINTDIR/goblint $OPTS -v --enable dbg.debug &> $LOG || true
17+
grep -F "Function definition missing" $LOG && exit 1
18+
19+
grep -F "$INTERESTING" $LOG

src/framework/analyses.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct
5555

5656
let pretty_trace () ((n,c) as x) =
5757
if get_bool "dbg.trace.context" then dprintf "(%a, %a) on %a \n" Node.pretty_trace n LD.pretty c CilType.Location.pretty (getLocation x)
58+
(* if get_bool "dbg.trace.context" then dprintf "(%a, %d) on %a" Node.pretty_trace n (LD.tag c) CilType.Location.pretty (getLocation x) *)
5859
else dprintf "%a on %a" Node.pretty_trace n CilType.Location.pretty (getLocation x)
5960

6061
let printXml f (n,c) =

src/framework/constraints.ml

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ module FromSpec (S:Spec) (Cfg:CfgBackward) (I: Increment)
454454
and module GVar = Basetype.Variables
455455
and module D = S.D
456456
and module G = S.G
457-
val tf : MyCFG.node * S.C.t -> (Cil.location * MyCFG.edge) list * MyCFG.node -> ((MyCFG.node * S.C.t) -> S.D.t) -> (MyCFG.node * S.C.t -> S.D.t -> unit) -> (Cil.varinfo -> G.t) -> (Cil.varinfo -> G.t -> unit) -> D.t
457+
val tf : MyCFG.node * S.C.t -> (Cil.location * MyCFG.edge) list * MyCFG.node -> D.t -> ((MyCFG.node * S.C.t) -> S.D.t) -> (MyCFG.node * S.C.t -> S.D.t -> unit) -> (Cil.varinfo -> G.t) -> (Cil.varinfo -> G.t -> unit) -> D.t
458458
end
459459
=
460460
struct
@@ -679,53 +679,64 @@ struct
679679
let tf var getl sidel getg sideg prev_node (_,edge) d (f,t) =
680680
let old_loc = !Tracing.current_loc in
681681
let old_loc2 = !Tracing.next_loc in
682-
let _ = Tracing.current_loc := f in
683-
let _ = Tracing.next_loc := t in
684-
let d = tf var getl sidel getg sideg prev_node edge d in
685-
let _ = Tracing.current_loc := old_loc in
686-
let _ = Tracing.next_loc := old_loc2 in
687-
d
688-
689-
let tf (v,c) (edges, u) getl sidel getg sideg =
690-
let pval = getl (u,c) in
682+
Tracing.current_loc := f;
683+
Tracing.next_loc := t;
684+
Fun.protect ~finally:(fun () ->
685+
Tracing.current_loc := old_loc;
686+
Tracing.next_loc := old_loc2
687+
) (fun () ->
688+
let d = tf var getl sidel getg sideg prev_node edge d in
689+
d
690+
)
691+
692+
let tf (v,c) (edges, u) pval getl sidel getg sideg =
693+
(* let pval = getl (u,c) in *)
691694
let _, locs = List.fold_right (fun (f,e) (t,xs) -> f, (f,t)::xs) edges (Node.location v,[]) in
692695
List.fold_left2 (|>) pval (List.map (tf (v,Obj.repr (fun () -> c)) getl sidel getg sideg u) edges) locs
693696

694-
let tf (v,c) (e,u) getl sidel getg sideg =
697+
let tf (v,c) (e,u) pval getl sidel getg sideg =
695698
let old_node = !current_node in
696699
let old_context = !M.current_context in
697-
let _ = current_node := Some u in
700+
current_node := Some u;
698701
M.current_context := Some (Obj.repr c);
699-
let d = tf (v,c) (e,u) getl sidel getg sideg in
700-
let _ = current_node := old_node in
701-
M.current_context := old_context;
702-
d
702+
Fun.protect ~finally:(fun () ->
703+
current_node := old_node;
704+
M.current_context := old_context
705+
) (fun () ->
706+
let d = tf (v,c) (e,u) pval getl sidel getg sideg in
707+
d
708+
)
703709

704710
let system (v,c) =
705711
match v with
706712
| FunctionEntry _ ->
707713
None
708714
| _ ->
709715
let tf getl sidel getg sideg =
710-
let tf' eu = tf (v,c) eu getl sidel getg sideg in
716+
let get_pval (_, u) = getl (u, c) in
717+
let tf' eu pval = tf (v,c) eu pval getl sidel getg sideg in
711718

712719
match NodeH.find_option CfgTools.node_scc_global v with
713720
| Some scc when NodeH.mem scc.prev v && NodeH.length scc.prev = 1 ->
714721
(* Limited to loops with only one entry node. Otherwise unsound as is. *)
715722
(* TODO: Is it possible to do soundly for multi-entry loops? *)
716723
let stricts = NodeH.find_all scc.prev v in
717-
let xs_stricts = List.map tf' stricts in
724+
let pvals_stricts = List.map get_pval stricts in (* get pvals before executing any tf to maximize abort *)
725+
let xs_stricts = List.map2 tf' stricts pvals_stricts in
718726
if List.for_all S.D.is_bot xs_stricts then
719727
S.D.bot ()
720728
else
721729
let xs_strict = List.fold_left S.D.join (S.D.bot ()) xs_stricts in
722730
let equal = [%eq: (CilType.Location.t * Edge.t) list * Node.t] in
723731
let is_strict eu = List.exists (equal eu) stricts in
724732
let non_stricts = List.filter (neg is_strict) (Cfg.prev v) in
725-
let xs_non_stricts = List.map tf' non_stricts in
733+
let pvals_non_stricts = List.map get_pval non_stricts in (* get pvals before executing any tf to maximize abort *)
734+
let xs_non_stricts = List.map2 tf' non_stricts pvals_non_stricts in
726735
List.fold_left S.D.join xs_strict xs_non_stricts
727736
| _ ->
728-
let xs = List.map tf' (Cfg.prev v) in
737+
let prevs = Cfg.prev v in
738+
let pvals = List.map get_pval prevs in (* get pvals before executing any tf to maximize abort *)
739+
let xs = List.map2 tf' prevs pvals in
729740
List.fold_left S.D.join (S.D.bot ()) xs
730741
in
731742
Some tf

src/maingoblint.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ let merge_preprocessed cpp_file_names =
320320
let do_stats () =
321321
if get_bool "printstats" then (
322322
print_newline ();
323-
ignore (Pretty.printf "vars = %d evals = %d \n" !Goblintutil.vars !Goblintutil.evals);
323+
ignore (Pretty.printf "vars = %d evals = %d aborts = %d\n" !Goblintutil.vars !Goblintutil.evals !Goblintutil.aborts);
324324
print_newline ();
325325
Stats.print (Messages.get_out "timing" Legacy.stderr) "Timings:\n";
326326
flush_all ()

src/solvers/generic.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ struct
242242
Goblintutil.evals := !Goblintutil.evals + 1;
243243
if (get_bool "dbg.solver-progress") then (incr stack_d; print_int !stack_d; flush stdout)
244244

245+
let abort_rhs_event x =
246+
incr Goblintutil.aborts
247+
245248
let update_var_event x o n =
246249
if tracing then increase x;
247250
if full_trace || ((not (Dom.is_bot o)) && Option.is_some !max_var && Var.equal (Option.get !max_var) x) then begin

0 commit comments

Comments
 (0)