@@ -210,89 +210,91 @@ let constBefore var loop f =
210210 in
211211 fst @@ lastAssignmentToVarBeforeLoop (Some Z. zero) f.sbody.bstmts (* the top level call should never return false*)
212212
213- let rec loopIterations start diff comp =
214- let flip = function
215- | Lt -> Gt
216- | Gt -> Lt
217- | Ge -> Le
218- | Le -> Ge
219- | s -> s
220- in let loopIterations' goal shouldBeExact =
221- let range = Z. sub goal start in
222- if Z. equal diff Z. zero || Z. equal range Z. zero || (Z. gt diff Z. zero && Z. lt range Z. zero) || (Z. lt diff Z. zero && Z. gt range Z. zero) then
223- None (* unfitting parameters*)
224- else (
225- let roundedDown = Z. div range diff in
226- let isExact = Z. equal (Z. mul roundedDown diff) range in
227- if isExact then
228- Some roundedDown
229- else if shouldBeExact then
230- None
231- else
232- Some (Z. succ roundedDown)
233- )
234- in
235- match comp with
236- | BinOp (op , (Const _ as c ), var , t ) -> loopIterations start diff (BinOp (flip op, var, c, t))
237- | BinOp (Lt, _ , (Const (CInt (cint ,_ ,_ ) )), _ ) -> if Z. lt diff Z. zero then None else loopIterations' cint false
238- | BinOp (Gt, _ , (Const (CInt (cint ,_ ,_ ) )), _ ) -> if Z. gt diff Z. zero then None else loopIterations' cint false
239- | BinOp (Le, _ , (Const (CInt (cint ,_ ,_ ) )), _ ) -> if Z. lt diff Z. zero then None else loopIterations' (Z. succ cint) false
240- | BinOp (Ge, _ , (Const (CInt (cint ,_ ,_ ) )), _ ) -> if Z. gt diff Z. zero then None else loopIterations' (Z. pred cint) false
241- | BinOp (Ne, _ , (Const (CInt (cint ,_ ,_ ) )), _ ) -> loopIterations' cint true
213+ (* find a single break in the else branch of a toplevel if*)
214+ let findBreakComparison loopStatement =
215+ try
216+ let compOption = ref None in
217+ let visitor = new findBreakVisitor (compOption) in
218+ ignore @@ visitCilBlock visitor (loopBody loopStatement);
219+ ! compOption
220+ with WrongOrMultiple ->
221+ None
222+
223+ let getLoopVar = function
224+ | BinOp (op , (Const (CInt (goal , _ , _ ) )), Lval ((Var varinfo ), NoOffset), (TInt _ )) when isCompare op && not varinfo.vglob ->
225+ (* TODO: define isCompare and flip in cilfacade and refactor to use instead of the many separately defined similar functions *)
226+ let flip = function | Lt -> Gt | Gt -> Lt | Ge -> Le | Le -> Ge | s -> s in
227+ Some (flip op, varinfo, goal)
228+ | BinOp (op , Lval ((Var varinfo ), NoOffset), (Const (CInt (goal , _ , _ ) )), (TInt _ )) when isCompare op && not varinfo.vglob ->
229+ Some (op, varinfo, goal)
230+ | _ -> None
231+
232+ let getsPointedAt var func =
233+ try
234+ let visitor = new isPointedAtVisitor (var) in
235+ ignore @@ visitCilFunction visitor func;
236+ false
237+ with Found ->
238+ true
239+
240+ let assignmentDifference loop var =
241+ try
242+ let diff = ref None in
243+ let visitor = new findAssignmentConstDiff (diff, var) in
244+ ignore @@ visitCilBlock visitor loop;
245+ ! diff
246+ with WrongOrMultiple ->
247+ None
248+
249+ let adjustGoal diff goal op =
250+ match op with
251+ | Lt -> if Z. lt diff Z. zero then None else Some goal
252+ | Gt -> if Z. gt diff Z. zero then None else Some goal
253+ | Le -> if Z. lt diff Z. zero then None else Some (Z. succ goal)
254+ | Ge -> if Z. gt diff Z. zero then None else Some (Z. pred goal)
255+ | Ne -> Some goal
242256 | _ -> failwith " unexpected comparison in loopIterations"
243257
244- let ( >> = ) = Option. bind
245- let fixedLoopSize loopStatement func =
246- let findBreakComparison = try (* find a single break in the else branch of a toplevel if*)
247- let compOption = ref None in
248- let visitor = new findBreakVisitor(compOption) in
249- ignore @@ visitCilBlock visitor (loopBody loopStatement);
250- ! compOption
251- with | WrongOrMultiple -> None
252- in let getLoopVar = function
253- | BinOp (op, (Const (CInt _ )), Lval ((Var info), NoOffset ), (TInt _))
254- | BinOp (op , Lval ((Var info ), NoOffset), (Const (CInt _ )), (TInt _ )) when isCompare op && not info.vglob->
255- Some info
256- | _ -> None
257- in let getsPointedAt var = try
258- let visitor = new isPointedAtVisitor(var) in
259- ignore @@ visitCilFunction visitor func;
260- false
261- with | Found -> true
262- in let assignmentDifference loop var = try
263- let diff = ref None in
264- let visitor = new findAssignmentConstDiff(diff, var) in
265- ignore @@ visitCilBlock visitor loop;
266- ! diff
267- with | WrongOrMultiple -> None
268- in
258+ let loopIterations start diff goal shouldBeExact =
259+ let range = Z. sub goal start in
260+ if Z. equal diff Z. zero || Z. equal range Z. zero || (Z. gt diff Z. zero && Z. lt range Z. zero) || (Z. lt diff Z. zero && Z. gt range Z. zero) then
261+ None (* unfitting parameters*)
262+ else (
263+ let roundedDown = Z. div range diff in
264+ let isExact = Z. equal (Z. mul roundedDown diff) range in
265+ if isExact then
266+ Some roundedDown
267+ else if shouldBeExact then
268+ None
269+ else
270+ Some (Z. succ roundedDown)
271+ )
269272
270- findBreakComparison >> = fun comparison ->
271- getLoopVar comparison >> = fun var ->
272- if getsPointedAt var then
273+ let fixedLoopSize loopStatement func =
274+ let open GobOption.Syntax in
275+ let * comparison = findBreakComparison loopStatement in
276+ let * op, var, goal = getLoopVar comparison in
277+ if getsPointedAt var func then
273278 None
274279 else
275- constBefore var loopStatement func >> = fun start ->
276- assignmentDifference (loopBody loopStatement) var >> = fun diff ->
277- Logs. debug " comparison: " ;
278- Pretty. fprint stderr (dn_exp () comparison) ~width: max_int;
279- Logs. debug " " ;
280- Logs. debug " variable: " ;
281- Logs. debug " %s" var.vname;
282- Logs. debug " start:" ;
283- Logs. debug " %s" @@ Z. to_string start;
284- Logs. debug " diff:" ;
285- Logs. debug " %s" @@ Z. to_string diff;
286- let iterations = loopIterations start diff comparison in
280+ let * start = constBefore var loopStatement func in
281+ let * diff = assignmentDifference (loopBody loopStatement) var in
282+ let * goal = adjustGoal diff goal op in
283+ let iterations = loopIterations start diff goal (op= Ne ) in
284+ Logs. debug " comparison: %a" CilType.Exp. pretty comparison;
285+ Logs. debug " variable: %s" var.vname;
286+ Logs. debug " start: %a" GobZ. pretty start;
287+ Logs. debug " diff: %a" GobZ. pretty diff;
287288 match iterations with
288289 | None -> Logs. debug " iterations failed" ; None
289290 | Some s ->
290291 try
291292 let s' = Z. to_int s in
292- Logs. debug " iterations:" ;
293- Logs. debug " %d" s';
293+ Logs. debug " iterations: %d" s';
294294 Some s'
295- with Z. Overflow -> Logs. debug " iterations too big for integer" ; None
295+ with Z. Overflow ->
296+ Logs. debug " iterations too big for integer" ;
297+ None
296298
297299
298300class arrayVisitor = object
0 commit comments