feat: USize.reduceToNat (#6190)

This PR adds the builtin simproc `USize.reduceToNat` which reduces the
`USize.toNat` operation on literals less than `UInt32.size` (i.e.,
`4294967296`).
This commit is contained in:
Mac Malone 2024-11-29 03:24:40 -05:00 committed by GitHub
parent c9ee66fb1f
commit 27cc0c8039
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 3 deletions

View file

@ -84,8 +84,22 @@ declare_uint_simprocs UInt8
declare_uint_simprocs UInt16
declare_uint_simprocs UInt32
declare_uint_simprocs UInt64
/-
We disabled the simprocs for USize since the result of most operations depend on an opaque value: `System.Platform.numBits`.
We could reduce some cases using the fact that this opaque value is `32` or `64`, but it is unclear whether it would be useful in practice.
We do not use the normal simprocs for `USize` since the result of most operations depend on an opaque value: `System.Platform.numBits`.
However, we do reduce natural literals using the fact this opaque value is at least `32`.
-/
-- declare_uint_simprocs USize
namespace USize
def fromExpr (e : Expr) : SimpM (Option USize) := do
let some (n, _) ← getOfNatValue? e ``USize | return none
return USize.ofNat n
builtin_simproc [simp, seval] reduceToNat (USize.toNat _) := fun e => do
let_expr USize.toNat e ← e | return .continue
let some (n, _) ← getOfNatValue? e ``USize | return .continue
unless n < UInt32.size do return .continue
let e := toExpr n
let p ← mkDecideProof (← mkLT e (mkNatLit UInt32.size))
let p := mkApp2 (mkConst ``USize.toNat_ofNat_of_lt_32) e p
return .done { expr := e, proof? := p }

View file

@ -0,0 +1,7 @@
variable (x : USize)
/- USize.toNat -/
#check_simp USize.toNat 4294967296 !~>
#check_simp USize.toNat 4294967295 ~> 4294967295
#check_simp USize.toNat (x &&& 1) ~> x.toNat % 2