Skip to content

Commit cda9ec4

Browse files
authored
Merge pull request #1595 from goblint/no-unrolling-resource
Restrict unrolling to loops that are nested within less than 4 loops
2 parents bf76679 + eb1fded commit cda9ec4

File tree

2 files changed

+36
-34
lines changed

2 files changed

+36
-34
lines changed

src/util/loopUnrolling.ml

+36-18
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,20 @@ class findAssignmentConstDiff((diff: Z.t option ref), var) = object
119119
| _ -> SkipChildren
120120
end
121121

122+
class findStmtContainsInstructions = object
123+
inherit nopCilVisitor
124+
method! vinst = function
125+
| Set _
126+
| Call _ -> raise Found
127+
| _ -> DoChildren
128+
end
129+
130+
let containsInstructions stmt =
131+
try
132+
ignore @@ visitCilStmt (new findStmtContainsInstructions) stmt; false
133+
with Found ->
134+
true
135+
122136
let isCompare = function
123137
| Lt | Gt | Le | Ge | Ne -> true (*an loop that test for equality can not be of the type we look for*)
124138
| _ -> false
@@ -334,20 +348,18 @@ let max_default_unrolls_per_spec (spec: Svcomp.Specification.t) =
334348

335349
let loop_unrolling_factor loopStatement func totalLoops =
336350
let configFactor = get_int "exp.unrolling-factor" in
337-
if AutoTune0.isActivated "loopUnrollHeuristic" then
338-
let loopStats = AutoTune0.collectFactors visitCilStmt loopStatement in
339-
if loopStats.instructions > 0 then
351+
if containsInstructions loopStatement then
352+
if AutoTune0.isActivated "loopUnrollHeuristic" then
340353
match fixedLoopSize loopStatement func with
341354
| Some i when i <= 20 -> Logs.debug "fixed loop size %d" i; i
342355
| _ ->
343356
match Svcomp.Specification.of_option () with
344357
| [] -> 4
345358
| specs -> BatList.max @@ List.map max_default_unrolls_per_spec specs
346359
else
347-
(* Don't unroll empty (= while(1){}) loops*)
348-
0
349-
else
350-
configFactor
360+
configFactor
361+
else (* Don't unroll empty (= while(1){}) loops*)
362+
0
351363

352364
(*actual loop unrolling*)
353365

@@ -426,16 +438,19 @@ let copy_and_patch_labels break_target current_continue_target stmts =
426438
let patchLabelsVisitor = new patchLabelsGotosVisitor(StatementHashTable.find_opt gotos) in
427439
List.map (visitCilStmt patchLabelsVisitor) stmts'
428440

429-
class loopUnrollingVisitor(func, totalLoops) = object
441+
class loopUnrollingVisitor (func, totalLoops) = object
430442
(* Labels are simply handled by giving them a fresh name. Jumps coming from outside will still always go to the original label! *)
431443
inherit nopCilVisitor
432444

433-
method! vstmt s =
434-
let duplicate_and_rem_labels s =
435-
match s.skind with
436-
| Loop (b,loc, loc2, break , continue) ->
437-
let factor = loop_unrolling_factor s func totalLoops in
438-
if(factor > 0) then (
445+
val mutable nests = 0
446+
447+
method! vstmt stmt =
448+
let duplicate_and_rem_labels stmt =
449+
match stmt.skind with
450+
| Loop (b, loc, loc2, break, continue) ->
451+
nests <- nests - 1; Logs.debug "nests: %i" nests;
452+
let factor = loop_unrolling_factor stmt func totalLoops in
453+
if factor > 0 then (
439454
Logs.info "unrolling loop at %a with factor %d" CilType.Location.pretty loc factor;
440455
annotateArrays b;
441456
(* top-level breaks should immediately go to the end of the loop, and not just break out of the current iteration *)
@@ -447,11 +462,14 @@ class loopUnrollingVisitor(func, totalLoops) = object
447462
one_copy_stmts @ [current_continue_target]
448463
)
449464
in
450-
mkStmt (Block (mkBlock (List.flatten copies @ [s; break_target])))
451-
) else s (*no change*)
452-
| _ -> s
465+
mkStmt (Block (mkBlock (List.flatten copies @ [stmt; break_target])))
466+
) else stmt (*no change*)
467+
| _ -> stmt
453468
in
454-
ChangeDoChildrenPost(s, duplicate_and_rem_labels)
469+
match stmt.skind with
470+
| Loop _ when nests + 1 < 4 -> nests <- nests + 1; ChangeDoChildrenPost(stmt, duplicate_and_rem_labels)
471+
| Loop _ -> SkipChildren
472+
| _ -> ChangeDoChildrenPost(stmt, duplicate_and_rem_labels)
455473
end
456474

457475
let unroll_loops fd totalLoops =
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
$ goblint --set lib.activated '[]' --set exp.unrolling-factor 1 --enable justcil --set dbg.justcil-printer clean 08-bad.c
2-
[Info] unrolling loop at 08-bad.c:9:7-9:23 with factor 1
3-
[Info] unrolling loop at 08-bad.c:15:8-15:24 with factor 1
42
int main(void)
53
{
64
int m ;
75
86
{
97
{
108
goto switch_default;
11-
{
12-
if (! 0) {
13-
goto loop_end;
14-
}
15-
loop_continue_0: /* CIL Label */ ;
169
switch_default: /* CIL Label */
1710
{
1811
while (1) {
@@ -23,16 +16,9 @@
2316
}
2417
while_break: /* CIL Label */ ;
2518
}
26-
loop_end: /* CIL Label */ ;
27-
}
2819
switch_break: /* CIL Label */ ;
2920
}
3021
goto lab;
31-
{
32-
if (! 0) {
33-
goto loop_end___0;
34-
}
35-
loop_continue_0___0: /* CIL Label */ ;
3622
lab:
3723
{
3824
while (1) {
@@ -43,8 +29,6 @@
4329
}
4430
while_break___0: /* CIL Label */ ;
4531
}
46-
loop_end___0: /* CIL Label */ ;
47-
}
4832
return (0);
4933
}
5034
}

0 commit comments

Comments
 (0)