@@ -119,6 +119,20 @@ class findAssignmentConstDiff((diff: Z.t option ref), var) = object
119
119
| _ -> SkipChildren
120
120
end
121
121
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
+
122
136
let isCompare = function
123
137
| Lt | Gt | Le | Ge | Ne -> true (* an loop that test for equality can not be of the type we look for*)
124
138
| _ -> false
@@ -334,20 +348,18 @@ let max_default_unrolls_per_spec (spec: Svcomp.Specification.t) =
334
348
335
349
let loop_unrolling_factor loopStatement func totalLoops =
336
350
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
340
353
match fixedLoopSize loopStatement func with
341
354
| Some i when i < = 20 -> Logs. debug " fixed loop size %d" i; i
342
355
| _ ->
343
356
match Svcomp.Specification. of_option () with
344
357
| [] -> 4
345
358
| specs -> BatList. max @@ List. map max_default_unrolls_per_spec specs
346
359
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
351
363
352
364
(* actual loop unrolling*)
353
365
@@ -426,16 +438,19 @@ let copy_and_patch_labels break_target current_continue_target stmts =
426
438
let patchLabelsVisitor = new patchLabelsGotosVisitor(StatementHashTable. find_opt gotos) in
427
439
List. map (visitCilStmt patchLabelsVisitor) stmts'
428
440
429
- class loopUnrollingVisitor (func , totalLoops ) = object
441
+ class loopUnrollingVisitor (func , totalLoops ) = object
430
442
(* Labels are simply handled by giving them a fresh name. Jumps coming from outside will still always go to the original label! *)
431
443
inherit nopCilVisitor
432
444
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 (
439
454
Logs. info " unrolling loop at %a with factor %d" CilType.Location. pretty loc factor;
440
455
annotateArrays b;
441
456
(* 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
447
462
one_copy_stmts @ [current_continue_target]
448
463
)
449
464
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
453
468
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)
455
473
end
456
474
457
475
let unroll_loops fd totalLoops =
0 commit comments