You are an expert Lean4 and formal verification agent proving a Lean4 theorem. Your output **must** strictly adhere to the specified format.

### Input Information
You will receive the following components, relevant to the target theorem:
* <all_available_defs>: Definitions available from imported modules (either from the current Lean repository or from Mathlib)
* <all_available_lemmas>: Lemmas/theorems available that may assist the proof.
* <local_ctx>...</local_ctx>: The local file context (imports, namespaces, definitions, comments, etc.) from the top of the file up to—but not including—the target theorem or any previously defined local lemmas/theorems.
* <target_theorem>...</target_theorem>: The target theorem statement, ending with `:=`.

**Notes**
1. Definitions include their full bodies, but for definitions whose bodies contain proofs, the proof parts are replaced by `admit` (i.e., admit /- proof elided -/), while the rest of the definition is kept unchanged; lemmas include only their statements.
2. You may freely reference any definition or lemma contained in these tags without redefining them.
3. The tags for available definitions and lemmas (all_available_defs, all_available_lemmas) may be omitted if empty.

### Output Format & Requirements
Your output MUST contain a complete, syntactically correct Lean 4 proof for the target theorem.

**Strict Output Structure:**
<reasoning> 
...
</reasoning> 

<lean4_invented_lemmas>
-- each lemma is a full Lean 4 declaration with a complete proof
...
</lean4_invented_lemmas>

<lean4_proof>
-- Lean 4 proof body of the target theorem
...
</lean4_proof>

**Requirements:**
1. <reasoning> and <lean4_invented_lemmas> are OPTIONAL. Include them only if they aid proof construction.
2. <lean4_proof> MUST contain only the proof body (tactics/terms), starting by "by", NOT the theorem declaration.
3. <lean4_invented_lemmas> (if present) MUST contain syntactically correct lemma declarations that type checks AND complete proof bodies. Defining a lemma using `axiom` is NOT allowed.
4. <reasoning> contains high-level proof planning.
5. If you create a lemma under <lean4_invented_lemmas> whose name is namespaced (e.g., X.Y.Z), you MUST always refer to it using its fully qualified name. Do NOT rely on shortened names. For example, write rw [X.Y.Z], not rw [Z] for invented lemmas.
6. All Lean 4 code MUST be syntactically correct. No `sorry`, `admit`, or non-Lean text. Comments allowed using `--` or `/- ... -/`.
7. Follow the tags and structure EXACTLY. No extra text before, between, or after the sections.
8. Do NOT wrap invented lemmas in a `mutual` block unless they have genuine mutual recursion. Declare each lemma independently.

### Examples are provided here (example input are under "User Prompt", and example assistant response are under "Agent Response"):
Example 1 ------------------- 
User Prompt:
<all_available_defs>
structure BitVec (w : Nat) where
  /-- Construct a `BitVec w` from a number less than `2^w`.
  O(1), because we use `Fin` as the internal representation of a bitvector. -/
  ofFin ::

  /-- Interpret a bitvector as a number less than `2^w`.
  O(1), because we use `Fin` as the internal representation of a bitvector. -/
  toFin : Fin (hPow 2 w)
</all_available_defs>

<all_available_lemmas>
theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) : (l₁ ++ l₂)[i] = l₁[i]
theorem getElem_eq_testBit_toNat (x : BitVec w) (i : Nat) (h : i < w) :
  x[i] = x.toNat.testBit i := rfl
@[simp, grind =] theorem toNat_cons (b : Bool) (x : BitVec w) :
    (cons b x).toNat = (b.toNat <<< w) ||| x.toNat
@[simp, grind =] theorem getLsbD_of_ge (x : BitVec w) (i : Nat) (ge : w ≤ i) : getLsbD x i = false
theorem testBit_toNat (x : BitVec w) : x.toNat.testBit i = x.getLsbD i
</all_available_lemmas>

<local_ctx>
import Mathlib.Computability.NFA
import Mathlib.Data.FinEnum
import Mathlib.Data.Rel
import Mathlib.Data.Vector.Basic
import Blase.AutoStructs.ForLean

open Set
open Mathlib
open SetRel

-- this is better because card is defeq to n
instance (α : Type) : Inter (Language α) := ⟨Set.inter⟩
instance (α : Type) : Union (Language α) := ⟨Set.union⟩

/--
The set of `n`-tuples of bit vectors of an arbitrary width.
-/
structure BitVecs (n : Nat) where
  w : Nat
  bvs : List.Vector (BitVec w) n

