Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(BV, CP): Propagators for addition and multiplication #1083

Merged
merged 2 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion src/lib/reasoners/bitlist.ml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ let explanation { ex; _ } = ex

let exact width value ex =
{ width
; bits_set = value
; bits_set = Z.extract value 0 width
; bits_clr = Z.extract (Z.lognot value) 0 width
; ex }

Expand Down Expand Up @@ -264,3 +264,46 @@ let fold_domain f b acc =
(ofs + 1) { b with bits_set = Z.logor b.bits_set mask } acc
in
fold_domain_aux 0 b acc

(* simple propagator: only compute known low bits

Example: ???100 * ???000 = ?00000 (trailing zeroes accumulate)
???111 * ????11 = ????01 (min of low bits known) *)
let mul a b =
let sz = width a in
assert (width b = sz);

let ex = Ex.union (explanation a) (explanation b) in

(* (a * 2^n) * (b * 2^m) = (a * b) * 2^(n + m) *)
let zeroes_a = Z.trailing_zeros @@ Z.lognot a.bits_clr in
let zeroes_b = Z.trailing_zeros @@ Z.lognot b.bits_clr in
if zeroes_a + zeroes_b >= sz then
exact sz Z.zero ex
else
(* Factor out the low zeroes *)
let low_bits =
if zeroes_a + zeroes_b = 0 then empty
Halbaroth marked this conversation as resolved.
Show resolved Hide resolved
else exact (zeroes_a + zeroes_b) Z.zero ex
in
let a = extract a zeroes_a (zeroes_a + sz - width low_bits - 1) in
assert (width a + width low_bits = sz);
let b = extract b zeroes_b (zeroes_b + sz - width low_bits - 1) in
assert (width b + width low_bits = sz);
(* a = ah * 2^n + al (0 <= al < 2^n)
b = bh * 2^m + bl (0 <= bl < 2^m)

((ah * 2^n) + al) * ((bh * 2^m) + bl) =
al * bl (mod 2^(min n m)) *)
let low_a_known = Z.trailing_zeros @@ Z.lognot @@ bits_known a in
let low_b_known = Z.trailing_zeros @@ Z.lognot @@ bits_known b in
let low_known = min low_a_known low_b_known in
let mid_bits =
if low_known = 0 then empty
else exact
low_known
Z.(extract (value a) 0 low_known * extract (value b) 0 low_known)
ex
in
concat (unknown (sz - width mid_bits - width low_bits) Ex.empty) @@
concat mid_bits low_bits
3 changes: 3 additions & 0 deletions src/lib/reasoners/bitlist.mli
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ val logor : t -> t -> t
val logxor : t -> t -> t
(** Bitwise xor. *)

val mul : t -> t -> t
(** Integer multiplication. *)

val concat : t -> t -> t
(** Bit-vector concatenation. *)

Expand Down
10 changes: 8 additions & 2 deletions src/lib/reasoners/bitv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,10 @@ module Shostak(X : ALIEN) = struct
let is_mine_symb sy =
match sy with
| Sy.Bitv _
| Op (Concat | Extract _ | BV2Nat | BVnot | BVand | BVor | BVxor)
| Op (
Concat | Extract _ | BV2Nat
| BVnot | BVand | BVor | BVxor
| BVadd | BVsub | BVmul)
-> true
| _ -> false

Expand Down Expand Up @@ -403,7 +406,10 @@ module Shostak(X : ALIEN) = struct
let other ~neg t _sz ctx =
let r, ctx' =
match E.term_view t with
| { f = Op (BVand | BVor | BVxor); _ } ->
| { f = Op (
BVand | BVor | BVxor
| BVadd | BVsub | BVmul
); _ } ->
X.term_embed t, []
| _ -> X.make t
in
Expand Down
Loading
Loading