Skip to content

Commit fe986b4

Browse files
authored
feat: BitVec.add_shiftLeft_eq_or_shiftLeft (leanprover#7761)
This PR implements the core theorem for the Bitwuzla rewrites [NORM_BV_NOT_OR_SHL](https://github.com/bitwuzla/bitwuzla/blob/e09c50818b798f990bd84bf61174553fef46d561/src/rewrite/rewrites_bv.cpp#L1495-L1510) and [BV_ADD_SHL](https://github.com/bitwuzla/bitwuzla/blob/e09c50818b798f990bd84bf61174553fef46d561/src/rewrite/rewrites_bv.cpp#L395-L401), which convert the mixed-boolean-arithmetic expression into a purely arithmetic expression: ```lean theorem add_shiftLeft_eq_or_shiftLeft {x y : BitVec w} : x + (y <<< x) = x ||| (y <<< x) ```
1 parent 336b68e commit fe986b4

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

src/Init/Data/BitVec/Bitblast.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,4 +1757,17 @@ theorem append_add_append_eq_append {v w : Nat} {x : BitVec v} {y : BitVec w} :
17571757
(x ++ 0#w) + (0#v ++ y) = x ++ y := by
17581758
rw [add_eq_or_of_and_eq_zero] <;> ext i <;> simp
17591759

1760+
/-- Heuristically, `y <<< x` is much larger than `x`,
1761+
and hence low bits of `y <<< x`. Thus, `x + (y <<< x) = x ||| (y <<< x).` -/
1762+
theorem add_shifLeft_eq_or_shiftLeft {x y : BitVec w} :
1763+
x + (y <<< x) = x ||| (y <<< x) := by
1764+
rw [add_eq_or_of_and_eq_zero]
1765+
ext i hi
1766+
simp only [shiftLeft_eq', getElem_and, getElem_shiftLeft, getElem_zero, and_eq_false_imp,
1767+
not_eq_eq_eq_not, Bool.not_true, decide_eq_false_iff_not, Nat.not_lt]
1768+
intros hxi hxval
1769+
have : 2^i ≤ x.toNat := two_pow_le_toNat_of_getElem_eq_true hi hxi
1770+
have : i < 2^i := by exact Nat.lt_two_pow_self
1771+
omega
1772+
17601773
end BitVec

src/Init/Data/BitVec/Lemmas.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ protected theorem toNat_lt_twoPow_of_le (h : m ≤ n) {x : BitVec m} :
136136

137137
theorem testBit_toNat (x : BitVec w) : x.toNat.testBit i = x.getLsbD i := rfl
138138

139+
theorem two_pow_le_toNat_of_getElem_eq_true {i : Nat} {x : BitVec w}
140+
(hi : i < w) (hx : x[i] = true) : 2^i ≤ x.toNat := by
141+
apply Nat.testBit_implies_ge
142+
rw [← getElem_eq_testBit_toNat x i hi]
143+
exact hx
144+
139145
theorem getMsb'_eq_getLsb' (x : BitVec w) (i : Fin w) :
140146
x.getMsb' i = x.getLsb' ⟨w - 1 - i, by omega⟩ := by
141147
simp only [getMsb', getLsb']

0 commit comments

Comments
 (0)