Skip to content

Commit bf76679

Browse files
authored
Merge pull request #1590 from goblint/loopUnroll-loop-cond-vars
Handle loop statement comparison between two variables in loop unrolling
2 parents 81b4507 + 13bcf34 commit bf76679

File tree

1 file changed

+20
-3
lines changed

1 file changed

+20
-3
lines changed

src/util/loopUnrolling.ml

+20-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,16 @@ let constBefore var loop f =
154154
let targetLocation = loopLocation loop
155155
in let rec lastAssignmentToVarBeforeLoop (current: (Z.t option)) (statements: stmt list) = match statements with
156156
| st::stmts -> (
157-
let current' = if st.labels <> [] then (Logs.debug "has Label"; (None)) else current in
157+
let current' =
158+
(* If there exists labels that are not the ones inserted by loop unrolling, forget the found assigned constant value *)
159+
if List.exists (function
160+
| Label (s,_,_) -> not (String.starts_with ~prefix:"loop_continue" s || String.starts_with ~prefix:"loop_end" s)
161+
| _ -> true) st.labels
162+
then
163+
(Logs.debug "has Label"; (None))
164+
else
165+
current
166+
in
158167
match st.skind with
159168
| Instr list -> (
160169
match lastAssignToVar var list with
@@ -220,13 +229,21 @@ let findBreakComparison loopStatement =
220229
with WrongOrMultiple ->
221230
None
222231

223-
let getLoopVar = function
232+
let getLoopVar loopStatement func = function
224233
| BinOp (op, (Const (CInt (goal, _, _) )), Lval ((Var varinfo), NoOffset), (TInt _)) when isCompare op && not varinfo.vglob ->
225234
(* TODO: define isCompare and flip in cilfacade and refactor to use instead of the many separately defined similar functions *)
226235
let flip = function | Lt -> Gt | Gt -> Lt | Ge -> Le | Le -> Ge | s -> s in
227236
Some (flip op, varinfo, goal)
228237
| BinOp (op, Lval ((Var varinfo), NoOffset), (Const (CInt (goal, _, _) )), (TInt _)) when isCompare op && not varinfo.vglob ->
229238
Some (op, varinfo, goal)
239+
(* When loop condition has a comparison between variables, we assume that the left one is the counter and right one is the bound.
240+
TODO: can we do something more meaningful instead of this assumption? *)
241+
| BinOp (op, Lval ((Var varinfo), NoOffset), Lval ((Var varinfo2), NoOffset), (TInt _))
242+
| BinOp (op, CastE ((TInt _), (Lval ((Var varinfo), NoOffset))), Lval ((Var varinfo2), NoOffset), (TInt _)) when isCompare op && not varinfo.vglob && not varinfo2.vglob ->
243+
begin match constBefore varinfo2 loopStatement func with
244+
| Some goal -> Logs.debug "const: %a %a" CilType.Varinfo.pretty varinfo2 GobZ.pretty goal; Some (op, varinfo, goal)
245+
| None -> None
246+
end;
230247
| _ -> None
231248

232249
let getsPointedAt var func =
@@ -273,7 +290,7 @@ let loopIterations start diff goal shouldBeExact =
273290
let fixedLoopSize loopStatement func =
274291
let open GobOption.Syntax in
275292
let* comparison = findBreakComparison loopStatement in
276-
let* op, var, goal = getLoopVar comparison in
293+
let* op, var, goal = getLoopVar loopStatement func comparison in
277294
if getsPointedAt var func then
278295
None
279296
else

0 commit comments

Comments
 (0)