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>
Bool in Init.Prelude
Nat in Init.Prelude
BitVec in Init.Prelude
BitVec.adcb in Init.Data.BitVec.Bitblast
Prod in Init.Prelude
Fin in Init.Prelude
BitVec.iunfoldr in Init.Data.BitVec.Folds
FinEnum in Mathlib.Data.FinEnum
FinEnum.card in Mathlib.Data.FinEnum
Polynomial.X in Mathlib.Algebra.Polynomial.Basic
ZMod in Mathlib.Data.ZMod.Defs
BEq in Init.Prelude
DecidableEq in Init.Prelude
Hashable in Init.Prelude
Repr in Init.Data.Repr
Std.HashMap in Std.Data.HashMap.Basic
Std.HashSet in Std.Data.HashSet.Basic
Array in Init.Prelude
List.map in Init.Prelude
Array.foldl in Init.Data.Array.Basic
Std.HashMap.emptyWithCapacity in Std.Data.HashMap.Basic
Array.size in Init.Prelude
List in Init.Prelude
Vector in Init.Data.Vector.Basic
String in Init.Prelude
Unit in Init.Prelude
Field in Mathlib.Algebra.Field.Defs
Int.xor in Mathlib.Data.Int.Bitwise
Inhabited in Init.Prelude
Lean.ToExpr in Lean.ToExpr
Empty in Init.Prelude
Empty.elim in Init.Core
Sum.inr in Init.Core
Sum.inl in Init.Core
Sum in Init.Core
Sum.elim in Init.Data.Sum.Basic
id in Init.Prelude
Fin.castLE in Init.Data.Fin.Basic
cond in Init.Prelude
Nat.testBit in Init.Data.Nat.Bitwise.Basic
Fin.last in Init.Data.Fin.Basic
Array.emptyWithCapacity in Init.Prelude
Prod.mk in Init.Prelude
Array.empty in Init.Prelude
FinEnum.toList in Mathlib.Data.FinEnum
Fintype in Mathlib.Data.Fintype.Defs
BitVec.zero in Init.Data.BitVec.Basic
impl in Mathlib.Deprecated.MLList.BestFirst
atom in Leanwuzla.Sexp.Basic
List.Vector in Mathlib.Data.Vector.Defs
Vector.ofFn in Init.Data.Vector.Basic
Set in Mathlib.Data.Set.Defs
BitVec.ofNat in Init.Prelude
FinEnum.equiv in Mathlib.Data.FinEnum
NFA in Mathlib.Computability.NFA
NFA.accept in Mathlib.Computability.NFA
NFA.start in Mathlib.Computability.NFA
NFA.step in Mathlib.Computability.NFA
NFA.stepSet in Mathlib.Computability.NFA
Subsingleton in Init.Core
reduceDIte in Lean.Meta.Tactic.Simp.BuiltinSimprocs.Core
Language in Mathlib.Computability.Language
BitVec.cons in Init.Data.BitVec.Basic
List.Vector.ofFn in Mathlib.Data.Vector.Defs
List.Vector.replicate in Mathlib.Data.Vector.Defs
List.finRange in Init.Data.List.FinRange
List.reverseRecOn in Mathlib.Data.List.Induction
SetRel in Mathlib.Data.Rel
Array.back? in Init.Data.Array.Basic
Array.isEmpty in Init.Data.Array.Basic
List.next in Mathlib.Data.List.Cycle
L in Archive.Hairer
Fin.mk in Init.Prelude
Fin.cast in Init.Data.Fin.Basic
Fin.castLT in Init.Data.Fin.Basic
Fin.subNat in Init.Data.Fin.Basic
List.Vector.get in Mathlib.Data.Vector.Defs
List.Vector.nil in Mathlib.Data.Vector.Defs
Finset in Mathlib.Data.Finset.Defs
Finset.range in Mathlib.Data.Finset.Range
DFA in Mathlib.Computability.DFA
NFA.toDFA in Mathlib.Computability.NFA
List.range in Init.Data.List.Basic
Eq in Init.Prelude
Fin.natAdd in Init.Data.Fin.Basic
NeZero in Init.Data.NeZero
cmp in Mathlib.Data.Ordering.Basic
BitVec.ofFin in Init.Prelude
BitVec.ule in Init.Data.BitVec.Basic
BitVec.ult in Init.Data.BitVec.Basic
BitVec.sle in Init.Data.BitVec.Basic
BitVec.slt in Init.Data.BitVec.Basic
LawfulBEq in Init.Core
Classical.propDecidable in Init.Classical
Decidable in Init.Prelude
Function.RightInverse in Init.Data.Function

syntax "max" : MLIR.Pretty.uniform_op

syntax "slt" : MLIR.Pretty.uniform_op

syntax "xor" : 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 carry (initCarry : Bool) (x y : BitStream) : BitStream :=
  fun n => (addAux' initCarry x y n).2

def BitStream : Type := Nat → Bool

def addAux' (carryIn : Bool) (x y : BitStream) (i : Nat) :  Bool × Bool :=
  let carryIn : Bool := match i with
    | 0 => carryIn
    | i + 1 => (addAux' carryIn x y i).2
  Prod.swap (BitVec.adcb (x i) (y i) carryIn)

def BitVec.ofFn {w : Nat} (f : Fin w → Bool) : BitVec w :=
  BitVec.iunfoldr (fun i _ => ((), f i)) () |>.2

noncomputable def f : (ZMod q)[X] := X^(2^n) + 1

def worklistRun (final : S → Bool) (inits : Array S)
    (hinits : inits.toList.Nodup) (f : S → Array (BitVec n × S)) : CNFA n :=
  ⟨worklistRun' _ S final inits hinits f, worklistRun'_wf (BitVec n) S⟩

def worklistRun' (final : S → Bool) (inits : Array S) (hinits : inits.toList.Nodup) (f : S → Array (A × S)) : RawCNFA A :=
  let st0 := worklist.initState _ _ inits hinits final
  go st0
where go (st0 : worklist.St A S) : RawCNFA A :=
  if hemp : st0.worklist.isEmpty then st0.m else
  let sa? := st0.worklist.back?
  match heq : sa? with
  | some sa =>
    let wl := st0.worklist.pop
    let st1 := { st0 with worklist := wl,
                          worklist_nodup := by admit /- proof elided -/

structure worklist.St where
  m : RawCNFA A
  map : Std.HashMap S State := ∅
  worklist : Array S := ∅
  worklist_nodup : worklist.toList.Nodup
  worklist_incl : ∀ sa ∈ worklist, sa ∈ map

def worklist.initState (inits : Array S) (hinits : inits.toList.Nodup) (final? : S → Bool) : worklist.St A S :=
  let m := RawCNFA.empty (A := A)
  let mapm := inits.foldl (init := (Std.HashMap.emptyWithCapacity, m)) fun (map, m) sa =>
    let (s, m) := m.newState
    let m := m.addInitial s
    let m := if final? sa then m.addFinal s else m
    (map.insert sa s, m)
  let map := mapm.1
  let m := mapm.2
  let worklist_incl : ∀ sa ∈ inits, sa ∈ map :=

instance RawCNFA.statesFinset (m : RawCNFA A) : Fintype m.states := (Finset.range m.stateMax).fintypeCoeSort

abbrev State := Nat

def RawCNFA.empty : RawCNFA A := {
  stateMax := 0
  initials := ∅
  finals := ∅
  trans := ∅
}

def processOneElem (final : S → Bool) (s : State) (st : worklist.St A S) : A × S → worklist.St A S :=
  fun (a', sa') =>
    let (s', st') := st.addOrCreateState _ _ (final sa') sa'
    let m := st'.m.addTrans a' s s'
    { st' with m }

def worklist.St.addOrCreateState (st : worklist.St A S) (final? : Bool) (sa : S) : State × worklist.St A S :=
  match heq : st.map[sa]? with
  | some s => (s, st)
  | none =>
    let (s, m) := st.m.newState
    let m := if final? then m.addFinal s else m
    let map := st.map.insert sa s
    let worklist := st.worklist.push sa
    have worklist_nodup : worklist.toList.Nodup := by admit /- proof elided -/

structure CNFA (n : Nat) where
  m : RawCNFA (BitVec n)
  wf : m.WF

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 }

def sub (x y : BitStream) : BitStream :=
  fun n => (subAux x y n).1

def subAux (x y : BitStream) : Nat → Bool × Bool
  | 0 => (xor (x 0) (y 0), !(x 0) && y 0)
  | n+1 =>
    let borrow := (subAux x y n).2
    let a := x (n + 1)
    let b := y (n + 1)
    (xor a (xor b borrow), !a && b || ((!(xor a b)) && borrow))

abbrev ofTerm (t : Term) : FSM (Fin t.arity) := termEvalEqFSM t |>.toFSM

inductive Term : Type
| var : Nat → Term
 
| zero : Term
 
| negOne : Term
 
| one : Term
 
| ofNat (n : Nat) : Term
 
| and : Term → Term → Term
 
| or : Term → Term → Term
 
| xor : Term → Term → Term
 
| not : Term → Term
 
| add : Term → Term → Term
 
| sub : Term → Term → Term
 
| neg : Term → Term

| shiftL : Term → Nat → Term

deriving Repr, Inhabited, Lean.ToExpr

def termEvalEqFSM : ∀ (t : Term), FSMTermSolution t
  | ofNat n =>
    { toFSM := FSM.ofNat n,
      good := by admit /- proof elided -/

def or : FSM Bool :=
  { α := Empty,
    initCarry := Empty.elim,
    outputCirc := Circuit.var true (inr true) ||| Circuit.var true (inr false),
    nextStateCirc := fun a => a.elim
  }

def shiftLeft (n : Nat) : FSM Unit :=
  match n with
  | 0 => FSM.id
  | n + 1 => composeUnaryAux (FSM.ls false) (shiftLeft n)

def id : FSM Unit := {
 α := Empty,
 initCarry := Empty.elim,
 outputCirc := Circuit.var true (inr ()),
 nextStateCirc := Empty.elim
}

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

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 -/

def and : FSM Bool :=
  { α := Empty,
    initCarry := Empty.elim,
    nextStateCirc := fun a => a.elim,
    outputCirc := Circuit.var true (inr true) &&& Circuit.var true (inr false),
  }

def xor : FSM Bool :=
  { α := Empty,
    initCarry := Empty.elim,
    outputCirc := Circuit.var true (inr true) ^^^ Circuit.var true (inr false),
    nextStateCirc := Empty.elim
  }

def neg : FSM Unit :=
  { α := Unit,
    i := by admit /- proof elided -/

def composeBinary
    (p : FSM Bool)
    {t₁ t₂ : Term}
    (q₁ : FSMTermSolution t₁)
    (q₂ : FSMTermSolution t₂) :
    FSM (Fin (max t₁.arity t₂.arity)) := composeBinaryAux p q₁.toFSM q₂.toFSM

def composeBinaryAux
    (p : FSM Bool)
    (q₁ : FSM (Fin a₁))
    (q₂ : FSM (Fin a₂)) :
    FSM (Fin (max a₁ a₂)) :=
  p.compose (Fin (max a₁ a₂))
    (λ b => Fin (cond b a₁ a₂))
    (λ b i => Fin.castLE (by admit /- proof elided -/
    ) i)
    (λ b => match b with
      | true => q₁
      | false => q₂)

structure FSMTermSolution (t : Term) extends FSM (Fin t.arity) where
  ( good : t.evalFin = toFSM.eval )

@[simp] def Term.evalFin (t : Term) (vars : Fin (arity t) → BitStream) : BitStream :=
  match t with
  | var n => vars (Fin.last n)
  | zero    => BitStream.zero
  | one     => BitStream.one
  | negOne  => BitStream.negOne
  | ofNat n => BitStream.ofNat n
  | and t₁ t₂ =>
      let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ &&& x₂
  | or t₁ t₂ =>
      let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ ||| x₂
  | xor t₁ t₂ =>
      let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ ^^^ x₂
  | not t     => ~~~(t.evalFin vars)
  | add t₁ t₂ =>
      let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ + x₂
  | sub t₁ t₂ =>
      let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ - x₂
  | neg t       => -(Term.evalFin t vars)
 
 
  | shiftL t n  => BitStream.shiftLeft (Term.evalFin t vars) n

@[simp] def Predicate.evalFin (p : Predicate) (vars : Fin (arity p) → BitStream) : BitStream :=
match p with
| .width .eq n => BitStream.falseIffEq n
| .width .neq n => BitStream.falseIffNeq n
| .width .lt n => BitStream.falseIffLt n
| .width .le n => BitStream.falseIffLe n
| .width .gt n => BitStream.falseIffGt n
| .width .ge n => BitStream.falseIffGe n
| .binary .eq t₁ t₂ =>
    let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
    ) i))
    let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
    ) i))
    Predicate.evalEq x₁ x₂
| .binary .neq t₁ t₂  =>
    let x₁ := t₁.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
    ) i))
    let x₂ := t₂.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
    ) i))
    Predicate.evalNeq x₁ x₂
| .land p q =>
  
  
  let x₁ := p.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  let x₂ := q.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  Predicate.evalLand x₁ x₂
| .lor p q =>
  
  let x₁ := p.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  let x₂ := q.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  Predicate.evalLor x₁ x₂
| .binary .slt p q =>
  let x₁ := p.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  let x₂ := q.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  Predicate.evalSlt x₁ x₂
| .binary .sle p q =>
  let x₁ := p.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  let x₂ := q.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  Predicate.evalLor (Predicate.evalSlt x₁ x₂) (Predicate.evalEq x₁ x₂)
| .binary .ult p q =>
  let x₁ := p.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  let x₂ := q.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  (Predicate.evalUlt x₁ x₂)
| .binary .ule p q =>
  let x₁ := p.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  let x₂ := q.evalFin (fun i => vars (Fin.castLE (by admit /- proof elided -/
  ) i))
  Predicate.evalLor (Predicate.evalUlt x₁ x₂) (Predicate.evalEq x₁ x₂)

def Predicate.evalUlt (t₁ t₂ : BitStream) : BitStream := (~~~ (t₁.borrow t₂)).concat true

def borrow (x y : BitStream) : BitStream :=
  fun n => (subAux x y n).2

def Predicate.evalLor (t₁ t₂ : BitStream) : BitStream := (t₁ &&& t₂)

def Predicate.evalSlt (t₁ t₂ : BitStream) : BitStream :=
    (((Predicate.evalUlt t₁ t₂)) ^^^ (Predicate.evalMsbEq t₁ t₂))

def Predicate.evalMsbEq (t₁ t₂ : BitStream) : BitStream :=
  (t₁ ^^^ t₂).concat false

def Predicate.evalLand (t₁ t₂ : BitStream) : BitStream := (t₁ ||| t₂)

def Predicate.evalNeq (t₁ t₂ : BitStream) : BitStream := (t₁.nxor t₂).concat true |>.scanAnd

def nxor (a b : BitStream) : BitStream := fun i => a i == b i

def scanAnd (s : BitStream) : BitStream := scanl true Bool.and 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 Predicate.evalEq (t₁ t₂ : BitStream) : BitStream := (t₁ ^^^ t₂).concat false |>.scanOr

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

inductive Predicate : Type where
 
| width (wp : WidthPredicate) (n : Nat) : Predicate
| binary (p : BinaryPredicate) (t₁ t₂ : Term)
| land  (p q : Predicate) : Predicate
| lor (p q : Predicate) : Predicate
deriving Repr, Inhabited, Lean.ToExpr

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

abbrev falseIffLt (n : Nat) : BitStream := fun i => decide (i ≥ n)

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

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

abbrev falseIffEq (n : Nat) : BitStream := fun i => decide (i != n)

abbrev falseIffGt (n : Nat) : BitStream := fun i => decide (i ≤ n)

def Term.width (t : Term) : WidthExpr :=
  match t with

| .ofNat w _n => w
  | .var _v w => w
  | .add w _a _b => w
  | .zext _a wnew => wnew
  | .setWidth _a wnew => wnew
  | .sext _a wnew => wnew
  | .bor w _a _b => w
  | .band w _a _b => w
  | .bxor w _a _b => w
  | .bnot w _a => w
  | .boolVar _v => WidthExpr.const 1 
  | .boolConst _b => WidthExpr.const 1
  | .shiftl w _a _k => w
  | .bvOfBool _b => WidthExpr.const 1
  | binWidthRel _k wa wb => WidthExpr.const 0
  | binRel _k w _a _b => w
  | or _p1 _p2 => WidthExpr.const 0
  | and _p1 _p2 => WidthExpr.const 0
  | pvar _v => WidthExpr.const 0
  | boolBinRel _k _a _b => WidthExpr.const 0

@[simp] def Term.arity : Term → Nat
| (var n) => n+1
| zero => 0
| one => 0
| negOne => 0
| ofNat _ => 0
| Term.and t₁ t₂ => max (arity t₁) (arity t₂)
| Term.or t₁ t₂ => max (arity t₁) (arity t₂)
| Term.xor t₁ t₂ => max (arity t₁) (arity t₂)
| Term.not t => arity t
| add t₁ t₂ => max (arity t₁) (arity t₂)
| sub t₁ t₂ => max (arity t₁) (arity t₂)
| neg t => arity t

| shiftL t .. => arity t

abbrev negOne : BitStream := fun _ => true

def shiftLeft (x : BitStream) (k : Nat) : BitStream :=
  fun i => if i < k then false else x (i - k)

def ofNat (x : Nat) : BitStream :=
  Nat.testBit x

abbrev one    : BitStream := (· == 0)

abbrev zero   : BitStream := fun _ => false

def ofNat (n : Nat)  : FSM (Fin 0) :=
  match hn : n with
  | 0 => FSM.zero

| n' + 1 =>
    let bit := n.testBit 0
    let m := n / 2
    have h : m < n := by admit /- proof elided -/

def zero : FSM (Fin 0) :=
  { α := Empty,
    initCarry := Empty.elim,
    nextStateCirc := Empty.elim,
    outputCirc := Circuit.fals
  }

def composeUnary
    (p : FSM Unit)
    {t : Term}
    (q : FSMTermSolution t) :
    FSM (Fin t.arity) := composeUnaryAux p q.toFSM

def one : FSM (Fin 0) :=
  { α := Unit,
    i := by admit /- proof elided -/

def var (n : ℕ) : FSM (Fin (n+1)) :=
  { α := Empty,
    i := by admit /- proof elided -/

def add : FSM Bool :=
  { α := Unit,
    initCarry := λ _ => false,
    nextStateCirc := fun () =>
      Circuit.var true (inr true) &&& Circuit.var true (inr false) |||
      Circuit.var true (inr true) &&& Circuit.var true (inl ()) |||
      Circuit.var true (inr false) &&& Circuit.var true (inl ()),
    outputCirc := Circuit.var true (inr true) ^^^
                  Circuit.var true (inr false) ^^^
                  Circuit.var true (inl ()),
  }

def negOne : FSM (Fin 0) :=
  { α := Empty,
    i := by admit /- proof elided -/

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

def not : FSM Unit :=
  { α := Empty,
    initCarry := Empty.elim,
    nextStateCirc := Empty.elim,
    outputCirc := Circuit.var false (inr ())
  }

def add (x y : BitStream) : BitStream :=
  fun n => (addAux x y n).1

def addAux (x y : BitStream) (i : Nat) :  Bool × Bool :=
  let carryIn : Bool := match i with
    | 0 => false
    | i + 1 => (addAux x y i).2
  Prod.swap (BitVec.adcb (x i) (y i) carryIn)

def neg (x : BitStream) : BitStream :=
  fun n => (negAux x n).1

def negAux (x : BitStream) : Nat → Bool × Bool
  | 0 => (x 0, !(x 0))
  | n+1 =>
    let borrow := (negAux x n).2
    let a := x (n + 1)
    (xor (!a) borrow, !a && borrow)

def CNFA.inter (m1 m2 : CNFA n) : CNFA n := product (fun b1 b2 => b1 && b2) m1 m2

def product (final? : Bool → Bool → Bool) (m₁ m₂ : CNFA n) : CNFA n :=
  worklistRun (m₁.m.states × m₂.m.states) final (product.inits m₁ m₂)
    (by admit /- proof elided -/
    ) f
where final (ss : m₁.m.states × m₂.m.states) := final? (ss.1 ∈ m₁.m.finals) (ss.2 ∈ m₂.m.finals)
      f (ss : m₁.m.states × m₂.m.states) :=
        let (s1, s2) := ss
        (FinEnum.toList (α := BitVec n)).foldl (init := Array.empty) fun as a =>
          product.prodArray' (λ s₁ s₂ ↦ (a, (s₁, s₂)))
            (fun s' => m₁.wf.trans_tgt_lt (s := s1) (a := a)) (fun s' => m₂.wf.trans_tgt_lt (s := s2) (a := a)) as

@[inline]
def product.prodArray' (a : Array γ) :=
  m₁.attachWith _ hm₁ |>.fold (init := a) fun is s1 =>
    m₂.attachWith _ hm₂ |>.fold (init := is) fun is s2 =>
      is.push (f s1 s2)

def product.inits_nodup : inits m₁ m₂ |>.toList.Nodup :=

def product.inits (m₁ m₂ : CNFA n) :=
  product.prodArray Prod.mk @m₁.wf.initials_lt @m₂.wf.initials_lt

@[inline]
def product.prodArray := prodArray' f hm₁ hm₂ (Array.emptyWithCapacity <| m₁.size * m₂.size)

def liftMaxSuccSucc2 (n m : Nat) : Fin (m + 1) → Fin (max n m + 3) :=
  fun k => if _ : k = Fin.last m then max n m + 1 else k.castLE (by admit /- proof elided -/
  )

def liftMaxSuccSucc1 (n m : Nat) : Fin (n + 1) → Fin (max n m + 3) :=
  fun k => if _ : k = Fin.last n then (max n m).cast else k.castLE (by admit /- proof elided -/
  )

def liftLast3 n : Fin 3 → Fin (n + 3)
| 0 => n
| 1 => n + 1
| 2 => Fin.last (n + 2)

inductive Unop
| neg
deriving Repr

inductive RelationOrdering
| lt | le | gt | ge
deriving Repr, Fintype

inductive Relation
| eq
| signed (ord : RelationOrdering)
| unsigned (ord : RelationOrdering)
deriving Repr

inductive WidthPredicate
| eq
| neq
| lt
| le
| gt
| ge
deriving Repr, Inhabited, Lean.ToExpr

inductive Binop
| and | or | impl | equiv
deriving Repr

def liftLast2 n : Fin 2 → Fin (n + 2)
| 0 => n
| 1 => Fin.last (n + 1)

def liftMaxSucc2 (n m : Nat) : Fin (m + 1) → Fin (max n m + 2) :=
  fun k => if _ : k = m then Fin.last (max n m + 1) else k.castLE (by admit /- proof elided -/
  )

def liftMaxSucc1 (n m : Nat) : Fin (n + 1) → Fin (max n m + 2) :=
  fun k => if _ : k = n then Fin.last (max n m) else k.castLE (by admit /- proof elided -/
  )

def liftMax2 (n m : Nat) : Fin m → Fin (max n m) :=
  fun k => k.castLE (by admit /- proof elided -/
  )

def liftExcept2 n : Fin n → Fin (n + 2) :=
  fun k => Fin.castLE (by admit /- proof elided -/
  ) k

@[simp]
def Formula.arity : Formula → Nat
| width _ _ => 0
| atom _ t1 t2 => max t1.arity t2.arity
| msbSet t => t.arity
| unop _ φ => φ.arity
| binop _ φ1 φ2 => max φ1.arity φ2.arity

def liftMax1 (n m : Nat) : Fin n → Fin (max n m) :=
  fun k => k.castLE (by admit /- proof elided -/
  )

inductive Formula : Type
| width : WidthPredicate → Nat → Formula
| atom : Relation → Term → Term → Formula
| msbSet : Term → Formula
| unop : Unop → Formula → Formula
| binop : Binop → Formula → Formula → Formula
deriving Repr

def CNFA.inter_bv_language (m₁ m₂ : CNFA n) :
    m₁.bv_recognizes L₁ →
    m₂.bv_recognizes L₂ →
    (m₁.inter m₂).bv_recognizes (L₁ ∩ L₂) :=

def HashSet.inter [BEq A] [Hashable A] (m1 m2 : Std.HashSet A) : Std.HashSet A :=
  m1.fold (init := ∅) fun mi x => if m2.contains x then mi.insert x else mi

@[simp]
def Formula.language (φ : Formula) : Set (BitVecs φ.arity) :=
  match φ with
  | .width wp n => { bvs | wp.sat bvs.w n }
  | .atom rel t1 t2 =>
    let l1 := t1.language.lift (liftMaxSucc1 (FinEnum.card $ Fin t1.arity) (FinEnum.card $ Fin t2.arity))
    let l2 := t2.language.lift (liftMaxSucc2 (FinEnum.card $ Fin t1.arity) (FinEnum.card $ Fin t2.arity))
    let lrel := rel.language.lift $ liftLast2 (max (FinEnum.card (Fin t1.arity)) (FinEnum.card (Fin t2.arity)))
    let l := lrel ∩ l1 ∩ l2
    l.proj (liftExcept2 _)
  | .unop .neg φ => φ.languageᶜ
  | .binop op φ1 φ2 =>
    let l1 := φ1.language.lift $ liftMax1 φ1.arity φ2.arity
    let l2 := φ2.language.lift $ liftMax2 φ1.arity φ2.arity
    langBinop op l1 l2
  | .msbSet t =>
    let lmsb := langMsb.lift $ fun _ => Fin.last t.arity
    let l' := t.language ∩ lmsb
    l'.proj fun n => n.castLE (by admit /- proof elided -/
    )

@[simp]
def WidthPredicate.sat (wp : WidthPredicate) (w n : Nat) : Bool :=
  match wp with
  | .eq => w = n
  | .neq => w ≠ n
  | .lt => w < n
  | .le => w ≤ n
  | .gt => w > n
  | .ge => w ≥ n

@[simp]
def _root_.Set.proj (f : Fin n → Fin m) (bvs : Set (BitVecs m)) : Set (BitVecs n) :=
  BitVecs.transport f '' bvs

def BitVecs.transport (f : Fin n → Fin m) (bvs : BitVecs m) : BitVecs n :=
  { w := bvs.w, bvs := bvs.bvs.transport f }

def BitVec.transport (f : Fin n2 → Fin n1) (bv : BitVec n1) : BitVec n2 :=
  BitVec.ofFn fun i => bv.getLsbD (f i)

structure BitVecs (n : Nat) where
  w : Nat
  bvs : List.Vector (BitVec w) n

def List.Vector.transport (v : Vector α m) (f : Fin n → Fin m) : Vector α n :=
  Vector.ofFn fun i => v.get (f i)

def BitVecs'.transport (f : Fin n → Fin m) (bvs' : BitVecs' m): BitVecs' n :=
  bvs'.map fun bv => bv.transport f

def Term.language (t : Term) : Set (BitVecs (t.arity + 1)) :=
  { bvs : BitVecs (t.arity + 1) | t.evalFinBV (fun n => bvs.bvs.get n) = bvs.bvs.get t.arity }

@[simp] def Term.evalFinBV (t : Term) (vars : Fin (arity t) → BitVec w) : BitVec w :=
  match t with
  | .var n => vars (Fin.last n)
  | .zero    => BitVec.zero w
  | .one     => 1
  | .negOne  => -1
  | .ofNat n => BitVec.ofNat _ n
  | .and t₁ t₂ =>
      let x₁ := t₁.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ &&& x₂
  | .or t₁ t₂ =>
      let x₁ := t₁.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ ||| x₂
  | .xor t₁ t₂ =>
      let x₁ := t₁.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ ^^^ x₂
  | .not t     => ~~~(t.evalFinBV vars)
  
  | .add t₁ t₂ =>
      let x₁ := t₁.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ + x₂
  | .sub t₁ t₂ =>
      let x₁ := t₁.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      let x₂ := t₂.evalFinBV (fun i => vars (Fin.castLE (by admit /- proof elided -/
      ) i))
      x₁ - x₂
  | .neg t       => -(t.evalFinBV vars)
  | .shiftL a n => (a.evalFinBV vars) <<< n

@[simp]
def _root_.Set.lift (f : Fin n → Fin m) (bvs : Set (BitVecs n)) : Set (BitVecs m) :=
  BitVecs.transport f ⁻¹' bvs

@[simp]
def Formula.sat {w : Nat} (φ : Formula) (ρ : Fin φ.arity → BitVec w) : Prop :=
  match φ with
  | .width wp n => wp.sat w n
  | .atom rel t1 t2 =>
    let bv1 := t1.evalFinBV (fun n => ρ $ Fin.castLE (by admit /- proof elided -/
    ) n)
    let bv2 := t2.evalFinBV (fun n => ρ $ Fin.castLE (by admit /- proof elided -/
    ) n)
    evalRelation rel bv1 bv2
  | .unop .neg φ => ¬ φ.sat ρ
  | .binop op φ1 φ2 =>
    let b1 := φ1.sat (fun n => ρ $ Fin.castLE (by admit /- proof elided -/
    ) n)
    let b2 := φ2.sat (fun n => ρ $ Fin.castLE (by admit /- proof elided -/
    ) n)
    evalBinop op b1 b2
  | .msbSet t => (t.evalFinBV ρ).msb

def evalBinop (op : Binop) (b1 b2 : Prop) : Prop :=
  match op with
  | .and => b1 ∧ b2
  | .or => b1 ∨ b2
  | .impl => b1 → b2
  | .equiv => b1 ↔ b2

def evalRelation (rel : Relation) {w} (bv1 bv2 : BitVec w) : Prop :=
  match rel with
  | .eq => bv1 = bv2
  | .signed .lt => bv1.slt bv2
  | .signed .le => bv1.sle  bv2
  | .signed .gt => bv2.slt bv1
  | .signed .ge => bv2.sle bv1
  | .unsigned .lt => bv1.ult bv2
  | .unsigned .le => bv1.ule bv2
  | .unsigned .gt => bv2.ult bv1
  | .unsigned .ge => bv2.ule bv1

def langBinop (op : Binop) (l1 l2 : Set (BitVecs n)) : Set (BitVecs n) :=
  match op with
  | .and => l1 ∩ l2
  | .or => l1 ∪ l2
  | .impl => l1ᶜ ∪ l2
  | .equiv => (l1ᶜ ∪ l2) ∩ (l2ᶜ ∪ l1)

@[simp]
def Relation.language (rel : Relation) : Set (BitVecs 2) :=
  { bvs | evalRelation rel (bvs.bvs.get 0) (bvs.bvs.get 1) }

structure NFA' (n : Nat) where
  σ : Type
  M : NFA (BitVec n) σ

def eval (x : arity → BitStream) : BitStream :=
  fun n => (p.nextBit (p.carry x n) (fun i => x i n)).2

def nextBit : p.State → (arity → Bool) → p.State × Bool :=
  fun carry inputBits =>
    let input := Sum.elim carry inputBits
    let newState : p.State  := fun (a : p.α) => (p.nextStateCirc a).eval input
    let outBit : Bool       := (p.outputCirc).eval input
    (newState, outBit)

abbrev State : Type := p.α → Bool

def carry (x : arity → BitStream) : ℕ → p.State
  | 0 => p.initCarry
  | n+1 => (p.nextBit (carry x n) (fun i => x i n)).1

def carryBV (x : ar → BitVec w) : p.State :=
  p.carry (fun ar => .ofBitVecSext (x ar)) w

def evalBV {w} (x : ar → BitVec w) : BitVec w :=
  BitVec.ofFn fun k => p.eval (fun ar => .ofBitVecSext (x ar)) k

abbrev ofBitVecSext {w} (x : BitVec w) : BitStream :=
  fun i => if i < w then x.getLsbD i else x.msb

def enc (bvs : BitVecs n) : BitVecs' n :=
  (List.finRange bvs.w).map (fun i =>
    BitVec.ofFn (fun (k : Fin n) => (bvs.bvs.get k)[i]))

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

def accepts (M : NFA' n) : Set (BitVecs n) := dec '' M.accepts'

def accepts' (M : NFA' n) : Set (BitVecs' n) := M.M.accepts

def worklistRun_spec : (worklistRun S final inits hinits f |>.Sim $ nfa' inits final f) :=
  worklistRun'_spec inits final f

def nfa' : NFA' n :=
  { σ := _, M := nfa inits final f }

def nfa : NFA A S where
  start := { sa | sa ∈ inits }
  accept := { sa | final sa }
  step sa a := { sa' | (a, sa') ∈ f sa }

def worklistRun'_spec :
    (worklistRun' A S final inits hinits f |>.Sim $ nfa inits final f) :=

structure StInv (m : RawCNFA A) (map : Std.HashMap S State) where
  wf : m.WF
  map_states : ∀ (sa : S) s, map[sa]? = some s → s ∈ m.states
  map_surj : ∀ s : m.states, ∃ (sa : S), map[sa]? = some s.val
  map_inj : ∀ {s} {sa sa' : S}, map[sa]? = some s → map[sa']? = some s → sa = sa'

def worklist.St.D (st : worklist.St A S) : Set S := st.visited

def worklist.St.visited (st : worklist.St A S) : Set S := { s : S | s ∈ st.map ∧ s ∉ st.worklist }

def worklistGo_spec {st : worklist.St A S} (inv : StInv A S st.m st.map) :
    st.sim inits final f ∅ →
    (worklistRun'.go A S final f st |>.Sim $ nfa inits final f) :=

def worklist.St.rel (st : worklist.St A S) : SetRel State S := {(s, sa) | st.map[sa]? = some s }

def processOneElem_mot (s : State) (sa : S) (n : ℕ) (st : worklist.St A S) : Prop :=
  st.map[sa]? = some s ∧
  sa ∈ st.visited ∧
  StInv A S st.m st.map ∧
  st.sim inits final f  {(sa1, a, sa') | sa1 = sa ∧ ∃ k ≥ n, (f sa)[k]? = some (a, sa') }

abbrev worklist.St.sim {st : worklist.St A S} (T : Set (S × A × S)) :=
  st.m.Simul (nfa inits final f) st.rel st.D T

def RawCNFA.Sim (m : RawCNFA A) (A : NFA A S) := ∃ R, RawCNFA.Simul m A R ⊤ ∅

structure RawCNFA.Simul (m : RawCNFA A) (M : NFA A Q) (R : SetRel State Q) (D : Set Q) (T : Set (Q × A × Q)) where
  accept {s q} : s ~[R] q → (s ∈ m.finals ↔ q ∈ M.accept)
  initial₁ {s} : s ∈ m.initials → ∃ q ∈ M.start, s ~[R] q
  initial₂ {q} : q ∈ M.start → ∃ s ∈ m.initials, s ~[R] q
  trans_match₁ {s s' a q} : s ~[R] q → s' ∈ m.tr s a → ∃ q', q' ∈ M.step q a ∧ s' ~[R] q'
  trans_match₂ {s a q q'} : s ~[R] q → q' ∈ M.step q a → q ∈ D → (q, a, q') ∉ T → ∃ s', s' ∈ m.tr s a ∧ s' ~[R] q'

structure RawCNFA.SimulFun (m : RawCNFA A) (M : NFA A Q) (f : m.states ≃ Q)  where
  accept {q} : ((f.invFun q).val ∈ m.finals ↔ q ∈ M.accept)
  initial {q} : q ∈ M.start ↔ (f.invFun q).val ∈ m.initials
  trans_match {a q q'} : q' ∈ M.step q a ↔ (f.invFun q').val ∈ m.tr (f.invFun q) a

@[inline]
def RawCNFA.tr (m : RawCNFA A) s a := m.trans.getD (s, a) ∅

abbrev R := (ZMod q)[X] ⧸ (Ideal.span {f q n})

def CNFA.Sim (m : CNFA n) (M : NFA' n) :=
  m.m.Sim M.M

def CNFA.bv_recognizes (m : CNFA n) (L : Set (BitVecs n)) :=
  ∃ L', m.recognizes L' ∧ L = dec '' L'

def RawCNFA.recognizes (m : RawCNFA A) (L : Language A) :=
  ∃ (σ : Type) (M : NFA A σ), m.Sim M ∧ M.accepts = L

def CNFA.recognizes (m : CNFA n) (L : Language (BitVec n)) :=
  ∃ (M : NFA' n), m.Sim M ∧ M.M.accepts = L

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

def Valuation.cons {Γ : Ctxt Ty} {t : Ty} (x : toType t) (V : Γ.Valuation) :
    (Γ.cons t).Valuation :=

def CNFA.minimize (m : CNFA n) : CNFA n :=
  let mᵣ := m.reverse.determinize
  mᵣ.reverse.determinize

def CNFA.determinize (m : CNFA n) : CNFA n :=
  worklistRun (BitVec m.m.stateMax)
    (fun ss => ss.any fun n b => b == true && n ∈ m.m.finals)
    (determinize.inits m)
    (by admit /- proof elided -/
    )
    f
where
  f := fun (ss : BitVec m.m.stateMax) =>
        (FinEnum.toList (BitVec n)).foldl (init := Array.empty) fun ts a =>
          let ss' := m.m.transSetBV ss a
          ts.push (a, ss')

def CNFA.determinize.inits (m : CNFA n) : Array (BitVec m.m.stateMax) :=
  #[BitVec.ofFn (fun n => n ∈ m.m.initials)]

def CNFA.reverse (m : CNFA n) : CNFA n :=
  ⟨m.m.reverse, RawCNFA.reverse_spec m.wf |>.1⟩

def RawCNFA.reverse (m : RawCNFA A) : RawCNFA A :=
  let m' := { stateMax := m.stateMax, trans := Std.HashMap.emptyWithCapacity m.trans.size, initials := m.finals, finals := m.initials}
  m.trans.fold (init := m') processState
where
  processState := fun m' (s, a) ss' =>
    ss'.fold (init := m') fun m' s' => m'.addTrans a s' s

def CNFA.toNFA' (m : CNFA n) : NFA' n := ⟨_, m.toNFA⟩

def CNFA.toNFA (m : CNFA n) : NFA (BitVec n) m.m.states where
  start := { s | s.val ∈ m.m.initials }
  accept := { s | s.val ∈ m.m.finals }
  step s₁ a := { s₂ | s₂.val ∈ m.m.tr s₁.val a }

def RawCNFA.states (m : RawCNFA A) : Finset State := Finset.range m.stateMax

def reverse (M : NFA' n) : NFA' n where
  σ := _
  M := M.M.reverse

def CNFA.determinize_spec (m : CNFA n)
  {M : NFA' n} (hsim : m.Sim M) :
    m.determinize.Sim M.determinize :=

private def bv_to_set (bv : BitVec w) : Set State :=
  { s | bv.getLsbD s }

structure _root_.SetRel.set_eq (R : SetRel α β) (A : Set α) (B : Set β) where
  fwd : a ∈ A → ∃ b ∈ B, a ~[R] b
  bwd : b ∈ B → ∃ a ∈ A, a ~[R] b

@[inline]
def RawCNFA.lift (m₁: RawCNFA (BitVec n1)) (f : Fin n1 → Fin n2) : RawCNFA (BitVec n2) :=
  let trans := (List.range m₁.stateMax).foldl (init := ∅) fun m2 s => processState m2 s
  { m₁ with trans }
where

@[inline]
def CNFA.lift (m: CNFA n1) (f : Fin n1 → Fin n2) : CNFA n2 :=
  ⟨m.m.lift f, m.m.lift_wf m.wf⟩

@[inline]
def RawCNFA.proj (m1: RawCNFA (BitVec n1)) (f : Fin n2 → Fin n1) : RawCNFA (BitVec n2) :=
  let trans := m1.trans.keysArray.foldl (init := Std.HashMap.emptyWithCapacity) process
  { m1 with trans }
where

def CNFA.proj_spec (m : CNFA n2) (f : Fin n1 → Fin n2) {M : NFA' n2} :
    m.Sim M → (m.proj f |>.Sim (M.proj f)) :=

@[inline]
def CNFA.proj (m: CNFA n2) (f : Fin n1 → Fin n2) : CNFA n1 :=
  ⟨m.m.proj f, m.m.proj_wf m.wf⟩

def CNFA.neg_spec (m : CNFA n)  {M : NFA' n} (hsim : m.Sim M) :
    m.neg.Sim M.neg :=

def CNFA.neg (m : CNFA n) : CNFA n := m.determinize.flipFinals

def CNFA.flipFinals (m : CNFA n) : CNFA n := ⟨m.m.flipFinals, m.m.flipFinals_wf m.wf⟩

def RawCNFA.flipFinals (m : RawCNFA A) : RawCNFA A :=
  let oldFinals := m.finals
  let newFinals := (List.range m.stateMax).foldl (init := ∅) fun fins s =>
    if oldFinals.contains s then fins else fins.insert s
  { m with finals := newFinals }

def bv2 : BitVec 4 := BitVec.ofNat 4 1

def bv1 : BitVec 4 := BitVec.ofNat 4 5

instance instFinEnumBV : FinEnum (BitVec w) where
  card := 2^w
  equiv := {
    toFun := fun x => x.toFin
    invFun := fun x => BitVec.ofFin x
    left_inv := by admit /- proof elided -/

structure RawCNFA.WF (m : RawCNFA A) where
  initials_lt : ∀ {s}, s ∈ m.initials → s ∈ m.states
  finals_lt : ∀ {s}, s ∈ m.finals → s ∈ m.states
  trans_src_lt : ∀ s_a ∈ m.trans, s_a.1 ∈ m.states
  trans_tgt_lt : s' ∈ m.tr s a → s' ∈ m.states

def CNFA.product_spec (final? : Bool → Bool → Bool) (m1 m2 : CNFA n)
  {M1 : NFA' n} {M2 : NFA' n} :
    m1.Sim M1 →
    m2.Sim M2 →
    (product final? m1 m2).Sim (NFA'.product (to_prop final?) M1 M2) :=

noncomputable def to_prop (f : Bool → Bool → Bool) (p1 p2 : Prop) : Prop :=
  f (@Decidable.decide p1 (Classical.propDecidable _)) (@Decidable.decide p2 (Classical.propDecidable _))

def CNFA.union (m1 m2 : CNFA n) : CNFA n :=
  product (fun b1 b2 => b1 || b2) m1.addSink m2.addSink

@[inline]
def CNFA.addSink (m : CNFA n) : CNFA n := ⟨m.m.addSink, wf_createSink m.wf⟩

@[inline]
def RawCNFA.addSink (m : RawCNFA A) : RawCNFA A := m.createSink.2

noncomputable def complete (M : NFA' n) : NFA' n where
  σ := _
  M := M.M.complete

def RawCNFA.addTrans (m : RawCNFA A) (a : A) (s s' : State) : RawCNFA A :=
  let ns := m.trans.getD (s, a) ∅
  let ns := ns.insert s'
  { m with trans :=  m.trans.insert (s, a) ns }

def RawCNFA.newState (m : RawCNFA A) : State × RawCNFA A :=
  let old := m.stateMax
  let m := { m with stateMax := old + 1 }
  (old, m)

def RawCNFA.addInitial (m : RawCNFA A) (s : State) : RawCNFA A :=
  { m with initials := m.initials.insert s }

@[simp]
def langMsb : Set (BitVecs 1) := { bvs | bvs.bvs.get 0 |>.msb }

def head (x : BitStream) : Bool      := x 0

infixr:67 "::ᵥ" => Valuation.cons

def foo_before := [llvm|
{
^0(%arg2 : i32, %arg3 : i32):
  %0 = llvm.add %arg3, %arg2 overflow<nsw> : i32
  %1 = llvm.mul %0, %arg3 overflow<nsw> : i32
  %2 = llvm.mul %arg3, %arg3 overflow<nsw> : i32
  %3 = llvm.sub %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

@[simp_denote]
def llvm_sub_nsw_lower_riscv_32: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where
  lhs := llvm_sub_nsw_32
  rhs := sub_riscv_32

def dec_mask_commute_neg_i32_before := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(-1 : i32) : i32
  %3 = llvm.sdiv %0, %arg6 : i32
  %4 = llvm.sub %1, %3 : i32
  %5 = llvm.and %3, %4 : i32
  %6 = llvm.add %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def demorgan_and_apint4_before := [llvm|
{
^0(%arg52 : i66, %arg53 : i66):
  %0 = llvm.mlir.constant(-1 : i66) : i66
  %1 = llvm.xor %arg52, %0 : i66
  %2 = llvm.xor %arg53, %0 : i66
  %3 = llvm.and %1, %2 : i66
  "llvm.return"(%3) : (i66) -> ()
}
]

def ashrsgt_03_06_after := [llvm|
{
^0(%arg279 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def scalar_i32_shl_and_signbit_eq_nonzero_after := [llvm|
{
^0(%arg0 : i32, %arg1 : i32):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def main14_after := [llvm|
{
^0(%arg16 : i32):
  %0 = llvm.mlir.constant(32896 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(2 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.and %arg16, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = "llvm.select"(%5, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def test_add_nuw_nsw__nsw_is_safe_before := [llvm|
{
^0(%arg39 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.mlir.constant(0 : i32) : i32
  %4 = llvm.or %arg39, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.add %4, %2 overflow<nsw,nuw> : i32
  %7 = "llvm.select"(%5, %3, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def icmp_slt_0_and_icmp_sge_neg1_i64_fail_after := [llvm|
{
^0(%arg59 : i64):
  %0 = llvm.mlir.constant(-2) : i64
  %1 = llvm.mlir.constant(62) : i64
  %2 = llvm.mlir.constant(1) : i64
  %3 = llvm.mlir.constant(0) : i64
  %4 = llvm.icmp "sgt" %arg59, %0 : i64
  %5 = llvm.lshr %arg59, %1 : i64
  %6 = llvm.and %5, %2 : i64
  %7 = "llvm.select"(%4, %6, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%7) : (i64) -> ()
}
]

def mkTy : MLIR.AST.MLIRType 0 → MLIR.AST.ExceptM HSxComb HSxComb.Ty
  | MLIR.AST.MLIRType.undefined s => do
    match s.splitOn "_" with
    | ["Stream", "BitVec", w] =>
      match w.toNat? with
      | some w' => return .stream (.bitvec w')
      | _ => throw .unsupportedType
    | ["Stream2", "BitVec", w] =>
      match w.toNat? with
      | some w' => return .stream2 (.bitvec w')
      | _ => throw .unsupportedType
    | ["Stream2Token", "BitVec", w] =>
      match w.toNat? with
      | some w' => return .stream2token (.bitvec w')
      | _ => throw .unsupportedType
    | _ => throw .unsupportedType
  | _ => throw .unsupportedType

def PR2539_B_after := [llvm|
{
^0(%arg0 : i1):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def bool_eq0_before := [llvm|
{
^0(%arg33 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.mlir.constant(1) : i64
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "sgt" %arg33, %0 : i64
  %4 = llvm.icmp "eq" %arg33, %1 : i64
  %5 = llvm.icmp "eq" %4, %2 : i1
  %6 = llvm.and %3, %5 : i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def one_side_fold_slt_after := [llvm|
{
^0(%arg33 : i32, %arg34 : i32, %arg35 : i32, %arg36 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.icmp "slt" %arg34, %arg33 : i32
  %2 = "llvm.select"(%arg36, %1, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def rewritePeepholeRecursively (fuel : ℕ)
    (pr : PeepholeRewrite d Γ t) (target : Com d Γ₂ eff t₂) :
    { out : Com d Γ₂ eff t₂ // out.denote = target.denote } :=
  match fuel with
  | 0 => ⟨target, rfl⟩
  | fuel + 1 =>
    let target' := rewritePeephole fuel pr target
    have htarget'_denote_eq_htarget : target'.denote = target.denote := by admit /- proof elided -/

def substitute_constant_and_eq_eq_logical_after := [llvm|
{
^0(%arg320 : i8, %arg321 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "eq" %arg320, %0 : i8
  %3 = llvm.icmp "eq" %arg321, %0 : i8
  %4 = "llvm.select"(%2, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (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 commute_int_constant_to_rhs_mulhu: RISCVPeepholeRewrite [Ty.riscv (.bv)] where
  lhs := [LV| {
    ^entry (%x: !riscv.reg):
      %c = li (1) : !riscv.reg
      %0 = mulhu %c, %x : !riscv.reg
      ret %0 : !riscv.reg
  }]
  rhs := [LV| {
    ^entry (%x: !riscv.reg):
      %c = li (1) : !riscv.reg
      %0 = mulhu %x, %c : !riscv.reg
      ret %0 : !riscv.reg
  }]

def PostLegalizerCombiner_LLVMIR_64 : List (Σ Γ, LLVMPeepholeRewriteRefine 64  Γ) :=
  hoist_logic_op_with_same_opcode_hands_64 ++
  sub_add_reg ++
  integer_reassoc_combines ++
  sub_to_add ++
  select_same_val ++
  matchMulO ++
  LLVMIR_cast_combines_64 ++
  xor_of_and_with_same_reg_list ++
  LLVMIR_identity_combines_64 ++
  match_selects ++
  idempotent_prop

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

def test86_before := [llvm|
{
^0(%arg59 : i16):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.sext %arg59 : i16 to i32
  %2 = llvm.ashr %1, %0 : i32
  %3 = llvm.trunc %2 : i32 to i16
  "llvm.return"(%3) : (i16) -> ()
}
]

def ashrsgt_01_11_after := [llvm|
{
^0(%arg306 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def icmp_eq_sext_eq_otherwise_after := [llvm|
{
^0(%arg15 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.icmp "eq" %arg15, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def not_and_and_or_not_or_or_commute2_or_before := [llvm|
{
^0(%arg247 : i32, %arg248 : i32, %arg249 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg248, %arg249 : i32
  %2 = llvm.or %1, %arg247 : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.xor %arg247, %0 : i32
  %5 = llvm.and %4, %arg248 : i32
  %6 = llvm.and %5, %arg249 : i32
  %7 = llvm.or %6, %3 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def zext_nneg_signbit_extract_after := [llvm|
{
^0(%arg4 : i32):
  %0 = llvm.mlir.constant(0) : i64
  "llvm.return"(%0) : (i64) -> ()
}
]

def test33_before := [llvm|
{
^0(%arg253 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-2 : i32) : i32
  %2 = llvm.and %arg253, %0 : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.and %arg253, %1 : i32
  %5 = llvm.or %4, %3 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

@[simp_denote]
def slt_riscv_i32 :=
  [LV| {
    ^entry (%arg0: i32, %arg1: i32):
    %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64)
    %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64)
    %0 = sext.w %a : !i64
    %1 = sext.w %b : !i64
    %2 = slt %0, %1 : !i64
    %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32)
    llvm.return %3 : i32
  }]

def mul_selectp2_x_non_const_after := [llvm|
{
^0(%arg15 : i8, %arg16 : i1, %arg17 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = "llvm.select"(%arg16, %0, %arg17) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %2 = llvm.shl %arg15, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def shl_add_lshr_comm_before := [llvm|
{
^0(%arg151 : i32, %arg152 : i32, %arg153 : i32):
  %0 = llvm.shl %arg151, %arg152 overflow<nuw> : i32
  %1 = llvm.mul %arg153, %arg153 : i32
  %2 = llvm.add %1, %0 overflow<nuw> : i32
  %3 = llvm.lshr %2, %arg152 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def trunc_shl_32_i32_i64_before := [llvm|
{
^0(%arg32 : i64):
  %0 = llvm.mlir.constant(32) : i64
  %1 = llvm.shl %arg32, %0 : i64
  %2 = llvm.trunc %1 : i64 to i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def mul32_low_after := [llvm|
{
^0(%arg22 : i32, %arg23 : i32):
  %0 = llvm.mul %arg22, %arg23 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

def EnvFin (w : Nat) (n : Nat) := Fin n → (BitVec w)

def slt_zero_eq_i1_signed_after := [llvm|
{
^0(%arg2 : i32, %arg3 : i1):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.icmp "sgt" %arg2, %0 : i32
  %2 = llvm.xor %1, %arg3 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def mkDecideTy : SolverM Expr := do
  let ty ← mkEq (mkNatLit 1) (mkNatLit 1)
  debugCheck ty
  return ty

def andcond_before := [llvm|
{
^0(%arg169 : i1, %arg170 : i1, %arg171 : i8, %arg172 : i8, %arg173 : i8):
  %0 = llvm.mlir.constant(false) : i1
  %1 = "llvm.select"(%arg169, %arg170, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = "llvm.select"(%arg169, %arg171, %arg172) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = "llvm.select"(%1, %arg173, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def trunc_equality_nsw_zext_after := [llvm|
{
^0(%arg16 : i32, %arg17 : i8):
  %0 = llvm.zext %arg17 : i8 to i32
  %1 = llvm.icmp "ne" %arg16, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def ule_or_min_logical_after := [llvm|
{
^0(%arg140 : i8, %arg141 : i8):
  %0 = llvm.icmp "ule" %arg140, %arg141 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

def mul_constant_eq_before := [llvm|
{
^0(%arg140 : i32, %arg141 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mul %arg140, %0 : i32
  %2 = llvm.mul %arg141, %0 : i32
  %3 = llvm.icmp "eq" %1, %2 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

@[simp]
def liftUnop_unchanged' (k : Fin n) : liftUnop n k.castSucc = k.castLE (by simp) :=

def masked_or_allzeroes_before := [llvm|
{
^0(%arg131 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(39 : i32) : i32
  %3 = llvm.and %arg131, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  %5 = llvm.and %arg131, %2 : i32
  %6 = llvm.icmp "eq" %5, %1 : i32
  %7 = llvm.or %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def negative4_before := [llvm|
{
^0(%arg6 : i32, %arg7 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg7, %0 : i32
  %3 = llvm.icmp "ne" %arg6, %2 : i32
  %4 = llvm.icmp "sge" %arg6, %1 : i32
  %5 = llvm.and %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def not_match_inconsistent_values_before := [llvm|
{
^0(%arg12 : i64):
  %0 = llvm.mlir.constant(299) : i64
  %1 = llvm.mlir.constant(29) : i64
  %2 = llvm.mlir.constant(64) : i64
  %3 = llvm.urem %arg12, %0 : i64
  %4 = llvm.udiv %arg12, %1 : i64
  %5 = llvm.urem %4, %2 : i64
  %6 = llvm.mul %5, %0 : i64
  %7 = llvm.add %3, %6 : i64
  "llvm.return"(%7) : (i64) -> ()
}
]

def fold_sext_to_and_wrong_before := [llvm|
{
^0(%arg9 : i8):
  %0 = llvm.mlir.constant(-2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sext %arg9 : i8 to i32
  %3 = llvm.and %2, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

def icmp_ne_sext_slt_otherwise_nofold_after := [llvm|
{
^0(%arg2 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.icmp "slt" %arg2, %0 : i32
  %2 = llvm.sext %1 : i1 to i32
  %3 = llvm.icmp "ne" %arg2, %2 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def function : Parser :=
  leading_parser argumentList >> arrow >> termParser

def sgt_swap_and_min_commute_before := [llvm|
{
^0(%arg340 : i8, %arg341 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.icmp "slt" %arg341, %arg340 : i8
  %2 = llvm.icmp "eq" %arg340, %0 : i8
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def ashrslt_02_02_exact_after := [llvm|
{
^0(%arg35 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def or_or_and_pat3_before := [llvm|
{
^0(%arg66 : i8, %arg67 : i8, %arg68 : i8, %arg69 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.udiv %0, %arg68 : i8
  %2 = llvm.and %arg66, %arg67 : i8
  %3 = llvm.and %arg67, %arg69 : i8
  %4 = llvm.or %1, %3 : i8
  %5 = llvm.or %4, %2 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def not {Γ : Ctxt _} (a : Var Γ (.stream (.bitvec 1))) : Expr (Handshake) Γ .pure (.stream (.bitvec 1))  :=
  Expr.mk
    (op := .not)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

def simplify_or_common_op_commute1_before := [llvm|
{
^0(%arg42 : i4, %arg43 : i4, %arg44 : i4):
  %0 = llvm.mlir.constant(-1 : i4) : i4
  %1 = llvm.and %arg43, %arg42 : i4
  %2 = llvm.and %1, %arg44 : i4
  %3 = llvm.xor %2, %0 : i4
  %4 = llvm.or %3, %arg42 : i4
  "llvm.return"(%4) : (i4) -> ()
}
]

def shl_C1_add_A_C2_i32_after := [llvm|
{
^0(%arg8 : i16):
  %0 = llvm.mlir.constant(192 : i32) : i32
  %1 = llvm.zext nneg %arg8 : i16 to i32
  %2 = llvm.shl %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def test18_before := [llvm|
{
^0(%arg78 : i16, %arg79 : i32):
  %0 = llvm.mlir.constant(4 : i16) : i16
  %1 = llvm.mlir.constant(0 : i16) : i16
  %2 = llvm.mlir.constant(32 : i32) : i32
  %3 = llvm.mlir.constant(64 : i32) : i32
  %4 = llvm.and %arg78, %0 : i16
  %5 = llvm.icmp "ne" %4, %1 : i16
  %6 = "llvm.select"(%5, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = llvm.urem %arg79, %6 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def PR38139_after := [llvm|
{
^0(%arg0 : i8):
  %0 = llvm.mlir.constant(-64 : i8) : i8
  %1 = llvm.icmp "ult" %arg0, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def pv_before := [llvm|
{
^0(%arg14 : i8, %arg15 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.lshr %0, %arg15 : i8
  %2 = llvm.and %1, %arg14 : i8
  %3 = llvm.icmp "uge" %2, %arg14 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def test1_before := [llvm|
{
^0(%arg27 : i32, %arg28 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.icmp "sgt" %arg27, %0 : i32
  %3 = llvm.icmp "slt" %arg28, %1 : i32
  %4 = llvm.xor %3, %2 : i1
  %5 = llvm.zext %4 : i1 to i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def Config.default : Config := {}

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

def and_ne_with_one_bit_diff_constants3_before := [llvm|
{
^0(%arg356 : i8):
  %0 = llvm.mlir.constant(65 : i8) : i8
  %1 = llvm.mlir.constant(-63 : i8) : i8
  %2 = llvm.icmp "ne" %arg356, %0 : i8
  %3 = llvm.icmp "ne" %arg356, %1 : i8
  %4 = llvm.and %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def test6_before := [llvm|
{
^0(%arg204 : i8):
  %0 = llvm.mlir.constant(17 : i8) : i8
  %1 = llvm.xor %arg204, %0 : i8
  %2 = llvm.xor %1, %0 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def lshrugt_01_01_exact_after := [llvm|
{
^0(%arg220 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.icmp "ugt" %arg220, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def Term.Ctx.Env.cons
  {wcard : Nat} {wenv : Fin wcard → Nat}
  {tctx : Term.Ctx wcard tcard}
  (tenv : tctx.Env wenv)
  (wexpr : WidthExpr wcard)
  {w : Nat} (bv : BitVec w)
  (hw : w = wexpr.toNat wenv) :
  Term.Ctx.Env (tctx.cons wexpr) wenv :=
  fun v => v.cases (bv.cast hw) tenv

def trunc_sandwich_small_shift1_before := [llvm|
{
^0(%arg67 : i32):
  %0 = llvm.mlir.constant(19 : i32) : i32
  %1 = llvm.mlir.constant(1 : i12) : i12
  %2 = llvm.lshr %arg67, %0 : i32
  %3 = llvm.trunc %2 : i32 to i12
  %4 = llvm.lshr %3, %1 : i12
  "llvm.return"(%4) : (i12) -> ()
}
]

def and_xor_or8_after := [llvm|
{
^0(%arg652 : i64, %arg653 : i64, %arg654 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.udiv %0, %arg653 : i64
  %2 = llvm.udiv %0, %arg654 : i64
  %3 = llvm.or %1, %2 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def sgt_positive_multip_rem_nz_after := [llvm|
{
^0(%arg168 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.icmp "sgt" %arg168, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def lshr_or_or_no_const_after := [llvm|
{
^0(%arg142 : i8, %arg143 : i8, %arg144 : i8, %arg145 : i8):
  %0 = llvm.or %arg143, %arg142 : i8
  %1 = llvm.lshr %0, %arg144 : i8
  %2 = llvm.or %1, %arg145 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_6_before := [llvm|
{
^0(%arg14 : i32):
  %0 = llvm.mlir.constant(12 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(15 : i32) : i32
  %3 = llvm.mlir.constant(8 : i32) : i32
  %4 = llvm.and %arg14, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.and %arg14, %2 : i32
  %7 = llvm.icmp "ne" %6, %3 : i32
  %8 = llvm.or %7, %5 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def t2_before := [llvm|
{
^0(%arg8 : i64):
  %0 = llvm.mlir.constant(63) : i64
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.ashr %arg8, %0 : i64
  %3 = llvm.trunc %2 : i64 to i32
  %4 = llvm.sub %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def logical_or_cond_reuse_before := [llvm|
{
^0(%arg256 : i1, %arg257 : i1):
  %0 = "llvm.select"(%arg256, %arg256, %arg257) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def HVector.replicateToList {α : Type} {f : α → Type} {a : α} :
    {n : Nat} → HVector f (List.replicate n a) → List (f a)
  | 0, _ => []
  | n + 1, HVector.cons x xs => x :: replicateToList xs


example (op : Comb.Op) : DialectSignature.effectKind (d := HSxComb) (.comb op) = .pure := rfl



example (op : Comb.Op) : DialectSignature.regSig (d := HSxComb) (.comb op) = [] := rfl

def ashrsgt_02_13_exact_after := [llvm|
{
^0(%arg72 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def icmp_ule_after := [llvm|
{
^0(%arg49 : i32, %arg50 : i32):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def positive_sameconst_shlnuwnsw_before := [llvm|
{
^0(%arg46 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.ashr %arg46, %0 : i8
  %2 = llvm.shl %1, %0 overflow<nsw,nuw> : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

def sub_to_xor_or_commuted_after := [llvm|
{
^0(%arg7 : i32, %arg8 : i32):
  %0 = llvm.xor %arg7, %arg8 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def sextinreg_alt_after := [llvm|
{
^0(%arg11 : i32):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.shl %arg11, %0 : i32
  %2 = llvm.ashr exact %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def shl_add_after := [llvm|
{
^0(%arg179 : i8, %arg180 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.mlir.constant(63 : i8) : i8
  %2 = llvm.lshr %arg180, %0 : i8
  %3 = llvm.add %2, %arg179 : i8
  %4 = llvm.and %3, %1 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def and_or_not_not_wrong_b_before := [llvm|
{
^0(%arg328 : i32, %arg329 : i32, %arg330 : i32, %arg331 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg331, %arg328 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.and %arg328, %arg330 : i32
  %4 = llvm.xor %3, %0 : i32
  %5 = llvm.or %4, %arg329 : i32
  %6 = llvm.and %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def bVal : DCOp.ValueStream (BitVec 32) := ofList [none, some 1#32, none, some 2#32, some 5#32]

def test37_before := [llvm|
{
^0(%arg156 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.mlir.constant(512 : i32) : i32
  %2 = llvm.mlir.constant(11 : i8) : i8
  %3 = llvm.lshr %arg156, %0 : i32
  %4 = llvm.or %3, %1 : i32
  %5 = llvm.trunc %4 : i32 to i8
  %6 = llvm.icmp "eq" %5, %2 : i8
  "llvm.return"(%6) : (i1) -> ()
}
]

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

def ashrslt_01_02_exact_before := [llvm|
{
^0(%arg51 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(2 : i4) : i4
  %2 = llvm.ashr exact %arg51, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def IsGoodTermFSM_mkTermFSM (wcard tcard bcard ncard icard pcard : Nat) {tctx : Term.Ctx wcard tcard}
    {wold : WidthExpr wcard}
    (t : Term bcard ncard icard pcard tctx (.bv wold)) :
    (HTermFSMToBitStream (mkTermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm t))) :=

def or_xor_common_op_commute6_before := [llvm|
{
^0(%arg117 : i8, %arg118 : i8, %arg119 : i8):
  %0 = llvm.or %arg117, %arg118 : i8
  %1 = llvm.xor %arg119, %arg117 : i8
  %2 = llvm.or %1, %0 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def runParser (parser : @ParseFun ParseOutput) (fileName : String) : IO (Option ParseOutput) := do
   
  let packagePaths : List String :=
    match (← IO.getEnv "LEAN_PATH") with
    | .none => []
    | .some colonSeparatedPaths => colonSeparatedPaths.splitOn ":"
  if packagePaths.isEmpty then
    throw <| IO.userError ("Expected `LEAN_PATH` environment variable to be set. " ++
    " Are you running via `lake exec opt`?")
  initSearchPath (← Lean.findSysroot) packagePaths
  let modules : Array Import := #[⟨`LeanMLIR.MLIRSyntax.EDSL, false, false, false⟩]
  let env ← importModules (loadExts := true)  modules {}
  let filePath := System.mkFilePath [fileName]
  if !(← isFile filePath) then
    throw <| IO.userError s!"File {fileName} does not exist"
  parseFile env parser filePath

def llvm_const_lower_riscv_li_24 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_24, rhs:= liRiscv_24,
   correct := by admit /- proof elided -/

def dropFirstNone (x : Stream α) : Stream α :=
  if x.head.isNone then
    x.tail
  else
    x

def test_or2_logical_before := [llvm|
{
^0(%arg30 : i32, %arg31 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.mlir.constant(true) : i1
  %3 = llvm.and %arg31, %0 : i32
  %4 = llvm.icmp "sle" %arg30, %1 : i32
  %5 = llvm.icmp "sgt" %arg30, %3 : i32
  %6 = "llvm.select"(%4, %2, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def main5_like_logical_after := [llvm|
{
^0(%arg111 : i32, %arg112 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.and %arg111, %0 : i32
  %3 = llvm.icmp "ne" %2, %0 : i32
  %4 = llvm.and %arg112, %0 : i32
  %5 = llvm.icmp "ne" %4, %0 : i32
  %6 = "llvm.select"(%3, %1, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %7 = llvm.zext %6 : i1 to i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def test15_before := [llvm|
{
^0(%arg284 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.lshr %arg284, %0 : i8
  %3 = llvm.and %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def Vars.state0 (s : σ) {n : Nat} : Vars σ ι n :=
  .state (Inputs.mk ⟨0, by admit /- proof elided -/
  ⟩ s)

def icmp_sle_x_negy_before := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.or %arg29, %0 : i8
  %2 = llvm.and %1, %arg28 : i8
  %3 = llvm.icmp "sle" %2, %arg28 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def and_xor_or1_after := [llvm|
{
^0(%arg673 : i64, %arg674 : i64, %arg675 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.udiv %0, %arg674 : i64
  %2 = llvm.udiv %0, %arg675 : i64
  %3 = llvm.or %2, %1 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def PostLegalizerCombiner_LLVMIR_32 : List (Σ Γ, LLVMPeepholeRewriteRefine 32  Γ) :=
  LLVMIR_identity_combines_32 ++
  LLVMIR_cast_combines_32 ++
  hoist_logic_op_with_same_opcode_hands_32 ++
  LLVMIR_identity_combines_32

def both_before := [llvm|
{
^0(%arg9 : i8, %arg10 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.shl %0, %arg9 : i8
  %2 = llvm.shl %0, %arg10 : i8
  %3 = llvm.icmp "ule" %1, %2 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def test1_after := [llvm|
{
^0(%arg6 : i47, %arg7 : i47):
  %0 = llvm.mlir.constant(-70368744177664 : i47) : i47
  %1 = llvm.mlir.constant(70368744177661 : i47) : i47
  %2 = llvm.and %arg6, %0 : i47
  %3 = llvm.and %arg7, %1 : i47
  %4 = llvm.or disjoint %2, %3 : i47
  "llvm.return"(%4) : (i47) -> ()
}
]

def map {α β : Type} (s : Stream α) (f : α → β) : Stream β :=
  fun i => (s i).map f

def or_or_logic_and_2_after := [llvm|
{
^0(%arg9 : i1, %arg10 : i1, %arg11 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = "llvm.select"(%arg11, %arg10, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = llvm.or %arg9, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

private def attrVal0Str : AttrVal := [mlir_attr_val| "foo"]

def orcond.001.inv.outer.cond_before := [llvm|
{
^0(%arg70 : i1, %arg71 : i1, %arg72 : i1, %arg73 : i1, %arg74 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg70, %0, %arg71) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = "llvm.select"(%arg70, %arg72, %arg73) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = llvm.xor %1, %0 : i1
  %4 = "llvm.select"(%3, %0, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

@[simp_llvm_option]
def freeze (x: IntW w) : IntW w := do
  match x with
  | poison => value (0)
  | value a => value (a)

def or_not_and_and_not_and_xor_commute5_before := [llvm|
{
^0(%arg274 : i32, %arg275 : i32, %arg276 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg275, %arg276 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.or %2, %arg274 : i32
  %4 = llvm.xor %arg275, %arg276 : i32
  %5 = llvm.and %4, %arg274 : i32
  %6 = llvm.xor %5, %0 : i32
  %7 = llvm.and %6, %3 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def bitwise_or_bitwise_or_icmps_comm3_after := [llvm|
{
^0(%arg187 : i8, %arg188 : i8, %arg189 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.icmp "eq" %arg188, %0 : i8
  %3 = llvm.shl %1, %arg189 overflow<nuw> : i8
  %4 = llvm.or %3, %1 : i8
  %5 = llvm.and %arg187, %4 : i8
  %6 = llvm.icmp "ne" %5, %4 : i8
  %7 = llvm.or %6, %2 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

Lean.withImportModules in Lean.Environment

def test59_after := [llvm|
{
^0(%arg122 : i8, %arg123 : i8):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.mlir.constant(48 : i32) : i32
  %2 = llvm.mlir.constant(4 : i8) : i8
  %3 = llvm.zext %arg122 : i8 to i32
  %4 = llvm.shl %3, %0 overflow<nsw,nuw> : i32
  %5 = llvm.and %4, %1 : i32
  %6 = llvm.lshr %arg123, %2 : i8
  %7 = llvm.zext nneg %6 : i8 to i32
  %8 = llvm.or disjoint %5, %7 : i32
  %9 = llvm.zext nneg %8 : i32 to i64
  "llvm.return"(%9) : (i64) -> ()
}
]

def gt_signed_to_large_signed_before := [llvm|
{
^0(%arg40 : i8):
  %0 = llvm.mlir.constant(1024 : i32) : i32
  %1 = llvm.sext %arg40 : i8 to i32
  %2 = llvm.icmp "sgt" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

instance : MLIR.AST.TransformReturn LLVMPlusRiscV 0 where
  mkReturn := mkReturn

abbrev HasBool (d : Dialect) [TyDenote d.Ty] [DialectSignature d] : Type := HasTy d Bool

def icmp_ne_sext_ne_zero_after := [llvm|
{
^0(%arg24 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(-2 : i32) : i32
  %2 = llvm.add %arg24, %0 : i32
  %3 = llvm.icmp "ult" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def or_not_and_after := [llvm|
{
^0(%arg537 : i32, %arg538 : i32, %arg539 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg538, %arg539 : i32
  %2 = llvm.xor %arg537, %0 : i32
  %3 = llvm.and %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def llvm_srl_lower_riscv_exact_64 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := lshr_llvm_exact_64
  rhs := srl_riscv_64

def main14_before := [llvm|
{
^0(%arg16 : i32):
  %0 = llvm.mlir.constant(0 : i16) : i16
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.mlir.constant(2 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.trunc %arg16 : i32 to i16
  %5 = llvm.icmp "sge" %4, %0 : i16
  %6 = llvm.trunc %arg16 : i32 to i8
  %7 = llvm.icmp "sge" %6, %1 : i8
  %8 = llvm.and %5, %7 : i1
  %9 = "llvm.select"(%8, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def t3_ult_sgt_neg1_after := [llvm|
{
^0(%arg69 : i32, %arg70 : i32, %arg71 : i32):
  %0 = llvm.mlir.constant(-16 : i32) : i32
  %1 = llvm.mlir.constant(127 : i32) : i32
  %2 = llvm.icmp "slt" %arg69, %0 : i32
  %3 = llvm.icmp "sgt" %arg69, %1 : i32
  %4 = "llvm.select"(%2, %arg70, %arg69) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %5 = "llvm.select"(%3, %arg71, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

RV64.sexth in RISCV.Instructions

def test_sub_nuw_nsw__none_are_safe_before := [llvm|
{
^0(%arg19 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : i32) : i32
  %2 = llvm.mlir.constant(2147483647 : i32) : i32
  %3 = llvm.icmp "eq" %arg19, %0 : i32
  %4 = llvm.sub %1, %arg19 overflow<nsw,nuw> : i32
  %5 = "llvm.select"(%3, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def test_after := [llvm|
{
^0(%arg0 : i26):
  "llvm.return"(%arg0) : (i26) -> ()
}
]

def smear_set_bit_different_dest_type_wider_dst_after := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(24 : i32) : i32
  %1 = llvm.mlir.constant(31 : i32) : i32
  %2 = llvm.shl %arg0, %0 : i32
  %3 = llvm.ashr %2, %1 : i32
  %4 = llvm.sext %3 : i32 to i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def canonicalize_icmp_sge_2 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant 2 : i64
      %1 = llvm.icmp.sge %c, %x : i64
      llvm.return %1 : i1
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant 2 : i64
      %1 = llvm.icmp.sle %x, %c : i64
      llvm.return %1 : i1
  }]

def smear_sign_and_widen_after := [llvm|
{
^0(%arg169 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.ashr %arg169, %0 : i8
  %2 = llvm.zext %1 : i8 to i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def avg_lsb_before := [llvm|
{
^0(%arg4 : i8, %arg5 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.and %arg4, %0 : i8
  %2 = llvm.and %arg5, %0 : i8
  %3 = llvm.add %2, %1 overflow<nsw,nuw> : i8
  %4 = llvm.lshr %3, %0 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def ashrsgt_01_09_after := [llvm|
{
^0(%arg308 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

@[simp] abbrev Com.pdenote :
    Com d Γ .pure ty → Γ.Valuation → (HVector toType ty) :=
  Com.denote

def ule_umax2_after := [llvm|
{
^0(%arg50 : i32, %arg51 : i32):
  %0 = llvm.icmp "ule" %arg51, %arg50 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

def alive_AddSub_1165_tgt :=
[sllvm| {
^bb0(%a : i64, %b : i64):
  %v1 = llvm.add %a, %b : i64
  %v2 = llvm.mlir.constant 0 : i64
  %v3 = llvm.sub %v2, %a : i64
  %v4 = llvm.mlir.constant 0 : i64
  %v5 = llvm.sub %v4, %b : i64
  %v6 = llvm.mlir.constant 0 : i64
  %v7 = llvm.sub %v6, %v1 : i64
  llvm.return %v7 : i64
}]

def sle_smin2_before := [llvm|
{
^0(%arg53 : i32, %arg54 : i32):
  %0 = llvm.icmp "slt" %arg54, %arg53 : i32
  %1 = "llvm.select"(%0, %arg54, %arg53) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "sle" %1, %arg53 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_2_before := [llvm|
{
^0(%arg90 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(7 : i32) : i32
  %3 = llvm.and %arg90, %0 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %arg90, %2 : i32
  %6 = llvm.icmp "eq" %5, %1 : i32
  %7 = llvm.and %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def mul_add_to_mul_6_before := [llvm|
{
^0(%arg26 : i32, %arg27 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mul %arg26, %arg27 overflow<nsw> : i32
  %2 = llvm.mul %1, %0 overflow<nsw> : i32
  %3 = llvm.add %1, %2 overflow<nsw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def test_add__none_are_safe_after := [llvm|
{
^0(%arg32 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.add %arg32, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def not_cmp_fold : List (Σ Γ, LLVMPeepholeRewriteRefine 1 Γ) :=
  [⟨_, not_cmp_fold_eq⟩,
  ⟨_, not_cmp_fold_ne⟩,
  ⟨_, not_cmp_fold_ge⟩,
  ⟨_, not_cmp_fold_ugt⟩,
  ⟨_, not_cmp_fold_uge⟩,
  ⟨_, not_cmp_fold_sgt⟩,
  ⟨_, not_cmp_fold_sge⟩,
  ⟨_, not_cmp_fold_sge⟩]

def add_positive_high_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := add_positive_high_bound_reject_llvm
  rhs := add_positive_high_bound_reject_riscv

def masked_icmps_mask_notallzeros_bmask_mixed_negated_7_before := [llvm|
{
^0(%arg56 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(15 : i32) : i32
  %3 = llvm.mlir.constant(8 : i32) : i32
  %4 = llvm.and %arg56, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.and %arg56, %2 : i32
  %7 = llvm.icmp "ne" %6, %3 : i32
  %8 = llvm.or %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_2_before := [llvm|
{
^0(%arg90 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(7 : i32) : i32
  %3 = llvm.and %arg90, %0 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %arg90, %2 : i32
  %6 = llvm.icmp "eq" %5, %1 : i32
  %7 = llvm.and %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def zext_ashr_before := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(2 : i16) : i16
  %1 = llvm.zext %arg11 : i8 to i16
  %2 = llvm.ashr %1, %0 : i16
  %3 = llvm.and %2, %1 : i16
  "llvm.return"(%3) : (i16) -> ()
}
]

def sdiv_eq_smin_after := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.icmp "eq" %arg28, %0 : i8
  %3 = llvm.icmp "eq" %arg29, %1 : i8
  %4 = llvm.and %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def ashr_ugt_5_before := [llvm|
{
^0(%arg109 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(5 : i4) : i4
  %2 = llvm.ashr %arg109, %0 : i4
  %3 = llvm.icmp "ugt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def logical_or_not_before := [llvm|
{
^0(%arg260 : i1, %arg261 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg260, %arg261, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%1) : (i1) -> ()
}
]

@[simp_denote]
def slti_llvm_i32 := [LV| {
    ^entry (%a: i32):
    %0 = llvm.mlir.constant (2) : i32
    %1 = llvm.icmp.slt %a, %0 : i32
    %2 = llvm.zext %1 : i1 to i32
    llvm.return %2 : i32
  }]

def ne_nsw_rem_nz_after := [llvm|
{
^0(%arg157 : i8):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

RV64.sh2adduw in RISCV.Instructions

def add_nosignbit_shl_before := [llvm|
{
^0(%arg16 : i32):
  %0 = llvm.mlir.constant(2147418112 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.add %arg16, %0 : i32
  %3 = llvm.shl %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def exampleFstVal := [DCxComb_com| {
  ^entry(%0: !ValueTokenStream_8):
    %src = "DCxComb.fstVal" (%0) : (!ValueTokenStream_8) -> (!ValueStream_8)
    "return" (%src) : (!ValueStream_8) -> ()
  }]

def trunc_sandwich_after := [llvm|
{
^0(%arg70 : i32):
  %0 = llvm.mlir.constant(30 : i32) : i32
  %1 = llvm.lshr %arg70, %0 : i32
  %2 = llvm.trunc %1 overflow<nsw,nuw> : i32 to i12
  "llvm.return"(%2) : (i12) -> ()
}
]

def ashrsgt_01_11_exact_after := [llvm|
{
^0(%arg90 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def or_or_and_pat3_after := [llvm|
{
^0(%arg66 : i8, %arg67 : i8, %arg68 : i8, %arg69 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.udiv %0, %arg68 : i8
  %2 = llvm.or %arg69, %arg66 : i8
  %3 = llvm.and %arg67, %2 : i8
  %4 = llvm.or %1, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def Factor.numVars : Factor → Nat
| .var n => n+1
| .and x y | .or x y | xor x y => max (x.numVars) (y.numVars)
| .not x => x.numVars

def llvm_trunc_riscv_64_to_32_nuw_nsw : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 64)] :=
  {lhs:= trunc_llvm_64_to_32_nsw_nuw, rhs:= trunc_riscv_to_32_nsw_nuw}

def ashrsgt_02_07_before := [llvm|
{
^0(%arg294 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.mlir.constant(7 : i4) : i4
  %2 = llvm.ashr %arg294, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def lshrult_02_10_exact_after := [llvm|
{
^0(%arg123 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test8_after := [llvm|
{
^0(%arg1 : i128):
  %0 = llvm.mlir.constant(170141183460469231731687303715884105600 : i128) : i128
  %1 = llvm.xor %arg1, %0 : i128
  "llvm.return"(%1) : (i128) -> ()
}
]

def LLVMIR_identity_combines_32 : List (Σ Γ, LLVMPeepholeRewriteRefine 32 Γ) := anyext_trunc_fold

def llvm_const_lower_riscv_li_30 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_30, rhs:= liRiscv_30,
   correct := by admit /- proof elided -/

def ashrsgt_03_00_exact_after := [llvm|
{
^0(%arg69 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def shl_nuw_eq_0_before := [llvm|
{
^0(%arg34 : i8, %arg35 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.shl %arg34, %arg35 overflow<nuw> : i8
  %2 = llvm.icmp "eq" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def no_shift_xor_multiuse_cmp_xor_before := [llvm|
{
^0(%arg44 : i32, %arg45 : i32, %arg46 : i32, %arg47 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg44, %0 : i32
  %3 = llvm.icmp "ne" %1, %2 : i32
  %4 = llvm.xor %arg45, %0 : i32
  %5 = "llvm.select"(%3, %arg45, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = "llvm.select"(%3, %arg46, %arg47) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = llvm.mul %5, %6 : i32
  %8 = llvm.mul %7, %4 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

def t1_otherbitwidth_before := [llvm|
{
^0(%arg11 : i16):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.shl %arg11, %0 : i16
  %2 = llvm.ashr %1, %0 : i16
  "llvm.return"(%2) : (i16) -> ()
}
]

def icmp_eq_and_pow2_shl1_before := [llvm|
{
^0(%arg69 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.shl %0, %arg69 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.icmp "eq" %4, %2 : i32
  %6 = llvm.zext %5 : i1 to i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def ashr_lshr_exact_ashr_only_after := [llvm|
{
^0(%arg133 : i32, %arg134 : i32):
  %0 = llvm.ashr %arg133, %arg134 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def t0_before := [llvm|
{
^0(%arg18 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.shl %0, %arg18 : i8
  %3 = llvm.add %2, %1 : i8
  %4 = llvm.or %3, %2 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def test17_after := [llvm|
{
^0(%arg17 : i8):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def n10_before := [llvm|
{
^0(%arg0 : i64):
  %0 = llvm.mlir.constant(63) : i64
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.lshr %arg0, %0 : i64
  %3 = llvm.trunc %2 : i64 to i32
  %4 = llvm.sub %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def ashrsgt_01_10_after := [llvm|
{
^0(%arg307 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def sgt_and_min_before := [llvm|
{
^0(%arg352 : i9, %arg353 : i9):
  %0 = llvm.mlir.constant(-256 : i9) : i9
  %1 = llvm.icmp "sgt" %arg352, %arg353 : i9
  %2 = llvm.icmp "eq" %arg352, %0 : i9
  %3 = llvm.and %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def fix : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1)] where
  lhs:= original
  rhs:= optimized_correct
  correct := by admit /- proof elided -/

def sel_sext_constants_before := [llvm|
{
^0(%arg97 : i1):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(42 : i8) : i8
  %2 = "llvm.select"(%arg97, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.sext %2 : i8 to i16
  "llvm.return"(%3) : (i16) -> ()
}
]

def select_icmp_ne_0_and_32_or_4096_before := [llvm|
{
^0(%arg203 : i32, %arg204 : i32):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(4096 : i32) : i32
  %3 = llvm.and %arg203, %0 : i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  %5 = llvm.or %arg204, %2 : i32
  %6 = "llvm.select"(%4, %arg204, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

@[simp_denote]
def add_shl_sext_riscv := [LV| {
    ^entry (%a: i32):
    %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64)
    %0 = addi %a0, 3 : !i64
    %1 = sllw %0, %a0 : !i64
    %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64)
    llvm.return %2 : i64
  }]

def sub_from_constant_after := [llvm|
{
^0(%arg6 : i5, %arg7 : i5):
  %0 = llvm.mlir.constant(10 : i5) : i5
  %1 = llvm.sub %arg7, %arg6 : i5
  %2 = llvm.add %1, %0 : i5
  "llvm.return"(%2) : (i5) -> ()
}
]

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

def test_invalid_simplify_select_1_before := [llvm|
{
^0(%arg206 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.icmp "eq" %arg206, %0 : i8
  %3 = llvm.sub %arg206, %1 : i8
  %4 = "llvm.select"(%2, %1, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def main7c_before := [llvm|
{
^0(%arg72 : i32, %arg73 : i32, %arg74 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.mul %arg74, %0 : i32
  %4 = llvm.and %arg73, %arg72 : i32
  %5 = llvm.icmp "eq" %arg73, %4 : i32
  %6 = llvm.and %3, %arg72 : i32
  %7 = llvm.icmp "eq" %3, %6 : i32
  %8 = llvm.and %5, %7 : i1
  %9 = "llvm.select"(%8, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def test29_after := [llvm|
{
^0(%arg166 : i32, %arg167 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.or %arg167, %arg166 : i32
  %2 = llvm.and %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def shl_match : List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) := [
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_nuw_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nuw_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_nuw_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nuw_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_nuw_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nuw_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nsw_nuw_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_shl_lower_riscv_nuw_64)
]

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

def slt_or_not_max_logical_before := [llvm|
{
^0(%arg60 : i8, %arg61 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "slt" %arg60, %arg61 : i8
  %3 = llvm.icmp "ne" %arg60, %0 : i8
  %4 = "llvm.select"(%2, %1, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def scalar_i32_shl_and_signbit_slt_before := [llvm|
{
^0(%arg2 : i32, %arg3 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %arg2, %arg3 : i32
  %3 = llvm.and %2, %0 : i32
  %4 = llvm.icmp "slt" %3, %1 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

inductive SubstitutionValue (genExpr : Nat → Type) where
| genExpr {w} (genExpr : genExpr w)
| packedBV  (bv: BVExpr.PackedBitVec)

def test3_after := [llvm|
{
^0(%arg119 : i32):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.and %arg119, %0 : i32
  %3 = llvm.or disjoint %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

class HydrableGeneralize (parsedExpr : Type) (genPred : outParam Type) (genExpr : outParam (Nat → Type)) extends
  HydrableInitialParserState,
  HydrableExistsForall parsedExpr  genPred genExpr,
  HydrableChangePredWidth genPred,
  HydrableReduceWidth parsedExpr genPred genExpr,
  HydrableSynthesizeWithNoPrecondition parsedExpr genPred genExpr,
  HydrableCheckForPreconditions parsedExpr genPred genExpr
  where

def sle_and_min_logical_before := [llvm|
{
^0(%arg220 : i8, %arg221 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "sle" %arg220, %arg221 : i8
  %3 = llvm.icmp "eq" %arg220, %0 : i8
  %4 = "llvm.select"(%2, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

private def attrVal8Alias : AttrVal := [mlir_attr_val| #"A" ]

def icmp_sle10_after := [llvm|
{
^0(%arg3 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "slt" %arg3, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def t3_exact_before := [llvm|
{
^0(%arg7 : i64):
  %0 = llvm.mlir.constant(63) : i64
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.ashr exact %arg7, %0 : i64
  %3 = llvm.trunc %2 : i64 to i32
  %4 = llvm.sub %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

instance : ToString DCOp.TokenStream where
  toString s := toString (Stream.toList 100 s)

def test2_before := [llvm|
{
^0(%arg24 : i32, %arg25 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.icmp "sgt" %arg24, %0 : i32
  %2 = llvm.icmp "sgt" %arg25, %0 : i32
  %3 = llvm.or %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def canonicalize_icmp_sgt_neg4 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant -4 : i64
      %1 = llvm.icmp.sgt %c, %x : i64
      llvm.return %1 : i1
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant -4 : i64
      %1 = llvm.icmp.slt %x, %c : i64
      llvm.return %1 : i1
  }]

def and_or_not_not_before := [llvm|
{
^0(%arg375 : i32, %arg376 : i32, %arg377 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg376, %arg375 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.and %arg375, %arg377 : i32
  %4 = llvm.xor %3, %0 : i32
  %5 = llvm.or %4, %arg376 : i32
  %6 = llvm.and %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def scalar_i32_shl_and_signbit_eq_after := [llvm|
{
^0(%arg31 : i32, %arg32 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.shl %arg31, %arg32 : i32
  %2 = llvm.icmp "sgt" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def icmp_mul_nsw_slt_neg_before := [llvm|
{
^0(%arg11 : i8, %arg12 : i8):
  %0 = llvm.mlir.constant(-7 : i8) : i8
  %1 = llvm.mul %arg11, %0 overflow<nsw> : i8
  %2 = llvm.mul %arg12, %0 overflow<nsw> : i8
  %3 = llvm.icmp "slt" %1, %2 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def eq_210_after := [llvm|
{
^0(%arg128 : i32, %arg129 : i32):
  %0 = llvm.trunc %arg128 : i32 to i24
  %1 = llvm.trunc %arg129 : i32 to i24
  %2 = llvm.icmp "eq" %0, %1 : i24
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def add_nsw_poison_constant_fold_after := [llvm|
{
^0(%arg2 : i1, %arg3 : i8):
  %0 = llvm.mlir.constant(64 : i8) : i8
  %1 = llvm.mlir.constant(-127 : i8) : i8
  %2 = llvm.add %arg3, %0 overflow<nsw> : i8
  %3 = "llvm.select"(%arg2, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def test_mul_one_lhs_LHS := [mod_arith q, hq| {
  ^bb0(%x : !R):
    %one = mod_arith.constant 1 : !R
    %mul = mod_arith.mul %one, %x : !R
    return %mul : !R
}]

def trunc_shl_ashr_infloop_before := [llvm|
{
^0(%arg21 : i64):
  %0 = llvm.mlir.constant(3) : i64
  %1 = llvm.mlir.constant(2) : i64
  %2 = llvm.ashr %arg21, %0 : i64
  %3 = llvm.shl %2, %1 : i64
  %4 = llvm.trunc %3 : i64 to i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test_or_eq_a_b_after := [llvm|
{
^0(%arg36 : i1, %arg37 : i8, %arg38 : i8):
  %0 = "llvm.select"(%arg36, %arg37, %arg38) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%0) : (i8) -> ()
}
]

def samesign_commute2_after := [llvm|
{
^0(%arg123 : i32, %arg124 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg123, %arg124 : i32
  %2 = llvm.icmp "sgt" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def ashrsgt_03_11_exact_before := [llvm|
{
^0(%arg58 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(-5 : i4) : i4
  %2 = llvm.ashr exact %arg58, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def and_two_ranges_to_mask_and_range_no_add_on_one_range_before := [llvm|
{
^0(%arg249 : i16):
  %0 = llvm.mlir.constant(12 : i16) : i16
  %1 = llvm.mlir.constant(16 : i16) : i16
  %2 = llvm.mlir.constant(28 : i16) : i16
  %3 = llvm.icmp "uge" %arg249, %0 : i16
  %4 = llvm.icmp "ult" %arg249, %1 : i16
  %5 = llvm.icmp "uge" %arg249, %2 : i16
  %6 = llvm.or %4, %5 : i1
  %7 = llvm.and %3, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def elabDefSignatureFor (dialect : Term) (alts : TSyntax ``matchAltsSig) : CommandElabM Unit := do
  let msg := (return m!"{exceptEmoji ·} Defining operation signature for {dialect} dialect")
  withTraceNode `LeanMLIR.Elab msg (collapsed := false) <| do
    let alts := getMatchAlts alts
    let alts ← do
      alts.mapM fun view => do
        trace[LeanMLIR.Elab] m!"Parsing match alternative with\n\
          \tpatterns: {view.patterns}\n\
          \tsignature: {view.rhs}"
        let rhs ← parseSignature view.rhs
        return { view with rhs }

    |

def urem_common_divisor_after := [llvm|
{
^0(%arg61 : i1, %arg62 : i5, %arg63 : i5, %arg64 : i5):
  %0 = "llvm.select"(%arg61, %arg64, %arg63) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i5, i5) -> i5
  %1 = llvm.urem %0, %arg62 : i5
  "llvm.return"(%1) : (i5) -> ()
}
]

def lor_band_left1_after := [llvm|
{
^0(%arg74 : i1, %arg75 : i1):
  "llvm.return"(%arg74) : (i1) -> ()
}
]

def nonexact_lshr_eq_noexactdiv_after := [llvm|
{
^0(%arg142 : i8):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def llvm_sub_self_ex := [LV| {
  ^entry (%x: i64 ):
    %1 = llvm.sub %x, %x : i64
    llvm.return %1 : i64
  }]

def udiv400_before := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(100 : i32) : i32
  %2 = llvm.lshr %arg5, %0 : i32
  %3 = llvm.udiv %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def test19a_after := [llvm|
{
^0(%arg13 : i39):
  %0 = llvm.mlir.constant(-5 : i39) : i39
  %1 = llvm.icmp "ugt" %arg13, %0 : i39
  "llvm.return"(%1) : (i1) -> ()
}
]

def or_ranges_single_elem_right_before := [llvm|
{
^0(%arg258 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.mlir.constant(11 : i8) : i8
  %3 = llvm.icmp "uge" %arg258, %0 : i8
  %4 = llvm.icmp "ule" %arg258, %1 : i8
  %5 = llvm.and %3, %4 : i1
  %6 = llvm.icmp "eq" %arg258, %2 : i8
  %7 = llvm.or %5, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def test5_before := [llvm|
{
^0(%arg95 : i32, %arg96 : i8):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.zext %arg96 : i8 to i32
  %2 = llvm.shl %0, %1 : i32
  %3 = llvm.urem %arg95, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def ashrslt_03_09_before := [llvm|
{
^0(%arg228 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(-7 : i4) : i4
  %2 = llvm.ashr %arg228, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def visitSUB_X0 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant (0) : i64
      %0 = llvm.sub %x, %c : i64
      llvm.return %0 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      llvm.return %x : i64
  }]

def masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_logical_after := [llvm|
{
^0(%arg9 : i32):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def BitVec.outputToString : Option (BitVec w) → String
| .none => "poison"
| .some bv =>
    let iv := BitVec.toInt bv
    if w == 1
    then
      if iv == 0 then "false"
      else if iv == -1 then "true"
      else "<unk_i1>"
    else toString iv

def ashr_ult_noexact_after := [llvm|
{
^0(%arg159 : i8):
  %0 = llvm.mlir.constant(80 : i8) : i8
  %1 = llvm.icmp "ult" %arg159, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def canonicalize_logic_first_and0_before := [llvm|
{
^0(%arg28 : i8):
  %0 = llvm.mlir.constant(48 : i8) : i8
  %1 = llvm.mlir.constant(-10 : i8) : i8
  %2 = llvm.add %arg28, %0 : i8
  %3 = llvm.and %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

def test7_after := [llvm|
{
^0(%arg19 : i32):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def exact_ashr_ne_exactdiv_before := [llvm|
{
^0(%arg147 : i8):
  %0 = llvm.mlir.constant(-80 : i8) : i8
  %1 = llvm.mlir.constant(-5 : i8) : i8
  %2 = llvm.ashr exact %0, %arg147 : i8
  %3 = llvm.icmp "ne" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def ne_smax4_before := [llvm|
{
^0(%arg41 : i32, %arg42 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.add %arg41, %0 : i32
  %2 = llvm.icmp "sgt" %arg42, %1 : i32
  %3 = "llvm.select"(%2, %arg42, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

def map (f : Ty₁ → Ty₂) : Ctxt Ty₁ → Ctxt Ty₂ :=
  ofList ∘ (List.map f) ∘ toList

def n14_trunc_of_lshr_after := [llvm|
{
^0(%arg4 : i64, %arg5 : i32, %arg6 : i32):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.sub %0, %arg6 : i32
  %4 = llvm.zext nneg %3 : i32 to i64
  %5 = llvm.lshr %arg4, %4 : i64
  %6 = llvm.trunc %5 : i64 to i32
  %7 = llvm.add %arg6, %1 : i32
  %8 = llvm.shl %arg5, %7 : i32
  %9 = llvm.and %8, %6 : i32
  %10 = llvm.icmp "ne" %9, %2 : i32
  "llvm.return"(%10) : (i1) -> ()
}
]

instance [inst : Cli.ParseableType τ] {n : ℕ} : Cli.ParseableType (List.Vector τ n) where
  name := s!"Vector ({inst.name}) {n}"
  parse? str := do
    let arr : Array τ ← Cli.ParseableType.parse? str
    if h : arr.size = n then
      return h ▸ Vector.ofArray arr
    else
      none

def llvm_trunc_riscv_32_to_16 : LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 32)] :=
  {lhs:=  trunc_llvm_32_to_16, rhs:= trunc_riscv_32_to_16
  }

def test2_after := [llvm|
{
^0(%arg25 : i47):
  "llvm.return"(%arg25) : (i47) -> ()
}
]

def rotateleft_9_neg_mask_wide_amount_commute_before := [llvm|
{
^0(%arg29 : i9, %arg30 : i33):
  %0 = llvm.mlir.constant(0 : i33) : i33
  %1 = llvm.mlir.constant(8 : i33) : i33
  %2 = llvm.sub %0, %arg30 : i33
  %3 = llvm.and %arg30, %1 : i33
  %4 = llvm.and %2, %1 : i33
  %5 = llvm.zext %arg29 : i9 to i33
  %6 = llvm.shl %5, %3 : i33
  %7 = llvm.lshr %5, %4 : i33
  %8 = llvm.or %6, %7 : i33
  %9 = llvm.trunc %8 : i33 to i9
  "llvm.return"(%9) : (i9) -> ()
}
]

def ashr_lshr_exact_lshr_only_before := [llvm|
{
^0(%arg127 : i32, %arg128 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.icmp "sgt" %arg127, %0 : i32
  %2 = llvm.lshr exact %arg127, %arg128 : i32
  %3 = llvm.ashr %arg127, %arg128 : i32
  %4 = "llvm.select"(%1, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def srai_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := srai_llvm_i32
  rhs := srai_riscv_i32

def and_or_not_not_commute2_after := [llvm|
{
^0(%arg369 : i32, %arg370 : i32, %arg371 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg371, %arg370 : i32
  %2 = llvm.and %1, %arg369 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

@[simp_denote]
def constLLVM0_1bit : Com LLVMPlusRiscV ⟨[]⟩ .pure (.llvm (.bitvec 1)) := [LV| {
  ^entry ():
    %1 = llvm.mlir.constant (0) : i1
    llvm.return %1 : i1
  }]

def lshr_sub_before := [llvm|
{
^0(%arg77 : i8, %arg78 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(3 : i8) : i8
  %2 = llvm.srem %arg77, %0 : i8
  %3 = llvm.lshr %arg78, %1 : i8
  %4 = llvm.sub %2, %3 : i8
  %5 = llvm.shl %4, %1 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def alive_AndOrXor_716_tgt :=
[sllvm| {
^bb0(%a : i64, %b : i64, %d : i64):
  %v1 = llvm.and %b, %d : i64
  %v2 = llvm.and %a, %v1 : i64
  %v3 = llvm.and %a, %b : i64
  %v4 = llvm.and %a, %d : i64
  %v5 = llvm.icmp.eq %v3, %a : i64
  %v6 = llvm.icmp.eq %v4, %a : i64
  %v7 = llvm.icmp.eq %v2, %a : i64
  llvm.return %v7 : i1
}]

def low_bitmask_ult_after := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "ne" %arg11, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def shl_mask_wrong_shl_const_after := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.mlir.constant(7 : i32) : i32
  %2 = llvm.and %arg5, %0 : i32
  %3 = llvm.shl %2, %1 overflow<nsw,nuw> : i32
  %4 = llvm.or %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def sub_to_xor_before := [llvm|
{
^0(%arg14 : i32, %arg15 : i32):
  %0 = llvm.or %arg14, %arg15 : i32
  %1 = llvm.and %arg14, %arg15 : i32
  %2 = llvm.sub %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def icmp_equality_test_commute_icmp2_after := [llvm|
{
^0(%arg20 : i64, %arg21 : i64, %arg22 : i64):
  %0 = llvm.icmp "eq" %arg21, %arg20 : i64
  "llvm.return"(%0) : (i1) -> ()
}
]

def test32_before := [llvm|
{
^0(%arg254 : i32):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.and %arg254, %0 : i32
  %4 = llvm.lshr %3, %1 : i32
  %5 = llvm.and %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def mul128_low_before := [llvm|
{
^0(%arg18 : i128, %arg19 : i128):
  %0 = llvm.mlir.constant(18446744073709551615 : i128) : i128
  %1 = llvm.mlir.constant(64 : i128) : i128
  %2 = llvm.and %arg18, %0 : i128
  %3 = llvm.lshr %arg18, %1 : i128
  %4 = llvm.and %arg19, %0 : i128
  %5 = llvm.lshr %arg19, %1 : i128
  %6 = llvm.mul %5, %2 : i128
  %7 = llvm.mul %4, %3 : i128
  %8 = llvm.mul %4, %2 : i128
  %9 = llvm.add %6, %7 : i128
  %10 = llvm.shl %9, %1 : i128
  %11 = llvm.add %10, %8 : i128
  "llvm.return"(%11) : (i128) -> ()
}
]

def ashrsgt_03_03_exact_before := [llvm|
{
^0(%arg66 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.ashr exact %arg66, %0 : i4
  %2 = llvm.icmp "sgt" %1, %0 : i4
  "llvm.return"(%2) : (i1) -> ()
}
]

def ashr_ule_noexact_before := [llvm|
{
^0(%arg158 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.ashr %arg158, %0 : i8
  %3 = llvm.icmp "ule" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def compReg (input : Stream α) (initialValue : α) : Stream α :=
  Stream.corec (β := Stream α × Option α × Option α)
    (input, none,  some initialValue) fun (input, store, init) =>
  match init with
  | some initVal  => (initVal, input.tail, input.head, none)
  | _ => (store, input.tail, input.head, none)

def logic_and_logic_or_6_before := [llvm|
{
^0(%arg162 : i1, %arg163 : i1, %arg164 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg163, %arg162, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = "llvm.select"(%arg162, %arg164, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def sgt_mulzero_before := [llvm|
{
^0(%arg144 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(21 : i8) : i8
  %2 = llvm.mul %arg144, %0 overflow<nsw> : i8
  %3 = llvm.icmp "sgt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def n1_after := [llvm|
{
^0(%arg7 : i8, %arg8 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.shl %0, %arg8 overflow<nsw> : i8
  %3 = llvm.xor %2, %1 : i8
  %4 = llvm.icmp "ult" %3, %arg7 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def ugt_umax2_before := [llvm|
{
^0(%arg34 : i32, %arg35 : i32):
  %0 = llvm.icmp "ugt" %arg35, %arg34 : i32
  %1 = "llvm.select"(%0, %arg35, %arg34) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "ugt" %1, %arg34 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def xor_lshr_before := [llvm|
{
^0(%arg624 : i8, %arg625 : i8, %arg626 : i8, %arg627 : i8):
  %0 = llvm.lshr %arg624, %arg627 : i8
  %1 = llvm.lshr %arg625, %arg627 : i8
  %2 = llvm.xor %0, %arg626 : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

def main4c_before := [llvm|
{
^0(%arg124 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(48 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.and %arg124, %0 : i32
  %5 = llvm.icmp "ne" %4, %0 : i32
  %6 = llvm.and %arg124, %1 : i32
  %7 = llvm.icmp "ne" %6, %1 : i32
  %8 = llvm.or %5, %7 : i1
  %9 = "llvm.select"(%8, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def test_and4_logical_after := [llvm|
{
^0(%arg38 : i32, %arg39 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.and %arg39, %0 : i32
  %2 = llvm.icmp "ule" %arg38, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def eq_umin2_after := [llvm|
{
^0(%arg58 : i32, %arg59 : i32):
  %0 = llvm.icmp "ule" %arg58, %arg59 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

def t3_c0_after := [llvm|
{
^0(%arg25 : i8, %arg26 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.add %arg25, %arg26 : i8
  %2 = llvm.sub %0, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def PR42691_3_logical_after := [llvm|
{
^0(%arg338 : i32):
  %0 = llvm.mlir.constant(-2147483647 : i32) : i32
  %1 = llvm.icmp "ult" %arg338, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def test15a_after := [llvm|
{
^0(%arg27 : i32):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.and %arg27, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def lshrugt_02_04_after := [llvm|
{
^0(%arg395 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_negated_3_after := [llvm|
{
^0(%arg66 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.and %arg66, %0 : i32
  %3 = llvm.icmp "ne" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def negation_of_increment_via_or_disjoint_after := [llvm|
{
^0(%arg81 : i8, %arg82 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg82, %0 : i8
  %2 = llvm.add %arg81, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def ashrslt_01_15_exact_before := [llvm|
{
^0(%arg38 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(-1 : i4) : i4
  %2 = llvm.ashr exact %arg38, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

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 ())
  }

def uge_swap_and_max_logical_before := [llvm|
{
^0(%arg228 : i8, %arg229 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "ule" %arg229, %arg228 : i8
  %3 = llvm.icmp "eq" %arg228, %0 : i8
  %4 = "llvm.select"(%2, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def test5_before := [llvm|
{
^0(%arg2 : i700):
  %0 = llvm.mlir.constant(288230376151711743 : i700) : i700
  %1 = llvm.or %arg2, %0 : i700
  %2 = llvm.xor %1, %0 : i700
  "llvm.return"(%2) : (i700) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_3b_logical_after := [llvm|
{
^0(%arg85 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(3 : i32) : i32
  %3 = llvm.and %arg85, %0 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %arg85, %2 : i32
  %6 = llvm.icmp "eq" %5, %1 : i32
  %7 = llvm.and %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def or_wrong_const1_after := [llvm|
{
^0(%arg1 : i16):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test8_before := [llvm|
{
^0(%arg79 : i32, %arg80 : i32):
  %0 = llvm.mlir.constant(32 : i128) : i128
  %1 = llvm.zext %arg79 : i32 to i128
  %2 = llvm.zext %arg80 : i32 to i128
  %3 = llvm.shl %2, %0 : i128
  %4 = llvm.or %3, %1 : i128
  %5 = llvm.trunc %4 : i128 to i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def trunc_lshr_sext_narrow_input_after := [llvm|
{
^0(%arg24 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.ashr %arg24, %0 : i8
  %2 = llvm.sext %1 : i8 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

def test10_before := [llvm|
{
^0(%arg23 : i32):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.trunc %arg23 : i32 to i8
  %2 = llvm.shl %1, %0 : i8
  %3 = llvm.ashr %2, %0 : i8
  %4 = llvm.sext %3 : i8 to i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def lshrugt_01_12_exact_before := [llvm|
{
^0(%arg209 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(-4 : i4) : i4
  %2 = llvm.lshr exact %arg209, %0 : i4
  %3 = llvm.icmp "ugt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def and_slt_to_mask_before := [llvm|
{
^0(%arg5 : i8):
  %0 = llvm.mlir.constant(-124 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.icmp "slt" %arg5, %0 : i8
  %4 = llvm.and %arg5, %1 : i8
  %5 = llvm.icmp "eq" %4, %2 : i8
  %6 = llvm.and %3, %5 : i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def main7c_logical_before := [llvm|
{
^0(%arg69 : i32, %arg70 : i32, %arg71 : i32):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.and %arg70, %arg69 : i32
  %4 = llvm.icmp "eq" %arg70, %3 : i32
  %5 = llvm.and %arg71, %arg69 : i32
  %6 = llvm.icmp "eq" %arg71, %5 : i32
  %7 = "llvm.select"(%4, %6, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %8 = "llvm.select"(%7, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%8) : (i32) -> ()
}
]

def test7_before := [llvm|
{
^0(%arg7 : i47):
  %0 = llvm.mlir.constant(39 : i47) : i47
  %1 = llvm.mlir.constant(255 : i47) : i47
  %2 = llvm.ashr %arg7, %0 : i47
  %3 = llvm.and %2, %1 : i47
  "llvm.return"(%3) : (i47) -> ()
}
]

class HydrableExistsForall (parsedExpr : Type)  (genPred : outParam Type) (genExpr : outParam (Nat → Type)) extends
  HydrableInstances genPred,
  HydrableSolve parsedExpr genPred genExpr,
  HydrableSubstitute genPred genExpr,
  HydrablePackedBitvecToSubstitutionValue genPred genExpr,
  HydrableBooleanAlgebra genPred genExpr,
  HydrableGetIdentityAndAbsorptionConstraints genPred,
  
  HydrableGenExpr genExpr
  where

def shl_trunc_smaller_ashr_before := [llvm|
{
^0(%arg41 : i32):
  %0 = llvm.mlir.constant(10 : i32) : i32
  %1 = llvm.mlir.constant(13 : i24) : i24
  %2 = llvm.ashr %arg41, %0 : i32
  %3 = llvm.trunc %2 : i32 to i24
  %4 = llvm.shl %3, %1 : i24
  "llvm.return"(%4) : (i24) -> ()
}
]

def ult_and_not_max_commute_after := [llvm|
{
^0(%arg106 : i8, %arg107 : i8):
  %0 = llvm.icmp "ult" %arg106, %arg107 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

def n8_after := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(2 : i32) : i32
  %3 = llvm.and %arg0, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  %5 = llvm.lshr %arg0, %2 : i32
  %6 = llvm.and %5, %0 : i32
  %7 = "llvm.select"(%4, %0, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

def t0_lshr_after := [llvm|
{
^0(%arg30 : i32, %arg31 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.shl %0, %arg31 overflow<nsw> : i32
  %2 = llvm.and %1, %arg30 : i32
  %3 = llvm.lshr exact %2, %arg31 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def or_xor_tree_1010_before := [llvm|
{
^0(%arg15 : i32, %arg16 : i32, %arg17 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mul %arg15, %0 : i32
  %2 = llvm.mul %arg16, %0 : i32
  %3 = llvm.mul %arg17, %0 : i32
  %4 = llvm.xor %1, %2 : i32
  %5 = llvm.xor %3, %2 : i32
  %6 = llvm.xor %5, %1 : i32
  %7 = llvm.or %6, %4 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def xor_or_xor_before := [llvm|
{
^0(%arg157 : i8):
  %0 = llvm.mlir.constant(33 : i8) : i8
  %1 = llvm.mlir.constant(7 : i8) : i8
  %2 = llvm.mlir.constant(12 : i8) : i8
  %3 = llvm.xor %arg157, %0 : i8
  %4 = llvm.or %3, %1 : i8
  %5 = llvm.xor %4, %2 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def test_mul__all_are_safe_before := [llvm|
{
^0(%arg12 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.mlir.constant(17 : i32) : i32
  %2 = llvm.mlir.constant(9 : i32) : i32
  %3 = llvm.mlir.constant(153 : i32) : i32
  %4 = llvm.and %arg12, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.mul %4, %2 : i32
  %7 = "llvm.select"(%5, %3, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

Sigma in Init.Core

def not_and_and_or_no_or_before := [llvm|
{
^0(%arg163 : i32, %arg164 : i32, %arg165 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg164, %arg163 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.xor %arg163, %0 : i32
  %4 = llvm.and %3, %arg164 : i32
  %5 = llvm.and %4, %arg165 : i32
  %6 = llvm.or %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def substitute_constant_and_eq_eq_after := [llvm|
{
^0(%arg322 : i8, %arg323 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.icmp "eq" %arg322, %0 : i8
  %2 = llvm.icmp "eq" %arg323, %0 : i8
  %3 = llvm.and %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def add_or_sub_comb_i128_commuted3_nuw_nsw_after := [llvm|
{
^0(%arg14 : i128):
  %0 = llvm.mul %arg14, %arg14 : i128
  "llvm.return"(%0) : (i128) -> ()
}
]

RV64.sub in RISCV.Instructions

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

def logical_and_implies_after := [llvm|
{
^0(%arg249 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(42 : i32) : i32
  %2 = llvm.icmp "ne" %arg249, %0 : i32
  %3 = llvm.icmp "ne" %arg249, %1 : i32
  %4 = llvm.and %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def main8_before := [llvm|
{
^0(%arg28 : i32):
  %0 = llvm.mlir.constant(64 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.mlir.constant(2 : i32) : i32
  %4 = llvm.mlir.constant(1 : i32) : i32
  %5 = llvm.and %arg28, %0 : i32
  %6 = llvm.icmp "ne" %5, %1 : i32
  %7 = llvm.trunc %arg28 : i32 to i8
  %8 = llvm.icmp "slt" %7, %2 : i8
  %9 = llvm.or %6, %8 : i1
  %10 = "llvm.select"(%9, %3, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%10) : (i32) -> ()
}
]

Int.succ in Mathlib.Data.Int.Init

def different_size_sext_sext_eq_after := [llvm|
{
^0(%arg10 : i7, %arg11 : i4):
  %0 = llvm.sext %arg11 : i4 to i7
  %1 = llvm.icmp "eq" %arg10, %0 : i7
  "llvm.return"(%1) : (i1) -> ()
}
]

def not_xor_to_or_not4_before := [llvm|
{
^0(%arg30 : i3, %arg31 : i3, %arg32 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg31, %arg32 : i3
  %2 = llvm.and %arg32, %arg30 : i3
  %3 = llvm.xor %2, %1 : i3
  %4 = llvm.xor %3, %0 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

def trunc_lshr_before := [llvm|
{
^0(%arg10 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.mlir.constant(14 : i6) : i6
  %2 = llvm.lshr %arg10, %0 : i8
  %3 = llvm.trunc %2 : i8 to i6
  %4 = llvm.and %3, %1 : i6
  "llvm.return"(%4) : (i6) -> ()
}
]

def alive_AndOrXor_2587__BAA___B__A_tgt :=
[sllvm| {
^bb0(%a : i64, %op1 : i64):
  %v1 = llvm.mlir.constant -1 : i64
  %v2 = llvm.xor %a, %v1 : i64
  %v3 = llvm.and %a, %op1 : i64
  %v4 = llvm.and %v2, %op1 : i64
  llvm.return %v4 : i64
}]

def revertIntW (g : MVarId) : MetaM (Array FVarId × MVarId) := do
  let type ← g.getType
  let (_, fvars) ← type.forEachWhere Expr.isFVar collector |>.run {}
  g.revert fvars.toArray
where
  collector (e : Expr) : StateT (Std.HashSet FVarId) MetaM Unit := do
    let fvarId := e.fvarId!
    let typ ← fvarId.getType
    match_expr typ with
    | LLVM.IntW _ =>
      modify fun s => s.insert fvarId
    | _ => return ()

def sext_zext_nneg_uge_op0_wide_after := [llvm|
{
^0(%arg26 : i16, %arg27 : i8):
  %0 = llvm.sext %arg27 : i8 to i16
  %1 = llvm.icmp "uge" %arg26, %0 : i16
  "llvm.return"(%1) : (i1) -> ()
}
]

def negtest_near_pow2_cmpval_isnt_close_to_pow2_after := [llvm|
{
^0(%arg1 : i8):
  %0 = llvm.mlir.constant(12 : i8) : i8
  %1 = llvm.icmp "slt" %arg1, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

@[match_pattern] abbrev mul (w : Nat) (flags: NoWrapFlags := {}) : LLVM.Op := MOp.mul (.concrete w) flags

def icmp_equality_test_commute_icmp2_after := [llvm|
{
^0(%arg20 : i64, %arg21 : i64, %arg22 : i64):
  %0 = llvm.icmp "eq" %arg21, %arg20 : i64
  "llvm.return"(%0) : (i1) -> ()
}
]

def icmp_power2_and_icmp_shifted_mask_2147483648_1610612736_before := [llvm|
{
^0(%arg45 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(1610612736 : i32) : i32
  %2 = llvm.icmp "ult" %arg45, %0 : i32
  %3 = llvm.and %arg45, %1 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %2, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def and_logic_and_logic_or_7_before := [llvm|
{
^0(%arg120 : i1, %arg121 : i1, %arg122 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.and %arg121, %arg120 : i1
  %3 = "llvm.select"(%arg120, %arg122, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def test_shl_nuw_nsw__nsw_is_safe_after := [llvm|
{
^0(%arg75 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

@[simp_denote]
def or_riscv_64 := [LV| {
  ^entry (%r1: i64, %r2: i64):
    %0 = "builtin.unrealized_conversion_cast"(%r1) : (i64) -> (!i64)
    %1 = "builtin.unrealized_conversion_cast"(%r2) : (i64) -> (!i64)
    %2 = or %0, %1 : !i64
    %3= "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i64)
    llvm.return %3 : i64
  }]

def masked_icmps_bmask_notmixed_and_expected_false_before := [llvm|
{
^0(%arg1 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(15 : i32) : i32
  %2 = llvm.mlir.constant(255 : i32) : i32
  %3 = llvm.mlir.constant(242 : i32) : i32
  %4 = llvm.and %arg1, %0 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  %6 = llvm.and %arg1, %2 : i32
  %7 = llvm.icmp "ne" %6, %3 : i32
  %8 = llvm.and %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def n10_ugt_slt_after := [llvm|
{
^0(%arg48 : i32, %arg49 : i32, %arg50 : i32):
  %0 = llvm.mlir.constant(128 : i32) : i32
  %1 = llvm.icmp "ugt" %arg48, %0 : i32
  %2 = "llvm.select"(%1, %arg48, %arg50) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def sle_swap_or_not_min_after := [llvm|
{
^0(%arg280 : i8, %arg281 : i8):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def ashrsgt_01_09_before := [llvm|
{
^0(%arg308 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(-7 : i4) : i4
  %2 = llvm.ashr %arg308, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def test16_after := [llvm|
{
^0(%arg8 : i51):
  %0 = llvm.mlir.constant(-1123 : i51) : i51
  %1 = llvm.sdiv %arg8, %0 : i51
  "llvm.return"(%1) : (i51) -> ()
}
]

def positive_with_mask_after := [llvm|
{
^0(%arg60 : i32):
  %0 = llvm.mlir.constant(128 : i32) : i32
  %1 = llvm.icmp "ult" %arg60, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def slt_swap_and_not_max_before := [llvm|
{
^0(%arg118 : i8, %arg119 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.icmp "sgt" %arg119, %arg118 : i8
  %2 = llvm.icmp "ne" %arg118, %0 : i8
  %3 = llvm.and %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def icmp_power2_and_icmp_shifted_mask_swapped_2147483648_1610612736_before := [llvm|
{
^0(%arg44 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(1610612736 : i32) : i32
  %2 = llvm.icmp "ult" %arg44, %0 : i32
  %3 = llvm.and %arg44, %1 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %4, %2 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def srem_i1_is_zero_after := [llvm|
{
^0(%arg2 : i1, %arg3 : i1):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def ofList {Γ : Ctxt _} ty : (l : List ((ty : Comb.Ty) × Γ.Var ty)) → (h : l.all (·.1 = ty)) → HVector (Γ.Var) (List.replicate l.length ty)
| [], h => .nil
| ⟨ty', var⟩::rest, h =>
  have hty : ty' = ty := by admit /- proof elided -/

def icmp_and_ashr_multiuse_logical_after := [llvm|
{
^0(%arg4 : i32):
  %0 = llvm.mlir.constant(240 : i32) : i32
  %1 = llvm.mlir.constant(224 : i32) : i32
  %2 = llvm.mlir.constant(496 : i32) : i32
  %3 = llvm.mlir.constant(432 : i32) : i32
  %4 = llvm.and %arg4, %0 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  %6 = llvm.and %arg4, %2 : i32
  %7 = llvm.icmp "ne" %6, %3 : i32
  %8 = llvm.and %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def ugt_swap_or_not_min_logical_after := [llvm|
{
^0(%arg4 : i8, %arg5 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "ne" %arg4, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def test13_before := [llvm|
{
^0(%arg0 : i1024):
  %0 = llvm.mlir.constant(1016 : i1024) : i1024
  %1 = llvm.mlir.constant(255 : i1024) : i1024
  %2 = llvm.ashr %arg0, %0 : i1024
  %3 = llvm.and %2, %1 : i1024
  "llvm.return"(%3) : (i1024) -> ()
}
]

def trunc_shl_7_i8_i64_before := [llvm|
{
^0(%arg52 : i64):
  %0 = llvm.mlir.constant(7) : i64
  %1 = llvm.shl %arg52, %0 : i64
  %2 = llvm.trunc %1 : i64 to i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

def Eqn.toExpr (e : Eqn) : Expr := ToExpr.toExpr (α := List Term) e

def lor_lor_right2_after := [llvm|
{
^0(%arg16 : i1, %arg17 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg16, %0, %arg17) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%1) : (i1) -> ()
}
]

def ashrsgt_03_07_after := [llvm|
{
^0(%arg278 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test12_after := [llvm|
{
^0(%arg196 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.icmp "ne" %arg196, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def lt_signed_to_small_signed_after := [llvm|
{
^0(%arg49 : i8):
  %0 = llvm.mlir.constant(17 : i8) : i8
  %1 = llvm.icmp "slt" %arg49, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def test2_before := [llvm|
{
^0(%arg0 : i999, %arg1 : i999):
  %0 = llvm.mlir.constant(65280 : i999) : i999
  %1 = llvm.and %arg0, %0 : i999
  %2 = llvm.and %arg1, %0 : i999
  %3 = llvm.icmp "ne" %1, %2 : i999
  "llvm.return"(%3) : (i1) -> ()
}
]

def pr40493_neg1_before := [llvm|
{
^0(%arg17 : i32):
  %0 = llvm.mlir.constant(11 : i32) : i32
  %1 = llvm.mlir.constant(4 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.mul %arg17, %0 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.icmp "eq" %4, %2 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

def ashrslt_02_04_before := [llvm|
{
^0(%arg249 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.mlir.constant(4 : i4) : i4
  %2 = llvm.ashr %arg249, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def and_or_not_not_commute5_after := [llvm|
{
^0(%arg360 : i32, %arg361 : i32, %arg362 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg362, %arg361 : i32
  %2 = llvm.and %1, %arg360 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def a_true_implies_b_false2_comm_before := [llvm|
{
^0(%arg18 : i8, %arg19 : i1, %arg20 : i1):
  %0 = llvm.mlir.constant(20 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.icmp "ugt" %arg18, %0 : i8
  %3 = llvm.icmp "eq" %arg18, %1 : i8
  %4 = "llvm.select"(%3, %arg19, %arg20) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = llvm.and %4, %2 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def abs_diff_signed_slt_swap_wrong_pred1_after := [llvm|
{
^0(%arg15 : i32, %arg16 : i32):
  %0 = llvm.sub %arg15, %arg16 overflow<nsw> : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

def p_constmask_after := [llvm|
{
^0(%arg49 : i32, %arg50 : i32):
  %0 = llvm.mlir.constant(65280 : i32) : i32
  %1 = llvm.mlir.constant(-65281 : i32) : i32
  %2 = llvm.and %arg49, %0 : i32
  %3 = llvm.and %arg50, %1 : i32
  %4 = llvm.or disjoint %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def mul_constant_partial_nuw_eq_before := [llvm|
{
^0(%arg104 : i32, %arg105 : i32):
  %0 = llvm.mlir.constant(44 : i32) : i32
  %1 = llvm.mul %arg104, %0 : i32
  %2 = llvm.mul %arg105, %0 overflow<nuw> : i32
  %3 = llvm.icmp "eq" %1, %2 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def n5_before := [llvm|
{
^0(%arg9 : i8, %arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.and %arg9, %0 : i8
  %3 = llvm.icmp "eq" %2, %1 : i8
  %4 = "llvm.select"(%3, %arg10, %arg11) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

def lor_lor_right2_before := [llvm|
{
^0(%arg16 : i1, %arg17 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg17, %0, %arg16) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = "llvm.select"(%arg16, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def ashrslt_02_11_before := [llvm|
{
^0(%arg242 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.mlir.constant(-5 : i4) : i4
  %2 = llvm.ashr %arg242, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

inductive IcmpPredicate where
  | eq
  | ne
  | slt
  | sle
  | sgt
  | sge
  | ult
  | ule
  | ugt
  | uge
deriving Inhabited, DecidableEq, Repr

def test1_trunc_after := [llvm|
{
^0(%arg53 : i32):
  %0 = llvm.mlir.constant(24 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.mlir.constant(65280 : i32) : i32
  %3 = llvm.lshr %arg53, %0 : i32
  %4 = llvm.lshr %arg53, %1 : i32
  %5 = llvm.and %4, %2 : i32
  %6 = llvm.or disjoint %3, %5 : i32
  %7 = llvm.trunc %6 overflow<nuw> : i32 to i16
  "llvm.return"(%7) : (i16) -> ()
}
]

def negate_add_with_single_negatible_operand_depth2_before := [llvm|
{
^0(%arg21 : i8, %arg22 : i8):
  %0 = llvm.mlir.constant(21 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.add %arg21, %0 : i8
  %3 = llvm.mul %2, %arg22 : i8
  %4 = llvm.sub %1, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

def q : Nat := 42

def test_or4_logical_after := [llvm|
{
^0(%arg22 : i32, %arg23 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.and %arg23, %0 : i32
  %2 = llvm.icmp "ugt" %arg22, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def test_after := [llvm|
{
^0(%arg0 : i1, %arg1 : i1):
  %0 = llvm.xor %arg0, %arg1 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def lsb_mask_sign_sext_wrong_cst2_before := [llvm|
{
^0(%arg2 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(31 : i32) : i32
  %3 = llvm.add %arg2, %0 : i32
  %4 = llvm.xor %arg2, %1 : i32
  %5 = llvm.and %3, %4 : i32
  %6 = llvm.ashr %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

def t0_before := [llvm|
{
^0(%arg51 : i8, %arg52 : i8, %arg53 : i8):
  %0 = llvm.sub %arg51, %arg52 : i8
  %1 = llvm.sub %0, %arg53 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def positive_biggerlshr_after := [llvm|
{
^0(%arg60 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(24 : i8) : i8
  %2 = llvm.lshr %arg60, %0 : i8
  %3 = llvm.and %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def ashr_slt_exact_near_pow2_cmpval_after := [llvm|
{
^0(%arg5 : i8):
  %0 = llvm.mlir.constant(9 : i8) : i8
  %1 = llvm.icmp "slt" %arg5, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def lshrult_03_09_exact_after := [llvm|
{
^0(%arg108 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def trunc_unsigned_nsw_sext_after := [llvm|
{
^0(%arg30 : i32, %arg31 : i8):
  %0 = llvm.sext %arg31 : i8 to i32
  %1 = llvm.icmp "ult" %arg30, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

def sle_swap_or_min_commute_after := [llvm|
{
^0(%arg146 : i8, %arg147 : i8):
  %0 = llvm.icmp "sge" %arg147, %arg146 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

def demorgan_nand_before := [llvm|
{
^0(%arg38 : i8, %arg39 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg38, %0 : i8
  %2 = llvm.and %1, %arg39 : i8
  %3 = llvm.xor %2, %0 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def positive_with_extra_and_logical_after := [llvm|
{
^0(%arg51 : i32, %arg52 : i1):
  %0 = llvm.mlir.constant(128 : i32) : i32
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "ult" %arg51, %0 : i32
  %3 = "llvm.select"(%2, %arg52, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def main4_before := [llvm|
{
^0(%arg135 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(48 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.and %arg135, %0 : i32
  %5 = llvm.icmp "eq" %4, %0 : i32
  %6 = llvm.and %arg135, %1 : i32
  %7 = llvm.icmp "eq" %6, %1 : i32
  %8 = llvm.and %5, %7 : i1
  %9 = "llvm.select"(%8, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def masked_or_allzeroes_logical_before := [llvm|
{
^0(%arg130 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(39 : i32) : i32
  %3 = llvm.mlir.constant(true) : i1
  %4 = llvm.and %arg130, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.and %arg130, %2 : i32
  %7 = llvm.icmp "eq" %6, %1 : i32
  %8 = "llvm.select"(%5, %3, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%8) : (i1) -> ()
}
]

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

def ashr_uge_noexact_before := [llvm|
{
^0(%arg160 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.ashr %arg160, %0 : i8
  %3 = llvm.icmp "uge" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def eq_umin3_before := [llvm|
{
^0(%arg56 : i32, %arg57 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.add %arg56, %0 : i32
  %2 = llvm.icmp "ult" %1, %arg57 : i32
  %3 = "llvm.select"(%2, %1, %arg57) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.icmp "eq" %1, %3 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

def zext_sub_before := [llvm|
{
^0(%arg14 : i8):
  %0 = llvm.mlir.constant(-5 : i16) : i16
  %1 = llvm.zext %arg14 : i8 to i16
  %2 = llvm.sub %0, %1 : i16
  %3 = llvm.and %2, %1 : i16
  "llvm.return"(%3) : (i16) -> ()
}
]

def xor_andn_commute4_before := [llvm|
{
^0(%arg66 : i32, %arg67 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.udiv %0, %arg66 : i32
  %3 = llvm.udiv %0, %arg67 : i32
  %4 = llvm.xor %2, %1 : i32
  %5 = llvm.and %3, %4 : i32
  %6 = llvm.xor %2, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

class DialectPrint (d : Dialect) where
   
  printOpName : d.Op → String
   
  printAttributes : d.Op → String

   
  printTy : d.Ty → String

   
  dialectName : String
  

   
  printReturn : List d.Ty → String
   
  printFunc : List d.Ty → String := fun _ => "^entry"

@[simp_denote]
def sub_0xffffffffff_riscv_i64 :=
  [LV| {
    ^entry (%x: i64):
    %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64)
    %1 = srli %0, 24 : !i64
    %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64)
    %2 = sub %a0, %1 : !i64
    %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64)
    llvm.return %3 : i64
  }]

def trunc_lshr_big_mask_after := [llvm|
{
^0(%arg8 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.mlir.constant(31 : i6) : i6
  %2 = llvm.lshr %arg8, %0 : i8
  %3 = llvm.trunc %2 overflow<nuw> : i8 to i6
  %4 = llvm.and %3, %1 : i6
  "llvm.return"(%4) : (i6) -> ()
}
]

def ashrsgt_03_00_after := [llvm|
{
^0(%arg285 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test59_before := [llvm|
{
^0(%arg122 : i8, %arg123 : i8):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.mlir.constant(48 : i32) : i32
  %2 = llvm.zext %arg122 : i8 to i32
  %3 = llvm.shl %2, %0 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.zext %arg123 : i8 to i32
  %6 = llvm.lshr %5, %0 : i32
  %7 = llvm.or %6, %4 : i32
  %8 = llvm.zext %7 : i32 to i64
  "llvm.return"(%8) : (i64) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_swapped_2_before := [llvm|
{
^0(%arg46 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(7 : i32) : i32
  %3 = llvm.and %arg46, %0 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %arg46, %2 : i32
  %6 = llvm.icmp "eq" %5, %1 : i32
  %7 = llvm.and %6, %4 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def select_icmp_eq_pow2_flipped_before := [llvm|
{
^0(%arg12 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.and %arg12, %0 : i8
  %3 = llvm.icmp "eq" %2, %1 : i8
  %4 = llvm.xor %arg12, %0 : i8
  %5 = "llvm.select"(%3, %4, %arg12) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def ashr_ugt_5_before := [llvm|
{
^0(%arg109 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(5 : i4) : i4
  %2 = llvm.ashr %arg109, %0 : i4
  %3 = llvm.icmp "ugt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def icmp_ne_and1_lshr_pow2_before := [llvm|
{
^0(%arg46 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.lshr %0, %arg46 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.icmp "eq" %4, %2 : i32
  %6 = llvm.zext %5 : i1 to i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def p0_before := [llvm|
{
^0(%arg16 : i8, %arg17 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.shl %0, %arg17 : i8
  %2 = llvm.icmp "ule" %1, %arg16 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_7b_before := [llvm|
{
^0(%arg76 : i32):
  %0 = llvm.mlir.constant(6 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(15 : i32) : i32
  %3 = llvm.mlir.constant(8 : i32) : i32
  %4 = llvm.and %arg76, %0 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  %6 = llvm.and %arg76, %2 : i32
  %7 = llvm.icmp "eq" %6, %3 : i32
  %8 = llvm.and %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

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

def determinize (M : NFA' n) : NFA' n where
  σ := _
  M := M.M.toDFA.toNFA

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

def test_sub__all_are_safe_before := [llvm|
{
^0(%arg28 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.mlir.constant(6 : i32) : i32
  %2 = llvm.mlir.constant(-254 : i32) : i32
  %3 = llvm.mlir.constant(-260 : i32) : i32
  %4 = llvm.and %arg28, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.sub %2, %4 : i32
  %7 = "llvm.select"(%5, %3, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def t3_after := [llvm|
{
^0(%arg23 : i8, %arg24 : i2):
  %0 = llvm.sext %arg24 : i2 to i8
  %1 = llvm.add %arg23, %0 : i8
  %2 = llvm.xor %1, %0 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def not_and_and_or_not_or_or_commute1_and_before := [llvm|
{
^0(%arg244 : i32, %arg245 : i32, %arg246 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg245, %arg244 : i32
  %2 = llvm.or %1, %arg246 : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.xor %arg244, %0 : i32
  %5 = llvm.and %4, %arg246 : i32
  %6 = llvm.and %5, %arg245 : i32
  %7 = llvm.or %6, %3 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def positive_biggershl_shlnuwnsw_lshrexact_before := [llvm|
{
^0(%arg24 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(6 : i8) : i8
  %2 = llvm.lshr exact %arg24, %0 : i8
  %3 = llvm.shl %2, %1 overflow<nsw,nuw> : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def test21_after := [llvm|
{
^0(%arg0 : i256, %arg1 : i256):
  %0 = llvm.mlir.constant(0 : i256) : i256
  %1 = llvm.icmp "ne" %arg1, %0 : i256
  "llvm.return"(%1) : (i1) -> ()
}
]

def xor_and_logic_or1_before := [llvm|
{
^0(%arg30 : i1, %arg31 : i1, %arg32 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg30, %0, %arg32) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = llvm.and %arg30, %arg31 : i1
  %3 = llvm.xor %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def canonicalize_icmp_ult_neg5 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant -5 : i64
      %1 = llvm.icmp.ult %c, %x : i64
      llvm.return %1 : i1
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant -5 : i64
      %1 = llvm.icmp.ugt %x, %c : i64
      llvm.return %1 : i1
  }]

@[simp_denote]
def shl_llvm_nsw_64 := [LV| {
  ^entry (%x: i64, %y: i64):
    %1 = llvm.shl %x, %y overflow<nsw> : i64
    llvm.return %1 : i64
  }]

def lshrult_01_05_exact_after := [llvm|
{
^0(%arg144 : i4):
  %0 = llvm.mlir.constant(-6 : i4) : i4
  %1 = llvm.icmp "ult" %arg144, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def icmp_slt_0_and_icmp_sgt_neg1_i64_before := [llvm|
{
^0(%arg60 : i64):
  %0 = llvm.mlir.constant(-1) : i64
  %1 = llvm.mlir.constant(63) : i64
  %2 = llvm.icmp "sgt" %arg60, %0 : i64
  %3 = llvm.zext %2 : i1 to i64
  %4 = llvm.lshr %arg60, %1 : i64
  %5 = llvm.and %4, %3 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def fsmCarry' (initialCarryVal : Bool): FSM Bool :=
  let outputCirc :=
    let carry := Circuit.var true (Sum.inl ())
    let a := Circuit.var true (Sum.inr true)
    let b := Circuit.var true (Sum.inr false)
    
    ((a &&& b) ||| (a &&& carry) ||| (b &&& carry))
  { α := Unit,
    
    
    initCarry := fun () => initialCarryVal, 
    outputCirc := outputCirc,
    nextStateCirc := fun () => outputCirc
  }

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

@[simp_denote]
def and_riscv_i16 :=
  [LV| {
    ^entry (%arg0: i16, %arg1: i16 ):
    %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64)
    %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64)
    %0 = and %a, %b : !i64
    %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16)
    llvm.return %1 :i16
  }]

def absdiff_before := [llvm|
{
^0(%arg4 : i64, %arg5 : i64):
  %0 = llvm.icmp "ult" %arg4, %arg5 : i64
  %1 = llvm.sext %0 : i1 to i64
  %2 = llvm.sub %arg4, %arg5 : i64
  %3 = llvm.xor %1, %2 : i64
  %4 = llvm.sub %3, %1 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def test_negative_nsw_and_unsigned_pred_before := [llvm|
{
^0(%arg52 : i64):
  %0 = llvm.mlir.constant(10) : i64
  %1 = llvm.mlir.constant(3) : i64
  %2 = llvm.sub %0, %arg52 overflow<nsw> : i64
  %3 = llvm.icmp "ult" %2, %1 : i64
  "llvm.return"(%3) : (i1) -> ()
}
]

def PR42691_8_logical_after := [llvm|
{
^0(%arg328 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-2147483635 : i32) : i32
  %2 = llvm.add %arg328, %0 : i32
  %3 = llvm.icmp "ult" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def logical_and_logical_and_icmps_comm3_after := [llvm|
{
^0(%arg199 : i8, %arg200 : i8, %arg201 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "eq" %arg200, %0 : i8
  %4 = llvm.shl %1, %arg201 overflow<nuw> : i8
  %5 = llvm.or %4, %1 : i8
  %6 = llvm.and %arg199, %5 : i8
  %7 = llvm.icmp "eq" %6, %5 : i8
  %8 = "llvm.select"(%7, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def samesign_inverted_commute3_before := [llvm|
{
^0(%arg97 : i32, %arg98 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg97, %arg98 : i32
  %3 = llvm.icmp "sgt" %2, %0 : i32
  %4 = llvm.or %arg98, %arg97 : i32
  %5 = llvm.icmp "slt" %4, %1 : i32
  %6 = llvm.and %5, %3 : i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def icmp_ne_and_z_and_onefail_after := [llvm|
{
^0(%arg18 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.icmp "ugt" %arg18, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def ashrsgt_01_13_exact_before := [llvm|
{
^0(%arg88 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(-3 : i4) : i4
  %2 = llvm.ashr exact %arg88, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def icmp_power2_and_icmp_shifted_mask_swapped_8_6_before := [llvm|
{
^0(%arg34 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(6 : i32) : i32
  %2 = llvm.icmp "ult" %arg34, %0 : i32
  %3 = llvm.and %arg34, %1 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.and %4, %2 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def test_before := [llvm|
{
^0(%arg0 : i64):
  %0 = llvm.mlir.constant(4294967294) : i64
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.or %arg0, %0 : i64
  %3 = llvm.trunc %2 : i64 to i32
  %4 = llvm.srem %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def udiv_common_dividend_defined_cond_before := [llvm|
{
^0(%arg17 : i1, %arg18 : i5, %arg19 : i5, %arg20 : i5):
  %0 = llvm.udiv %arg18, %arg19 : i5
  %1 = llvm.udiv %arg18, %arg20 : i5
  %2 = "llvm.select"(%arg17, %1, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i5, i5) -> i5
  "llvm.return"(%2) : (i5) -> ()
}
]

def scalar_i32_shl_and_negC_eq_X_is_constant1_after := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(12345 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.shl %0, %arg5 : i32
  %3 = llvm.icmp "ult" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def lshr_shl_demand3_before := [llvm|
{
^0(%arg7 : i8):
  %0 = llvm.mlir.constant(28 : i8) : i8
  %1 = llvm.mlir.constant(3 : i8) : i8
  %2 = llvm.lshr %0, %arg7 : i8
  %3 = llvm.shl %2, %1 : i8
  %4 = llvm.or %3, %1 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def t1_lshr_after := [llvm|
{
^0(%arg26 : i32, %arg27 : i8):
  %0 = llvm.zext nneg %arg27 : i8 to i32
  %1 = llvm.lshr %arg26, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def not_xor_to_or_not3_before := [llvm|
{
^0(%arg33 : i3, %arg34 : i3, %arg35 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg35, %arg34 : i3
  %2 = llvm.and %arg35, %arg33 : i3
  %3 = llvm.xor %2, %1 : i3
  %4 = llvm.xor %3, %0 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

def ripple_nsw5_before := [llvm|
{
^0(%arg15 : i16, %arg16 : i16):
  %0 = llvm.mlir.constant(-21845 : i16) : i16
  %1 = llvm.mlir.constant(-10923 : i16) : i16
  %2 = llvm.or %arg16, %0 : i16
  %3 = llvm.or %arg15, %1 : i16
  %4 = llvm.add %2, %3 : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

def add_shl_same_amount_nuw_before := [llvm|
{
^0(%arg53 : i64, %arg54 : i64, %arg55 : i64):
  %0 = llvm.shl %arg53, %arg55 overflow<nuw> : i64
  %1 = llvm.shl %arg54, %arg55 overflow<nuw> : i64
  %2 = llvm.add %0, %1 overflow<nuw> : i64
  "llvm.return"(%2) : (i64) -> ()
}
]

def ashrsgt_03_10_before := [llvm|
{
^0(%arg275 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(-6 : i4) : i4
  %2 = llvm.ashr %arg275, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def ashr_ule_exact_before := [llvm|
{
^0(%arg168 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.ashr exact %arg168, %0 : i8
  %3 = llvm.icmp "ule" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def no_shift_xor_multiuse_cmp_and_after := [llvm|
{
^0(%arg40 : i32, %arg41 : i32, %arg42 : i32, %arg43 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(-4097 : i32) : i32
  %3 = llvm.and %arg40, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  %5 = llvm.and %arg41, %2 : i32
  %6 = "llvm.select"(%4, %5, %arg41) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = "llvm.select"(%4, %arg43, %arg42) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %8 = llvm.mul %6, %7 : i32
  %9 = llvm.mul %8, %5 : i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def ashrsgt_03_08_before := [llvm|
{
^0(%arg277 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(-8 : i4) : i4
  %2 = llvm.ashr %arg277, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

instance : DialectParse SLLVM 0 where
  isValidReturn Γ opStx := return opStx.name == "llvm.return"

  mkExpr (Γ : Ctxt SLLVM.Ty) (opStx : MLIR.AST.Op 0) := do
  let args ← opStx.parseArgs Γ

   
  let binW := do
  
    let args ← args.assumeArity 2
    getIntWidth args[0]

   
  let unW := do
    let args ← args.assumeArity 1
    getIntWidth args[0]

  let getOutputWidth := getOutputWidth opStx

  let mkExprOf := opStx.mkExprOf (args? := args) Γ
  match opStx.name with
    
    | "ptr.add" => mkExprOf <| .ptradd
    | "ptr.load" => mkExprOf <| .load (← getOutputWidth)
    | "ptr.store" => do
        let args ← args.assumeArity 2
        mkExprOf <| .store (← getIntWidth args[1])
    | "ptr.alloca" =>
        let t ← opStx.getTypeAttr "elem_type"
        let .int _ w := t
          | throw <| .generic s!"Expected value of attribute `elem_type` to be an integer type"
        mkExprOf <| .alloca w.toConcrete
    
    | "llvm.select" =>
        let args ← args.assumeArity 3
        let w ← getIntWidth args[1]
        mkExprOf <| Op.select w
    
    | "llvm.and"      => mkExprOf <| Op.and (← binW)
    | "llvm.or"       => mkExprOf <| Op.or (← binW) ⟨opStx.hasAttr "isDisjoint"⟩
    | "llvm.xor"      => mkExprOf <| Op.xor (← binW)
    | "llvm.urem"     => mkExprOf <| Op.urem (← binW)
    | "llvm.srem"     => mkExprOf <| Op.srem (← binW)
    | "llvm.lshr"     => mkExprOf <| Op.lshr (← binW) ⟨opStx.hasAttr "isExact"⟩
    | "llvm.ashr"     => mkExprOf <| Op.ashr (← binW) ⟨opStx.hasAttr "isExact"⟩
    | "llvm.sdiv"     => mkExprOf <| Op.sdiv (← binW) ⟨opStx.hasAttr "isExact"⟩
    | "llvm.udiv"     => mkExprOf <| Op.udiv (← binW) ⟨opStx.hasAttr "isExact"⟩
    | "llvm.shl"      => mkExprOf <| Op.shl (← binW) (← parseOverflowFlags opStx)
    | "llvm.add"      => mkExprOf <| Op.add (← binW) (← parseOverflowFlags opStx)
    | "llvm.mul"      => mkExprOf <| Op.mul (← binW) (← parseOverflowFlags opStx)
    | "llvm.sub"      => mkExprOf <| Op.sub (← binW) (← parseOverflowFlags opStx)
    | "llvm.icmp.eq"  => mkExprOf <| Op.icmp .eq (← binW)
    | "llvm.icmp.ne"  => mkExprOf <| Op.icmp .ne (← binW)
    | "llvm.icmp.ugt" => mkExprOf <| Op.icmp .ugt (← binW)
    | "llvm.icmp.uge" => mkExprOf <| Op.icmp .uge (← binW)
    | "llvm.icmp.ult" => mkExprOf <| Op.icmp .ult (← binW)
    | "llvm.icmp.ule" => mkExprOf <| Op.icmp .ule (← binW)
    | "llvm.icmp.sgt" => mkExprOf <| Op.icmp .sgt (← binW)
    | "llvm.icmp.sge" => mkExprOf <| Op.icmp .sge (← binW)
    | "llvm.icmp.slt" => mkExprOf <| Op.icmp .slt (← binW)
    | "llvm.icmp.sle" => mkExprOf <| Op.icmp .sle (← binW)
    
    | "llvm.not"    => mkExprOf <| Op.not (← unW)
    | "llvm.neg"    => mkExprOf <| Op.neg (← unW)
    | "llvm.copy"   => mkExprOf <| Op.copy (← unW)
    | "llvm.freeze" => mkExprOf <| Op.freeze (← unW)
    | "llvm.zext"   => mkExprOf <| Op.zext (← unW) (← getOutputWidth) ⟨ opStx.hasAttr "nonNeg" ⟩
    | "llvm.sext"   => mkExprOf <| Op.sext (← unW) (← getOutputWidth)
    | "llvm.trunc"  => mkExprOf <| Op.trunc (← unW) (← getOutputWidth) (← parseOverflowFlags opStx)
    
    | "llvm.mlir.constant" => do
      let ⟨val, ty⟩ ← opStx.getIntAttr "value"
      let opTy ← mkTy ty
      let Ty.bitvec w := opTy
        | throw <| .generic s!"Expected a `bitvec _`, but found: {opTy}"
      mkExprOf <| Op.const w val
    
    | opName => throw <| .unsupportedOp opName

def ashr_eq_noexact_before := [llvm|
{
^0(%arg163 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.ashr %arg163, %0 : i8
  %3 = llvm.icmp "eq" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def and_nosignbit_select_lshr_after := [llvm|
{
^0(%arg28 : i32, %arg29 : i1):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(8388352 : i32) : i32
  %2 = llvm.lshr %arg28, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = "llvm.select"(%arg29, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def lowbitmask_casted_shift_before := [llvm|
{
^0(%arg157 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(2147483647 : i32) : i32
  %2 = llvm.ashr %arg157, %0 : i8
  %3 = llvm.sext %2 : i8 to i32
  %4 = llvm.and %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def ne_umax1_after := [llvm|
{
^0(%arg44 : i32, %arg45 : i32):
  %0 = llvm.icmp "ult" %arg44, %arg45 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

IO.FS.FileType.file in Init.System.IO

def uadd_sat_flipped_wrong_bounds_after := [llvm|
{
^0(%arg96 : i32):
  %0 = llvm.mlir.constant(-13 : i32) : i32
  %1 = llvm.mlir.constant(9 : i32) : i32
  %2 = llvm.mlir.constant(-1 : i32) : i32
  %3 = llvm.icmp "ugt" %arg96, %0 : i32
  %4 = llvm.add %arg96, %1 : i32
  %5 = "llvm.select"(%3, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

inductive TransformError
  | nameAlreadyDeclared (var : String)
  | undeclaredName (var : String)
  | indexOutOfBounds (name : String) (index len : Nat)
  | typeError (expected got : String)
  | widthError {φ} (expected got : Width φ)
  
  
  | unsupportedUnaryOp
  | unsupportedBinaryOp (error : String)
  | unsupportedOp (error : String)
  | unsupportedType
  | generic (error : String)

def lshrugt_03_09_after := [llvm|
{
^0(%arg374 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test_implied_false_after := [llvm|
{
^0(%arg6 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(5 : i8) : i8
  %2 = llvm.mlir.constant(20 : i8) : i8
  %3 = llvm.icmp "slt" %arg6, %0 : i8
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def ashrslt_02_08_after := [llvm|
{
^0(%arg245 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def ashr_ult_exact_after := [llvm|
{
^0(%arg169 : i8):
  %0 = llvm.mlir.constant(80 : i8) : i8
  %1 = llvm.icmp "ult" %arg169, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def scalar_i32_lshr_and_negC_eq_X_is_constant2_before := [llvm|
{
^0(%arg8 : i32):
  %0 = llvm.mlir.constant(268435456 : i32) : i32
  %1 = llvm.mlir.constant(-8 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.lshr %0, %arg8 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.icmp "eq" %4, %2 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

def test_sub_nuw__none_are_safe_after := [llvm|
{
^0(%arg18 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.sub %0, %arg18 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def or_not_xor_common_op_commute6_after := [llvm|
{
^0(%arg89 : i8, %arg90 : i8, %arg91 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.sub %0, %arg91 : i8
  %3 = llvm.and %arg90, %arg89 : i8
  %4 = llvm.xor %3, %1 : i8
  %5 = llvm.or %4, %2 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def t3_before := [llvm|
{
^0(%arg10 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sub %0, %arg10 overflow<nsw> : i8
  %2 = llvm.icmp "sle" %1, %arg10 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def test44_after := [llvm|
{
^0(%arg144 : i8):
  %0 = llvm.mlir.constant(1234 : i16) : i16
  %1 = llvm.zext %arg144 : i8 to i16
  %2 = llvm.or %1, %0 : i16
  %3 = llvm.zext nneg %2 : i16 to i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def sra_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where
  lhs := sra_llvm_i32
  rhs := sra_riscv_i32

@[simp_denote]
def run {Γ : Ctxt _} {t : Arith.Ty} (v : Var Γ t) (body : Com ScfArith ⟨[t]⟩ .impure t) :
    Expr ScfArith Γ .impure t :=
  Expr.mk
    (op := .run t)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons v .nil)
    (regArgs := HVector.cons body <| HVector.nil)

def test11_after := [llvm|
{
^0(%arg103 : i32, %arg104 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg104, %arg103 : i32
  %2 = llvm.xor %arg103, %arg104 : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.and %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def scalar_i16_shl_and_negC_eq_after := [llvm|
{
^0(%arg33 : i16, %arg34 : i16):
  %0 = llvm.mlir.constant(128 : i16) : i16
  %1 = llvm.shl %arg33, %arg34 : i16
  %2 = llvm.icmp "ult" %1, %0 : i16
  "llvm.return"(%2) : (i1) -> ()
}
]

def icmp_uge_x_y_2_before := [llvm|
{
^0(%arg36 : i8, %arg37 : i8):
  %0 = llvm.mul %arg36, %arg36 : i8
  %1 = llvm.and %0, %arg37 : i8
  %2 = llvm.icmp "ule" %0, %1 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def slt_and_not_max_before := [llvm|
{
^0(%arg126 : i8, %arg127 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.icmp "slt" %arg126, %arg127 : i8
  %2 = llvm.icmp "ne" %arg126, %0 : i8
  %3 = llvm.and %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def slt_zero_sgt_minus1_after := [llvm|
{
^0(%arg22 : i4, %arg23 : i4):
  %0 = llvm.mlir.constant(-1 : i4) : i4
  %1 = llvm.xor %arg22, %arg23 : i4
  %2 = llvm.icmp "sgt" %1, %0 : i4
  "llvm.return"(%2) : (i1) -> ()
}
]

def ashr_ule_exact_before := [llvm|
{
^0(%arg168 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.ashr exact %arg168, %0 : i8
  %3 = llvm.icmp "ule" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def alive_AddSub_1202_src :=
[sllvm| {
^bb0(%x : i64, %C : i64):
  %v1 = llvm.mlir.constant -1 : i64
  %v2 = llvm.xor %x, %v1 : i64
  %v3 = llvm.add %v2, %C : i64
  llvm.return %v3 : i64
}]

def test6_before := [llvm|
{
^0(%arg31 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.lshr %arg31, %0 : i32
  %2 = llvm.mul %1, %0 : i32
  %3 = llvm.sext %2 : i32 to i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def ashrslt_01_03_after := [llvm|
{
^0(%arg266 : i4):
  %0 = llvm.mlir.constant(6 : i4) : i4
  %1 = llvm.icmp "slt" %arg266, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def ugt_swap_and_not_min_commute_before := [llvm|
{
^0(%arg66 : i8, %arg67 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "ult" %arg67, %arg66 : i8
  %2 = llvm.icmp "ne" %arg66, %0 : i8
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def select_of_symmetric_selects_negative1_after := [llvm|
{
^0(%arg29 : i32, %arg30 : i32, %arg31 : i1, %arg32 : i1):
  %0 = "llvm.select"(%arg31, %arg29, %arg30) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %1 = "llvm.select"(%arg32, %0, %arg29) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def select_icmp_and_2147483648_eq_0_xor_2147483648_before := [llvm|
{
^0(%arg169 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg169, %0 : i32
  %3 = llvm.icmp "eq" %2, %1 : i32
  %4 = llvm.xor %arg169, %0 : i32
  %5 = "llvm.select"(%3, %4, %arg169) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def t11_shl_nsw_flag_preservation_after := [llvm|
{
^0(%arg21 : i32, %arg22 : i32):
  %0 = llvm.mlir.constant(30 : i32) : i32
  %1 = llvm.shl %arg21, %0 overflow<nsw> : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def sdiv_icmp5_before := [llvm|
{
^0(%arg10 : i64):
  %0 = llvm.mlir.constant(-5) : i64
  %1 = llvm.mlir.constant(1) : i64
  %2 = llvm.sdiv exact %arg10, %0 : i64
  %3 = llvm.icmp "eq" %2, %1 : i64
  "llvm.return"(%3) : (i1) -> ()
}
]

def n2_badmask_before := [llvm|
{
^0(%arg6 : i32, %arg7 : i32, %arg8 : i32, %arg9 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg9, %0 : i32
  %2 = llvm.or %1, %arg6 : i32
  %3 = llvm.or %arg8, %arg7 : i32
  %4 = llvm.and %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def shl_and_lshr_comm_before := [llvm|
{
^0(%arg91 : i32, %arg92 : i32, %arg93 : i32):
  %0 = llvm.shl %arg91, %arg92 overflow<nuw> : i32
  %1 = llvm.and %arg93, %0 : i32
  %2 = llvm.lshr %1, %arg92 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def masked_icmps_mask_notallzeros_bmask_mixed_swapped_5_logical_before := [llvm|
{
^0(%arg37 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(8 : i32) : i32
  %3 = llvm.mlir.constant(false) : i1
  %4 = llvm.and %arg37, %0 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  %6 = llvm.and %arg37, %0 : i32
  %7 = llvm.icmp "eq" %6, %2 : i32
  %8 = "llvm.select"(%7, %5, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def a_true_implies_b_true_before := [llvm|
{
^0(%arg36 : i8, %arg37 : i1, %arg38 : i1):
  %0 = llvm.mlir.constant(20 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "ugt" %arg36, %0 : i8
  %4 = llvm.icmp "ugt" %arg36, %1 : i8
  %5 = "llvm.select"(%4, %arg37, %arg38) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %6 = "llvm.select"(%3, %5, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def ashrsgt_01_10_exact_after := [llvm|
{
^0(%arg91 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (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 substitute_constant_and_eq_eq_commute_before := [llvm|
{
^0(%arg318 : i8, %arg319 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.icmp "eq" %arg318, %0 : i8
  %2 = llvm.icmp "eq" %arg318, %arg319 : i8
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def select_icmp_ne_0_and_1073741824_and_not_8_before := [llvm|
{
^0(%arg191 : i32, %arg192 : i8):
  %0 = llvm.mlir.constant(1073741824 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(-9 : i8) : i8
  %3 = llvm.and %arg191, %0 : i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  %5 = llvm.and %arg192, %2 : i8
  %6 = "llvm.select"(%4, %arg192, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%6) : (i8) -> ()
}
]

def sle_swap_or_not_min_after := [llvm|
{
^0(%arg280 : i8, %arg281 : i8):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def xor_of_icmps_commute_before := [llvm|
{
^0(%arg30 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.mlir.constant(1) : i64
  %2 = llvm.icmp "sgt" %arg30, %0 : i64
  %3 = llvm.icmp "eq" %arg30, %1 : i64
  %4 = llvm.xor %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def Region.WellTyped : UnTyped.Region Op VarName → RegionType Ty → Prop
  | ⟨entry, _⟩ => BasicBlock.WellTyped entry

def select_icmp_ne_0_and_4096_or_4096_after := [llvm|
{
^0(%arg233 : i32, %arg234 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.and %arg233, %0 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.or %arg234, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def not_and_and_or_no_or_commute2_and_after := [llvm|
{
^0(%arg157 : i32, %arg158 : i32, %arg159 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg157, %0 : i32
  %2 = llvm.xor %arg158, %0 : i32
  %3 = llvm.or %arg159, %2 : i32
  %4 = llvm.and %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def lshr_add_xor_fail_after := [llvm|
{
^0(%arg90 : i8, %arg91 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(123 : i8) : i8
  %2 = llvm.lshr %arg90, %0 : i8
  %3 = llvm.lshr %arg91, %0 : i8
  %4 = llvm.add %3, %1 overflow<nuw> : i8
  %5 = llvm.xor %2, %4 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def sdiv2_after := [llvm|
{
^0(%arg39 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.ashr exact %arg39, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def sub_select_not_sext_before := [llvm|
{
^0(%arg20 : i1, %arg21 : i64):
  %0 = llvm.mlir.constant(64) : i64
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg20, %arg21, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  %3 = llvm.xor %arg20, %1 : i1
  %4 = llvm.sext %3 : i1 to i64
  %5 = llvm.sub %2, %4 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def udiv_exact_eq_1_before := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.udiv exact %arg10, %arg11 : i8
  %2 = llvm.icmp "ne" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def append (d₁ : Diff Γ₁ Γ₂) (d₂ : Diff Γ₂ Γ₃) : Diff Γ₁ Γ₃ :=
  {val := d₁.val + d₂.val,  property := append_valid d₁.property d₂.property}

def allSignBits_before := [llvm|
{
^0(%arg13 : i32, %arg14 : i32, %arg15 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.ashr %arg13, %0 : i32
  %3 = llvm.xor %2, %1 : i32
  %4 = llvm.and %arg14, %2 : i32
  %5 = llvm.and %3, %arg15 : i32
  %6 = llvm.or %4, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def fold_nested_logic_zext_icmp_after := [llvm|
{
^0(%arg87 : i64, %arg88 : i64, %arg89 : i64, %arg90 : i64):
  %0 = llvm.icmp "sgt" %arg87, %arg88 : i64
  %1 = llvm.icmp "slt" %arg87, %arg89 : i64
  %2 = llvm.and %0, %1 : i1
  %3 = llvm.icmp "eq" %arg87, %arg90 : i64
  %4 = llvm.or %2, %3 : i1
  %5 = llvm.zext %4 : i1 to i8
  "llvm.return"(%5) : (i8) -> ()
}
]

@[simp_denote]
def ori_riscv_i64 :=
  [LV| {
    ^entry (%arg: i64):
    %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64)
    %0 = ori %a, 5 : !i64
    %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64)
    llvm.return %1 : i64
  }]

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 shift_trunc_wrong_cmp_after := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(24 : i32) : i32
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.lshr %arg0, %0 : i32
  %3 = llvm.trunc %2 overflow<nuw> : i32 to i8
  %4 = llvm.icmp "slt" %3, %1 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def add_shl_moreOneUse_sh2add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := add_shl_moreOneUse_sh2add
  rhs := add_shl_moreOneUse_sh2add_riscv_no_ZBA

Union.union in Init.Core

def push (Γ : Context Ty) (v : VarName) (ty : Ty) : Context Ty :=
  (v, ty) :: Γ

def test6_after := [llvm|
{
^0(%arg48 : i55):
  %0 = llvm.mlir.constant(6 : i55) : i55
  %1 = llvm.mul %arg48, %0 : i55
  "llvm.return"(%1) : (i55) -> ()
}
]

def lshr_pow2_ult_equal_constants_before := [llvm|
{
^0(%arg61 : i32):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.lshr %0, %arg61 : i32
  %2 = llvm.icmp "ult" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def ashrslt_01_14_after := [llvm|
{
^0(%arg255 : i4):
  %0 = llvm.mlir.constant(-4 : i4) : i4
  %1 = llvm.icmp "slt" %arg255, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def test17_after := [llvm|
{
^0(%arg36 : i32, %arg37 : i32):
  %0 = llvm.mlir.constant(1431655765 : i32) : i32
  %1 = llvm.or %arg36, %0 : i32
  %2 = llvm.sub %arg37, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def llvm_const_lower_riscv_li35 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM35, rhs:= liRiscv35,
   correct := by admit /- proof elided -/

def icmp_slt_0_or_icmp_sgt_0_i64_before := [llvm|
{
^0(%arg73 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.icmp "slt" %arg73, %0 : i64
  %2 = llvm.icmp "sgt" %arg73, %0 : i64
  %3 = llvm.zext %1 : i1 to i64
  %4 = llvm.zext %2 : i1 to i64
  %5 = llvm.or %3, %4 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def mkStateUniqueCircuitN {arity : Type _}
  [DecidableEq arity] [Fintype arity] [Hashable arity]
  (p : FSM arity) (n : Nat) : Circuit (Vars p.α arity n) :=
  let sn : p.α → Circuit (Vars p.α arity n) := fun s =>
    Circuit.var true (Vars.stateN s n)
  let circs := (List.range n).attach |>.map fun ⟨i, hi⟩ =>
    let si : p.α → Circuit (Vars p.α arity n) := fun s =>
      Circuit.var true (Vars.stateN s i (by admit /- proof elided -/
      ))
    (mkStateNeqCircuit p si sn)
  Circuit.bigOr circs

def lshr_2_add_zext_basic_before := [llvm|
{
^0(%arg37 : i1, %arg38 : i1):
  %0 = llvm.mlir.constant(1 : i2) : i2
  %1 = llvm.zext %arg37 : i1 to i2
  %2 = llvm.zext %arg38 : i1 to i2
  %3 = llvm.add %1, %2 : i2
  %4 = llvm.lshr %3, %0 : i2
  "llvm.return"(%4) : (i2) -> ()
}
]

def lshrugt_01_11_exact_before := [llvm|
{
^0(%arg210 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(-5 : i4) : i4
  %2 = llvm.lshr exact %arg210, %0 : i4
  %3 = llvm.icmp "ugt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def dcAdd2 := [DCxComb_com| {
  ^entry(%a: !ValueStream_32, %b: !ValueStream_32):
    %unpacka = "DCxComb.unpack" (%a) : (!ValueStream_32) -> (!ValueTokenStream_32)
    
    %output = "DCxComb.fstVal" (%unpacka) : (!ValueTokenStream_32) -> (!ValueStream_32)
    %token = "DCxComb.sndVal" (%unpacka) : (!ValueTokenStream_32) -> (!TokenStream)
    
    %2 = "DCxComb.add" (%output, %output) : (!ValueStream_32, !ValueStream_32) -> (!ValueStream_32)
    %unpackb = "DCxComb.unpack" (%b) : (!ValueStream_32) -> (!ValueTokenStream_32)
    
    %output1 = "DCxComb.fstVal" (%unpackb) : (!ValueTokenStream_32) -> (!ValueStream_32)
    %token0 = "DCxComb.sndVal" (%unpackb) : (!ValueTokenStream_32) -> (!TokenStream)
    %3 = "DCxComb.join" (%token, %token0) : (!TokenStream, !TokenStream) -> (!TokenStream)
    %4 = "DCxComb.add" (%2, %output) : (!ValueStream_32, !ValueStream_32) -> (!ValueStream_32)
    %5 = "DCxComb.pack" (%4, %3) : (!ValueStream_32, !TokenStream) -> (!ValueStream_32)
    "return" (%5) : (!ValueStream_32) -> ()
}]

def not_and_and_or_not_or_or_commute3_after := [llvm|
{
^0(%arg232 : i32, %arg233 : i32, %arg234 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg233 : i32
  %3 = llvm.xor %arg234, %2 : i32
  %4 = llvm.or %3, %arg232 : i32
  %5 = llvm.xor %4, %1 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def icmp_slt_0_and_icmp_ne_neg2_i32_fail_before := [llvm|
{
^0(%arg44 : i32):
  %0 = llvm.mlir.constant(-2 : i32) : i32
  %1 = llvm.mlir.constant(31 : i32) : i32
  %2 = llvm.icmp "ne" %arg44, %0 : i32
  %3 = llvm.zext %2 : i1 to i32
  %4 = llvm.lshr %arg44, %1 : i32
  %5 = llvm.and %4, %3 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def selection00 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs:= [LV| {
  ^entry (%arg0: i64):
    %c = llvm.mlir.constant (4) : i64
    %1 = llvm.mul %arg0, %c : i64
    llvm.return %1 : i64
  }]
  rhs:= [LV| {
  ^entry (%arg0: i64):
    %r1 = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg)
    %c = slli %r1, 2 : !riscv.reg
    %rd = "builtin.unrealized_conversion_cast" (%c) : (!riscv.reg) -> (i64)
    llvm.return %rd : i64
  }]

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

def lowmask_or_zext_commute_before := [llvm|
{
^0(%arg217 : i16, %arg218 : i24):
  %0 = llvm.mlir.constant(65535 : i24) : i24
  %1 = llvm.zext %arg217 : i16 to i24
  %2 = llvm.or %arg218, %1 : i24
  %3 = llvm.and %2, %0 : i24
  "llvm.return"(%3) : (i24) -> ()
}
]

def p2_slt_65536_before := [llvm|
{
^0(%arg50 : i32, %arg51 : i32):
  %0 = llvm.mlir.constant(65536 : i32) : i32
  %1 = llvm.mlir.constant(65535 : i32) : i32
  %2 = llvm.icmp "slt" %arg50, %0 : i32
  %3 = "llvm.select"(%2, %arg51, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def lowmask_add_2_after := [llvm|
{
^0(%arg144 : i8):
  %0 = llvm.mlir.constant(63 : i8) : i8
  %1 = llvm.and %arg144, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def sge_swap_or_max_after := [llvm|
{
^0(%arg182 : i8, %arg183 : i8):
  %0 = llvm.icmp "sle" %arg183, %arg182 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

def ashrslt_01_02_after := [llvm|
{
^0(%arg267 : i4):
  %0 = llvm.mlir.constant(4 : i4) : i4
  %1 = llvm.icmp "slt" %arg267, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def test9_before := [llvm|
{
^0(%arg18 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.mlir.constant(1) : i64
  %2 = llvm.sub %0, %arg18 overflow<nsw> : i64
  %3 = llvm.and %2, %1 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def test19_after := [llvm|
{
^0(%arg178 : i32):
  %0 = llvm.mlir.constant(12345 : i32) : i32
  %1 = llvm.icmp "slt" %arg178, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def mul_splat_fold_too_narrow_before := [llvm|
{
^0(%arg77 : i2):
  %0 = llvm.mlir.constant(-2 : i2) : i2
  %1 = llvm.mlir.constant(1 : i2) : i2
  %2 = llvm.mul %arg77, %0 overflow<nuw> : i2
  %3 = llvm.lshr %2, %1 : i2
  "llvm.return"(%3) : (i2) -> ()
}
]

def Term.quote (t : _root_.Term) : Expr :=
  match t with
  | ofNat n => mkApp (mkConst ``Term.ofNat) (mkNatLit n)
  | var n => mkApp (mkConst ``Term.var) (mkNatLit n)
  | zero => mkConst ``Term.zero
  | one => mkConst ``Term.one
  | negOne => mkConst ``Term.negOne

  
  | neg t => mkApp (mkConst ``Term.neg) (t.quote)
  | not t => mkApp (mkConst ``Term.not) (t.quote)
  | sub t₁ t₂ => mkApp2 (mkConst ``Term.sub) (t₁.quote) (t₂.quote)
  | add t₁ t₂ => mkApp2 (mkConst ``Term.add) (t₁.quote) (t₂.quote)
  | xor t₁ t₂ => mkApp2 (mkConst ``Term.xor) (t₁.quote) (t₂.quote)
  | or t₁ t₂ => mkApp2 (mkConst ``Term.or) (t₁.quote) (t₂.quote)
  | and t₁ t₂ => mkApp2 (mkConst ``Term.and) (t₁.quote) (t₂.quote)
  | shiftL t₁ n => mkApp2 (mkConst ``Term.shiftL) (t₁.quote) (mkNatLit n)

def wrap (bvExpr : FpExpr w) : FpExprWrapper := { bvExpr := bvExpr, width := w}

def test_or_ne_a_b_before := [llvm|
{
^0(%arg15 : i1, %arg16 : i8, %arg17 : i8):
  %0 = llvm.icmp "ne" %arg16, %arg17 : i8
  %1 = llvm.or %arg15, %0 : i1
  %2 = "llvm.select"(%1, %arg16, %arg17) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%2) : (i8) -> ()
}
]

Stream'.tail in Mathlib.Data.Stream.Defs

def wide_source_matching_signbits_before := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.and %arg5, %0 : i32
  %3 = llvm.shl %1, %2 overflow<nsw> : i32
  %4 = llvm.trunc %3 : i32 to i8
  %5 = llvm.sext %4 : i8 to i24
  "llvm.return"(%5) : (i24) -> ()
}
]

RV64.clz in RISCV.Instructions

def p_commutative0_after := [llvm|
{
^0(%arg32 : i32, %arg33 : i32, %arg34 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg34, %arg32 : i32
  %2 = llvm.xor %arg34, %0 : i32
  %3 = llvm.and %arg33, %2 : i32
  %4 = llvm.or disjoint %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test_logical_and_ne_a_b_after := [llvm|
{
^0(%arg3 : i1, %arg4 : i8, %arg5 : i8):
  %0 = "llvm.select"(%arg3, %arg4, %arg5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%0) : (i8) -> ()
}
]

def eq_smax3_after := [llvm|
{
^0(%arg59 : i32, %arg60 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.add %arg59, %0 : i32
  %2 = llvm.icmp "sge" %1, %arg60 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def icmp_slt_0_or_icmp_sgt_0_i64_after := [llvm|
{
^0(%arg73 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.icmp "ne" %arg73, %0 : i64
  %2 = llvm.zext %1 : i1 to i64
  "llvm.return"(%2) : (i64) -> ()
}
]

def shl_C1_add_A_C2_i32_before := [llvm|
{
^0(%arg78 : i16):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(6 : i32) : i32
  %2 = llvm.zext %arg78 : i16 to i32
  %3 = llvm.add %2, %0 : i32
  %4 = llvm.shl %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def udiv_common_divisor_defined_cond_before := [llvm|
{
^0(%arg33 : i1, %arg34 : i5, %arg35 : i5, %arg36 : i5):
  %0 = llvm.udiv %arg35, %arg34 : i5
  %1 = llvm.udiv %arg36, %arg34 : i5
  %2 = "llvm.select"(%arg33, %1, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i5, i5) -> i5
  "llvm.return"(%2) : (i5) -> ()
}
]

def icmp_equality_test_commute_icmp1_after := [llvm|
{
^0(%arg23 : i64, %arg24 : i64, %arg25 : i64):
  %0 = llvm.icmp "eq" %arg24, %arg23 : i64
  "llvm.return"(%0) : (i1) -> ()
}
]

def land_bor_right2_before := [llvm|
{
^0(%arg36 : i1, %arg37 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = "llvm.select"(%arg37, %arg36, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = llvm.or %arg36, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def evalBVExpr (assignments : Std.HashMap Nat BVExpr.PackedBitVec) (expr: GenBVExpr w) : BitVec w :=
  let substitutedBvExpr := substituteBVExpr expr (packedBitVecToSubstitutionValue assignments)
  GenBVExpr.eval assignments substitutedBvExpr

def alive_AndOrXor_144_tgt :=
[sllvm| {
^bb0(%X : i64, %C1 : i64, %C2 : i64):
  %v1 = llvm.and %C1, %C2 : i64
  %v2 = llvm.or %X, %v1 : i64
  %v3 = llvm.or %X, %C1 : i64
  %v4 = llvm.and %v2, %C2 : i64
  llvm.return %v4 : i64
}]

def exact_lshr_eq_opposite_msb_after := [llvm|
{
^0(%arg164 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.icmp "eq" %arg164, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

private def setAnalyzeTrue (opts : Options) : Options :=
     (opts.setBool pp.analyze.name true)
     |>.setBool pp.analyze.checkInstances.name true

StateT in Init.Control.State

def add_or_sub_comb_i8_negative_xor_instead_or_after := [llvm|
{
^0(%arg3 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sub %0, %arg3 : i8
  %2 = llvm.xor %arg3, %1 : i8
  %3 = llvm.add %2, %arg3 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def main7b_after := [llvm|
{
^0(%arg78 : i32, %arg79 : i32, %arg80 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mul %arg80, %0 : i32
  %2 = llvm.or %arg79, %1 : i32
  %3 = llvm.and %arg78, %2 : i32
  %4 = llvm.icmp "ne" %3, %2 : i32
  %5 = llvm.zext %4 : i1 to i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

def icmp_ne_sext_ne_otherwise_i128_before := [llvm|
{
^0(%arg7 : i128):
  %0 = llvm.mlir.constant(2 : i128) : i128
  %1 = llvm.icmp "ne" %arg7, %0 : i128
  %2 = llvm.sext %1 : i1 to i128
  %3 = llvm.icmp "ne" %2, %arg7 : i128
  "llvm.return"(%3) : (i1) -> ()
}
]

def ashrsgt_01_02_before := [llvm|
{
^0(%arg315 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(2 : i4) : i4
  %2 = llvm.ashr %arg315, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def t15_and_with_const1_before := [llvm|
{
^0(%arg3 : i32, %arg4 : i32, %arg5 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.lshr %arg3, %arg4 : i32
  %3 = llvm.and %2, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def positive_samevar_shlnsw_lshrexact_after := [llvm|
{
^0(%arg37 : i8, %arg38 : i8):
  "llvm.return"(%arg37) : (i8) -> ()
}
]

def shift_no_xor_multiuse_cmp_with_xor_before := [llvm|
{
^0(%arg116 : i32, %arg117 : i32, %arg118 : i32, %arg119 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(2 : i32) : i32
  %3 = llvm.and %arg116, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  %5 = llvm.xor %arg117, %2 : i32
  %6 = "llvm.select"(%4, %arg117, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = "llvm.select"(%4, %arg118, %arg119) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %8 = llvm.mul %6, %7 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

def sge_swap_or_max_commute_after := [llvm|
{
^0(%arg178 : i8, %arg179 : i8):
  %0 = llvm.icmp "sle" %arg179, %arg178 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def test1_before := [llvm|
{
^0(%arg0 : i8):
  %0 = llvm.mlir.constant(65544 : i32) : i32
  %1 = llvm.zext %arg0 : i8 to i32
  %2 = llvm.and %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def trunc_ashr_trunc_exact_before := [llvm|
{
^0(%arg6 : i64):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.trunc %arg6 : i64 to i32
  %2 = llvm.ashr exact %1, %0 : i32
  %3 = llvm.trunc %2 : i32 to i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def ult_rem_zero_nsw_before := [llvm|
{
^0(%arg173 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(21 : i8) : i8
  %2 = llvm.mul %arg173, %0 overflow<nsw,nuw> : i8
  %3 = llvm.icmp "ult" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def ult_x_impliesT_eq_umax_todo_before := [llvm|
{
^0(%arg5 : i8, %arg6 : i8, %arg7 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.icmp "ugt" %arg7, %arg5 : i8
  %2 = "llvm.select"(%1, %0, %arg6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.icmp "ne" %2, %arg5 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

inductive TermBinop where
| and | or | xor | add | sub

def toBitVec (w : Nat) (x : BitStream) : BitVec w :=
  match w with
  | 0   => 0#0
  | w+1 => (x.toBitVec w).cons (x w)

def not_cmp_fold_sge : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.icmp.sge %x, %y : i64
      %c = llvm.mlir.constant (-1) : i1
      %1 = llvm.xor %0, %c : i1
      llvm.return %1 : i1
  }]
  rhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.icmp.slt %x, %y : i64
      llvm.return %0 : i1
  }]

def no_shift_no_xor_multiuse_cmp_after := [llvm|
{
^0(%arg108 : i32, %arg109 : i32, %arg110 : i32, %arg111 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg108, %0 : i32
  %3 = llvm.icmp "eq" %2, %1 : i32
  %4 = llvm.or %arg109, %2 : i32
  %5 = "llvm.select"(%3, %arg110, %arg111) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = llvm.mul %4, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

abbrev ExceptM  (_ : Dialect) := Except TransformError

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

Quot in Init.Prelude

def not_signbit_splat_mask2_after := [llvm|
{
^0(%arg107 : i8, %arg108 : i16):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.ashr %arg107, %0 : i8
  %2 = llvm.sext %1 : i8 to i16
  %3 = llvm.and %arg108, %2 : i16
  "llvm.return"(%3) : (i16) -> ()
}
]

def p_commutative0_before := [llvm|
{
^0(%arg32 : i32, %arg33 : i32, %arg34 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg34, %arg32 : i32
  %2 = llvm.xor %arg34, %0 : i32
  %3 = llvm.and %2, %arg33 : i32
  %4 = llvm.xor %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def and_orn_xor_before := [llvm|
{
^0(%arg80 : i4, %arg81 : i4):
  %0 = llvm.mlir.constant(-1 : i4) : i4
  %1 = llvm.xor %arg80, %arg81 : i4
  %2 = llvm.xor %arg80, %0 : i4
  %3 = llvm.or %2, %arg81 : i4
  %4 = llvm.and %3, %1 : i4
  "llvm.return"(%4) : (i4) -> ()
}
]

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

def t0_after := [llvm|
{
^0(%arg10 : i64):
  %0 = llvm.mlir.constant(63) : i64
  %1 = llvm.ashr %arg10, %0 : i64
  %2 = llvm.trunc %1 overflow<nsw> : i64 to i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def xor_or_xor_common_op_commute8_before := [llvm|
{
^0(%arg59 : i32, %arg60 : i32, %arg61 : i32):
  %0 = llvm.xor %arg61, %arg59 : i32
  %1 = llvm.or %arg60, %arg59 : i32
  %2 = llvm.xor %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def not_lshr_const_after := [llvm|
{
^0(%arg135 : i8):
  %0 = llvm.mlir.constant(-43 : i8) : i8
  %1 = llvm.ashr %0, %arg135 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

Setoid in Init.Core

def main5c_like_logical_before := [llvm|
{
^0(%arg101 : i32, %arg102 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.and %arg101, %0 : i32
  %5 = llvm.icmp "ne" %4, %0 : i32
  %6 = llvm.and %arg102, %0 : i32
  %7 = llvm.icmp "ne" %6, %0 : i32
  %8 = "llvm.select"(%5, %1, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %9 = "llvm.select"(%8, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%9) : (i32) -> ()
}
]

def p0_before := [llvm|
{
^0(%arg31 : i8, %arg32 : i8, %arg33 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.and %arg31, %0 : i8
  %2 = llvm.icmp "eq" %1, %0 : i8
  %3 = "llvm.select"(%2, %arg32, %arg33) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%3) : (i8) -> ()
}
]

private def mkAxiomLikeMessage (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (safety : DefinitionSafety) : MetaM MessageData := do
  mkHeader kind id levelParams type safety

def mkTermEnvCons (reader : CollectState)
    (wenv : Expr) (tenv : Expr) (w : MultiWidth.Nondep.WidthExpr) (bv : Expr) : SolverM Expr := do
  let wexpr ← mkWidthExpr reader.wcard w
  let out ← mkAppM (``MultiWidth.Term.Ctx.Env.cons)
    #[ tenv,
      wexpr,
      bv,
      ← mkEqRefl (← mkAppM ``MultiWidth.WidthExpr.toNat #[wexpr, wenv])
      ]
  debugCheck out
  return out

Lean.PrettyPrinter.Formatter in Lean.PrettyPrinter.Formatter
</all_available_defs>

<all_available_lemmas>
List.nodup_singleton in Mathlib.Data.List.Nodup
NFA.eval_append_singleton in Mathlib.Computability.NFA
NFA.eval_nil in Mathlib.Computability.NFA
Set.mem_setOf_eq in Mathlib.Data.Set.Operations
Nat.add_comm in Init.Data.Nat.Basic
Fin.add_def in Init.Data.Fin.Lemmas
Fin.castLE_castLE in Init.Data.Fin.Lemmas
Nat.le_of_eq in Init.Data.Nat.Basic
Nat.mod_eq_of_lt in Init.Data.Nat.Div.Basic
Fin.ext_iff in Init.Data.Fin.Lemmas
Nat.mod_le in Init.Data.Nat.Div.Basic
eq_iff_iff in Init.Core
iff_true in Init.SimpLemmas
ite_cond_eq_true in Init.SimpLemmas
BitVec.toNat_eq in Init.Data.BitVec.Lemmas
le_iff_lt_or_eq in Mathlib.Order.Defs.PartialOrder
Nat.le_antisymm in Init.Prelude
BitVec.toInt_inj in Init.Data.BitVec.Lemmas
BitVec.zero_eq in Init.Data.BitVec.Basic
Finset.mem_range in Mathlib.Data.Finset.Range
Function.iterate_add in Mathlib.Logic.Function.Iterate
eq_of_forall_lt_iff in Mathlib.Order.Basic
gt_iff_lt in Init.Core
Fin.val_one in Init.Data.Fin.Lemmas
eq_iff_eq_of_cmp_eq_cmp in Mathlib.Order.Compare
BitVec.eq_nil in Init.Data.BitVec.Basic
BitVec.getElem_one in Init.Data.BitVec.Lemmas
BitVec.getLsbD_eq_getElem in Init.Data.BitVec.Basic
BitVec.msb_eq_getLsbD_last in Init.Data.BitVec.Lemmas
BitVec.ofNat_eq_ofNat in Init.Data.BitVec.Basic
List.getElem?_eq_getElem in Init.GetElem
List.getLast?_eq_getElem? in Init.Data.List.Lemmas
Set.mem_image in Mathlib.Data.Set.Operations
and_true in Init.SimpLemmas
decide_true in Init.Core

@[ext]
theorem ext {x y : BitStream} (h : ∀ i, x i = y i) : x = y

lemma bisim_comp (m : RawCNFA A) :
    m.Sim M₁ → M₁.Bisim M₂ → m.Sim M₂

lemma bisimul_comp {m : RawCNFA A} :
    m.Simul M₁ R₁ ⊤ ∅ → M₁.Bisimul R₂ M₂ →
    m.Simul M₂ (R₁.comp R₂) ⊤ ∅

lemma CNFA.bv_recognizes_equiv {m : CNFA n} :
    m.bv_recognizes L ↔ ∃ (M : NFA' n), m.Sim M ∧ M.accepts = L

@[simp]
lemma List.Vector.append_get_ge {x : List.Vector α n} {y : List.Vector α m} {i : Fin (n+m)} (hlt: n ≤ i) :
    (x ++ y).get i = y.get ((i.cast (Nat.add_comm n m) |>.subNat n hlt))

@[simp]
lemma List.Vector.append_get_lt {x : List.Vector α n} {y : List.Vector α m} {i : Fin (n+m)} (hlt: i < n) :
    (x ++ y).get i = x.get (i.castLT hlt)

lemma CNFA.minimize_bv_language {m : CNFA n} :
    m.bv_recognizes L → m.minimize.bv_recognizes L

lemma CNFA.minimize_language {m : CNFA n} :
    m.recognizes L → m.minimize.recognizes L

lemma CNFA.reverse_language {m : CNFA n} (hl : m.recognizes L) : m.reverse.recognizes L.reverse

lemma CNFA.reverse_spec {m : CNFA n} : m.reverse.Sim m.toNFA'.reverse

lemma RawCNFA.reverse_spec {m : RawCNFA A} (hwf : m.WF) :
    let m'

lemma RawCNFA.reverse_spec_procesState {m : RawCNFA A} (hwf : m.WF) s₀ a₀ ss' (hs₀ : s₀ ∈ m.states) :
    let motive m' ss'

lemma CNFA.determinize_language {m : CNFA n} :
    m.recognizes L → m.determinize.recognizes L

@[simp]
lemma CNFA.lift_bv_language {m : CNFA n1} {f : Fin n1 → Fin n2} :
    m.bv_recognizes L → (m.lift f |>.bv_recognizes (BitVecs.transport f ⁻¹' L))

lemma CNFA.lift_spec (m : CNFA n1) (f : Fin n1 → Fin n2) {M : NFA' n1} :
    m.Sim M → (m.lift f |>.Sim (M.lift f))

lemma CNFA.proj_bv_language {m : CNFA n2} {f : Fin n1 → Fin n2} :
    m.bv_recognizes L → (m.proj f |>.bv_recognizes (BitVecs.transport f '' L))

@[simp]
lemma BitVecs.transport_getElem {bvs : BitVecs m} (f : Fin n → Fin m) (i : Fin n) :
    (bvs.transport f).bvs.get i = bvs.bvs.get (f i)

lemma simulFun_sim {m : CNFA n} f :
    m.m.SimulFun M.M f → m.Sim M

lemma simulFun_sim_raw [LawfulBEq A] {m : RawCNFA A} (hwf : m.WF) f :
    m.SimulFun M f → m.Sim M

@[simp]
lemma RawCNFA.Simul.initial {m : RawCNFA A} {M : NFA A Q} (hsim : m.Simul M R ⊤ ∅) :
    R.set_eq m.initials.toSet M.start

lemma CNFA.inter_spec (m1 m2 : CNFA n)
  {M1 : NFA' n} {M2 : NFA' n} :
    m1.Sim M1 →
    m2.Sim M2 →
    (m1.inter m2).Sim (M1.inter M2)

lemma CNFA.union_spec (m1 m2 : CNFA n)
  {M1 : NFA' n} {M2 : NFA' n} :
    m1.Sim M1 →
    m2.Sim M2 →
    (m1.union m2).Sim (M1.union M2)

lemma CNFA.addSink_spec (m : CNFA n) (M : NFA' n) :
    m.Sim M →
    m.addSink.Sim M.complete

@[grind ., simp, aesop 50% unsafe]
lemma wf_addTrans [LawfulBEq A] (m : RawCNFA A) (hwf : m.WF) s a s' (hin : s ∈ m.states) (hin' : s' ∈ m.states) :
    (m.addTrans a s s').WF

@[grind =, simp]
lemma RawCNFA.same_stateMax (m : RawCNFA A) x y (z : Std.HashMap (State × A) (Std.HashSet State)) :
    (RawCNFA.mk m.stateMax x y z).states = m.states

@[grind =, simp, aesop 50% unsafe]
lemma newState_eq (m : RawCNFA A) :
    m.newState.1 = m.stateMax

@[grind =, simp]
lemma addInitial_stateMax {m : RawCNFA A} : (m.addInitial s).stateMax = m.stateMax

@[grind =, simp]
lemma addTrans_stateMax {m : RawCNFA A} : (m.addTrans a s s').stateMax = m.stateMax

@[simp]
lemma dec_enc' : dec (enc bvs) = bvs

@[simp]
lemma dec_enc : Function.RightInverse (α := BitVecs' n) enc dec

lemma dec_enc_w (bvs : BitVecs n) : (dec (enc bvs)).w = bvs.w

@[simp]
theorem BitVec.ofFn_getElem {w : Nat} (f : Fin w → Bool) {i : Nat} (hi : i < w) :
    (BitVec.ofFn f)[i] = f ⟨i, hi⟩

@[simp]
theorem BitVec.ofFn_getLsbD {w : Nat} {f : Fin w → Bool} {i : Nat} (hi : i < w) :
    (BitVec.ofFn f).getLsbD i = f ⟨i, hi⟩

theorem BitVec.ofFn_getLsbD_fin {w : Nat} {f : Fin w → Bool} {i : Fin w} :
    (BitVec.ofFn f).getLsbD i = f i

theorem test_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (13#32 <ᵤ x) &&& ofBool (x == 15#32) = ofBool (x == 15#32)

theorem zext_sext_add_icmp_slt_2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ofBool (zeroExtend 8 x_1 + signExtend 8 x <ₛ 2#8) = 1#1

theorem lshr_mul_negative_nsw_thm (e : IntW 64) :
  lshr (mul e (const? 64 52) { «nsw» := true, «nuw» := false }) (const? 64 2) ⊑
    lshr (mul e (const? 64 52) { «nsw» := true, «nuw» := false }) (const? 64 2) { «exact» := true }

theorem test22_proof : test22_before ⊑ test22_after

theorem bv_AddSub_1539_2 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.sub e e_1 ⊑ LLVM.add e (LLVM.neg e_1)

theorem sge_smin4_thm (e e_1 : IntW 32) :
  icmp IntPred.sle (add e_1 (const? 32 3))
      (select (icmp IntPred.slt e (add e_1 (const? 32 3))) e (add e_1 (const? 32 3))) ⊑
    icmp IntPred.sge e (add e_1 (const? 32 3))

theorem ne_commuted_equal_minus_1_proof : ne_commuted_equal_minus_1_before ⊑ ne_commuted_equal_minus_1_after

theorem slt_or_not_max_commute_logical_proof : slt_or_not_max_commute_logical_before ⊑ slt_or_not_max_commute_logical_after

theorem lowmask_sub_zext_commute_thm.extracted_1._1 : ∀ (x : BitVec 5) (x_1 : BitVec 17),
  x_1 - zeroExtend 17 x &&& 31#17 = zeroExtend 17 (truncate 5 x_1 - x)

@[simp] lemma BitVec.lk31 : (3#2 : BitVec 2)[1] = true

theorem not_lt_is_geq {a b: Nat} (NOT_LT: ¬ (a < b)): a >= b

theorem lshr_not_nneg2_proof : lshr_not_nneg2_before ⊑ lshr_not_nneg2_after

theorem t2_ashr_proof : t2_ashr_before ⊑ t2_ashr_after

theorem different_size_zext_zext_sgt_thm (e : IntW 4) (e_1 : IntW 7) :
  icmp IntPred.sgt (zext 25 e_1) (zext 25 e) ⊑ icmp IntPred.ugt e_1 (zext 7 e)

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

theorem invert_both_cmp_operands_sub_proof : invert_both_cmp_operands_sub_before ⊑ invert_both_cmp_operands_sub_after

theorem self_EqualUpTo_ofBitVecZext_toBitVec (x : BitStream) :
  EqualUpTo w x (BitStream.ofBitVecZext (x.toBitVec w))

theorem test15_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(x ≥ ↑32 ∨ zeroExtend 64 (1#32 <<< x) = 0) →
    True ∧ ((-1#32) <<< x).sshiftRight' x ≠ -1#32 ∨ x ≥ ↑32 ∨ True ∧ (x_1 &&& ((-1#32) <<< x ^^^ -1#32)).msb = true →
      False

theorem src_is_notmask_neg_p2_fail_not_invertable_proof : src_is_notmask_neg_p2_fail_not_invertable_before ⊑ src_is_notmask_neg_p2_fail_not_invertable_after

theorem mul_select_zext_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  x_1 = 1#1 → x * zeroExtend 64 x_1 = x

theorem add_mask_sign_i32_proof : add_mask_sign_i32_before ⊑ add_mask_sign_i32_after

theorem or_or_logic_and_2_thm.extracted_1._5 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 ||

theorem t14_x_is_one_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(32#32 - x ≥ ↑32 ∨ zeroExtend 64 (x + BitVec.ofInt 32 (-16)) ≥ ↑64) →
    ofBool (x_1 <<< (32#32 - x) &&& truncate 32 (1#64 >>> zeroExtend 64 (x + BitVec.ofInt 32 (-16))) != 0#32) = 0#1

theorem p0_proof : p0_before ⊑ p0_after

theorem t22_sign_check2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (-1#32 <ₛ x) = 1#1 → ofBool (x <ₛ 0#32) = 1#1 → False

theorem zext_sext_add_icmp_ugt_1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ofBool (1#8 <ᵤ zeroExtend 8 x_1 + signExtend 8 x) = x &&& (x_1 ^^^ 1#1)

theorem xor_and_logic_or2_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 1),
  x = 1#1 → ¬x_1 = 1#1 → x_2 &&& x_1 ^^^ 1#1 = x

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

theorem test22_proof : test22_before ⊑ test22_after

theorem positive_samevar_shlnuw_lshrexact_proof : positive_samevar_shlnuw_lshrexact_before ⊑ positive_samevar_shlnuw_lshrexact_after

theorem p_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ (x_2 &&& x_1 &&& (x &&& (x_1 ^^^ -1#32)) != 0) = true) →
    x_2 &&& x_1 ^^^ (x_1 ^^^ -1#32) &&& x = x_2 &&& x_1 ||

theorem missed_const_prop_2002h12h05_thm (e : IntW 32) :
  add (sub (const? 32 0) e) (add e (add (sub (const? 32 0) (const? 32 1)) (const? 32 1))) ⊑ const? 32 0

theorem negate_ashr_proof : negate_ashr_before ⊑ negate_ashr_after

theorem alive_Select_858  (w : Nat)   : alive_Select_858_src w  ⊑ alive_Select_858_tgt 1

theorem e_1053 :
     - 2 * (z |||  ~~~t) + 5 *  ~~~z - 6 *  ~~~t + 3 *  ~~~(z ||| t) - 4 *  ~~~(z |||  ~~~t) + 9 * (z &&&  ~~~t) + 2 * (z &&& t) = 1 * (z ^^^ t)

theorem and_nosignbit_select_shl_proof : and_nosignbit_select_shl_before ⊑ and_nosignbit_select_shl_after

theorem test_add_nuw_nsw__all_are_safe_proof : test_add_nuw_nsw__all_are_safe_before ⊑ test_add_nuw_nsw__all_are_safe_after

theorem e_419 :
    4 * (x ||| y) - 1 *  ~~~y + 2 *  ~~~(x &&& y) + 3 *  ~~~(x &&&  ~~~y) - 4 *  ~~~(x ||| y) - 14 *  ~~~(x |||  ~~~y) - 10 * (x &&&  ~~~y) - 7 * (x &&& y) =  - 5 * (x ^^^ y)

theorem testi64i32_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬63#64 ≥ ↑64 → ¬ofBool (-1#64 <ₛ x) = 1#1 → truncate 32 (x.sshiftRight' 63#64) ^^^ 127#32 = BitVec.ofInt 32 (-128)

theorem test11_proof : test11_before ⊑ test11_after

theorem masked_and_notA_slightly_optimized_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (8#32 ≤ᵤ x) = 1#1 → 0#1 = ofBool (x &&& BitVec.ofInt 32 (-40) != 0#32)

theorem masked_icmps_mask_notallzeros_bmask_mixed_swapped_6_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 15#32 == 8#32) = 1#1 → ofBool (x &&& 12#32 != 0#32) = ofBool (x &&& 15#32 == 8#32)

theorem main7f_logical_thm.extracted_1._6 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ¬ofBool (x_3 &&& x_2 == x_1 &&& (x_3 &&& x_2)) = 1#1 →
    ofBool (x_3 &&& x_2 != x_1 &&& (x_3 &&& x_2)) = 1#1 → ¬0#1 = 1#1 → 1#32 = zeroExtend 32 1#1

theorem e_1782 :
    11 * (b ^^^ (a ||| ( ~~~b &&& c))) + 1 * ((a &&& b) |||  ~~~(b |||  ~~~c)) + 7 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 6 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) + 2 * (a ^^^ ( ~~~b ||| c)) - 3 * (c ^^^  ~~~(a ||| (b &&& c))) + 2 * (b ^^^ (a ||| ( ~~~b ||| c))) + 11 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 6 * (a ||| b) - 2 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 5 * (a &&&  ~~~b) + 2 *  ~~~(a ^^^ (b ^^^ c)) + 4 * (c &&&  ~~~(a &&&  ~~~b)) + 1 * (b |||  ~~~(a ^^^ c)) - 2 *  ~~~( ~~~a ||| (b ^^^ c)) - 2 *  ~~~(a |||  ~~~b) + 11 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) - 6 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 3 * (a ^^^ b) - 3 *  ~~~(a &&& ( ~~~b &&& c)) - 1 * (b ^^^  ~~~(a &&& c)) + 1 *  ~~~( ~~~a &&& (b ^^^ c)) - 1 *  ~~~(a ^^^ ( ~~~b &&& c)) - 2 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 3 * (b ^^^ (a &&& (b ^^^ c))) + 11 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) - 6 *  ~~~a + 3 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 3 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 4 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) - 6 *  ~~~(a ||| (b ||| c)) - 13 *  ~~~( ~~~a ||| (b ||| c)) - 20 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 40 * ( ~~~a &&& ( ~~~b &&& c)) - 5 * ( ~~~a &&& (b &&& c)) - 35 * (a &&& ( ~~~b &&& c)) + 15 * (a &&& (b &&& c)) =  - 1 *  ~~~(a &&& (b &&& c)) + 3 *  ~~~(a |||  ~~~c)

theorem sgt_or_not_min_proof : sgt_or_not_min_before ⊑ sgt_or_not_min_after

@[symm] theorem Bisim.symm {a b : Stream α} : a ~ b → b ~ a

theorem icmp_select_var_select_thm.extracted_1._15 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  ¬x_2 = 1#1 →
    ofBool (x_1 == 0#8) = 1#1 ∧ x_2 = 1#1 →
      ¬ofBool (x_1 == 0#8) = 1#1 → ¬x_2 ^^^ 1#1 = 1#1 → ofBool (x == x_1) = ofBool (x_1 == x)

theorem t7_ugt_sgt_neg1_thm.extracted_1._6 : ∀ (x x_1 : BitVec 32),
  ofBool (65535#32 <ᵤ x_1) = 1#1 → ¬ofBool (-1#32 <ₛ x_1) = 1#1 → ofBool (65535#32 <ₛ x_1) = 1#1 → False

theorem add_umax_simplify2_proof : add_umax_simplify2_before ⊑ add_umax_simplify2_after

theorem icmp_shl_nsw_sgt_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ (x <<< 21#32).sshiftRight' 21#32 ≠ x ∨ 21#32 ≥ ↑32) → ofBool (0#32 <ₛ x <<< 21#32) = ofBool (0#32 <ₛ x)

theorem lowmask_xor_zext_commute_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  (x_1 * x_1 ^^^ zeroExtend 32 x) &&& 255#32 = zeroExtend 32 (x ^^^ truncate 8 (x_1 * x_1))

theorem test_and4_logical_thm (e e_1 : IntW 32) :
  select (icmp IntPred.sge (LLVM.and e_1 (const? 32 2147483647)) e) (icmp IntPred.sge e (const? 32 0))
      (const? 1 0) ⊑
    icmp IntPred.ule e (LLVM.and e_1 (const? 32 2147483647))

theorem test_sub_nuw_nsw__nuw_is_safe_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 2147483647#32 == 1073741824#32) = 1#1 →
    True ∧ (BitVec.ofInt 32 (-2147483648)).usubOverflow (x &&& 2147483647#32) = true → False

theorem slt_0_proof : slt_0_before ⊑ slt_0_after

theorem scalar_i32_signbit_lshr_and_eq_proof : scalar_i32_signbit_lshr_and_eq_before ⊑ scalar_i32_signbit_lshr_and_eq_after

theorem and_zext_zext_thm.extracted_1._1 : ∀ (x : BitVec 4) (x_1 : BitVec 8),
  True ∧ (x_1 &&& zeroExtend 8 x).msb = true → False

theorem if_false' {t : Arith.Ty} (cond : Var Γ Arith.Ty.bool) (hcond : Γv cond = false)
    (v : Var Γ t) (then_ else_ : Com ScfArith ⟨[t]⟩ .impure t) :
    Expr.denote (if_ (t := t) cond v then_ else_) Γv
    = Expr.denote (run (t := t) v else_) Γv

theorem trunc_shl_31_i32_i64_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬31#64 ≥ ↑64 → ¬31#32 ≥ ↑32 → truncate 32 (x <<< 31#64) = truncate 32 x <<< 31#32

theorem trunc_shl_15_i16_i64_proof : trunc_shl_15_i16_i64_before ⊑ trunc_shl_15_i16_i64_after

theorem sext_xor_sub_proof : sext_xor_sub_before ⊑ sext_xor_sub_after

theorem main2_logical_thm (e : IntW 32) :
  select
      (select (icmp IntPred.eq (LLVM.and e (const? 32 1)) (const? 32 0)) (const? 1 1)
        (icmp IntPred.eq (LLVM.and e (const? 32 2)) (const? 32 0)))
      (const? 32 0) (const? 32 1) ⊑
    zext 32 (icmp IntPred.eq (LLVM.and e (const? 32 3)) (const? 32 3))

theorem select_icmp_sgt_allones_smin_flipped_thm (e : IntW 8) :
  select (icmp IntPred.sgt e (const? 8 (-1))) (LLVM.xor e (const? 8 (-128))) e ⊑
    LLVM.or e (const? 8 (-128))

theorem sub_undemanded_low_bits_proof : sub_undemanded_low_bits_before ⊑ sub_undemanded_low_bits_after

theorem lowmask_sub_zext_commute_proof : lowmask_sub_zext_commute_before ⊑ lowmask_sub_zext_commute_after

theorem e_2298 :
     - 1 * ( ~~~d &&& ( ~~~e ||| f)) - 5 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 5 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 1 *  ~~~(e ^^^ f) + 1 * (f &&& (d ^^^ e)) - 3 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 2 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 3 * ((d ^^^ e) &&& (d ^^^ f)) + 3 *  ~~~(d ^^^ (e ||| f)) + 1 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 2 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 3 * ( ~~~d ||| ( ~~~e &&& f)) + 7 * (e ^^^  ~~~(d |||  ~~~f)) + 4 * (e ||| f) + 7 * (d ||| (e ^^^ f)) + 1 * ((d &&& e) |||  ~~~(e ||| f)) - 3 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) - 3 * e - 2 * ( ~~~f &&&  ~~~(d ^^^ e)) + 1 *  ~~~f + 1 * (f ^^^ (d &&& (e ||| f))) + 11 * (e ^^^ ( ~~~d ||| (e &&& f))) - 3 * (f ^^^ ( ~~~d &&& (e ||| f))) - 6 * (e ||| (d &&&  ~~~f)) + 5 * (e ^^^ (d ||| ( ~~~e &&& f))) + 4 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 1 * (f &&&  ~~~(d &&&  ~~~e)) - 5 * (e ^^^  ~~~(d &&& (e ^^^ f))) + 3 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 1 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 2 * (e ^^^ (d ||| (e &&& f))) - 6 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) - 7 * (f ||| (d &&&  ~~~e)) - 6 *  ~~~(d &&&  ~~~d) - 7 *  ~~~e - 1 * (f &&& (d ||| e)) + 5 * (f ^^^ (d ||| e)) - 1 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 11 * ( ~~~e ||| (d ^^^ f)) + 1 * (e &&&  ~~~(d ^^^ f)) - 1 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) + 2 * ( ~~~d &&& (e ^^^ f)) - 5 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 3 * (e ^^^ (d &&& (e ^^^ f))) - 2 * (f ^^^ (d ||| (e &&& f))) + 7 * (f ^^^ (d |||  ~~~e)) - 6 * (d |||  ~~~f) - 1 * (e ||| (d ^^^ f)) + 1 *  ~~~(d ||| (e &&& f)) + 1 * (e |||  ~~~f) - 1 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) + 1 * (e ^^^ f) - 11 * (f ^^^  ~~~(d &&& e)) + 2 * ( ~~~d ||| (e ^^^ f)) + 35 *  ~~~(d ||| (e ||| f)) - 3 *  ~~~(d ||| ( ~~~e ||| f)) + 53 *  ~~~( ~~~d ||| (e ||| f)) - 12 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 2 * ( ~~~d &&& ( ~~~e &&& f)) + 24 * ( ~~~d &&& (e &&& f)) + 19 * (d &&& ( ~~~e &&& f)) + 21 * (d &&& (e &&& f)) = 1 * (f ^^^ (d ||| ( ~~~e &&& f))) - 1 * (f ^^^ (d ||| (e ||| f)))

theorem test_sext4_thm.extracted_1._5 : ∀ (x x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬x_1 ^^^ 1#1 = 1#1 → -1#32 = signExtend 32 x

theorem fold_sext_to_and_wrong4_proof : fold_sext_to_and_wrong4_before ⊑ fold_sext_to_and_wrong4_after

theorem wrongimm_thm (e : IntW 16) :
  LLVM.xor (trunc 8 (ashr e (const? 16 14))) (const? 8 27) ⊑
    LLVM.xor (trunc 8 (ashr e (const? 16 14)) { «nsw» := true, «nuw» := false }) (const? 8 27)

theorem scalar_i32_lshr_and_negC_eq_X_is_constant2_thm (e : IntW 32) :
  icmp IntPred.eq (LLVM.and (lshr (const? 32 (-2147483648)) e) (const? 32 (-2147483648))) (const? 32 0) ⊑
    icmp IntPred.ne e (const? 32 0)

theorem ugt_3_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (3#8 <ᵤ truncate 8 x) = ofBool (x &&& 252#32 != 0#32)

theorem t6_shl_proof : t6_shl_before ⊑ t6_shl_after

theorem toTensor_fromTensor [hqgt1 : Fact (q > 1)] (tensor : List Int) (i : Nat)
  (htensorlen : List.length tensor < 2 ^ n) :
  (R.fromTensor tensor (q:=q) (n :=n)).toTensor.getD i 0 = (tensor.getD i 0) % q

theorem test_add__nsw_is_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x ||| BitVec.ofInt 32 (-2147483648) == -1#32) = 1#1 →
    ¬(True ∧ (x ||| BitVec.ofInt 32 (-2147483648)).saddOverflow 1#32 = true) →
      0#32 = (x ||| BitVec.ofInt 32 (-2147483648)) + 1#32

theorem alive_Select_705 : forall (w : Nat) (A B : Bitvec 1)
, TSSA.eval
  (Op := Op) (e := e)
  (i := TSSAIndex.STMT (UserType.base (BaseType.bitvec 1)))
  [dsl_bb|
  ^bb
  %v0 := unit: ;
  %v1 := op:const (A) %v0;
  %v2 := op:const (B) %v0;
  %v3 := pair:%v1 %v2;
  %v4 := op:icmp sge  w %v3;
  %v5 := triple:%v4 %v1 %v2;
  %v6 := op:select 1 %v5;
  %v7 := pair:%v6 %v1;
  %v8 := op:icmp slt  w %v7;
  %v9 := triple:%v8 %v6 %v1;
  %v10 := op:select 1 %v9
  dsl_ret %v10
  ]  ⊑
  TSSA.eval
  (Op := Op) (e := e)
  (i := TSSAIndex.STMT (UserType.base (BaseType.bitvec 1)))
  [dsl_bb|
  ^bb
  %v0 := unit: ;
  %v1 := op:const (A) %v0;
  %v2 := op:const (B) %v0;
  %v3 := pair:%v1 %v2;
  %v4 := op:icmp sge  1 %v3;
  %v5 := triple:%v4 %v1 %v2;
  %v6 := op:select 1 %v5;
  %v7 := pair:%v6 %v1;
  %v8 := op:icmp slt  1 %v7;
  %v9 := op:copy 1 %v1
  dsl_ret %v9
  ]

theorem ashr_sle_noexact_proof : ashr_sle_noexact_before ⊑ ashr_sle_noexact_after

theorem t4_ugt_slt_128_thm.extracted_1._10 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (143#32 <ᵤ x_2 + 16#32) = 1#1 → ofBool (x_2 <ₛ 128#32) = 1#1 → ofBool (127#32 <ₛ x_2) = 1#1 → x_1 = x

theorem mul_of_sdiv_proof : mul_of_sdiv_before ⊑ mul_of_sdiv_after

theorem test_or_ne_a_b_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  ¬x_2 ||

theorem BitVec.odd_mul_eq_shiftLeft_mul_of_eq_mul_two_add_one (w : Nat) (x : BitVec w) (n o : Nat)
    (ho : o = n * 2 + 1) : (BitVec.ofNat w o) * x = x + (BitVec.ofNat w n) * (x <<< (1 : Nat))

theorem slt_swap_or_not_max_commute_proof : slt_swap_or_not_max_commute_before ⊑ slt_swap_or_not_max_commute_after

theorem testi64i32_proof : testi64i32_before ⊑ testi64i32_after

theorem eq_10_thm (e e_1 : IntW 32) :
  LLVM.and (icmp IntPred.eq (trunc 8 e_1) (trunc 8 e))
      (icmp IntPred.eq (trunc 8 (lshr e_1 (const? 32 8))) (trunc 8 (lshr e (const? 32 8)))) ⊑
    icmp IntPred.eq (trunc 16 e_1) (trunc 16 e)

theorem bools2_logical_commute1_thm.extracted_1._19 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬x_1 ^^^ 1#1 = 1#1 → x_1 = 1#1 → ¬0#1 = 1#1 → 0#1 = x_2

theorem shl_and_proof : shl_and_before ⊑ shl_and_after

theorem positive_biggerashr_shlnuw_ashrexact_proof : positive_biggerashr_shlnuw_ashrexact_before ⊑ positive_biggerashr_shlnuw_ashrexact_after

theorem lshrugt_03_02_exact_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 3) { «exact» := true }) (const? 4 2) ⊑ const? 1 0

theorem and_logic_and_logic_or_3_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 &&& x_1 = 1#1 → x_1 = 1#1 → ¬x_2 = 1#1 → 1#1 = x

theorem ult_rem_zero_nsw_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.smulOverflow 7#8 = true ∨ True ∧ x.umulOverflow 7#8 = true) →
    ofBool (x * 7#8 <ᵤ 21#8) = ofBool (x <ᵤ 3#8)

theorem negate_select_of_op_vs_negated_op_nsw_commuted_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 1)
  (x_2 : BitVec 8), ¬x_1 = 1#1 → ¬(True ∧ (0#8).ssubOverflow x = true) → x_2 - (0#8 - x) = x + x_2

theorem e_1607 :
    1 * ( ~~~c |||  ~~~(a ^^^ b)) + 5 * (b ^^^  ~~~(a |||  ~~~c)) - 3 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 11 * (b ^^^  ~~~(a &&&  ~~~c)) + 7 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) - 2 * (b ^^^ c) - 2 * (b ||| (a &&&  ~~~c)) + 2 * (c ^^^  ~~~(a |||  ~~~b)) + 4 * (c ||| (a &&&  ~~~b)) + 4 *  ~~~(a ^^^ ( ~~~b ||| c)) - 1 * ((a &&& b) ^^^ (b ||| c)) - 3 * (b ^^^  ~~~( ~~~a ||| (b ^^^ c))) - 16 *  ~~~(a ||| (b ||| c)) - 8 *  ~~~(a ||| ( ~~~b ||| c)) - 1 *  ~~~( ~~~a ||| (b ||| c)) - 14 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 20 * ( ~~~a &&& ( ~~~b &&& c)) + 2 * ( ~~~a &&& (b &&& c)) - 21 * (a &&& (b &&& c)) = 22 * (a &&& ( ~~~b &&& c))

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_0_logical_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 12)) (const? 32 0)) (const? 1 1)
      (icmp IntPred.ne (LLVM.and e (const? 32 3)) (const? 32 1)) ⊑
    LLVM.or (icmp IntPred.eq (LLVM.and e (const? 32 12)) (const? 32 0))
      (icmp IntPred.ne (LLVM.and e (const? 32 3)) (const? 32 1))

theorem udiv_x_by_const_cmp_x_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬123#32 = 0 → ofBool (x / 123#32 <ₛ x) = ofBool (0#32 <ₛ x)

theorem ne_21_logical_thm (e e_1 : IntW 32) :
  select (icmp IntPred.ne (trunc 8 (lshr e_1 (const? 32 16))) (trunc 8 (lshr e (const? 32 16)))) (const? 1 1)
      (icmp IntPred.ne (trunc 8 (lshr e_1 (const? 32 8))) (trunc 8 (lshr e (const? 32 8)))) ⊑
    icmp IntPred.ne (trunc 16 (lshr e_1 (const? 32 8))) (trunc 16 (lshr e (const? 32 8)))

theorem e_1974 :
    3 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) - 2 * (a ^^^ ( ~~~b &&& c)) + 5 * (a ||| b) + 7 * (a ||| c) - 7 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 1 * (a ^^^ (b &&& c)) - 3 *  ~~~( ~~~a ||| (b ^^^ c)) + 2 * ((a ||| b) &&& (b ^^^ c)) - 1 * (c ^^^  ~~~(a ||| b)) + 4 * ( ~~~a &&& (b ^^^ c)) - 11 * (a ||| (b ||| c)) + 3 *  ~~~c - 3 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) - 2 * (b ^^^ (a &&& (b ^^^ c))) + 1 * (a ||| ( ~~~b ||| c)) + 1 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) + 11 * b - 5 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 5 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) + 7 * (c &&&  ~~~(a &&&  ~~~b)) - 1 * ((a &&& c) ^^^ (b ||| c)) - 5 * ( ~~~(a ||| b) ||| (b ^^^ c)) + 4 * ( ~~~b &&& (a ^^^ c)) + 1 * (b &&&  ~~~c) - 2 * (c ^^^ (a ||| (b &&& c))) - 11 * (b &&& (a ||| c)) - 2 * (c ^^^ (a ||| ( ~~~b &&& c))) - 1 *  ~~~(b &&& c) + 2 * (c &&& (a |||  ~~~b)) - 1 * (c ^^^ (a &&& ( ~~~b ||| c))) - 1 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c))) + 2 * (a &&& (b ||| c)) - 1 * (c ^^^  ~~~(a &&&  ~~~b)) + 2 * (b &&&  ~~~(a &&& c)) - 7 *  ~~~( ~~~a &&& (b &&& c)) - 5 * ((a &&& b) |||  ~~~(b ^^^ c)) + 3 * (a ^^^ (b ||| c)) + 11 * (a ||| ( ~~~b &&& c)) + 5 * (b ^^^  ~~~(a &&& (b ^^^ c))) + 1 * ((a &&& b) |||  ~~~(b ||| c)) + 7 * ((a &&& c) ^^^ (a ^^^ (b &&& c))) + 1 *  ~~~(a ||| c) + 2 * (b ^^^  ~~~(a &&& (b ||| c))) + 7 * ( ~~~b |||  ~~~(a ^^^ c)) - 7 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) - 1 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 1 * ((a &&& b) ^^^ (b ||| c)) - 6 * (b ^^^ ( ~~~a ||| (b ^^^ c))) - 6 * (b |||  ~~~(a |||  ~~~c)) + 7 *  ~~~(a ||| (b ||| c)) - 4 *  ~~~(a ||| ( ~~~b ||| c)) - 7 *  ~~~( ~~~a ||| (b ||| c)) - 4 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 8 * ( ~~~a &&& (b &&& c)) + 5 * (a &&& ( ~~~b &&& c)) + 10 * (a &&& (b &&& c)) =  - 7 * (b ||| (a ^^^ c))

theorem fold_sext_to_and_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (signExtend 32 x &&& BitVec.ofInt 32 (-2147483647) == 1#32) = ofBool (x &&& BitVec.ofInt 8 (-127) == 1#8)

theorem pv_proof : pv_before ⊑ pv_after

theorem test68_proof : test68_before ⊑ test68_after

@[bv_multi_width_normalize]
theorem ult_iff_ule_eq_false {a b : BitVec w} : a.ule b = false ↔ b.ult a

theorem udiv_shl_mul_nuw_swap_thm (e e_1 e_2 : IntW 5) :
  LLVM.udiv (shl e_2 e_1 { «nsw» := false, «nuw» := true }) (mul e e_2 { «nsw» := false, «nuw» := true }) ⊑
    LLVM.udiv (shl (const? 5 1) e_1 { «nsw» := false, «nuw» := true }) e

theorem logic_and_logic_or_4_thm.extracted_1._5 : ∀ (x x_1 : BitVec 1), ¬x_1 = 1#1 → ¬x = 1#1 → 0#1 = 1#1 → 1#1 = 0#1

theorem t2_ashr_proof : t2_ashr_before ⊑ t2_ashr_after

theorem test_shl_nuw_nsw__all_are_safe_thm.extracted_1._4 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 15#32 == 0#32) = 1#1 →
    ¬(True ∧ ((x_1 &&& 15#32) <<< 2#32).sshiftRight' 2#32 ≠ x_1 &&& 15#32 ∨
          True ∧ (x_1 &&& 15#32) <<< 2#32 >>> 2#32 ≠ x_1 &&& 15#32 ∨
            2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& 15#32) <<< 2#32) ≥ ↑64) →
      ¬(2#32 ≥ ↑32 ∨ True ∧ (x_1 <<< 2#32 &&& 60#32).msb = true ∨ zeroExtend 64 (x_1 <<< 2#32 &&& 60#32) ≥ ↑64) →
        x.sshiftRight' (zeroExtend 64 ((x_1 &&& 15#32) <<< 2#32)) =
          x.sshiftRight' (zeroExtend 64 (x_1 <<< 2#32 &&& 60#32))

theorem test71_proof : test71_before ⊑ test71_after

theorem lshrugt_02_08_exact_proof : lshrugt_02_08_exact_before ⊑ lshrugt_02_08_exact_after

theorem e_1702 :
    2 *  ~~~(a &&& (b &&& c)) - 1 * (a &&&  ~~~c) - 7 *  ~~~(a ^^^ (b ^^^ c)) + 11 * (b ^^^ (a ||| c)) - 6 * (a &&& (b ^^^ c)) + 1 *  ~~~(a ^^^ (b &&& c)) + 11 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 7 * (b ^^^  ~~~(a ||| c)) - 2 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) - 2 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) + 2 * (b ^^^  ~~~(a &&&  ~~~c)) - 5 * a + 11 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) + 7 * (a ||| (b &&& c)) - 1 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 1 * (b ||| (a &&&  ~~~c)) + 3 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) - 1 *  ~~~(a &&&  ~~~c) + 5 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 4 * (c ^^^ (a ||| b)) + 7 * (c |||  ~~~(a ||| b)) - 23 *  ~~~(a ||| (b ||| c)) - 41 *  ~~~(a ||| ( ~~~b ||| c)) - 31 *  ~~~( ~~~a ||| (b ||| c)) - 16 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 42 * ( ~~~a &&& ( ~~~b &&& c)) - 25 * ( ~~~a &&& (b &&& c)) - 27 * (a &&& ( ~~~b &&& c)) - 28 * (a &&& (b &&& c)) = 2 * (b ^^^  ~~~(a &&& (b ^^^ c))) - 5 * ((a |||  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c)))

theorem select_zext_or_eq_ult_add_thm (e : IntW 32) :
  select (icmp IntPred.ult (add e (const? 32 (-3))) (const? 32 2)) (const? 32 1)
      (zext 32 (icmp IntPred.eq e (const? 32 5))) ⊑
    zext 32 (icmp IntPred.ult (add e (const? 32 (-3))) (const? 32 3))

theorem bools2_logical_commute0_and2_thm.extracted_1._9 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬0#1 = 1#1 → (x_2 ^^^ 1#1) &&& x = x

@[simp] theorem Hom.castDomain_rfl {h : Δ = Δ} {f : Γ.Hom Δ} :
    (f.castCodomain h) = f

theorem e_1207 :
     - 6 * (z ^^^ t) + 2 *  ~~~z - 11 * z - 11 *  ~~~(z &&& t) + 3 *  ~~~(z &&&  ~~~t) + 6 *  ~~~(z ||| t) + 10 *  ~~~(z |||  ~~~t) + 26 * (z &&&  ~~~t) + 6 * (z &&& t) =  - 2 * (z ||| t)

theorem e_1522 :
     - 6 * (c ^^^  ~~~(a &&& (b &&& c))) + 2 * (c ^^^ (a ||| ( ~~~b &&& c))) - 2 *  ~~~( ~~~a &&& (b ^^^ c)) + 7 *  ~~~(a ||| (b ||| c)) + 5 *  ~~~(a ||| ( ~~~b ||| c)) + 6 *  ~~~( ~~~a ||| (b ||| c)) + 6 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 1 * ( ~~~a &&& ( ~~~b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) + 8 * (a &&& (b &&& c)) =  - 1 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c)))

theorem lshrugt_02_11_proof : lshrugt_02_11_before ⊑ lshrugt_02_11_after

theorem e_665 :
    1 *  ~~~(x &&&  ~~~y) - 1 * (x ^^^ y) - 2 * x + 3 *  ~~~(x ^^^ y) - 5 * (x ||| y) - 11 * y - 7 *  ~~~(x ||| y) + 13 *  ~~~(x |||  ~~~y) + 5 * (x &&&  ~~~y) + 11 * (x &&& y) =  - 3 *  ~~~(x &&&  ~~~x)

theorem test_zext2_proof : test_zext2_before ⊑ test_zext2_after

theorem shift_xor_multiuse_cmp_or_thm.extracted_1._3 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ofBool (0#32 != x_3 &&& 4096#32) = 1#1 →
    ofBool (x_3 &&& 4096#32 == 0#32) = 1#1 →
      x_2 * x_1 * (x_2 ||| 2048#32) = (x_2 ||| 2048#32) * x * (x_2 ||| 2048#32)

theorem t0_commutative_thm.extracted_1._23 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1) (x_3 x_4 : BitVec 8),
  ¬ofBool (x_4 == x_3) = 1#1 → ¬ofBool (x_4 != x_3) = 1#1 → x_2 ^^^ 1#1 = 1#1 → 0#1 = 1#1 → x_1 = x

theorem sgt_or_not_min_commute_logical_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != BitVec.ofInt 8 (-128)) = 1#1 → ofBool (x <ₛ x_1) = ofBool (x_1 != BitVec.ofInt 8 (-128))

theorem lshr_and_or_proof : lshr_and_or_before ⊑ lshr_and_or_after

theorem alive_AndOrXor_2231__A__B__B__C__A___A__B__C  (w : Nat)   : alive_AndOrXor_2231__A__B__B__C__A___A__B__C_src w  ⊑ alive_AndOrXor_2231__A__B__B__C__A___A__B__C_tgt w

theorem t5_ugt_slt_0_thm.extracted_1._6 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (143#32 <ᵤ x_1 + 16#32) = 1#1 → ofBool (127#32 <ₛ x_1) = 1#1 → x_1 = x

theorem e_2307 :
    1 * (e &&&  ~~~f) - 2 *  ~~~(d &&&  ~~~e) + 1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 1 * (e ^^^ (d &&&  ~~~f)) + 2 * ((e &&& f) ^^^  ~~~(d &&& (e ^^^ f))) + 5 * (f ^^^ (d &&& (e ||| f))) + 3 * (d ||| (e &&& f)) + 7 *  ~~~(d &&&  ~~~f) + 11 * (e ^^^ ( ~~~d &&& (e ^^^ f))) + 2 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 7 * (d |||  ~~~f) - 1 *  ~~~(e ^^^ f) - 2 *  ~~~(d ^^^ (e ^^^ f)) + 1 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 6 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 1 * (f &&& (d |||  ~~~e)) - 6 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 2 * (d ^^^ f) - 3 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 1 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 3 * ( ~~~f |||  ~~~(d ^^^ e)) + 1 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 4 *  ~~~(d &&& (e &&& f)) + 11 *  ~~~e + 1 * (f ||| (d &&&  ~~~e)) - 11 * ( ~~~e &&& (d ^^^ f)) - 11 *  ~~~(d |||  ~~~f) - 6 *  ~~~(d &&& (e ^^^ f)) - 3 *  ~~~(d &&&  ~~~d) + 2 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 11 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 2 *  ~~~(e ||| f) - 6 * (d &&&  ~~~f) - 1 * (f &&& (d ^^^ e)) - 6 * ((d &&& e) ^^^ (e |||  ~~~f)) + 11 * (f ^^^  ~~~(d &&& (e ||| f))) - 2 *  ~~~(d &&& (e ||| f)) + 2 * (f ^^^ (d &&& e)) + 5 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) - 11 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 11 * (f &&& (d ||| e)) - 1 *  ~~~(d ^^^ f) + 1 * ( ~~~f &&&  ~~~(d ^^^ e)) - 3 * (e ^^^ (d ||| f)) - 5 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 4 *  ~~~d + 3 * (f ^^^  ~~~(d |||  ~~~e)) - 5 * ( ~~~d ||| ( ~~~e ||| f)) + 4 *  ~~~(d ||| f) + 3 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) - 2 * (f ^^^  ~~~(d &&& e)) + 1 * ( ~~~e ||| (d ^^^ f)) - 1 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 5 * (f ^^^ (d &&&  ~~~e)) + 4 * (d ^^^ e) - 12 *  ~~~(d ||| (e ||| f)) + 12 *  ~~~(d ||| ( ~~~e ||| f)) + 20 *  ~~~( ~~~d ||| (e ||| f)) - 29 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 17 * ( ~~~d &&& ( ~~~e &&& f)) - 14 * ( ~~~d &&& (e &&& f)) - 24 * (d &&& ( ~~~e &&& f)) - 26 * (d &&& (e &&& f)) = 7 * (d &&& ( ~~~e ||| f))

theorem t_2_192_proof : t_2_192_before ⊑ t_2_192_after

theorem lshrult_03_07_exact_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 3) { «exact» := true }) (const? 4 7) ⊑ const? 1 1

theorem mul_five (x : BitVec w) : 5 * x = x + x + x + x + x

theorem test18a_thm (e : IntW 8) :
  icmp IntPred.eq (LLVM.and e (const? 8 (-2))) (const? 8 0) ⊑ icmp IntPred.ult e (const? 8 2)

theorem select_icmp_sgt_allones_smin_proof : select_icmp_sgt_allones_smin_before ⊑ select_icmp_sgt_allones_smin_after

theorem add_shl_same_amount_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 6),
  ¬(x_1 ≥ ↑6 ∨ x_1 ≥ ↑6) → ¬x_1 ≥ ↑6 → x_2 <<< x_1 + x <<< x_1 = (x_2 + x) <<< x_1

theorem masked_or_allones_logical_proof : masked_or_allones_logical_before ⊑ masked_or_allones_logical_after

theorem sub_ashr_and_i32_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1.ssubOverflow x = true ∨ 31#32 ≥ ↑32) →
    ofBool (x_1 <ₛ x) = 1#1 → (x_1 - x).sshiftRight' 31#32 &&& x = x

theorem icmp_sgt7_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (x <<< 1#8).sshiftRight' 1#8 ≠ x ∨ 1#8 ≥ ↑8) → ofBool (124#8 <ₛ x <<< 1#8) = ofBool (62#8 <ₛ x)

theorem n7_wrong_pred2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ofBool (x_1 - x == x_1) = ofBool (x == 0#8)

theorem t3_const_after_fold_lshr_shl_ne_proof : t3_const_after_fold_lshr_shl_ne_before ⊑ t3_const_after_fold_lshr_shl_ne_after

theorem bitwise_and_logical_and_masked_icmp_allones_poison1_proof : bitwise_and_logical_and_masked_icmp_allones_poison1_before ⊑ bitwise_and_logical_and_masked_icmp_allones_poison1_after

theorem and_consts_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (4#32 &&& x == 0#32) = 1#1 → 1#1 = ofBool (x &&& 12#32 != 12#32)

theorem e_1008 :
    2 * (z ^^^ t) - 11 *  ~~~(z ^^^ t) + 4 * (z ||| t) + 3 *  ~~~(z &&&  ~~~z) + 8 *  ~~~(z ||| t) - 9 *  ~~~(z |||  ~~~t) - 9 * (z &&&  ~~~t) =  - 4 * (z &&& t)

theorem ule_swap_and_min_commute_logical_proof : ule_swap_and_min_commute_logical_before ⊑ ule_swap_and_min_commute_logical_after

@[simp] lemma eval_single [DecidableEq α] {s : List α} (x : ∀ a ∈ s, Bool) (g : α → Bool):
  eval (single x) g ↔ (∀ a (ha : a ∈ s), g a = x a (by simpa))

theorem t0_const_lshr_shl_ne_proof : t0_const_lshr_shl_ne_before ⊑ t0_const_lshr_shl_ne_after

theorem ne_umax2_proof : ne_umax2_before ⊑ ne_umax2_after

theorem t1_single_bit_proof : t1_single_bit_before ⊑ t1_single_bit_after

theorem or_and_not_not_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ((x_2 ||| x_1) ^^^ -1#32) &&& x ||

theorem main5e_like_logical_thm.extracted_1._6 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 &&& x_1 == x_2) = 1#1 →
    ofBool (x_2 &&& x_1 != x_2) = 1#1 → ¬ofBool (x_2 &&& x == x_2) = 1#1 → 1#32 = zeroExtend 32 1#1

theorem icmp_power2_and_icmp_shifted_mask_8_6_proof : icmp_power2_and_icmp_shifted_mask_8_6_before ⊑ icmp_power2_and_icmp_shifted_mask_8_6_after

theorem e_161 :
     - 11 *  ~~~(x &&&  ~~~y) - 7 * y + 11 *  ~~~(x ||| y) + 19 *  ~~~(x |||  ~~~y) + 1 * (x &&&  ~~~y) + 19 * (x &&& y) = 1 * (x ||| y)

theorem multiuse_select_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 0#64 * (0#64 - zeroExtend 64 x) = 0#64

theorem ashr_ne_noexact_proof : ashr_ne_noexact_before ⊑ ashr_ne_noexact_after

theorem test37_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → ofBool (truncate 8 (x >>> 31#32 ||| 512#32) == 11#8) = 0#1

theorem e_2290 :
     - 3 * (e |||  ~~~(d ^^^ f)) - 1 * (f &&& (d ^^^ e)) - 6 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 1 *  ~~~( ~~~d ||| (e &&& f)) + 11 * (f ^^^  ~~~(d &&& (e ||| f))) + 1 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 2 * (f ^^^  ~~~(d &&& (e &&& f))) - 5 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) - 1 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 1 * (e |||  ~~~(d ||| f)) + 5 * ( ~~~d &&& (e ||| f)) - 11 * ( ~~~d ||| (e ||| f)) - 1 * (f ^^^ (d ||| e)) + 11 * (f ^^^  ~~~(d |||  ~~~e)) + 2 *  ~~~(d ^^^ e) - 6 *  ~~~(d |||  ~~~f) + 11 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) + 2 * (f ^^^ (d &&& (e ||| f))) + 4 * ((d &&& f) ^^^ (e ||| f)) + 5 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 2 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) + 2 *  ~~~(d &&& (e &&& f)) - 6 * (f &&& (d |||  ~~~e)) + 1 * (d ^^^ ( ~~~e &&& f)) - 1 * ((d &&& e) |||  ~~~(e ^^^ f)) - 7 * (d ^^^ ( ~~~e ||| f)) - 1 * (d &&& e) + 1 *  ~~~(e ^^^ f) - 7 * ( ~~~e &&&  ~~~(d ^^^ f)) + 4 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 3 * (e ^^^  ~~~(d &&& (e &&& f))) - 6 *  ~~~e + 3 * (d ^^^ (e ^^^ f)) + 2 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 2 * (e &&& (d ^^^ f)) + 1 * (e &&&  ~~~(d &&&  ~~~f)) + 1 * e + 7 * ( ~~~d ||| ( ~~~e &&& f)) + 2 * (e ^^^ (d ||| (e &&& f))) - 3 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 3 * (e ^^^ (d ||| f)) - 2 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 5 * (f ^^^  ~~~(d ||| (e &&& f))) + 4 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) - 2 *  ~~~(d &&&  ~~~e) - 2 * (e ^^^  ~~~(d &&& (e ||| f))) - 2 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) - 1 *  ~~~(e &&&  ~~~f) + 11 * (f ^^^ (d ||| ( ~~~e &&& f))) - 11 *  ~~~(d &&& (e ^^^ f)) - 7 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) + 1 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 7 * (e ||| (d &&&  ~~~f)) + 13 *  ~~~(d ||| (e ||| f)) - 37 *  ~~~(d ||| ( ~~~e ||| f)) + 2 *  ~~~( ~~~d ||| (e ||| f)) - 16 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 29 * ( ~~~d &&& ( ~~~e &&& f)) + 20 * ( ~~~d &&& (e &&& f)) - 12 * (d &&& ( ~~~e &&& f)) + 11 * (d &&& (e &&& f)) = 5 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f)))

theorem test19 (x y : BitVec w) : (x &&&  (~~~ y)) = (x -  (x &&& y))

theorem icmp_select_var_pred_ne_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 8),
  ofBool (x_2 == 0#8) = 1#1 → ofBool (x_2 != 0#8) = 1#1 → ofBool (x_1 != x_1) = ofBool (x != x_1)

theorem zext_or_eq_ult_add_proof : zext_or_eq_ult_add_before ⊑ zext_or_eq_ult_add_after

theorem add_or_sub_comb_i32_commuted1_nuw_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ (0#32 - x ||| x).uaddOverflow x = true) → (0#32 - x ||| x) + x = x

theorem bools_logical_commute1_thm.extracted_1._4 : ∀ (x x_1 : BitVec 1),
  x_1 = 1#1 → ¬x = 1#1 → ¬x ^^^ 1#1 = 1#1 → 0#1 = x_1

theorem ashr_exact_poison_constant_fold_proof : ashr_exact_poison_constant_fold_before ⊑ ashr_exact_poison_constant_fold_after

theorem e_320 :
     - 7 *  ~~~x + 1 * x + 7 *  ~~~(x &&&  ~~~x) + 1 *  ~~~(x ||| y) + 1 *  ~~~(x |||  ~~~y) - 7 * (x &&&  ~~~y) - 8 * (x &&& y) = 1 *  ~~~(x &&& y)

theorem test11_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(True ∧ (x &&& BitVec.ofInt 8 (-13) &&& 8#8 != 0) = true) →
    (x ||| 12#8) ^^^ 4#8 = x &&& BitVec.ofInt 8 (-13) ||

theorem sgt_swap_and_not_min_commute_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.ne e_1 (const? 8 (-128))) (icmp IntPred.slt e e_1) ⊑
    icmp IntPred.slt e e_1

theorem shl_xor_lshr_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑32 ∨ x_1 ≥ ↑32) → x_1 ≥ ↑32 → False

theorem uaddo_commute4_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.ult (LLVM.xor e_2 (const? 32 (-1))) e_1) e (add e_2 e_1) ⊑
    select (icmp IntPred.ugt e_1 (LLVM.xor e_2 (const? 32 (-1)))) e (add e_2 e_1)

theorem exact_ashr_ne_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 != -1#8) = ofBool (x != 7#8)

theorem match_unsigned_thm (e : IntW 64) :
  add (urem e (const? 64 299)) (mul (urem (LLVM.udiv e (const? 64 299)) (const? 64 64)) (const? 64 299)) ⊑
    urem e (const? 64 19136)

theorem pr51551_proof : pr51551_before ⊑ pr51551_after

theorem wrongimm2_proof : wrongimm2_before ⊑ wrongimm2_after

theorem shl_and_and_fail_proof : shl_and_and_fail_before ⊑ shl_and_and_fail_after

theorem shift_trunc_signbit_test_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬24#32 ≥ ↑32 → ofBool (truncate 8 (x >>> 24#32) <ₛ 0#8) = ofBool (x <ₛ 0#32)

theorem lt_unsigned_to_small_signed_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (zeroExtend 32 x <ₛ 17#32) = ofBool (x <ᵤ 17#8)

theorem test93_proof : test93_before ⊑ test93_after

theorem main3b_logical_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 0#32) = 1#1 → 0#1 = 1#1 → 0#32 = zeroExtend 32 (ofBool (x &&& 23#32 != 0#32))

theorem t3_no_extrause_proof : t3_no_extrause_before ⊑ t3_no_extrause_after

theorem Eqn.denote_hard_case_aux {eqn : Eqn}
    (h1 : ∀ (env1 : EnvFin 1 eqn.numVars), Eqn.denoteFin eqn env1 = 0) :
    ∀ {w : Nat} (env : EnvFin w eqn.numVars), eqn.denoteFin env = 0

theorem main7d_logical_thm.extracted_1._12 : ∀ (x x_1 x_2 x_3 x_4 : BitVec 32),
  ofBool (x_4 &&& (x_3 &&& x_2) == x_3 &&& x_2) = 1#1 →
    ¬ofBool (x_4 &&& (x_3 &&& x_2) != x_3 &&& x_2) = 1#1 →
      ¬ofBool (x_4 &&& (x_1 &&& x) == x_1 &&& x) = 1#1 →
        1#32 = zeroExtend 32 (ofBool (x_4 &&& (x_1 &&& x) != x_1 &&& x))

theorem test1_proof : test1_before ⊑ test1_after

theorem xor_or_xor_common_op_commute6_proof : xor_or_xor_common_op_commute6_before ⊑ xor_or_xor_common_op_commute6_after

theorem sgt_minnum_proof : sgt_minnum_before ⊑ sgt_minnum_after

theorem sgt_smin3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 + 3#32 <ₛ x) = 1#1 → ofBool (x_1 + 3#32 <ₛ x_1 + 3#32) = 0#1

theorem ashrsgt_02_01_exact_proof : ashrsgt_02_01_exact_before ⊑ ashrsgt_02_01_exact_after

theorem lshrugt_02_13_proof : lshrugt_02_13_before ⊑ lshrugt_02_13_after

theorem lshrugt_01_04_exact_proof : lshrugt_01_04_exact_before ⊑ lshrugt_01_04_exact_after

theorem test_ult_thm (e : IntW 16) (e_1 : IntW 32) :
  icmp IntPred.ult (trunc 8 e_1 { «nsw» := true, «nuw» := false }) (trunc 8 e { «nsw» := true, «nuw» := false }) ⊑
    icmp IntPred.ult e_1 (sext 32 e)

theorem mul_add_to_mul_3_proof : mul_add_to_mul_3_before ⊑ mul_add_to_mul_3_after

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

theorem mul_mask_fakepow2_ne0_proof : mul_mask_fakepow2_ne0_before ⊑ mul_mask_fakepow2_ne0_after

theorem ashr_and_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(x ≥ ↑8 ∨ x + 1#8 ≥ ↑8) →
    ¬x ≥ ↑8 →
      (BitVec.ofInt 8 (-64)).sshiftRight' x &&& (BitVec.ofInt 8 (-128)).sshiftRight' (x + 1#8) =
        (BitVec.ofInt 8 (-64)).sshiftRight' x

theorem xor_logic_and_logic_or4_thm.extracted_1._6 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬x_1 = 1#1 → 0#1 ^^^ x = x

theorem uge_swap_and_max_proof : uge_swap_and_max_before ⊑ uge_swap_and_max_after

theorem trunc_lshr_sext_wide_input_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬9#32 ≥ ↑32 →
    ¬(9#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 9#16)) ≠ x.sshiftRight' 9#16) →
      truncate 8 (signExtend 32 x >>> 9#32) = truncate 8 (x.sshiftRight' 9#16)

theorem test1_proof : test1_before ⊑ test1_after

theorem and_or_not_not_wrong_b_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  (x_3 &&& x_2 ^^^ -1#32 ||| x_1) &&& (x &&& x_3 ^^^ -1#32) =
    (x_1 ||| x_3 &&& x_2 ^^^ -1#32) &&& (x &&& x_3 ^^^ -1#32)

theorem and_xor_or1_proof : and_xor_or1_before ⊑ and_xor_or1_after

theorem t3_ult_sgt_neg1_thm.extracted_1._7 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 <ᵤ 65536#32) = 1#1 → ¬ofBool (65535#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ 0#32) = 1#1 → x_1 = x

theorem test53_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ (truncate 16 x &&& 7224#16 &&& BitVec.ofInt 16 (-32574) != 0) = true) →
    zeroExtend 64 ((truncate 16 x ||| BitVec.ofInt 16 (-32574)) &&& BitVec.ofInt 16 (-25350)) =
      zeroExtend 64 (truncate 16 x &&& 7224#16 ||| BitVec.ofInt 16 (-32574))

theorem t7_ugt_sgt_neg1_thm.extracted_1._9 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (143#32 <ᵤ x_1 + 16#32) = 1#1 →
    ¬ofBool (127#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ BitVec.ofInt 32 (-16)) = 1#1 → x_1 = x

theorem sextbool_add_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  signExtend 32 x_1 + x = x + signExtend 32 x_1

theorem not_cond_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1), x_1 ^^^ 1#1 = 1#1 → x_1 = 1#1 → False

theorem exact_ashr_eq_noexactdiv_thm (e : IntW 8) :
  icmp IntPred.eq (ashr (const? 8 (-80)) e { «exact» := true }) (const? 8 (-31)) ⊑ const? 1 0

theorem masked_icmps_mask_notallzeros_bmask_mixed_5_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 15#32 != 0#32) = 1#1 → 0#1 = ofBool (x &&& 15#32 == 8#32)

theorem shl_mask_wrong_shl_const_thm (e : IntW 32) :
  LLVM.or (LLVM.and e (const? 32 255)) (shl (LLVM.and e (const? 32 255)) (const? 32 7)) ⊑
    LLVM.or (LLVM.and e (const? 32 255))
      (shl (LLVM.and e (const? 32 255)) (const? 32 7) { «nsw» := true, «nuw» := true })

theorem bools2_logical_commute0_thm.extracted_1._15 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 = 1#1 → ¬x_2 ^^^ 1#1 = 1#1 → x_1 = 1#1 → 1#1 = x_1

theorem test37_thm (e : IntW 32) :
  icmp IntPred.eq (trunc 8 (LLVM.or (lshr e (const? 32 31)) (const? 32 512))) (const? 8 11) ⊑ const? 1 0

theorem e_2203 :
    2 * (e ^^^  ~~~(d &&& (e &&& f))) + 11 * (d &&& e) - 7 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 * (e &&& (d ^^^ f)) - 11 *  ~~~( ~~~d &&& ( ~~~e &&& f)) - 2 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) - 5 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 7 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) - 11 * (f ^^^  ~~~(d &&& e)) - 3 *  ~~~( ~~~d &&& (e &&& f)) - 2 * (e ^^^  ~~~(d &&&  ~~~f)) - 1 * (f ^^^ (d &&& (e ||| f))) + 11 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 4 *  ~~~(d ||| e) - 1 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 1 * (f ^^^ (d ||| (e &&& f))) - 11 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 7 * (e ^^^ ( ~~~d &&& (e ||| f))) - 3 * (e &&&  ~~~(d ^^^ f)) - 1 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 2 * (f ^^^  ~~~(d &&& (e &&& f))) - 11 * (e &&& (d ||| f)) + 1 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 1 *  ~~~(d ^^^ (e ^^^ f)) - 1 *  ~~~(d ^^^ (e &&& f)) + 3 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 4 * (e ^^^ ( ~~~d ||| (e ^^^ f))) + 1 * ((d &&& f) |||  ~~~(e ||| f)) - 1 * ( ~~~d ||| (e &&& f)) + 5 * ((d |||  ~~~e) &&& (e ^^^ f)) - 6 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 3 * ( ~~~d ||| ( ~~~e ||| f)) + 2 *  ~~~(d ^^^ f) - 1 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 11 * (d &&&  ~~~f) - 2 * (e &&&  ~~~f) + 1 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) + 11 * (e ^^^ (d ||| (e &&& f))) + 4 * (f ^^^  ~~~(d ||| e)) + 2 * (f ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 1 * ((d &&& e) |||  ~~~(e ^^^ f)) - 6 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 3 * ( ~~~f ||| (d ^^^ e)) - 1 *  ~~~(d &&&  ~~~d) - 6 *  ~~~(d |||  ~~~e) + 34 *  ~~~(d ||| (e ||| f)) + 41 *  ~~~(d ||| ( ~~~e ||| f)) + 57 *  ~~~( ~~~d ||| (e ||| f)) + 42 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 3 * ( ~~~d &&& ( ~~~e &&& f)) + 47 * ( ~~~d &&& (e &&& f)) + 29 * (d &&& (e &&& f)) =  - 11 * (d &&& ( ~~~e &&& f)) + 7 * (d |||  ~~~e)

theorem sle_smin2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), ofBool (x_1 <ₛ x) = 1#1 → ofBool (x_1 ≤ₛ x) = 1#1

theorem n0_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x &&& 4#8 != x) = ofBool (x &&& BitVec.ofInt 8 (-5) != 0#8)

theorem PR28476_thm (e e_1 : IntW 32) :
  LLVM.xor (zext 32 (LLVM.and (icmp IntPred.ne e_1 (const? 32 0)) (icmp IntPred.ne e (const? 32 0))))
      (const? 32 1) ⊑
    zext 32 (LLVM.or (icmp IntPred.eq e_1 (const? 32 0)) (icmp IntPred.eq e (const? 32 0)))

theorem and_not_or_commute7_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (LLVM.or (LLVM.xor (LLVM.and e_2 e_1) (const? 32 (-1))) e)
      (LLVM.or (LLVM.xor (LLVM.and e_1 e) (const? 32 (-1))) e_2) ⊑
    LLVM.xor (LLVM.and (LLVM.xor e_2 e) e_1) (const? 32 (-1))

theorem fold_ne_rhs_fail_shift_not_1s_thm (e e_1 : IntW 8) :
  icmp IntPred.ne (LLVM.and (LLVM.xor e_1 (const? 8 123)) (shl (const? 8 (-2)) e)) (const? 8 0) ⊑
    icmp IntPred.ne (LLVM.and (LLVM.xor e_1 (const? 8 122)) (shl (const? 8 (-2)) e)) (const? 8 0)

theorem logic_and_logic_or_6_thm.extracted_1._10 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬x = 1#1 → 0#1 = 1#1 → 1#1 = 0#1

theorem select_icmp_ne_0_and_1073741824_and_not_8_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ¬ofBool (0#32 != x_1 &&& 1073741824#32) = 1#1 →
    ¬ofBool (x_1 &&& 1073741824#32 == 0#32) = 1#1 → x &&& BitVec.ofInt 8 (-9) = x

theorem e_2319 :
    11 * (e |||  ~~~f) + 1 *  ~~~(d &&& ( ~~~e &&& f)) + 5 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * ( ~~~d ||| (e ||| f)) - 2 * (f ||| (d &&&  ~~~e)) - 7 * (e ^^^ (d &&&  ~~~f)) + 4 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) + 1 * ( ~~~d ||| ( ~~~e ||| f)) - 1 * (d ||| (e &&& f)) + 2 * ( ~~~d ||| (e &&& f)) - 1 * (e ^^^ (d &&& (e ||| f))) - 1 * (f &&&  ~~~(d ^^^ e)) + 3 *  ~~~(d ^^^ f) - 7 * ((d &&& f) ||| (e &&&  ~~~f)) + 7 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 3 * ( ~~~e ||| (d ^^^ f)) + 2 * ( ~~~e |||  ~~~(d ^^^ f)) - 5 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 2 * (e ^^^  ~~~(d &&& (e &&& f))) - 3 *  ~~~(e &&& f) + 1 * (e ^^^  ~~~(d |||  ~~~f)) + 2 * (e ^^^ (d ||| (e ^^^ f))) + 11 * (f ^^^  ~~~(d &&& (e &&& f))) - 11 * (d &&& ( ~~~e ||| f)) + 1 * (f ^^^ (d ||| (e &&& f))) + 2 * (d &&&  ~~~f) + 7 * (f ^^^  ~~~(d &&&  ~~~e)) - 1 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) - 2 * (e |||  ~~~(d ^^^ f)) - 6 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 5 * (e ^^^ f) + 5 *  ~~~(d ||| (e ^^^ f)) - 2 * (e ^^^  ~~~(d ||| f)) - 6 * (f ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 4 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) + 1 * (d ||| ( ~~~e &&& f)) + 5 * ( ~~~f ||| (d ^^^ e)) - 3 * (e ^^^  ~~~(d ||| (e &&& f))) + 3 * ( ~~~d &&& (e ||| f)) - 1 * (f ^^^ ( ~~~d &&& (e ||| f))) + 5 * (d ^^^ ( ~~~e ||| f)) - 5 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 1 *  ~~~( ~~~d &&& ( ~~~e &&& f)) + 1 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 7 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) + 2 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) + 4 * (e &&& (d ||| f)) - 6 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 1 * (e ^^^ (d ||| (e &&& f))) - 2 *  ~~~(d ^^^ (e ||| f)) + 11 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 7 * ( ~~~d ||| ( ~~~e &&& f)) + 2 * (d ||| e) + 5 *  ~~~(d ||| f) + 11 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) - 52 *  ~~~(d ||| (e ||| f)) - 5 *  ~~~(d ||| ( ~~~e ||| f)) - 13 *  ~~~( ~~~d ||| (e ||| f)) - 29 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 9 * ( ~~~d &&& ( ~~~e &&& f)) - 33 * ( ~~~d &&& (e &&& f)) + 5 * (d &&& ( ~~~e &&& f)) - 32 * (d &&& (e &&& f)) = 1 * d - 7 * (f ^^^  ~~~(d ||| e))

theorem t20_thm (e : IntW 16) (e_1 : IntW 8) :
  sub e_1 (trunc 8 (shl (const? 16 (-42)) e)) ⊑ add e_1 (trunc 8 (shl (const? 16 42) e))

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

theorem e_658 :
     - 2 * (x ^^^ y) + 2 * x - 11 *  ~~~(x &&&  ~~~x) + 1 *  ~~~y - 2 * (x ||| y) - 1 * (x |||  ~~~y) + 2 * y + 11 *  ~~~(x ||| y) + 13 *  ~~~(x |||  ~~~y) + 10 * (x &&& y) =  - 13 * (x &&&  ~~~y)

theorem t0_proof : t0_before ⊑ t0_after

theorem uge_swap_or_not_max_commute_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != -1#8) = 1#1 → ofBool (x ≤ᵤ x_1) = 1#1

@[simp]
theorem Factor.reflect_zero_of_denote_zero {w : Nat} {f : Factor} {xs : Env w} (h : f.denote xs = 0) :
    f.reflect xs = 0#w

theorem e_546 :
     - 3 *  ~~~(x &&&  ~~~y) + 2 *  ~~~(x &&& y) - 2 *  ~~~x + 11 * x + 1 *  ~~~y + 1 *  ~~~(x ||| y) + 3 *  ~~~(x |||  ~~~y) - 14 * (x &&&  ~~~y) - 9 * (x &&& y) =  - 1 *  ~~~(x ^^^ y)

theorem logic_or_logic_and_4_thm (e e_1 e_2 : IntW 1) :
  select (select e_2 (const? 1 1) e_1) (select e (const? 1 1) e_2) (const? 1 0) ⊑
    select e_2 (const? 1 1) (select e_1 e (const? 1 0))

theorem rem_euclid_pow2_true_arm_folded_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(2#32 == 0 || 32 != 1 && x == intMin 32 && 2#32 == -1) = true →
    ofBool (x.srem 2#32 <ₛ 0#32) = 1#1 → 1#32 = x &&& 1#32

theorem ashr_can_be_lshr_2_proof : ashr_can_be_lshr_2_before ⊑ ashr_can_be_lshr_2_after

theorem not_or_or_and_not_and_and_commute2_and_proof : not_or_or_and_not_and_and_commute2_and_before ⊑ not_or_or_and_not_and_and_commute2_and_after

theorem n10_wrong_pred2_thm (e e_1 : IntW 8) :
  icmp IntPred.eq (add e_1 e) e ⊑ icmp IntPred.eq e_1 (const? 8 0)

theorem lshr_lshr_proof : lshr_lshr_before ⊑ lshr_lshr_after

theorem n11_wrong_pred3_thm (e e_1 : IntW 8) :
  icmp IntPred.ne (add e_1 e) e ⊑ icmp IntPred.ne e_1 (const? 8 0)

theorem e_934 :
    2 *  ~~~(z &&&  ~~~t) - 1 *  ~~~(z &&& t) + 11 * t - 1 *  ~~~(z ||| t) - 12 *  ~~~(z |||  ~~~t) - 17 * (z &&& t) = 3 * (z &&&  ~~~t) - 4 * z

theorem _root_.SetRel.set_eq_symm {R : SetRel α β} (h : R.set_eq A B) : R.inv.set_eq B A

theorem substitute_constant_and_ne_ugt_swap_logical_proof : substitute_constant_and_ne_ugt_swap_logical_before ⊑ substitute_constant_and_ne_ugt_swap_logical_after

theorem badimm3_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 8#16 ≥ ↑16) →
    ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 8#16)) = 1#1 →
      ¬ofBool (x + 128#16 <ᵤ 256#16) = 1#1 →
        ¬(14#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 14#16)) ≠ x.sshiftRight' 14#16) →
          truncate 8 x = truncate 8 (x.sshiftRight' 14#16) ^^^ 127#8

theorem ugt_and_min_commute_logical_proof : ugt_and_min_commute_logical_before ⊑ ugt_and_min_commute_logical_after

theorem ashrslt_01_13_proof : ashrslt_01_13_before ⊑ ashrslt_01_13_after

theorem alive_Select_1070 : forall (w : Nat) (Y c Z W : Bitvec 1)
, TSSA.eval
  (Op := Op) (e := e)
  (i := TSSAIndex.STMT (UserType.base (BaseType.bitvec 1)))
  [dsl_bb|
  ^bb
  %v0 := unit: ;
  %v1 := op:const (c) %v0;
  %v2 := op:const (W) %v0;
  %v3 := op:const (Z) %v0;
  %v4 := triple:%v1 %v2 %v3;
  %v5 := op:select w %v4;
  %v6 := op:const (Y) %v0;
  %v7 := triple:%v1 %v5 %v6;
  %v8 := op:select w %v7
  dsl_ret %v8
  ]  ⊑
  TSSA.eval
  (Op := Op) (e := e)
  (i := TSSAIndex.STMT (UserType.base (BaseType.bitvec 1)))
  [dsl_bb|
  ^bb
  %v0 := unit: ;
  %v1 := op:const (c) %v0;
  %v2 := op:const (W) %v0;
  %v3 := op:const (Z) %v0;
  %v4 := triple:%v1 %v2 %v3;
  %v5 := op:select 1 %v4;
  %v6 := op:const (Y) %v0;
  %v7 := triple:%v1 %v2 %v6;
  %v8 := op:select 1 %v7
  dsl_ret %v8
  ]

theorem uadd_sat_canon_nuw_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1.uaddOverflow x = true) → ofBool (x_1 + x <ᵤ x_1) = 1#1 → -1#32 = x_1 + x

theorem trunc_unsigned_both_proof : trunc_unsigned_both_before ⊑ trunc_unsigned_both_after

@[simp]
theorem shiftRight_and_xor_shiftLeft_distrib {x y z : BitVec w} {n : Nat} :
    (x >>> n &&& y ^^^ z) <<< n = x &&& y <<< n ^^^ z <<< n

theorem e_1073 :
    1 *  ~~~t + 3 * (z ^^^ t) + 1 *  ~~~(z &&& t) + 1 *  ~~~z - 3 *  ~~~(z ||| t) + 2 *  ~~~(z |||  ~~~t) + 7 * (z &&& t) = 5 * (z &&&  ~~~t) + 7 * t

theorem test5_thm (e : IntW 8) :
  icmp IntPred.slt e (const? 8 127) ⊑ icmp IntPred.ne e (const? 8 127)

theorem e_1201 :
     - 2 *  ~~~(z &&&  ~~~z) + 2 *  ~~~(z &&&  ~~~t) + 7 * (z ^^^ t) - 6 * z + 3 * (z |||  ~~~t) - 3 *  ~~~(z ||| t) - 7 *  ~~~(z |||  ~~~t) + 3 * (z &&& t) = 2 * (z &&&  ~~~t)

theorem t3_singlebit_thm (e e_1 : IntW 32) :
  icmp IntPred.ne
      (LLVM.and (shl e_1 (sub (const? 32 32) e))
        (trunc 32 (lshr (const? 64 65536) (zext 64 (add e (const? 32 (-16)))))))
      (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and e_1 (const? 32 1)) (const? 32 0)

theorem PR39793_bswap_u32_as_u16_trunc_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(8#32 ≥ ↑32 ∨ 8#32 ≥ ↑32) → 8#32 ≥ ↑32 → False

theorem relabel_unsat_iff_of_not_NonEmpty {aigα : AIG α} {r : α → β} {hidx1} {hidx2}
    (hαNonempty : ¬ Nonempty α) :
    (aigα.relabel r).UnsatAt idx invert hidx1 ↔ aigα.UnsatAt idx invert hidx2

theorem scalar_i32_lshr_and_signbit_eq_proof : scalar_i32_lshr_and_signbit_eq_before ⊑ scalar_i32_lshr_and_signbit_eq_after

theorem masked_or_A_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 14#32 == x) = 1#1 → 1#1 = ofBool (x &&& BitVec.ofInt 32 (-79) == 0#32)

theorem width2 {v w : Nat} (x : BitVec v) :
    x.signExtend (max v (min v w)) = x.zeroExtend (max v (min v w))

private theorem add_odd_iff_neq (n m : Nat) :
    (n + m) % 2 = 1 ↔ (n % 2 = 1) ≠ (m % 2 = 1)

theorem test44_proof : test44_before ⊑ test44_after

theorem select_xor_icmp_meta_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.eq e_2 (const? 32 0)) (LLVM.xor e_2 e_1) e ⊑
    select (icmp IntPred.eq e_2 (const? 32 0)) e_1 e

theorem i_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬((BitVec.ofInt 8 (-3) == 0 || 8 != 1 && x == intMin 8 && BitVec.ofInt 8 (-3) == -1) = true ∨
        (BitVec.ofInt 8 (-3) == 0 || 8 != 1 && x.sdiv (BitVec.ofInt 8 (-3)) == intMin 8 && BitVec.ofInt 8 (-3) == -1) =
          true) →
    ¬(9#8 == 0 || 8 != 1 && x == intMin 8 && 9#8 == -1) = true →
      (x.sdiv (BitVec.ofInt 8 (-3))).sdiv (BitVec.ofInt 8 (-3)) = x.sdiv 9#8

theorem scalar_i32_signbit_lshr_and_slt_proof : scalar_i32_signbit_lshr_and_slt_before ⊑ scalar_i32_signbit_lshr_and_slt_after

theorem shl_lshr_pow2_not_const_case2_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 3#16 ≥ ↑16) → ofBool (x == 2#16) = 1#1 → 16#16 <<< x >>> 3#16 &&& 8#16 ^^^ 8#16 = 0#16

theorem select_icmp_eq_and_1_0_xor_2_thm.extracted_1._4 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 1#32 == 0#32) = 1#1 → ¬1#32 ≥ ↑32 → x ^^^ 2#32 = x ^^^ x_1 <<< 1#32 &&& 2#32

theorem ashr_mul_times_3_div_2_thm (e : IntW 32) :
  ashr (mul e (const? 32 3) { «nsw» := true, «nuw» := true }) (const? 32 1) ⊑
    add e (lshr e (const? 32 1)) { «nsw» := true, «nuw» := true }

theorem e_1888 :
    2 * ((a ||| b) &&& (b ^^^ c)) - 3 * ( ~~~(a ||| b) ||| (b ^^^ c)) - 1 * (b ^^^ (a &&& (b ||| c))) - 1 * ( ~~~(a ^^^ b) ||| (a ^^^ c)) + 1 *  ~~~(b ^^^ c) + 7 * (b ^^^ (a ||| (b ^^^ c))) + 11 * (c &&& (a ^^^ b)) - 3 * (b ^^^ (a ||| ( ~~~b ||| c))) + 2 * ( ~~~b ||| (a ^^^ c)) + 4 * (b ^^^ (a ||| c)) + 7 *  ~~~(a &&& c) - 11 *  ~~~(b |||  ~~~c) - 6 * ((b &&& c) ||| (a &&& (b ||| c))) - 3 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) + 7 * (a ^^^ (b &&& c)) - 5 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) + 3 * (a |||  ~~~c) + 5 * (c ^^^  ~~~(a &&&  ~~~b)) - 7 *  ~~~(a |||  ~~~b) + 1 *  ~~~(b ||| c) + 1 * ( ~~~a &&& ( ~~~b ||| c)) - 11 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) + 7 * (c ^^^ (a ||| ( ~~~b &&& c))) + 5 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 7 *  ~~~(a &&&  ~~~c) - 1 * (b ^^^  ~~~(a &&&  ~~~c)) - 5 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) - 2 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 1 * (a |||  ~~~b) - 7 *  ~~~( ~~~a &&& ( ~~~b &&& c)) - 1 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) + 2 * (a ||| ( ~~~b &&& c)) - 1 * ((a ||| b) &&&  ~~~(b ^^^ c)) - 6 * (b &&& c) + 1 * (b ^^^ (a ||| (b &&& c))) - 5 * ((a &&& b) ^^^ (b |||  ~~~c)) - 3 * (c ^^^  ~~~(a &&& (b &&& c))) + 7 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 7 *  ~~~(a ^^^ (b ||| c)) + 1 *  ~~~(a ||| (b ^^^ c)) - 7 *  ~~~(a ||| (b ||| c)) + 10 *  ~~~(a ||| ( ~~~b ||| c)) - 11 *  ~~~( ~~~a ||| (b ||| c)) - 4 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 6 * ( ~~~a &&& ( ~~~b &&& c)) + 9 * ( ~~~a &&& (b &&& c)) - 13 * (a &&& ( ~~~b &&& c)) + 29 * (a &&& (b &&& c)) =  - 2 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) - 5 *  ~~~b

theorem ashrsgt_03_05_exact_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ x >>> 3#4 <<< 3#4 ≠ x ∨ 3#4 ≥ ↑4) → ofBool (5#4 <ₛ x.sshiftRight' 3#4) = 0#1

theorem ashr_2_add_zext_basic_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ¬1#2 ≥ ↑2 → True ∧ (zeroExtend 2 x_1).uaddOverflow (zeroExtend 2 x) = true ∨ 1#2 ≥ ↑2 → False

theorem and_nosignbit_select_ashr_proof : and_nosignbit_select_ashr_before ⊑ and_nosignbit_select_ashr_after

theorem slt_or_not_max_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ne e_1 (const? 8 127)) (const? 1 1) (icmp IntPred.slt e_1 e) ⊑
    icmp IntPred.ne e_1 (const? 8 127)

theorem icmp_slt_0_or_icmp_eq_100_i32_fail_proof : icmp_slt_0_or_icmp_eq_100_i32_fail_before ⊑ icmp_slt_0_or_icmp_eq_100_i32_fail_after

theorem uge_umin2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 <ᵤ x) = 1#1 → ofBool (x ≤ᵤ x) = ofBool (x ≤ᵤ x_1)

theorem e_956 :
    7 *  ~~~(z &&&  ~~~z) + 2 * t - 7 *  ~~~t - 11 *  ~~~(z |||  ~~~t) + 3 * (z &&&  ~~~t) - 4 * (z &&& t) = 5 * z - 2 * (z ^^^ t)

theorem testi32i8_proof : testi32i8_before ⊑ testi32i8_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_3b_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 3#32 != 0#32) = 1#1 →
    ofBool (x &&& 15#32 == 0#32) = ofBool (x &&& 3#32 != 0#32) ||

theorem icmp_eq_x_invertable_y2_todo_proof : icmp_eq_x_invertable_y2_todo_before ⊑ icmp_eq_x_invertable_y2_todo_after

theorem lshrult_02_02_proof : lshrult_02_02_before ⊑ lshrult_02_02_after

theorem addhshlhsdivhscalar2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬((BitVec.ofInt 32 (-1073741824) == 0 || 32 != 1 && x == intMin 32 && BitVec.ofInt 32 (-1073741824) == -1) = true ∨
        30#32 ≥ ↑32) →
    (1073741824#32 == 0 || 32 != 1 && x == intMin 32 && 1073741824#32 == -1) = true → False

theorem test_proof : test_before ⊑ test_after

theorem slt_swap_and_not_max_logical_proof : slt_swap_and_not_max_logical_before ⊑ slt_swap_and_not_max_logical_after

theorem and_add_bool_no_fold_thm (e : IntW 32) :
  LLVM.and (add (const? 32 (-1)) (LLVM.and e (const? 32 1))) e ⊑
    select (icmp IntPred.eq (LLVM.and e (const? 32 1)) (const? 32 0)) e (const? 32 0)

theorem negative4_logical_thm (e e_1 : IntW 32) :
  select (icmp IntPred.ne e_1 (LLVM.and e (const? 32 2147483647))) (icmp IntPred.sge e_1 (const? 32 0))
      (const? 1 0) ⊑
    LLVM.and (icmp IntPred.ne e_1 (LLVM.and e (const? 32 2147483647)))
      (icmp IntPred.sgt e_1 (const? 32 (-1)))

theorem icmp_ne_sext_ne_zero_i128_thm.extracted_1._1 : ∀ (x : BitVec 128),
  ofBool (signExtend 128 (ofBool (x != 0#128)) != x) = ofBool (x + -1#128 <ᵤ BitVec.ofInt 128 (-2))

theorem corec₂_eq_val (x : Stream α):
  (corec₂ x fun x => Id.run (x 0, x 0, tail x)) = (corec₂ x fun x => Id.run (x 0, x 0, x.tail))

theorem e_1157 :
     - 3 * t + 2 * (z ^^^ t) - 6 *  ~~~t + 1 * z + 7 *  ~~~(z ||| t) + 1 *  ~~~(z |||  ~~~t) + 3 * (z &&&  ~~~t) + 3 * (z &&& t) = 1 *  ~~~(z ^^^ t)

theorem t5_proof : t5_before ⊑ t5_after

theorem lshrult_03_01_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 3)) (const? 4 1) ⊑ icmp IntPred.sgt e (const? 4 (-1))

theorem and_ne_with_one_bit_diff_constants2_proof : and_ne_with_one_bit_diff_constants2_before ⊑ and_ne_with_one_bit_diff_constants2_after

theorem e_1629 :
     - 3 * (c &&& (a ^^^ b)) + 5 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) + 2 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 3 * ( ~~~a ||| ( ~~~b &&& c)) - 5 * (a ^^^ ( ~~~b &&& c)) + 2 * ((a &&& b) ^^^ (b ||| c)) - 1 * ( ~~~a ||| (b ||| c)) - 1 *  ~~~(b ||| c) - 1 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 1 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 5 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 1 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 1 * ((a |||  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 1 * (a ||| ( ~~~b ||| c)) - 6 *  ~~~(a ||| ( ~~~b ||| c)) + 7 *  ~~~( ~~~a ||| (b ||| c)) + 12 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 7 * ( ~~~a &&& ( ~~~b &&& c)) + 5 * ( ~~~a &&& (b &&& c)) + 13 * (a &&& ( ~~~b &&& c)) + 5 * (a &&& (b &&& c)) =  - 9 *  ~~~(a ||| (b ||| c))

theorem slt_zero_eq_i1_proof : slt_zero_eq_i1_before ⊑ slt_zero_eq_i1_after

theorem foo1_or_signbit_lshr_without_shifting_signbit_both_sides_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (icmp IntPred.slt (shl e_2 e_1) (const? 32 0)) (icmp IntPred.slt (shl e_2 e) (const? 32 0)) ⊑
    icmp IntPred.slt (LLVM.and (shl e_2 e_1) (shl e_2 e)) (const? 32 0)

theorem canonicalize_logic_first_xor_0_nswnuw_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.saddOverflow 96#8 = true ∨ True ∧ x.uaddOverflow 96#8 = true) →
    True ∧ (x ^^^ 31#8).saddOverflow 96#8 = true ∨ True ∧ (x ^^^ 31#8).uaddOverflow 96#8 = true → False

theorem e_1758 :
    3 * ((b &&& c) ||| (a &&& (b ||| c))) + 2 * (c ^^^ (a ||| b)) - 1 *  ~~~b - 11 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 2 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) - 6 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 3 *  ~~~c - 7 * ((a &&& c) ||| (b &&&  ~~~c)) + 2 * (b ^^^ (a ||| ( ~~~b ||| c))) - 1 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) + 2 * (c &&&  ~~~(a ^^^ b)) + 5 * (a ^^^ ( ~~~b ||| c)) + 1 *  ~~~( ~~~a &&& ( ~~~b ||| c)) + 3 *  ~~~(a ||| (b ^^^ c)) + 5 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c))) + 1 *  ~~~(b ^^^ c) + 1 * (c ||| (a &&& b)) + 2 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 2 * (a ^^^ c) + 11 * ((a &&& c) |||  ~~~(b ||| c)) - 1 * (c &&&  ~~~(a &&& b)) - 1 * ( ~~~(a ||| b) |||  ~~~(a ^^^ (b ^^^ c))) - 1 * (a ||| ( ~~~b ||| c)) + 7 * ( ~~~a ||| (b &&& c)) - 2 * ( ~~~(a &&& b) &&& (b ^^^ c)) + 3 * ( ~~~(a &&& b) &&&  ~~~(b ^^^ c)) - 1 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 19 *  ~~~(a ||| (b ||| c)) + 6 *  ~~~(a ||| ( ~~~b ||| c)) - 13 *  ~~~( ~~~a ||| (b ||| c)) + 20 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 8 * ( ~~~a &&& ( ~~~b &&& c)) - 7 * ( ~~~a &&& (b &&& c)) - 11 * (a &&& ( ~~~b &&& c)) - 20 * (a &&& (b &&& c)) =  - 1 * (c |||  ~~~(a |||  ~~~b)) - 4 * (a &&& c)

theorem uge_swap_and_max_commute_proof : uge_swap_and_max_commute_before ⊑ uge_swap_and_max_commute_after

theorem t_2_4_proof : t_2_4_before ⊑ t_2_4_after

theorem test_proof : test_before ⊑ test_after

theorem e_1855 :
     - 7 * ( ~~~b &&& (a ^^^ c)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 4 *  ~~~( ~~~a ||| (b &&& c)) + 2 * (c ^^^  ~~~(a ||| b)) - 3 * ((a |||  ~~~b) &&& (b ^^^ c)) - 5 *  ~~~(a ||| ( ~~~b &&& c)) + 2 * ( ~~~c ||| (a ^^^ b)) + 2 * (c ^^^ (a ||| ( ~~~b &&& c))) - 2 * (b ^^^  ~~~( ~~~a ||| (b ^^^ c))) + 2 * (c ^^^  ~~~(a |||  ~~~b)) - 6 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) + 1 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 7 *  ~~~(a &&& (b &&& c)) + 7 * (b ^^^ (a &&& (b ||| c))) + 4 *  ~~~(a &&& b) + 1 *  ~~~(a &&& c) + 7 *  ~~~( ~~~a ||| (b ^^^ c)) - 11 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) - 2 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 2 * (b ^^^  ~~~(a &&& c)) + 1 * ((a &&& b) ^^^ (a ^^^ ( ~~~b ||| c))) - 3 * (b ^^^  ~~~(a &&&  ~~~c)) + 2 * (b ^^^  ~~~(a &&& (b ||| c))) - 5 * (a ||| ( ~~~b ||| c)) + 1 *  ~~~(a ||| b) - 1 *  ~~~b - 11 * (c &&& (a ^^^ b)) - 2 * (c ||| (a ^^^ b)) + 1 *  ~~~( ~~~a &&& (b ^^^ c)) - 1 * ((a &&&  ~~~b) ||| (b ^^^ c)) + 5 * (b ^^^ (a &&& c)) + 5 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) + 5 * (c ^^^ (a ||| ( ~~~b ||| c))) + 3 * (b ^^^ ( ~~~a &&& (b ||| c))) + 3 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 1 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 1 * ((b &&& c) ||| (a &&& (b ||| c))) - 2 *  ~~~(a |||  ~~~c) + 21 *  ~~~(a ||| (b ||| c)) + 4 *  ~~~(a ||| ( ~~~b ||| c)) - 9 *  ~~~( ~~~a ||| (b ||| c)) - 19 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 16 * ( ~~~a &&& ( ~~~b &&& c)) + 1 * ( ~~~a &&& (b &&& c)) + 22 * (a &&& ( ~~~b &&& c)) = 1 * (a &&& (b &&& c)) + 11 * (c ^^^  ~~~(a ||| ( ~~~b &&& c)))

theorem src5_thm (e e_1 : IntW 32) :
  add (LLVM.xor (LLVM.or e_1 e) (const? 32 (-1))) (LLVM.and e_1 e) ⊑ LLVM.xor (LLVM.xor e_1 e) (const? 32 (-1))

theorem test_sext_zext_thm.extracted_1._1 : ∀ (x : BitVec 16), signExtend 64 (zeroExtend 32 x) = zeroExtend 64 x

theorem test7_proof : test7_before ⊑ test7_after

theorem test23_proof : test23_before ⊑ test23_after

theorem lshrugt_02_02_exact_proof : lshrugt_02_02_exact_before ⊑ lshrugt_02_02_exact_after

theorem main7f_logical_thm.extracted_1._8 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ¬ofBool (x_3 &&& x_2 == x_1 &&& (x_3 &&& x_2)) = 1#1 →
    ¬ofBool (x_3 &&& x_2 != x_1 &&& (x_3 &&& x_2)) = 1#1 → ¬0#1 = 1#1 → False

theorem or_not_and_commute3_proof : or_not_and_commute3_before ⊑ or_not_and_commute3_after

theorem exact_lshr_eq_noexactdiv_proof : exact_lshr_eq_noexactdiv_before ⊑ exact_lshr_eq_noexactdiv_after

@[simp] theorem Hom.unCons_apply {Γ : Ctxt Ty} (f : Hom (Γ.cons t) Δ) (v : Var Γ u) :
    f.unCons v = f v.toCons

theorem Bisimul.symm (hsim : Bisimul R M₁ M₂) : Bisimul R.inv M₂ M₁

theorem negate_select_of_op_vs_negated_op_nsw_commuted_proof : negate_select_of_op_vs_negated_op_nsw_commuted_before ⊑ negate_select_of_op_vs_negated_op_nsw_commuted_after

theorem main9_proof : main9_before ⊑ main9_after

@[simp]
theorem Term.toBV_band {wenv : WidthExpr.Env wcard}
    {tctx : Term.Ctx wcard tcard}
    (benv : Term.BoolEnv bcard)
    (tenv : tctx.Env wenv) (a b : Term bcard ncard icard pcard tctx (.bv w)) :
  Term.toBV benv nenv ienv penv tenv (.band a b) = a.toBV benv nenv ienv penv tenv &&& b.toBV benv nenv ienv penv tenv

theorem positive_biggershl_shlnuw_ashrexact_proof : positive_biggershl_shlnuw_ashrexact_before ⊑ positive_biggershl_shlnuw_ashrexact_after

theorem corec₂_eq_corec₂_of
    (R : β₁ → β₂→ Prop)
    (f₁ : β₁ → (Option α₁ × Option α₂ × β₁) )
    (f₂ : β₂ → (Option α₁ × Option α₂ × β₂))
    (h : ∀ b₁ b₂, R b₁ b₂ →
      (f₁ b₁).fst = (f₂ b₂).fst
      ∧ R (f₁ b₁).snd.snd (f₂ b₂).snd.snd)
    (h2 : ∀ b₁ b₂, R b₁ b₂ →
      (f₁ b₁).snd.fst = (f₂ b₂).snd.fst
      ∧ R (f₁ b₁).snd.snd (f₂ b₂).snd.snd)
    {b₁ : β₁} {b₂ : β₂} (hR : R b₁ b₂):
    corec₂ b₁ f₁ = corec₂ b₂ f₂

theorem ashrsgt_02_01_exact_thm (e : IntW 4) :
  icmp IntPred.sgt (ashr e (const? 4 2) { «exact» := true }) (const? 4 1) ⊑ const? 1 0

theorem factorize_proof : factorize_before ⊑ factorize_after

theorem test47_thm (e : IntW 8) :
  zext 64 (LLVM.or (sext 32 e) (const? 32 42)) ⊑ zext 64 (sext 32 (LLVM.or e (const? 8 42)))

theorem test92_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬32#96 ≥ ↑96 → ¬32#64 ≥ ↑64 → truncate 64 (signExtend 96 x >>> 32#96) = x.sshiftRight' 32#64

theorem test3_thm (e : IntW 123) : LLVM.xor e e ⊑ const? 123 0

theorem trunc_shl_shl_infloop_thm.extracted_1._1 : ∀ (x : BitVec 64), ¬(1#64 ≥ ↑64 ∨ 2#64 ≥ ↑64) → 3#32 ≥ ↑32 → False

theorem lshrugt_02_03_proof : lshrugt_02_03_before ⊑ lshrugt_02_03_after

theorem lshr_or_or_fail_proof : lshr_or_or_fail_before ⊑ lshr_or_or_fail_after

theorem c_1_1_0_thm.extracted_1._1 : ∀ (x x_1 : BitVec 4),
  True ∧ (x_1 &&& BitVec.ofInt 4 (-2) &&& (x &&& 1#4) != 0) = true → False

theorem unmasked_shlop_insufficient_mask_shift_amount_proof : unmasked_shlop_insufficient_mask_shift_amount_before ⊑ unmasked_shlop_insufficient_mask_shift_amount_after

theorem sext_xor_sub_3_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → signExtend 64 x_1 - (signExtend 64 x_1 ^^^ x) = 0#64 - x

theorem and_not_or_or_not_or_xor_commute2_proof : and_not_or_or_not_or_xor_commute2_before ⊑ and_not_or_or_not_or_xor_commute2_after

theorem test5_proof : test5_before ⊑ test5_after

theorem shl_nsw_nuw_add_nsw_proof : shl_nsw_nuw_add_nsw_before ⊑ shl_nsw_nuw_add_nsw_after

theorem e_2 :
    1 *  ~~~x - 2 * (x ^^^ y) + 1 *  ~~~(x &&& y) = 2 *  ~~~(x ||| y) - 1 * (x &&&  ~~~y)

lemma CNFA.determinize_bv_language {m : CNFA n} :
    m.bv_recognizes L → m.determinize.bv_recognizes L

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 1), x &&& x = x

theorem trunc_shl_7_i8_i64_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬7#64 ≥ ↑64 → ¬7#8 ≥ ↑8 → truncate 8 (x <<< 7#64) = truncate 8 x <<< 7#8

theorem or_xor_common_op_commute5_thm (e e_1 e_2 : IntW 8) :
  LLVM.or (LLVM.xor e_2 e_1) (LLVM.or e e_2) ⊑ LLVM.or (LLVM.or e e_2) e_1

theorem ashr_C1_add_A_C2_i32_proof : ashr_C1_add_A_C2_i32_before ⊑ ashr_C1_add_A_C2_i32_after

lemma CNFA.determinize.f_spec {m : CNFA n} {a : BitVec n} {sa sa' : BitVec m.m.stateMax} :
    (a, sa') ∈ f m sa ↔ (∀ {s'}, s' ∈ bv_to_set sa' ↔ ∃ s ∈ bv_to_set sa, s' ∈ m.m.tr s a)

theorem zext_nneg_sext_ule_op0_wide_thm (e : IntW 8) (e_1 : IntW 9) :
  icmp IntPred.ule (zext 32 e_1 { «nneg» := true }) (sext 32 e) ⊑ icmp IntPred.ule e_1 (sext 9 e)

theorem main3b_logical_thm.extracted_1._4 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 0#32) = 1#1 → ¬0#1 = 1#1 → 1#32 = zeroExtend 32 (ofBool (x &&& 23#32 != 0#32))

@[simp]
lemma reduce_spec (M : NFA α σ) : M.reduce.accepts = M.accepts

theorem and_ne_with_one_bit_diff_constants3_logical_thm (e : IntW 8) :
  select (icmp IntPred.ne e (const? 8 65)) (icmp IntPred.ne e (const? 8 (-63))) (const? 1 0) ⊑
    icmp IntPred.ne (LLVM.and e (const? 8 127)) (const? 8 65)

theorem Term.denoteFin_eq_add {w : Nat} (t : Term) (env : EnvFin (w + 1) t.numVars) :
    t.denoteFin env = 2 * t.denoteFin env.getNonLsbs + t.denoteFin env.getLsb

theorem sgt_and_min_proof : sgt_and_min_before ⊑ sgt_and_min_after

theorem ashr_ult_9_proof : ashr_ult_9_before ⊑ ashr_ult_9_after

theorem ashrsgt_03_05_exact_proof : ashrsgt_03_05_exact_before ⊑ ashrsgt_03_05_exact_after

theorem bools_logical_commute1_and2_thm.extracted_1._6 : ∀ (x x_1 : BitVec 1), ¬x_1 = 1#1 → 0#1 = 1#1 → False

theorem mul_two' 
  (hppot : ppot &&& (ppot - 1) = 0)
  (hqpot : qpot &&& (qpot - 1) = 0)
  (hrpot : rpot &&& (rpot - 1) = 0)
  (hspot : spot &&& (spot - 1) = 0)
  (htpot : tpot &&& (tpot - 1) = 0)
  (hupot : upot &&& (upot - 1) = 0)
  (hpmask : pmask = ppot - 1)
  (hqmask : qmask = qpot - 1)
  (hrmask : rmask = rpot - 1)
  (hsmask : smask = spot - 1)
  (htmask : tmask = tpot - 1)
  (humask : umask = upot - 1) :
  (bw' rmask (mulMax' (bw' pmask a') pmask (bw' (2#o) (2#o)) (2#o))) =
  (bw' rmask ((bw' pmask a') <<< 1))

theorem zext_zext_sgt_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (zeroExtend 32 x <ₛ zeroExtend 32 x_1) = ofBool (x <ᵤ x_1)

theorem n0_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x &&& 4#8 <ᵤ x) = ofBool (x &&& BitVec.ofInt 8 (-5) != 0#8)

theorem ashr_sgt_exact_proof : ashr_sgt_exact_before ⊑ ashr_sgt_exact_after

theorem canonicalize_logic_first_and0_nsw_proof : canonicalize_logic_first_and0_nsw_before ⊑ canonicalize_logic_first_and0_nsw_after

theorem lsb_mask_sign_zext_wrong_cst2_proof : lsb_mask_sign_zext_wrong_cst2_before ⊑ lsb_mask_sign_zext_wrong_cst2_after

theorem lshr_or_or_no_const_thm (e e_1 e_2 e_3 : IntW 8) :
  LLVM.or (lshr e_3 e_2) (LLVM.or (lshr e_1 e_2) e) ⊑ LLVM.or (lshr (LLVM.or e_1 e_3) e_2) e

theorem PR30273_three_bools_thm.extracted_1._11 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 →
    ¬x_1 = 1#1 →
      True ∧ (zeroExtend 32 x).saddOverflow (zeroExtend 32 x_2) = true ∨
          True ∧ (zeroExtend 32 x).uaddOverflow (zeroExtend 32 x_2) = true →
        False

theorem shl_trunc_smaller_shl_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬(2#32 ≥ ↑32 ∨ 4#8 ≥ ↑8) → 6#8 ≥ ↑8 → False

theorem and_sequence_40_eq (w : Nat) :
    and_sequence_40_lhs w  ⊑ and_sequence_40_rhs w

theorem test43_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  (x_2 ||| x_1 * x) &&& (x_2 ^^^ -1#32 ^^^ x_1 * x) = x_1 * x &&& x_2

theorem zext_masked_bit_zero_to_smaller_bitwidth_proof : zext_masked_bit_zero_to_smaller_bitwidth_before ⊑ zext_masked_bit_zero_to_smaller_bitwidth_after

theorem lshrult_03_03_proof : lshrult_03_03_before ⊑ lshrult_03_03_after

theorem main7e_logical_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 &&& x_1 &&& x == x_2 &&& x_1) = 1#1 →
    ¬ofBool (x_2 &&& x_1 &&& x != x_2 &&& x_1) = 1#1 → ¬0#1 = 1#1 → False

theorem sext_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ (zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8))).saddOverflow (BitVec.ofInt 7 (-8)) = true) →
    zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) + BitVec.ofInt 7 (-8) = signExtend 7 x

theorem and_and_logic_or_2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), x_1 &&& x = 1#1 → x = 1#1 → 1#1 = x_1 &&& 1#1

theorem add_mask_ashr28_i32_thm (e : IntW 32) :
  add (LLVM.and (ashr e (const? 32 28)) (const? 32 8)) (ashr e (const? 32 28)) ⊑
    LLVM.and (lshr e (const? 32 28)) (const? 32 7)

theorem bools_logical_commute0_and1_and2_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 1),
  (x_2 ^^^ 1#1) &&& x_1 = 1#1 → ¬x_2 = 1#1 → 1#1 = x_1

theorem masked_and_notallzeroes_proof : masked_and_notallzeroes_before ⊑ masked_and_notallzeroes_after

theorem l_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32), 0#32 - x_2 + (0#32 - x_1) + x = x - (x_2 + x_1)

theorem lshrugt_02_10_exact_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ x >>> 2#4 <<< 2#4 ≠ x ∨ 2#4 ≥ ↑4) → ofBool (BitVec.ofInt 4 (-6) <ᵤ x >>> 2#4) = 0#1

theorem both_sides_fold_slt_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → ofBool (9#32 <ₛ 1#32) = 0#1

@[simp]
theorem replicate_zero' {w : Nat} : BitVec.replicate w 0#1 = BitVec.cast (by simp) (0#w)

theorem fixed : ∀ (x : BitVec 4) (y : BitVec 7),
  (signExtend 25 y = signExtend 25 x) ↔ (y = signExtend 7 x)

theorem main4_logical_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 7#32) = 1#1 → 0#1 = 1#1 → 0#32 = zeroExtend 32 (ofBool (x &&& 55#32 != 55#32))

theorem and1_shl1_is_cmp_eq_0_proof : and1_shl1_is_cmp_eq_0_before ⊑ and1_shl1_is_cmp_eq_0_after

theorem scalar_i32_shl_and_negC_eq_nonzero_thm (e e_1 : IntW 32) :
  icmp IntPred.eq (LLVM.and (shl e_1 e) (const? 32 (-8))) (const? 32 1) ⊑ const? 1 0

theorem zext_sext_ugt_known_nonneg_thm (e e_1 : IntW 8) :
  icmp IntPred.ugt (zext 32 (LLVM.and e_1 (const? 8 127))) (sext 32 e) ⊑
    icmp IntPred.ugt (LLVM.and e_1 (const? 8 127)) e

theorem test3_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1.ssubOverflow x = true) →
    ¬ofBool (x_1 - x == 0#32) = 1#1 → ofBool (x_1 == x) = 1#1 → ofBool (x_1 - x == 31#32) = 1#1

theorem not_shl_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬7#8 ≥ ↑8 → x <<< 7#8 ^^^ BitVec.ofInt 8 (-128) = (x ^^^ -1#8) <<< 7#8

theorem test85_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.uaddOverflow (BitVec.ofInt 32 (-16777216)) = true ∨
        True ∧ (x + BitVec.ofInt 32 (-16777216)) >>> 23#32 <<< 23#32 ≠ x + BitVec.ofInt 32 (-16777216) ∨ 23#32 ≥ ↑32) →
    23#32 ≥ ↑32 → False

theorem lshr_shl_pow2_const_xor_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 2#16 ≥ ↑16) → ofBool (x == 7#16) = 1#1 → 256#16 >>> x <<< 2#16 &&& 8#16 ^^^ 8#16 = 0#16

theorem positive_sameconst_shlnuwnsw_proof : positive_sameconst_shlnuwnsw_before ⊑ positive_sameconst_shlnuwnsw_after

theorem PR2844_logical_proof : PR2844_logical_before ⊑ PR2844_logical_after

theorem poo_thm (e e_1 e_2 e_3 : IntW 32) :
  LLVM.or (LLVM.and (select (icmp IntPred.slt e_3 e_2) (const? 32 (-1)) (const? 32 0)) e_1)
      (LLVM.and (select (icmp IntPred.slt e_3 e_2) (const? 32 0) (const? 32 (-1))) e) ⊑
    select (icmp IntPred.slt e_3 e_2) e_1 e

theorem test_zext_nneg_proof : test_zext_nneg_before ⊑ test_zext_nneg_after

theorem lshr_add_fail_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(x ≥ ↑8 ∨ x + 1#8 ≥ ↑8) →
    x ≥ ↑8 ∨
        x + 1#8 ≥ ↑8 ∨
          True ∧ (16#8 >>> x).saddOverflow (7#8 >>> (x + 1#8)) = true ∨
            True ∧ (16#8 >>> x).uaddOverflow (7#8 >>> (x + 1#8)) = true →
      False

theorem lshrugt_02_01_exact_proof : lshrugt_02_01_exact_before ⊑ lshrugt_02_01_exact_after

theorem test21_thm.extracted_1._1 : ∀ (x : BitVec 32), signExtend 32 (truncate 8 x) &&& 255#32 = x &&& 255#32

theorem select_ashr_proof : select_ashr_before ⊑ select_ashr_after

theorem select_icmp_eq_and_4096_0_xor_4096_thm (e e_1 : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e_1 (const? 32 4096)) (const? 32 0)) e (LLVM.xor e (const? 32 4096)) ⊑
    LLVM.xor e (LLVM.and e_1 (const? 32 4096))

theorem testtrunclowhigh_proof : testtrunclowhigh_before ⊑ testtrunclowhigh_after

theorem xor_nosignbit_ashr_thm (e : IntW 32) :
  ashr (LLVM.xor e (const? 32 2147418112)) (const? 32 8) ⊑ LLVM.xor (ashr e (const? 32 8)) (const? 32 8388352)

@[simp] theorem ofBitVec_and {w : Nat} {x y : BitVec w} : ofBitVecSext (x &&& y) = (ofBitVecSext x) &&& (ofBitVecSext y)

theorem or_not_xor_common_op_commute7_thm (e e_1 e_2 : IntW 8) :
  LLVM.or (LLVM.or (sub (const? 8 0) e_2) (LLVM.xor e_1 (const? 8 (-1)))) (LLVM.xor e e_1) ⊑
    LLVM.or (LLVM.xor (LLVM.and e e_1) (const? 8 (-1))) (sub (const? 8 0) e_2)

theorem n9_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬62#64 ≥ ↑64 →
    62#64 ≥ ↑64 ∨
        True ∧ signExtend 64 (truncate 32 (x >>> 62#64)) ≠ x >>> 62#64 ∨
          True ∧ zeroExtend 64 (truncate 32 (x >>> 62#64)) ≠ x >>> 62#64 ∨
            True ∧ (0#32).ssubOverflow (truncate 32 (x >>> 62#64)) = true →
      False

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

theorem absdiff1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 64),
  ¬ofBool (x_1 <ᵤ x) = 1#1 →
    (x_1 - x ^^^ signExtend 64 (ofBool (x_1 <ᵤ x))) - signExtend 64 (ofBool (x_1 <ᵤ x)) = x_1 - x

theorem select_2_thm.extracted_1._14 : ∀ (x x_1 x_2 : BitVec 8) (x_3 x_4 : BitVec 1),
  x_4 = 1#1 → x_3 = 1#1 → x_2 ^^^ -1#8 ^^^ -1#8 = x_2

theorem scalar_i32_signbit_lshr_and_eq_X_is_constant1_proof : scalar_i32_signbit_lshr_and_eq_X_is_constant1_before ⊑ scalar_i32_signbit_lshr_and_eq_X_is_constant1_after

theorem t_0_1_proof : t_0_1_before ⊑ t_0_1_after

theorem lowmask_or_zext_commute_proof : lowmask_or_zext_commute_before ⊑ lowmask_or_zext_commute_after

theorem ashr_lshr_exact_lshr_only_proof : ashr_lshr_exact_lshr_only_before ⊑ ashr_lshr_exact_lshr_only_after

theorem smear_sign_and_widen_proof : smear_sign_and_widen_before ⊑ smear_sign_and_widen_after

theorem ashrslt_01_07_thm.extracted_1._1 : ∀ (x : BitVec 4), ¬1#4 ≥ ↑4 → ofBool (x.sshiftRight' 1#4 <ₛ 7#4) = 1#1

@[simp]
theorem List.mem_attachWith_mem (l : List α) {P H}(x : α) h : ⟨x, h⟩ ∈ l.attachWith P H ↔ x ∈ l

theorem shift_xor_multiuse_cmp_xor_thm (e e_1 e_2 e_3 : IntW 32) :
  mul
      (mul
        (select (icmp IntPred.ne (const? 32 0) (LLVM.and e_3 (const? 32 4096))) e_2
          (LLVM.xor e_2 (const? 32 2048)))
        (select (icmp IntPred.ne (const? 32 0) (LLVM.and e_3 (const? 32 4096))) e_1 e))
      (LLVM.xor e_2 (const? 32 2048)) ⊑
    mul
      (mul
        (select (icmp IntPred.eq (LLVM.and e_3 (const? 32 4096)) (const? 32 0)) (LLVM.xor e_2 (const? 32 2048))
          e_2)
        (select (icmp IntPred.eq (LLVM.and e_3 (const? 32 4096)) (const? 32 0)) e e_1))
      (LLVM.xor e_2 (const? 32 2048))

theorem bools2_logical_commute1_and1_thm.extracted_1._7 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 &&& x_1 = 1#1 → x_1 ^^^ 1#1 = 1#1 → x_1 = 1#1 → x = x_2

theorem eq_invariant_fn
    (f : LoopBody t) (g : t → t) (hf : ∀ (i : Int) (v : t), f i v = g v) :
    LoopBody.IndexInvariant f ∧ atZero f = g

theorem e_1421 :
    3 *  ~~~z + 2 * (z ^^^ t) + 1 * z + 7 *  ~~~(z &&& t) + 1 *  ~~~t + 1 *  ~~~(z ^^^ t) - 5 *  ~~~(z ||| t) - 13 *  ~~~(z |||  ~~~t) - 4 * (z &&&  ~~~t) + 4 * (z &&& t) = 7 * (z |||  ~~~t) - 1 * t

theorem is_ascii_alphabetic_proof : is_ascii_alphabetic_before ⊑ is_ascii_alphabetic_after

theorem PR23309v2_proof : PR23309v2_before ⊑ PR23309v2_after

theorem test11_thm (e : IntW 32) :
  icmp IntPred.ult (LLVM.udiv (const? 32 4) e) (const? 32 1) ⊑ icmp IntPred.ugt e (const? 32 4)

theorem icmp_power2_and_icmp_shifted_mask_2147483648_805306368_proof : icmp_power2_and_icmp_shifted_mask_2147483648_805306368_before ⊑ icmp_power2_and_icmp_shifted_mask_2147483648_805306368_after

include hinj in
omit [BEq α] [Hashable α] [LawfulBEq α] in
lemma product.prodArray_spec_helper
    (is : Array γ) (hnd : is.toList.Nodup)
    (s : S₁) (hnew : ∀ s₂, f s s₂ ∉ is):
  let motive (a : Array γ) (S : Set S₂)  :=
    a.toList.Nodup ∧
    (∃ r, a.toList = is.toList ++ r ∧ (∀ z ∈ r, ∃ s₁ s₂, z = f s₁ s₂)) ∧
    ∀ s1 s2, f s1 s2 ∈ a ↔ s1 ≠ s ∧ f s1 s2 ∈ is ∨ s1 = s ∧ s2 ∈ S
  let body := m₂.attachWith _ hm₂ |>.fold (init := is) fun is s2 =>
      is.push (f s s2)
  motive body (m₂.attachWith _ hm₂).toSet

theorem add_smin_simplify2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.saddOverflow (BitVec.ofInt 32 (-3)) = true) →
    ¬ofBool (x + BitVec.ofInt 32 (-3) <ₛ 2147483645#32) = 1#1 → 2147483645#32 = x + BitVec.ofInt 32 (-3)

theorem lshr_shl_demand4_thm (e : IntW 8) :
  LLVM.or (shl (lshr (const? 8 60) e) (const? 8 3)) (const? 8 7) ⊑
    LLVM.or (shl (lshr (const? 8 60) e) (const? 8 3)) (const? 8 7) { «disjoint» := true }

theorem select_constants_and_icmp_ne0_zero_fval_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1),
  x_1 = 1#1 → ¬x = 1#1 → ofBool (12#8 &&& 0#8 != 0#8) = x

theorem shl_add_lshr_comm_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_1 <<< x >>> x ≠ x_1 ∨ x ≥ ↑32 ∨ True ∧ (x_2 * x_2).uaddOverflow (x_1 <<< x) = true ∨ x ≥ ↑32) →
    ¬(x ≥ ↑32 ∨ True ∧ ((x_2 * x_2) >>> x).uaddOverflow x_1 = true) →
      (x_2 * x_2 + x_1 <<< x) >>> x = (x_2 * x_2) >>> x + x_1

theorem src_thm.extracted_1._1 : ∀ (x : BitVec 1),
  ¬(zeroExtend 32 x ≥ ↑32 ∨ zeroExtend 32 x ≥ ↑32) →
    True ∧ ((-1#32) <<< zeroExtend 32 x).sshiftRight' (zeroExtend 32 x) ≠ -1#32 ∨
        zeroExtend 32 x ≥ ↑32 ∨
          True ∧
              ((((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x) <<< zeroExtend 32 x).sshiftRight'
                  (zeroExtend 32 x) ≠
                ((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x ∨
            True ∧
                (((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x) <<< zeroExtend 32 x >>> zeroExtend 32 x ≠
                  ((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x ∨
              zeroExtend 32 x ≥ ↑32 →
      False

theorem ashrslt_03_13_proof : ashrslt_03_13_before ⊑ ashrslt_03_13_after

theorem udiv_shl_mul_nuw_exact_proof : udiv_shl_mul_nuw_exact_before ⊑ udiv_shl_mul_nuw_exact_after

theorem PR28476_logical_proof : PR28476_logical_before ⊑ PR28476_logical_after

theorem FSM.and_eq (a b : FSM arity) : (a &&& b) = composeBinaryAux' FSM.and a b

theorem test3_apint_proof : test3_apint_before ⊑ test3_apint_after

theorem sle_swap_and_min_commute_proof : sle_swap_and_min_commute_before ⊑ sle_swap_and_min_commute_after

theorem test15b_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 32#32 == 0#32) = 1#1 → 0#32 = x &&& 32#32 ^^^ 32#32

theorem ashr_lshr_wrong_cond_thm (e e_1 : IntW 32) :
  select (icmp IntPred.sge e_1 (const? 32 (-1))) (lshr e_1 e) (ashr e_1 e) ⊑
    select (icmp IntPred.sgt e_1 (const? 32 (-2))) (lshr e_1 e) (ashr e_1 e)

theorem f1_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (truncate 8 x != 0#8) = 1#1 →
    ofBool (x &&& 16711680#32 != 0#32) = ofBool (truncate 8 x != 0#8) &&& ofBool (x &&& 16711680#32 != 0#32)

theorem test15j_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 2#32 != 0#32) = 1#1 → ofBool (x &&& 2#32 == 0#32) = 1#1 → 1089#32 = 577#32

theorem e_1187 :
     - 5 *  ~~~t - 5 *  ~~~(z &&&  ~~~t) + 1 *  ~~~(z &&&  ~~~z) - 5 * t - 1 *  ~~~(z &&& t) + 10 *  ~~~(z ||| t) + 4 * (z &&&  ~~~t) + 8 * (z &&& t) =  - 1 * (z ||| t) - 9 *  ~~~(z |||  ~~~t)

theorem multiuse_shl_shl_thm.extracted_1._1 : ∀ (x : BitVec 42),
  ¬(8#42 ≥ ↑42 ∨ 8#42 ≥ ↑42 ∨ 9#42 ≥ ↑42) → 8#42 ≥ ↑42 ∨ 17#42 ≥ ↑42 → False

theorem main6d_thm (e : IntW 32) :
  select
      (LLVM.or (icmp IntPred.ne (LLVM.and e (const? 32 7)) (const? 32 3))
        (icmp IntPred.eq (LLVM.and e (const? 32 16)) (const? 32 0)))
      (const? 32 0) (const? 32 1) ⊑
    zext 32 (icmp IntPred.eq (LLVM.and e (const? 32 23)) (const? 32 19))

theorem main5_like_logical_thm.extracted_1._8 : ∀ (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 (ofBool (x &&& 7#32 != 7#32))

theorem eq_smin3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 + 3#32 <ₛ x) = 1#1 → ofBool (x_1 + 3#32 == x_1 + 3#32) = ofBool (x_1 + 3#32 ≤ₛ x)

theorem sel_false_val_is_a_masked_ashr_of_true_val1_thm.extracted_1._4 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& BitVec.ofInt 32 (-2147483588) == 0#32) = 1#1 →
    ¬(2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& BitVec.ofInt 32 (-2147483588)).sshiftRight' 2#32) ≥ ↑64) →
      ¬(2#32 ≥ ↑32 ∨
            True ∧ (x_1.sshiftRight' 2#32 &&& BitVec.ofInt 32 (-536870897)).msb = true ∨
              zeroExtend 64 (x_1.sshiftRight' 2#32 &&& BitVec.ofInt 32 (-536870897)) ≥ ↑64) →
        x.sshiftRight' (zeroExtend 64 ((x_1 &&& BitVec.ofInt 32 (-2147483588)).sshiftRight' 2#32)) =
          x.sshiftRight' (zeroExtend 64 (x_1.sshiftRight' 2#32 &&& BitVec.ofInt 32 (-536870897)))

theorem test_and1_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (0#32 ≤ₛ x_1) = 1#1 → ¬ofBool (-1#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ x &&& 2147483647#32) = 0#1

theorem icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail_proof : icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail_before ⊑ icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail_after

theorem uge_or_not_max_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ne e_1 (const? 8 (-1))) (const? 1 1) (icmp IntPred.uge e_1 e) ⊑ const? 1 1

theorem scalar_i32_shl_and_negC_slt_thm (e e_1 : IntW 32) :
  icmp IntPred.slt (LLVM.and (shl e_1 e) (const? 32 (-8))) (const? 32 0) ⊑
    icmp IntPred.slt (shl e_1 e) (const? 32 0)

theorem select_1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  x_2 = 1#1 → x_1 ^^^ (x ^^^ 45#8) ^^^ -1#8 = x ^^^ x_1 ^^^ BitVec.ofInt 8 (-46)

theorem ashrsgt_03_11_proof : ashrsgt_03_11_before ⊑ ashrsgt_03_11_after

theorem sge_or_max_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x ≤ₛ x_1) = 1#1 → ofBool (x_1 == 127#8) = ofBool (x ≤ₛ x_1)

theorem neg_or_ashr_i32_commute_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬((x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨
        (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨ 31#32 ≥ ↑32) →
    ¬(x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true →
      ((42#32).sdiv x ||| 0#32 - (42#32).sdiv x).sshiftRight' 31#32 = signExtend 32 (ofBool ((42#32).sdiv x != 0#32))

theorem and_or2_thm (e e_1 e_2 : IntW 1) :
  select (LLVM.and (LLVM.xor e_2 (const? 1 1)) e_1) e e_1 ⊑ select e_1 (select e_2 (const? 1 1) e) (const? 1 0)

theorem ashr_lshr_cst2_proof : ashr_lshr_cst2_before ⊑ ashr_lshr_cst2_after

theorem test23_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.sgt e (const? 32 1)) (icmp IntPred.sle e (const? 32 2)) ⊑
    icmp IntPred.eq e (const? 32 2)

theorem test13_thm (e e_1 : IntW 32) :
  add (add e_1 (const? 32 1)) (LLVM.xor (LLVM.or e (const? 32 (-1431655767))) (const? 32 1431655766)) ⊑
    sub e_1 (LLVM.and e (const? 32 1431655766))

theorem ule_or_min_proof : ule_or_min_before ⊑ ule_or_min_after

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

theorem demorgan_and_apint4_thm (e e_1 : IntW 66) :
  LLVM.and (LLVM.xor e_1 (const? 66 (-1))) (LLVM.xor e (const? 66 (-1))) ⊑
    LLVM.xor (LLVM.or e_1 e) (const? 66 (-1))

theorem a_false_implies_b_false2_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8),
  ofBool (20#8 <ᵤ x_1) = 1#1 → ofBool (10#8 <ᵤ x_1) = 1#1 → ofBool (10#8 <ᵤ x_1) ||

theorem slt_and_shl_one_proof : slt_and_shl_one_before ⊑ slt_and_shl_one_after

theorem e_1191 :
    2 *  ~~~z + 11 *  ~~~t - 7 *  ~~~(z ^^^ t) + 3 *  ~~~(z &&&  ~~~z) - 1 * z - 9 *  ~~~(z ||| t) - 5 *  ~~~(z |||  ~~~t) - 13 * (z &&&  ~~~t) =  - 5 * (z &&& t)

theorem ashr_sge_noexact_proof : ashr_sge_noexact_before ⊑ ashr_sge_noexact_after

theorem land_lor_left1_thm (e e_1 : IntW 1) : select (select e_1 e (const? 1 0)) (const? 1 1) e_1 ⊑ e_1

theorem foo1_and_signbit_lshr_without_shifting_signbit_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x_1 ≥ ↑32 → ofBool (1#32 <<< x_1 &&& x == 0#32) = 1#1 → True ∧ 1#32 <<< x_1 >>> x_1 ≠ 1#32 ∨ x_1 ≥ ↑32 → False

theorem tryFactorization_xor_lshr_ashr_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬(x ≥ ↑32 ∨ x ≥ ↑32) → x ≥ ↑32 → False

theorem e_340 :
     - 11 * (x |||  ~~~y) + 4 *  ~~~x + 7 *  ~~~(x &&&  ~~~y) - 2 *  ~~~(x &&& y) + 1 * y + 2 *  ~~~(x ||| y) - 13 *  ~~~(x |||  ~~~y) + 10 * (x &&&  ~~~y) =  - 3 * (x &&& y) - 3 * (x ^^^ y)

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

theorem main7b_proof : main7b_before ⊑ main7b_after

theorem icmp_slt_sext_ne_zero_nofold_thm (e : IntW 32) :
  icmp IntPred.slt (sext 32 (icmp IntPred.ne e (const? 32 0))) e ⊑
    icmp IntPred.sgt e (sext 32 (icmp IntPred.ne e (const? 32 0)))

theorem scalar_i64_signbit_lshr_and_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 64),
  ¬x_1 ≥ ↑64 →
    True ∧ BitVec.ofInt 64 (-9223372036854775808) >>> x_1 <<< x_1 ≠ BitVec.ofInt 64 (-9223372036854775808) ∨ x_1 ≥ ↑64 →
      False

theorem fold_sext_to_and_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (signExtend 32 x &&& BitVec.ofInt 32 (-2147483647) == 1#32) = ofBool (x &&& BitVec.ofInt 8 (-127) == 1#8)

theorem t0_proof : t0_before ⊑ t0_after

theorem icmp_shl_nsw_sge1_proof : icmp_shl_nsw_sge1_before ⊑ icmp_shl_nsw_sge1_after

theorem ashr_exact_poison_constant_fold_proof : ashr_exact_poison_constant_fold_before ⊑ ashr_exact_poison_constant_fold_after

theorem equiv_add (a : (BitVec 32)) :
    (CombOp.add [a, a]) = CombOp.shlPar a 1

theorem udiv_shl_shl_nuw_nsw2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(True ∧ (x_2 <<< x_1).sshiftRight' x_1 ≠ x_2 ∨
        True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨
          x_1 ≥ ↑8 ∨ True ∧ (x <<< x_1).sshiftRight' x_1 ≠ x ∨ x_1 ≥ ↑8 ∨ x <<< x_1 = 0) →
    x = 0 → False

theorem slt_zero_eq_ne_0_fail1_proof : slt_zero_eq_ne_0_fail1_before ⊑ slt_zero_eq_ne_0_fail1_after

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

theorem uge_and_max_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x ≤ᵤ x_1) = 1#1 → 0#1 = ofBool (x_1 == -1#8)

theorem select_icmp_ne_0_and_8_xor_1073741824_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 8),
  ofBool (0#8 != x_1 &&& 8#8) = 1#1 → ofBool (x_1 &&& 8#8 == 0#8) = 1#1 → x = x ^^^ 1073741824#32

theorem slt_negative_multip_rem_zero_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.smulOverflow (BitVec.ofInt 8 (-7)) = true) →
    ofBool (x * BitVec.ofInt 8 (-7) <ₛ 21#8) = ofBool (BitVec.ofInt 8 (-3) <ₛ x)

theorem test42_proof : test42_before ⊑ test42_after

theorem sext_shl_trunc_smaller_thm (e : IntW 32) (e_1 : IntW 16) :
  trunc 5 (shl (sext 32 e_1) e) ⊑ trunc 5 (shl (zext 32 e_1) e)

theorem shl_trunc_bigger_shl_proof : shl_trunc_bigger_shl_before ⊑ shl_trunc_bigger_shl_after

theorem e_191 :
     - 11 *  ~~~(x ^^^ y) + 11 * y + 5 * (x ||| y) + 4 *  ~~~(x ||| y) - 12 * (x &&&  ~~~y) - 5 * (x &&& y) =  - 7 *  ~~~(x &&& y) + 23 *  ~~~(x |||  ~~~y)

theorem t0_commutative_thm.extracted_1._10 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 x_3 : BitVec 8),
  ¬ofBool (x_3 == x_2) = 1#1 → ¬ofBool (x_3 != x_2) = 1#1 → x_1 ^^^ 1#1 = 1#1 → 0#1 = 1#1 → False

theorem e_412 :
    7 *  ~~~(x &&&  ~~~x) - 1 * y + 2 *  ~~~x + 2 *  ~~~(x &&& y) + 4 * (x |||  ~~~y) + 11 *  ~~~(x &&&  ~~~y) - 26 *  ~~~(x ||| y) - 13 * (x &&&  ~~~y) = 21 * (x &&& y) + 21 *  ~~~(x |||  ~~~y)

theorem src_is_notmask_x_xor_neg_x_proof : src_is_notmask_x_xor_neg_x_before ⊑ src_is_notmask_x_xor_neg_x_after

theorem fold_sext_to_and_wrong4_proof : fold_sext_to_and_wrong4_before ⊑ fold_sext_to_and_wrong4_after

theorem PR1817_1_logical_thm (e : IntW 32) :
  select (icmp IntPred.slt e (const? 32 10)) (icmp IntPred.ult e (const? 32 10)) (const? 1 0) ⊑
    icmp IntPred.ult e (const? 32 10)

theorem sum_same'
  (hppot : ppot &&& (ppot - 1) = 0)
  (hqpot : qpot &&& (qpot - 1) = 0)
  (hrpot : rpot &&& (rpot - 1) = 0)
  (hspot : spot &&& (spot - 1) = 0)
  (htpot : tpot &&& (tpot - 1) = 0)
  (hupot : upot &&& (upot - 1) = 0)
  (hpmask : pmask = ppot - 1)
  (hqmask : qmask = qpot - 1)
  (hrmask : rmask = rpot - 1)
  (hsmask : smask = spot - 1)
  (htmask : tmask = tpot - 1)
  (humask : umask = upot - 1) :
  (bw' qmask (addMax' (bw' pmask a') pmask (bw' pmask a') pmask)) =
  (bw' qmask (mulMax' (bw' (2#o) (2#o)) (2#o) (bw' pmask a') pmask))

theorem e_1604 :
     - 5 * ((a &&& b) |||  ~~~(b ||| c)) + 2 * (b ^^^ ( ~~~a &&& (b ||| c))) + 1 * (a ^^^ (b ||| c)) - 2 * (b &&&  ~~~(a ^^^ c)) - 1 * (c ^^^ ( ~~~a ||| (b &&& c))) - 1 * ( ~~~b &&&  ~~~(a ^^^ c)) + 2 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 1 *  ~~~(a &&& ( ~~~b &&& c)) - 6 *  ~~~( ~~~a &&& (b ||| c)) + 2 *  ~~~(a ^^^ (b &&& c)) + 5 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 3 *  ~~~(a ||| (b ||| c)) - 10 *  ~~~(a ||| ( ~~~b ||| c)) - 3 *  ~~~( ~~~a ||| (b ||| c)) + 3 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 13 * ( ~~~a &&& ( ~~~b &&& c)) - 9 * ( ~~~a &&& (b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) + 6 * (a &&& (b &&& c)) =  - 7 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c)))

theorem e_965 :
     - 7 *  ~~~(z ^^^ t) + 7 * (z |||  ~~~t) - 2 * (z ||| t) - 2 *  ~~~z + 2 *  ~~~(z &&&  ~~~z) + 4 *  ~~~(z |||  ~~~t) - 7 * (z &&&  ~~~t) = 2 *  ~~~(z &&& t) - 2 *  ~~~t

theorem select_1_thm.extracted_1._12 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 x_3 : BitVec 8) (x_4 : BitVec 1),
  ¬x_4 = 1#1 → ¬x_1 = 1#1 → x ^^^ 123#8 ^^^ -1#8 = x ^^^ BitVec.ofInt 8 (-124)

theorem t10_almost_highest_bit_thm (e : IntW 64) (e_1 e_2 : IntW 32) :
  icmp IntPred.ne
      (LLVM.and (shl e_2 (sub (const? 32 64) e_1)) (trunc 32 (lshr e (zext 64 (add e_1 (const? 32 (-2)))))))
      (const? 32 0) ⊑
    icmp IntPred.ne
      (LLVM.and (shl e_2 (sub (const? 32 64) e_1))
        (trunc 32 (lshr e (zext 64 (add e_1 (const? 32 (-2))) { «nneg» := true }))))
      (const? 32 0)

theorem lshr_sext_i1_to_i128_proof : lshr_sext_i1_to_i128_before ⊑ lshr_sext_i1_to_i128_after

@[simp]
lemma Set.mem_cast (A : W → Type) (P : A w → Prop) (h : w = w') (x : A w') :
  x ∈ h ▸ setOf P ↔
  P (h ▸ x)

theorem n2_proof : n2_before ⊑ n2_after

theorem p_constmask_commutative_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  True ∧ (x_1 &&& BitVec.ofInt 32 (-65281) &&& (x &&& 65280#32) != 0) = true → False

theorem sgt_minnum_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.smulOverflow 7#8 = true) → ofBool (BitVec.ofInt 8 (-128) <ₛ x * 7#8) = 1#1

theorem t4_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8), x = 1#1 → x_1 - BitVec.ofInt 8 (-42) = 42#8 + x_1

theorem test20_thm (e : IntW 8) : LLVM.and (lshr e (const? 8 7)) (const? 8 1) ⊑ lshr e (const? 8 7)

theorem lshrugt_01_08_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬1#4 ≥ ↑4 → ofBool (BitVec.ofInt 4 (-8) <ᵤ x >>> 1#4) = 0#1

@[simp]
lemma List.Vector.ofFn_0 {f : Fin 0 → α} : ofFn f = .nil

theorem trunc_sel_equal_zext_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → zeroExtend 32 42#16 = 42#32

theorem main10_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 64#32 == 0#32) = 1#1 →
    ofBool (x &&& 192#32 == 0#32) = 1#1 → ¬ofBool (0#8 ≤ₛ truncate 8 x) = 1#1 → 1#32 = 2#32

@[simp] theorem Lets.denote_nil {Γ : Ctxt d.Ty} :
    (Lets.nil : Lets d Γ eff Γ).denote = (return ·)

theorem urem_i32_c_multiuse_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬10#32 = 0 →
    10#32 = 0 ∨
        True ∧ (zeroExtend 32 x % 10#32).saddOverflow (zeroExtend 32 x) = true ∨
          True ∧ (zeroExtend 32 x % 10#32).uaddOverflow (zeroExtend 32 x) = true →
      False

theorem e_1232 :
    7 *  ~~~(z ^^^ t) - 3 * (z |||  ~~~t) - 6 * (z ||| t) - 2 *  ~~~(z &&&  ~~~z) - 11 *  ~~~z + 7 * t + 9 *  ~~~(z ||| t) + 12 *  ~~~(z |||  ~~~t) + 13 * (z &&&  ~~~t) = 1 * (z &&& t) + 2 * z

theorem test12commuted_proof : test12commuted_before ⊑ test12commuted_after

theorem lshrult_02_01_exact_proof : lshrult_02_01_exact_before ⊑ lshrult_02_01_exact_after

theorem ule_swap_or_not_min_commute_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != 0#8) = 1#1 → ofBool (x_1 ≤ᵤ x) = 1#1

theorem multiuse_select_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → 64#64 * (64#64 - zeroExtend 64 x) = 4032#64

@[simp] lemma eval_var' (i : arity) (x : arity → BitStream) : (var' i).eval x = x i

theorem logical_and_cond_reuse_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → x = 0#1

theorem multiuse2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ ((x &&& 96#32) <<< 8#32).sshiftRight' 8#32 ≠ x &&& 96#32 ∨
        True ∧ (x &&& 96#32) <<< 8#32 >>> 8#32 ≠ x &&& 96#32 ∨
          8#32 ≥ ↑32 ∨
            True ∧ ((x &&& 6#32) <<< 8#32).sshiftRight' 8#32 ≠ x &&& 6#32 ∨
              True ∧ (x &&& 6#32) <<< 8#32 >>> 8#32 ≠ x &&& 6#32 ∨
                8#32 ≥ ↑32 ∨
                  True ∧ ((x &&& 24#32) <<< 8#32).sshiftRight' 8#32 ≠ x &&& 24#32 ∨
                    True ∧ (x &&& 24#32) <<< 8#32 >>> 8#32 ≠ x &&& 24#32 ∨
                      8#32 ≥ ↑32 ∨
                        True ∧ ((x &&& 6#32) <<< 1#32).sshiftRight' 1#32 ≠ x &&& 6#32 ∨
                          True ∧ (x &&& 6#32) <<< 1#32 >>> 1#32 ≠ x &&& 6#32 ∨
                            1#32 ≥ ↑32 ∨
                              True ∧ ((x &&& 96#32) <<< 1#32).sshiftRight' 1#32 ≠ x &&& 96#32 ∨
                                True ∧ (x &&& 96#32) <<< 1#32 >>> 1#32 ≠ x &&& 96#32 ∨
                                  1#32 ≥ ↑32 ∨
                                    True ∧ ((x &&& 24#32) <<< 1#32).sshiftRight' 1#32 ≠ x &&& 24#32 ∨
                                      True ∧ (x &&& 24#32) <<< 1#32 >>> 1#32 ≠ x &&& 24#32 ∨ 1#32 ≥ ↑32) →
    8#32 ≥ ↑32 ∨
        1#32 ≥ ↑32 ∨
          1#32 ≥ ↑32 ∨
            1#32 ≥ ↑32 ∨
              True ∧ (x <<< 1#32 &&& 192#32 &&& (x <<< 1#32 &&& 48#32) != 0) = true ∨
                True ∧ (x <<< 1#32 &&& 12#32 &&& (x <<< 1#32 &&& 192#32 ||| x <<< 1#32 &&& 48#32) != 0) = true ∨
                  True ∧
                    (x <<< 8#32 &&& 32256#32 &&&
                          (x <<< 1#32 &&& 12#32 ||| (x <<< 1#32 &&& 192#32 ||| x <<< 1#32 &&& 48#32)) !=
                        0) =
                      true →
      False

theorem mul_constant_nuw_eq_thm (e e_1 : IntW 32) :
  icmp IntPred.eq (mul e_1 (const? 32 22) { «nsw» := false, «nuw» := true })
      (mul e (const? 32 22) { «nsw» := false, «nuw» := true }) ⊑
    icmp IntPred.eq e_1 e

theorem e_1358 :
     - 7 * (z ||| t) + 1 * z + 5 *  ~~~(z &&& t) + 3 *  ~~~z - 1 *  ~~~(z &&&  ~~~t) - 2 * (z |||  ~~~t) - 1 * t - 2 *  ~~~(z ||| t) + 1 *  ~~~(z |||  ~~~t) + 13 * (z &&& t) = 3 *  ~~~(z ^^^ t) - 3 * (z &&&  ~~~t)

theorem lshr_shl_pow2_const_xor_proof : lshr_shl_pow2_const_xor_before ⊑ lshr_shl_pow2_const_xor_after

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

theorem icmp_mul_nsw_sle_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ x_1.smulOverflow 7#8 = true ∨ True ∧ x.smulOverflow 7#8 = true) →
    ofBool (x_1 * 7#8 ≤ₛ x * 7#8) = ofBool (x_1 ≤ₛ x)

theorem land_band_left2_proof : land_band_left2_before ⊑ land_band_left2_after

theorem n7_wrong_pred2_proof : n7_wrong_pred2_before ⊑ n7_wrong_pred2_after

theorem icmp_slt_0_and_icmp_sge_neg2_i64_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬63#64 ≥ ↑64 →
    x >>> 63#64 &&& zeroExtend 64 (ofBool (BitVec.ofInt 64 (-2) ≤ₛ x)) =
      zeroExtend 64 (ofBool (BitVec.ofInt 64 (-3) <ᵤ x))

theorem test24_logical_proof : test24_logical_before ⊑ test24_logical_after

theorem e_1495 :
    3 *  ~~~t - 3 *  ~~~(z ^^^ t) + 1 *  ~~~z - 6 *  ~~~(z &&& t) - 1 * t - 2 *  ~~~(z &&&  ~~~t) - 2 * z + 4 * (z ^^^ t) + 7 *  ~~~(z ||| t) + 9 *  ~~~(z |||  ~~~t) + 6 * (z &&&  ~~~t) =  - 13 * (z &&& t) + 5 * (z ||| t)

theorem main7d_logical_thm.extracted_1._14 : ∀ (x x_1 x_2 x_3 x_4 : BitVec 32),
  ¬ofBool (x_4 &&& (x_3 &&& x_2) == x_3 &&& x_2) = 1#1 →
    ofBool (x_4 &&& (x_3 &&& x_2) != x_3 &&& x_2) = 1#1 → ¬0#1 = 1#1 → 1#32 = zeroExtend 32 1#1

theorem e_2125 :
    1 * (e &&&  ~~~(d ^^^ f)) + 7 * (e ^^^ (d ||| ( ~~~e ||| f))) - 7 *  ~~~(d &&& ( ~~~e ||| f)) + 1 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 1 * (e ^^^ (d &&& f)) - 7 *  ~~~( ~~~d &&& (e ||| f)) + 1 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 1 * (e ^^^ (d &&&  ~~~f)) - 5 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * (f &&&  ~~~(d ^^^ e)) + 7 * (e ^^^ ( ~~~d ||| (e ^^^ f))) + 7 * (e &&& (d ||| f)) + 7 * (e |||  ~~~(d |||  ~~~f)) - 6 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) - 7 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 5 * ((d &&& e) ||| (e ^^^ f)) + 3 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) + 3 * (d ^^^ f) - 5 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) + 2 * (e |||  ~~~(d ^^^ f)) - 1 *  ~~~(d ^^^ (e &&& f)) - 3 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) - 6 * ( ~~~d ||| ( ~~~e &&& f)) - 3 * (d |||  ~~~e) + 5 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 5 * ((d &&& f) |||  ~~~(e ||| f)) - 1 * ( ~~~f ||| (d ^^^ e)) - 2 *  ~~~(d &&&  ~~~d) - 7 * (e ^^^ ( ~~~d ||| (e ||| f))) - 1 * d + 2 *  ~~~(d |||  ~~~f) - 2 *  ~~~(d ^^^ (e ||| f)) - 1 *  ~~~(d |||  ~~~e) + 1 * (e &&&  ~~~(d &&&  ~~~f)) + 2 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 2 * (e &&& f) - 1 * (d ||| f) - 6 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 14 *  ~~~(d ||| (e ||| f)) + 3 *  ~~~(d ||| ( ~~~e ||| f)) + 9 *  ~~~( ~~~d ||| (e ||| f)) + 14 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 16 * ( ~~~d &&& ( ~~~e &&& f)) + 9 * ( ~~~d &&& (e &&& f)) + 1 * (d &&& ( ~~~e &&& f)) = 3 * e

theorem e_23 :
     - 2 *  ~~~(x ^^^ y) - 2 *  ~~~(x &&& y) + 1 *  ~~~(x |||  ~~~y) + 1 * (x &&&  ~~~y) + 1 * (x &&& y) =  - 4 *  ~~~(x ||| y) - 1 * (x ||| y)

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

theorem neg_or_lshr_i32_commute_proof : neg_or_lshr_i32_commute_before ⊑ neg_or_lshr_i32_commute_after

theorem test5_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (x ≤ₛ x) = 1#1

theorem lshr_shl_pow2_const_overflow_proof : lshr_shl_pow2_const_overflow_before ⊑ lshr_shl_pow2_const_overflow_after

theorem trunc_shl_1_i32_i64_thm.extracted_1._1 : ∀ (x : BitVec 64), ¬1#64 ≥ ↑64 → 1#32 ≥ ↑32 → False

theorem test10_thm.extracted_1._1 : ∀ (x : BitVec 1), ofBool (1#1 <ᵤ x) = 0#1

theorem shl_xor_xor_good_mask_proof : shl_xor_xor_good_mask_before ⊑ shl_xor_xor_good_mask_after

@[simp]
theorem eval_repeatForever_eq_self (b : Bool) : (FSM.repeatForever b).eval env = fun _ => b

theorem test69_proof : test69_before ⊑ test69_after

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

theorem xor_andn_commute4_proof : xor_andn_commute4_before ⊑ xor_andn_commute4_after

theorem trunc_shl_31_i32_i64_proof : trunc_shl_31_i32_i64_before ⊑ trunc_shl_31_i32_i64_after

theorem main2_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 1#32 == 0#32) ||

@[simp]
theorem castLe_mk_eq_mk {α : Type _} {n m : Nat} (i : Fin n) (h : n ≤ m) (x : α) :
    (Inputs.mk i x).castLe h = Inputs.mk (i.castLE (by omega)) x

theorem andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond_proof : andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond_before ⊑ andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond_after

theorem ripple_nsw4_proof : ripple_nsw4_before ⊑ ripple_nsw4_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_5_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.ne (LLVM.and e (const? 32 15)) (const? 32 0))
      (icmp IntPred.eq (LLVM.and e (const? 32 15)) (const? 32 8)) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 15)) (const? 32 8)

theorem select_xor_icmp_meta_proof : select_xor_icmp_meta_before ⊑ select_xor_icmp_meta_after

theorem positive_samevar_proof : positive_samevar_before ⊑ positive_samevar_after

@[simp] theorem Com.denoteLets_outContextHom (com : Com d Γ .pure ty) (V : Valuation Γ)
    {vTy} (v : Var Γ vTy) :
    com.denoteLets V (com.outContextHom v) = V v

theorem fold_sext_to_and_wrong9_proof : fold_sext_to_and_wrong9_before ⊑ fold_sext_to_and_wrong9_after

theorem test8_thm (e e_1 : IntW 32) :
  trunc 64 (LLVM.or (shl (zext 128 e_1) (const? 128 32)) (zext 128 e)) ⊑
    LLVM.or (shl (zext 64 e_1) (const? 64 32) { «nsw» := false, «nuw» := true }) (zext 64 e)
      { «disjoint» := true }

theorem trunc_equality_nsw_zext_proof : trunc_equality_nsw_zext_before ⊑ trunc_equality_nsw_zext_after

theorem icmp_sgt11_thm (e : IntW 8) :
  icmp IntPred.sgt (shl e (const? 8 7) { «nsw» := true, «nuw» := false }) (const? 8 (-2)) ⊑
    icmp IntPred.sgt e (const? 8 (-1))

theorem sge_or_max_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x ≤ₛ x_1) ||

theorem test4_proof : test4_before ⊑ test4_after

theorem test_proof : test_before ⊑ test_after

@[simp, grind=] theorem val_dropUntilDiff : (@dropUntilDiff _ Γ _ v).val = v.val+1

theorem main4f_like_logical_thm.extracted_1._9 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 &&& x_1 != x_1) = 1#1 →
    ofBool (x_2 &&& x_1 == x_1) = 1#1 →
      ofBool (x_2 &&& x != x) = 1#1 → 0#32 = zeroExtend 32 (ofBool (x_2 &&& x == x))

theorem lshrult_03_11_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬3#4 ≥ ↑4 → ofBool (x >>> 3#4 <ᵤ BitVec.ofInt 4 (-5)) = 1#1

theorem t0_thm (e : IntW 16) (e_1 : IntW 32) :
  shl (trunc 16 (shl e_1 (zext 32 (sub (const? 16 32) e)))) (add e (const? 16 (-24))) ⊑
    shl (trunc 16 e_1) (const? 16 8)

@[simp]
lemma lift_accepts (M : NFA (BitVec n) σ) (f : Fin n → Fin m) :
    (M.lift f).accepts = BitVecs'.transport f ⁻¹' M.accepts

theorem t3_thm (e : IntW 8) :
  icmp IntPred.sle (sub (const? 8 0) e { «nsw» := true, «nuw» := false }) e ⊑
    icmp IntPred.sgt e (const? 8 (-1))

theorem or_or_logic_and_2_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 ||

theorem xor_of_icmps_commute_proof : xor_of_icmps_commute_before ⊑ xor_of_icmps_commute_after

theorem lshrult_02_03_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 2)) (const? 4 3) ⊑ icmp IntPred.ult e (const? 4 (-4))

theorem test_shl_nuw__all_are_safe_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ofBool (x_1 &&& 15#32 == 0#32) = 1#1 →
    ¬(2#32 ≥ ↑32 ∨ True ∧ (x_1 <<< 2#32 &&& 60#32).msb = true ∨ zeroExtend 64 (x_1 <<< 2#32 &&& 60#32) ≥ ↑64) →
      x = x.sshiftRight' (zeroExtend 64 (x_1 <<< 2#32 &&& 60#32))

theorem select_constants_and_icmp_eq0_zero_fval_thm.extracted_1._4 : ∀ (x x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬x = 1#1 → ofBool (0#8 &&& 0#8 == 0#8) = 0#1 ^^^ 1#1

theorem test4_thm (e : IntW 8) :
  icmp IntPred.sle e (const? 8 126) ⊑ icmp IntPred.ne e (const? 8 127)

theorem t0_thm (e e_1 e_2 e_3 : IntW 8) (e_4 : IntW 1) :
  select (select (LLVM.xor e_4 (const? 1 1)) (icmp IntPred.eq e_3 e_2) (const? 1 0)) e_1 e ⊑
    select (select e_4 (const? 1 1) (icmp IntPred.ne e_3 e_2)) e e_1

theorem mul_of_sdiv_fail_ub_thm (e : IntW 8) :
  mul (LLVM.sdiv e (const? 8 6) { «exact» := true }) (const? 8 (-6)) ⊑ sub (const? 8 0) e

theorem logical_and_icmps2_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → 0#1 = 1#1 → ofBool (x == 10086#32) = 0#1

theorem e_1401 :
    4 * t - 2 * (z |||  ~~~t) + 2 * (z ^^^ t) - 2 *  ~~~(z &&&  ~~~z) + 1 *  ~~~(z ^^^ t) + 3 * (z ||| t) - 4 *  ~~~(z ||| t) - 14 *  ~~~(z |||  ~~~t) - 1 * (z &&&  ~~~t) - 4 * (z &&& t) =  - 7 *  ~~~z

@[simp]
theorem BitVec.intCast_eq_ofInt : ((i : Int) : BitVec w) = BitVec.ofInt w i

theorem or_ashr_not_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8), ¬(x_1 ≥ ↑8 ∨ x_1 ≥ ↑8) → x_1 ≥ ↑8 → False

theorem positive_biggershl_ashrexact_proof : positive_biggershl_ashrexact_before ⊑ positive_biggershl_ashrexact_after

theorem scalar_i32_udiv_and_negC_eq_X_is_constant3_proof : scalar_i32_udiv_and_negC_eq_X_is_constant3_before ⊑ scalar_i32_udiv_and_negC_eq_X_is_constant3_after

theorem shl_xor_xor_bad_mask_distribute_proof : shl_xor_xor_bad_mask_distribute_before ⊑ shl_xor_xor_bad_mask_distribute_after

theorem select1_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → zeroExtend 32 (truncate 8 x) = x &&& 255#32

theorem t0_const_lshr_shl_ne_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (LLVM.and (shl e_1 (const? 32 1)) (lshr e (const? 32 1))) (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and (lshr e (const? 32 2)) e_1) (const? 32 0)

theorem icmp_ugt_16_proof : icmp_ugt_16_before ⊑ icmp_ugt_16_after

theorem ugt_and_min_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ugt e_1 e) (icmp IntPred.eq e_1 (const? 8 0)) (const? 1 0) ⊑ const? 1 0

theorem zext_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 0#41 = zeroExtend 41 x

theorem icmp_eq_select_proof : icmp_eq_select_before ⊑ icmp_eq_select_after

theorem positive_different_trunc_both_proof : positive_different_trunc_both_before ⊑ positive_different_trunc_both_after

theorem logical_or_implies_proof : logical_or_implies_before ⊑ logical_or_implies_after

@[simp]
theorem instantiate_mvar_zero {hφ : List.length (w :: ws) = φ} {h0 : 0 < φ} :
    ConcreteOrMVar.instantiate (Subtype.mk (w :: ws) hφ)  (ConcreteOrMVar.mvar ⟨0, h0⟩) = w

theorem icmp_eq_and_pow2_shl_pow2_negative1_thm (e : IntW 32) :
  zext 32 (icmp IntPred.eq (LLVM.and (shl (const? 32 11) e) (const? 32 16)) (const? 32 0)) ⊑
    LLVM.xor (LLVM.and (lshr (shl (const? 32 11) e) (const? 32 4)) (const? 32 1)) (const? 32 1)

theorem lshrugt_02_07_exact_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ x >>> 2#4 <<< 2#4 ≠ x ∨ 2#4 ≥ ↑4) → ofBool (7#4 <ᵤ x >>> 2#4) = 0#1

theorem reused_mul_nuw_xy_z_selectnonzero_ugt_thm (e e_1 e_2 : IntW 8) :
  select (icmp IntPred.ne e_2 (const? 8 0))
      (icmp IntPred.ugt (mul e_1 e_2 { «nsw» := false, «nuw» := true })
        (mul e e_2 { «nsw» := false, «nuw» := true }))
      (const? 1 1) ⊑
    select (icmp IntPred.eq e_2 (const? 8 0)) (const? 1 1)
      (icmp IntPred.ugt (mul e_1 e_2 { «nsw» := false, «nuw» := true })
        (mul e e_2 { «nsw» := false, «nuw» := true }))

theorem and_not_or_commute3_proof : and_not_or_commute3_before ⊑ and_not_or_commute3_after

theorem ult_or_not_max_commute_proof : ult_or_not_max_commute_before ⊑ ult_or_not_max_commute_after

theorem zext_sext_add_icmp_eq_minus1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ofBool (zeroExtend 8 x_1 + signExtend 8 x == -1#8) = x &&& (x_1 ^^^ 1#1)

theorem shl_trunc_bigger_shl_proof : shl_trunc_bigger_shl_before ⊑ shl_trunc_bigger_shl_after

theorem some_left {x : α} {y? : Option α} :
    some x ⊑ y? ↔ y? = some x

theorem zext_sext_add_icmp_sgt_minus2_proof : zext_sext_add_icmp_sgt_minus2_before ⊑ zext_sext_add_icmp_sgt_minus2_after

theorem test_shl__nuw_is_safe_proof : test_shl__nuw_is_safe_before ⊑ test_shl__nuw_is_safe_after

theorem test35_proof : test35_before ⊑ test35_after

theorem or_logic_or_logic_and_6_proof : or_logic_or_logic_and_6_before ⊑ or_logic_or_logic_and_6_after

theorem add_of_mul_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(True ∧ x_2.smulOverflow x_1 = true ∨
        True ∧ x_2.smulOverflow x = true ∨ True ∧ (x_2 * x_1).saddOverflow (x_2 * x) = true) →
    x_2 * x_1 + x_2 * x = x_2 * (x_1 + x)

theorem e_1729 :
    2 * ((a ||| b) &&&  ~~~(b ^^^ c)) - 1 * (b ^^^ (a &&&  ~~~c)) + 7 *  ~~~(b &&& c) - 1 * ((a &&& b) ^^^ (b |||  ~~~c)) - 1 *  ~~~(a &&&  ~~~b) - 1 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) + 3 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 3 * (b &&&  ~~~(a &&&  ~~~c)) + 1 * (b &&&  ~~~(a ^^^ c)) - 6 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 2 *  ~~~(a |||  ~~~c) - 1 *  ~~~( ~~~a &&& ( ~~~b &&& c)) + 1 * ( ~~~a &&& ( ~~~b ||| c)) + 11 * (a &&& b) + 7 *  ~~~(a ||| b) - 2 * (a ^^^ (b ^^^ c)) + 7 * (a ||| (b &&& c)) - 3 *  ~~~( ~~~a &&& (b &&& c)) + 3 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 4 * (a ||| b) + 11 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 5 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) + 1 *  ~~~(a &&& ( ~~~b ||| c)) - 13 *  ~~~(a ||| (b ||| c)) - 13 *  ~~~(a ||| ( ~~~b ||| c)) - 32 *  ~~~( ~~~a ||| (b ||| c)) - 17 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 14 * ( ~~~a &&& ( ~~~b &&& c)) - 16 * ( ~~~a &&& (b &&& c)) - 32 * (a &&& ( ~~~b &&& c)) - 25 * (a &&& (b &&& c)) =  - 4 * (b ^^^ (a ||| c))

theorem udiv_exact_ne_30_no_of_thm (e e_1 : IntW 8) :
  icmp IntPred.ne (LLVM.udiv e_1 (LLVM.and e (const? 8 7)) { «exact» := true }) (const? 8 30) ⊑
    icmp IntPred.ne (mul (LLVM.and e (const? 8 7)) (const? 8 30) { «nsw» := false, «nuw» := true }) e_1

theorem scalar_i32_shl_and_negC_eq_X_is_constant2_thm (e : IntW 32) :
  icmp IntPred.eq (LLVM.and (shl (const? 32 1) e) (const? 32 (-8))) (const? 32 0) ⊑
    icmp IntPred.ult e (const? 32 3)

@[bv_multi_width_normalize] theorem Bool.or_eq_false : ((a || b) = false) = (a = false ∧ b = false)

theorem and_not_or_commute8_proof : and_not_or_commute8_before ⊑ and_not_or_commute8_after

theorem e_853 :
     - 7 *  ~~~(z &&& t) - 5 *  ~~~t + 13 *  ~~~(z ||| t) + 8 *  ~~~(z |||  ~~~t) + 13 * (z &&&  ~~~t) + 1 * (z &&& t) = 1 *  ~~~(z &&&  ~~~z)

theorem Factor.denote_eq_toNat_reflectFin {w : Nat} (xs : Env w) (f : Factor) :
    f.denote xs = (f.reflectFin (EnvFin.ofEnv xs _)).toNat

theorem and_ne_with_diff_one_logical_proof : and_ne_with_diff_one_logical_before ⊑ and_ne_with_diff_one_logical_after

theorem test58_proof : test58_before ⊑ test58_after

theorem test3_proof : test3_before ⊑ test3_after

theorem add_shl_same_amount_partial_nsw2_proof : add_shl_same_amount_partial_nsw2_before ⊑ add_shl_same_amount_partial_nsw2_after

theorem icmp_ne_and_pow2_shl1_proof : icmp_ne_and_pow2_shl1_before ⊑ icmp_ne_and_pow2_shl1_after

theorem badimm3_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 8#16 ≥ ↑16) →
    ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 8#16)) = 1#1 →
      ¬ofBool (x + 128#16 <ᵤ 256#16) = 1#1 →
        14#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 14#16)) ≠ x.sshiftRight' 14#16 → False

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

theorem icmp_slt_0_or_icmp_sgt_0_i64_fail0_thm (e : IntW 64) :
  LLVM.or (lshr e (const? 64 63)) (zext 64 (icmp IntPred.slt e (const? 64 0))) ⊑ lshr e (const? 64 63)

theorem trunc_shl_7_i8_i64_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬7#64 ≥ ↑64 → ¬7#8 ≥ ↑8 → truncate 8 (x <<< 7#64) = truncate 8 x <<< 7#8

theorem test19_thm.extracted_1._2 : ∀ (x : BitVec 10),
  ¬(2#3 ≥ ↑3 ∨ 2#3 ≥ ↑3) →
    ¬(True ∧ (0#3).ssubOverflow (truncate 3 x &&& 1#3) = true) →
      signExtend 10 ((truncate 3 x <<< 2#3).sshiftRight' 2#3) = signExtend 10 (0#3 - (truncate 3 x &&& 1#3))

theorem xor_to_xor2_thm (e e_1 : IntW 32) : LLVM.xor (LLVM.and e_1 e) (LLVM.or e e_1) ⊑ LLVM.xor e_1 e

@[bv_multi_width_normalize] theorem ite_true_false {_ : Decidable p} : (ite p True False) = p

theorem test23_thm (e : IntW 44) : trunc 11 (ashr (shl e (const? 44 33)) (const? 44 33)) ⊑ trunc 11 e

theorem trunc_shl_15_i16_i32_proof : trunc_shl_15_i16_i32_before ⊑ trunc_shl_15_i16_i32_after

theorem tail_bisim_of_bisim_of_head_eq {a b : Stream α} (h_sim : a ~ b) (head_eq : a.head = b.head) :
    a.tail ~ b.tail

theorem uge_swap_or_not_max_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 ≤ᵤ x) = 1#1 → ofBool (x != -1#8) = 1#1

theorem t10_almost_highest_bit_proof : t10_almost_highest_bit_before ⊑ t10_almost_highest_bit_after

theorem src2_proof : src2_before ⊑ src2_after

theorem e_2334 :
    1 *  ~~~(d ||| (e &&& f)) + 2 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 6 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 1 * (f &&& (d ||| e)) - 7 *  ~~~(d ^^^ f) + 11 * (f &&&  ~~~(d &&&  ~~~e)) - 5 * (f ^^^ (d |||  ~~~e)) + 11 * ((e &&& f) ||| (d &&& (e ||| f))) - 1 * (f ||| (d ^^^ e)) - 2 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) - 2 *  ~~~( ~~~d ||| (e ^^^ f)) - 2 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 1 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 11 * (e ^^^ ( ~~~d ||| (e ^^^ f))) - 3 * (f ^^^  ~~~(d |||  ~~~e)) - 3 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 2 * (d &&& e) - 1 * (f |||  ~~~(d ||| e)) - 11 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 2 * (f |||  ~~~(d ^^^ e)) + 11 * (d &&& (e ^^^ f)) + 2 * (e ^^^ (d ||| (e &&& f))) - 3 * (d ||| f) - 5 * (d &&& (e ||| f)) + 2 * ((d &&& e) ||| (e ^^^ f)) - 1 * (e ^^^ f) + 7 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 1 *  ~~~(d &&& (e ||| f)) + 11 *  ~~~(d &&& ( ~~~e &&& f)) + 7 * (e ^^^ ( ~~~d ||| (e ||| f))) + 2 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 5 * ((d &&& f) |||  ~~~(e ||| f)) + 1 *  ~~~(e ^^^ f) + 4 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) - 6 * ( ~~~d ||| ( ~~~e ||| f)) + 4 * (d ^^^ ( ~~~e ||| f)) + 5 * (e ||| (d &&& f)) + 1 * ( ~~~e &&&  ~~~(d ^^^ f)) + 1 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 1 * (f ^^^ (d ||| ( ~~~e ||| f))) - 1 * (f ^^^ (d ||| ( ~~~e &&& f))) - 11 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) + 1 * (e ||| (d ^^^ f)) + 4 * (e ^^^ ( ~~~d ||| (e &&& f))) - 2 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) - 5 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 1 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) - 1 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 2 * (f ||| (d &&& e)) - 1 *  ~~~(d ||| e) + 3 * ((d &&& e) |||  ~~~(e |||  ~~~f)) + 5 * (e ^^^ (d ||| ( ~~~e &&& f))) + 1 * (e ^^^  ~~~(d &&&  ~~~f)) - 1 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 5 * ((e &&& f) ^^^  ~~~(d &&& (e ^^^ f))) - 3 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 6 *  ~~~(d &&& ( ~~~e ||| f)) + 1 *  ~~~(d ^^^ (e ||| f)) - 26 *  ~~~(d ||| (e ||| f)) + 16 *  ~~~(d ||| ( ~~~e ||| f)) + 17 *  ~~~( ~~~d ||| (e ||| f)) - 7 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 32 * ( ~~~d &&& ( ~~~e &&& f)) - 23 * (d &&& ( ~~~e &&& f)) - 31 * (d &&& (e &&& f)) = 1 *  ~~~(e |||  ~~~f)

theorem different_size_sext_sext_sle_proof : different_size_sext_sext_sle_before ⊑ different_size_sext_sext_sle_after

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

theorem main3e_like_logical_thm.extracted_1._9 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 &&& x_1 == 0#32) = 1#1 → ofBool (x_2 &&& x_1 != 0#32) = 1#1 → 0#1 = 1#1 → 0#32 = zeroExtend 32 1#1

theorem imp2 (w : Nat) (a b : BitVec w) : ((a ≤ b) ∧ (b ≤ a)) → (a = b)

theorem t0_proof : t0_before ⊑ t0_after

theorem test10_proof : test10_before ⊑ test10_after

theorem xor_orn_commute1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ¬(x_1 = 0 ∨ x_1 = 0) → x_1 = 0 → False

theorem mul_of_sdiv_thm (e : IntW 8) :
  mul (LLVM.sdiv e (const? 8 12) { «exact» := true }) (const? 8 (-6)) ⊑
    sub (const? 8 0) (ashr e (const? 8 1) { «exact» := true }) { «nsw» := true, «nuw» := false }

theorem negative2_thm (e e_1 : IntW 32) :
  LLVM.and (icmp IntPred.slt e_1 e) (icmp IntPred.sge e_1 (const? 32 0)) ⊑
    LLVM.and (icmp IntPred.slt e_1 e) (icmp IntPred.sgt e_1 (const? 32 (-1)))

theorem test_sub_255_Y_eq_255_proof : test_sub_255_Y_eq_255_before ⊑ test_sub_255_Y_eq_255_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_7_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 0#32) = 1#1 → ofBool (x &&& 15#32 != 8#32) = 1#1

theorem test_nuw_dropped_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741823#32 == 0#32) = 1#1 → 2#32 ≥ ↑32 → False

theorem select_sub_icmp_bad_2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == 1#32) = 1#1 → x - x_1 = x + -1#32

theorem uge_swap_or_max_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ule e_1 e) (const? 1 1) (icmp IntPred.eq e (const? 8 (-1))) ⊑
    icmp IntPred.ule e_1 e

theorem and_zext_eq_zero_proof : and_zext_eq_zero_before ⊑ and_zext_eq_zero_after

theorem ashrslt_01_06_proof : ashrslt_01_06_before ⊑ ashrslt_01_06_after

theorem ashr_mul_sign_bits_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬3#32 ≥ ↑32 → True ∧ (signExtend 16 x_1).smulOverflow (signExtend 16 x) = true ∨ 3#16 ≥ ↑16 → False

theorem ashrsgt_02_14_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬2#4 ≥ ↑4 → ofBool (BitVec.ofInt 4 (-2) <ₛ x.sshiftRight' 2#4) = ofBool (BitVec.ofInt 4 (-5) <ₛ x)

theorem lshr_pow2_ult_proof : lshr_pow2_ult_before ⊑ lshr_pow2_ult_after

theorem fold_add_udiv_urem_to_mul_proof : fold_add_udiv_urem_to_mul_before ⊑ fold_add_udiv_urem_to_mul_after

theorem test_ne_proof : test_ne_before ⊑ test_ne_after

theorem udiv_shl_mul_nuw_proof : udiv_shl_mul_nuw_before ⊑ udiv_shl_mul_nuw_after

theorem e_79 :
    3 *  ~~~y - 11 * x + 11 *  ~~~(x &&&  ~~~x) - 14 *  ~~~(x ||| y) - 3 * (x &&&  ~~~y) = 11 *  ~~~(x |||  ~~~y)

theorem bool_eq_iff (b₁ b₂ : Bool) : (b₁ = b₂) = (b₁ ↔ b₂)

theorem test15d_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and e (const? 32 16)) (const? 32 0)) (const? 32 16) (const? 32 0) ⊑
    LLVM.and e (const? 32 16)

theorem max_sub_ult_c1_thm (e : IntW 32) :
  select (icmp IntPred.ult e (const? 32 1)) (add e (const? 32 (-1))) (const? 32 0) ⊑
    sext 32 (icmp IntPred.eq e (const? 32 0))

theorem main7d_logical_thm.extracted_1._13 : ∀ (x x_1 x_2 x_3 x_4 : BitVec 32),
  ¬ofBool (x_4 &&& (x_3 &&& x_2) == x_3 &&& x_2) = 1#1 →
    ofBool (x_4 &&& (x_3 &&& x_2) != x_3 &&& x_2) = 1#1 → 0#1 = 1#1 → 0#32 = zeroExtend 32 1#1

theorem p3_sgt_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (65534#32 <ₛ x) = 1#1 → ¬ofBool (x <ₛ 65535#32) = 1#1 → False

theorem reduce_xor_common_op_commute0_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 4),
  x_2 ^^^ x_1 ^^^ x ||

theorem test_and2_thm (e e_1 : IntW 32) :
  LLVM.and (icmp IntPred.sgt e_1 (const? 32 (-1)))
      (icmp IntPred.sle e_1 (LLVM.and e (const? 32 2147483647))) ⊑
    icmp IntPred.ule e_1 (LLVM.and e (const? 32 2147483647))

theorem test7_proof : test7_before ⊑ test7_after

theorem test9_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741824#32 != 0#32) &&& ofBool (-1#32 <ₛ x) =
    ofBool (x &&& BitVec.ofInt 32 (-1073741824) == 1073741824#32)

theorem t1_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → signExtend 8 x_1 + x ^^^ signExtend 8 x_1 = x

theorem add_2_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 : BitVec 8),
  x_1 = 1#1 → x_2 + (x ^^^ -1#8) ^^^ -1#8 = x - x_2

theorem do_not_add_annotation_to_existing_instr_proof : do_not_add_annotation_to_existing_instr_before ⊑ do_not_add_annotation_to_existing_instr_after

theorem ashr_ult_0_proof : ashr_ult_0_before ⊑ ashr_ult_0_after

theorem ashrsgt_01_05_exact_proof : ashrsgt_01_05_exact_before ⊑ ashrsgt_01_05_exact_after

theorem shl_or_proof : shl_or_before ⊑ shl_or_after

theorem icmp_x_slt_0_and_icmp_y_sgt_neg1_i32_fail_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬31#32 ≥ ↑32 →
    x_1 >>> 31#32 &&& zeroExtend 32 (ofBool (-1#32 <ₛ x)) =
      zeroExtend 32 (ofBool (x_1 <ₛ 0#32) &&& ofBool (-1#32 <ₛ x))

theorem ashrsgt_03_02_thm.extracted_1._1 : ∀ (x : BitVec 4), ¬3#4 ≥ ↑4 → ofBool (2#4 <ₛ x.sshiftRight' 3#4) = 0#1

theorem positive_sameconst_shlnuw_thm (e : IntW 32) :
  lshr (shl e (const? 32 5) { «nsw» := false, «nuw» := true }) (const? 32 5) ⊑ e

theorem p0_proof : p0_before ⊑ p0_after

theorem t0_thm (e e_1 e_2 e_3 : IntW 32) :
  LLVM.xor (select (icmp IntPred.eq e_3 e_2) (icmp IntPred.eq e_1 e) (const? 1 0)) (const? 1 1) ⊑
    select (icmp IntPred.ne e_3 e_2) (const? 1 1) (icmp IntPred.ne e_1 e)

theorem or_logic_or_logic_and_6_proof : or_logic_or_logic_and_6_before ⊑ or_logic_or_logic_and_6_after

theorem shl_lshr_demand3_proof : shl_lshr_demand3_before ⊑ shl_lshr_demand3_after

theorem const_sub_const_sub_proof : const_sub_const_sub_before ⊑ const_sub_const_sub_after

theorem e_1963 :
     - 2 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 5 * ((a &&& c) ||| (b &&&  ~~~c)) - 7 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) - 2 * (b ||| c) - 1 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) + 1 * ( ~~~c &&&  ~~~(a ^^^ b)) - 7 * (c |||  ~~~(a |||  ~~~b)) + 11 * (c ^^^ (a |||  ~~~b)) + 1 * (b &&&  ~~~c) + 3 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 7 * (c ^^^ (a ||| b)) + 2 * (a ||| (b &&& c)) - 6 * (a &&& (b ||| c)) - 7 *  ~~~(a &&& (b &&& c)) - 1 * (a ^^^ (b ^^^ c)) + 2 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) + 3 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 5 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 1 *  ~~~(a &&& c) - 7 * (c &&& (a ^^^ b)) - 2 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 4 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) + 3 * ( ~~~a &&& ( ~~~b ||| c)) - 5 * ((a &&& c) ^^^ (b ||| c)) + 7 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c))) - 6 * (b ^^^ ( ~~~a &&& (b ^^^ c))) - 3 * (b ^^^ ( ~~~a ||| (b ||| c))) - 1 * a + 7 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 7 * ((a &&& b) |||  ~~~(b |||  ~~~c)) - 1 * (c &&&  ~~~(a ^^^ b)) - 11 * (b &&&  ~~~(a &&& c)) - 1 * (a ^^^ (b &&& c)) + 3 * ( ~~~b ||| (a ^^^ c)) + 2 *  ~~~a + 5 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) - 5 *  ~~~(a ||| (b &&& c)) + 5 * (b ^^^  ~~~(a ||| (b &&& c))) + 1 *  ~~~(a ||| ( ~~~b &&& c)) - 5 * (c ^^^ ( ~~~a &&& (b ||| c))) - 1 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) + 1 * (c ||| (a &&&  ~~~b)) + 2 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) - 11 * (b &&& c) - 5 * ((a |||  ~~~b) &&& (b ^^^ c)) + 7 *  ~~~(a ^^^ (b ^^^ c)) + 1 * (b |||  ~~~(a ||| c)) - 25 *  ~~~(a ||| (b ||| c)) + 42 *  ~~~(a ||| ( ~~~b ||| c)) - 11 *  ~~~( ~~~a ||| (b ||| c)) + 7 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 33 * ( ~~~a &&& ( ~~~b &&& c)) + 13 * ( ~~~a &&& (b &&& c)) + 22 * (a &&& ( ~~~b &&& c)) + 14 * (a &&& (b &&& c)) =  - 3 * (b ^^^ (a &&& c))

@[simp] theorem Valuation.cast_rfl {Γ : Ctxt Ty} (h : Γ = Γ) (V : Valuation Γ) : V.cast h = V

theorem test_add_nuw__nsw_is_safe_proof : test_add_nuw__nsw_is_safe_before ⊑ test_add_nuw__nsw_is_safe_after

theorem select2_proof : select2_before ⊑ select2_after
</all_available_lemmas>

<local_ctx>
import Batteries.Data.Fin.Basic

import Batteries.Data.Fin.Lemmas

import Blase.SingleWidth.Defs

import Blase.AutoStructs.Constructions

import Blase.AutoStructs.Defs

import Blase.AutoStructs.FiniteStateMachine

import Mathlib.Tactic.Ring

import Mathlib.Data.Nat.Size -- TODO: remove and get rid of shiftLeft_eq_mul_pow use

import Mathlib.Data.BitVec

import Mathlib.Tactic.FinCases

open Fin.NatCast

open Mathlib

def NFA.sa (_ : NFA α σ) := σ → Language α

structure NFA.correct (M : NFA α σ) (ζ : M.sa) (L : Language α) where
  cond1 : ∀ w, (w ∈ L ↔ ∃ q ∈ M.accept, w ∈ ζ q)
  cond2 : ∀ w q, q ∈ M.eval w ↔ w ∈ ζ q

abbrev BVRel := ∀ ⦃w⦄, BitVec w → BitVec w → Prop

abbrev BVNRel n := ∀ ⦃w⦄, List.Vector (BitVec w) n → Prop

def NFA'.sa (M : NFA' n) := M.σ → BVNRel n

def NFA'.sa2 (M : NFA' 2) := M.σ → BVRel

def langRel (R : BVNRel n) : Set (BitVecs n) :=
  { bvs | R bvs.bvs }

def langRel2 (R : BVRel) : Set (BitVecs 2) :=
  { bvs | R (bvs.bvs.get 0) (bvs.bvs.get 1) }

structure NFA'.correct (M : NFA' n) (ζ : M.sa) (L : BVNRel n) where
  cond1 : ∀ ⦃w⦄ (bvn : List.Vector (BitVec w) n), (L bvn ↔ ∃ q ∈ M.M.accept, ζ q bvn)
  cond2 q : q ∈ M.M.start ↔ ζ q (List.Vector.replicate n .nil)
  cond3 q a {w} (bvn : List.Vector (BitVec w) n) : q ∈ M.M.stepSet { q | ζ q bvn } a ↔
              ζ q (List.Vector.ofFn fun k => BitVec.cons (a.getLsbD k) (bvn.get k))

structure NFA'.correct2 (M : NFA' 2) (ζ : M.sa2) (L : BVRel) where
  cond1 : ∀ (bv1 bv2 : BitVec w), (L bv1 bv2 ↔ ∃ q ∈ M.M.accept, ζ q bv1 bv2)
  cond2 q : q ∈ M.M.start ↔ ζ q .nil .nil
  cond3 q a w (bv1 bv2 : BitVec w) : q ∈ M.M.stepSet { q | ζ q bv1 bv2 } a ↔
              ζ q (BitVec.cons (a.getLsbD 0) bv1) (BitVec.cons (a.getLsbD 1) bv2)

section fsm

abbrev Alphabet (arity: Type) [FinEnum arity] := BitVec (FinEnum.card arity + 1)

variable {arity : Type} [FinEnum arity]

def finFunToBitVec [fe : FinEnum carry] (c : carry → Bool) : BitVec (FinEnum.card carry) :=
  BitVec.ofFn fun i => c (fe.equiv.invFun i)

def bitVecToFinFun [FinEnum ar] (bv : BitVec $ FinEnum.card ar) : ar → Bool :=
  fun c => bv[FinEnum.equiv.toFun c]

def NFA.ofFSM (p : FSM arity) : NFA (Alphabet arity) (p.α → Bool) where
  start := { q | q = p.initCarry }
  accept := ⊤
  step s a := {s' |
    let (s'', b) := p.nextBit s (bitVecToFinFun (a.truncate $ FinEnum.card arity))
    s' = s'' ∧ a.msb = b }

@[simp]
abbrev inFSMRel (p : FSM arity) {w} (bvn : List.Vector (BitVec w) _) :=
  bvn.get (Fin.last (FinEnum.card arity)) = p.evalBV (fun ar => bvn.get (FinEnum.equiv.toFun ar))

def NFA'.ofFSM_sa (p : FSM arity) : (NFA'.ofFSM' p).sa := fun q _ bvn =>
    inFSMRel p bvn ∧ q = p.carryBV (fun ar => bvn.get (FinEnum.equiv.toFun ar))

def NFA'.ofFSM_correct (p : FSM arity) :
    (NFA'.ofFSM' p).correct (ofFSM_sa p) (fun _ bvn => inFSMRel p bvn) :=

open BitStream in

def CNFA.ofFSM (p : FSM arity) : CNFA (FinEnum.card arity + 1) :=
  worklistRun (BitVec (FinEnum.card p.α))
    (fun _ => true)
    #[finFunToBitVec p.initCarry]
    (by admit /- proof elided -/
    )
    f
  where

end fsm

section nfas_relations

def RawCNFA.autEq : RawCNFA (BitVec 2) :=
  let m := RawCNFA.empty
  let (s, m) := m.newState
  let m := m.addInitial s
  let m := m.addFinal s
  let m := m.addTrans 0 s s
  let m := m.addTrans 3 s s
  m

def CNFA.autEq : CNFA 2 :=
  ⟨RawCNFA.autEq, by admit /- proof elided -/
  ⟩

def NFA.autEq : NFA (BitVec 2) Unit :=
  { start := ⊤, accept := ⊤, step _ a := { _s' | if a = 0 ∨ a = 3 then true else false }}

def NFA'.autEq : NFA' 2 :=
  ⟨Unit, NFA.autEq⟩

def NFA'.eqRel : BVRel := fun _ x y => x = y

def autEq_equiv : CNFA.autEq.m.states ≃ NFA'.autEq.σ where
  toFun := fun ⟨s, hs⟩ =>
    match s with
    | _ => ()
  invFun q :=
    match q with
    | () => ⟨0, by admit /- proof elided -/
    ⟩
  left_inv := by admit /- proof elided -/

def RawCNFA.autUnsignedCmp (cmp: RelationOrdering) : RawCNFA (BitVec 2) :=
  let m := RawCNFA.empty
  let (seq, m) := m.newState
  let (sgt, m) := m.newState
  let (slt, m) := m.newState
  let m := m.addInitial seq
  let m := m.addManyTrans [0#2, 3#2] seq seq
  let m := m.addTrans 1#2 seq sgt
  let m := m.addTrans 2#2 seq slt
  let m := m.addManyTrans [0#2, 1#2, 3#2] sgt sgt
  let m := m.addTrans 2#2 sgt slt
  let m := m.addManyTrans [0#2, 2#2, 3#2] slt slt
  let mf := m.addTrans 1#2 slt sgt
  match cmp with
  | .lt => mf.addFinal slt
  | .le => (mf.addFinal slt).addFinal seq
  | .gt => mf.addFinal sgt
  | .ge => (mf.addFinal sgt).addFinal seq

def CNFA.autUnsignedCmp (cmp: RelationOrdering) : CNFA 2 :=
  ⟨RawCNFA.autUnsignedCmp cmp, RawCNFA.autoUnsignedCmp_wf⟩

inductive NFA.unsignedCmpState : Type where
| eq | gt | lt
deriving Fintype, DecidableEq

def NFA.unsignedCmpStep (q : NFA.unsignedCmpState) (a : BitVec 2) : List NFA.unsignedCmpState :=
  match q, a with
  | .eq, 0 => [ .eq ] | .eq, 3 => [ .eq ] | .eq, 1 => [ .gt ] | .eq, 2 => [ .lt ]
  | .gt, 0 => [ .gt ] | .gt, 1 => [ .gt ] | .gt, 3 => [ .gt ] | .gt, 2 => [ .lt ]
  | .lt, 0 => [ .lt ] | .lt, 1 => [ .gt ] | .lt, 2 => [ .lt ] | .lt, 3 => [ .lt ]

def NFA.autUnsignedCmp (cmp: RelationOrdering) : NFA (BitVec 2) unsignedCmpState where
  step s a := { s' | s' ∈ unsignedCmpStep s a }
  start := {s | s = .eq }
  accept := { s | s ∈ match cmp with | .lt => [unsignedCmpState.lt] | .le => [.lt, .eq] | .gt => [.gt] | .ge => [.gt, .eq] }

def NFA'.autUnsignedCmp (cmp: RelationOrdering) : NFA' 2 :=
  ⟨_, NFA.autUnsignedCmp cmp⟩

def RelationOrdering.urel (cmp : RelationOrdering) : BVRel :=
  match cmp with
  | .lt => fun _ bv1 bv2 => bv1.ult bv2
  | .le => fun _ bv1 bv2 => bv1.ule bv2
  | .gt => fun _ bv1 bv2 => bv2.ult bv1
  | .ge => fun _ bv1 bv2 => bv2.ule bv1

def NFA'.autUnsignedCmpSA (q : NFA.unsignedCmpState) : BVRel :=
  match q with
  | .eq => fun _ bv1 bv2 => bv1 = bv2
  | .lt => fun _ bv1 bv2 => bv1.ult bv2
  | .gt => fun _ bv1 bv2 => bv2.ult bv1

def RawCNFA.autSignedCmp (cmp: RelationOrdering) : RawCNFA (BitVec 2) :=
  let (m, sltfin, sgtfin, seq) := m
  match cmp with
  | .lt => m.addFinal sltfin
  | .le => (m.addFinal sltfin).addFinal seq
  | .gt => m.addFinal sgtfin
  | .ge => (m.addFinal sgtfin).addFinal seq
where

def CNFA.autSignedCmp (cmp: RelationOrdering) : CNFA 2 :=
  ⟨RawCNFA.autSignedCmp cmp, RawCNFA.autSignedCmp_wf⟩

inductive NFA.signedCmpState : Type where
| eq | gt | lt | ltfin | gtfin
deriving DecidableEq, Fintype

def NFA.signedCmpStep (q : NFA.signedCmpState) (a : BitVec 2) : List NFA.signedCmpState :=
  match q, a with
  | .eq, 0 => [ .eq ] | .eq, 3 => [.eq] | .eq, 1 => [.gt, .ltfin] | .eq, 2 => [ .lt, .gtfin ]
  | .gt, 0 => [ .gt, .gtfin ] | .gt, 1 => [ .gt, .ltfin ] | .gt, 3 => [ .gt, .gtfin ] | .gt, 2 => [ .lt, .gtfin ]
  | .lt, 0 => [ .lt, .ltfin ] | .lt, 1 => [ .gt, .ltfin ] | .lt, 2 => [ .lt, .gtfin ] | .lt, 3 => [ .lt, .ltfin ]
  | .gtfin, _ => ∅
  | .ltfin, _ => ∅

def NFA.autSignedCmp (cmp: RelationOrdering) : NFA (BitVec 2) signedCmpState where
  step s a := { s' | s' ∈ signedCmpStep s a }
  start := { s | s = signedCmpState.eq }
  accept := { s | s ∈ match cmp with | .lt => [NFA.signedCmpState.ltfin] | .le => [.ltfin, .eq] | .gt => [.gtfin] | .ge => [.gtfin, .eq] }

def NFA'.autSignedCmp (cmp: RelationOrdering) : NFA' 2 :=
  ⟨_, NFA.autSignedCmp cmp⟩

def RelationOrdering.srel (cmp : RelationOrdering) : BVRel :=
  match cmp with
  | .lt => fun _ bv1 bv2 => bv1.slt bv2
  | .le => fun _ bv1 bv2 => bv1.sle bv2
  | .gt => fun _ bv1 bv2 => bv2.slt bv1
  | .ge => fun _ bv1 bv2 => bv2.sle bv1

def NFA'.autSignedCmpSA (q : NFA.signedCmpState) : BVRel :=
  match q with
  | .eq => fun _ bv1 bv2 => bv1 = bv2
  | .lt => fun _ bv1 bv2 => bv1.ult bv2
  | .gt => fun _ bv1 bv2 => bv2.ult bv1
  | .ltfin => fun _ bv1 bv2 => bv1.slt bv2
  | .gtfin => fun _ bv1 bv2 => bv2.slt bv1

def unsigned_equiv cmp : (CNFA.autUnsignedCmp cmp).m.states ≃ (NFA'.autUnsignedCmp cmp).σ where
  toFun := fun ⟨s, hs⟩ =>
    match s with
    | 0 => .eq
    | 1 => .gt
    | _ => .lt
  invFun q :=
    match q with
    | .eq => ⟨0, by admit /- proof elided -/
    ⟩
    | .gt => ⟨1, by admit /- proof elided -/
    ⟩
    | .lt => ⟨2, by admit /- proof elided -/
    ⟩
  left_inv := by admit /- proof elided -/

def signed_equiv cmp : (CNFA.autSignedCmp cmp).m.states ≃ (NFA'.autSignedCmp cmp).σ where
  toFun := fun ⟨s, hs⟩ =>
    match s with
    | 0 => .eq
    | 1 => .gt
    | 2 => .lt
    | 3 => .gtfin
    | _ => .ltfin
  invFun q :=
    match q with
    | .eq => ⟨0, by admit /- proof elided -/
    ⟩
    | .gt => ⟨1, by admit /- proof elided -/
    ⟩
    | .lt => ⟨2, by admit /- proof elided -/
    ⟩
    | .gtfin => ⟨3, by admit /- proof elided -/
    ⟩
    | .ltfin => ⟨4, by admit /- proof elided -/
    ⟩
  left_inv := by admit /- proof elided -/

def RawCNFA.autMsbSet : RawCNFA (BitVec 1) :=
  let m := RawCNFA.empty
  let (si, m) := m.newState
  let (sf, m) := m.newState
  let m := m.addInitial si
  let m := m.addFinal sf
  let m := m.addTrans 1 si sf
  let m := m.addManyTrans [0, 1] si si
  m

@[inline]
def CNFA.autMsbSet : CNFA 1 :=
  ⟨RawCNFA.autMsbSet, RawCNFA.autMsbSet_wf⟩

inductive NFA.msbState : Type where
| i | f
deriving DecidableEq, Fintype

def NFA.msbStep (q : NFA.msbState) (a : BitVec 1) : List NFA.msbState :=
  match q, a with
  | .i, 0 => [.i]
  | .i, 1 => [.i, .f]
  | _, _ => []

def NFA.autMsbSet : NFA (BitVec 1) msbState where
  step s a := { s' | s' ∈ msbStep s a }
  start := {.i}
  accept := {.f}

def NFA'.autMsbSet : NFA' 1 := ⟨_, NFA.autMsbSet⟩

def NFA.msbLang : Language (BitVec 1) := { bvs  | bvs.getLast? = some 1 }

def NFA.msbSA (q : msbState) : Language (BitVec 1) :=
  match q with
  | .i => ⊤
  | .f => msbLang

def NFA.msbCorrect : NFA.autMsbSet.correct msbSA msbLang :=

def autMsb_equiv : CNFA.autMsbSet.m.states ≃ NFA'.autMsbSet.σ where
  toFun := fun ⟨s, hs⟩ =>
    match s with
    | 0 => .i
    | 1 => .f
    | _ => .i
  invFun q :=
    match q with
    | .i => ⟨0, by admit /- proof elided -/
    ⟩
    | .f => ⟨1, by admit /- proof elided -/
    ⟩
  left_inv := by admit /- proof elided -/

def WidthPredicate.final? (wp : WidthPredicate) (n : Nat) (s : State) : Bool :=
  decide (wp.sat s n)

def RawCNFA.autWidth (wp : WidthPredicate) (n : Nat) : RawCNFA (BitVec 0) :=
  let m := (n+2).iterate f empty
  let m := m.addInitial 0
  m.addTrans (BitVec.zero 0) (n + 1) (n + 1)
where
  f m :=
    let (s, m) := m.newState
    let m := if wp.final? n s then m.addFinal s else m
    if s > 0 then m.addTrans (BitVec.zero 0) (s-1) s else m

def CNFA.autWidth (wp : WidthPredicate) (n : Nat) : CNFA 0 :=
  ⟨RawCNFA.autWidth wp n, RawCNFA.autWidth_wf⟩

def NFA.autWidth (wp : WidthPredicate) (n : Nat) : NFA (BitVec 0) (Fin (n+2)) where
  start := { 0 }
  accept := { s | wp.final? n s }
  step s₁ _ := { s₂ | if s₁ = Fin.last (n+1) then s₁ = s₂ else s₂ = s₁ + 1 }

def NFA'.autWidth (wp : WidthPredicate) (n : Nat) : NFA' 0 := ⟨_, NFA.autWidth wp n⟩

@[simp]
def NFA'.autWidth_spec : (autWidth wp n).accepts = { bv | wp.sat bv.w n } :=

def autWidth_equiv : (CNFA.autWidth wp n).m.states ≃ (NFA'.autWidth wp n).σ where
  toFun := fun ⟨s, hs⟩ =>
    Fin.mk s (by admit /- proof elided -/
    )
  invFun q := ⟨q.val, by admit /- proof elided -/
  ⟩
  left_inv := by admit /- proof elided -/

end nfas_relations

def Relation.autOfRelation : Relation → CNFA 2
| .eq => CNFA.autEq
| .signed ord => CNFA.autSignedCmp ord
| .unsigned ord => CNFA.autUnsignedCmp ord

def Relation.absAutOfRelation (rel : Relation) : NFA' 2 :=
  match rel with
  | .eq => NFA'.autEq
  | .unsigned cmp => NFA'.autUnsignedCmp cmp
  | .signed cmp => NFA'.autSignedCmp cmp

def unopNfa (op : Unop) (m : CNFA n) : CNFA n :=
  match op with
  | .neg => m.neg

def unopAbsNfa (op : Unop) (M : NFA' n) : NFA' n :=
  match op with
  | .neg => M.neg

def binopNfa (op : Binop) (m1 m2 : CNFA n) : CNFA n :=
  match op with
  | .and => m1.inter m2
  | .or => m1.union m2
  | .impl => m1.neg.union m2
  | .equiv => (m1.neg.union m2).inter (m2.neg.union m1)

def binopAbsNfa (op : Binop) (M1 M2: NFA' n) : NFA' n :=
  match op with
  | .and => M1.inter M2
  | .or => M1.union M2
  | .impl => M1.neg.union M2
  | .equiv => (M1.neg.union M2).inter (M2.neg.union M1)

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 -/
    )

@[simp]
def liftOp_unchanged (k : Fin n) : liftOp n k.castSucc = k.castLE (by simp) :=

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

inductive TermBinop where
| and | or | xor | add | sub

def TermBinop.subst (op : TermBinop) (t₁ t₂ : Term) : Term :=
  match op with
  | .and => .and t₁ t₂
  | .or => .or t₁ t₂
  | .xor => .xor t₁ t₂
  | .add => .add t₁ t₂
  | .sub => .sub t₁ t₂

def TermBinop.openTerm (op : TermBinop) : Term := op.subst (.var 0) (.var 1)

@[simp]
def TermBinop.openTerm_arity (op : TermBinop) : op.openTerm.arity + 1 = 3 :=

def TermBinop.termGadget (t : TermBinop) : CNFA 3 :=
  match t with
  | .and => FSM.ofTerm (.and (.var 0) (.var 1)) |> CNFA.ofFSM
  | .or => FSM.ofTerm (.or (.var 0) (.var 1)) |> CNFA.ofFSM
  | .xor => FSM.ofTerm (.xor (.var 0) (.var 1)) |> CNFA.ofFSM
  | .add => FSM.ofTerm (.add (.var 0) (.var 1)) |> CNFA.ofFSM
  | .sub => FSM.ofTerm (.sub (.var 0) (.var 1)) |> CNFA.ofFSM

def autOfTermBinop (op : TermBinop) (m₁ : CNFA (n + 1)) (m₂ : CNFA (m + 1)) : CNFA ((n ⊔ m) + 1 ) :=
  let mop : CNFA 3 := op.termGadget
  let f₁ := liftMaxSuccSucc1 n m
  let m1' := m₁.lift f₁
  let f₂ := liftMaxSuccSucc2 n m
  let m2' := m₂.lift f₂
  let mop := mop.lift $ liftLast3 (max (FinEnum.card (Fin n)) (FinEnum.card (Fin m)))
  let m := CNFA.inter m1' m2' |> CNFA.inter mop
  let mfinal := m.proj (liftOp _)
  mfinal.minimize

def swapLastTwoBlock (x : Fin (n + 3)) : Fin (n + 3) :=
  if x = Fin.last (n+2) then n
  else if x = n+1 then Fin.last (n + 2)
  else if x = n then n + 1
  else x

inductive TermUnop where
| neg | not | shiftL (k : Nat)

def TermUnop.openTerm (op : TermUnop) : Term :=
  match op with
  | .neg => .neg (.var 0)
  | .not => .not (.var 0)
  | .shiftL k => .shiftL (.var 0) k

def TermUnop.openTerm_arity (op : TermUnop) : op.openTerm.arity = 1 :=

@[simp]
def TermUnop.openTerm_arity' (op : TermUnop) : op.openTerm.arity + 1 = 2 :=

def TermUnop.subst (op : TermUnop) (t : Term) : Term :=
  match op with
  | .neg => .neg t
  | .not => .not t
  | .shiftL k => .shiftL t k

def TermUnop.termGadget (t : TermUnop) : CNFA 2 :=
  match t with
  | .neg => FSM.ofTerm (.neg (.var 0)) |> CNFA.ofFSM
  | .not => FSM.ofTerm (.not (.var 0)) |> CNFA.ofFSM
  | .shiftL k => FSM.ofTerm (.shiftL (.var 0) k) |> CNFA.ofFSM

def autOfTermUnop (op : TermUnop) (m : CNFA (n + 1)) : CNFA (n + 1) :=
  let mop : CNFA 2 := op.termGadget
  let mop : CNFA (n + 2) := mop.lift (λ i ↦ i.natAdd n)
  let m : CNFA (n + 2) := m.lift (λ i ↦ i.castLE (by admit /- proof elided -/
  ))
  let m := CNFA.inter m mop
  let mfinal := m.proj (liftUnop n)
  mfinal.minimize

def nfaOfTerm (t : Term) : CNFA (t.arity + 1) :=
  match t with
  | .var n => FSM.ofTerm (.var n) |> CNFA.ofFSM
  | .zero => FSM.ofTerm .zero |> CNFA.ofFSM
  | .negOne => FSM.ofTerm .negOne |> CNFA.ofFSM
  | .one => FSM.ofTerm .one |> CNFA.ofFSM
  | .ofNat n => FSM.ofTerm (.ofNat n) |> CNFA.ofFSM
  | .and t₁ t₂ => autOfTermBinop .and (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .or t₁ t₂ => autOfTermBinop .or (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .xor t₁ t₂ => autOfTermBinop .xor (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .add t₁ t₂ => autOfTermBinop .add (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .sub t₁ t₂ => autOfTermBinop .sub (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .neg t => autOfTermUnop .neg (nfaOfTerm t)
  | .not t => autOfTermUnop .not (nfaOfTerm t)
  | .shiftL t k => autOfTermUnop (.shiftL k) (nfaOfTerm t)

def swapLastTwo (x : Fin (n + 2)) : Fin (n + 2) :=
  if x = Fin.last (n + 1) then n else if x = n then Fin.last (n + 1) else x

def nfaOfFormula (φ : Formula) : CNFA φ.arity :=
  match φ with
  | .width wp n => CNFA.autWidth wp n
  | .atom rel t1 t2 =>
    let m1 := nfaOfTerm t1
    let m2 := nfaOfTerm t2
    let f1 := liftMaxSucc1 (FinEnum.card $ Fin t1.arity) (FinEnum.card $ Fin t2.arity)
    let m1' := m1.lift f1
    let f2 := liftMaxSucc2 (FinEnum.card $ Fin t1.arity) (FinEnum.card $ Fin t2.arity)
    let m2' := m2.lift f2
    let meq := rel.autOfRelation.lift $ liftLast2 (max (FinEnum.card (Fin t1.arity)) (FinEnum.card (Fin t2.arity)))
    let m := CNFA.inter m1' m2' |> CNFA.inter meq
    let mfinal := m.proj (liftExcept2 _)
    mfinal
  | .msbSet t =>
    let m := (termEvalEqFSM t).toFSM |> CNFA.ofFSM
    let mMsb := CNFA.autMsbSet.lift $ fun _ => Fin.last t.arity
    let res := m.inter mMsb
    res.proj $ fun n => n.castLE (by admit /- proof elided -/
    )
  | .unop op φ => unopNfa op (nfaOfFormula φ)
  | .binop op φ1 φ2 =>
    let m1 := (nfaOfFormula φ1).lift $ liftMax1 φ1.arity φ2.arity
    let m2 := (nfaOfFormula φ2).lift $ liftMax2 φ1.arity φ2.arity
    binopNfa op m1 m2
</local_ctx>

<target_theorem>
theorem nfaOfFormula_bv_language φ :
    (nfaOfFormula φ).bv_recognizes φ.language :=
</target_theorem>

