Skip to content

Commit 657bc6b

Browse files
authored
Merge pull request #1826 from goblint/var_eq-invariant
Reduce var_eq witness invariants from quadratic to linear
2 parents 4952e78 + c0a4ba0 commit 657bc6b

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

src/analyses/varEq.ml

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,23 @@ struct
2121
fold (fun s a ->
2222
if B.mem MyCFG.unknown_exp s then
2323
a
24-
else
25-
let module B_prod = BatSet.Make2 (Exp) (Exp) in
26-
let s_prod = B_prod.cartesian_product s s in
27-
let i = B_prod.Product.fold (fun (x, y) a ->
28-
if Exp.compare x y < 0 && not (InvariantCil.exp_contains_tmp x) && not (InvariantCil.exp_contains_tmp y) && InvariantCil.exp_is_in_scope scope x && InvariantCil.exp_is_in_scope scope y then (* each equality only one way, no self-equalities *)
29-
let eq = BinOp (Eq, x, y, intType) in
24+
else (
25+
let s' = B.filter (fun x -> not (InvariantCil.exp_contains_tmp x) && InvariantCil.exp_is_in_scope scope x) s in
26+
if B.cardinal s' >= 2 then (
27+
(* instead of returning quadratically many pairwise equalities from a cluster,
28+
output linear number of equalities with just one expression *)
29+
let lhs = B.choose s' in (* choose arbitrary expression for lhs *)
30+
let rhss = B.remove lhs s' in (* and exclude it from rhs-s (no point in reflexive equality) *)
31+
let i = B.fold (fun rhs a ->
32+
let eq = BinOp (Eq, lhs, rhs, intType) in
3033
Invariant.(a && of_exp eq)
31-
else
32-
a
33-
) s_prod (Invariant.top ())
34-
in
35-
Invariant.(a && i)
34+
) rhss (Invariant.top ())
35+
in
36+
Invariant.(a && i)
37+
)
38+
else (* cannot output any equalities between just 0 or 1 usable expressions *)
39+
a
40+
)
3641
) ss (Invariant.top ())
3742
end
3843

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// CRAM
2+
3+
int main() {
4+
int a, b, c, d;
5+
a = b = c = d;
6+
return 0;
7+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
$ goblint --set ana.activated[+] var_eq --enable witness.yaml.enabled 71-var_eq-invariants.c
2+
[Info][Deadcode] Logical lines of code (LLoC) summary:
3+
live: 3
4+
dead: 0
5+
total lines: 3
6+
[Info][Witness] witness generation summary:
7+
location invariants: 3
8+
loop invariants: 0
9+
flow-insensitive invariants: 0
10+
total generation entries: 1
11+
12+
With 4 equal variables, there should be just 3 var_eq invariants, not 6.
13+
14+
$ yamlWitnessStrip < witness.yml
15+
- entry_type: invariant_set
16+
content:
17+
- invariant:
18+
type: location_invariant
19+
location:
20+
file_name: 71-var_eq-invariants.c
21+
line: 6
22+
column: 3
23+
function: main
24+
value: a == b
25+
format: c_expression
26+
- invariant:
27+
type: location_invariant
28+
location:
29+
file_name: 71-var_eq-invariants.c
30+
line: 6
31+
column: 3
32+
function: main
33+
value: a == c
34+
format: c_expression
35+
- invariant:
36+
type: location_invariant
37+
location:
38+
file_name: 71-var_eq-invariants.c
39+
line: 6
40+
column: 3
41+
function: main
42+
value: a == d
43+
format: c_expression

0 commit comments

Comments
 (0)