Skip to content

Commit

Permalink
Merge branch 'main' into benchmarks-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkeizer committed Sep 26, 2024
2 parents 93a3f81 + 0194790 commit 1f948b8
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 31 deletions.
11 changes: 7 additions & 4 deletions Arm/Memory/SeparateAutomation.lean
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,12 @@ The tactic shall be implemented as follows:

section BvOmega

-- |TODO: Upstream BitVec.le_def unfolding to bv_omega.
macro "bv_omega'" : tactic =>
`(tactic| (try simp only [bv_toNat, mem_legal'] at * <;> try rw [BitVec.le_def]) <;> bv_omega)
/- We tag `mem_legal'` as `bv_toNat` here, since we want to actually lazily unfold this.
Doing it here lets us remove it from `bv_toNat` simp-set as a change to `SeparateAutomation.lean`,
without needing us to modify the core definitions file which incurs a recompile cost,
making experimentation annoying.
-/
attribute [bv_toNat] mem_legal'

end BvOmega

Expand Down Expand Up @@ -427,7 +430,7 @@ def omega : SimpMemM Unit := do
-- https://leanprover.zulipchat.com/#narrow/stream/326056-ICERM22-after-party/topic/Regression.20tests/near/290131280
-- @bollu: TODO: understand what precisely we are recovering from.
withoutRecover do
evalTactic (← `(tactic| bv_omega'))
evalTactic (← `(tactic| bv_omega))

section Hypotheses

Expand Down
6 changes: 5 additions & 1 deletion Benchmarks/Command.lean
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,20 @@ elab "benchmark" id:ident declSig:optDeclSig val:declVal : command => do

let n := 5
let mut totalRunTime := 0
-- geomean = exp(log((a₁ a₂ ... aₙ)^1/n)) =
-- exp(1/n * (log a₁ + log a₂ + log aₙ)).
let mut totalRunTimeLog := 0
for i in [0:n] do
logInfo m!"\n\nRun {i} (out of {n}):\n"
let ((), _, runTime) ← withHeartbeatsAndMs <|
elabCommand stx

logInfo m!"Proof took {runTime / 1000}s in total"
totalRunTime := totalRunTime + runTime
totalRunTimeLog := totalRunTimeLog + Float.log runTime.toFloat

let avg := totalRunTime.toFloat / n.toFloat / 1000
let geomean := (totalRunTime.toFloat.pow (1.0 / n.toFloat)) / 1000.0
let geomean := (Float.exp (totalRunTimeLog / n.toFloat)) / 1000.0
logInfo m!"\
{id}:
average runtime over {n} runs:
Expand Down
12 changes: 6 additions & 6 deletions Proofs/Experiments/MemoryAliasing.lean
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ theorem mem_automation_test_4
simp only [memory_rules]
simp_mem
congr 1
bv_omega' -- TODO: address normalization.
bv_omega -- TODO: address normalization.

/-- info: 'mem_automation_test_4' depends on axioms: [propext, Classical.choice, Quot.sound] -/
#guard_msgs in #print axioms mem_automation_test_4
Expand Down Expand Up @@ -229,7 +229,7 @@ theorem overlapping_read_test_2 {out : BitVec (16 * 8)}
simp_mem
· congr
-- ⊢ (src_addr + 6).toNat - src_addr.toNat = 6
bv_omega'
bv_omega
/--
info: 'ReadOverlappingRead.overlapping_read_test_2' depends on axioms: [propext, Classical.choice, Quot.sound]
-/
Expand All @@ -248,13 +248,13 @@ theorem overlapping_read_test_3
simp_mem
· congr
-- ⊢ (src_addr + 6).toNat - src_addr.toNat = 6
bv_omega'
bv_omega
/--
info: 'ReadOverlappingRead.overlapping_read_test_3' depends on axioms: [propext, Classical.choice, Quot.sound]
-/
#guard_msgs in #print axioms overlapping_read_test_3

/- TODO(@bollu): This test case hangs at `bv_omega'`. This is to be debugged.
/- TODO(@bollu): This test case hangs at `bv_omega`. This is to be debugged.
/-- A read in the goal state overlaps with a read in the
right hand side of the hypotheis `h`.
-/
Expand All @@ -268,7 +268,7 @@ theorem overlapping_read_test_4
simp_mem
· congr
-- ⊢ (src_addr + 6).toNat - src_addr.toNat = 6
bv_omega' -- TODO: Lean gets stuck here?
bv_omega -- TODO: Lean gets stuck here?
#guard_msgs in #print axioms overlapping_read_test_4
-/
Expand All @@ -290,7 +290,7 @@ theorem test_2 {val : BitVec _}
Memory.read_bytes 6 (src_addr + 10) (Memory.write_bytes 16 src_addr val mem) =
val.extractLsBytes 10 6 := by
simp_mem
have : ((src_addr + 10).toNat - src_addr.toNat) = 10 := by bv_omega'
have : ((src_addr + 10).toNat - src_addr.toNat) = 10 := by bv_omega
rw [this]