def BitVecs.cast (bvs : BitVecs n) (h : n = n') : BitVecs n' :=
  { w := bvs.w, bvs := h ▸ bvs.bvs }

abbrev BitVecs.empty : BitVecs n := ⟨0, List.Vector.replicate n .nil⟩
abbrev BitVecs.singleton {w : Nat} (bv : BitVec w) : BitVecs 1 := ⟨w, bv ::ᵥ .nil⟩
abbrev BitVecs.pair {w : Nat} (bv1 bv2 : BitVec w) : BitVecs 2 := ⟨w, bv1 ::ᵥ bv2 ::ᵥ .nil⟩

/--
The set of `n`-tuples of bit vectors of an arbitrary width, encoded as a list of
bit vectors of width `n`. The width of the encoded bit vectors is the length of
the list.
-/
abbrev BitVecs' (n : Nat) := List (BitVec n)

@[simps]
def dec (bvs' : BitVecs' n) : BitVecs n where
  w := bvs'.length
  bvs := List.Vector.ofFn fun k => BitVec.ofFn fun i => bvs'[i].getLsbD k

@[simp]
</local_ctx>

<target_theorem>
lemma dec_snoc n (bvs' : BitVecs' n) (a : BitVec n) :
  dec (bvs' ++ [a]) =
    { w := bvs'.length + 1
      bvs := List.Vector.ofFn fun k =>
        BitVec.cons (a.getLsbD k) ((dec bvs').bvs.get k) } :=
</target_theorem>

Agent Response:
<reasoning> 
The goal is to understand what `dec` does after appending one more bitvector `a` to `bvs'`. By definition, `dec` builds a width `= length` and a vector of bitvectors whose `i`-th bit at position `k` is `bvs'[i].getLsbD k`. So for `bvs' ++ [a]`, we expect the width to increase by 1 and each resulting bitvector to be `BitVec.cons` of the new bit coming from `a`.

First, I use `ext` twice: once on the record to focus on the `bvs` field, and once on the resulting bitvector. This reduces everything to a pointwise statement:
for fixed `k` and `i` with `i < bvs'.length + 1`,
the bit `(bvs' ++ [a])[i].getLsbD k` should match the bit at index `i` of `BitVec.cons (a.getLsbD k) ((dec bvs').bvs.get k)`.

At this point I need a clean description of indexing into `BitVec.cons`: if we have `x : BitVec n`, then `(cons b x)[i]` should give `b` at the new “last” index `n` and `x[i]` otherwise. That motivates an auxiliary lemma `getElem_cons` expressing exactly this behavior, proved via the `testBit`/`toNat` characterization and a case split on `i < n`, `i = n`, `i > n`.

Using `getElem_cons`, the RHS becomes an `if` on whether `i = bvs'.length`. So I split into cases:
- If `i = bvs'.length`, then `(bvs' ++ [a])[i]` is the appended `a`, so both sides reduce to `a.getLsbD k`.
- If `i ≠ bvs'.length`, the bound `i < bvs'.length + 1` forces `i < bvs'.length`. Then `(bvs' ++ [a])[i] = bvs'[i]` by `List.getElem_append_left`, and the RHS takes the “else” branch and likewise gives the bit from `bvs'[i]`. In both subcases, `simp` (plus the definition of `dec`) finishes.

So the whole proof is: `ext` to bit level, unfold `dec` with `simp_all`, rewrite with `getElem_cons`, split on the boundary index `i = length bvs'`, and in the “< length” branch use `List.getElem_append_left` and bounds to line up both sides.
</reasoning> 

<lean4_invented_lemmas>
@[grind =]
theorem getElem_cons {b : Bool} {n} {x : BitVec n} {i : Nat} (h : i < n + 1) :
    (cons b x)[i] = if h : i = n then b else x[i] := by
  simp only [BitVec.getElem_eq_testBit_toNat, BitVec.toNat_cons, Nat.testBit_or]
  rw [Nat.testBit_shiftLeft]
  rcases Nat.lt_trichotomy i n with i_lt_n | i_eq_n | n_lt_i
  · have p1 : ¬(n ≤ i) := by omega
    have p2 : i ≠ n := by omega
    simp [p1, p2]
  · simp only [i_eq_n, ge_iff_le, Nat.le_refl, decide_true, Nat.sub_self, Nat.testBit_zero,
    Bool.true_and, BitVec.testBit_toNat, BitVec.getLsbD_of_ge, Bool.or_false]
    cases b <;> trivial
  · have p1 : i ≠ n := by omega
    have p2 : i - n ≠ 0 := by omega
    simp [p1, p2, Nat.testBit_bool_toNat]
</lean4_invented_lemmas>

<lean4_proof>
by
  ext k i hi <;> simp_all
  rw [getElem_cons]
  split
  next heq => simp_all
  next h =>
    have hlt : i < List.length bvs' := by simp at hi; omega
    rw [List.getElem_append_left hlt]
    simp
</lean4_proof>

### Your task:
<all_available_defs>
Vector in Init.Data.Vector.Basic
Fin in Init.Prelude
String in Init.Prelude
Unit in Init.Prelude
List in Init.Prelude
Field in Mathlib.Algebra.Field.Defs
Bool in Init.Prelude
DecidableEq in Init.Prelude
FinEnum in Mathlib.Data.FinEnum
Hashable in Init.Prelude
Sum.inl in Init.Core
Sum.inr in Init.Core
Nat in Init.Prelude
Repr in Init.Data.Repr
Sum in Init.Core
Sum.elim in Init.Data.Sum.Basic
id in Init.Prelude
Nat.max in Init.Data.Nat.Basic
Nat.min in Init.Data.Nat.Basic
Decidable in Init.Prelude

syntax "min" : MLIR.Pretty.uniform_op

macro_rules
  | `(mlir_op| $res:mlir_op_operand = const ($x)
      $[: $outer_type]? ) => do
      let outer_type ← outer_type.getDM `(mlir_type| _)
      `(mlir_op| $res:mlir_op_operand = "const"()
          {val = $x:num : $outer_type} : ($outer_type) -> ($outer_type) )

macro_rules
  | `(mlir_op| $res:mlir_op_operand = li ($x)
     $[: $outer_type]?  ) => do
      let outer_type ← outer_type.getDM `(mlir_type| _ )
      `(mlir_op| $res:mlir_op_operand = "li"()
          {imm = $x:num : $outer_type } : ($outer_type) -> ($outer_type))

macro_rules
| `(mlir_op| $res:mlir_op_operand = $op1:MLIR.Pretty.RV.opWithImmediate $reg1 , $x : $t)  => do
    let some opName := MLIR.EDSL.Pretty.extractOpName op1.raw
      | Macro.throwUnsupported
    `(mlir_op| $res:mlir_op_operand = $opName ($reg1) {imm = $x:num : $t} : ($t) -> ($t) )

macro_rules
| `(mlir_op| $res:mlir_op_operand = $op1:MLIR.Pretty.RV.opWithShamt $reg1 , $x  : $t )  => do
    let some opName := MLIR.EDSL.Pretty.extractOpName op1.raw
      | Macro.throwUnsupported
    `(mlir_op| $res:mlir_op_operand = $opName ($reg1) {shamt = $x:num : $t}  : ($t) -> ($t) )

def ls (b : Bool) : FSM Unit :=
  { α := Unit,
    initCarry := fun _ => b,
    nextStateCirc := fun () => Circuit.var true (inr ()),
    outputCirc := Circuit.var true (inl ())
  }

structure FSM (arity : Type) : Type 1 where
   
  ( α  : Type )
  [ i : FinEnum α ]
  [ h : Hashable α ]
  [ dec_eq : DecidableEq α ]
   
  ( initCarry : α → Bool )
   
  outputCirc : Circuit (α ⊕ arity)
  nextStateCirc : α → Circuit (α ⊕ arity)

inductive Circuit (α : Type u) : Type u
  | tru : Circuit α
  | fals : Circuit α
   
  | var : (positive: Bool) → α → Circuit α
  | and : Circuit α → Circuit α → Circuit α
  | or : Circuit α → Circuit α → Circuit α
  | xor : Circuit α → Circuit α → Circuit α
deriving Repr, DecidableEq

def Var (Γ : Context Ty) (ty : Ty) : Type := { v : VarName // Γ.hasType v ty }

inductive StateSpace (wcard tcard bcard ncard icard pcard : Nat)
| widthVar (v : Fin wcard)
| termVar (v : Fin tcard)
| predVar (v : Fin pcard)
| boolVar (v : Fin bcard)
deriving DecidableEq, Repr, Hashable

inductive Term
| ofNat (w : WidthExpr) (n : Nat) : Term
| var (v : Nat) (w : WidthExpr) : Term
| add (w : WidthExpr) (a b : Term) : Term
| zext (a : Term) (wnew : WidthExpr) : Term
| setWidth (a : Term) (wnew : WidthExpr) : Term
| sext (a : Term) (wnew : WidthExpr) : Term
| bor (w : WidthExpr) (a b : Term) : Term
| band (w : WidthExpr) (a b : Term) : Term
| bxor (w : WidthExpr) (a b : Term) : Term
| bnot (w : WidthExpr)  (a : Term) : Term
| boolVar (v : Nat) : Term
| boolConst (b : Bool) : Term
| shiftl (w : WidthExpr) (a : Term) (k : Nat) : Term
| bvOfBool (b : Term) : Term
| binWidthRel (k : WidthBinaryRelationKind) (wa wb : WidthExpr) : Term
| binRel (k : BinaryRelationKind) (w : WidthExpr)
    (a : Term) (b : Term) : Term
| or (p1 p2 : Term) : Term
| and (p1 p2 : Term) : Term
| pvar (v : Nat) : Term
| boolBinRel (k : BoolBinaryRelationKind)
    (a b : Term) : Term
deriving DecidableEq, Inhabited, Repr, Lean.ToExpr

def composeUnaryAux
    (p : FSM Unit)
    (q : FSM arity) :
    FSM arity :=
  p.compose
    arity
    _
    (λ _ => id)
    (λ _ => q)

def compose [FinEnum arity] [DecidableEq arity] [Hashable arity]
    (new_arity : Type)        
    (q_arity : arity → Type)  
    (vars : ∀ (a : arity), q_arity a → new_arity)
    
    
    (q : ∀ (a : arity), FSM (q_arity a)) : 
    FSM new_arity :=
  { α := p.α ⊕ (Σ a, (q a).α),
    i := by admit /- proof elided -/

structure NatFSM (wcard tcard bcard ncard icard pcard : Nat) (v : Nondep.WidthExpr) where
  toFsm : FSM (StateSpace wcard tcard bcard ncard icard pcard)

inductive WidthExpr where
| const : Nat → WidthExpr
| var : Nat → WidthExpr
| max : WidthExpr → WidthExpr → WidthExpr
| min : WidthExpr → WidthExpr → WidthExpr
| addK : WidthExpr → Nat → WidthExpr
| kadd : Nat → WidthExpr → WidthExpr
deriving Inhabited, Repr, Hashable, DecidableEq, Lean.ToExpr

def scanOr  : FSM Unit :=
  {
   α := Unit,
   initCarry := fun () => false,
   outputCirc := Circuit.var true (inl ()) ||| Circuit.var true (inr ()),
   nextStateCirc := fun () => Circuit.var true (inl ()) ||| Circuit.var true (inr ())
  }

abbrev WidthExpr.Env (wcard : Nat) : Type :=
  Fin wcard → Nat

structure HWidthEnv {wcard tcard : Nat}
    (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream)
    (wenv : Fin wcard → Nat) : Prop where
    heq_width : ∀ (v : Fin wcard),
      fsmEnv (StateSpace.widthVar v) = BitStream.ofNatUnary (wenv v)

structure HPredicateEnv {wcard tcard bcard ncard icard pcard : Nat}
    (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream)
    (penv : Fin pcard → Prop) : Prop where
    heq_width : ∀ (v : Fin pcard),
      fsmEnv (StateSpace.predVar v) = BitStream.ofProp (penv v)

def BitStream : Type := Nat → Bool

abbrev ofNatUnary (n : Nat) : BitStream :=
  fun i => decide (i < n)

structure HNatFSMToBitstream {wcard : Nat} {v : WidthExpr wcard} {tcard : Nat} {bcard : Nat} {pcard : Nat}
   (fsm : NatFSM wcard tcard bcard ncard icard pcard (.ofDep v)) : Prop where
  heq :
    ∀ (wenv : Fin wcard → Nat)
    (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream),
    (henv : HWidthEnv fsmEnv wenv) →
      fsm.toFsm.eval fsmEnv =
      BitStream.ofNatUnary (v.toNat wenv)

def WidthExpr.toNat (e : WidthExpr wcard) (env : WidthExpr.Env wcard) : Nat :=
  match e with
  | .const n => n
  | .var v => env v
  | .min v w => Nat.min (v.toNat env) (w.toNat env)
  | .max v w => Nat.max (v.toNat env) (w.toNat env)
  | .addK v k => v.toNat env + k
  | .kadd k v => k + v.toNat env

inductive WidthExpr (wcard : Nat) : Type
| const (n : Nat) :  WidthExpr wcard
| var : (v : Fin wcard) → WidthExpr wcard
| min : (v w : WidthExpr wcard) → WidthExpr wcard
| max : (v w : WidthExpr wcard) → WidthExpr wcard
| addK : (v : WidthExpr wcard) → (k : Nat) → WidthExpr wcard
| kadd : (k : Nat) → (v : WidthExpr wcard) → WidthExpr wcard

structure HPredFSMToBitStream {pcard : Nat}
  {tctx : Term.Ctx wcard tcard}
  {p : Term bcard ncard icard pcard tctx .prop}
  (fsm : TermFSM wcard tcard bcard ncard icard pcard
    (.ofDepTerm p)) : Prop where
  heq :
    ∀ {wenv : WidthExpr.Env wcard}
      (benv : Term.BoolEnv bcard)
      (nenv : Term.NatEnv ncard)
      (ienv : Term.IntEnv icard)
      (penv : Predicate.Env pcard) (tenv : tctx.Env wenv)
      (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream),
      (htenv : HTermEnv fsmEnv tenv benv) →
      (hpenv : HPredicateEnv fsmEnv penv) →
        p.toBV benv nenv ienv penv tenv  ↔ (fsm.toFsmZext.eval fsmEnv = .negOne)

def scanOr (s : BitStream) : BitStream := scanl false Bool.or s

abbrev scanl (init : Bool) (f : Bool → Bool → Bool) (s : BitStream) : BitStream :=
  fun n => match n with
    | 0 => f init (s 0)
    | n+1 => f (scanl init f s n) (s (n + 1))

def mkPostcondIndHypNoCycleBreaking {n} (_circs : KInductionCircuits fsm n) :
    Circuit (Vars fsm.α arity (n + 2)) :=
  mkUnsatImpliesCircuit
    
    (castCircLe (mkOutEqZeroCircuitLeN fsm <| n))
    
    (mkOutEqZeroCircuitN fsm <| n+1)

def pr51551_after := [llvm|
{
^0(%arg8 : i32, %arg9 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg8, %0 : i32
  %3 = llvm.icmp "eq" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def or_eq_with_one_bit_diff_constants1_logical_before := [llvm|
{
^0(%arg365 : i32):
  %0 = llvm.mlir.constant(50 : i32) : i32
  %1 = llvm.mlir.constant(51 : i32) : i32
  %2 = llvm.mlir.constant(true) : i1
  %3 = llvm.icmp "eq" %arg365, %0 : i32
  %4 = llvm.icmp "eq" %arg365, %1 : i32
  %5 = "llvm.select"(%3, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def irc_constants_C1Minus2MinusC2_0_1 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%a: i64):
      %c1 = llvm.mlir.constant (0) : i64
      %c2 = llvm.mlir.constant (1) : i64
      %0 = llvm.sub %c1, %a : i64
      %1 = llvm.sub %0, %c2 : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%a: i64):
      %c1 = llvm.mlir.constant (0) : i64
      %c2 = llvm.mlir.constant (1) : i64
      %0 = llvm.sub %c1, %c2 : i64
      %1 = llvm.sub %0, %a : i64
      llvm.return %1 : i64
  }]

def and_not_or_or_not_or_xor_commute4_before := [llvm|
{
^0(%arg313 : i32, %arg314 : i32, %arg315 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg313 : i32
  %3 = llvm.or %arg314, %arg315 : i32
  %4 = llvm.xor %3, %1 : i32
  %5 = llvm.and %2, %4 : i32
  %6 = llvm.xor %arg314, %arg315 : i32
  %7 = llvm.or %2, %6 : i32
  %8 = llvm.xor %7, %1 : i32
  %9 = llvm.or %5, %8 : i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def shl_add_lshr_after := [llvm|
{
^0(%arg154 : i32, %arg155 : i32, %arg156 : i32):
  %0 = llvm.lshr %arg156, %arg155 : i32
  %1 = llvm.add %0, %arg154 overflow<nuw> : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def factorize5_after := [llvm|
{
^0(%arg1 : i32, %arg2 : i32):
  %0 = llvm.mul %arg2, %arg1 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def liftOp n : Fin (n + 1) → Fin (n + 3) :=
  fun k =>
    if k = n then Fin.last (n+2) else k.castLE (by admit /- proof elided -/
    )

def NFA.autWidthSA (n : Nat) (q : Fin (n+2)) : Language (BitVec 0) :=
  if q = Fin.last (n+1) then { w | w.length > n } else { w | w.length = q }

def not_ashr_const_after := [llvm|
{
^0(%arg138 : i8):
  %0 = llvm.mlir.constant(41 : i8) : i8
  %1 = llvm.lshr %0, %arg138 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

Lean.MacroM in Init.Prelude

HPow in Init.Prelude

def mkInitCarryAssignCircuitAux {arity : Type _}
  [DecidableEq arity]
  [Fintype arity]
  [Hashable arity]
  (p : FSM arity) (s : p.α):
  Circuit (Vars p.α arity 0) :=
    Circuit.xor
      (Circuit.ofBool (p.initCarry s))
      (Circuit.var true <| Vars.stateN s 0)

def and_zext_eq_odd_after := [llvm|
{
^0(%arg31 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.icmp "eq" %arg31, %0 : i32
  %2 = llvm.zext %1 : i1 to i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def add_and_or_after := [llvm|
{
^0(%arg15 : i32, %arg16 : i32):
  %0 = llvm.add %arg15, %arg16 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

@[simp_denote]
def sext_riscv_i1_to_32 := [LV| {
  ^entry (%arg: i1):
    %0 = "builtin.unrealized_conversion_cast"(%arg) : (i1) -> (!i64)
    %1 = slli %0, 63 : !i64
    %2 = srai %1, 63 : !i64
    %res = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i32)
    llvm.return %res : i32
  }]

def sub_from_constant_of_sub_from_constant_before := [llvm|
{
^0(%arg170 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(11 : i8) : i8
  %2 = llvm.sub %0, %arg170 : i8
  %3 = llvm.sub %1, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def positive_samevar_shlnsw_before := [llvm|
{
^0(%arg52 : i8, %arg53 : i8):
  %0 = llvm.lshr %arg52, %arg53 : i8
  %1 = llvm.shl %0, %arg53 overflow<nsw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def test20_after := [llvm|
{
^0(%arg2 : i33, %arg3 : i33):
  %0 = llvm.mlir.constant(0 : i33) : i33
  %1 = llvm.icmp "ne" %arg3, %0 : i33
  "llvm.return"(%1) : (i1) -> ()
}
]

def constLLVM34 : Com LLVMPlusRiscV ⟨[]⟩ .pure (.llvm (.bitvec 64)) := [LV| {
  ^entry ():
    %1 = llvm.mlir.constant (34) : i64
    llvm.return %1 : i64
  }]

instance : HydrablePrettifyAsTheorem FpPredicate where
  prettifyAsTheorem := prettifyAsTheorem

def ugt_and_not_min_after := [llvm|
{
^0(%arg78 : i8, %arg79 : i8):
  %0 = llvm.icmp "ugt" %arg78, %arg79 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

def alive_AddSub_1043_tgt := [sllvm| {
^bb0(%C1 : i64, %Z : i64, %RHS : i64):
  %v1 = llvm.not %C1 : i64
  %v2 = llvm.or %Z, %v1 : i64
  %v3 = llvm.and %Z, %C1 : i64
  %v4 = llvm.xor %v3, %C1 : i64
  %v5 = llvm.mlir.constant 1 : i64
  %v6 = llvm.add %v4, %v5 : i64
  %v7 = llvm.sub %RHS, %v2 : i64
  llvm.return %v7 : i64
}]

Std.Format.group in Init.Data.Format.Basic

def lshrult_03_03_before := [llvm|
{
^0(%arg332 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.lshr %arg332, %0 : i4
  %2 = llvm.icmp "ult" %1, %0 : i4
  "llvm.return"(%2) : (i1) -> ()
}
]

def shl_nsw_nuw_add_nsw_before := [llvm|
{
^0(%arg13 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.shl %0, %arg13 overflow<nsw,nuw> : i32
  %3 = llvm.add %2, %1 overflow<nsw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def add_and_or_after := [llvm|
{
^0(%arg15 : i32, %arg16 : i32):
  %0 = llvm.add %arg15, %arg16 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def select_icmp_eq_and_1_0_or_2_after := [llvm|
{
^0(%arg255 : i32, %arg256 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.shl %arg255, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.or %arg256, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def llvm_const_lower_riscv_li12 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM12, rhs:= liRiscv12,
   correct := by admit /- proof elided -/

def t20_before := [llvm|
{
^0(%arg145 : i8, %arg146 : i16):
  %0 = llvm.mlir.constant(-42 : i16) : i16
  %1 = llvm.shl %0, %arg146 : i16
  %2 = llvm.trunc %1 : i16 to i8
  %3 = llvm.sub %arg145, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

let processingWidth := state.processingWidth

def or_not_and_commute5_after := [llvm|
{
^0(%arg522 : i32, %arg523 : i32, %arg524 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg522 : i32
  %3 = llvm.sdiv %0, %arg524 : i32
  %4 = llvm.xor %arg523, %3 : i32
  %5 = llvm.xor %2, %1 : i32
  %6 = llvm.and %4, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def lshrult_03_07_before := [llvm|
{
^0(%arg328 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(7 : i4) : i4
  %2 = llvm.lshr %arg328, %0 : i4
  %3 = llvm.icmp "ult" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def test_mul__none_are_safe_after := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(9 : i32) : i32
  %1 = llvm.mul %arg0, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def nonexact_lshr_eq_before := [llvm|
{
^0(%arg154 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.lshr %0, %arg154 : i8
  %3 = llvm.icmp "eq" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def test9b_after := [llvm|
{
^0(%arg109 : i32, %arg110 : i32):
  %0 = llvm.or %arg109, %arg110 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def add_umin_simplify2_before := [llvm|
{
^0(%arg53 : i32):
  %0 = llvm.mlir.constant(43 : i32) : i32
  %1 = llvm.mlir.constant(42 : i32) : i32
  %2 = llvm.add %arg53, %0 overflow<nuw> : i32
  %3 = llvm.icmp "ult" %2, %1 : i32
  %4 = "llvm.select"(%3, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def ule_and_min_commute_before := [llvm|
{
^0(%arg202 : i8, %arg203 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "ule" %arg202, %arg203 : i8
  %2 = llvm.icmp "eq" %arg202, %0 : i8
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def test92_after := [llvm|
{
^0(%arg48 : i64):
  %0 = llvm.mlir.constant(32) : i64
  %1 = llvm.ashr %arg48, %0 : i64
  "llvm.return"(%1) : (i64) -> ()
}
]

def sub_2_before := [llvm|
{
^0(%arg109 : i8, %arg110 : i1, %arg111 : i8, %arg112 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(123 : i8) : i8
  %2 = llvm.xor %arg111, %0 : i8
  %3 = llvm.xor %arg112, %1 : i8
  %4 = "llvm.select"(%arg110, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %5 = llvm.sub %arg109, %4 : i8
  %6 = llvm.xor %5, %0 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

def sra_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := sra_negative_constant_lhs_llvm_i32
  rhs := sra_negative_constant_lhs_riscv_i32

def not_cond_before := [llvm|
{
^0(%arg24 : i1, %arg25 : i32, %arg26 : i32):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg24, %0 : i1
  %2 = "llvm.select"(%1, %arg25, %arg26) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def test_sge_xor_after := [llvm|
{
^0(%arg38 : i32, %arg39 : i32):
  %0 = llvm.xor %arg39, %arg38 : i32
  %1 = llvm.icmp "sle" %0, %arg38 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def ripple_nsw6_after := [llvm|
{
^0(%arg13 : i16, %arg14 : i16):
  %0 = llvm.mlir.constant(-21845 : i16) : i16
  %1 = llvm.mlir.constant(-10923 : i16) : i16
  %2 = llvm.or %arg14, %0 : i16
  %3 = llvm.or %arg13, %1 : i16
  %4 = llvm.add %3, %2 overflow<nsw> : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

def ashr_pow2_ugt_after := [llvm|
{
^0(%arg67 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.mlir.constant(-96 : i8) : i8
  %2 = llvm.ashr exact %0, %arg67 : i8
  %3 = llvm.icmp "ugt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def zext_nneg_sext_sle_op0_narrow_before := [llvm|
{
^0(%arg50 : i8, %arg51 : i16):
  %0 = llvm.zext nneg %arg50 : i8 to i32
  %1 = llvm.sext %arg51 : i16 to i32
  %2 = llvm.icmp "sle" %0, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def slt_zero_before := [llvm|
{
^0(%arg30 : i4, %arg31 : i4):
  %0 = llvm.mlir.constant(0 : i4) : i4
  %1 = llvm.icmp "slt" %arg30, %0 : i4
  %2 = llvm.icmp "slt" %arg31, %0 : i4
  %3 = llvm.xor %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def test13_after := [llvm|
{
^0(%arg27 : i18):
  %0 = llvm.mlir.constant(6 : i18) : i18
  %1 = llvm.mlir.constant(-512 : i18) : i18
  %2 = llvm.mul %arg27, %0 : i18
  %3 = llvm.and %2, %1 : i18
  "llvm.return"(%3) : (i18) -> ()
}
]

def p_after := [llvm|
{
^0(%arg60 : i32, %arg61 : i32, %arg62 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg60, %arg62 : i32
  %2 = llvm.xor %arg62, %0 : i32
  %3 = llvm.and %arg61, %2 : i32
  %4 = llvm.or disjoint %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

@[simp_llvm]
def sdiv? {w : Nat} (x y : BitVec w) : IntW w :=
  if y == 0 || (w != 1 && x == (BitVec.intMin w) && y == -1) then
    .poison
  else
    .value (x.sdiv y)

def test19_after := [llvm|
{
^0(%arg76 : i32, %arg77 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.shl %0, %arg76 overflow<nuw> : i32
  %3 = llvm.shl %0, %arg77 overflow<nuw> : i32
  %4 = llvm.and %2, %3 : i32
  %5 = llvm.add %4, %2 : i32
  %6 = llvm.add %5, %1 : i32
  %7 = llvm.and %arg77, %6 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def intro_example_rhs := [LV| {
  ^entry (%arg: i64, %amount: i64):
    llvm.return %arg : i64
  }]

def shl_xor_before := [llvm|
{
^0(%arg63 : i32, %arg64 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(7 : i32) : i32
  %2 = llvm.shl %arg63, %0 : i32
  %3 = llvm.xor %2, %arg64 : i32
  %4 = llvm.shl %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def liRiscv_39 := [LV| {
  ^entry ():
    %0 = "li"() {imm = -39 : !i64} : (!i64) -> (!i64)
    %1 = "builtin.unrealized_conversion_cast"(%0) : (!i64) -> (i64)
    llvm.return %1 : i64
  }]

def _root_.Int.testBit' (i : Int) (k : Nat) : Bool :=
  match i with
  | .ofNat n => n.testBit k
  | .negSucc n => !(n.testBit k)

def bitwise_and_logical_and_icmps_before := [llvm|
{
^0(%arg232 : i8, %arg233 : i8, %arg234 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.mlir.constant(false) : i1
  %4 = llvm.icmp "eq" %arg233, %0 : i8
  %5 = llvm.and %arg232, %1 : i8
  %6 = llvm.shl %1, %arg234 : i8
  %7 = llvm.and %arg232, %6 : i8
  %8 = llvm.icmp "ne" %5, %2 : i8
  %9 = llvm.icmp "ne" %7, %2 : i8
  %10 = "llvm.select"(%4, %8, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %11 = llvm.and %10, %9 : i1
  "llvm.return"(%11) : (i1) -> ()
}
]

def nonexact_ashr_ne_noexactlog_before := [llvm|
{
^0(%arg133 : i8):
  %0 = llvm.mlir.constant(-90 : i8) : i8
  %1 = llvm.mlir.constant(-30 : i8) : i8
  %2 = llvm.ashr %0, %arg133 : i8
  %3 = llvm.icmp "ne" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def ofList (vals : List (Option α)) : Stream α :=
  fun i => (vals[i]?).join

def foo_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(7 : i32) : i32
  %2 = llvm.or %0, %1 : i32
  %3 = llvm.and %arg0, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

|
</all_available_defs>

<all_available_lemmas>
decide_eq_true_iff in Init.PropLemmas
iff_true in Init.SimpLemmas
inf_of_le_left in Mathlib.Order.Lattice
le_refl in Mathlib.Order.Defs.PartialOrder
left_eq_inf in Mathlib.Order.Lattice
not_iff in Mathlib.Logic.Basic
not_le in Mathlib.Order.Defs.LinearOrder
not_lt in Mathlib.Order.Defs.LinearOrder

theorem scanOr_eq_decide (s : BitStream) (n : Nat) :
    s.scanOr n = decide (∃ (i : Nat), i ≤ n ∧ s i = true)

theorem scanOr_true_iff (s : BitStream) (n : Nat)
    : s.scanOr n = true ↔ ∃ (i : Nat), (i ≤ n) ∧ s i = true

theorem scanOr_false_iff (s : BitStream) (n : Nat) : s.scanOr n = false ↔ ∀ (i : Nat), (hi : i ≤ n) → s i = false

@[simp]
theorem scanOr_succ (s : BitStream) : scanOr s (n+1) = ((s.scanOr n) || s (n + 1))

lemma CNFA.autUnsignedCmp_spec {cmp} : (CNFA.autUnsignedCmp cmp).Sim (NFA'.autUnsignedCmp cmp)

theorem udiv_i32_multiuse_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬zeroExtend 32 x = 0 →
    zeroExtend 32 x = 0 ∨
        True ∧ (zeroExtend 32 x_1).saddOverflow (zeroExtend 32 x) = true ∨
          True ∧ (zeroExtend 32 x_1).uaddOverflow (zeroExtend 32 x) = true ∨
            True ∧ (zeroExtend 32 x_1 / zeroExtend 32 x).smulOverflow (zeroExtend 32 x_1 + zeroExtend 32 x) = true ∨
              True ∧ (zeroExtend 32 x_1 / zeroExtend 32 x).umulOverflow (zeroExtend 32 x_1 + zeroExtend 32 x) = true →
      False

theorem uge_or_max_commute_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == -1#8) ||

theorem not_ashr_bitwidth_mask_thm (e e_1 : IntW 8) :
  LLVM.and (LLVM.xor (ashr e_1 (const? 8 7)) (const? 8 (-1))) e ⊑
    select (icmp IntPred.slt e_1 (const? 8 0)) (const? 8 0) e

theorem hoist_ashr_ahead_of_sext_2_thm (e : IntW 8) : ashr (sext 32 e) (const? 32 8) ⊑ sext 32 (ashr e (const? 8 7))

theorem e_1709 :
     - 2 * (b |||  ~~~(a ^^^ c)) - 7 * (b |||  ~~~(a |||  ~~~c)) - 11 *  ~~~( ~~~a ||| ( ~~~b &&& c)) + 4 * (b ^^^ (a ||| (b &&& c))) + 1 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 1 * ((a &&&  ~~~b) ||| (b ^^^ c)) + 1 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 5 * (c ||| (a &&& b)) + 3 * (a &&& b) + 1 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) + 1 * ((a ^^^ b) ||| (a ^^^ c)) - 7 * (a |||  ~~~c) + 3 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 1 * (a ^^^ ( ~~~b &&& c)) + 11 * (c ^^^ (a &&& b)) + 1 * ( ~~~a ||| (b ||| c)) - 3 * (c ^^^ (a ||| ( ~~~b &&& c))) + 11 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 2 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) - 2 * (b ^^^  ~~~(a ||| (b &&& c))) + 3 * (b &&& c) - 1 * (b ^^^ ( ~~~a &&& (b ^^^ c))) - 1 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 7 * (b ^^^  ~~~(a &&&  ~~~c)) - 2 *  ~~~(a ||| (b ||| c)) + 9 *  ~~~(a ||| ( ~~~b ||| c)) + 3 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 23 * ( ~~~a &&& ( ~~~b &&& c)) - 25 * (a &&& ( ~~~b &&& c)) + 15 * (a &&& (b &&& c)) = 14 * ( ~~~a &&& (b &&& c)) - 7 * (c &&&  ~~~(a &&&  ~~~b))

theorem e_690 :
    1 *  ~~~(x &&&  ~~~x) + 7 * (x ^^^ y) - 5 *  ~~~(x &&&  ~~~y) + 1 * x + 1 *  ~~~x - 1 *  ~~~(x ^^^ y) + 7 * (x ||| y) + 4 *  ~~~(x ||| y) - 11 *  ~~~(x |||  ~~~y) - 3 * (x &&& y) = 16 * (x &&&  ~~~y)

theorem test4_proof : test4_before ⊑ test4_after

theorem and_or2_thm.extracted_1._3 : ∀ (x x_1 : BitVec 1), ¬(x_1 ^^^ 1#1) &&& x = 1#1 → ¬x = 1#1 → x = 0#1

theorem AvoidCollision_signExtend_not {x : BitVec w} (h : 0 < w) :
    (~~~x).signExtend v = ~~~(x.signExtend v)

theorem lshr_ne_msb_low_last_zero_proof : lshr_ne_msb_low_last_zero_before ⊑ lshr_ne_msb_low_last_zero_after

theorem and_nosignbit_select_ashr_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → ¬8#32 ≥ ↑32 → (x &&& 2147418112#32).sshiftRight' 8#32 = x.sshiftRight' 8#32 &&& 8388352#32

theorem e_820 :
    5 * z + 1 *  ~~~(z &&&  ~~~z) + 5 *  ~~~t - 1 *  ~~~(z ||| t) - 5 * (z &&&  ~~~t) = 5 * (z |||  ~~~t) + 1 * (z ||| t)

theorem multiuse_add_proof : multiuse_add_before ⊑ multiuse_add_after

theorem e_2419 :
     - 3 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 3 * ( ~~~d ||| (e ^^^ f)) + 3 * (f &&&  ~~~(d ^^^ e)) + 1 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 2 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 2 *  ~~~(d ^^^ f) + 7 * (e ^^^ (d ||| (e ^^^ f))) - 7 *  ~~~d - 11 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) + 4 * (e ^^^  ~~~(d ||| (e &&& f))) + 5 * ( ~~~d ||| ( ~~~e ||| f)) - 6 * (e ||| (d &&& f)) - 2 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) - 1 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) + 1 *  ~~~( ~~~d ||| (e &&& f)) + 11 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * (f &&&  ~~~(d &&&  ~~~e)) + 1 * ((d ||| e) &&& (e ^^^ f)) - 1 * (e ^^^ (d &&& f)) - 1 * (f ^^^ (d &&&  ~~~e)) + 5 * (e &&&  ~~~(d &&& f)) + 11 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) + 2 * (f ^^^ (d ||| e)) + 1 * (e ^^^ ( ~~~d ||| (e ^^^ f))) - 7 * ((d &&& e) |||  ~~~(e ||| f)) + 3 * ( ~~~d &&& (e ^^^ f)) - 11 * (f ^^^  ~~~(d ||| e)) - 1 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 7 * ((d &&& f) |||  ~~~(e ||| f)) + 1 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 5 * (d &&& e) + 3 *  ~~~(d ^^^ (e ||| f)) - 6 * (e ^^^  ~~~(d &&& f)) - 11 * (e &&&  ~~~(d ^^^ f)) - 7 * (f &&& (d ^^^ e)) - 3 * (d &&& f) - 2 * (e ||| (d &&&  ~~~f)) - 11 * (e ^^^  ~~~(d &&& (e &&& f))) - 2 * (e &&& f) - 7 *  ~~~(d &&&  ~~~e) + 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 2 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) - 3 * (d &&& (e ||| f)) - 1 * (d &&& ( ~~~e ||| f)) - 11 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 4 * (f ^^^  ~~~(d |||  ~~~e)) + 1 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 1 * ((d &&& e) |||  ~~~(e |||  ~~~f)) + 1 * (f ^^^ (d |||  ~~~e)) - 7 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 5 *  ~~~(e ^^^ f) + 2 * (f ||| (d &&&  ~~~e)) - 1 *  ~~~(e ||| f) + 5 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 2 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) + 1 * ((d &&& e) ||| (e ^^^ f)) - 1 * ( ~~~f |||  ~~~(d ^^^ e)) + 4 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) + 2 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 2 * (e ^^^  ~~~(d ||| f)) + 2 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) - 2 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 5 * (e &&&  ~~~f) - 1 * (e ^^^  ~~~(d &&& (e ^^^ f))) + 4 * (f ^^^  ~~~(d &&& e)) - 5 *  ~~~(e |||  ~~~f) + 30 *  ~~~(d ||| (e ||| f)) + 10 *  ~~~(d ||| ( ~~~e ||| f)) + 16 *  ~~~( ~~~d ||| (e ||| f)) + 8 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 17 * ( ~~~d &&& ( ~~~e &&& f)) - 20 * ( ~~~d &&& (e &&& f)) + 23 * (d &&& ( ~~~e &&& f)) + 50 * (d &&& (e &&& f)) =  - 7 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f)))

theorem exact_lshr_eq_thm (e : IntW 8) :
  icmp IntPred.eq (lshr (const? 8 4) e { «exact» := true }) (const? 8 1) ⊑
    icmp IntPred.eq e (const? 8 2)

theorem e_1424 :
    1 * t + 4 *  ~~~z + 4 *  ~~~t - 1 *  ~~~(z &&&  ~~~z) - 1 *  ~~~(z ^^^ t) - 7 * (z |||  ~~~t) - 1 * (z ^^^ t) - 4 *  ~~~(z |||  ~~~t) + 4 * (z &&&  ~~~t) + 8 * (z &&& t) =  - 1 *  ~~~(z &&& t)

theorem t5_ugt_slt_0_thm.extracted_1._10 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (65535#32 <ᵤ x_2) = 1#1 → ofBool (65535#32 <ₛ x_2) = 1#1 → x_2 = x

theorem zext_sext_add_icmp_slt_minus1_proof : zext_sext_add_icmp_slt_minus1_before ⊑ zext_sext_add_icmp_slt_minus1_after

@[simp]
lemma RawCNFA.lift_processState_spec {m : CNFA n₁} {f : Fin n₁ → Fin n₂} :
    s' ∈ (lift.processState m.m f trs s₀).getD (s, b) ∅ ↔
      s' ∈ trs.getD (s, b) ∅ ∨ s = s₀ ∧ s' ∈ m.m.tr s (b.transport f)

theorem sdiv_icmp1_thm (e : IntW 64) :
  icmp IntPred.eq (LLVM.sdiv e (const? 64 5) { «exact» := true }) (const? 64 0) ⊑
    icmp IntPred.eq e (const? 64 0)

theorem bar_proof : bar_before ⊑ bar_after

theorem gt_signed_to_large_negative_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (BitVec.ofInt 32 (-1024) <ₛ signExtend 32 x) = 1#1

theorem lor_lor_left1_proof : lor_lor_left1_before ⊑ lor_lor_left1_after

theorem denote_multiRewritePeepholeAt (fuel : ℕ)
  (prs : List (Σ Γ, Σ ty, PeepholeRewrite d Γ ty)) (ix : ℕ) (target : Com d Γ₂ eff t₂) :
    (multiRewritePeepholeAt fuel prs ix target).denote = target.denote

theorem xor_or2_proof : xor_or2_before ⊑ xor_or2_after

theorem e_386 :
    2 *  ~~~(x &&& y) + 4 * (x ^^^ y) + 2 * (x |||  ~~~y) - 11 *  ~~~y - 1 *  ~~~(x &&&  ~~~y) + 8 *  ~~~(x ||| y) - 16 *  ~~~(x |||  ~~~y) - 12 * (x &&& y) =  - 3 * (x &&&  ~~~y) - 11 * y

theorem lshrugt_01_07_proof : lshrugt_01_07_before ⊑ lshrugt_01_07_after

theorem test2_thm (e e_1 : IntW 39) :
  LLVM.or
      (LLVM.and (add e_1 (LLVM.and e (const? 39 (-274877906944)))) (LLVM.xor (const? 39 274877906943) (const? 39 (-1))))
      (LLVM.and e_1 (const? 39 274877906943)) ⊑
    add e_1 (LLVM.and e (const? 39 (-274877906944)))

theorem main12_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (truncate 16 x <ₛ 0#16) = 1#1 → ofBool (x &&& 32896#32 == 0#32) = 1#1 → ¬True → 2#32 = 1#32

theorem test_shl_nsw__nuw_is_safe_thm (e : IntW 64) (e_1 : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e_1 (const? 32 1073741822)) (const? 32 0)) e
      (ashr e (zext 64 (shl (LLVM.and e_1 (const? 32 1073741822)) (const? 32 2) { «nsw» := true, «nuw» := false }))) ⊑
    ashr e (zext 64 (LLVM.and (shl e_1 (const? 32 2)) (const? 32 (-8))) { «nneg» := true })

theorem main5c_like_logical_thm.extracted_1._12 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 7#32 != 7#32) = 1#1 →
    ¬ofBool (x_1 &&& 7#32 == 7#32) = 1#1 → ¬ofBool (x &&& 7#32 != 7#32) = 1#1 → 1#32 = zeroExtend 32 0#1

theorem e_604 :
     - 1 *  ~~~y - 1 * y + 3 * (x ^^^ y) - 7 *  ~~~(x &&& y) - 2 * x - 1 *  ~~~(x ^^^ y) + 1 * (x ||| y) - 1 * (x |||  ~~~y) + 6 *  ~~~(x ||| y) + 3 * (x &&&  ~~~y) =  - 4 *  ~~~(x &&&  ~~~x)

theorem test2_proof : test2_before ⊑ test2_after

theorem and_orn_cmp_3_proof : and_orn_cmp_3_before ⊑ and_orn_cmp_3_after

theorem bswap_and_mask_1_proof : bswap_and_mask_1_before ⊑ bswap_and_mask_1_after

theorem or3 (w : Nat) (a : BitVec w) : (a ≠ a + 1#w) ∨ (1#w + 1#w = 0#w) ∨ (1#w = 0#w)

theorem test12_proof : test12_before ⊑ test12_after

theorem p_proof : p_before ⊑ p_after

theorem sgt_smin3_thm (e e_1 : IntW 32) :
  icmp IntPred.slt (add e_1 (const? 32 3))
      (select (icmp IntPred.slt (add e_1 (const? 32 3)) e) (add e_1 (const? 32 3)) e) ⊑
    const? 1 0

theorem ult_and_max_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ofBool (x_1 <ᵤ x) &&& ofBool (x_1 == -1#8) = 0#1

theorem negation_of_increment_via_or_with_no_common_bits_set_proof : negation_of_increment_via_or_with_no_common_bits_set_before ⊑ negation_of_increment_via_or_with_no_common_bits_set_after

theorem sdiv_shl_pair3_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ (x_2 <<< x_1).sshiftRight' x_1 ≠ x_2 ∨
        x_1 ≥ ↑32 ∨
          True ∧ (x_2 <<< x).sshiftRight' x ≠ x_2 ∨
            x ≥ ↑32 ∨ (x_2 <<< x == 0 || 32 != 1 && x_2 <<< x_1 == intMin 32 && x_2 <<< x == -1) = true) →
    ¬(True ∧ 1#32 <<< x_1 >>> x_1 ≠ 1#32 ∨ x_1 ≥ ↑32 ∨ x ≥ ↑32) → (x_2 <<< x_1).sdiv (x_2 <<< x) = 1#32 <<< x_1 >>> x

@[bv_multi_width_normalize] theorem ofBool_eq_ofBool_iff (x y : Bool) :
  BitVec.ofBool x = BitVec.ofBool y ↔ (x = y)

theorem land_lor_right2_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → 1#1 = x_1

theorem e_2175 :
     - 3 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) + 7 * (d ||| ( ~~~e &&& f)) + 2 * ((d &&& e) |||  ~~~(e |||  ~~~f)) + 1 *  ~~~(d &&& f) + 3 * (e ^^^ ( ~~~d ||| (e &&& f))) - 3 * (e ^^^  ~~~(d ||| (e &&& f))) - 7 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 1 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 7 * (e |||  ~~~f) + 11 *  ~~~(d ||| ( ~~~e &&& f)) - 1 * (d ||| (e &&& f)) - 3 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 1 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) - 5 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) + 1 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 3 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 7 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 11 * (e ||| (d &&&  ~~~f)) + 5 * ((d ||| e) &&& (e ^^^ f)) + 3 *  ~~~( ~~~d ||| (e &&& f)) + 1 * (e |||  ~~~(d |||  ~~~f)) + 1 * ( ~~~e |||  ~~~(d ^^^ f)) - 2 * (e ^^^ f) - 3 *  ~~~(d ^^^ ( ~~~e ||| f)) - 1 * (f ^^^ (d ||| (e ||| f))) + 2 * (e ^^^ (d &&& ( ~~~e ||| f))) + 3 * (e &&& (d |||  ~~~f)) + 2 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 6 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) - 2 *  ~~~(d ||| (e &&& f)) + 2 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) - 7 * (f ^^^  ~~~(d &&& (e &&& f))) - 2 * (e |||  ~~~(d ^^^ f)) - 1 * ((d &&& f) ^^^ (e ||| f)) + 1 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 11 *  ~~~(e |||  ~~~f) - 5 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 2 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 5 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 11 * (f ^^^  ~~~(d &&& (e ||| f))) + 4 * ( ~~~d ||| (e ^^^ f)) - 5 *  ~~~(d ||| (e ||| f)) + 16 *  ~~~(d ||| ( ~~~e ||| f)) + 17 *  ~~~( ~~~d ||| (e ||| f)) + 21 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 10 * ( ~~~d &&& ( ~~~e &&& f)) + 20 * ( ~~~d &&& (e &&& f)) - 1 * (d &&& ( ~~~e &&& f)) + 19 * (d &&& (e &&& f)) = 11 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f)))

theorem positive_with_icmp_logical_proof : positive_with_icmp_logical_before ⊑ positive_with_icmp_logical_after

theorem lshr_eq_msb_low_last_zero_proof : lshr_eq_msb_low_last_zero_before ⊑ lshr_eq_msb_low_last_zero_after

theorem smear_set_bit_different_dest_type_wider_dst_proof : smear_set_bit_different_dest_type_wider_dst_before ⊑ smear_set_bit_different_dest_type_wider_dst_after

theorem n0_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 8),
  ¬x_2 ≥ ↑8 →
    ¬(True ∧ ((-1#8) <<< x_2).sshiftRight' x_2 ≠ -1#8 ∨ x_2 ≥ ↑8) →
      ofBool (((-1#8) <<< x_2 ^^^ -1#8) &&& x_1 != x) = ofBool (x_1 &&& ((-1#8) <<< x_2 ^^^ -1#8) != x)

theorem logical_or_logical_or_icmps_comm1_thm.extracted_1._5 : ∀ (x x_1 x_2 : BitVec 8),
  ¬x_1 ≥ ↑8 →
    ¬(ofBool (x_2 &&& 1#8 <<< x_1 == 0#8) = 1#1 ∨ ofBool (x == 42#8) = 1#1) →
      ¬(True ∧ 1#8 <<< x_1 >>> x_1 ≠ 1#8 ∨ x_1 ≥ ↑8) →
        ofBool (x_2 &&& 1#8 <<< x_1 == 0#8) = 1#1 → True → ofBool (x_2 &&& 1#8 == 0#8) = 1#1

@[simp] theorem size_var : (var e body : Com d Γ eff t).size = body.size + 1

theorem shl_shl_constants_div_proof : shl_shl_constants_div_before ⊑ shl_shl_constants_div_after

theorem test_simplify_decrement_invalid_ne_proof : test_simplify_decrement_invalid_ne_before ⊑ test_simplify_decrement_invalid_ne_after

theorem ashrslt_03_06_proof : ashrslt_03_06_before ⊑ ashrslt_03_06_after

theorem not_and_and_or_no_or_commute1_and_proof : not_and_and_or_no_or_commute1_and_before ⊑ not_and_and_or_no_or_commute1_and_after

theorem icmp_ult_x_y_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ofBool (x_1 &&& x <ᵤ x_1) = ofBool (x_1 &&& x != x_1)

theorem and_xor_commute3_thm (e e_1 : IntW 32) :
  LLVM.xor (LLVM.and (LLVM.udiv (const? 32 42) e_1) (LLVM.udiv (const? 32 42) e)) (LLVM.udiv (const? 32 42) e_1) ⊑
    LLVM.and (LLVM.udiv (const? 32 42) e_1) (LLVM.xor (LLVM.udiv (const? 32 42) e) (const? 32 (-1)))

theorem narrow_sext_sub_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 16),
  truncate 16 (signExtend 32 x_1 - x) = x_1 - truncate 16 x

theorem shl_xor_xor_good_mask_proof : shl_xor_xor_good_mask_before ⊑ shl_xor_xor_good_mask_after

theorem test_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(17#32 ≥ ↑32 ∨ 17#32 ≥ ↑32) → ¬31#32 ≥ ↑32 → (x.sshiftRight' 17#32).sshiftRight' 17#32 = x.sshiftRight' 31#32

theorem main12_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (truncate 16 x <ₛ 0#16) = 1#1 → ofBool (x &&& 32896#32 == 0#32) = 1#1 → ¬True → 2#32 = 1#32

theorem and_ashr_not_commuted_proof : and_ashr_not_commuted_before ⊑ and_ashr_not_commuted_after

theorem ashrsgt_01_14_exact_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ x >>> 1#4 <<< 1#4 ≠ x ∨ 1#4 ≥ ↑4) →
    ofBool (BitVec.ofInt 4 (-2) <ₛ x.sshiftRight' 1#4) = ofBool (BitVec.ofInt 4 (-4) <ₛ x)

theorem fold_add_udiv_urem_without_noundef_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(10#32 = 0 ∨ 4#32 ≥ ↑32 ∨ 10#32 = 0) →
    ¬(10#32 = 0 ∨ 4#32 ≥ ↑32 ∨ 10#32 = 0 ∨ True ∧ ((x / 10#32) <<< 4#32 &&& x % 10#32 != 0) = true) →
      (x / 10#32) <<< 4#32 + x % 10#32 = (x / 10#32) <<< 4#32 ||

theorem ashrslt_03_09_exact_thm (e : IntW 4) :
  icmp IntPred.slt (ashr e (const? 4 3) { «exact» := true }) (const? 4 (-7)) ⊑ const? 1 0

theorem test15a_proof : test15a_before ⊑ test15a_after

theorem ashrslt_03_05_proof : ashrslt_03_05_before ⊑ ashrslt_03_05_after

theorem lshrult_01_07_exact_proof : lshrult_01_07_exact_before ⊑ lshrult_01_07_exact_after

theorem and_signbit_select_lshr_proof : and_signbit_select_lshr_before ⊑ and_signbit_select_lshr_after

theorem ne_umax2_proof : ne_umax2_before ⊑ ne_umax2_after

theorem exact_ashr_ne_both_equal_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ BitVec.ofInt 8 (-128) >>> x <<< x ≠ BitVec.ofInt 8 (-128) ∨ x ≥ ↑8) →
    ofBool ((BitVec.ofInt 8 (-128)).sshiftRight' x != BitVec.ofInt 8 (-128)) = ofBool (x != 0#8)

theorem gt_signed_to_large_signed_thm (e : IntW 8) : icmp IntPred.sgt (sext 32 e) (const? 32 1024) ⊑ const? 1 0

theorem test_const_shr_exact_and_1_ne_0_proof : test_const_shr_exact_and_1_ne_0_before ⊑ test_const_shr_exact_and_1_ne_0_after

theorem xor_or_xor_common_op_commute5_proof : xor_or_xor_common_op_commute5_before ⊑ xor_or_xor_common_op_commute5_after

theorem or_xor_commute4_proof : or_xor_commute4_before ⊑ or_xor_commute4_after

theorem ne_nsw_rem_nz_thm (e : IntW 8) :
  icmp IntPred.ne (mul e (const? 8 5) { «nsw» := true, «nuw» := false }) (const? 8 (-126)) ⊑ const? 1 1

theorem land_lor_right1_thm.extracted_1._3 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → 1#1 = x_1

theorem e_969 :
    2 *  ~~~t + 1 *  ~~~(z &&&  ~~~z) - 6 * (z ||| t) - 4 *  ~~~(z ||| t) + 4 *  ~~~(z |||  ~~~t) + 2 * (z &&&  ~~~t) + 4 * (z &&& t) =  - 1 * (z ^^^ t) - 1 *  ~~~(z ^^^ t)

theorem e_940 :
     - 6 *  ~~~(z &&& t) - 2 * (z ^^^ t) + 2 * z + 6 *  ~~~(z ||| t) + 6 * (z &&&  ~~~t) - 2 * (z &&& t) =  - 8 *  ~~~(z |||  ~~~t)
</all_available_lemmas>

<local_ctx>
import Blase.Fast.FiniteStateMachine

import Blase.Vars

import Blase.MultiWidth.Defs

import Blase.KInduction.KInduction

import Lean

namespace MultiWidth

def NatFSM.fsmUnaryIndexUle (a : NatFSM wcard tcard bcard ncard icard pcard v) :
    FSM (StateSpace wcard tcard bcard ncard icard pcard) :=
  composeUnaryAux (FSM.ls true) a.toFsm

def fsmUnaryNeqUpto (a : NatFSM wcard tcard bcard ncard icard pcard (.ofDep v))
    (b : NatFSM wcard tcard bcard ncard icard pcard (.ofDep w)) : FSM (StateSpace wcard tcard bcard ncard icard pcard) :=
  composeUnaryAux FSM.scanOr (a.fsmUnaryIndexUle ^^^ b.fsmUnaryIndexUle)
</local_ctx>

<target_theorem>
@[simp]
theorem eval_fsmUnaryNeqUpto_eq_decide
    (a : NatFSM wcard tcard bcard ncard icard pcard (.ofDep v))
    (b : NatFSM wcard tcard bcard ncard icard pcard (.ofDep w))
    {wenv : WidthExpr.Env wcard}
    {fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream}
    (henv : HWidthEnv fsmEnv wenv)
    (ha : HNatFSMToBitstream a) (hb : HNatFSMToBitstream b) :
    ((fsmUnaryNeqUpto a b).eval fsmEnv) i =
    (decide (min i (v.toNat wenv) ≠ min i (w.toNat wenv))) :=
</target_theorem>

