diff --git a/src/plugins/eva/Eva.mli b/src/plugins/eva/Eva.mli index a317fca1878143ba241ca512e61dfed56eb30e47..498e4fdd241f24faf716fc5bc69c668705dd3e6a 100644 --- a/src/plugins/eva/Eva.mli +++ b/src/plugins/eva/Eva.mli @@ -571,6 +571,8 @@ module Eva_annotations: sig type unroll_annotation = | UnrollAmount of Cil_types.term (** Unroll the n first iterations. *) | UnrollFull (** Unroll amount defined by -eva-default-loop-unroll. *) + | UnrollAuto of int (** Use the automatic loop unrolling with the given limit, + as if -eva-auto-loop-unroll N was locally set. *) type split_kind = Static | Dynamic diff --git a/src/plugins/eva/partitioning/partitioning_parameters.ml b/src/plugins/eva/partitioning/partitioning_parameters.ml index d331531446bf78c9b260930d0302f1c3d0459528..9221c06ac9091004ba796f83ac283f9ae83efe4e 100644 --- a/src/plugins/eva/partitioning/partitioning_parameters.ml +++ b/src/plugins/eva/partitioning/partitioning_parameters.ml @@ -74,14 +74,16 @@ struct "%s loop without unroll annotation" loop_kind let unroll stmt = - let default = - if auto_loop_unroll > min_loop_unroll - then Partition.AutoUnroll (stmt, min_loop_unroll, auto_loop_unroll) + let automatic_unrolling i = + if i > min_loop_unroll + then Partition.AutoUnroll (stmt, min_loop_unroll, i) else Partition.IntLimit min_loop_unroll in + let default = automatic_unrolling auto_loop_unroll in match get_unroll_annot stmt with | [] -> warn_no_loop_unroll stmt; default | [UnrollFull] -> Partition.IntLimit default_loop_unroll + | [UnrollAuto i] -> automatic_unrolling i | [UnrollAmount t] -> begin (* Inlines the value of const variables in [t]. *) let global_init vi = @@ -98,8 +100,8 @@ struct warn "invalid loop unrolling parameter; ignoring"; default end - | _ -> - warn "invalid unroll annotation; ignoring"; + | _ :: _ :: _ -> + warn "more than one loop unroll annotation; ignoring"; default let history_size = HistoryPartitioning.get () diff --git a/src/plugins/eva/utils/eva_annotations.ml b/src/plugins/eva/utils/eva_annotations.ml index d00ff4fd2825b1ac40b9811e2036ec2ff9b84a25..334d7565a90df0eae97eab6ca588105511a4900b 100644 --- a/src/plugins/eva/utils/eva_annotations.ml +++ b/src/plugins/eva/utils/eva_annotations.ml @@ -32,6 +32,7 @@ type slevel_annotation = type unroll_annotation = | UnrollAmount of Cil_types.term | UnrollFull + | UnrollAuto of int type split_kind = Static | Dynamic type split_term = @@ -180,20 +181,35 @@ module Unroll = Register (struct let open Logic_typing in UnrollAmount (typing_context.type_term typing_context typing_context.pre_state t) + | [{lexpr_node = PLvar "auto"}; + {lexpr_node = PLconstant (IntConstant i)}] -> + let i = match int_of_string i with + | i when i >= 0 -> i + | _i -> raise Parse_error + | exception Failure _ -> raise Parse_error + in + UnrollAuto i | _ -> raise Parse_error let export = function | UnrollFull -> Ext_terms [] | UnrollAmount t -> Ext_terms [t] + | UnrollAuto i -> + Ext_terms [Logic_const.tstring "auto"; Logic_const.tinteger i] let import = function | Ext_terms [] -> UnrollFull | Ext_terms [t] -> UnrollAmount t + | Ext_terms [ + {term_node = TConst (LStr "auto")}; + {term_node = TConst (Integer (i, _))}] -> + UnrollAuto (Integer.to_int_exn i) | _ -> assert false let print fmt = function | UnrollFull -> () | UnrollAmount t -> Printer.pp_term fmt t + | UnrollAuto i -> Format.fprintf fmt "auto, %d" i end) module SplitTermAnnotation = diff --git a/src/plugins/eva/utils/eva_annotations.mli b/src/plugins/eva/utils/eva_annotations.mli index a56ce470ae9125b8bf154b00c7db743e1dfe60c7..8cd2ed06adf22729295d0828b8c58e7f33392767 100644 --- a/src/plugins/eva/utils/eva_annotations.mli +++ b/src/plugins/eva/utils/eva_annotations.mli @@ -43,6 +43,8 @@ type slevel_annotation = type unroll_annotation = | UnrollAmount of Cil_types.term (** Unroll the n first iterations. *) | UnrollFull (** Unroll amount defined by -eva-default-loop-unroll. *) + | UnrollAuto of int (** Use the automatic loop unrolling with the given limit, + as if -eva-auto-loop-unroll N was locally set. *) type split_kind = Static | Dynamic diff --git a/tests/value/oracle/partitioning-annots.0.res.oracle b/tests/value/oracle/partitioning-annots.0.res.oracle index ea9768af17d7484dcc0269ee930d6996a11dbb2f..3294c2b093f9bf1a6c502c10bd189bd06929b7cd 100644 --- a/tests/value/oracle/partitioning-annots.0.res.oracle +++ b/tests/value/oracle/partitioning-annots.0.res.oracle @@ -6,13 +6,13 @@ nondet ∈ [--..--] k ∈ {0} [eva] computing for function test_slevel <- main. - Called from partitioning-annots.c:278. + Called from partitioning-annots.c:289. [eva] partitioning-annots.c:243: starting to merge loop iterations [eva] partitioning-annots.c:248: starting to merge loop iterations [eva] Recording results for test_slevel [eva] Done for function test_slevel [eva] computing for function test_unroll <- main. - Called from partitioning-annots.c:279. + Called from partitioning-annots.c:290. [eva:loop-unroll:partial] partitioning-annots.c:26: loop not completely unrolled [eva] partitioning-annots.c:26: starting to merge loop iterations [eva:loop-unroll:partial] partitioning-annots.c:34: loop not completely unrolled @@ -25,7 +25,7 @@ [eva] Recording results for test_unroll [eva] Done for function test_unroll [eva] computing for function test_split <- main. - Called from partitioning-annots.c:280. + Called from partitioning-annots.c:291. [eva] computing for function Frama_C_interval <- test_split <- main. Called from partitioning-annots.c:73. [eva] using specification for function Frama_C_interval @@ -65,7 +65,7 @@ [eva] Recording results for test_split [eva] Done for function test_split [eva] computing for function test_dynamic_split <- main. - Called from partitioning-annots.c:281. + Called from partitioning-annots.c:292. [eva] partitioning-annots.c:95: Warning: this partitioning parameter cannot be evaluated safely on all states [eva] computing for function Frama_C_interval <- test_dynamic_split <- main. @@ -90,12 +90,12 @@ [eva] Recording results for test_dynamic_split [eva] Done for function test_dynamic_split [eva] computing for function test_dynamic_split_predicate <- main. - Called from partitioning-annots.c:282. + Called from partitioning-annots.c:293. [eva] partitioning-annots.c:124: starting to merge loop iterations [eva] Recording results for test_dynamic_split_predicate [eva] Done for function test_dynamic_split_predicate [eva] computing for function test_splits_post_call <- main. - Called from partitioning-annots.c:283. + Called from partitioning-annots.c:294. [eva] computing for function Frama_C_interval <- test_splits_post_call <- main. Called from partitioning-annots.c:205. [eva] partitioning-annots.c:205: @@ -119,6 +119,12 @@ [eva] partitioning-annots.c:217: Frama_C_show_each_body: {-1}, [-1000..1000] [eva] Recording results for test_splits_post_call [eva] Done for function test_splits_post_call +[eva] computing for function test_auto_limit <- main. + Called from partitioning-annots.c:295. +[eva:loop-unroll:auto] partitioning-annots.c:280: Automatic loop unrolling. +[eva] partitioning-annots.c:284: starting to merge loop iterations +[eva] Recording results for test_auto_limit +[eva] Done for function test_auto_limit [eva] Recording results for main [eva] Done for function main [eva] ====== VALUES COMPUTED ====== @@ -128,6 +134,8 @@ state ∈ {-1; 0; 1} y ∈ [-1000..1000] or UNINITIALIZED __retres ∈ [-510..510] +[eva:final-states] Values at end of function test_auto_limit: + [eva:final-states] Values at end of function test_dynamic_split: Frama_C_entropy_source ∈ [--..--] a ∈ {0} @@ -185,6 +193,8 @@ k ∈ {0; 1} [from] Computing for function body [from] Done for function body +[from] Computing for function test_auto_limit +[from] Done for function test_auto_limit [from] Computing for function test_dynamic_split [from] Computing for function Frama_C_interval <-test_dynamic_split [from] Done for function Frama_C_interval @@ -214,6 +224,8 @@ [from] Function spec: x FROM i \result FROM i +[from] Function test_auto_limit: + NO EFFECTS [from] Function test_dynamic_split: Frama_C_entropy_source FROM Frama_C_entropy_source; nondet (and SELF) [from] Function test_dynamic_split_predicate: @@ -235,6 +247,10 @@ i2; absolute; tmp; state; y; __retres [inout] Inputs for function body: nondet +[inout] Out (internal) for function test_auto_limit: + i; i_0 +[inout] Inputs for function test_auto_limit: + \nothing [inout] Out (internal) for function test_dynamic_split: Frama_C_entropy_source; a; b [inout] Inputs for function test_dynamic_split: diff --git a/tests/value/oracle_apron/partitioning-annots.0.res.oracle b/tests/value/oracle_apron/partitioning-annots.0.res.oracle index 68d268103b83832bb45759df2b7108b8ad474e1e..4e3b70b39201f9d1fe5f8186bb1082350e7e6481 100644 --- a/tests/value/oracle_apron/partitioning-annots.0.res.oracle +++ b/tests/value/oracle_apron/partitioning-annots.0.res.oracle @@ -10,7 +10,7 @@ > Called from partitioning-annots.c:212. > [eva] Recording results for body > [eva] Done for function body -136,137c142,143 +144,145c150,151 < x ∈ [0..44] < y ∈ [0..44] --- diff --git a/tests/value/oracle_octagon/partitioning-annots.0.res.oracle b/tests/value/oracle_octagon/partitioning-annots.0.res.oracle index 141d3a1f322385d29fea8cd73951c79d349d8440..d2a1e9742d6130d3fdb3e0af17461453825fcd68 100644 --- a/tests/value/oracle_octagon/partitioning-annots.0.res.oracle +++ b/tests/value/oracle_octagon/partitioning-annots.0.res.oracle @@ -1,4 +1,4 @@ -136,137c136,137 +144,145c144,145 < x ∈ [0..44] < y ∈ [0..44] --- diff --git a/tests/value/partitioning-annots.c b/tests/value/partitioning-annots.c index 6323f1df659d5f8bdc4864ea3df9fd88baaf82b2..169ca8b57aeb4982051cb5a8d4c896487fce059e 100644 --- a/tests/value/partitioning-annots.c +++ b/tests/value/partitioning-annots.c @@ -273,6 +273,17 @@ void test_slevel() } } +void test_auto_limit() +{ + // This loop should be unrolled + //@ loop unroll auto, 30; + for (int i = 0; i < 20; i++) {} + + // This loop should not be unrolled + //@ loop unroll auto, 5; + for (int i = 0; i < 20; i++) {} +} + void main(void) { test_slevel(); @@ -281,4 +292,5 @@ void main(void) test_dynamic_split(); test_dynamic_split_predicate(); test_splits_post_call(); + test_auto_limit(); }