Skip to content

Commit

Permalink
feat: simprocs for applying shiftLeft_shiftLeft and `shiftRight_shi…
Browse files Browse the repository at this point in the history
…ftRight` (#4194)
  • Loading branch information
leodemoura authored May 16, 2024
1 parent e8c4540 commit 1382e9f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Init/Data/BitVec/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ theorem msb_append {x : BitVec w} {y : BitVec v} :
simp only [getLsb_append, cond_eq_if]
split <;> simp [*]

theorem shiftRight_shiftRight (w : Nat) (x : BitVec w) (n m : Nat) :
theorem shiftRight_shiftRight {w : Nat} (x : BitVec w) (n m : Nat) :
(x >>> n) >>> m = x >>> (n + m) := by
ext i
simp [Nat.add_assoc n m i]
Expand Down
22 changes: 22 additions & 0 deletions src/Lean/Meta/Tactic/Simp/BuiltinSimprocs/BitVec.lean
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Lean.Meta.LitValues
import Lean.Meta.Tactic.Simp.BuiltinSimprocs.Nat
import Lean.Meta.Tactic.Simp.BuiltinSimprocs.Int
import Init.Data.BitVec.Basic
import Init.Data.BitVec.Lemmas

namespace BitVec
open Lean Meta Simp
Expand Down Expand Up @@ -303,4 +304,25 @@ builtin_dsimproc [simp, seval] reduceBitVecToFin (BitVec.toFin _) := fun e => d
let some ⟨_, v⟩ ← getBitVecValue? v | return .continue
return .done <| toExpr v.toFin

/--
Helper function for reducing `(x <<< i) <<< j` (and `(x >>> i) >>> j`) where `i` and `j` are
natural number literals.
-/
@[inline] def reduceShiftShift (declName : Name) (thmName : Name) (e : Expr) : SimpM Step := do
unless e.isAppOfArity declName 6 do return .continue
let aux := e.appFn!.appArg!
let some i ← Nat.fromExpr? e.appArg! | return .continue
unless aux.isAppOfArity declName 6 do return .continue
let x := aux.appFn!.appArg!
let some j ← Nat.fromExpr? aux.appArg! | return .continue
let i_add_j := toExpr (i + j)
let expr ← mkAppM declName #[x, i_add_j]
let proof ← mkAppM thmName #[x, aux.appArg!, e.appArg!]
return .visit { expr, proof? := some proof }

builtin_simproc reduceShiftLeftShiftLeft (((_ <<< _ : BitVec _) <<< _ : BitVec _)) :=
reduceShiftShift ``HShiftLeft.hShiftLeft ``shiftLeft_shiftLeft
builtin_simproc reduceShiftRightShiftRight (((_ >>> _ : BitVec _) >>> _ : BitVec _)) :=
reduceShiftShift ``HShiftRight.hShiftRight ``shiftRight_shiftRight

end BitVec
16 changes: 16 additions & 0 deletions tests/lean/run/bitvec_simproc.lean
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,19 @@ example (a : BitVec 32) (h : a >>> 2 = b) : a >>> 2#32 = b := by
simp; guard_target =ₛ a >>> 2 = b; assumption
example (a : BitVec 32) (h : a <<< 2 = b) : a <<< 2#32 = b := by
simp; guard_target =ₛ a <<< 2 = b; assumption
example (a : BitVec 32) (h : a <<< 3 = b) : (a <<< 1#32) <<< 2#32 = b := by
simp; guard_target =ₛ a <<< 3 = b; assumption
example (a : BitVec 32) (h : a <<< 3 = b) : (a <<< 1) <<< 2#32 = b := by
simp; guard_target =ₛ a <<< 3 = b; assumption
example (a : BitVec 32) (h : a <<< 3 = b) : (a <<< 1) <<< 2 = b := by
simp; guard_target =ₛ a <<< 3 = b; assumption
example (a : BitVec 32) (h : a <<< 3 = b) : (a <<< 1#32) <<< 2 = b := by
simp; guard_target =ₛ a <<< 3 = b; assumption
example (a : BitVec 32) (h : a >>> 3 = b) : (a >>> 1#32) >>> 2#32 = b := by
simp; guard_target =ₛ a >>> 3 = b; assumption
example (a : BitVec 32) (h : a >>> 3 = b) : (a >>> 1) >>> 2#32 = b := by
simp; guard_target =ₛ a >>> 3 = b; assumption
example (a : BitVec 32) (h : a >>> 3 = b) : (a >>> 1) >>> 2 = b := by
simp; guard_target =ₛ a >>> 3 = b; assumption
example (a : BitVec 32) (h : a >>> 3 = b) : (a >>> 1#32) >>> 2 = b := by
simp; guard_target =ₛ a >>> 3 = b; assumption

0 comments on commit 1382e9f

Please sign in to comment.