/--
Expand Down
2 changes: 1 addition & 1 deletion Proofs/Experiments/SHA512MemoryAliasing.lean
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ theorem sha512_block_armv8_prelude_sym_ctx_access (s0 : ArmState)
-- @shilpi: should this also be proven automatically? feels a little unreasonable to me.
· congr
-- ⊢ (ctx_addr s0 + 48#64).toNat - (ctx_addr s0).toNat = 48
bv_omega'
bv_omega

/--
info: 'SHA512MemoryAliasing.sha512_block_armv8_prelude_sym_ctx_access' depends on axioms: [propext,
Expand Down
40 changes: 21 additions & 19 deletions Tactics/Reflect/AxEffects.lean
Original file line number Diff line number Diff line change
Expand Up @@ -420,19 +420,12 @@ return an `AxEffects` where `s` is the intial state, and `e` is `currentState`.
Note that as soon as an unsupported expression (e.g., an `if`) is encountered,
the whole expression is taken to be the initial state,
even if there might be more `w`/`write_mem`s in sub-expressions. -/
partial def fromExpr (e : Expr) : MetaM AxEffects := do
let msg := m!"Building effects with writes from: {e}"
withTraceNode `Tactic.sym (fun _ => pure msg) <| do match_expr e with
| write_mem_bytes n addr val e =>
let eff ← fromExpr e
eff.update_write_mem n addr val
def fromExpr (e : Expr) : MetaM AxEffects := do
let s0 ← mkFreshExprMVar mkArmState
let eff := initial s0
let eff ← eff.updateWithExpr e
return { eff with initialState := ← instantiateMVars eff.initialState}

| w field value e =>
let eff ← fromExpr e
eff.update_w field value

| _ =>
return initial e

/-- Given a proof `eq : s = <currentState>`,
set `s` to be the new `currentState`, and update all proofs accordingly -/
Expand Down Expand Up @@ -464,25 +457,34 @@ def adjustCurrentStateWithEq (eff : AxEffects) (s eq : Expr) :
currentState, fields, nonEffectProof, memoryEffectProof, programProof
}

/-- Given a proof `eq : ?s = <sequence of w/write_mem to ?s0>`,
/-- Given a proof `eq : ?s = <sequence of w/write_mem to eff.currentState>`,
where `?s` and `?s0` are arbitrary `ArmState`s,
return an `AxEffect` with `?s0` as the initial state,
the rhs of the equality as the current state, and
`eq` stored as `currentStateEq`,
so that `?s` is the public-facing current state -/
def fromEq (eq : Expr) : MetaM AxEffects :=
return an `AxEffect` with the rhs of the equality as the current state,
and the (non-)effects updated accordingly -/
def updateWithEq (eff : AxEffects) (eq : Expr) : MetaM AxEffects :=
let msg := m!"Building effects with equality: {eq}"
withTraceNode `Tactic.sym (fun _ => pure msg) <| do
let s ← mkFreshExprMVar mkArmState
let rhs ← mkFreshExprMVar mkArmState
assertHasType eq <| mkEqArmState s rhs

let eff ← fromExpr (← instantiateMVars rhs)
let eff ← eff.updateWithExpr (← instantiateMVars rhs)
let eff ← eff.adjustCurrentStateWithEq s eq
withTraceNode `Tactic.sym (fun _ => pure "new state") do
trace[Tactic.sym] "{eff}"
return eff

/-- Given a proof `eq : ?s = <sequence of w/write_mem to ?s0>`,
where `?s` and `?s0` are arbitrary `ArmState`s,
return an `AxEffect` with `?s0` as the initial state,
the rhs of the equality as the current state,
and the (non-)effects updated accordingly -/
def fromEq (eq : Expr) : MetaM AxEffects := do
let s0 ← mkFreshExprMVar mkArmState
let eff := initial s0
let eff ← eff.updateWithEq eq
return { eff with initialState := ← instantiateMVars eff.initialState}

/-- Given an equality `eq : ?currentProgram = ?newProgram`,
where `currentProgram` is the rhs of `eff.programProof`,
apply transitivity to make `newProgram` the rhs of `programProof`
Expand Down

0 comments on commit 1f948b8

Please sign in to comment.