Skip to content

Commit 0e3066c

Browse files
authored
Merge pull request #1403 from goblint/yaml-witness-unrolled-loop
Record statement copies during loop unrolling
2 parents 9649faf + 41f4a6d commit 0e3066c

10 files changed

Lines changed: 323 additions & 5 deletions

File tree

src/common/framework/cfgTools.ml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,16 @@ struct
559559
| FunctionEntry _ -> ["shape=box"]
560560
in
561561
let styles = String.concat "," (label @ shape @ extraNodeStyles n) in
562-
Format.fprintf out ("\t%a [%s];\n") p_node n styles
562+
Format.fprintf out ("\t%a [%s];\n") p_node n styles;
563+
match n with
564+
| Statement s when get_bool "dbg.cfg.loop-unrolling" ->
565+
begin match LoopUnrolling0.find_copyof s with
566+
| Some s' ->
567+
let n' = Statement s' in
568+
Format.fprintf out "\t%a -> %a [style=dotted];\n" p_node n p_node n'
569+
| None -> ()
570+
end
571+
| _ -> ()
563572
end
564573

565574
let fprint_dot (module CfgPrinters: CfgPrinters) iter_edges out =

src/common/util/loopUnrolling0.ml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
open GoblintCil
2+
3+
module CopyOfHashTable = Hashtbl.Make(struct
4+
type t = stmt
5+
(* Identity by physical equality. *)
6+
let equal = (==)
7+
(* Hash only labels and skind (statement itself) because they should remain unchanged between now
8+
and lookup after analysis.
9+
CFG construction modifies sid, succs, preds and fallthrough, which are empty here.*)
10+
let hash (s: stmt) = Hashtbl.hash (s.skind, s.labels)
11+
end)
12+
let copyof = CopyOfHashTable.create 113
13+
14+
let find_copyof = CopyOfHashTable.find_opt copyof
15+
16+
let rec find_original s =
17+
match find_copyof s with
18+
| None -> s
19+
| Some s' -> (find_original [@tailcall]) s'

src/config/options.schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,12 @@
19911991
"description": "Add loop SCC clusters to CFG .dot output.",
19921992
"type": "boolean",
19931993
"default": false
1994+
},
1995+
"loop-unrolling": {
1996+
"title": "dbg.cfg.loop-unrolling",
1997+
"description": "Add dotted loop unrolling copy-of edges to CFG .dot output.",
1998+
"type": "boolean",
1999+
"default": false
19942000
}
19952001
},
19962002
"additionalProperties": false

src/util/loopUnrolling.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
(** Syntactic loop unrolling. *)
2-
31
open GobConfig
42
open GoblintCil
53

4+
module M = Messages
5+
66
(*loop unroll heuristics*)
77
(*used if AutoTune is activated*)
88

@@ -384,6 +384,8 @@ class patchLabelsGotosVisitor(newtarget) = object
384384
| _ -> DoChildren
385385
end
386386

387+
include LoopUnrolling0
388+
387389
(*
388390
Makes a copy, replacing top-level breaks with goto loopEnd and top-level continues with
389391
goto currentIterationEnd
@@ -401,6 +403,8 @@ class copyandPatchLabelsVisitor(loopEnd, currentIterationEnd, gotos) = object
401403
let new_labels = List.map (function Label(str,loc,b) -> Label (Cil.freshLabel str,loc,b) | x -> x) sn.labels in
402404
(* this makes new physical copy*)
403405
let new_s = {sn with labels = new_labels} in
406+
CopyOfHashTable.replace copyof new_s s;
407+
if M.tracing then M.trace "cfg" "Marking %a as copy of %a" CilType.Stmt.pretty new_s CilType.Stmt.pretty s;
404408
if new_s.labels <> [] then
405409
(* Use original s, ns might be temporay e.g. if the type of statement changed *)
406410
(* record that goto s; appearing in the current fragment should later be patched to goto new_s *)

src/util/loopUnrolling.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(** Syntactic loop unrolling. *)
2+
3+
val unroll_loops: GoblintCil.fundec -> int -> unit
4+
(** Unroll loops in a function.
5+
6+
@param totalLoops total number of loops from autotuner *)
7+
8+
val find_original: GoblintCil.stmt -> GoblintCil.stmt
9+
(** Find original un-unrolled instance of the statement. *)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
int main() {
2+
int i = 0;
3+
while (i < 10)
4+
i++;
5+
6+
int j = 0, k = 0;
7+
while (j < 10) {
8+
while (k < 100)
9+
k++;
10+
j++;
11+
}
12+
return 0;
13+
}

tests/regression/55-loop-unrolling/11-unrolled-loop-invariant.t

Lines changed: 230 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
(cram
22
(deps (glob_files *.c)))
3+
4+
(cram
5+
(applies_to 11-unrolled-loop-invariant)
6+
(enabled_if %{bin-available:graph-easy})
7+
(deps
8+
%{bin:cfgDot}))

tests/regression/cfg/util/cfgDot.ml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
1+
open Goblint_lib
2+
3+
let usage_msg = "cfgDot [--unroll <n>] <file>"
4+
5+
let files = ref []
6+
let unroll = ref 0
7+
8+
let anon_fun filename =
9+
files := filename :: !files
10+
11+
let speclist = [
12+
("--unroll", Arg.Set_int unroll, "Unroll loops");
13+
]
14+
115
let main () =
216
Goblint_logs.Logs.Level.current := Info;
317
Cilfacade.init ();
18+
GobConfig.set_bool "dbg.cfg.loop-unrolling" true;
19+
GobConfig.set_int "exp.unrolling-factor" !unroll;
420

5-
let ast = Cilfacade.getAST (Fpath.v Sys.argv.(1)) in
21+
assert (List.length !files = 1);
22+
let ast = Cilfacade.getAST (Fpath.v (List.hd !files)) in
623
CilCfg0.end_basic_blocks ast;
724
(* Part of CilCfg.createCFG *)
825
GoblintCil.iterGlobals ast (function
926
| GFun (fd, _) ->
27+
if !unroll > 0 then
28+
LoopUnrolling.unroll_loops fd (-1);
1029
GoblintCil.prepareCFG fd;
1130
GoblintCil.computeCFGInfo fd true
1231
| _ -> ()
@@ -52,4 +71,6 @@ let main () =
5271
| _ -> ()
5372
)
5473

55-
let () = main ()
74+
let () =
75+
Arg.parse speclist anon_fun usage_msg;
76+
main ()

tests/regression/cfg/util/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
goblint-cil
55
goblint_logs
66
goblint_common
7+
goblint_lib ; TODO: avoid: extract LoopUnrolling from goblint_lib
78
fpath
89
goblint.sites.dune
910
goblint.build-info.dune)

0 commit comments

Comments
 (0)