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
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
List.Vector in Mathlib.Data.Vector.Defs
Set in Mathlib.Data.Set.Defs
NFA.stepSet in Mathlib.Computability.NFA
Subsingleton in Init.Core
reduceDIte in Lean.Meta.Tactic.Simp.BuiltinSimprocs.Core
BitVec.ofNat in Init.Prelude
BitVec.zero in Init.Data.BitVec.Basic
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
Eq in Init.Prelude
Fin.natAdd in Init.Data.Fin.Basic
List.Vector.nil in Mathlib.Data.Vector.Defs
NeZero in Init.Data.NeZero
Vector.ofFn in Init.Data.Vector.Basic
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

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

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

structure BitVecs (n : Nat) where
  w : Nat
  bvs : List.Vector (BitVec w) 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 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 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

@[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

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 BitVec.transport (f : Fin n2 → Fin n1) (bv : BitVec n1) : BitVec n2 :=
  BitVec.ofFn fun i => bv.getLsbD (f i)

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 BitVecs.transport (f : Fin n → Fin m) (bvs : BitVecs m) : BitVecs n :=
  { w := bvs.w, bvs := bvs.bvs.transport f }

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⟩

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

def udiv400_after := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(400 : i32) : i32
  %1 = llvm.udiv %arg5, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

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

def xor_or_xor_common_op_commute5_after := [llvm|
{
^0(%arg68 : i32, %arg69 : i32, %arg70 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg68, %0 : i32
  %2 = llvm.and %arg69, %1 : i32
  %3 = llvm.xor %2, %arg70 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def test0_before := [llvm|
{
^0(%arg210 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.xor %arg210, %0 : i1
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def opRet : Op 0 := [mlir_op| llvm.return %4 : i32]

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 or_and_not_not_commute2_after := [llvm|
{
^0(%arg419 : i32, %arg420 : i32, %arg421 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg421, %arg420 : i32
  %2 = llvm.or %1, %arg419 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def sext_ule_sext_before := [llvm|
{
^0(%arg119 : i1, %arg120 : i8):
  %0 = llvm.mul %arg120, %arg120 : i8
  %1 = llvm.sext %arg119 : i1 to i16
  %2 = llvm.sext %0 : i8 to i16
  %3 = llvm.icmp "ule" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def sext_xor_sub_2_before := [llvm|
{
^0(%arg24 : i64, %arg25 : i1):
  %0 = llvm.sext %arg25 : i1 to i64
  %1 = llvm.xor %arg24, %0 : i64
  %2 = llvm.sub %0, %1 : i64
  "llvm.return"(%2) : (i64) -> ()
}
]

def NFA.autWidth_correct : (autWidth wp n).correct (autWidthSA n) (autWidthLang wp n) :=

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

@[simp_denote]
def icmp {Γ : Ctxt _} (w : ℕ) (pred : LLVM.IntPred) (l r : Nat)
    (lp : (Γ[l]? = some (InstCombine.MTy.bitvec (ConcreteOrMVar.concrete w)))
      := by admit /- proof elided -/
      )
    (rp : (Γ[r]? = some (InstCombine.MTy.bitvec (ConcreteOrMVar.concrete w)))
      := by admit /- proof elided -/
      ) :
    Expr InstCombine.LLVM Γ .pure (LLVM.Ty.bitvec 1) :=
  Expr.mk
    (op := InstCombine.MOp.icmp pred w)
    (eff_le := by admit /- proof elided -/
    )
    (ty_eq := rfl)
    (args := .cons ⟨l, lp⟩ <| .cons ⟨r, rp⟩ .nil)
    (regArgs := .nil)

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

instance (p : Predicate) :
    Decidable (∀ (n : ℕ) (x : Fin p.arity → BitStream) , p.evalFin x n = false) :=
  decidable_of_iff
    (decideIfZeros (predicateEvalEqFSM p).toFSM) $ by
  rw [decideIfZeros_correct]
  simp only [FSM.eval_simplify]
  rw [← (predicateEvalEqFSM p).good]

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

def t1_after := [llvm|
{
^0(%arg46 : i64, %arg47 : i32):
  %0 = llvm.mlir.constant(4294901760) : i64
  %1 = llvm.mlir.constant(0) : i64
  %2 = llvm.and %arg46, %0 : i64
  %3 = llvm.icmp "ne" %2, %1 : i64
  "llvm.return"(%3) : (i1) -> ()
}
]

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 main4c_after := [llvm|
{
^0(%arg124 : i32):
  %0 = llvm.mlir.constant(55 : i32) : i32
  %1 = llvm.and %arg124, %0 : i32
  %2 = llvm.icmp "eq" %1, %0 : i32
  %3 = llvm.zext %2 : i1 to i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def CNFA.union_language (m₁ m₂ : CNFA n) :
    m₁.recognizes L₁ →
    m₂.recognizes L₂ →
    (m₁.union m₂).recognizes (L₁ ∪ L₂) :=

def test3_after := [llvm|
{
^0(%arg195 : i64):
  %0 = llvm.mlir.constant(255) : i64
  %1 = llvm.and %arg195, %0 : i64
  "llvm.return"(%1) : (i64) -> ()
}
]

def icmp_eq_mul_nuw_nonequal_before := [llvm|
{
^0(%arg32 : i8, %arg33 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.add %arg32, %0 : i8
  %2 = llvm.mul %arg32, %arg33 overflow<nuw> : i8
  %3 = llvm.mul %1, %arg33 overflow<nuw> : i8
  %4 = llvm.icmp "eq" %2, %3 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def lshr_lshr_pow2_const_negative_nopow2_2_before := [llvm|
{
^0(%arg62 : i16):
  %0 = llvm.mlir.constant(8192 : i16) : i16
  %1 = llvm.mlir.constant(6 : i16) : i16
  %2 = llvm.mlir.constant(3 : i16) : i16
  %3 = llvm.lshr %0, %arg62 : i16
  %4 = llvm.lshr %3, %1 : i16
  %5 = llvm.and %4, %2 : i16
  "llvm.return"(%5) : (i16) -> ()
}
]

def not_cmp_fold_uge : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.icmp.uge %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.ult %x, %y : i64
      llvm.return %0 : i1
  }]

def test12_after := [llvm|
{
^0(%arg76 : i32, %arg77 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.zext %arg76 : i32 to i64
  %2 = llvm.and %arg77, %0 : i32
  %3 = llvm.zext nneg %2 : i32 to i64
  %4 = llvm.lshr %1, %3 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def sel_false_val_is_a_masked_lshr_of_true_val1_before := [llvm|
{
^0(%arg6 : i32, %arg7 : i64):
  %0 = llvm.mlir.constant(60 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.and %arg6, %0 : i32
  %4 = llvm.lshr %3, %1 : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.icmp "eq" %3, %2 : i32
  %7 = llvm.ashr %arg7, %5 : i64
  %8 = "llvm.select"(%6, %arg7, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

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

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

def t9_after := [llvm|
{
^0(%arg176 : i8, %arg177 : i8):
  %0 = llvm.sub %arg176, %arg177 : i8
  "llvm.return"(%0) : (i8) -> ()
}
]

def mul_add_to_mul_3_before := [llvm|
{
^0(%arg30 : i16):
  %0 = llvm.mlir.constant(2 : i16) : i16
  %1 = llvm.mlir.constant(3 : i16) : i16
  %2 = llvm.mul %arg30, %0 : i16
  %3 = llvm.mul %arg30, %1 : i16
  %4 = llvm.add %2, %3 overflow<nsw> : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

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

def mkExpr (Γ : Ctxt _) (opStx : MLIR.AST.Op 0) :
    MLIR.AST.ReaderM Comb (Σ eff ty, Expr Comb Γ eff ty) := do
  let args ← opStx.parseArgs Γ
  
  let unW := do
    let args ← args.assumeArity 1
    return getVarWidth args[0]
  
  let binW : AST.ReaderM (Comb) (Nat) := do
    let args ← args.assumeArity 2
    return getVarWidth args[0]
  
  let terW : AST.ReaderM (Comb) (Nat) := do
    let args ← args.assumeArity 3
    return getVarWidth args[0]
  
  if h : args.toList.length = 0 then
    throw <| .generic s!" empty list of argument provided for the variadic op {repr opStx.args}"
  else
    
    let nnW : AST.ReaderM (Comb) (Nat) := do
      let args ← args.assumeArity args.toList.length
      return getVarWidth args[0]
    let mkExprOf := opStx.mkExprOf (args? := args) Γ
    match (opStx.name).splitOn "_" with
    
    | ["Comb.parity"] => mkExprOf <| .parity (← unW)
    | ["Comb.extract", ns] =>
      match ns.toNat? with
      | some n =>  mkExprOf <| .extract (← unW) n
      | _ => throw <| .generic s!" an integer attribute should be provided for {repr opStx.args}"
    | ["Comb.replicate", ns] =>
      match ns.toNat? with
      | some n =>  mkExprOf <| .replicate (← unW) n
      | _ => throw <| .generic s!" an integer attribute should be provided for {repr opStx.args}"
    
    | ["Comb.divs"] => mkExprOf <| .divs (← binW)
    | ["Comb.divu"] => mkExprOf <| .divu (← binW)
    | ["Comb.icmp", ps] =>
      match (ofString? ps) with
      
      | some p => mkExprOf <| .icmp ps (← binW)
      | _ => throw <| .generic s!" invalid attribute provided for {repr opStx.args}"
    | ["Comb.mods"] => mkExprOf <| .mods (← binW)
    | ["Comb.modu"] => mkExprOf <| .modu (← binW)
    | ["Comb.shl"] => mkExprOf <| .shl (← binW)
    | ["Comb.shrs"] => mkExprOf <| .shrs (← binW)
    | ["Comb.shru"] => mkExprOf <| .shru (← binW)
    | ["Comb.sub "] => mkExprOf <| .sub (← binW)
    
    | ["Comb.mux"] => mkExprOf <| .mux (← terW)
    
    | ["Comb.add"] => mkExprOf <| .add (← nnW) args.toList.length
    | ["Comb.and"] => mkExprOf <| .and (← nnW) args.toList.length
    | ["Comb.mul"] => mkExprOf <| .mul (← nnW) args.toList.length
    | ["Comb.or"] => mkExprOf <| .or (← nnW) args.toList.length
    | ["Comb.xor"] => mkExprOf <| .xor (← nnW) args.toList.length
    
    | ["Comb.shlPar", n] =>
      match n.toNat? with
      | some n' => mkExprOf <| .shlPar n' (← unW)
      | _  => throw <| .generic s!"type mismatch"
    | _ => throw <| .unsupportedOp s!"{repr opStx}"

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

def band_lor_left1_after := [llvm|
{
^0(%arg82 : i1, %arg83 : i1):
  "llvm.return"(%arg82) : (i1) -> ()
}
]

List.find? in Init.Data.List.Basic

def Lets.substitute (σ : Substitution) : Lets Op T → Lets Op T
  | ⟨ls⟩    => ⟨go ls⟩
  where go : List (Expr Op T) → List (Expr Op T)
    | [] => []
    | l::ls => l.substitute σ :: go ls

def is_ready {l : List Nat} (v : HVector (fun i => Option (BitVec i)) l) :
    Option (HVector (fun i => BitVec i) l) :=
  match v with
        | .nil => some .nil
        | .cons (some x) xs =>
            match is_ready xs with
            | some xs' => some (.cons x xs')
            | none => none
        | .cons none _ => none

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

def test38_after := [llvm|
{
^0(%arg238 : i32):
  %0 = llvm.mlir.constant(240 : i32) : i32
  %1 = llvm.and %arg238, %0 : i32
  %2 = llvm.zext nneg %1 : i32 to i64
  "llvm.return"(%2) : (i64) -> ()
}
]

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

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

def testi16i8_after := [llvm|
{
^0(%arg9 : i16):
  %0 = llvm.mlir.constant(-1 : i16) : i16
  %1 = llvm.mlir.constant(27 : i8) : i8
  %2 = llvm.mlir.constant(-28 : i8) : i8
  %3 = llvm.icmp "sgt" %arg9, %0 : i16
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def no_shift_xor_multiuse_cmp_or_after := [llvm|
{
^0(%arg48 : i32, %arg49 : i32, %arg50 : i32, %arg51 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg48, %0 : i32
  %3 = llvm.icmp "eq" %2, %1 : i32
  %4 = llvm.or %arg49, %0 : i32
  %5 = "llvm.select"(%3, %4, %arg49) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = "llvm.select"(%3, %arg51, %arg50) <{"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 n10_lshr_ashr_after := [llvm|
{
^0(%arg0 : i32, %arg1 : i16):
  %0 = llvm.mlir.constant(32 : i16) : i16
  %1 = llvm.mlir.constant(-1 : i16) : i16
  %2 = llvm.sub %0, %arg1 : i16
  %3 = llvm.zext nneg %2 : i16 to i32
  %4 = llvm.lshr %arg0, %3 : i32
  %5 = llvm.trunc %4 : i32 to i16
  %6 = llvm.add %arg1, %1 : i16
  %7 = llvm.ashr %5, %6 : i16
  "llvm.return"(%7) : (i16) -> ()
}
]

def sext_sub_after := [llvm|
{
^0(%arg20 : i8, %arg21 : i1):
  %0 = llvm.zext %arg21 : i1 to i8
  %1 = llvm.add %arg20, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

instance : HydrableGetGenPredSize FpPredicate where
  getGenPredSize e := e.size

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

instance : AndOp (Circuit α) := ⟨Circuit.simplifyAnd⟩

def GeneralizerStateM.liftTermElabM
  {parsedExpr : Type}  {genPred : Type}
  [HydrableInstances genPred]
  (m : TermElabM α) : GeneralizerStateM parsedExpr genPred α := do
  let v ← m
  return v

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

def t2_ult_sgt_128_before := [llvm|
{
^0(%arg72 : i32, %arg73 : i32, %arg74 : i32):
  %0 = llvm.mlir.constant(127 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mlir.constant(144 : i32) : i32
  %3 = llvm.icmp "sgt" %arg72, %0 : i32
  %4 = "llvm.select"(%3, %arg74, %arg73) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %5 = llvm.add %arg72, %1 : i32
  %6 = llvm.icmp "ult" %5, %2 : i32
  %7 = "llvm.select"(%6, %arg72, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def xor_notand_to_or_not4_before := [llvm|
{
^0(%arg9 : i3, %arg10 : i3, %arg11 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg10, %arg11 : i3
  %2 = llvm.and %arg11, %arg9 : i3
  %3 = llvm.xor %2, %0 : i3
  %4 = llvm.xor %3, %1 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

def n12_wrong_bias_after := [llvm|
{
^0(%arg9 : i8):
  %0 = llvm.mlir.constant(15 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.mlir.constant(-16 : i8) : i8
  %3 = llvm.mlir.constant(32 : i8) : i8
  %4 = llvm.and %arg9, %0 : i8
  %5 = llvm.icmp "eq" %4, %1 : i8
  %6 = llvm.and %arg9, %2 : i8
  %7 = llvm.add %6, %3 : i8
  %8 = "llvm.select"(%5, %arg9, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%8) : (i8) -> ()
}
]

def llvm_const_lower_riscv_li47 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM47, rhs:= liRiscv47,
   correct := by admit /- proof elided -/

def t4_ugt_slt_128_before := [llvm|
{
^0(%arg66 : i32, %arg67 : i32, %arg68 : i32):
  %0 = llvm.mlir.constant(128 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mlir.constant(143 : i32) : i32
  %3 = llvm.icmp "slt" %arg66, %0 : i32
  %4 = "llvm.select"(%3, %arg67, %arg68) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %5 = llvm.add %arg66, %1 : i32
  %6 = llvm.icmp "ugt" %5, %2 : i32
  %7 = "llvm.select"(%6, %4, %arg66) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

def a_true_implies_b_false2_after := [llvm|
{
^0(%arg21 : i8, %arg22 : i1, %arg23 : i1):
  %0 = llvm.mlir.constant(20 : i8) : i8
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "ugt" %arg21, %0 : i8
  %3 = "llvm.select"(%2, %arg23, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def positive_samevar_lshrexact_after := [llvm|
{
^0(%arg42 : i8, %arg43 : i8):
  "llvm.return"(%arg42) : (i8) -> ()
}
]

def and_zext_before := [llvm|
{
^0(%arg40 : i32, %arg41 : i1):
  %0 = llvm.zext %arg41 : i1 to i32
  %1 = llvm.and %arg40, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def add_negative_high_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := add_negative_high_bound_reject_llvm
  rhs := add_negative_high_bound_reject_riscv

def trunc_after := [llvm|
{
^0(%arg15 : i32, %arg16 : i32, %arg17 : i32):
  %0 = llvm.mlir.constant(42 : i16) : i16
  %1 = llvm.icmp "ult" %arg15, %arg16 : i32
  %2 = llvm.trunc %arg17 : i32 to i16
  %3 = "llvm.select"(%1, %0, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
  "llvm.return"(%3) : (i16) -> ()
}
]

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

StateT.lift in Init.Control.State

inductive Op : Type
  | add : Op
  | const : (val : ℤ) → Op
  deriving DecidableEq, Lean.ToExpr

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

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

def fsmZext (nFsm wnewfsm : FSM (StateSpace wcard tcard bcard ncard icard pcard))
    : FSM (StateSpace wcard tcard bcard ncard icard pcard) :=
  (nFsm) &&& (wnewfsm)

def commutativity_constant_6_vary_invmask_after := [llvm|
{
^0(%arg16 : i4, %arg17 : i4):
  %0 = llvm.mlir.constant(6 : i4) : i4
  %1 = llvm.xor %arg16, %0 : i4
  %2 = llvm.and %1, %arg17 : i4
  %3 = llvm.xor %2, %0 : i4
  "llvm.return"(%3) : (i4) -> ()
}
]

def test15_after := [llvm|
{
^0(%arg24 : i1):
  %0 = llvm.mlir.constant(12 : i45) : i45
  %1 = llvm.mlir.constant(4 : i45) : i45
  %2 = "llvm.select"(%arg24, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i45, i45) -> i45
  "llvm.return"(%2) : (i45) -> ()
}
]

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

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

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 AndZextZext : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where
  lhs := [LV| {
    ^entry (%x: i32, %y: i32):
      %0 = llvm.zext %x : i32 to i64
      %1 = llvm.zext %y : i32 to i64
      %2 = llvm.and %0, %1 : i64
      llvm.return %2 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i32, %y: i32):
      %0 = llvm.and %x, %y : i32
      %1 = llvm.zext %0 : i32 to i64
      llvm.return %1 : i64
  }]

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

def uge_or_max_logical_after := [llvm|
{
^0(%arg172 : i8, %arg173 : i8):
  %0 = llvm.icmp "uge" %arg172, %arg173 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def test44_before := [llvm|
{
^0(%arg203 : i32, %arg204 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg204, %0 : i32
  %2 = llvm.or %1, %arg203 : i32
  %3 = llvm.and %2, %arg204 : i32
  "llvm.return"(%3) : (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) -> ()
}
]

Lean.Parser.mkAtomicInfo in Lean.Parser.Basic

@[inline]
def CNFA.autMsbSet : CNFA 1 :=
  ⟨RawCNFA.autMsbSet, RawCNFA.autMsbSet_wf⟩

def or_not_and_commute2_after := [llvm|
{
^0(%arg531 : i32, %arg532 : i32, %arg533 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg532 : i32
  %3 = llvm.xor %arg533, %2 : i32
  %4 = llvm.xor %arg531, %1 : i32
  %5 = llvm.and %3, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def getBoolValue? (e : Expr) : Option Bool :=
  match_expr e with
  | Bool.true => some true
  | Bool.false => some false
  | _ => none

def irc_constants_APlusC1MinusC2_neg2_2 : 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.add %a, %c1 : i64
      %1 = llvm.sub %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 %c1, %c2 : i64
      %1 = llvm.add %a, %0 : i64
      llvm.return %1 : i64
  }]

instance {cmp} : Fintype (NFA'.autSignedCmp cmp).σ :=

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 shl1_nsw_not_exact_after := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.shl %0, %arg11 overflow<nsw,nuw> : i8
  %2 = llvm.sdiv %arg10, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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 test4_after := [llvm|
{
^0(%arg10 : i37):
  %0 = llvm.mlir.constant(2147483647 : i37) : i37
  %1 = llvm.icmp "ugt" %arg10, %0 : i37
  "llvm.return"(%1) : (i1) -> ()
}
]

def lshr_or_and_before := [llvm|
{
^0(%arg152 : i8, %arg153 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.mlir.constant(-58 : i8) : i8
  %2 = llvm.lshr %arg152, %0 : i8
  %3 = llvm.lshr %arg153, %0 : i8
  %4 = llvm.or %2, %1 : i8
  %5 = llvm.and %4, %3 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def val1 : DCOp.ValueStream (BitVec 8) := ofList [some 1, none, some 2, some 3, none]

def alive_AddSub_1309_src :=
[sllvm| {
^bb0(%a : i64, %b : i64):
  %v1 = llvm.and %a, %b : i64
  %v2 = llvm.or %a, %b : i64
  %v3 = llvm.add %v1, %v2 : i64
  llvm.return %v3 : i64
}]

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

def ugt_rem_nz_before := [llvm|
{
^0(%arg165 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.mlir.constant(21 : i8) : i8
  %2 = llvm.mul %arg165, %0 overflow<nuw> : i8
  %3 = llvm.icmp "ugt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def test7_before := [llvm|
{
^0(%arg81 : i64):
  %0 = llvm.mlir.constant(32 : i128) : i128
  %1 = llvm.zext %arg81 : i64 to i128
  %2 = llvm.lshr %1, %0 : i128
  %3 = llvm.trunc %2 : i128 to i92
  "llvm.return"(%3) : (i92) -> ()
}
]

def absdiff2_before := [llvm|
{
^0(%arg0 : i64, %arg1 : i64):
  %0 = llvm.icmp "ugt" %arg0, %arg1 : i64
  %1 = llvm.sext %0 : i1 to i64
  %2 = llvm.sub %arg1, %arg0 : i64
  %3 = llvm.xor %2, %1 : i64
  %4 = llvm.sub %3, %1 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def test4_after := [llvm|
{
^0(%arg22 : i108, %arg23 : i108):
  %0 = llvm.add %arg23, %arg22 : i108
  "llvm.return"(%0) : (i108) -> ()
}
]

def icmp_sgt_riscv_eq_icmp_slt_llvm_64 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] :=
  {lhs:= icmp_sgt_llvm_64, rhs:= icmp_sgt_riscv_64}

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

def urem_i32_c_before := [llvm|
{
^0(%arg10 : i8):
  %0 = llvm.mlir.constant(10 : i32) : i32
  %1 = llvm.zext %arg10 : i8 to i32
  %2 = llvm.urem %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def icmpPredicates := [ LLVM.IntPredicate.eq, LLVM.IntPredicate.ne, LLVM.IntPredicate.ugt,
  LLVM.IntPredicate.uge, LLVM.IntPredicate.ult, LLVM.IntPredicate.ule, LLVM.IntPredicate.sgt,
  LLVM.IntPredicate.sge, LLVM.IntPredicate.slt, LLVM.IntPredicate.sle]

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

def a_false_implies_b_true2_comm_before := [llvm|
{
^0(%arg9 : i8, %arg10 : i1, %arg11 : i1):
  %0 = llvm.mlir.constant(10 : i8) : i8
  %1 = llvm.mlir.constant(20 : i8) : i8
  %2 = llvm.icmp "ugt" %arg9, %0 : i8
  %3 = llvm.icmp "ult" %arg9, %1 : i8
  %4 = "llvm.select"(%3, %arg10, %arg11) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = llvm.or %4, %2 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def toString : GenBVPred → String
  | bin lhs op rhs => s!"({lhs.toString} {op.toString} {rhs.toString})"
  | getLsbD expr idx => s!"{expr.toString}[{idx}]"

def or_xor_tree_1100_after := [llvm|
{
^0(%arg9 : i32, %arg10 : i32, %arg11 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mul %arg9, %0 : i32
  %2 = llvm.mul %arg10, %0 : i32
  %3 = llvm.mul %arg11, %0 : i32
  %4 = llvm.xor %1, %2 : i32
  %5 = llvm.or %4, %3 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

RV64.sra in RISCV.Instructions

@[simp_denote]
def icmp_ule_llvm_32 : Com LLVMPlusRiscV ⟨[.llvm (.bitvec 32), .llvm (.bitvec 32)]⟩
  .pure (.llvm (.bitvec 1)) := [LV| {
  ^entry (%lhs: i32, %rhs: i32):
    %1 = llvm.icmp.ule %lhs, %rhs : i32
    llvm.return %1 : i1
  }]

Lean.Parser.mkAntiquot in Lean.Parser.Basic

def eq_21_comm_eq2_before := [llvm|
{
^0(%arg118 : i32, %arg119 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.lshr %arg118, %0 : i32
  %3 = llvm.trunc %2 : i32 to i8
  %4 = llvm.lshr %arg118, %1 : i32
  %5 = llvm.trunc %4 : i32 to i8
  %6 = llvm.lshr %arg119, %0 : i32
  %7 = llvm.trunc %6 : i32 to i8
  %8 = llvm.lshr %arg119, %1 : i32
  %9 = llvm.trunc %8 : i32 to i8
  %10 = llvm.icmp "eq" %7, %3 : i8
  %11 = llvm.icmp "eq" %5, %9 : i8
  %12 = llvm.and %11, %10 : i1
  "llvm.return"(%12) : (i1) -> ()
}
]

def uaddo_commute8_after := [llvm|
{
^0(%arg10 : i32, %arg11 : i32, %arg12 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg11, %0 : i32
  %2 = llvm.add %arg11, %arg10 : i32
  %3 = llvm.icmp "ugt" %arg10, %1 : i32
  %4 = "llvm.select"(%3, %2, %arg12) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def main4e_like_logical_before := [llvm|
{
^0(%arg125 : i32, %arg126 : i32, %arg127 : i32):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.and %arg125, %arg126 : i32
  %4 = llvm.icmp "eq" %3, %arg126 : i32
  %5 = llvm.and %arg125, %arg127 : i32
  %6 = llvm.icmp "eq" %5, %arg127 : 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 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 bitwise_or_bitwise_or_icmps_comm1_before := [llvm|
{
^0(%arg193 : i8, %arg194 : i8, %arg195 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.icmp "eq" %arg194, %0 : i8
  %4 = llvm.and %arg193, %1 : i8
  %5 = llvm.shl %1, %arg195 : i8
  %6 = llvm.and %arg193, %5 : i8
  %7 = llvm.icmp "eq" %4, %2 : i8
  %8 = llvm.icmp "eq" %6, %2 : i8
  %9 = llvm.or %3, %7 : i1
  %10 = llvm.or %8, %9 : i1
  "llvm.return"(%10) : (i1) -> ()
}
]

def test25_before := [llvm|
{
^0(%arg271 : i32):
  %0 = llvm.mlir.constant(50 : i32) : i32
  %1 = llvm.mlir.constant(100 : i32) : i32
  %2 = llvm.icmp "sge" %arg271, %0 : i32
  %3 = llvm.icmp "slt" %arg271, %1 : i32
  %4 = llvm.and %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def narrow_zext_add_after := [llvm|
{
^0(%arg42 : i16, %arg43 : i32):
  %0 = llvm.trunc %arg43 : i32 to i16
  %1 = llvm.add %arg42, %0 : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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 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 test_and_ne_a_b_after := [llvm|
{
^0(%arg33 : i1, %arg34 : i8, %arg35 : i8):
  %0 = "llvm.select"(%arg33, %arg34, %arg35) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%0) : (i8) -> ()
}
]

def bool_eq0_after := [llvm|
{
^0(%arg33 : i64):
  %0 = llvm.mlir.constant(1) : i64
  %1 = llvm.icmp "sgt" %arg33, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

def n2_before := [llvm|
{
^0(%arg39 : i32, %arg40 : i32, %arg41 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "eq" %arg39, %arg40 : i32
  %3 = "llvm.select"(%arg41, %2, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = llvm.xor %3, %1 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def not_or_or_and_not_and_and_commute1_and_after := [llvm|
{
^0(%arg205 : i32, %arg206 : i32, %arg207 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg205, %0 : i32
  %2 = llvm.xor %arg207, %arg206 : i32
  %3 = llvm.or %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

RV64.remu in RISCV.Instructions

def dropUntil : Ctxt Ty :=
  ⟨Γ.toList.drop (v.val + 1)⟩

instance : Functor Ctxt where
  map := map

abbrev Expr.IsDenotationForPureE (e : Expr d Γ eff tys) (Γv : Valuation Γ)
    (x : HVector toType tys) : Prop :=
  ∀ (ePure : Expr d Γ .pure tys), e.toPure? = some ePure → ePure.denoteOp Γv = x

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

def pr51551_neg1_before := [llvm|
{
^0(%arg4 : i32, %arg5 : i32):
  %0 = llvm.mlir.constant(-3 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.mlir.constant(7 : i32) : i32
  %3 = llvm.mlir.constant(0 : i32) : i32
  %4 = llvm.and %arg5, %0 : i32
  %5 = llvm.or %4, %1 : i32
  %6 = llvm.mul %5, %arg4 overflow<nsw> : i32
  %7 = llvm.and %6, %2 : i32
  %8 = llvm.icmp "eq" %7, %3 : i32
  "llvm.return"(%8) : (i1) -> ()
}
]

def test23_before := [llvm|
{
^0(%arg185 : i32, %arg186 : i32):
  %0 = llvm.xor %arg186, %arg185 : i32
  %1 = llvm.icmp "eq" %0, %arg185 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

def test_lshr__exact_is_unsafe_before := [llvm|
{
^0(%arg56 : i32, %arg57 : i64):
  %0 = llvm.mlir.constant(63 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.and %arg56, %0 : i32
  %4 = llvm.lshr %3, %1 : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.icmp "eq" %3, %2 : i32
  %7 = llvm.ashr %arg57, %5 : i64
  %8 = "llvm.select"(%6, %arg57, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

def sle_swap_and_min_commute_before := [llvm|
{
^0(%arg210 : i8, %arg211 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.icmp "sge" %arg211, %arg210 : i8
  %2 = llvm.icmp "eq" %arg210, %0 : i8
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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 dec_mask_neg_i32_after := [llvm|
{
^0(%arg7 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.add %arg7, %0 : i32
  %2 = llvm.xor %arg7, %0 : i32
  %3 = llvm.and %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def or_and_not_not_commute7_after := [llvm|
{
^0(%arg404 : i32, %arg405 : i32, %arg406 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg406, %arg405 : i32
  %2 = llvm.or %1, %arg404 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def testtrunclowhigh_after := [llvm|
{
^0(%arg40 : i32, %arg41 : i16, %arg42 : i16):
  %0 = llvm.mlir.constant(128 : i32) : i32
  %1 = llvm.mlir.constant(256 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.add %arg40, %0 : i32
  %4 = llvm.icmp "ult" %3, %1 : i32
  %5 = llvm.trunc %arg40 : i32 to i16
  %6 = llvm.icmp "slt" %arg40, %2 : i32
  %7 = "llvm.select"(%6, %arg41, %arg42) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
  %8 = "llvm.select"(%4, %5, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
  "llvm.return"(%8) : (i16) -> ()
}
]

def t1_after := [llvm|
{
^0(%arg17 : i16):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.mlir.constant(-1 : i16) : i16
  %2 = llvm.sub %0, %arg17 : i16
  %3 = llvm.lshr %1, %2 : i16
  "llvm.return"(%3) : (i16) -> ()
}
]

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

@[simp_denote]
def xori_llvm := [LV| {
    ^entry (%a: i16):
    %0 = llvm.mlir.constant (4) : i16
    %1 = llvm.xor %a, %0 : i16
    llvm.return %1 :i16
  }]

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

def not_lshr_after := [llvm|
{
^0(%arg82 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(5 : i8) : i8
  %2 = llvm.xor %arg82, %0 : i8
  %3 = llvm.lshr %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def resTypes : List (MLIRType φ) :=
  op.res.map Prod.snd

def narrow_zext_ashr_keep_trunc_before := [llvm|
{
^0(%arg8 : i8, %arg9 : i8):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.sext %arg8 : i8 to i32
  %2 = llvm.sext %arg9 : i8 to i32
  %3 = llvm.add %1, %2 overflow<nsw> : i32
  %4 = llvm.ashr %3, %0 : i32
  %5 = llvm.trunc %4 : i32 to i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def test2_gen (x y : BitVec w) : (~~~(x ^^^ y)) = ((x &&& y) + ~~~(x ||| y)) :=

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

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

def logic_or_logic_and_7_after := [llvm|
{
^0(%arg69 : i1, %arg70 : i1, %arg71 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg71, %arg70, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = "llvm.select"(%2, %1, %arg69) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def test18_after := [llvm|
{
^0(%arg78 : i16, %arg79 : i32):
  %0 = llvm.mlir.constant(4 : i16) : i16
  %1 = llvm.mlir.constant(0 : i16) : i16
  %2 = llvm.mlir.constant(63 : i32) : i32
  %3 = llvm.mlir.constant(31 : i32) : i32
  %4 = llvm.and %arg78, %0 : i16
  %5 = llvm.icmp "eq" %4, %1 : i16
  %6 = "llvm.select"(%5, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = llvm.and %arg79, %6 : i32
  "llvm.return"(%7) : (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 shift_xor_multiuse_xor_before := [llvm|
{
^0(%arg126 : i32, %arg127 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(2048 : i32) : i32
  %3 = llvm.and %arg126, %0 : i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  %5 = llvm.xor %arg127, %2 : i32
  %6 = "llvm.select"(%4, %arg127, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = llvm.mul %6, %5 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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 not_and_and_or_not_or_or_before := [llvm|
{
^0(%arg253 : i32, %arg254 : i32, %arg255 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg254, %arg253 : i32
  %2 = llvm.or %1, %arg255 : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.xor %arg253, %0 : i32
  %5 = llvm.and %4, %arg254 : i32
  %6 = llvm.and %5, %arg255 : i32
  %7 = llvm.or %6, %3 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def src_srem_shl_demand_min_signbit_mask_hit_last_demand_before := [llvm|
{
^0(%arg20 : i32):
  %0 = llvm.mlir.constant(536870912 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.mlir.constant(-1073741822 : i32) : i32
  %3 = llvm.srem %arg20, %0 : i32
  %4 = llvm.shl %3, %1 : i32
  %5 = llvm.and %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

def unmasked_shlop_insufficient_mask_shift_amount_after := [llvm|
{
^0(%arg14 : i16, %arg15 : i16, %arg16 : i16):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.mlir.constant(255 : i16) : i16
  %2 = llvm.mlir.constant(8 : i16) : i16
  %3 = llvm.and %arg16, %0 : i16
  %4 = llvm.and %arg14, %1 : i16
  %5 = llvm.sub %2, %3 overflow<nsw> : i16
  %6 = llvm.shl %arg15, %5 : i16
  %7 = llvm.lshr %4, %3 : i16
  %8 = llvm.or %6, %7 : i16
  %9 = llvm.trunc %8 : i16 to i8
  "llvm.return"(%9) : (i8) -> ()
}
]

def udiv1_before := [llvm|
{
^0(%arg32 : i32, %arg33 : i32):
  %0 = llvm.udiv exact %arg32, %arg33 : i32
  %1 = llvm.mul %0, %arg33 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def idempotent_prop_freeze : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %0 = llvm.freeze %x : i64
      %1 = llvm.freeze %0 : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      %0 = llvm.freeze %x : i64
      llvm.return %0 : i64
  }]

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 wrongimm_before := [llvm|
{
^0(%arg4 : i16):
  %0 = llvm.mlir.constant(14 : i16) : i16
  %1 = llvm.mlir.constant(27 : i8) : i8
  %2 = llvm.ashr %arg4, %0 : i16
  %3 = llvm.trunc %2 : i16 to i8
  %4 = llvm.xor %3, %1 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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

def PoisonOr.getOrUB  : PoisonOr α → m α
  | .value x => pure x
  | .poison => throwUB

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

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

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

def test6_before := [llvm|
{
^0(%arg3 : i16):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.zext %arg3 : i16 to i32
  %2 = llvm.shl %1, %0 : i32
  %3 = llvm.ashr %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

def dont_narrow_zext_ashr_keep_trunc_after := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(1 : i16) : i16
  %1 = llvm.sext %arg0 : i8 to i16
  %2 = llvm.sext %arg1 : i8 to i16
  %3 = llvm.add %1, %2 overflow<nsw> : i16
  %4 = llvm.lshr %3, %0 : i16
  %5 = llvm.trunc %4 : i16 to i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def udiv_i32_multiuse_before := [llvm|
{
^0(%arg25 : i8, %arg26 : i8):
  %0 = llvm.zext %arg25 : i8 to i32
  %1 = llvm.zext %arg26 : i8 to i32
  %2 = llvm.udiv %0, %1 : i32
  %3 = llvm.add %0, %1 : i32
  %4 = llvm.mul %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def commute_int_constant_to_rhs_mul : RISCVPeepholeRewrite [Ty.riscv (.bv)] where
  lhs := [LV| {
    ^entry (%x: !riscv.reg):
      %c = li (1) : !riscv.reg
      %0 = mul%c, %x : !riscv.reg
      ret %0 : !riscv.reg
  }]
  rhs := [LV| {
    ^entry (%x: !riscv.reg):
      %c = li (1) : !riscv.reg
      %0 = mul %x, %c : !riscv.reg
      ret %0 : !riscv.reg
  }]

def or_disjoint_with_xor_after := [llvm|
{
^0(%arg28 : i32, %arg29 : i32):
  "llvm.return"(%arg29) : (i32) -> ()
}
]

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

def multiuse2_after := [llvm|
{
^0(%arg10 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(12 : i32) : i32
  %2 = llvm.mlir.constant(48 : i32) : i32
  %3 = llvm.mlir.constant(192 : i32) : i32
  %4 = llvm.mlir.constant(8 : i32) : i32
  %5 = llvm.mlir.constant(32256 : i32) : i32
  %6 = llvm.shl %arg10, %0 : i32
  %7 = llvm.and %6, %1 : i32
  %8 = llvm.shl %arg10, %0 : i32
  %9 = llvm.and %8, %2 : i32
  %10 = llvm.shl %arg10, %0 : i32
  %11 = llvm.and %10, %3 : i32
  %12 = llvm.shl %arg10, %4 : i32
  %13 = llvm.and %12, %5 : i32
  %14 = llvm.or disjoint %11, %9 : i32
  %15 = llvm.or disjoint %7, %14 : i32
  %16 = llvm.or disjoint %13, %15 : i32
  "llvm.return"(%16) : (i32) -> ()
}
]

def slt_and_shl_one_after := [llvm|
{
^0(%arg25 : i8, %arg26 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.shl %0, %arg26 overflow<nuw> : i8
  %2 = llvm.and %arg25, %1 : i8
  %3 = llvm.icmp "slt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def logic_and_logic_or_5_before := [llvm|
{
^0(%arg165 : i1, %arg166 : i1, %arg167 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg165, %arg166, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = "llvm.select"(%arg165, %arg167, %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 t0_basic_after := [llvm|
{
^0(%arg29 : i8, %arg30 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg30, %0 : i8
  %2 = llvm.icmp "ugt" %arg29, %1 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

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

instance {Γ : List d.Ty} {t'} {lhs : Com d (.ofList Γ) .pure t'} :
    Decidable (∀ (t : d.Ty) (v : Var (.ofList Γ) t), ⟨t, v⟩ ∈ lhs.vars) :=
  decidable_of_iff
    (∀ (i : Fin Γ.length),
      let v : Var (.ofList Γ) (Γ.get i) := ⟨i, by admit /- proof elided -/
      ⟩
      ⟨_, v⟩ ∈ lhs.vars) <|  by
  constructor
  · intro h t v
    rcases v with ⟨i, hi⟩
    try simp only [Erased.out_mk] at hi
    rcases List.getElem?_eq_some_iff.1 hi with ⟨h', rfl⟩
    simp at h'
    convert h ⟨i, h'⟩
  · intro h i
    apply h

def yw : WidthExpr 1 := WidthExpr.var ⟨0, by admit /- proof elided -/
⟩

inductive Op
| add

| constIx (v: Nat) | constTensor (t : Tensor2d' Int) | constInt (v : Int)
| sub
| map2d
| fill2d
| extract2d

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

def zext_masked_bit_zero_to_larger_bitwidth_after := [llvm|
{
^0(%arg39 : i32, %arg40 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.xor %arg39, %0 : i32
  %3 = llvm.lshr %2, %arg40 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.zext nneg %4 : i32 to i64
  "llvm.return"(%5) : (i64) -> ()
}
]

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

def match_selects : List (Σ Γ, LLVMPeepholeRewriteRefine 64  Γ) :=
  [⟨_, select_1_0⟩,
  ⟨_, select_neg1_0⟩,
  ⟨_, select_0_1⟩,
  ⟨_, select_0_neg1⟩,
  ⟨_, select_cond_f⟩,
  ⟨_, select_1_f⟩,
  ⟨_, select_t_cond⟩,
  ⟨_, select_t_0⟩,
  ⟨_, select_t_1⟩,
  ⟨_, select_0_f⟩]

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

abbrev GenM := StateT State TermElabM

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

def shift_no_xor_multiuse_or_after := [llvm|
{
^0(%arg146 : i32, %arg147 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.or %arg147, %0 : i32
  %3 = llvm.shl %arg146, %1 : i32
  %4 = llvm.and %3, %0 : i32
  %5 = llvm.or %arg147, %4 : i32
  %6 = llvm.mul %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

def n2_before := [llvm|
{
^0(%arg20 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.sdiv %arg20, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def select_icmp_slt_zero_smin_after := [llvm|
{
^0(%arg7 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.or %arg7, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def passriscv64_optimized (fileName : String) : IO UInt32 := do
    let icom? ← Com.parseFromFile LLVMPlusRiscV fileName
    match icom? with
    | none => return 1
    | some (Sigma.mk _Γ ⟨eff, ⟨retTy, c⟩⟩) =>
      match eff with
      | EffectKind.pure =>
        match retTy with
        | [Ty.llvm (.bitvec _w)]  =>
           
          let lowered := selectionPipeFuelWithCSEWithOpt 150 c true
          IO.println <| lowered.printModule
          return 0
        | _ =>
        IO.println s!" debug: WRONG RETURN TYPE : expected Ty.llvm (Ty.bitvec 64) "
        return 1
      | _ =>
      IO.println s!" debug: WRONG EFFECT KIND : expected pure program "
      return 1

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

@[simp_denote]
def xor_llvm_i16:= [LV| {
    ^entry (%a: i16,%b: i16 ):
    %0 = llvm.xor %a, %b : i16
    llvm.return %0 :i16
  }]

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

def ashr_eq_exact_after := [llvm|
{
^0(%arg173 : i8):
  %0 = llvm.mlir.constant(80 : i8) : i8
  %1 = llvm.icmp "eq" %arg173, %0 : i8
  "llvm.return"(%1) : (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) -> ()
}
]

inductive HVector {α : Type*} (f : α → Type*) : List α → Type _
  | nil : HVector f []
  | cons {a : α} : (f a) → HVector f as → HVector f (a :: as)

def icmp_eq_x_invertable_y2_before := [llvm|
{
^0(%arg2 : i8, %arg3 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg3, %0 : i8
  %2 = llvm.and %arg2, %1 : i8
  %3 = llvm.icmp "eq" %1, %2 : i8
  "llvm.return"(%3) : (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 slt_negative_multip_rem_zero_before := [llvm|
{
^0(%arg176 : i8):
  %0 = llvm.mlir.constant(-7 : i8) : i8
  %1 = llvm.mlir.constant(21 : i8) : i8
  %2 = llvm.mul %arg176, %0 overflow<nsw> : i8
  %3 = llvm.icmp "slt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def or_and_not_not_commute3_after := [llvm|
{
^0(%arg416 : i32, %arg417 : i32, %arg418 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg418, %arg417 : i32
  %2 = llvm.or %1, %arg416 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def icmp_ult_x_y_2_after := [llvm|
{
^0(%arg40 : i8, %arg41 : i8):
  %0 = llvm.mul %arg40, %arg40 : i8
  %1 = llvm.and %0, %arg41 : i8
  %2 = llvm.icmp "ne" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

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 c0_before := [llvm|
{
^0(%arg6 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.and %arg6, %0 : i8
  %2 = llvm.icmp "ule" %1, %arg6 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def xor_ashr_not_before := [llvm|
{
^0(%arg27 : i8, %arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.ashr %arg27, %arg29 : i8
  %2 = llvm.ashr %arg28, %arg29 : i8
  %3 = llvm.xor %2, %0 : i8
  %4 = llvm.xor %1, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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 src_x_and_nmask_uge_before := [llvm|
{
^0(%arg21 : i8, %arg22 : i8, %arg23 : i1):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.shl %0, %arg22 : i8
  %3 = "llvm.select"(%arg23, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %4 = llvm.and %arg21, %3 : i8
  %5 = llvm.icmp "uge" %4, %3 : i8
  "llvm.return"(%5) : (i1) -> ()
}
]

@[simp, reducible]
instance : DialectDenote (LLVMPlusRiscV) where
  denote
  | .llvm llvmOp, args, .nil => do
      let xs ← DialectDenote.denote llvmOp (llvmArgsFromHybrid args) .nil
      return xs.map' Ty.llvm (fun t x => x)
  | .riscv (riscvOp), args, .nil => do
      let xs ← DialectDenote.denote riscvOp (riscvArgsFromHybrid args) .nil
      return xs.map' Ty.riscv (fun t x => x)
  | .castRiscv _ , elemToCast, _ =>
    let toCast : BitVec 64 :=
      elemToCast.getN 0 (by admit /- proof elided -/
      )
    [castriscvToLLVM toCast]ₕ
  | .castLLVM _,
    (elemToCast : HVector TyDenote.toType [Ty.llvm (.bitvec _)]), _ =>
    let toCast : PoisonOr (BitVec _) :=
      elemToCast.getN 0 (by admit /- proof elided -/
      )
    [castLLVMToriscv toCast]ₕ

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

def llvm_sext_lower_riscv_i1_to_32 : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 1)] :=
  {lhs:= sext_llvm_i1_to_32, rhs:= sext_riscv_i1_to_32}

private def rgn3 : Region φ :=
  [mlir_region|  {
      "std.return"(%x0) : (i42) -> ()
  }]

def xor_or_after := [llvm|
{
^0(%arg137 : i1, %arg138 : i32, %arg139 : i32):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "uge" %arg138, %arg139 : i32
  %3 = llvm.xor %arg137, %0 : i1
  %4 = "llvm.select"(%3, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

LawfulHashable in Init.Data.LawfulHashable

def src_is_mask_shl_lshr_after := [llvm|
{
^0(%arg103 : i8, %arg104 : i8, %arg105 : i1):
  %0 = llvm.mlir.constant(122 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.xor %arg103, %0 : i8
  %3 = llvm.lshr %1, %arg104 : i8
  %4 = llvm.icmp "ugt" %2, %3 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

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

instance : ToString HydraVariable where
  toString s := s! "Variable[id: {s.id}, name : {s.name}, width : {s.width}]"

def test_mul_nsw__nsw_is_safe_after := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(-83886080 : i32) : i32
  %1 = llvm.mlir.constant(9 : i32) : i32
  %2 = llvm.or %arg5, %0 : i32
  %3 = llvm.mul %2, %1 overflow<nsw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def join (x y : TokenStream) : TokenStream  :=
  Stream.corec (β := TokenStream × TokenStream) (x, y) fun ⟨x, y⟩ =>
    match x 0, y 0 with
    | some _, some _ => (some (), (x.tail, y.tail))
    | some _, none => (none, (x, y.tail))
    | none, some _ => (none, (x.tail, y))
    | none, none => (none, (x.tail, y.tail))

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

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

def test18_before := [llvm|
{
^0(%arg179 : i8):
  %0 = llvm.sext %arg179 : i8 to i32
  %1 = llvm.trunc %0 : i32 to i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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

def test52_after := [llvm|
{
^0(%arg132 : i64):
  %0 = llvm.mlir.constant(7224 : i16) : i16
  %1 = llvm.mlir.constant(-32574 : i16) : i16
  %2 = llvm.trunc %arg132 : i64 to i16
  %3 = llvm.and %2, %0 : i16
  %4 = llvm.or disjoint %3, %1 : i16
  %5 = llvm.zext %4 : i16 to i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

def select_constant_cmp_true : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.mlir.constant (1) : i1
      %1 = llvm.select %0, %x, %y : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64, %y: i64):
      llvm.return %x : i64
  }]

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

def sub_from_variable_of_sub_from_constant_before := [llvm|
{
^0(%arg183 : i8, %arg184 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.sub %0, %arg183 : i8
  %2 = llvm.sub %arg184, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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 add_mask_ashr28_i32_before := [llvm|
{
^0(%arg2 : i32):
  %0 = llvm.mlir.constant(28 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.ashr %arg2, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.add %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def t0_before := [llvm|
{
^0(%arg8 : i8, %arg9 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg8, %0 : i8
  %2 = llvm.ashr %1, %arg9 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def trunc_shl_15_i16_i32_after := [llvm|
{
^0(%arg53 : i32):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.trunc %arg53 : i32 to i16
  %2 = llvm.shl %1, %0 : i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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

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

instance : DialectToExpr DCxComb where
  toExprM := .const ``Id [0]
  toExprDialect := .const ``DCxComb []

def Com.toLets (com : Com d Γ eff t) : Lets d Γ eff com.outContext :=
  Lets.nil.addComToEnd com

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

inductive Ty2
  | bitvec (w : Nat) : Ty2
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

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 ashrslt_01_03_exact_before := [llvm|
{
^0(%arg50 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(3 : i4) : i4
  %2 = llvm.ashr exact %arg50, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def ashrslt_02_15_exact_before := [llvm|
{
^0(%arg22 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.mlir.constant(-1 : i4) : i4
  %2 = llvm.ashr exact %arg22, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (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 sext_multi_uses_after := [llvm|
{
^0(%arg9 : i64, %arg10 : i1, %arg11 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.add %arg11, %arg9 : i64
  %2 = llvm.sub %0, %1 : i64
  %3 = "llvm.select"(%arg10, %2, %arg9) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def lshr_and_and_after := [llvm|
{
^0(%arg49 : i8, %arg50 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.mlir.constant(52 : i8) : i8
  %3 = llvm.srem %arg49, %0 : i8
  %4 = llvm.shl %3, %1 : i8
  %5 = llvm.and %arg50, %2 : i8
  %6 = llvm.and %5, %4 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

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

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

    |

structure Tensor2d' (α : Type) where
  dim₀ : Index
  dim₁ : Index
  mat : Matrix (Fin dim₀) (Fin dim₁) α

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

def icmp_sgt9_before := [llvm|
{
^0(%arg16 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(-128 : i8) : i8
  %2 = llvm.shl %arg16, %0 overflow<nsw> : i8
  %3 = llvm.icmp "sgt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def VarRemapVar
  (w': HVector Γ'.Var β) :
  {w : HVector Γ.Var β //
    ∀ (Vstart : Ctxt.Valuation Γstart),
      w.map (lets.denote Vstart)
      = w'.map ((lets.denote Vstart).comap hom)  } :=
    if TY : β = α then
      if H : TY ▸ w' = vnew then
        ⟨TY ▸ vold, by admit /- proof elided -/
          ⟩
      else ⟨w'.map hom, by admit /- proof elided -/
      ⟩
    else ⟨w'.map hom, by admit /- proof elided -/
    ⟩

def or_and_not_not_commute2_after := [llvm|
{
^0(%arg419 : i32, %arg420 : i32, %arg421 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg421, %arg420 : i32
  %2 = llvm.or %1, %arg419 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def logical_and_bitwise_and_icmps_comm3_before := [llvm|
{
^0(%arg211 : i8, %arg212 : i8, %arg213 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.mlir.constant(false) : i1
  %4 = llvm.icmp "eq" %arg212, %0 : i8
  %5 = llvm.and %arg211, %1 : i8
  %6 = llvm.shl %1, %arg213 : i8
  %7 = llvm.and %arg211, %6 : i8
  %8 = llvm.icmp "ne" %5, %2 : i8
  %9 = llvm.icmp "ne" %7, %2 : i8
  %10 = llvm.and %8, %4 : i1
  %11 = "llvm.select"(%9, %10, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%11) : (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 ashrsgt_01_04_after := [llvm|
{
^0(%arg313 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def hoist_logic_op_with_same_opcode_hands_32 : List (Σ Γ, LLVMPeepholeRewriteRefine 32 Γ) :=
  [⟨_, AndTruncTrunc⟩,
  ⟨_, OrTruncTrunc⟩,
  ⟨_, XorTruncTrunc⟩]

def logicalShiftRight (x : BitStream) (k : Nat) : BitStream :=
  fun i => x (k + i)

def udiv_shl_mul_nuw_exact_before := [llvm|
{
^0(%arg142 : i5, %arg143 : i5, %arg144 : i5):
  %0 = llvm.shl %arg142, %arg144 overflow<nuw> : i5
  %1 = llvm.mul %arg142, %arg143 overflow<nuw> : i5
  %2 = llvm.udiv exact %0, %1 : i5
  "llvm.return"(%2) : (i5) -> ()
}
]

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

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 alive_AndOrXor_135_src :=
[sllvm| {
^bb0(%X : i64, %C1 : i64, %C2 : i64):
  %v1 = llvm.xor %X, %C1 : i64
  %v2 = llvm.and %v1, %C2 : i64
  llvm.return %v2 : i64
}]

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

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

def PR39793_bswap_u32_as_u16_trunc_after := [llvm|
{
^0(%arg24 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.lshr %arg24, %0 : i32
  %2 = llvm.trunc %1 : i32 to i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

def alive_820_tgt  :=
[llvm()| {
^bb0(%X : i9, %Op1 : i9):
  %v1 = llvm.srem %X, %Op1 : i9
  %v2 = llvm.sub %X, %v1 : i9
  %v3 = llvm.sdiv %X, %Op1 : i9
  llvm.return %v3 : i9
}]

def test_add_nsw__nsw_is_safe_before := [llvm|
{
^0(%arg37 : 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 %arg37, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.add %4, %2 overflow<nsw> : i32
  %7 = "llvm.select"(%5, %3, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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 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 test2_before := [llvm|
{
^0(%arg5 : i1005):
  %0 = llvm.mlir.constant(0 : i1005) : i1005
  %1 = llvm.xor %arg5, %0 : i1005
  "llvm.return"(%1) : (i1005) -> ()
}
]

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

def or_and_xor_not_constant_commute1_before := [llvm|
{
^0(%arg166 : i9, %arg167 : i9):
  %0 = llvm.mlir.constant(42 : i9) : i9
  %1 = llvm.mlir.constant(-43 : i9) : i9
  %2 = llvm.xor %arg167, %arg166 : i9
  %3 = llvm.and %2, %0 : i9
  %4 = llvm.and %arg167, %1 : i9
  %5 = llvm.or %3, %4 : i9
  "llvm.return"(%5) : (i9) -> ()
}
]

def shl_sub_i32_before := [llvm|
{
^0(%arg18 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.sub %0, %arg18 : i32
  %3 = llvm.shl %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def src_is_mask_zext_before := [llvm|
{
^0(%arg131 : i16, %arg132 : i8):
  %0 = llvm.mlir.constant(123 : i16) : i16
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.xor %arg131, %0 : i16
  %3 = llvm.lshr %1, %arg132 : i8
  %4 = llvm.zext %3 : i8 to i16
  %5 = llvm.and %2, %4 : i16
  %6 = llvm.icmp "eq" %5, %2 : i16
  "llvm.return"(%6) : (i1) -> ()
}
]

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

def and_sel_op0_after := [llvm|
{
^0(%arg17 : i1):
  %0 = llvm.zext %arg17 : i1 to i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def or_xor_tree_1110_after := [llvm|
{
^0(%arg3 : i32, %arg4 : i32, %arg5 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mul %arg3, %0 : i32
  %2 = llvm.mul %arg4, %0 : i32
  %3 = llvm.mul %arg5, %0 : i32
  %4 = llvm.xor %1, %2 : i32
  %5 = llvm.or %4, %3 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

RV64.zexth in RISCV.Instructions

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 ashrslt_03_04_exact_before := [llvm|
{
^0(%arg17 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(4 : i4) : i4
  %2 = llvm.ashr exact %arg17, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

@[match_pattern] def xor    (w : Width φ) : MOp φ := .binary w .xor

def main4b_after := [llvm|
{
^0(%arg132 : i32):
  %0 = llvm.mlir.constant(23 : i32) : i32
  %1 = llvm.and %arg132, %0 : i32
  %2 = llvm.icmp "ne" %1, %0 : i32
  %3 = llvm.zext %2 : i1 to i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

BitVec.sshiftRight' in Init.Data.BitVec.Basic

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

def select_icmp_ne_0_and_4096_and_not_4096_before := [llvm|
{
^0(%arg227 : i32, %arg228 : 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 %arg227, %0 : i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  %5 = llvm.and %arg228, %2 : i32
  %6 = "llvm.select"(%4, %arg228, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def ne_21_comm_ne_before := [llvm|
{
^0(%arg68 : i32, %arg69 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.lshr %arg68, %0 : i32
  %3 = llvm.trunc %2 : i32 to i8
  %4 = llvm.lshr %arg68, %1 : i32
  %5 = llvm.trunc %4 : i32 to i8
  %6 = llvm.lshr %arg69, %0 : i32
  %7 = llvm.trunc %6 : i32 to i8
  %8 = llvm.lshr %arg69, %1 : i32
  %9 = llvm.trunc %8 : i32 to i8
  %10 = llvm.icmp "ne" %3, %7 : i8
  %11 = llvm.icmp "ne" %9, %5 : i8
  %12 = llvm.or %11, %10 : i1
  "llvm.return"(%12) : (i1) -> ()
}
]

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

def andn_or_cmp_4_before := [llvm|
{
^0(%arg161 : i32, %arg162 : i32, %arg163 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.icmp "eq" %arg161, %arg162 : i32
  %2 = llvm.icmp "ne" %arg161, %arg162 : i32
  %3 = llvm.icmp "ugt" %arg163, %0 : i32
  %4 = llvm.or %1, %3 : i1
  %5 = llvm.and %4, %2 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

@[simp_denote]
def add_llvm_nsw_nuw_flags_16 := [LV| {
   ^entry (%lhs: i16, %rhs: i16):
    %1 = llvm.add %lhs, %rhs overflow<nsw,nuw> : i16
    llvm.return %1 : i16
  }]

def mul_add_to_mul_8_after := [llvm|
{
^0(%arg24 : i16):
  %0 = llvm.mlir.constant(32767 : i16) : i16
  %1 = llvm.mul %arg24, %0 overflow<nsw> : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

instance : Monad (MetaLLVM φ).m :=

def select_0_neg1 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 1)] where
  lhs := [LV| {
    ^entry (%c: i1):
      %t = llvm.mlir.constant (0) : i64
      %f = llvm.mlir.constant (-1) : i64
      %0 = llvm.select %c, %t, %f : i64
      llvm.return %0 : i64
  }]
  rhs := [LV| {
    ^entry (%c: i1):
      %0 = llvm.not %c : i1
      %1 = llvm.sext %0: i1 to i64
      llvm.return %1 : i64
  }]

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

def AttrEntry.destructure {φ} : AttrEntry φ → String × AttrValue φ
  | .mk name value => (name,value)

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

BitVec.smulOverflow in Init.Data.BitVec.Basic

def or_signbit_shl_before := [llvm|
{
^0(%arg21 : i32):
  %0 = llvm.mlir.constant(-65536 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.or %arg21, %0 : i32
  %3 = llvm.shl %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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.or %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def lor_land_right2_after := [llvm|
{
^0(%arg24 : i1, %arg25 : i1):
  "llvm.return"(%arg24) : (i1) -> ()
}
]

abbrev Term.Ctx (wcard : Nat) (tcard : Nat) : Type :=
  Fin tcard → WidthExpr wcard

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

RV64.sll in RISCV.Instructions

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

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 icmp_ult_8_after := [llvm|
{
^0(%arg12 : i64):
  %0 = llvm.mlir.constant(16) : i64
  %1 = llvm.icmp "ult" %arg12, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

def t5_c2_before := [llvm|
{
^0(%arg21 : i8, %arg22 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.sub %arg21, %arg22 : i8
  %2 = llvm.sub %1, %0 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def test1_before := [llvm|
{
^0(%arg3 : i16):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(5 : i32) : i32
  %2 = llvm.zext %arg3 : i16 to i32
  %3 = llvm.lshr %2, %0 : i32
  %4 = llvm.mul %2, %1 : i32
  %5 = llvm.or %3, %4 : i32
  %6 = llvm.trunc %5 : i32 to i16
  "llvm.return"(%6) : (i16) -> ()
}
]

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

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

def scalar_i16_shl_ult_const_before := [llvm|
{
^0(%arg16 : i16):
  %0 = llvm.mlir.constant(8 : i16) : i16
  %1 = llvm.mlir.constant(1024 : i16) : i16
  %2 = llvm.shl %arg16, %0 : i16
  %3 = llvm.icmp "ult" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def src_is_mask_p2_m1_after := [llvm|
{
^0(%arg90 : i8, %arg91 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.mlir.constant(123 : i8) : i8
  %3 = llvm.shl %0, %arg91 : i8
  %4 = llvm.add %3, %1 : i8
  %5 = llvm.xor %arg90, %2 : i8
  %6 = llvm.icmp "ugt" %5, %4 : i8
  "llvm.return"(%6) : (i1) -> ()
}
]

def sub_from_variable_of_sub_from_constant_after := [llvm|
{
^0(%arg167 : i8, %arg168 : i8):
  %0 = llvm.mlir.constant(-42 : i8) : i8
  %1 = llvm.add %arg167, %0 : i8
  %2 = llvm.add %1, %arg168 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def or_logic_or_logic_and_1_after := [llvm|
{
^0(%arg48 : i1, %arg49 : i1, %arg50 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg49, %arg50, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = "llvm.select"(%arg48, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

def orn_and_cmp_2_logical_before := [llvm|
{
^0(%arg9 : i16, %arg10 : i16, %arg11 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "sge" %arg9, %arg10 : i16
  %3 = llvm.icmp "slt" %arg9, %arg10 : i16
  %4 = "llvm.select"(%arg11, %2, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = "llvm.select"(%4, %1, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (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 or_basic_after := [llvm|
{
^0(%arg15 : i16):
  %0 = llvm.mlir.constant(17791 : i16) : i16
  %1 = llvm.icmp "ne" %arg15, %0 : i16
  "llvm.return"(%1) : (i1) -> ()
}
]

private partial def Com.printAux : Com d Γ eff ts → Format
  | .rets vs =>
      let vs :=
        vs.mapToList printVar
        |> (Format.joinSep · ", ") |> Format.group
      let ret := printReturn ts
      let ts :=
        ts.map printTy
        |> (Format.joinSep · ", ") |> Format.group
      Format.align true ++ f!"\"{ret}\"({vs}) : ({ts}) -> ()"
  | .var e body => e.print ++ Com.printAux body

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 negative_not_less_than_logical_before := [llvm|
{
^0(%arg8 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(256 : i32) : i32
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "sgt" %arg8, %0 : i32
  %4 = llvm.add %arg8, %1 : i32
  %5 = llvm.icmp "ult" %4, %1 : i32
  %6 = "llvm.select"(%3, %5, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def test16_after := [llvm|
{
^0(%arg283 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  "llvm.return"(%0) : (i8) -> ()
}
]

def sameBothSides (bvLogicalExpr : (BoolExpr GenBVPred)) : Bool :=
    match bvLogicalExpr with
  | .literal (GenBVPred.bin lhs _ rhs) => lhs == rhs
  | _ => false

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

def testNameToRowName : String → String
  | testName => match testName.splitOn "_" with
    | [_,name] => name
    | [_,name, op] => s!"{name}.{op}"
    | _ => "Error"

def test1_trunc_before := [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 %3, %5 : i32
  %7 = llvm.trunc %6 : i32 to i16
  "llvm.return"(%7) : (i16) -> ()
}
]

def not_cmp_fold_eq : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.icmp.eq %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.ne %x, %y : i64
      llvm.return %0 : i1
  }]

abbrev RepeatDCEType {Γ : Ctxt d.Ty} {t} (com : Com d Γ .pure t) : Type :=
  { com' : Com d Γ .pure t //  ∀ (V : Γ.Valuation), com.denote V = com'.denote V}

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

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

instance : HasUB Option where
  throwUB := none

def select_sub_icmp_bad_2_before := [llvm|
{
^0(%arg68 : i32, %arg69 : i32, %arg70 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.icmp "eq" %arg68, %0 : i32
  %2 = llvm.sub %arg70, %arg68 : i32
  %3 = "llvm.select"(%1, %2, %arg69) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def test_sub_nuw__nuw_is_safe_after := [llvm|
{
^0(%arg26 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : i32) : i32
  %2 = llvm.and %arg26, %0 : i32
  %3 = llvm.sub %1, %2 overflow<nuw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

@[simp_denote]
def Refinement.ofHRefinement (inst : HRefinement α α) : Refinement α where
  IsRefinedBy x y := x ⊑ y

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

def binop_same_val : List (Σ Γ, RISCVPeepholeRewrite  Γ) :=
    [⟨_, binop_same_val_and⟩,
    ⟨_, binop_same_val_or⟩]

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

inductive MTy (φ : Nat)
  | bitvec (w : Width φ) : MTy φ
  deriving DecidableEq, Inhabited, Lean.ToExpr

def scalar_i64_lshr_and_signbit_eq_before := [llvm|
{
^0(%arg29 : i64, %arg30 : i64):
  %0 = llvm.mlir.constant(-9223372036854775808) : i64
  %1 = llvm.mlir.constant(0) : i64
  %2 = llvm.lshr %arg29, %arg30 : i64
  %3 = llvm.and %2, %0 : i64
  %4 = llvm.icmp "eq" %3, %1 : i64
  "llvm.return"(%4) : (i1) -> ()
}
]

def fsmWidthUle (a b : FSM α) : FSM α :=
  composeUnaryAux FSM.scanAnd (b ||| ~~~ a)

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 llvm_zext_lower_riscv_1_to_8 : LLVMPeepholeRewriteRefine 8 [Ty.llvm (.bitvec 1)] :=
  {lhs:= zext_llvm_1_to_8, rhs:= zext_riscv_1_to_8}

def alive_AddSub_1564_tgt  (w : Nat)  :=
[llvm( w )| {
^bb0(%x : _, %C : _):
  %v1 = llvm.mlir.constant -1
  %v2 = llvm.xor %x, %v1
  %v3 = llvm.mlir.constant 1
  %v4 = llvm.add %C, %v3
  %v5 = llvm.add %x, %v4
  llvm.return %v5
}]

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

def in_constant_14_vary_after := [llvm|
{
^0(%arg22 : i4, %arg23 : i4):
  %0 = llvm.mlir.constant(-2 : i4) : i4
  %1 = llvm.and %arg22, %0 : i4
  "llvm.return"(%1) : (i4) -> ()
}
]

BitVec.ugt in Leanwuzla.Aux

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

def reused_mul_nuw_xy_z_selectnonzero_ugt_after := [llvm|
{
^0(%arg39 : i8, %arg40 : i8, %arg41 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "eq" %arg41, %0 : i8
  %3 = llvm.mul %arg39, %arg41 overflow<nuw> : i8
  %4 = llvm.mul %arg40, %arg41 overflow<nuw> : i8
  %5 = llvm.icmp "ugt" %4, %3 : i8
  %6 = "llvm.select"(%2, %1, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

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

def and_ranges_overlap_single_before := [llvm|
{
^0(%arg255 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.mlir.constant(20 : i8) : i8
  %3 = llvm.icmp "uge" %arg255, %0 : i8
  %4 = llvm.icmp "ule" %arg255, %1 : i8
  %5 = llvm.and %3, %4 : i1
  %6 = llvm.icmp "uge" %arg255, %1 : i8
  %7 = llvm.icmp "ule" %arg255, %2 : i8
  %8 = llvm.and %6, %7 : i1
  %9 = llvm.and %5, %8 : i1
  "llvm.return"(%9) : (i1) -> ()
}
]

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

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

def test68_xor_after := [llvm|
{
^0(%arg162 : i32, %arg163 : i32):
  %0 = llvm.mlir.constant(6 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.lshr %arg162, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.xor %arg163, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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 ashrsgt_02_13_before := [llvm|
{
^0(%arg288 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.mlir.constant(-3 : i4) : i4
  %2 = llvm.ashr %arg288, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

@[simp_denote]
def icmp_uge_riscv_64 := [LV| {
  ^entry (%lhs: i64, %rhs: i64):
    %lhsr = "builtin.unrealized_conversion_cast"(%lhs) : (i64) -> (!i64)
    %rhsr = "builtin.unrealized_conversion_cast"(%rhs) : (i64) -> (!i64)
    %0 = sltu %lhsr, %rhsr : !i64
    %1 = xori %0, 1 : !i64
    %2 = "builtin.unrealized_conversion_cast"(%1) : (!i64) -> (i1)
    llvm.return %2 : i1
  }]

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

RV64.xnor in RISCV.Instructions

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

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

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

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

def 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 or_xor_xor_normal_binops_after := [llvm|
{
^0(%arg8 : i32, %arg9 : i32, %arg10 : i32):
  %0 = llvm.xor %arg9, %arg8 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

instance instPrint : DialectPrint SimpleReg where
  printOpName
  | .add => "add"
  | .const _ => "const"
  | .iterate _ => "iterate"
  printTy
  | .int => "i32"
  printAttributes
  | .const val => s!"\{value = {val} : i32}"
  | .iterate k => s!"\{iterations = {k}}"
  | _ => ""
  dialectName := "simple"
  printReturn _ := "return"

def positive_different_trunc_both_logical_before := [llvm|
{
^0(%arg36 : i32):
  %0 = llvm.mlir.constant(-1 : i15) : i15
  %1 = llvm.mlir.constant(128 : i16) : i16
  %2 = llvm.mlir.constant(256 : i16) : i16
  %3 = llvm.mlir.constant(false) : i1
  %4 = llvm.trunc %arg36 : i32 to i15
  %5 = llvm.icmp "sgt" %4, %0 : i15
  %6 = llvm.trunc %arg36 : i32 to i16
  %7 = llvm.add %6, %1 : i16
  %8 = llvm.icmp "ult" %7, %2 : i16
  %9 = "llvm.select"(%5, %8, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%9) : (i1) -> ()
}
]

def zero_sign_bit2_after := [llvm|
{
^0(%arg29 : i16, %arg30 : i16):
  %0 = llvm.mlir.constant(32767 : i16) : i16
  %1 = llvm.and %arg29, %0 : i16
  %2 = llvm.and %arg30, %0 : i16
  %3 = llvm.add %1, %2 overflow<nuw> : i16
  "llvm.return"(%3) : (i16) -> ()
}
]

def assignAllVars [DecidableEq α] (c : Circuit α)
  (f : α → Bool) : Circuit Empty
  := match c with
  | tru => tru
  | fals => fals
  | var b x =>
    let v := f x
    Circuit.ofBool (b = v)
  | and p q => assignAllVars p f &&& assignAllVars q f
  | or p q => assignAllVars p f ||| assignAllVars q f
  | xor p q => assignAllVars p f ^^^ assignAllVars q f

def PR60818_ne_before := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.sub %0, %arg5 : i32
  %2 = llvm.icmp "ne" %1, %arg5 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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 udiv_pow2_1 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant (1) : i64
      %0 = llvm.udiv %x, %c : i64
      llvm.return %0 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant (0) : i64
      %0 = llvm.lshr %x, %c : i64
      llvm.return %0 : i64
  }]

Lean.Parser.unicodeSymbol in Lean.Parser.Basic

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

instance : Add Term := ⟨add⟩

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

def test46_after := [llvm|
{
^0(%arg141 : i64):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(10752 : i32) : i32
  %2 = llvm.trunc %arg141 : i64 to i32
  %3 = llvm.shl %2, %0 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.zext nneg %4 : i32 to i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def factorize3_before := [llvm|
{
^0(%arg5 : i32, %arg6 : i32, %arg7 : i32):
  %0 = llvm.or %arg6, %arg7 : i32
  %1 = llvm.or %arg5, %0 : i32
  %2 = llvm.or %arg5, %arg7 : i32
  %3 = llvm.and %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

private def oprgn0 : Op φ := [mlir_op|
 "func"() ({ ^entry: %x = "foo.add"() : () -> (i64) } ) : () -> ()
]

noncomputable def mkSimplePathOfPath (fsm : FSM arity)
    (s0 : fsm.α → Bool) (n : Nat) (inputs : arity → BitStream) :
    SimplePathOfPath fsm s0 n inputs :=

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

def no_shift_no_xor_multiuse_xor_after := [llvm|
{
^0(%arg138 : i32, %arg139 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.and %arg138, %0 : i32
  %2 = llvm.xor %arg139, %0 : i32
  %3 = llvm.xor %arg139, %1 : i32
  %4 = llvm.mul %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test_or1_before := [llvm|
{
^0(%arg36 : i32, %arg37 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg37, %0 : i32
  %3 = llvm.icmp "slt" %arg36, %1 : i32
  %4 = llvm.icmp "sge" %arg36, %2 : i32
  %5 = llvm.or %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def rem_euclid_wrong_operands_select_before := [llvm|
{
^0(%arg8 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.srem %arg8, %0 : i32
  %3 = llvm.icmp "slt" %2, %1 : i32
  %4 = llvm.add %2, %0 : i32
  %5 = "llvm.select"(%3, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def test_sub_0_Y_ne_0_before := [llvm|
{
^0(%arg48 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sub %0, %arg48 : i8
  %2 = llvm.icmp "ne" %1, %0 : i8
  "llvm.return"(%2) : (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) -> ()
}
]

Polynomial.degree in Mathlib.Algebra.Polynomial.Degree.Definitions

def p_commutative2_after := [llvm|
{
^0(%arg27 : i32, %arg28 : i32, %arg29 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg27, %arg29 : i32
  %2 = llvm.xor %arg29, %0 : i32
  %3 = llvm.and %arg28, %2 : i32
  %4 = llvm.or disjoint %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def masked_or_A_slightly_optimized_before := [llvm|
{
^0(%arg119 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(39 : i32) : i32
  %2 = llvm.icmp "ult" %arg119, %0 : i32
  %3 = llvm.and %arg119, %1 : i32
  %4 = llvm.icmp "eq" %3, %arg119 : i32
  %5 = llvm.or %2, %4 : i1
  "llvm.return"(%5) : (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) -> ()
}
]

@[deprecated "Use `LLVM.Ty` instead" (since:="2025-04-30")] abbrev Ty := LLVM.Ty

def pack (x : Stream α) (y : Stream Unit) : Stream α :=
  syncMap₂ (xs := x) (ys := y) (f := wrapReadyValue)

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

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

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

def test6_after := [llvm|
{
^0(%arg27 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-1073741824 : i32) : i32
  %2 = llvm.ashr %arg27, %0 : i32
  %3 = llvm.add %2, %1 overflow<nsw> : i32
  %4 = llvm.sext %3 : i32 to i64
  "llvm.return"(%4) : (i64) -> ()
}
]

@[simp_denote]
def udiv_llvm_no_exact_64 : Com  LLVMPlusRiscV ⟨[.llvm (.bitvec 64), .llvm (.bitvec 64)]⟩
  .pure (.llvm (.bitvec 64)) := [LV| {
  ^entry (%x: i64, %y: i64 ):
    %1 = llvm.udiv    %x, %y : i64
    llvm.return %1 : i64
  }]

def to_loop_run (δ : Int) (f : LoopBody α) (niters : ℕ) (val : α) : α :=
  (counterDecorator δ f (niters,val)).2

def or_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where
  lhs := or_llvm_i16
  rhs := or_riscv_i16

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

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

def or_nosignbit_ashr_after := [llvm|
{
^0(%arg4 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(8388352 : i32) : i32
  %2 = llvm.ashr %arg4, %0 : i32
  %3 = llvm.or %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def or_eq_with_one_bit_diff_constants2_before := [llvm|
{
^0(%arg362 : i32):
  %0 = llvm.mlir.constant(97 : i32) : i32
  %1 = llvm.mlir.constant(65 : i32) : i32
  %2 = llvm.icmp "eq" %arg362, %0 : i32
  %3 = llvm.icmp "eq" %arg362, %1 : i32
  %4 = llvm.or %2, %3 : i1
  "llvm.return"(%4) : (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 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) -> ()
}
]

def udiv_i32_c_after := [llvm|
{
^0(%arg14 : i8):
  %0 = llvm.mlir.constant(10 : i8) : i8
  %1 = llvm.udiv %arg14, %0 : i8
  %2 = llvm.zext nneg %1 : i8 to i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def canonicalize_logic_first_or0_nswnuw_after := [llvm|
{
^0(%arg38 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(112 : i32) : i32
  %2 = llvm.or %arg38, %0 : i32
  %3 = llvm.add %2, %1 overflow<nsw,nuw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

instance [HRefinement α α] [DecidableRel (· ⊑ · : α → α → _)] :
    DecidableRel (· ⊑ · : PoisonOr α → PoisonOr α → _)
  | .poison, _ => .isTrue <| by simp
  | .value _, .poison => .isFalse <| by simp
  | .value a, .value b => decidable_of_decidable_of_iff (p := a ⊑ b) <| by simp

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

def a_after := [llvm|
{
^0(%arg48 : i1, %arg49 : i1):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.sext %arg49 : i1 to i32
  %3 = "llvm.select"(%arg48, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.add %3, %2 overflow<nsw> : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def test_shl_nuw_nsw__nuw_is_safe_before := [llvm|
{
^0(%arg82 : i32, %arg83 : i64):
  %0 = llvm.mlir.constant(1073741822 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.and %arg82, %0 : i32
  %4 = llvm.shl %3, %1 overflow<nsw,nuw> : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.icmp "eq" %3, %2 : i32
  %7 = llvm.ashr %arg83, %5 : i64
  %8 = "llvm.select"(%6, %arg83, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

def test2_after := [llvm|
{
^0(%arg2 : i499):
  %0 = llvm.mlir.constant(10633823966279326983230456482242756607 : i499) : i499
  %1 = llvm.and %arg2, %0 : i499
  "llvm.return"(%1) : (i499) -> ()
}
]

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

List.foldr in Init.Data.List.Basic

def logical_and_implies_before := [llvm|
{
^0(%arg249 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(42 : i32) : i32
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "ne" %arg249, %0 : i32
  %4 = llvm.icmp "ne" %arg249, %1 : i32
  %5 = "llvm.select"(%3, %4, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def no_shift_xor_multiuse_cmp_before := [llvm|
{
^0(%arg96 : i32, %arg97 : i32, %arg98 : i32, %arg99 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg96, %0 : i32
  %3 = llvm.icmp "ne" %1, %2 : i32
  %4 = llvm.or %arg97, %0 : i32
  %5 = "llvm.select"(%3, %arg97, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = "llvm.select"(%3, %arg98, %arg99) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = llvm.mul %5, %6 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

instance [ToMessageData α] : ToMessageData (ReflectResult α) where
  toMessageData result := m!"{result.e} {result.exprToIx}"

def negate_sext_before := [llvm|
{
^0(%arg114 : i8, %arg115 : i1):
  %0 = llvm.sext %arg115 : i1 to i8
  %1 = llvm.sub %arg114, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

def src_after := [llvm|
{
^0(%arg0 : i1):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.zext %arg0 : i1 to i32
  %2 = llvm.shl %0, %1 overflow<nsw> : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.shl %4, %1 overflow<nsw,nuw> : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def add_mask_ashr28_i32_before := [llvm|
{
^0(%arg2 : i32):
  %0 = llvm.mlir.constant(28 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.ashr %arg2, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.add %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def body : BasicBlock Op T → Body Op T
  | ⟨_, _, body⟩ => body

def simplify_neg_minmax : RISCVPeepholeRewrite [Ty.riscv (.bv) ] where
  lhs := [LV| {
    ^entry (%x: !riscv.reg):
      %0 = neg %x : !riscv.reg
      %1 = min %x, %0 : !riscv.reg
      %2 = neg %1 : !riscv.reg
      ret %2 : !riscv.reg
  }]
  rhs := [LV| {
    ^entry (%x: !riscv.reg):
      %0 = neg %x : !riscv.reg
      %1 = max %x, %0 : !riscv.reg
      ret %1 : !riscv.reg
  }]

def andn_or_cmp_4_logical_before := [llvm|
{
^0(%arg158 : i32, %arg159 : i32, %arg160 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "eq" %arg158, %arg159 : i32
  %4 = llvm.icmp "ne" %arg158, %arg159 : i32
  %5 = llvm.icmp "ugt" %arg160, %0 : i32
  %6 = "llvm.select"(%3, %1, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %7 = "llvm.select"(%6, %4, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def fsmTermNe {wcard tcard : Nat}
  {a b : Nondep.Term}
  (afsm : TermFSM wcard tcard bcard ncard icard pcard a)
  (bfsm : TermFSM wcard tcard bcard ncard icard pcard b)
  : FSM (StateSpace wcard tcard bcard ncard icard pcard) :=
    composeUnaryAux FSM.scanOr
    (composeBinaryAux' FSM.xor afsm.toFsmZext  bfsm.toFsmZext)

def ValueStream := Stream

def c_1_0_0_after := [llvm|
{
^0(%arg32 : i4, %arg33 : i4, %arg34 : i4):
  %0 = llvm.xor %arg33, %arg32 : i4
  %1 = llvm.and %0, %arg34 : i4
  %2 = llvm.xor %1, %arg32 : i4
  "llvm.return"(%2) : (i4) -> ()
}
]

def ashr_ne_noexact_after := [llvm|
{
^0(%arg162 : i8):
  %0 = llvm.mlir.constant(-8 : i8) : i8
  %1 = llvm.mlir.constant(80 : i8) : i8
  %2 = llvm.and %arg162, %0 : i8
  %3 = llvm.icmp "ne" %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 foo_after := [llvm|
{
^0(%arg113 : i32, %arg114 : i32, %arg115 : i32, %arg116 : i32):
  %0 = llvm.icmp "slt" %arg113, %arg114 : i32
  %1 = "llvm.select"(%0, %arg115, %arg116) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def or_and_not_not_wrong_b_before := [llvm|
{
^0(%arg378 : i32, %arg379 : i32, %arg380 : i32, %arg381 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg381, %arg378 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.or %arg378, %arg380 : i32
  %4 = llvm.xor %3, %0 : i32
  %5 = llvm.and %4, %arg379 : i32
  %6 = llvm.or %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

def simplify_neg_maxmin : RISCVPeepholeRewrite [Ty.riscv (.bv) ] where
  lhs := [LV| {
    ^entry (%x: !riscv.reg):
      %0 = neg %x : !riscv.reg
      %1 = max %x, %0 : !riscv.reg
      %2 = neg %1 : !riscv.reg
      ret %2 : !riscv.reg
  }]
  rhs := [LV| {
    ^entry (%x: !riscv.reg):
      %0 = neg %x : !riscv.reg
      %1 = min %x, %0 : !riscv.reg
      ret %1 : !riscv.reg
  }]

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

@[simp_denote]
def add_shl_moreOneUse_sh1add := [LV| {
    ^entry (%a: i32):
    %0 = llvm.mlir.constant (1) : i32
    %1 = llvm.or %a, %0 : i32
    %2 = llvm.shl %1, %0 : i32
    %3 = llvm.add %2, %1 : i32
    llvm.return %3 : i32
  }]

def not_signbit_splat_mask2_before := [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 %2, %arg108 : i16
  "llvm.return"(%3) : (i16) -> ()
}
]

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

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

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

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

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

def orcond_before := [llvm|
{
^0(%arg164 : i1, %arg165 : i1, %arg166 : i8, %arg167 : i8, %arg168 : i8):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg164, %0, %arg165) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = "llvm.select"(%arg164, %arg166, %arg167) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = "llvm.select"(%1, %2, %arg168) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def llvm_const_lower_riscv_li6 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM6, rhs:= liRiscv6,
   correct := by admit /- proof elided -/

def PR28476_before := [llvm|
{
^0(%arg8 : i32, %arg9 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.icmp "ne" %arg8, %0 : i32
  %3 = llvm.icmp "ne" %arg9, %0 : i32
  %4 = llvm.and %2, %3 : i1
  %5 = llvm.zext %4 : i1 to i32
  %6 = llvm.xor %5, %1 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

instance : ToString (MOp.BinaryOp) where
  toString := toStringWithFlags

def add? {w : Nat} (x y : BitVec w) : IntW w :=
  .value <| x + y

List.flatten in Init.Prelude

Int.instAdd in Init.Data.Int.Basic

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

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

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

@[simp_denote]
def lshr {Γ : Ctxt _} (w : ℕ) (l r : Nat)
    (lp : (Γ[l]? = some (InstCombine.MTy.bitvec (ConcreteOrMVar.concrete w)))
      := by admit /- proof elided -/
      )
    (rp : (Γ[r]? = some (InstCombine.MTy.bitvec (ConcreteOrMVar.concrete w)))
      := by admit /- proof elided -/
      ) :
    Expr InstCombine.LLVM Γ .pure (LLVM.Ty.bitvec w) :=
  Expr.mk
    (op := InstCombine.MOp.lshr w)
    (eff_le := by admit /- proof elided -/
    )
    (ty_eq := rfl)
    (args := .cons ⟨l, lp⟩ <| .cons ⟨r, rp⟩ .nil)
    (regArgs := .nil)

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

def andn_or_cmp_4_after := [llvm|
{
^0(%arg161 : i32, %arg162 : i32, %arg163 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.icmp "ne" %arg161, %arg162 : i32
  %2 = llvm.icmp "ugt" %arg163, %0 : i32
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def MatchArgResult.isTotal_of
    (map : MatchArgResult lets matchLets vs ws mapIn)
    (hvars : ∀ t (v : Var Δ_in t), ⟨t, v⟩ ∈ matchLets.varsOfVec ws) :
    map.val.IsTotal :=

def test15_after := [llvm|
{
^0(%arg40 : i32, %arg41 : i32):
  %0 = llvm.mlir.constant(1431655766 : i32) : i32
  %1 = llvm.or %arg40, %0 : i32
  %2 = llvm.sub %arg41, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def negative_with_nonuniform_bad_mask_logical_before := [llvm|
{
^0(%arg14 : i32):
  %0 = llvm.mlir.constant(1711276033 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(128 : i32) : i32
  %3 = llvm.mlir.constant(256 : i32) : i32
  %4 = llvm.mlir.constant(false) : i1
  %5 = llvm.and %arg14, %0 : i32
  %6 = llvm.icmp "eq" %5, %1 : i32
  %7 = llvm.add %arg14, %2 : i32
  %8 = llvm.icmp "ult" %7, %3 : i32
  %9 = "llvm.select"(%6, %8, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%9) : (i1) -> ()
}
]

def main4b_logical_after := [llvm|
{
^0(%arg131 : i32):
  %0 = llvm.mlir.constant(23 : i32) : i32
  %1 = llvm.and %arg131, %0 : i32
  %2 = llvm.icmp "ne" %1, %0 : i32
  %3 = llvm.zext %2 : i1 to i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def and_xor_not_common_op_after := [llvm|
{
^0(%arg686 : i32, %arg687 : i32):
  %0 = llvm.and %arg686, %arg687 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def test_before := [llvm|
{
^0(%arg0 : i64):
  %0 = llvm.trunc %arg0 : i64 to i32
  %1 = llvm.zext %0 : i32 to i64
  "llvm.return"(%1) : (i64) -> ()
}
]

def t1_before := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(24 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : i32) : i32
  %2 = llvm.zext %arg11 : i8 to i32
  %3 = llvm.shl %2, %0 : i32
  %4 = llvm.and %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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 PR42691_2_after := [llvm|
{
^0(%arg341 : i32):
  %0 = llvm.mlir.constant(-2 : i32) : i32
  %1 = llvm.icmp "sgt" %arg341, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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 scalar_i32_lshr_and_negC_eq_X_is_constant1_after := [llvm|
{
^0(%arg9 : i32):
  %0 = llvm.mlir.constant(12345 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.lshr %0, %arg9 : i32
  %3 = llvm.icmp "ult" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

RV64.sh3add in RISCV.Instructions

def test_ult_after := [llvm|
{
^0(%arg6 : i32, %arg7 : i16):
  %0 = llvm.sext %arg7 : i16 to i32
  %1 = llvm.icmp "ult" %arg6, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

instance [ToMessageData α] : ToMessageData (BoolExpr α) where
  toMessageData := go
  where
    go : BoolExpr α → MessageData
    | .literal a => toMessageData a
    | .const b => toMessageData b
    | .not x => "!" ++ go x
    | .gate g x y => "(" ++ go x ++ " " ++ g.toString ++ " " ++ go y ++ ")"
    | .ite d l r => "(if " ++ go d ++ " " ++ go l ++ " " ++ go r ++ ")"


deriving instance Hashable for BVBinPred
deriving instance BEq for BVBinPred
deriving instance DecidableEq for BVBinPred

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

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

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

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

def bools_before := [llvm|
{
^0(%arg51 : i1, %arg52 : i1, %arg53 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg53, %0 : i1
  %2 = llvm.and %1, %arg51 : i1
  %3 = llvm.and %arg53, %arg52 : i1
  %4 = llvm.or %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

OrOp in Init.Prelude

HShiftLeft in Init.Prelude

def castLe (i : Inputs ι n) (hn : n ≤ m) : Inputs ι m where
  ix := ⟨i.ix, by admit /- proof elided -/
  ⟩
  input := i.input

def castCtxt (h_eq : Γ = Δ) : Γ.Var ty → Δ.Var ty
  | ⟨i, h⟩ => ⟨i, h_eq ▸ h⟩

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

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

def sel_false_val_is_a_masked_shl_of_true_val1_before := [llvm|
{
^0(%arg10 : i32, %arg11 : i64):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.and %arg10, %0 : i32
  %4 = llvm.shl %3, %1 overflow<nsw,nuw> : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.icmp "eq" %3, %2 : i32
  %7 = llvm.ashr %arg11, %5 : i64
  %8 = "llvm.select"(%6, %arg11, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

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

def or_signbit_select_lshr_before := [llvm|
{
^0(%arg26 : i32, %arg27 : i1):
  %0 = llvm.mlir.constant(-65536 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.or %arg26, %0 : i32
  %3 = "llvm.select"(%arg27, %2, %arg26) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.lshr %3, %1 : i32
  "llvm.return"(%4) : (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 slt_zero_ne_ne_0_after := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.icmp "sgt" %arg5, %0 : i32
  "llvm.return"(%1) : (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 sge_smin3_before := [llvm|
{
^0(%arg75 : i32, %arg76 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.add %arg75, %0 : i32
  %2 = llvm.icmp "slt" %1, %arg76 : i32
  %3 = "llvm.select"(%2, %1, %arg76) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.icmp "sle" %1, %3 : 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 test_add_nuw_nsw__all_are_safe_after := [llvm|
{
^0(%arg47 : i32):
  %0 = llvm.mlir.constant(1073741823 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.and %arg47, %0 : i32
  %3 = llvm.add %2, %1 overflow<nsw,nuw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def positive_samevar_shlnsw_ashrexact_before := [llvm|
{
^0(%arg37 : i8, %arg38 : i8):
  %0 = llvm.ashr exact %arg37, %arg38 : i8
  %1 = llvm.shl %0, %arg38 overflow<nsw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def not_and_and_or_not_or_or_commute3_before := [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.or %2, %arg232 : i32
  %4 = llvm.or %3, %arg234 : i32
  %5 = llvm.xor %4, %1 : i32
  %6 = llvm.xor %arg232, %1 : i32
  %7 = llvm.and %2, %6 : i32
  %8 = llvm.and %7, %arg234 : i32
  %9 = llvm.or %8, %5 : i32
  "llvm.return"(%9) : (i32) -> ()
}
]

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

def and_signbit_select_ashr_before := [llvm|
{
^0(%arg14 : i32, %arg15 : i1):
  %0 = llvm.mlir.constant(-65536 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.and %arg14, %0 : i32
  %3 = "llvm.select"(%arg15, %2, %arg14) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.ashr %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

def test2_after := [llvm|
{
^0(%arg18 : i8):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(3 : i32) : i32
  %2 = llvm.zext %arg18 : i8 to i32
  %3 = llvm.add %2, %0 overflow<nsw,nuw> : i32
  %4 = llvm.lshr %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def xor_ashr_not_fail_lshr_ashr_before := [llvm|
{
^0(%arg21 : i8, %arg22 : i8, %arg23 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.lshr %arg21, %arg23 : i8
  %2 = llvm.ashr %arg22, %arg23 : i8
  %3 = llvm.xor %2, %0 : i8
  %4 = llvm.xor %1, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

def sext_ule_sext_before := [llvm|
{
^0(%arg119 : i1, %arg120 : i8):
  %0 = llvm.mul %arg120, %arg120 : i8
  %1 = llvm.sext %arg119 : i1 to i16
  %2 = llvm.sext %0 : i8 to i16
  %3 = llvm.icmp "ule" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

def shl_lshr_and_exact_after := [llvm|
{
^0(%arg88 : i32, %arg89 : i32, %arg90 : i32):
  %0 = llvm.lshr %arg90, %arg89 : i32
  %1 = llvm.and %0, %arg88 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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 foo_after := [llvm|
{
^0(%arg54 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(20 : i32) : i32
  %2 = llvm.mlir.constant(-20 : i32) : i32
  %3 = llvm.icmp "sgt" %arg54, %0 : i32
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %5 = llvm.add %arg54, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

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 test1_before := [llvm|
{
^0(%arg6 : i8, %arg7 : i8):
  %0 = llvm.zext %arg6 : i8 to i64
  %1 = llvm.zext %arg7 : i8 to i64
  %2 = llvm.add %0, %1 : i64
  %3 = llvm.trunc %2 : i64 to i8
  "llvm.return"(%3) : (i8) -> ()
}
]

instance {Γ : Context Ty} [DecidableEq Ty] {v ty} :
    Decidable (Γ.hasType v ty) :=

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

def trunc_equality_nuw_before := [llvm|
{
^0(%arg44 : i16, %arg45 : i16):
  %0 = llvm.trunc %arg44 overflow<nuw> : i16 to i8
  %1 = llvm.trunc %arg45 overflow<nuw> : i16 to i8
  %2 = llvm.icmp "eq" %0, %1 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

Lean.Expr.const in Lean.Expr

def resNames : List SSAVal :=
  op.res.map Prod.fst

def scalar_i16_signbit_lshr_and_eq_before := [llvm|
{
^0(%arg33 : i16, %arg34 : i16):
  %0 = llvm.mlir.constant(-32768 : i16) : i16
  %1 = llvm.mlir.constant(0 : i16) : i16
  %2 = llvm.lshr %0, %arg34 : i16
  %3 = llvm.and %2, %arg33 : i16
  %4 = llvm.icmp "eq" %3, %1 : i16
  "llvm.return"(%4) : (i1) -> ()
}
]

def HVector.toVarSet : {l : List d.Ty} → (T : HVector (Var Γ) l) → VarSet Γ
  | [], .nil => ∅
  | _::_, .cons v vs => insert ⟨_, v⟩ vs.toVarSet

def demorgan_and_apint3_before := [llvm|
{
^0(%arg54 : i65, %arg55 : i65):
  %0 = llvm.mlir.constant(-1 : i65) : i65
  %1 = llvm.xor %arg54, %0 : i65
  %2 = llvm.xor %0, %arg55 : i65
  %3 = llvm.and %1, %2 : i65
  "llvm.return"(%3) : (i65) -> ()
}
]

def eq_21_after := [llvm|
{
^0(%arg124 : i32, %arg125 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.lshr %arg124, %0 : i32
  %2 = llvm.trunc %1 : i32 to i16
  %3 = llvm.lshr %arg125, %0 : i32
  %4 = llvm.trunc %3 : i32 to i16
  %5 = llvm.icmp "eq" %2, %4 : i16
  "llvm.return"(%5) : (i1) -> ()
}
]

def not_not_cmp_before := [llvm|
{
^0(%arg147 : i32, %arg148 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg147, %0 : i32
  %2 = llvm.xor %arg148, %0 : i32
  %3 = llvm.icmp "slt" %1, %2 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def llvm_add_lower_riscv_noflags_8 : LLVMPeepholeRewriteRefine 8 [Ty.llvm (.bitvec 8), Ty.llvm (.bitvec 8)] where
  lhs:= add_llvm_no_flags_8
  rhs:= add_riscv_8

def visitADD_Sameop : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 1)] where
  lhs := [LV| {
    ^entry (%x: i1):
      %c = llvm.mlir.constant (1) : i64
      %0 = llvm.sext %x : i1 to i64
      %1 = llvm.add %0, %c : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i1):
      %0 = llvm.not %x : i1
      %1 = llvm.zext %0 : i1 to i64
      llvm.return %1 : i64
  }]

def positive_trunc_signbit_before := [llvm|
{
^0(%arg41 : i32):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(128 : i32) : i32
  %2 = llvm.mlir.constant(256 : i32) : i32
  %3 = llvm.trunc %arg41 : i32 to i8
  %4 = llvm.icmp "sgt" %3, %0 : i8
  %5 = llvm.add %arg41, %1 : i32
  %6 = llvm.icmp "ult" %5, %2 : i32
  %7 = llvm.and %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

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

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

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

List.Vector.nil in Mathlib.Data.Vector.Defs
</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.mod_eq_of_lt in Init.Data.Nat.Div.Basic
Nat.add_comm in Init.Data.Nat.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

@[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)

@[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 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))

theorem select_replace_one_use_proof : select_replace_one_use_before ⊑ select_replace_one_use_after

theorem select_icmp_eq_and_1_0_or_2_proof : select_icmp_eq_and_1_0_or_2_before ⊑ select_icmp_eq_and_1_0_or_2_after

theorem test8_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬32#128 ≥ ↑128 →
    True ∧ zeroExtend 64 x_1 <<< 32#64 >>> 32#64 ≠ zeroExtend 64 x_1 ∨
        32#64 ≥ ↑64 ∨ True ∧ (zeroExtend 64 x_1 <<< 32#64 &&& zeroExtend 64 x != 0) = true →
      False

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 p0_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x_1 ≥ ↑8 → ofBool ((-1#8) <<< x_1 ^^^ -1#8 <ᵤ x) = ofBool (x >>> x_1 != 0#8)

theorem test32_proof : test32_before ⊑ test32_after

theorem icmp_and_ashr_multiuse_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(4#32 ≥ ↑32 ∨ 4#32 ≥ ↑32) →
    ofBool (x.sshiftRight' 4#32 &&& 15#32 != 14#32) &&& ofBool (x.sshiftRight' 4#32 &&& 31#32 != 27#32) =
      ofBool (x &&& 240#32 != 224#32) &&& ofBool (x &&& 496#32 != 432#32)

theorem test35_with_trunc_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬ofBool (0#32 ≤ₛ truncate 32 x) = 1#1 → ofBool (x &&& 2147483648#64 == 0#64) = 1#1 → 100#32 = 60#32

theorem n7_proof : n7_before ⊑ n7_after

@[simp] theorem MatchVarM.liftM_eq_some_iff (x? : Option α) :
    (liftM x? : no_index MatchVarM Δ Γ α) mapIn = some (x, mapOut)
    ↔ x? = some x ∧ mapIn = mapOut

theorem select_icmp_ne_0_and_4096_xor_32_thm.extracted_1._4 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (0#32 != x_1 &&& 4096#32) = 1#1 → ¬7#32 ≥ ↑32 → x ^^^ 32#32 = x_1 >>> 7#32 &&& 32#32 ^^^ x ^^^ 32#32

theorem test_ashr__exact_is_unsafe_proof : test_ashr__exact_is_unsafe_before ⊑ test_ashr__exact_is_unsafe_after

theorem uge_or_not_max_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.uge e_1 e) (const? 1 1) (icmp IntPred.ne e_1 (const? 8 (-1))) ⊑ const? 1 1

theorem test_shl_nuw_nsw__nuw_is_safe_thm.extracted_1._3 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 1073741822#32 == 0#32) = 1#1 →
    ¬(True ∧ ((x_1 &&& 1073741822#32) <<< 2#32).sshiftRight' 2#32 ≠ x_1 &&& 1073741822#32 ∨
          True ∧ (x_1 &&& 1073741822#32) <<< 2#32 >>> 2#32 ≠ x_1 &&& 1073741822#32 ∨
            2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& 1073741822#32) <<< 2#32) ≥ ↑64) →
      2#32 ≥ ↑32 ∨
          True ∧ (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)).msb = true ∨
            zeroExtend 64 (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)) ≥ ↑64 →
        False

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

theorem bools2_logical_commute0_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → x ^^^ 1#1 = 1#1 → 0#1 = 1#1 → False

theorem ashr_mul_times_3_div_2_exact_proof : ashr_mul_times_3_div_2_exact_before ⊑ ashr_mul_times_3_div_2_exact_after

theorem ashr_slt_noexact_proof : ashr_slt_noexact_before ⊑ ashr_slt_noexact_after

theorem e_1698 :
     - 1 * ((a &&& b) ||| (b ^^^ c)) - 7 * (b &&& (a |||  ~~~c)) + 1 * (b ^^^ (a ||| c)) - 1 * (c &&& (a ^^^ b)) + 4 * (b &&& (a ^^^ c)) - 1 *  ~~~(a ^^^ c) - 1 * (a ^^^ (b &&& c)) - 6 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) + 7 *  ~~~(a &&& (b ^^^ c)) + 3 *  ~~~(a &&& (b &&& c)) - 1 * (c &&&  ~~~(a &&&  ~~~b)) - 2 * ((a &&& c) ^^^  ~~~(b &&&  ~~~c)) + 2 *  ~~~(a |||  ~~~c) - 5 * (b ^^^ (a &&&  ~~~c)) + 11 * ((a ||| b) &&& (b ^^^ c)) + 1 *  ~~~(a &&&  ~~~b) - 1 * (c &&& (a |||  ~~~b)) - 2 * ((a &&& c) ^^^  ~~~(a ^^^ ( ~~~b &&& c))) + 4 * (b &&&  ~~~(a ^^^ c)) - 7 * (b ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 6 *  ~~~(a ^^^ ( ~~~b &&& c)) + 1 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) + 23 *  ~~~(a ||| (b ||| c)) + 12 *  ~~~(a ||| ( ~~~b ||| c)) + 2 *  ~~~( ~~~a ||| (b ||| c)) + 7 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 2 * ( ~~~a &&& ( ~~~b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) + 22 * (a &&& (b &&& c)) =  - 1 * (a &&& ( ~~~b ||| c)) + 11 * (b ^^^ ( ~~~a &&& ( ~~~b ||| c)))

theorem test2_thm (e e_1 : IntW 32) :
  zext 32 (icmp IntPred.eq (LLVM.and e_1 (const? 32 8)) (LLVM.and e (const? 32 8))) ⊑
    LLVM.xor (LLVM.and (lshr (LLVM.xor e_1 e) (const? 32 3)) (const? 32 1)) (const? 32 1)

theorem ashrslt_03_07_exact_proof : ashrslt_03_07_exact_before ⊑ ashrslt_03_07_exact_after

theorem t0_thm (e : IntW 64) : sub (const? 64 0) (lshr e (const? 64 63)) ⊑ ashr e (const? 64 63)

theorem src_is_mask_p2_m1_proof : src_is_mask_p2_m1_before ⊑ src_is_mask_p2_m1_after

theorem lshr_and_thm (e e_1 : IntW 8) :
  shl (LLVM.and (lshr e_1 (const? 8 6)) (LLVM.srem e (const? 8 42))) (const? 8 6) ⊑
    LLVM.and e_1 (shl (LLVM.srem e (const? 8 42)) (const? 8 6))

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

theorem e_90 :
     - 5 *  ~~~(x &&& y) - 7 * (x ||| y) + 3 *  ~~~(x ||| y) + 10 *  ~~~(x |||  ~~~y) + 10 * (x &&&  ~~~y) =  - 5 * (x &&& y) - 2 *  ~~~(x &&&  ~~~x)

lemma Predicate.evalFin_eq_eval (p : Predicate)
   (varsList : List BitStream) (varsFin : Fin p.arity → BitStream)
   (hvars : ∀ (i : Fin p.arity), varsList.getD i default = (varsFin i)) :
    Predicate.evalFin p varsFin  = Predicate.eval p varsList

theorem mul_of_udiv_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.umod 12#8 ≠ 0 ∨ 12#8 = 0) → True ∧ x >>> 1#8 <<< 1#8 ≠ x ∨ 1#8 ≥ ↑8 → False

theorem nonexact_ashr_eq_noexactlog_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬x ≥ ↑8 → ofBool ((BitVec.ofInt 8 (-90)).sshiftRight' x == BitVec.ofInt 8 (-30)) = 0#1

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

theorem sgt_smax4_proof : sgt_smax4_before ⊑ sgt_smax4_after

theorem p0_proof : p0_before ⊑ p0_after

theorem tryFactorization_add_mul_nuw_mul_var_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_2.umulOverflow x_1 = true ∨ True ∧ x_2.umulOverflow x = true) → x_2 * x_1 + x_2 * x = x_2 * (x_1 + x)

theorem ashr_lshr_shift_base_mismatch_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (0#32 ≤ₛ x_2) = 1#1 → ¬x_1 ≥ ↑32 → ¬ofBool (x_2 <ₛ 0#32) = 1#1 → x.sshiftRight' x_1 = x_2 >>> x_1

theorem add_mask_ashr28_non_pow2_i32_thm (e : IntW 32) :
  add (LLVM.and (ashr e (const? 32 28)) (const? 32 9)) (ashr e (const? 32 28)) ⊑
    add (LLVM.and (ashr e (const? 32 28)) (const? 32 9)) (ashr e (const? 32 28))
      { «nsw» := true, «nuw» := false }

theorem t1_sshr_proof : t1_sshr_before ⊑ t1_sshr_after

theorem n3_constmask_samemask_thm (e e_1 : IntW 32) :
  LLVM.and (LLVM.or e_1 (const? 32 (-65281))) (LLVM.or e (const? 32 (-65281))) ⊑
    LLVM.or (LLVM.and e_1 e) (const? 32 (-65281))

theorem n2_proof : n2_before ⊑ n2_after

theorem or_to_nxor1_proof : or_to_nxor1_before ⊑ or_to_nxor1_after

theorem shl_add_and_proof : shl_add_and_before ⊑ shl_add_and_after

theorem substitute_constant_and_eq_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == 42#8) &&& ofBool (x_1 == x) = ofBool (x_1 == 42#8) &&& ofBool (x == 42#8)

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

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

theorem icmp_mul_nsw_slt_neg_proof : icmp_mul_nsw_slt_neg_before ⊑ icmp_mul_nsw_slt_neg_after

theorem logical_or_logical_or_icmps_comm3_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 8),
  ¬x_1 ≥ ↑8 →
    ofBool (x_2 &&& 1#8 <<< x_1 == 0#8) = 1#1 ∨ 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 main5e_like_logical_thm.extracted_1._7 : ∀ (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 → 0#32 = zeroExtend 32 (ofBool (x_2 &&& x != x_2))

theorem lshrugt_01_07_thm (e : IntW 4) : icmp IntPred.ugt (lshr e (const? 4 1)) (const? 4 7) ⊑ const? 1 0

theorem scalar_i8_lshr_and_negC_eq_proof : scalar_i8_lshr_and_negC_eq_before ⊑ scalar_i8_lshr_and_negC_eq_after

theorem test_proof : test_before ⊑ test_after

theorem p3_sgt_thm (e e_1 : IntW 32) :
  select (icmp IntPred.sgt e_1 (const? 32 65534)) e (const? 32 65535) ⊑
    select (icmp IntPred.slt e_1 (const? 32 65535)) (const? 32 65535) e

theorem test15_proof : test15_before ⊑ test15_after

theorem uge_umin3_proof : uge_umin3_before ⊑ uge_umin3_after

theorem e_2086 :
    2 * (f &&& (d ^^^ e)) - 1 * (d &&& (e ^^^ f)) - 1 * (d |||  ~~~f) + 1 * (e ||| f) - 1 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) + 11 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 2 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 6 * ( ~~~f |||  ~~~(d ^^^ e)) + 11 * (e ^^^  ~~~(d &&& f)) + 3 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 6 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) + 2 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 11 * (e ||| (d &&& f)) - 1 *  ~~~(e ^^^ f) + 3 *  ~~~(d ||| e) - 2 *  ~~~( ~~~d ||| (e ^^^ f)) + 4 * (d &&& ( ~~~e ||| f)) + 5 * (d ||| e) + 5 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) + 1 * (f ^^^ ( ~~~d ||| (e &&& f))) - 5 * (e &&& f) - 11 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 5 * (f ^^^ (d ||| (e ||| f))) + 2 * (d ||| ( ~~~e &&& f)) + 2 * (d ^^^ ( ~~~e &&& f)) + 1 *  ~~~e - 6 *  ~~~(d &&& ( ~~~e &&& f)) - 2 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) + 7 *  ~~~(d ||| (e ^^^ f)) - 6 * (d ^^^ e) - 1 * (d ^^^ f) + 4 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 8 *  ~~~(d ||| (e ||| f)) + 29 *  ~~~(d ||| ( ~~~e ||| f)) - 8 *  ~~~( ~~~d ||| (e ||| f)) + 33 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 15 * ( ~~~d &&& ( ~~~e &&& f)) + 7 * ( ~~~d &&& (e &&& f)) - 2 * (d &&& ( ~~~e &&& f)) - 9 * (d &&& (e &&& f)) = 2 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f)))

theorem add_or_and_proof : add_or_and_before ⊑ add_or_and_after

theorem e_516 :
     - 1 * (x |||  ~~~y) + 2 * x - 11 *  ~~~(x &&& y) + 7 * (x ||| y) - 7 *  ~~~x + 19 *  ~~~(x ||| y) + 10 *  ~~~(x |||  ~~~y) + 3 * (x &&&  ~~~y) - 9 * (x &&& y) =  - 1 * y

theorem t9_ashr_exact_flag_preservation_proof : t9_ashr_exact_flag_preservation_before ⊑ t9_ashr_exact_flag_preservation_after

theorem land_land_left2_proof : land_land_left2_before ⊑ land_land_left2_after

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

theorem test_imply_not2_thm.extracted_1._3 : ∀ (x : BitVec 1) (x_1 : BitVec 32),
  ofBool (x_1 == 0#32) = 1#1 → ofBool (x_1 != 0#32) = 1#1 → x ||

theorem negative_not_next_power_of_two_proof : negative_not_next_power_of_two_before ⊑ negative_not_next_power_of_two_after

theorem icmp_eq_x_invertable_y2_proof : icmp_eq_x_invertable_y2_before ⊑ icmp_eq_x_invertable_y2_after

theorem t4_ugt_slt_65536_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (65535#32 <ᵤ x_1) = 1#1 → ofBool (x_1 <ₛ 65536#32) = 1#1 → ofBool (65535#32 <ₛ x_1) = 1#1 → False

theorem n2_badmask_proof : n2_badmask_before ⊑ n2_badmask_after

theorem not_and_and_not_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (LLVM.and (LLVM.sdiv (const? 32 42) e_2) (LLVM.xor e_1 (const? 32 (-1)))) (LLVM.xor e (const? 32 (-1))) ⊑
    LLVM.and (LLVM.sdiv (const? 32 42) e_2) (LLVM.xor (LLVM.or e_1 e) (const? 32 (-1)))

theorem e_703 :
    11 * y - 1 * x - 3 *  ~~~(x &&&  ~~~x) - 1 *  ~~~x + 1 *  ~~~(x &&& y) + 7 * (x |||  ~~~y) + 11 * (x ||| y) - 3 *  ~~~(x ||| y) - 14 * (x &&&  ~~~y) - 25 * (x &&& y) = 1 *  ~~~y + 19 *  ~~~(x |||  ~~~y)

theorem e_1731 :
    3 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 3 * (c ^^^ ( ~~~a ||| (b ||| c))) + 3 * (c ^^^  ~~~(a &&&  ~~~b)) - 1 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) - 5 *  ~~~( ~~~a &&& (b &&& c)) + 11 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 2 *  ~~~(a &&&  ~~~b) - 11 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) - 1 *  ~~~(a ^^^ (b ^^^ c)) - 1 * ( ~~~a &&& (b ||| c)) - 3 * (b ^^^  ~~~(a &&&  ~~~c)) - 11 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) - 6 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) - 6 * ((a &&& c) ^^^ (a ^^^ (b &&& c))) + 7 * (b ^^^ ( ~~~a ||| (b &&& c))) - 11 * ((a ^^^ b) |||  ~~~(a ^^^ c)) - 5 * ( ~~~b &&&  ~~~(a ^^^ c)) + 3 * (b &&& (a ^^^ c)) + 3 * (b ^^^ ( ~~~a &&& (b ^^^ c))) - 1 *  ~~~( ~~~a ||| ( ~~~b &&& c)) - 2 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) - 1 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) + 1 * ((a ||| b) &&&  ~~~(b ^^^ c)) + 6 *  ~~~(a ||| (b ||| c)) + 46 *  ~~~(a ||| ( ~~~b ||| c)) + 32 *  ~~~( ~~~a ||| (b ||| c)) + 9 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 21 * ( ~~~a &&& ( ~~~b &&& c)) + 17 * ( ~~~a &&& (b &&& c)) + 16 * (a &&& ( ~~~b &&& c)) + 29 * (a &&& (b &&& c)) = 6 *  ~~~(a |||  ~~~c)

theorem reassoc_x2_mul_nuw_proof : reassoc_x2_mul_nuw_before ⊑ reassoc_x2_mul_nuw_after

theorem lshr_add_xor_fail_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(1#8 ≥ ↑8 ∨ 1#8 ≥ ↑8) → 1#8 ≥ ↑8 ∨ 1#8 ≥ ↑8 ∨ True ∧ (x >>> 1#8).uaddOverflow 123#8 = true → False

theorem xor_sub :
    [llvm(w)| {
  ^bb0(%X : _, %Y : _):
    %v1 = llvm.sub %X, %X
    %r = llvm.xor %v1, %Y
    llvm.return %r
  }] ⊑  [llvm(w)| {
  ^bb0(%X : _, %Y : _):
    llvm.return %Y
  }]

theorem ashr_ult_2_proof : ashr_ult_2_before ⊑ ashr_ult_2_after

theorem n6_proof : n6_before ⊑ n6_after

theorem test_zext4_thm.extracted_1._4 : ∀ (x x_1 : BitVec 1),
  ¬x_1 = 1#1 → x_1 ^^^ 1#1 = 1#1 → 1#32 = zeroExtend 32 1#1

theorem uge_and_max_commute_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.eq e_1 (const? 8 (-1))) (icmp IntPred.uge e_1 e) ⊑
    icmp IntPred.eq e_1 (const? 8 (-1))

theorem test55_thm.extracted_1._1 : ∀ (x : BitVec 32),
  True ∧ (truncate 16 x &&& 7224#16 &&& BitVec.ofInt 16 (-32574) != 0) = true → False

theorem demorgan_nor_use2c_proof : demorgan_nor_use2c_before ⊑ demorgan_nor_use2c_after

theorem lshrugt_03_13_exact_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ x >>> 3#4 <<< 3#4 ≠ x ∨ 3#4 ≥ ↑4) → ofBool (BitVec.ofInt 4 (-3) <ᵤ x >>> 3#4) = 0#1

theorem sle_swap_or_min_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x ≤ₛ x_1) = 1#1 → ofBool (x == BitVec.ofInt 8 (-128)) = ofBool (x ≤ₛ x_1)

theorem mul_unkV_evenC_ne_proof : mul_unkV_evenC_ne_before ⊑ mul_unkV_evenC_ne_after

theorem not_not_cmp_proof : not_not_cmp_before ⊑ not_not_cmp_after

theorem udiv_shl_pair2_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ (x_2 <<< x_1).sshiftRight' x_1 ≠ x_2 ∨
        True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑32 ∨ True ∧ x_2 <<< x >>> x ≠ x_2 ∨ x ≥ ↑32 ∨ x_2 <<< x = 0) →
    ¬(True ∧ (1#32 <<< x_1).sshiftRight' x_1 ≠ 1#32 ∨ True ∧ 1#32 <<< x_1 >>> x_1 ≠ 1#32 ∨ x_1 ≥ ↑32 ∨ x ≥ ↑32) →
      x_2 <<< x_1 / x_2 <<< x = 1#32 <<< x_1 >>> x

theorem R.fromTensorFinsupp_coeffs (coeffs : List Int) :
  Polynomial.coeff (fromTensorFinsupp q coeffs) i = ↑(List.getD coeffs i 0)

theorem foo_proof : foo_before ⊑ foo_after

theorem trunc_shl_shl_var_proof : trunc_shl_shl_var_before ⊑ trunc_shl_shl_var_after

theorem test55_thm (e : IntW 32) :
  sext 64 (LLVM.and (LLVM.or (trunc 16 e) (const? 16 (-32574))) (const? 16 (-25350))) ⊑
    sext 64 (LLVM.or (LLVM.and (trunc 16 e) (const? 16 7224)) (const? 16 (-32574)) { «disjoint» := true })

theorem ashrslt_03_09_proof : ashrslt_03_09_before ⊑ ashrslt_03_09_after

theorem reassoc_add_nuw_proof : reassoc_add_nuw_before ⊑ reassoc_add_nuw_after

theorem icmp_shl_ule_2_proof : icmp_shl_ule_2_before ⊑ icmp_shl_ule_2_after

@[simp] theorem carry'_zero
    (initCarry : Bool) (x y : BitStream) :
  (carry' initCarry x y 0) = initCarry

theorem test_negative_nuw_and_signed_pred_proof : test_negative_nuw_and_signed_pred_before ⊑ test_negative_nuw_and_signed_pred_after

theorem ult_umin1_thm (e e_1 : IntW 32) :
  icmp IntPred.ult (select (icmp IntPred.ult e_1 e) e_1 e) e_1 ⊑ icmp IntPred.ult e e_1

theorem t4_ugt_slt_65536_thm.extracted_1._5 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (65535#32 <ᵤ x_1) = 1#1 → ¬ofBool (65535#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ 0#32) = 1#1 → x_1 = x

theorem PR44545_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x == 0#32) = 1#1 →
    ¬(True ∧ (truncate 16 0#32).saddOverflow (-1#16) = true) → truncate 16 0#32 + -1#16 = -1#16

theorem t4_const_after_fold_lshr_shl_ne_thm (e e_1 e_2 : IntW 32) :
  icmp IntPred.ne (LLVM.and (shl e_2 (sub (const? 32 32) e_1)) (lshr e (add e_1 (const? 32 (-1))))) (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and (lshr e (const? 32 31)) e_2) (const? 32 0)

theorem shl_or_thm.extracted_1._2 : ∀ (x x_1 : BitVec 16),
  ¬((42#16 == 0 || 16 != 1 && x_1 == intMin 16 && 42#16 == -1) = true ∨ 5#16 ≥ ↑16 ∨ 7#16 ≥ ↑16) →
    ¬(12#16 ≥ ↑16 ∨
          (42#16 == 0 || 16 != 1 && x_1 == intMin 16 && 42#16 == -1) = true ∨
            True ∧ (x_1.srem 42#16 <<< 7#16).sshiftRight' 7#16 ≠ x_1.srem 42#16 ∨ 7#16 ≥ ↑16) →
      (x_1.srem 42#16 ||| x <<< 5#16) <<< 7#16 = x <<< 12#16 ||

theorem shl_or_proof : shl_or_before ⊑ shl_or_after

theorem scalar_i32_lshr_and_signbit_ne_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x ≥ ↑32 → ofBool (x_1 >>> x &&& BitVec.ofInt 32 (-2147483648) != 0#32) = ofBool (x_1 >>> x <ₛ 0#32)

theorem mul_four (x : BitVec w) : 4 * x = x + x + x + x

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

theorem positive_samevar_lshrexact_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ x_1 >>> x <<< x ≠ x_1 ∨ x ≥ ↑8 ∨ x ≥ ↑8) → x_1 >>> x <<< x = x_1

theorem demorgan_and_apint1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 477),
  (x_1 ^^^ -1#477) &&& (x ^^^ -1#477) = (x_1 ||| x) ^^^ -1#477

theorem t0_thm.extracted_1._16 : ∀ (x x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  ¬x_3 ^^^ 1#1 = 1#1 → x_3 = 1#1 → 0#1 = 1#1 → x_1 = x

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

theorem is_ascii_alphabetic_proof : is_ascii_alphabetic_before ⊑ is_ascii_alphabetic_after

theorem test8_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬32#128 ≥ ↑128 →
    True ∧ zeroExtend 64 x_1 <<< 32#64 >>> 32#64 ≠ zeroExtend 64 x_1 ∨
        32#64 ≥ ↑64 ∨ True ∧ (zeroExtend 64 x_1 <<< 32#64 &&& zeroExtend 64 x != 0) = true →
      False

theorem lshr_exact_add_nuw_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.uaddOverflow 1#32 = true ∨ True ∧ 4#32 >>> (x + 1#32) <<< (x + 1#32) ≠ 4#32 ∨ x + 1#32 ≥ ↑32) →
    True ∧ 2#32 >>> x <<< x ≠ 2#32 ∨ x ≥ ↑32 → False

theorem e_209 :
     - 2 * (x ||| y) - 3 *  ~~~(x &&&  ~~~y) + 3 *  ~~~y + 7 * y - 2 *  ~~~(x |||  ~~~y) - 1 * (x &&&  ~~~y) = 2 * (x &&& y)

theorem fold_sext_to_and_wrong5_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (signExtend 32 x &&& BitVec.ofInt 32 (-256) == 1#32) = 0#1

theorem test_mul__all_are_safe_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 255)) (const? 32 17)) (const? 32 153)
      (mul (LLVM.and e (const? 32 255)) (const? 32 9)) ⊑
    mul (LLVM.and e (const? 32 255)) (const? 32 9) { «nsw» := true, «nuw» := true }

theorem select_icmp_ne_0_and_4096_and_not_4096_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (0#32 != x_1 &&& 4096#32) = 1#1 →
    ¬ofBool (x_1 &&& 4096#32 == 0#32) = 1#1 → x &&& BitVec.ofInt 32 (-4097) = x

theorem t8_lshr_exact_flag_preservation_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1 >>> (32#32 - x) <<< (32#32 - x) ≠ x_1 ∨
        32#32 - x ≥ ↑32 ∨
          True ∧
              x_1 >>> (32#32 - x) >>> (x + BitVec.ofInt 32 (-2)) <<< (x + BitVec.ofInt 32 (-2)) ≠ x_1 >>> (32#32 - x) ∨
            x + BitVec.ofInt 32 (-2) ≥ ↑32) →
    True ∧ x_1 >>> 30#32 <<< 30#32 ≠ x_1 ∨ 30#32 ≥ ↑32 → False

theorem lshrult_03_14_exact_proof : lshrult_03_14_exact_before ⊑ lshrult_03_14_exact_after

theorem bools2_logical_commute1_and1_and2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  x_1 &&& x = 1#1 → x = 1#1 → 1#1 = x_1

theorem ashrslt_01_03_proof : ashrslt_01_03_before ⊑ ashrslt_01_03_after

theorem no_shift_xor_multiuse_cmp_thm.extracted_1._5 : ∀ (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 ||| x_3 &&& 4096#32 ^^^ 4096#32) * x

theorem lshr_pow2_ugt_proof : lshr_pow2_ugt_before ⊑ lshr_pow2_ugt_after

theorem e_876 :
     - 3 * (z ^^^ t) - 1 *  ~~~(z ^^^ t) - 6 *  ~~~(z &&&  ~~~t) + 1 *  ~~~t + 2 * (z &&&  ~~~t) + 7 * (z &&& t) =  - 6 *  ~~~(z ||| t) - 9 *  ~~~(z |||  ~~~t)

theorem and_or1_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 ^^^ 1#1 ||

theorem test35_thm.extracted_1._1 : ∀ (x : BitVec 32), True ∧ (0#32 - x &&& 240#32).msb = true → False

theorem e_1176 :
     - 5 * (z |||  ~~~t) + 4 *  ~~~(z ^^^ t) + 3 *  ~~~z + 1 *  ~~~(z &&&  ~~~t) + 1 *  ~~~(z &&& t) - 4 *  ~~~(z ||| t) - 4 *  ~~~(z |||  ~~~t) + 5 * (z &&&  ~~~t) =  - 1 * (z &&& t) + 1 * (z ||| t)

theorem shrink_and_proof : shrink_and_before ⊑ shrink_and_after

theorem masked_bit_clear_commute_proof : masked_bit_clear_commute_before ⊑ masked_bit_clear_commute_after

theorem main7b_logical_thm.extracted_1._4 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 == x &&& x_1) = 1#1 → ¬ofBool (x_1 != x &&& x_1) = 1#1 → ¬0#1 = 1#1 → False

theorem main6d_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 != 3#32) ||

@[simp]
theorem mkStateNeqCircuit_eq_false_iff {arity : Type _} {i : Nat}
  [DecidableEq arity] [Fintype arity] [Hashable arity]
  (p : FSM arity) (s t : p.α → Circuit (Vars p.α arity i)) :
  (∀ envBool, (mkStateNeqCircuit p s t).eval envBool = false) ↔
  (∀ (envBool : Vars p.α arity i → Bool), ∃ (a : p.α), (s a).eval envBool ≠ (t a).eval envBool)

theorem test6_proof : test6_before ⊑ test6_after

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

theorem shl_nsw_nuw_proof : shl_nsw_nuw_before ⊑ shl_nsw_nuw_after

theorem lshrugt_03_05_proof : lshrugt_03_05_before ⊑ lshrugt_03_05_after

theorem ashrsgt_02_11_exact_thm (e : IntW 4) :
  icmp IntPred.sgt (ashr e (const? 4 2) { «exact» := true }) (const? 4 (-5)) ⊑ const? 1 1

theorem test1_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬8#32 ≥ ↑32 →
    ¬8#16 ≥ ↑16 → truncate 16 (zeroExtend 32 x >>> 8#32 ||| zeroExtend 32 x * 5#32) = x >>> 8#16 ||

theorem e_793 :
     - 7 *  ~~~(z &&&  ~~~t) - 5 *  ~~~(z &&& t) + 5 *  ~~~(z ||| t) + 12 *  ~~~(z |||  ~~~t) + 5 * (z &&&  ~~~t) =  - 7 *  ~~~(z ^^^ t)

theorem e_1739 :
    1 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c))) + 2 * (b ^^^ (a ||| ( ~~~b &&& c))) + 3 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) - 5 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) - 1 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 4 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) + 5 * ((a &&& b) |||  ~~~(b |||  ~~~c)) - 1 *  ~~~a - 1 *  ~~~(a &&& (b &&& c)) - 1 * ((a ||| b) &&& (b ^^^ c)) + 7 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) + 11 * (c ^^^ (a &&& ( ~~~b ||| c))) + 5 * ( ~~~a ||| ( ~~~b &&& c)) - 7 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) - 7 * (b ^^^ ( ~~~a ||| (b &&& c))) + 3 * (c ^^^ (a ||| (b &&& c))) + 3 * (a ||| (b &&& c)) + 5 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c))) - 1 *  ~~~( ~~~a &&& (b &&& c)) - 2 * (b ^^^  ~~~(a ||| (b &&& c))) - 2 * (a &&&  ~~~b) + 1 * (c ||| (a &&& b)) + 1 * ((a &&& b) |||  ~~~(b ||| c)) + 4 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 2 * (b ^^^  ~~~(a |||  ~~~c)) - 1 * (b ^^^ (a &&&  ~~~c)) - 3 * (c ^^^ (a &&& b)) - 8 *  ~~~(a ||| (b ||| c)) - 24 *  ~~~( ~~~a ||| (b ||| c)) - 13 * ( ~~~a &&& ( ~~~b &&& c)) - 29 * ( ~~~a &&& (b &&& c)) - 19 * (a &&& ( ~~~b &&& c)) - 27 * (a &&& (b &&& c)) =  - 5 *  ~~~(a ||| ( ~~~b ||| c))

theorem zext_add_scalar_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → zeroExtend 32 x + 42#32 = 43#32

theorem test_srem_canonicalize_op0_thm (e e_1 : IntW 32) :
  LLVM.srem (sub (const? 32 0) e_1 { «nsw» := true, «nuw» := false }) e ⊑
    sub (const? 32 0) (LLVM.srem e_1 e) { «nsw» := true, «nuw» := false }

theorem lshrult_02_08_exact_proof : lshrult_02_08_exact_before ⊑ lshrult_02_08_exact_after

theorem e_295 :
     - 11 *  ~~~(x ^^^ y) - 3 *  ~~~y + 2 *  ~~~x + 2 * (x |||  ~~~y) + 10 *  ~~~(x ||| y) - 2 *  ~~~(x |||  ~~~y) + 6 * (x &&&  ~~~y) =  - 14 * (x &&& y) + 5 * x

theorem clear_to_clear_decomposebittest_proof : clear_to_clear_decomposebittest_before ⊑ clear_to_clear_decomposebittest_after

theorem positive_sameconst_shlnsw_proof : positive_sameconst_shlnsw_before ⊑ positive_sameconst_shlnsw_after

theorem lshrugt_03_07_proof : lshrugt_03_07_before ⊑ lshrugt_03_07_after

theorem test10_proof : test10_before ⊑ test10_after

theorem test_eq1_thm (e : IntW 16) (e_1 : IntW 32) :
  icmp IntPred.eq (trunc 8 e_1 { «nsw» := true, «nuw» := false }) (trunc 8 e { «nsw» := true, «nuw» := false }) ⊑
    icmp IntPred.eq e_1 (sext 32 e)

theorem ashr_ugt_5_proof : ashr_ugt_5_before ⊑ ashr_ugt_5_after

theorem test3_proof : test3_before ⊑ test3_after

theorem PR1817_2_logical_proof : PR1817_2_logical_before ⊑ PR1817_2_logical_after

theorem t13_x_is_one_thm (e : IntW 64) (e_1 : IntW 32) :
  icmp IntPred.ne
      (LLVM.and (shl (const? 32 1) (sub (const? 32 32) e_1)) (trunc 32 (lshr e (zext 64 (add e_1 (const? 32 (-16)))))))
      (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and e (const? 64 65536)) (const? 64 0)

theorem ashr_add_fail_thm (e : IntW 8) :
  add (ashr (const? 8 (-128)) e) (ashr (const? 8 (-128)) (add e (const? 8 1))) ⊑
    add (ashr (const? 8 (-128)) e { «exact» := true })
      (ashr (const? 8 (-128)) (add e (const? 8 1)) { «exact» := true })

theorem t0_thm (e e_1 : IntW 32) :
  lshr (lshr e_1 (sub (const? 32 32) e)) (add e (const? 32 (-2))) { «exact» := true } ⊑ lshr e_1 (const? 32 30)

theorem rawspeed_signbit_thm (e : IntW 64) (e_1 : IntW 32) :
  icmp IntPred.eq
      (LLVM.and (shl (const? 32 1) (add e_1 (const? 32 (-1)) { «nsw» := true, «nuw» := false }))
        (trunc 32 (lshr e (zext 64 (sub (const? 32 64) e_1 { «nsw» := true, «nuw» := false })))))
      (const? 32 0) ⊑
    icmp IntPred.sgt e (const? 64 (-1))

theorem sgt_smax1_proof : sgt_smax1_before ⊑ sgt_smax1_after

theorem e_589 :
     - 3 *  ~~~(x &&& y) + 2 *  ~~~x - 2 * x + 11 *  ~~~(x &&&  ~~~y) - 6 * (x |||  ~~~y) - 1 *  ~~~(x &&&  ~~~x) - 4 *  ~~~(x ||| y) - 9 *  ~~~(x |||  ~~~y) + 11 * (x &&&  ~~~y) - 2 * (x &&& y) =  - 1 *  ~~~y

theorem e_2237 :
    2 * (f &&&  ~~~(d &&& e)) + 1 * ((d &&& f) |||  ~~~(e ||| f)) + 3 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 3 *  ~~~(d &&& ( ~~~e &&& f)) - 7 * (f ^^^ (d ||| ( ~~~e ||| f))) - 1 *  ~~~(d &&& (e ^^^ f)) - 1 * (e ^^^  ~~~(d ||| (e &&& f))) + 1 *  ~~~(e &&&  ~~~f) - 1 *  ~~~(d ^^^ (e &&& f)) + 1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 2 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) - 5 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 11 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) + 2 * (e |||  ~~~(d |||  ~~~f)) - 1 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * (d &&& (e ^^^ f)) + 5 * (d &&& f) - 2 * ((d &&& e) |||  ~~~(e ||| f)) - 1 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 2 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 5 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) - 5 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) + 11 * ( ~~~f |||  ~~~(d ^^^ e)) - 11 * (f ^^^ (d &&&  ~~~e)) - 1 * (f ^^^  ~~~(d |||  ~~~e)) - 5 * (d ^^^ (e &&& f)) + 1 * ((d |||  ~~~e) &&& (e ^^^ f)) - 2 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) - 6 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 2 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 2 * (f ^^^  ~~~(d &&& (e &&& f))) - 3 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 2 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) + 11 * (e &&& f) - 11 *  ~~~(d &&& ( ~~~e ||| f)) - 1 * ( ~~~f ||| (d ^^^ e)) + 1 * (e ^^^ (d ||| (e &&& f))) - 3 * (e ^^^ ( ~~~d ||| (e ^^^ f))) + 1 * ( ~~~e &&& (d ^^^ f)) + 4 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 5 * ((d &&& e) |||  ~~~(e ^^^ f)) + 5 * (e &&&  ~~~(d &&&  ~~~f)) + 1 * ((d &&& f) ^^^ (e ||| f)) - 1 * (e &&&  ~~~(d ^^^ f)) - 6 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 6 * (d ^^^ f) - 3 * e + 6 *  ~~~(d ||| (e ||| f)) - 12 *  ~~~(d ||| ( ~~~e ||| f)) + 14 *  ~~~( ~~~d ||| (e ||| f)) - 2 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 39 * ( ~~~d &&& ( ~~~e &&& f)) + 4 * ( ~~~d &&& (e &&& f)) - 18 * (d &&& ( ~~~e &&& f)) - 9 * (d &&& (e &&& f)) =  - 11 *  ~~~(d ^^^ (e ||| f))

theorem bv_AddSub_1176 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.add e (LLVM.sub (LLVM.const? w 0) e_1) ⊑ LLVM.sub e e_1

theorem ashrsgt_02_11_proof : ashrsgt_02_11_before ⊑ ashrsgt_02_11_after

theorem ugt_rem_nz_proof : ugt_rem_nz_before ⊑ ugt_rem_nz_after

theorem eq_nsw_rem_nz_proof : eq_nsw_rem_nz_before ⊑ eq_nsw_rem_nz_after

theorem scalar_i8_lshr_and_negC_eq_not_negatedPowerOf2_thm (e e_1 : IntW 8) :
  icmp IntPred.eq (LLVM.and (lshr e_1 e) (const? 8 (-3))) (const? 8 0) ⊑
    icmp IntPred.eq (LLVM.and e_1 (shl (const? 8 (-3)) e)) (const? 8 0)

theorem a_true_implies_b_false2_thm.extracted_1._5 : ∀ (x x_1 : BitVec 1) (x_2 : BitVec 8),
  ofBool (x_2 == 10#8) = 1#1 → ofBool (20#8 <ᵤ x_2) = 1#1 → ofBool (20#8 <ᵤ x_2) &&& x_1 = x

theorem test_shl_nsw__all_are_safe_thm.extracted_1._3 : ∀ (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 ∨
          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 → False

@[simp]
lemma Fin.castLE_toNat (x : Fin n) : (x.castLE h).val = x.val

@[simp, simp_sllvm]
theorem pure_eq (x : α) (s) : (pure x : EffectM _) s = .value (x, s)

theorem n10_thm (e : IntW 8) :
  icmp IntPred.sgt (sub (const? 8 0) e) e ⊑ icmp IntPred.slt e (sub (const? 8 0) e)

theorem alive_AndOrXor_2617 : alive_AndOrXor_2617_src ⊑ alive_AndOrXor_2617_tgt

theorem prove_exact_with_high_mask_thm (e : IntW 8) :
  LLVM.sdiv (LLVM.and e (const? 8 (-8))) (const? 8 4) ⊑ LLVM.and (ashr e (const? 8 2)) (const? 8 (-2))

theorem not_match_inconsistent_values_proof : not_match_inconsistent_values_before ⊑ not_match_inconsistent_values_after

@[simp]
lemma BitVec.transport_getLsbD_nat (f : Fin n2 → Fin n1) (bv : BitVec n1) (i : Nat) (hlt : i < n2) :
    (bv.transport f).getLsbD i = bv.getLsbD (f ⟨i, hlt⟩)

theorem shl_C1_add_A_C2_i32_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬zeroExtend 32 x + 5#32 ≥ ↑32 →
    ¬(True ∧ x.msb = true ∨ zeroExtend 32 x ≥ ↑32) → 6#32 <<< (zeroExtend 32 x + 5#32) = 192#32 <<< zeroExtend 32 x

theorem fold_eq_lhs_thm (e e_1 : IntW 8) :
  icmp IntPred.eq (LLVM.and (shl (const? 8 (-1)) e_1) e) (const? 8 0) ⊑
    icmp IntPred.eq (lshr e e_1) (const? 8 0)

theorem and_zext_eq_odd_commuted_thm.extracted_1._1 : ∀ (x : BitVec 32),
  zeroExtend 32 (ofBool (x == 3#32)) &&& x = zeroExtend 32 (ofBool (x == 3#32))

theorem sub_to_xor_and_commuted_proof : sub_to_xor_and_commuted_before ⊑ sub_to_xor_and_commuted_after

theorem bv_AddSub_1624 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.sub (LLVM.or e e_1) (LLVM.xor e e_1) ⊑ LLVM.and e e_1

theorem xor_andn_commute3_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(x_1 = 0 ∨ x_1 = 0) → ¬x_1 = 0 → 42#32 / x_1 ^^^ (42#32 / x_1 ^^^ -1#32) &&& x = 42#32 / x_1 ||

theorem udiv_shl_pair1_thm (e e_1 e_2 : IntW 32) :
  LLVM.udiv (shl e_2 e_1 { «nsw» := false, «nuw» := true }) (shl e_2 e { «nsw» := false, «nuw» := true }) ⊑
    lshr (shl (const? 32 1) e_1 { «nsw» := false, «nuw» := true }) e

theorem ule_swap_or_min_logical_proof : ule_swap_or_min_logical_before ⊑ ule_swap_or_min_logical_after

theorem test_thm.extracted_1._1 : ∀ (x : BitVec 64), zeroExtend 64 (truncate 32 x) = x &&& 4294967295#64

@[simp] lemma composeUnaryAux_eval
    (p : FSM Unit)
    (q : FSM arity)
    (x : arity → BitStream) :
    (composeUnaryAux p q).eval x = p.eval (λ _ => q.eval x)

theorem udiv_icmp2_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(True ∧ x.umod 5#64 ≠ 0 ∨ 5#64 = 0) → ofBool (x / 5#64 == 0#64) = ofBool (x == 0#64)

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 8), x ^^^ 17#8 ^^^ 17#8 = x

theorem ashrsgt_02_12_exact_proof : ashrsgt_02_12_exact_before ⊑ ashrsgt_02_12_exact_after

theorem add_mask_sign_commute_i32_proof : add_mask_sign_commute_i32_before ⊑ add_mask_sign_commute_i32_after

theorem lshr_add_or_fail_thm (e e_1 : IntW 8) :
  LLVM.or (lshr e_1 (const? 8 1)) (add (lshr e (const? 8 1)) (const? 8 123)) ⊑
    LLVM.or (lshr e_1 (const? 8 1))
      (add (lshr e (const? 8 1)) (const? 8 123) { «nsw» := false, «nuw» := true })

theorem Tensor2d'.map_functorial (g : β → γ) (f : α → β) (t : Tensor2d' α) :
  t.map (g ∘ f) = (t.map f).map g

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

theorem sub_ashr_and_i32_proof : sub_ashr_and_i32_before ⊑ sub_ashr_and_i32_after

theorem shl_nuw_add_nsw_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ 1#32 <<< x >>> x ≠ 1#32 ∨ x ≥ ↑32 ∨ True ∧ (1#32 <<< x).saddOverflow (-1#32) = true) →
    ¬(True ∧ ((-1#32) <<< x).sshiftRight' x ≠ -1#32 ∨ x ≥ ↑32) → 1#32 <<< x + -1#32 = (-1#32) <<< x ^^^ -1#32

theorem main12_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (truncate 16 x <ₛ 0#16) ||

theorem main3_logical_proof : main3_logical_before ⊑ main3_logical_after

theorem bar_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ofBool (x_2 <ₛ x_1) = 1#1 →
    x_3 &&& (signExtend 32 (ofBool (x_2 <ₛ x_1)) ^^^ -1#32) ||

theorem test1_thm.extracted_1._2 : ∀ (x : BitVec 17),
  ¬(8#37 ≥ ↑37 ∨ 8#37 ≥ ↑37) →
    ¬(8#17 ≥ ↑17 ∨ 8#17 ≥ ↑17) →
      truncate 17 (zeroExtend 37 x >>> 8#37 ||| zeroExtend 37 x <<< 8#37) = x >>> 8#17 ||

theorem select_sub_thm.extracted_1._2 : ∀ (x x_1 : BitVec 17) (x_2 : BitVec 1), ¬x_2 = 1#1 → x_1 = x_1 - 0#17

theorem invert_both_cmp_operands_sub_proof : invert_both_cmp_operands_sub_before ⊑ invert_both_cmp_operands_sub_after

theorem test11_thm.extracted_1._1 : ∀ (x : BitVec 23),
  ¬(11#23 ≥ ↑23 ∨ 12#23 ≥ ↑23) → (x * 3#23) >>> 11#23 <<< 12#23 = x * 6#23 &&& BitVec.ofInt 23 (-4096)

theorem icmp_shl_uge_2_proof : icmp_shl_uge_2_before ⊑ icmp_shl_uge_2_after

theorem uadd_sat_canon_y_nuw_proof : uadd_sat_canon_y_nuw_before ⊑ uadd_sat_canon_y_nuw_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_3_thm (e : IntW 32) :
  LLVM.or (icmp IntPred.ne (LLVM.and e (const? 32 7)) (const? 32 0))
      (icmp IntPred.eq (LLVM.and e (const? 32 15)) (const? 32 0)) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 15)) (const? 32 8)

theorem logical_and_logical_and_icmps_comm1_proof : logical_and_logical_and_icmps_comm1_before ⊑ logical_and_logical_and_icmps_comm1_after

theorem trunc_shl_shl_var_proof : trunc_shl_shl_var_before ⊑ trunc_shl_shl_var_after

theorem drop_nuw_trunc_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  ¬(True ∧ zeroExtend 16 (truncate 8 (x_1 &&& 255#16 &&& x)) ≠ x_1 &&& 255#16 &&& x) →
    truncate 8 (x_1 &&& 255#16 &&& x) = truncate 8 (x_1 &&& x)

theorem icmp_equality_test_constant_samesign_proof : icmp_equality_test_constant_samesign_before ⊑ icmp_equality_test_constant_samesign_after

theorem test_shl_nuw_nsw__nuw_is_safe_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ofBool (x_1 &&& 1073741822#32 == 0#32) = 1#1 →
    2#32 ≥ ↑32 ∨
        True ∧ (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)).msb = true ∨
          zeroExtend 64 (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)) ≥ ↑64 →
      False

theorem neg_slt_1_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (0#8 - x <ₛ 1#8) = ofBool (x <ᵤ BitVec.ofInt 8 (-127))

theorem narrow_sext_sub_proof : narrow_sext_sub_before ⊑ narrow_sext_sub_after

theorem e_2388 :
     - 3 * ((d &&& e) ^^^ (e |||  ~~~f)) - 11 * ( ~~~d ||| (e &&& f)) - 7 *  ~~~(d ||| ( ~~~e &&& f)) + 2 * (e ^^^  ~~~(d &&& f)) - 5 * (e ^^^  ~~~(d ||| (e &&& f))) + 1 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) - 2 * (f |||  ~~~(d ||| e)) + 1 * (d &&& e) + 3 *  ~~~e - 7 * (d ^^^ e) + 1 * (f ||| (d ^^^ e)) - 5 *  ~~~(e ||| f) - 11 * (f ^^^ (d &&& e)) - 5 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 1 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 4 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 7 * (e ^^^  ~~~(d &&& (e ^^^ f))) + 2 * (f ^^^  ~~~(d |||  ~~~e)) + 1 * (d &&& ( ~~~e ||| f)) + 1 * (f ^^^ (d &&& ( ~~~e ||| f))) - 1 * (f ^^^  ~~~(d ||| e)) + 2 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 6 * (e ^^^ (d ||| ( ~~~e ||| f))) + 5 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * (f ^^^ ( ~~~d ||| (e &&& f))) + 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * (e ^^^ ( ~~~d ||| (e ||| f))) - 6 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 1 * (e ^^^  ~~~(d &&& (e &&& f))) - 1 *  ~~~(d ^^^ e) + 2 * (f &&& (d ^^^ e)) + 1 * (d &&& (e ^^^ f)) - 1 * ((d ^^^ e) ||| (d ^^^ f)) + 2 * (d ^^^ (e ^^^ f)) + 7 * (e ||| (d ^^^ f)) - 5 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) - 3 * (d ^^^ (e &&& f)) + 4 * ((d ^^^ e) &&& (d ^^^ f)) - 11 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) - 3 * (e ^^^ (d &&& (e ||| f))) + 4 * ((d &&& f) ||| (e &&&  ~~~f)) + 11 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 2 * d - 1 *  ~~~(d &&& ( ~~~e ||| f)) - 1 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) - 7 * (e &&&  ~~~(d &&& f)) - 11 *  ~~~(d ^^^ (e ||| f)) + 2 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) + 1 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * ((d &&& f) ^^^ (e ||| f)) + 1 * (f ^^^  ~~~(d &&& e)) + 5 * ( ~~~f ||| (d ^^^ e)) - 1 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) - 2 * (f &&&  ~~~(d &&&  ~~~e)) - 3 * ((d |||  ~~~e) &&& (e ^^^ f)) - 6 *  ~~~d + 7 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) - 3 *  ~~~(d ||| (e ^^^ f)) + 4 * (f ^^^  ~~~(d &&& (e ||| f))) + 11 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 2 * (f ^^^ (d ||| (e ||| f))) + 7 *  ~~~(d ||| f) + 30 *  ~~~(d ||| (e ||| f)) - 17 *  ~~~( ~~~d ||| (e ||| f)) + 14 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 19 * ( ~~~d &&& ( ~~~e &&& f)) + 39 * ( ~~~d &&& (e &&& f)) + 30 * (d &&& ( ~~~e &&& f)) + 14 * (d &&& (e &&& f)) =  - 1 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) + 5 *  ~~~( ~~~d &&& (e &&& f))

theorem or_and_shift_shift_and_proof : or_and_shift_shift_and_before ⊑ or_and_shift_shift_and_after

theorem negate_shl_xor_proof : negate_shl_xor_before ⊑ negate_shl_xor_after

theorem e_1635 :
     - 1 * ((a &&& c) ||| (b &&&  ~~~c)) - 1 *  ~~~(a ^^^ c) + 2 * (a ||| (b ^^^ c)) + 5 * (c ^^^ ( ~~~a ||| (b &&& c))) + 4 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) - 7 * ( ~~~(a ^^^ b) ||| (a ^^^ c)) + 1 * (c ^^^ (a ||| ( ~~~b &&& c))) - 1 * (c ^^^  ~~~(a ||| (b &&& c))) + 1 * (b ^^^ ( ~~~a &&& (b ^^^ c))) + 1 * (b &&& (a ^^^ c)) + 7 * (c ^^^  ~~~(a |||  ~~~b)) - 2 * (b &&&  ~~~(a ^^^ c)) + 1 * (c ^^^ (a ||| ( ~~~b ||| c))) + 1 * (a &&& (b ||| c)) + 1 * ((a ||| b) &&& (b ^^^ c)) - 1 *  ~~~(a ||| (b ||| c)) - 14 *  ~~~(a ||| ( ~~~b ||| c)) + 3 *  ~~~( ~~~a ||| (b ||| c)) - 4 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 7 * ( ~~~a &&& ( ~~~b &&& c)) + 5 * ( ~~~a &&& (b &&& c)) + 1 * (a &&& (b &&& c)) = 13 * (a &&& ( ~~~b &&& c))

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

theorem icmp_eq_sext_eq_otherwise_proof : icmp_eq_sext_eq_otherwise_before ⊑ icmp_eq_sext_eq_otherwise_after

theorem shl_and_and_thm (e e_1 : IntW 8) :
  LLVM.and (shl e_1 (const? 8 4)) (LLVM.and (shl e (const? 8 4)) (const? 8 88)) ⊑
    LLVM.and (shl (LLVM.and e e_1) (const? 8 4)) (const? 8 80)

theorem ne_umin1_proof : ne_umin1_before ⊑ ne_umin1_after

theorem test_shl_nsw__nuw_is_safe_thm.extracted_1._3 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 1073741822#32 == 0#32) = 1#1 →
    ¬(True ∧ ((x_1 &&& 1073741822#32) <<< 2#32).sshiftRight' 2#32 ≠ x_1 &&& 1073741822#32 ∨
          2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& 1073741822#32) <<< 2#32) ≥ ↑64) →
      2#32 ≥ ↑32 ∨
          True ∧ (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)).msb = true ∨
            zeroExtend 64 (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)) ≥ ↑64 →
        False

theorem test_sub__all_are_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 255#32 == 6#32) = 1#1 →
    ¬(True ∧ (BitVec.ofInt 32 (-254)).ssubOverflow (x &&& 255#32) = true ∨
          True ∧ (BitVec.ofInt 32 (-254)).usubOverflow (x &&& 255#32) = true) →
      BitVec.ofInt 32 (-260) = BitVec.ofInt 32 (-254) - (x &&& 255#32)

theorem max_sub_ugt_c0_proof : max_sub_ugt_c0_before ⊑ max_sub_ugt_c0_after

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

theorem and_min_7_8_proof : and_min_7_8_before ⊑ and_min_7_8_after

theorem test1_thm.extracted_1._1 : ∀ (x : BitVec 17), 10#17 ≥ ↑17 → False

theorem or_xor_tree_1100_proof : or_xor_tree_1100_before ⊑ or_xor_tree_1100_after

theorem icmp_ne_and1_lshr_pow2_thm (e : IntW 32) :
  zext 32 (icmp IntPred.eq (LLVM.and (lshr (const? 32 8) e) (const? 32 1)) (const? 32 0)) ⊑
    zext 32 (icmp IntPred.ne e (const? 32 3))

theorem e_593 :
    1 * (x ||| y) + 7 * (x |||  ~~~y) - 2 *  ~~~(x &&& y) + 11 *  ~~~(x ^^^ y) - 1 * y + 4 *  ~~~x - 17 *  ~~~(x ||| y) + 1 *  ~~~(x |||  ~~~y) - 3 * (x &&&  ~~~y) - 15 * (x &&& y) = 3 *  ~~~(x &&&  ~~~x)

theorem t4_ugt_slt_65536_thm.extracted_1._12 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (65535#32 <ᵤ x_2) = 1#1 →
    ¬ofBool (x_2 <ₛ 65536#32) = 1#1 → ¬ofBool (65535#32 <ₛ x_2) = 1#1 → ofBool (x_2 <ₛ 0#32) = 1#1 → x = x_1

theorem test_sub_nsw__none_are_safe_proof : test_sub_nsw__none_are_safe_before ⊑ test_sub_nsw__none_are_safe_after

theorem ashr_sge_exact_thm (e : IntW 8) :
  icmp IntPred.sge (ashr e (const? 8 3) { «exact» := true }) (const? 8 10) ⊑
    icmp IntPred.sgt e (const? 8 72)

theorem ashr_lshr_exact_lshr_only_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (-1#32 <ₛ x_1) = 1#1 → ¬(True ∧ x_1 >>> x <<< x ≠ x_1 ∨ x ≥ ↑32) → ¬x ≥ ↑32 → x_1 >>> x = x_1.sshiftRight' x

@[simp]
theorem mkSuccCarryAndOutsAssignPrecond_eval_envBoolStart_of_envBitstream_eq_false
  {circs : KInductionCircuits fsm n}
  (hCircs : circs.IsLawful)
  (envBitstream : _ ) :
  (mkSuccCarryAndOutsAssignPrecond circs).eval
    (envBoolStart_of_envBitstream fsm envBitstream (n + 1)) = false

theorem e_1745 :
    1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 5 *  ~~~(b ^^^ c) + 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 5 * ((b &&&  ~~~c) ^^^ (a ||| (b ^^^ c))) + 11 * (c &&& (a ||| b)) - 2 * (c ^^^ (a &&& b)) + 7 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 6 * (b ||| (a &&& c)) + 2 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) - 5 * (a &&& ( ~~~b ||| c)) - 7 * (c ^^^ (a ||| b)) - 1 * (b &&&  ~~~(a &&& c)) - 1 * ( ~~~a &&& (b ||| c)) + 2 * ( ~~~a ||| (b ||| c)) + 1 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) - 1 *  ~~~b - 5 * ( ~~~(a ||| b) |||  ~~~(a ^^^ (b ^^^ c))) + 7 * (a &&&  ~~~c) + 3 * (b ^^^  ~~~( ~~~a &&& (b ^^^ c))) + 5 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 2 * (b ^^^ (a &&& ( ~~~b ||| c))) + 5 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 2 * ((a ^^^ b) &&&  ~~~(a ^^^ c)) + 7 * ((a &&&  ~~~b) ||| (b ^^^ c)) - 2 * (b ^^^  ~~~(a &&& (b &&& c))) + 11 * (a ||| c) - 17 *  ~~~(a ||| (b ||| c)) + 4 *  ~~~(a ||| ( ~~~b ||| c)) - 39 *  ~~~( ~~~a ||| (b ||| c)) - 18 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 17 * ( ~~~a &&& ( ~~~b &&& c)) - 11 * ( ~~~a &&& (b &&& c)) - 35 * (a &&& ( ~~~b &&& c)) - 23 * (a &&& (b &&& c)) = 6 * (b |||  ~~~(a ||| c))

theorem a_false_implies_b_false2_comm_proof : a_false_implies_b_false2_comm_before ⊑ a_false_implies_b_false2_comm_after

theorem icmp_eq_and_pow2_shl_pow2_negative2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → zeroExtend 32 (ofBool (2#32 <<< x &&& 14#32 == 0#32)) = zeroExtend 32 (ofBool (2#32 <ᵤ x))

theorem prove_exact_with_high_mask_limit_proof : prove_exact_with_high_mask_limit_before ⊑ prove_exact_with_high_mask_limit_after

theorem sel_false_val_is_a_masked_shl_of_true_val2_proof : sel_false_val_is_a_masked_shl_of_true_val2_before ⊑ sel_false_val_is_a_masked_shl_of_true_val2_after

theorem udiv_shl_mul_nuw_swap_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 5),
  ¬(True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑5 ∨ True ∧ x.umulOverflow x_2 = true ∨ x * x_2 = 0) →
    True ∧ 1#5 <<< x_1 >>> x_1 ≠ 1#5 ∨ x_1 ≥ ↑5 ∨ x = 0 → False

theorem select_lshr_icmp_const_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (31#32 <ᵤ x) = 1#1 → ¬5#32 ≥ ↑32 → 0#32 = x >>> 5#32

theorem add_1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  x_2 = 1#1 → (x_1 ^^^ -1#8) + x ^^^ -1#8 = x_1 - x

theorem t0_thm (e e_1 e_2 e_3 : IntW 32) :
  LLVM.xor (select (icmp IntPred.eq e_3 e_2) (const? 1 1) (icmp IntPred.eq e_1 e)) (const? 1 1) ⊑
    select (icmp IntPred.ne e_3 e_2) (icmp IntPred.ne e_1 e) (const? 1 0)

theorem width5 (w : Nat) (a b : BitVec w) : (a + b = a - a) → a = - b

theorem t2_proof : t2_before ⊑ t2_after

theorem shl_or_disjoint_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_1 <<< x != 0) = true ∨ x ≥ ↑32) →
    ¬(x ≥ ↑32 ∨ True ∧ (x_2 >>> x &&& x_1 != 0) = true) → (x_2 ||| x_1 <<< x) >>> x = x_2 >>> x ||

theorem mullo_variant3_proof : mullo_variant3_before ⊑ mullo_variant3_after

theorem and_two_ranges_to_mask_and_range_different_sizes_thm (e : IntW 8) :
  LLVM.and (icmp IntPred.ugt (add e (const? 8 (-97))) (const? 8 25))
      (icmp IntPred.ugt (add e (const? 8 (-65))) (const? 8 24)) ⊑
    LLVM.and (icmp IntPred.ult (add e (const? 8 (-123))) (const? 8 (-26)))
      (icmp IntPred.ult (add e (const? 8 (-90))) (const? 8 (-25)))

theorem lshr_exact_add_nuw_proof : lshr_exact_add_nuw_before ⊑ lshr_exact_add_nuw_after

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

theorem n9_wrong_x1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 &&& 15#8 == 0#8) = 1#1 → x + 16#8 &&& BitVec.ofInt 8 (-16) = (x &&& BitVec.ofInt 8 (-16)) + 16#8

@[simp]
theorem eval_fsmNeq_eq_evalFin_Predicate_neq (t₁ t₂ : Term) :
   (fsmNeq (termEvalEqFSM t₁).toFSM (termEvalEqFSM t₂).toFSM).eval = (Predicate.binary .neq t₁ t₂).evalFin

theorem ashrsgt_03_14_proof : ashrsgt_03_14_before ⊑ ashrsgt_03_14_after

theorem ashr_shl_constants_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(x ≥ ↑32 ∨ 3#32 ≥ ↑32) →
    x ≥ ↑32 ∨
        True ∧
            ((BitVec.ofInt 32 (-33)).sshiftRight' x <<< 3#32).sshiftRight' 3#32 ≠
              (BitVec.ofInt 32 (-33)).sshiftRight' x ∨
          3#32 ≥ ↑32 →
      False

theorem e_1267 :
    7 *  ~~~(z ^^^ t) + 3 *  ~~~(z &&& t) + 2 *  ~~~z + 3 * (z ||| t) - 2 * z - 1 *  ~~~(z ||| t) - 5 *  ~~~(z |||  ~~~t) + 7 * (z &&&  ~~~t) + 6 * (z &&& t) = 11 * (z |||  ~~~t) + 3 * t

theorem icmp_eq_sext_ne_allones_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (signExtend 32 (ofBool (x != -1#32)) == x) = 0#1

theorem eq_smax4_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 + 3#32 <ₛ x) = 1#1 → ofBool (x_1 + 3#32 == x) = ofBool (x ≤ₛ x_1 + 3#32)

@[simp]
lemma eval_scanOr_succ (x : Unit → BitStream) (n : Nat) :
    (scanOr.eval x (n+1)) = ((scanOr.eval x n) || (x () (n+1)))

theorem bor_lor_left1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1), ¬x_1 ||

theorem masked_or_allzeroes_logical_proof : masked_or_allzeroes_logical_before ⊑ masked_or_allzeroes_logical_after

theorem positive_sameconst_shlnuwnsw_thm (e : IntW 8) :
  shl (lshr e (const? 8 3)) (const? 8 3) { «nsw» := true, «nuw» := true } ⊑ LLVM.and e (const? 8 (-8))

theorem ne_nuw_rem_zero_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.umulOverflow 5#8 = true) → ofBool (x * 5#8 != BitVec.ofInt 8 (-126)) = ofBool (x != 26#8)

theorem e_669 :
     - 7 * x + 11 *  ~~~x + 1 * y + 7 * (x ||| y) + 1 *  ~~~(x &&&  ~~~y) - 1 *  ~~~(x &&&  ~~~x) - 9 *  ~~~(x ||| y) - 19 *  ~~~(x |||  ~~~y) + 3 * (x &&&  ~~~y) + 1 * (x &&& y) = 2 * (x |||  ~~~y)

theorem land_band_left1_proof : land_band_left1_before ⊑ land_band_left1_after

theorem test3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(31#32 ≥ ↑32 ∨ 31#32 ≥ ↑32) →
    zeroExtend 32 (ofBool (x_1 >>> 31#32 == x >>> 31#32)) = zeroExtend 32 (ofBool (-1#32 <ₛ x_1 ^^^ x))

theorem select_icmp_x_and_8_ne_0_y_xor_8_thm.extracted_1._4 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 8#32 == 0#32) = 1#1 →
    ¬(True ∧ (x_1 &&& 8#32 ^^^ 8#32).msb = true) → x = x ^^^ zeroExtend 64 (x_1 &&& 8#32 ^^^ 8#32)

theorem eq_210_proof : eq_210_before ⊑ eq_210_after

theorem e_2306 :
    5 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 6 * (e &&&  ~~~(d ^^^ f)) - 11 * ((d &&& e) |||  ~~~(e ||| f)) - 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) + 1 * ((d ^^^ e) &&& (d ^^^ f)) + 1 * (e ^^^ (d ||| (e ||| f))) - 5 *  ~~~(d &&&  ~~~f) + 2 * (e ^^^ ( ~~~d &&& (e ||| f))) - 11 *  ~~~e + 11 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) + 7 * (d ||| (e &&& f)) - 11 * (d ||| f) + 4 * (e ||| (d &&& f)) + 5 *  ~~~f + 1 * (e ||| (d &&&  ~~~f)) - 2 *  ~~~(d &&& f) - 2 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) - 7 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 7 * ((d ^^^ e) ||| (d ^^^ f)) - 1 *  ~~~(d ^^^ (e ^^^ f)) + 1 * (d ^^^ (e ||| f)) - 7 * (d ||| ( ~~~e ||| f)) - 5 * (e ^^^  ~~~(d &&& (e &&& f))) - 3 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) + 2 * (e |||  ~~~(d ||| f)) + 5 *  ~~~(d &&& (e ||| f)) - 11 * (e ||| (d ^^^ f)) + 4 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 5 *  ~~~(d &&&  ~~~e) - 1 * (e ^^^ ( ~~~d ||| (e ||| f))) + 3 * e + 11 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 5 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * (e ^^^ (d &&&  ~~~f)) - 2 * ((d &&& f) ||| (e &&&  ~~~f)) - 2 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 2 * (f ^^^ (d &&&  ~~~e)) + 11 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 11 * ( ~~~f &&&  ~~~(d ^^^ e)) - 5 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) - 3 * (f ^^^ (d ||| ( ~~~e ||| f))) - 1 * (e ^^^  ~~~(d &&& f)) + 4 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 2 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 4 * (d &&& ( ~~~e ||| f)) - 3 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 2 * (d &&& (e ||| f)) - 1 * (e &&& f) + 3 *  ~~~(d &&& ( ~~~e ||| f)) - 7 * (e &&&  ~~~(d &&& f)) - 3 * (f |||  ~~~(d |||  ~~~e)) - 5 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) - 1 *  ~~~(e |||  ~~~f) + 1 * (e ^^^ f) - 6 *  ~~~(d ^^^ f) + 6 *  ~~~(d ||| (e ||| f)) + 11 *  ~~~(d ||| ( ~~~e ||| f)) + 30 *  ~~~( ~~~d ||| (e ||| f)) - 11 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 40 * ( ~~~d &&& ( ~~~e &&& f)) - 12 * ( ~~~d &&& (e &&& f)) + 35 * (d &&& ( ~~~e &&& f)) + 19 * (d &&& (e &&& f)) =  - 11 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) + 1 * (d |||  ~~~e)

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

theorem e_1838 :
    1 *  ~~~c + 2 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 1 * (b ^^^ (a ||| (b &&& c))) - 7 * (b ^^^ (a |||  ~~~c)) - 3 * ((a &&&  ~~~b) ||| (b ^^^ c)) - 1 * (a ||| ( ~~~b &&& c)) + 11 * ( ~~~a &&& (b ||| c)) + 3 * ( ~~~a ||| (b &&& c)) - 5 * (a ^^^ b) + 1 *  ~~~( ~~~a &&& (b &&& c)) - 11 *  ~~~(a &&& b) - 1 * b - 5 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) + 5 * (a &&& c) - 1 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 2 *  ~~~(a &&& ( ~~~b ||| c)) - 1 * (b ^^^  ~~~( ~~~a &&& (b ^^^ c))) + 1 * ( ~~~c &&& (a ^^^ b)) - 1 * ( ~~~b &&&  ~~~(a ^^^ c)) + 2 * (b ^^^ (a &&& c)) + 4 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 11 * ((a |||  ~~~b) &&& (b ^^^ c)) + 5 * (b ^^^ ( ~~~a &&& (b ||| c))) - 6 * (a &&&  ~~~b) - 1 * ((b &&&  ~~~c) ^^^ (a ||| (b ^^^ c))) - 1 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 1 * (c ^^^ (a ||| ( ~~~b ||| c))) + 1 *  ~~~(b &&&  ~~~c) - 3 * ((a &&& c) ^^^  ~~~(a ^^^ ( ~~~b &&& c))) + 5 * ((a ^^^ b) &&&  ~~~(a ^^^ c)) - 2 * ( ~~~a ||| (b ^^^ c)) - 3 *  ~~~(a ^^^ c) - 1 *  ~~~(a &&&  ~~~a) + 1 *  ~~~(a &&& c) - 2 * (b |||  ~~~(a |||  ~~~c)) + 7 * ( ~~~c |||  ~~~(a ^^^ b)) + 14 *  ~~~(a ||| (b ||| c)) + 4 *  ~~~(a ||| ( ~~~b ||| c)) + 26 *  ~~~( ~~~a ||| (b ||| c)) - 20 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 11 * ( ~~~a &&& ( ~~~b &&& c)) + 12 * ( ~~~a &&& (b &&& c)) + 18 * (a &&& ( ~~~b &&& c)) - 8 * (a &&& (b &&& c)) = 2 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c)))

theorem lshr_or_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬((42#8 == 0 || 8 != 1 && x_1 == intMin 8 && 42#8 == -1) = true ∨ 4#8 ≥ ↑8 ∨ 4#8 ≥ ↑8) →
    (42#8 == 0 || 8 != 1 && x_1 == intMin 8 && 42#8 == -1) = true ∨ 4#8 ≥ ↑8 → False

theorem bools_logical_commute0_and1_and2_proof : bools_logical_commute0_and1_and2_before ⊑ bools_logical_commute0_and1_and2_after

theorem test3_thm (e e_1 : IntW 49) :
  LLVM.and (LLVM.or e_1 (shl e (const? 49 1))) (const? 49 1) ⊑ LLVM.and e_1 (const? 49 1)

theorem ule_bignum_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x * -1#8 ≤ᵤ 0#8) = ofBool (x == 0#8)

theorem logic_or_logic_and_3_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → x = 1#1 → ¬x_1 = 1#1 → 0#1 = 1#1 → 0#1 = 1#1

theorem is_ascii_alphabetic_proof : is_ascii_alphabetic_before ⊑ is_ascii_alphabetic_after

@[simp] theorem Hom.appendCodomain_apply (f : Γ.Hom Δ) (v : Γ.Var t) :
    (f.appendCodomain (ts := ts)) v = (f v).appendInr

theorem trunc_sandwich_max_sum_shift_proof : trunc_sandwich_max_sum_shift_before ⊑ trunc_sandwich_max_sum_shift_after

theorem n1_thm (e e_1 : IntW 8) :
  icmp IntPred.ult (LLVM.xor (shl (const? 8 (-1)) e_1) (const? 8 1)) e ⊑
    icmp IntPred.ult (LLVM.xor (shl (const? 8 (-1)) e_1 { «nsw» := true, «nuw» := false }) (const? 8 1)) e

theorem a_false_implies_b_false2_comm_thm.extracted_1._8 : ∀ (x x_1 : BitVec 1) (x_2 : BitVec 8),
  ¬ofBool (20#8 <ᵤ x_2) = 1#1 → ¬ofBool (10#8 <ᵤ x_2) = 1#1 → x ||

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

theorem lshrult_01_04_exact_proof : lshrult_01_04_exact_before ⊑ lshrult_01_04_exact_after

theorem isMonotone_matchVarArg_aux (lets : Lets d Γ_in eff Γ_out) :
    (
     ∀  (Δ_out : Ctxt d.Ty)
        (matchLets : Lets d Δ_in EffectKind.pure Δ_out) (l : List d.Ty)
        (argsl : HVector Γ_out.Var l) (argsr : HVector Δ_out.Var l),
        (matchArg lets matchLets argsl argsr).IsMonotone
    )
    ∧ (
      ∀ (Δ_out : Ctxt d.Ty) (t : d.Ty) (v : Γ_out.Var t)
        (matchLets : Lets d Δ_in EffectKind.pure Δ_out)
        (w : Var Δ_out t),
        (matchVar lets v matchLets w).IsMonotone
    )

theorem or_and_not_not_commute6_proof : or_and_not_not_commute6_before ⊑ or_and_not_not_commute6_after

theorem t0_basic_proof : t0_basic_before ⊑ t0_basic_after

theorem sdiv_x_by_const_cmp_x_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(13#32 == 0 || 32 != 1 && x == intMin 32 && 13#32 == -1) = true → ofBool (x.sdiv 13#32 == x) = ofBool (x == 0#32)

theorem slt_zero_ne_ne_0_proof : slt_zero_ne_ne_0_before ⊑ slt_zero_ne_ne_0_after

theorem urem_common_divisor_thm (e e_1 e_2 : IntW 5) (e_3 : IntW 1) :
  select e_3 (urem e_2 e_1) (urem e e_1) ⊑ urem (select e_3 e_2 e) e_1

theorem not_not_true_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x ^^^ 1#1 = 1#1 → ¬x = 1#1 → False

@[simp_sllvm]
theorem PoisonOr.if_then_if_then_poison_eq {α : Type} (c₁ c₂ : Prop) [Decidable c₁] [Decidable c₂]
      (x y : PoisonOr α):
    (if c₁ then (if c₂ then poison else x : no_index _) else y : no_index _) =
    (if c₁ ∧ c₂ then poison else (if c₁ then x else y : no_index _) : no_index _)

theorem icmp_shl_eq_1_proof : icmp_shl_eq_1_before ⊑ icmp_shl_eq_1_after

theorem test35_with_trunc_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬ofBool (0#32 ≤ₛ truncate 32 x) = 1#1 → ofBool (x &&& 2147483648#64 == 0#64) = 1#1 → 100#32 = 60#32

@[aesop 50% unsafe]
theorem Std.HashMap.mem_of_getElem? [BEq K] [LawfulBEq K] [Hashable K] [LawfulHashable K] {m : Std.HashMap K V} {k : K} :
    m[k]? = some v → k ∈ m

theorem e_1407 :
    4 * z - 1 * (z ^^^ t) - 7 * (z |||  ~~~t) + 7 *  ~~~t + 2 *  ~~~(z &&& t) + 1 *  ~~~(z &&&  ~~~z) - 15 *  ~~~(z ||| t) - 14 *  ~~~(z |||  ~~~t) - 6 * (z &&&  ~~~t) + 1 * (z &&& t) =  - 11 *  ~~~z - 1 *  ~~~(z &&&  ~~~t)

theorem or_and_or_pat1_proof : or_and_or_pat1_before ⊑ or_and_or_pat1_after

theorem ashrsgt_01_00_proof : ashrsgt_01_00_before ⊑ ashrsgt_01_00_after

theorem lshrugt_01_14_thm (e : IntW 4) : icmp IntPred.ugt (lshr e (const? 4 1)) (const? 4 (-2)) ⊑ const? 1 0

theorem e_2275 :
     - 3 *  ~~~(d &&& (e ||| f)) + 2 * (f ^^^ (d &&& ( ~~~e ||| f))) - 2 * (f ^^^ (d &&& (e ||| f))) + 2 * (f &&& (d ^^^ e)) - 1 * (f ^^^ ( ~~~d &&& (e ||| f))) + 1 * (d ||| f) - 5 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) - 2 * (d ^^^ (e ^^^ f)) + 2 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) + 5 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 11 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 11 * ((d ^^^ e) &&& (d ^^^ f)) + 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) + 4 * (f ^^^  ~~~(d |||  ~~~e)) + 3 * (e ||| (d &&&  ~~~f)) + 1 * (e ^^^  ~~~(d &&& (e ||| f))) + 2 * (f ^^^ (d ||| ( ~~~e ||| f))) + 4 *  ~~~(d ^^^ ( ~~~e &&& f)) - 5 * (d ||| (e ^^^ f)) - 3 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 2 * (d &&& ( ~~~e ||| f)) + 1 *  ~~~(d ||| (e ^^^ f)) - 7 * (f &&&  ~~~(d ^^^ e)) - 7 * (f ^^^ (d ||| e)) - 2 * (e &&&  ~~~(d &&&  ~~~f)) + 7 *  ~~~f + 1 * ( ~~~e &&&  ~~~(d ^^^ f)) - 5 * ((e &&& f) ||| (d &&& (e ||| f))) - 6 * ( ~~~e ||| (d ^^^ f)) + 7 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) - 1 * (d ^^^ ( ~~~e ||| f)) + 1 *  ~~~(d ^^^ (e ||| f)) - 6 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) + 11 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 1 * ( ~~~e |||  ~~~(d ^^^ f)) - 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 4 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 2 *  ~~~( ~~~d &&& (e ||| f)) + 3 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 1 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 7 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) + 5 * (d &&&  ~~~e) + 7 * (e ^^^ (d &&& (e ^^^ f))) - 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 2 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) - 1 * (e ||| (d &&& f)) - 11 * (e ^^^  ~~~(d &&& f)) + 5 * (f ^^^ (d |||  ~~~e)) + 1 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * (d ||| e) - 16 *  ~~~(d ||| (e ||| f)) - 22 *  ~~~(d ||| ( ~~~e ||| f)) + 2 *  ~~~( ~~~d ||| (e ||| f)) + 10 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 11 * ( ~~~d &&& ( ~~~e &&& f)) - 8 * ( ~~~d &&& (e &&& f)) - 17 * (d &&& ( ~~~e &&& f)) - 10 * (d &&& (e &&& f)) = 7 * ((d ||| e) &&& (e ^^^ f))

theorem eq_umin1_proof : eq_umin1_before ⊑ eq_umin1_after

theorem ashrslt_02_08_exact_proof : ashrslt_02_08_exact_before ⊑ ashrslt_02_08_exact_after

theorem shl_add_nsw_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(x ≥ ↑32 ∨ True ∧ (1#32 <<< x).saddOverflow (-1#32) = true) →
    ¬(True ∧ ((-1#32) <<< x).sshiftRight' x ≠ -1#32 ∨ x ≥ ↑32) → 1#32 <<< x + -1#32 = (-1#32) <<< x ^^^ -1#32

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

theorem test5_proof : test5_before ⊑ test5_after

theorem t5_thm.extracted_1._7 : ∀ (x x_1 : BitVec 1) (x_2 : BitVec 32),
  x_1 = 1#1 → ¬x = 1#1 → ¬64#32 = 0 → ¬6#32 ≥ ↑32 → x_2 / 64#32 = x_2 >>> 6#32

theorem modulo2_thm (e : IntW 32) :
  add (select (icmp IntPred.slt (LLVM.srem e (const? 32 2)) (const? 32 0)) (const? 32 2) (const? 32 0))
      (LLVM.srem e (const? 32 2)) { «nsw» := true, «nuw» := false } ⊑
    LLVM.and e (const? 32 1)

theorem lshr_16_add_known_16_leading_zeroes_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬16#32 ≥ ↑32 →
    True ∧ (x_1 &&& 65535#32).saddOverflow (x &&& 65535#32) = true ∨
        True ∧ (x_1 &&& 65535#32).uaddOverflow (x &&& 65535#32) = true ∨ 16#32 ≥ ↑32 →
      False

theorem positive_samevar_shlnuw_ashrexact_proof : positive_samevar_shlnuw_ashrexact_before ⊑ positive_samevar_shlnuw_ashrexact_after

theorem positive_sameconst_shlnuwnsw_lshrexact_proof : positive_sameconst_shlnuwnsw_lshrexact_before ⊑ positive_sameconst_shlnuwnsw_lshrexact_after

theorem sge_smin3_proof : sge_smin3_before ⊑ sge_smin3_after

theorem ashr_bitwidth_mask_proof : ashr_bitwidth_mask_before ⊑ ashr_bitwidth_mask_after

theorem shl_add_and_lshr_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(4#32 ≥ ↑32 ∨ 4#32 ≥ ↑32) → ¬4#32 ≥ ↑32 → ((x_1 >>> 4#32 &&& 8#32) + x) <<< 4#32 = (x_1 &&& 128#32) + x <<< 4#32

theorem and_ranges_overlap_single_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (5#8 ≤ᵤ x) &&& ofBool (x ≤ᵤ 10#8) &&& (ofBool (10#8 ≤ᵤ x) &&& ofBool (x ≤ᵤ 20#8)) = ofBool (x == 10#8)

theorem t7_ugt_sgt_neg1_thm.extracted_1._12 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (143#32 <ᵤ x_2 + 16#32) = 1#1 →
    ¬ofBool (BitVec.ofInt 32 (-17) <ₛ x_2) = 1#1 → ofBool (127#32 <ₛ x_2) = 1#1 → x = x_1

theorem test5_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬16#128 ≥ ↑128 → 16#32 ≥ ↑32 → False

theorem xor_ashr_not_fail_lshr_ashr_proof : xor_ashr_not_fail_lshr_ashr_before ⊑ xor_ashr_not_fail_lshr_ashr_after

theorem c_0_1_0_proof : c_0_1_0_before ⊑ c_0_1_0_after

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

theorem test_invalid_simplify_eq2_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬ofBool (x == 2#8) = 1#1 → x - 1#8 = x + -1#8

theorem alive_AndOrXor_2453  (w : Nat)   : alive_AndOrXor_2453_src w  ⊑ alive_AndOrXor_2453_tgt w

theorem or_not_xor_common_op_commute6_thm (e e_1 e_2 : IntW 8) :
  LLVM.or (LLVM.xor e_2 e_1) (LLVM.or (sub (const? 8 0) e) (LLVM.xor e_1 (const? 8 (-1)))) ⊑
    LLVM.or (LLVM.xor (LLVM.and e_2 e_1) (const? 8 (-1))) (sub (const? 8 0) e)

theorem canonicalize_logic_first_xor_0_nsw_thm (e : IntW 8) :
  LLVM.xor (add e (const? 8 96) { «nsw» := true, «nuw» := false }) (const? 8 31) ⊑
    add (LLVM.xor e (const? 8 31)) (const? 8 96) { «nsw» := true, «nuw» := false }

theorem lshrugt_03_08_proof : lshrugt_03_08_before ⊑ lshrugt_03_08_after

theorem test4_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), x_1 ||

theorem e_1532 :
    1 * (c ||| (a ^^^ b)) - 1 * (c ^^^ (a ||| ( ~~~b &&& c))) + 4 * (c &&&  ~~~(a &&& b)) - 6 *  ~~~c - 1 * (b ||| (a &&&  ~~~c)) - 6 *  ~~~( ~~~a ||| (b &&& c)) + 11 *  ~~~(a ||| (b ||| c)) + 11 *  ~~~(a ||| ( ~~~b ||| c)) + 13 *  ~~~( ~~~a ||| (b ||| c)) + 14 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 1 * (a &&& ( ~~~b &&& c)) = 3 * ( ~~~a &&& (b &&& c)) + 5 *  ~~~(a ||| (b &&& c))

theorem e_1059 :
     - 2 *  ~~~(z ^^^ t) + 1 *  ~~~t - 3 * z - 5 *  ~~~(z &&&  ~~~z) + 6 *  ~~~(z ||| t) + 7 * (z &&&  ~~~t) + 10 * (z &&& t) =  - 5 *  ~~~(z |||  ~~~t)

theorem and_xor_not_common_op_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), (x_1 ^^^ (x ^^^ -1#32)) &&& x_1 = x_1 &&& x

theorem p_commutative2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  True ∧ (x_1 &&& (x_2 ^^^ -1#32) &&& (x &&& x_2) != 0) = true → False

theorem main10_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 64#32 == 0#32) &&& ofBool (0#8 ≤ₛ truncate 8 x) = 1#1 →
    ¬ofBool (x &&& 192#32 == 0#32) = 1#1 → 2#32 = 1#32

theorem add_five (x : BitVec w) : (x + x) + (x + x) + x = x + x + x + x + x

theorem test_sext_zext_proof : test_sext_zext_before ⊑ test_sext_zext_after

theorem main3e_like_logical_thm.extracted_1._7 : ∀ (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 →
      ofBool (x_2 &&& x == 0#32) = 1#1 → 0#32 = zeroExtend 32 (ofBool (x_2 &&& x != 0#32))

theorem zext_sext_add_icmp_slt_2_thm (e e_1 : IntW 1) :
  icmp IntPred.slt (add (zext 8 e_1) (sext 8 e)) (const? 8 2) ⊑ const? 1 1

theorem test_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x != 34#32) = 1#1 → 0#1 = ofBool (x != 34#32) &&& ofBool (-1#32 <ₛ x)

theorem one_side_fold_eq_thm (e e_1 e_2 : IntW 32) (e_3 : IntW 1) :
  icmp IntPred.eq (select e_3 e_2 e_1) (select e_3 e e_1) ⊑
    select (LLVM.xor e_3 (const? 1 1)) (const? 1 1) (icmp IntPred.eq e_2 e)

theorem scalar_i64_shl_ult_const_proof : scalar_i64_shl_ult_const_before ⊑ scalar_i64_shl_ult_const_after

theorem and_ranges_overlap_thm (e : IntW 8) :
  LLVM.and (LLVM.and (icmp IntPred.uge e (const? 8 5)) (icmp IntPred.ule e (const? 8 10)))
      (LLVM.and (icmp IntPred.uge e (const? 8 7)) (icmp IntPred.ule e (const? 8 20))) ⊑
    icmp IntPred.ult (add e (const? 8 (-7))) (const? 8 4)

theorem mul_of_pow2s_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), (x_1 &&& 8#32) * (x &&& 16#32) ||

theorem e_2400 :
     - 1 * (d ^^^ e) - 1 * f - 11 * (e ^^^ (d &&& f)) - 6 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) + 5 *  ~~~( ~~~d ||| (e &&& f)) + 5 * (f ||| (d ^^^ e)) - 11 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 2 * (f &&&  ~~~(d ^^^ e)) - 3 *  ~~~(d &&& ( ~~~e ||| f)) - 11 * ( ~~~d &&& (e ||| f)) - 1 * (f ^^^  ~~~(d &&& (e &&& f))) - 3 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) + 7 * (e ^^^ (d &&&  ~~~f)) + 1 * ( ~~~f &&&  ~~~(d ^^^ e)) + 4 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) + 2 *  ~~~(d ^^^ (e ||| f)) - 2 * (e ^^^  ~~~(d &&&  ~~~f)) + 3 * (f &&& (d ^^^ e)) + 1 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 3 *  ~~~(d ||| f) + 1 * ( ~~~e &&&  ~~~(d ^^^ f)) + 2 * ((d |||  ~~~e) &&& (e ^^^ f)) - 6 * (f &&& (d |||  ~~~e)) + 2 * (e ^^^ (d ||| f)) + 1 * (e ||| (d &&& f)) + 2 * (e ^^^ (d &&& (e ||| f))) + 5 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 1 * (e ^^^ ( ~~~d ||| (e ||| f))) - 5 * (e ^^^ (d ||| (e &&& f))) + 2 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) - 3 * (d |||  ~~~e) + 5 * (e &&&  ~~~(d &&&  ~~~f)) - 6 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) - 2 *  ~~~f + 3 * (e &&& (d ||| f)) - 7 * ( ~~~d ||| (e ^^^ f)) + 7 * ( ~~~d ||| (e &&& f)) - 7 * (d ||| (e &&& f)) + 2 * (d &&& (e ||| f)) + 11 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 11 * (f ^^^  ~~~(d &&&  ~~~e)) + 11 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 1 * (f ^^^  ~~~(d ||| (e &&& f))) + 4 * (f ^^^ (d &&&  ~~~e)) + 2 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 2 * (e ||| f) - 1 * (f &&&  ~~~(d &&&  ~~~e)) - 2 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 1 * ( ~~~d ||| ( ~~~e &&& f)) - 7 * (f ^^^  ~~~(d ||| e)) - 2 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 2 *  ~~~(e |||  ~~~f) + 1 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) + 4 * (e ^^^ (d &&& ( ~~~e ||| f))) + 3 *  ~~~( ~~~d &&& (e ^^^ f)) + 11 *  ~~~( ~~~d &&& (e ||| f)) - 5 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 2 *  ~~~(d &&& (e ||| f)) - 1 * (e |||  ~~~f) - 1 *  ~~~(d ||| (e &&& f)) - 6 * (f ||| (d &&&  ~~~e)) - 3 *  ~~~(d ^^^ ( ~~~e ||| f)) - 1 * (f |||  ~~~(d ^^^ e)) - 6 *  ~~~(d &&&  ~~~d) + 25 *  ~~~(d ||| (e ||| f)) + 19 *  ~~~(d ||| ( ~~~e ||| f)) + 1 *  ~~~( ~~~d ||| (e ||| f)) + 21 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 29 * ( ~~~d &&& ( ~~~e &&& f)) + 19 * ( ~~~d &&& (e &&& f)) + 39 * (d &&& ( ~~~e &&& f)) - 2 * (d &&& (e &&& f)) =  - 1 * (d &&&  ~~~f)

theorem sext_sub_nuw_thm (e : IntW 1) (e_1 : IntW 8) :
  sub e_1 (sext 8 e) { «nsw» := false, «nuw» := true } ⊑ add e_1 (zext 8 e)

theorem e_2240 :
     - 1 * (e &&& f) - 7 * (d |||  ~~~e) - 3 * (e |||  ~~~(d ^^^ f)) + 4 * (f ^^^  ~~~(d &&&  ~~~e)) + 1 * (d &&& (e ||| f)) + 2 * (e ||| (d &&& f)) + 4 * (d &&&  ~~~e) + 2 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) - 1 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) + 11 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) - 3 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 1 * ( ~~~d &&& (e ||| f)) - 5 * (e &&&  ~~~(d &&& f)) + 2 * (d ^^^ (e ||| f)) + 3 * (e ^^^  ~~~(d &&&  ~~~f)) - 2 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) - 1 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 3 *  ~~~(d ^^^ e) + 7 * (f ^^^ ( ~~~d ||| (e &&& f))) - 2 * ( ~~~e &&& (d ^^^ f)) + 3 * ( ~~~f |||  ~~~(d ^^^ e)) - 6 *  ~~~(d ||| f) - 2 * (f ^^^ (d &&& e)) + 11 * (d ^^^ e) + 2 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) + 2 * (e &&&  ~~~f) + 2 * ( ~~~f ||| (d ^^^ e)) - 1 * (f ^^^  ~~~(d &&& (e ||| f))) - 6 * (f ||| (d ^^^ e)) + 1 * ((d ^^^ e) &&& (d ^^^ f)) - 11 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) + 5 * (d &&& e) + 1 *  ~~~(d &&& e) - 2 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 5 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 11 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 5 * (d ^^^ f) + 1 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 11 * f + 1 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 11 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) - 7 *  ~~~(e |||  ~~~f) + 5 *  ~~~( ~~~d &&& ( ~~~e &&& f)) - 5 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 4 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 7 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * ((d &&& e) ^^^ (e ||| f)) - 1 * ( ~~~d ||| (e ||| f)) - 12 *  ~~~(d ||| (e ||| f)) - 16 *  ~~~(d ||| ( ~~~e ||| f)) - 9 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 37 * ( ~~~d &&& ( ~~~e &&& f)) - 20 * ( ~~~d &&& (e &&& f)) - 6 * (d &&& ( ~~~e &&& f)) + 26 * (d &&& (e &&& f)) = 20 *  ~~~( ~~~d ||| (e ||| f))

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

theorem testi64i32_ne_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(31#32 ≥ ↑32 ∨ 32#64 ≥ ↑64) →
    ofBool ((truncate 32 x).sshiftRight' 31#32 != truncate 32 (x >>> 32#64)) =
      ofBool (x + BitVec.ofInt 64 (-2147483648) <ᵤ BitVec.ofInt 64 (-4294967296))

theorem test_or1_proof : test_or1_before ⊑ test_or1_after

theorem e_2103 :
    2 * (f &&& (d ^^^ e)) + 5 * ((d &&&  ~~~e) ||| (e ^^^ f)) - 1 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 6 * ((d ^^^ e) &&& (d ^^^ f)) - 5 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) + 1 * f - 1 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 1 * ((d ||| e) &&& (e ^^^ f)) - 7 * (e ^^^ f) - 1 * (f ^^^ (d &&& e)) + 2 *  ~~~(d &&& ( ~~~e ||| f)) - 2 *  ~~~(d |||  ~~~f) - 1 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 4 * ((d &&& e) |||  ~~~(e ||| f)) - 1 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 7 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 2 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 11 * ((d &&& e) ||| (e ^^^ f)) - 7 *  ~~~(d ||| f) - 3 * (e ^^^  ~~~(d ||| (e &&& f))) + 1 *  ~~~(d &&&  ~~~e) + 1 *  ~~~(d &&& (e ||| f)) + 1 * (e &&&  ~~~(d ^^^ f)) + 11 * (d ^^^ f) - 1 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 2 *  ~~~(d &&&  ~~~f) - 3 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 1 * (e ^^^  ~~~(d &&& f)) + 7 *  ~~~f + 7 * (e &&&  ~~~(d &&& f)) + 2 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 4 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) + 7 * (e |||  ~~~(d ||| f)) + 1 * ( ~~~e ||| (d ^^^ f)) - 2 *  ~~~(d ^^^ ( ~~~e &&& f)) - 3 *  ~~~(d ||| (e ||| f)) - 12 *  ~~~(d ||| ( ~~~e ||| f)) - 1 *  ~~~( ~~~d ||| (e ||| f)) - 35 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 11 * ( ~~~d &&& ( ~~~e &&& f)) - 3 * (d &&& ( ~~~e &&& f)) - 3 * (d &&& (e &&& f)) = 11 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) + 9 * ( ~~~d &&& (e &&& f))

theorem t0_thm.extracted_1._8 : ∀ (x x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  ¬x_3 ^^^ 1#1 = 1#1 → ¬x_3 = 1#1 → 0#1 = 1#1 → ofBool (x_2 != x_1) = 1#1 → False

theorem test7_thm.extracted_1._1 : ∀ (x : BitVec 1), signExtend 64 (zeroExtend 32 x) = zeroExtend 64 x

theorem negate_zext_proof : negate_zext_before ⊑ negate_zext_after

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

theorem lshr_mul_times_5_div_4_exact_2_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ x.umulOverflow 5#32 = true ∨ True ∧ (x * 5#32) >>> 2#32 <<< 2#32 ≠ x * 5#32 ∨ 2#32 ≥ ↑32) →
    ¬(True ∧ x >>> 2#32 <<< 2#32 ≠ x ∨ 2#32 ≥ ↑32 ∨ True ∧ x.uaddOverflow (x >>> 2#32) = true) →
      (x * 5#32) >>> 2#32 = x + x >>> 2#32

theorem sext_xor_sub_1_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → (signExtend 64 x_1 ^^^ x) - signExtend 64 x_1 = x

theorem scalar_i64_shl_ult_const_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬25#64 ≥ ↑64 → ofBool (x <<< 25#64 <ᵤ 8589934592#64) = ofBool (x &&& 549755813632#64 == 0#64)

theorem e_460 :
    7 *  ~~~(x &&& y) - 2 *  ~~~(x ^^^ y) + 2 *  ~~~y + 2 * (x ||| y) - 1 * (x |||  ~~~y) - 17 *  ~~~(x ||| y) - 20 *  ~~~(x |||  ~~~y) - 24 * (x &&&  ~~~y) - 13 * (x &&& y) =  - 11 *  ~~~(x &&&  ~~~x) - 3 * x

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

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

theorem e_2340 :
     - 5 * (e ^^^  ~~~(d &&&  ~~~f)) - 1 * (f |||  ~~~(d |||  ~~~e)) - 3 * (e ||| (d ^^^ f)) - 11 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) - 2 * (d ^^^ (e &&& f)) + 3 * (e ||| (d &&&  ~~~f)) + 2 * ( ~~~d &&& ( ~~~e ||| f)) + 1 *  ~~~(d ^^^ ( ~~~e &&& f)) - 3 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) + 5 *  ~~~(e ^^^ f) + 1 * (e ^^^  ~~~(d |||  ~~~f)) + 3 * (e |||  ~~~f) + 4 * (e |||  ~~~(d |||  ~~~f)) + 1 * ( ~~~f ||| (d ^^^ e)) - 5 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 1 * (e ^^^ (d ||| (e &&& f))) + 1 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) + 1 * ((d ||| e) &&& (e ^^^ f)) + 7 *  ~~~( ~~~d ||| ( ~~~e &&& f)) - 6 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) + 4 * ((d &&& e) ||| (e ^^^ f)) - 5 *  ~~~(d &&& e) + 2 * (e ^^^ (d |||  ~~~f)) - 1 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 1 *  ~~~(d ^^^ e) + 7 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) - 7 * ( ~~~e ||| (d ^^^ f)) - 2 * (f &&&  ~~~(d ^^^ e)) - 3 * ( ~~~d ||| ( ~~~e ||| f)) - 1 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 1 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 3 * (f ^^^ (d ||| ( ~~~e ||| f))) + 11 * (e ||| (d &&& f)) - 6 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) + 1 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 1 *  ~~~(d ||| (e &&& f)) - 2 * (e ^^^  ~~~(d ||| (e ^^^ f))) + 2 * (e &&& (d ^^^ f)) + 11 *  ~~~(d &&& (e ||| f)) + 7 * ( ~~~d ||| (e ||| f)) - 6 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) + 2 * ((d &&& f) |||  ~~~(e ||| f)) - 11 * (e &&&  ~~~(d ^^^ f)) - 1 *  ~~~(d &&& ( ~~~e &&& f)) - 11 *  ~~~(d &&&  ~~~e) + 1 * ((d &&& e) |||  ~~~(e ||| f)) + 4 *  ~~~( ~~~d &&& ( ~~~e &&& f)) - 3 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) - 7 * ((d &&& e) |||  ~~~(e ^^^ f)) - 5 * (d &&& f) - 7 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) + 5 *  ~~~(d ^^^ (e ||| f)) + 3 *  ~~~(d ^^^ (e &&& f)) + 2 * (f ^^^ (d ||| ( ~~~e &&& f))) + 11 * ( ~~~f |||  ~~~(d ^^^ e)) + 2 * (e &&& f) + 5 * ((d &&& e) |||  ~~~(e |||  ~~~f)) + 1 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 4 *  ~~~(d ||| (e ||| f)) - 24 *  ~~~(d ||| ( ~~~e ||| f)) - 11 *  ~~~( ~~~d ||| (e ||| f)) - 20 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 13 * ( ~~~d &&& ( ~~~e &&& f)) - 5 * ( ~~~d &&& (e &&& f)) - 13 * (d &&& ( ~~~e &&& f)) - 3 * (d &&& (e &&& f)) =  - 5 * (f ^^^  ~~~( ~~~d &&& ( ~~~e &&& f)))

@[simp]
theorem scanl_zero (init : Bool) (f : Bool → Bool → Bool) (s : BitStream) : scanl init f s 0 = f init (s 0)

theorem e_2068 :
    11 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 1 *  ~~~(e ||| f) + 7 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) + 1 * ((d &&& f) |||  ~~~(e ||| f)) + 2 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) + 1 * (f ||| (d &&& e)) - 1 * (e &&& (d |||  ~~~f)) - 1 * ( ~~~d &&& (e ||| f)) - 6 *  ~~~(d &&&  ~~~f) - 2 * ( ~~~f &&& (d ^^^ e)) + 4 * f + 5 * ( ~~~f |||  ~~~(d ^^^ e)) + 3 * (f ^^^  ~~~(d ||| (e &&& f))) + 5 * ( ~~~d ||| (e &&& f)) + 3 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) - 1 * (e ^^^ (d ||| (e ^^^ f))) - 2 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) - 7 *  ~~~(d &&& ( ~~~e ||| f)) + 1 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 1 * (e &&&  ~~~(d ^^^ f)) - 11 * ( ~~~f &&&  ~~~(d ^^^ e)) + 1 * (e ^^^ (d ||| ( ~~~e ||| f))) - 2 * (f ||| (d ^^^ e)) + 5 * ( ~~~e ||| (d ^^^ f)) + 2 * (f ^^^  ~~~(d |||  ~~~e)) + 7 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 3 * (f ^^^  ~~~(d &&& (e &&& f))) - 3 * ((d &&& e) |||  ~~~(e ||| f)) - 3 * (f ^^^  ~~~(d &&&  ~~~e)) + 5 * (e ^^^ (d &&& (e ||| f))) - 1 * (f ^^^ (d &&&  ~~~e)) - 17 *  ~~~(d ||| (e ||| f)) - 12 *  ~~~(d ||| ( ~~~e ||| f)) - 20 *  ~~~( ~~~d ||| (e ||| f)) - 6 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 12 * ( ~~~d &&& ( ~~~e &&& f)) - 26 * ( ~~~d &&& (e &&& f)) - 18 * (d &&& ( ~~~e &&& f)) - 17 * (d &&& (e &&& f)) = 3 * (e ^^^  ~~~(d &&& (e &&& f)))

theorem and_and_logic_or_1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1), x_1 &&& x = 1#1 → ¬x = 1#1 → False

theorem test_and1_logical_thm (e e_1 : IntW 32) :
  select (icmp IntPred.sge e_1 (const? 32 0)) (icmp IntPred.slt e_1 (LLVM.and e (const? 32 2147483647)))
      (const? 1 0) ⊑
    select (icmp IntPred.sgt e_1 (const? 32 (-1))) (icmp IntPred.slt e_1 (LLVM.and e (const? 32 2147483647)))
      (const? 1 0)

theorem test_sub_nsw__nuw_is_safe_proof : test_sub_nsw__nuw_is_safe_before ⊑ test_sub_nsw__nuw_is_safe_after

theorem select_lshr_icmp_const_proof : select_lshr_icmp_const_before ⊑ select_lshr_icmp_const_after

theorem main7d_logical_proof : main7d_logical_before ⊑ main7d_logical_after

theorem ashrslt_02_14_exact_proof : ashrslt_02_14_exact_before ⊑ ashrslt_02_14_exact_after

theorem sdiv_eq_smin_thm (e e_1 : IntW 8) :
  icmp IntPred.eq (LLVM.sdiv e_1 e) (const? 8 (-128)) ⊑
    LLVM.and (icmp IntPred.eq e_1 (const? 8 (-128))) (icmp IntPred.eq e (const? 8 1))

theorem udiv_shl_pair2_proof : udiv_shl_pair2_before ⊑ udiv_shl_pair2_after

theorem e_620 :
    1 * (x |||  ~~~y) + 5 * (x ||| y) + 2 *  ~~~(x &&&  ~~~y) + 3 * (x ^^^ y) - 1 *  ~~~(x &&&  ~~~x) - 1 *  ~~~(x ^^^ y) - 2 *  ~~~(x ||| y) - 10 *  ~~~(x |||  ~~~y) - 8 * (x &&&  ~~~y) - 6 * (x &&& y) =  - 1 *  ~~~x

theorem ashr_lshr2_proof : ashr_lshr2_before ⊑ ashr_lshr2_after

theorem uge_swap_and_max_proof : uge_swap_and_max_before ⊑ uge_swap_and_max_after

theorem t0_thm (e e_1 e_2 e_3 : IntW 32) :
  LLVM.xor (LLVM.or (icmp IntPred.eq e_3 e_2) (icmp IntPred.eq e_1 e)) (const? 1 1) ⊑
    LLVM.and (icmp IntPred.ne e_3 e_2) (icmp IntPred.ne e_1 e)

theorem bools2_logical_commute3_and1_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 &&& x_1 = 1#1 → ¬x_1 = 1#1 → 1#1 = x

theorem sext_thm.extracted_1._1 : ∀ (x : BitVec 16),
  (zeroExtend 32 x ^^^ 32768#32) + BitVec.ofInt 32 (-32768) = signExtend 32 x

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 and_ne_with_one_bit_diff_constants2_logical_thm.extracted_1._2 : ∀ (x : BitVec 19),
  ¬ofBool (x != 65#19) = 1#1 → 0#1 = ofBool (x &&& BitVec.ofInt 19 (-129) != 65#19)

theorem xor_sext_to_sel_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  signExtend 32 x_1 ^^^ x = x ^^^ signExtend 32 x_1

theorem t1_lshr_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ¬signExtend 32 x ≥ ↑32 →
    ¬(True ∧ x.msb = true ∨ zeroExtend 32 x ≥ ↑32) → x_1 >>> signExtend 32 x = x_1 >>> zeroExtend 32 x

theorem test4a_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(31#32 ≥ ↑32 ∨ 31#32 ≥ ↑32) → ofBool (x.sshiftRight' 31#32 ||| (0#32 - x) >>> 31#32 <ₛ 1#32) = ofBool (x <ₛ 1#32)

theorem shift_xor_multiuse_cmp_and_proof : shift_xor_multiuse_cmp_and_before ⊑ shift_xor_multiuse_cmp_and_after

theorem ugt_swap_or_not_min_thm (e e_1 : IntW 8) :
  LLVM.or (icmp IntPred.ult e_1 e) (icmp IntPred.ne e (const? 8 0)) ⊑
    icmp IntPred.ne e (const? 8 0)

theorem zero_sign_bit2_thm (e e_1 : IntW 16) :
  add (LLVM.and e_1 (const? 16 32767)) (LLVM.and e (const? 16 32767)) ⊑
    add (LLVM.and e_1 (const? 16 32767)) (LLVM.and e (const? 16 32767)) { «nsw» := false, «nuw» := true }

theorem PR42691_2_logical_proof : PR42691_2_logical_before ⊑ PR42691_2_logical_after

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 negative_not_next_power_of_two_logical_proof : negative_not_next_power_of_two_logical_before ⊑ negative_not_next_power_of_two_logical_after

theorem ashr_sle_noexact_proof : ashr_sle_noexact_before ⊑ ashr_sle_noexact_after

theorem e_2294 :
    4 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 1 * (e ^^^  ~~~(d ||| f)) + 1 * (d &&& (e ||| f)) - 2 * (e ^^^ (d &&& (e ^^^ f))) + 11 * ((d &&& e) ^^^ (e ||| f)) - 11 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) - 7 * ((d ^^^ e) &&& (d ^^^ f)) - 1 *  ~~~(d ^^^ (e ||| f)) + 1 * (d &&& e) + 2 *  ~~~( ~~~d ||| (e &&& f)) - 2 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) + 1 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 7 * (e &&& (d |||  ~~~f)) - 6 * (e ^^^ (d ||| (e ||| f))) + 7 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 5 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) - 1 * (e ^^^ (d ||| (e &&& f))) + 3 * e + 7 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 2 *  ~~~( ~~~d &&& (e &&& f)) + 3 * ( ~~~d &&& (e ^^^ f)) - 2 * ( ~~~f &&&  ~~~(d ^^^ e)) + 1 * (e ^^^ (d ||| (e ^^^ f))) + 1 * ( ~~~e ||| (d ^^^ f)) + 4 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 1 * (e |||  ~~~(d ^^^ f)) - 1 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 1 * (f ||| (d &&& e)) - 2 * (f ^^^ (d &&& (e ||| f))) - 11 * (d ||| e) + 3 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) + 1 * (f &&& (d ||| e)) + 1 * (e ^^^  ~~~(d &&& (e ||| f))) - 6 * (f &&&  ~~~(d ^^^ e)) + 2 *  ~~~(e &&& f) - 7 *  ~~~(d &&& f) - 1 *  ~~~( ~~~d &&& (e ^^^ f)) + 3 * (e ||| (d ^^^ f)) + 7 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) + 2 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 1 * (f &&&  ~~~(d &&& e)) + 2 * (d |||  ~~~f) - 5 * (e ^^^ (d &&& f)) - 3 * f + 2 * (e ^^^ ( ~~~d ||| (e &&& f))) - 1 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 1 * (d ||| (e ||| f)) - 1 *  ~~~(d &&& ( ~~~e &&& f)) - 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) - 3 * (f &&& (d |||  ~~~e)) + 5 * (d ^^^ (e ||| f)) - 6 * (e ^^^ (d ||| f)) - 3 * (e &&& (d ^^^ f)) - 6 * (e &&&  ~~~(d ^^^ f)) - 15 *  ~~~(d ||| (e ||| f)) - 5 *  ~~~(d ||| ( ~~~e ||| f)) - 7 *  ~~~( ~~~d ||| (e ||| f)) - 1 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 11 * ( ~~~d &&& ( ~~~e &&& f)) - 13 * ( ~~~d &&& (e &&& f)) - 5 * (d &&& ( ~~~e &&& f)) + 3 * (d &&& (e &&& f)) =  - 5 * ((d &&& e) |||  ~~~(e ^^^ f)) + 5 * ((d |||  ~~~e) &&& (e ^^^ f))

theorem and_nosignbit_lshr_thm (e : IntW 32) :
  lshr (LLVM.and e (const? 32 2147418112)) (const? 32 8) ⊑ LLVM.and (lshr e (const? 32 8)) (const? 32 8388352)

theorem lshrult_02_05_exact_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 2) { «exact» := true }) (const? 4 5) ⊑ const? 1 1

theorem sub_to_xor_and_commuted_proof : sub_to_xor_and_commuted_before ⊑ sub_to_xor_and_commuted_after

theorem test_shl__none_are_safe_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ofBool (x_1 &&& BitVec.ofInt 32 (-2) == 0#32) = 1#1 →
    2#32 ≥ ↑32 ∨
        True ∧ (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)).msb = true ∨
          zeroExtend 64 (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)) ≥ ↑64 →
      False

theorem or_not_and_commute9_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬((x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true ∨
        (x_1 == 0 || 32 != 1 && 42#32 == intMin 32 && x_1 == -1) = true ∨
          (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨
            (x_1 == 0 || 32 != 1 && 42#32 == intMin 32 && x_1 == -1) = true ∨
              (x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true ∨
                (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true) →
    (x_1 == 0 || 32 != 1 && 42#32 == intMin 32 && x_1 == -1) = true ∨
        (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨
          (x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true →
      False

theorem select_constants_and_icmp_ne0_zero_fval_proof : select_constants_and_icmp_ne0_zero_fval_before ⊑ select_constants_and_icmp_ne0_zero_fval_after

theorem no_shift_xor_multiuse_and_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (0#32 != x_1 &&& 4096#32) = 1#1 →
    ¬ofBool (x_1 &&& 4096#32 == 0#32) = 1#1 →
      (x &&& BitVec.ofInt 32 (-4097)) * (x &&& BitVec.ofInt 32 (-4097)) = x * (x &&& BitVec.ofInt 32 (-4097))

theorem bools2_logical_commute1_thm.extracted_1._21 : ∀ (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

theorem Valuation.eq_nil (V : Valuation (empty : Ctxt Ty)) : V = Valuation.nil

theorem substitute_constant_or_ne_swap_sle_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != 42#8) = 1#1 → ofBool (x ≤ₛ x_1) = ofBool (x <ₛ 43#8)

theorem negate_zext_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8),
  x_1 - zeroExtend 8 x = x_1 + signExtend 8 x

theorem ne_smax1_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (select (icmp IntPred.sgt e_1 e) e_1 e) e_1 ⊑ icmp IntPred.slt e_1 e

theorem select_bittest_to_shl_negative_test_thm (e : IntW 32) :
  add (select (icmp IntPred.eq (LLVM.and e (const? 32 1)) (const? 32 0)) (const? 32 2) (const? 32 4)) (const? 32 2)
      { «nsw» := true, «nuw» := true } ⊑
    select (icmp IntPred.eq (LLVM.and e (const? 32 1)) (const? 32 0)) (const? 32 4) (const? 32 6)

theorem lshrult_02_01_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬2#4 ≥ ↑4 → ofBool (x >>> 2#4 <ᵤ 1#4) = ofBool (x <ᵤ 4#4)

theorem udiv_i1_is_op0_thm (e e_1 : IntW 1) : LLVM.udiv e_1 e ⊑ e_1

theorem shl_nsw_add_negative_proof : shl_nsw_add_negative_before ⊑ shl_nsw_add_negative_after

theorem ugt_swap_and_not_min_logical_proof : ugt_swap_and_not_min_logical_before ⊑ ugt_swap_and_not_min_logical_after

theorem or_and1_thm.extracted_1._5 : ∀ (x x_1 x_2 : BitVec 1),
  (x_2 ^^^ 1#1) &&& x_1 = 1#1 → ¬x_2 = 1#1 → ¬x_1 = 1#1 → x = 0#1

theorem test2_logical_thm (e e_1 : IntW 1) :
  select (select e_1 e (const? 1 0)) e_1 (const? 1 0) ⊑ select e_1 e (const? 1 0)

theorem shl_xor_xor_good_mask_proof : shl_xor_xor_good_mask_before ⊑ shl_xor_xor_good_mask_after

theorem ule_swap_or_min_commute_proof : ule_swap_or_min_commute_before ⊑ ule_swap_or_min_commute_after

theorem ashrslt_03_04_thm (e : IntW 4) : icmp IntPred.slt (ashr e (const? 4 3)) (const? 4 4) ⊑ const? 1 1

theorem ule_umax2_proof : ule_umax2_before ⊑ ule_umax2_after

theorem zext_sext_add_icmp_sgt_1_thm (e e_1 : IntW 1) :
  icmp IntPred.sgt (add (zext 8 e_1) (sext 8 e)) (const? 8 1) ⊑ const? 1 0

theorem lshrult_02_14_exact_proof : lshrult_02_14_exact_before ⊑ lshrult_02_14_exact_after

theorem trunc_shl_15_i16_i32_thm (e : IntW 32) : trunc 16 (shl e (const? 32 15)) ⊑ shl (trunc 16 e) (const? 16 15)

theorem e_1332 :
    4 *  ~~~(z &&& t) - 1 *  ~~~(z &&&  ~~~t) - 11 * (z |||  ~~~t) - 1 *  ~~~t + 1 *  ~~~(z &&&  ~~~z) - 1 *  ~~~(z ^^^ t) + 9 *  ~~~(z ||| t) - 4 *  ~~~(z |||  ~~~t) + 7 * (z &&&  ~~~t) =  - 12 * (z &&& t)

theorem test17_proof : test17_before ⊑ test17_after

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

theorem xor_or_thm.extracted_1._8 : ∀ (x x_1 : BitVec 32) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬x_2 ^^^ 1#1 = 1#1 → ofBool (x_1 <ᵤ x) ^^^ 1#1 = 0#1

theorem e_101 :
    1 *  ~~~(x &&&  ~~~x) - 2 * x - 11 * (x |||  ~~~y) - 1 *  ~~~(x |||  ~~~y) + 12 * (x &&&  ~~~y) + 12 * (x &&& y) =  - 10 *  ~~~(x ||| y)

theorem test2_thm.extracted_1._2 : ∀ (x : BitVec 167),
  ¬(9#577 ≥ ↑577 ∨ 8#577 ≥ ↑577) →
    ¬(9#167 ≥ ↑167 ∨ 8#167 ≥ ↑167) →
      truncate 167 (zeroExtend 577 x >>> 9#577 ||| zeroExtend 577 x <<< 8#577) = x >>> 9#167 ||

theorem lshr_shl_demand4_proof : lshr_shl_demand4_before ⊑ lshr_shl_demand4_after

theorem test3_proof : test3_before ⊑ test3_after

theorem positive_samevar_proof : positive_samevar_before ⊑ positive_samevar_after

theorem test6_proof : test6_before ⊑ test6_after

theorem bv_AndOrXor_2443 :
    ∀ (e e_1 : LLVM.IntW w),
      LLVM.xor (LLVM.ashr (LLVM.xor e_1 (LLVM.const? w (-1))) e) (LLVM.const? w (-1)) ⊑ LLVM.ashr e_1 e

theorem scalar_i8_shl_uge_const_thm (e : IntW 8) :
  icmp IntPred.uge (shl e (const? 8 5)) (const? 8 64) ⊑
    icmp IntPred.ne (LLVM.and e (const? 8 6)) (const? 8 0)

theorem ashrslt_01_15_thm (e : IntW 4) :
  icmp IntPred.slt (ashr e (const? 4 1)) (const? 4 (-1)) ⊑ icmp IntPred.slt e (const? 4 (-2))

theorem bor_lor_left1_thm (e e_1 : IntW 1) : select (LLVM.or e_1 e) (const? 1 1) e_1 ⊑ LLVM.or e_1 e

theorem n11_wrong_pred3_proof : n11_wrong_pred3_before ⊑ n11_wrong_pred3_after

theorem t1_lshr_proof : t1_lshr_before ⊑ t1_lshr_after

theorem or_logic_or_logic_and_2_thm.extracted_1._7 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 ||

theorem lshrugt_01_11_exact_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬(True ∧ x >>> 1#4 <<< 1#4 ≠ x ∨ 1#4 ≥ ↑4) → ofBool (BitVec.ofInt 4 (-5) <ᵤ x >>> 1#4) = 0#1

theorem land_bor_left2_proof : land_bor_left2_before ⊑ land_bor_left2_after

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

theorem sgt_positive_multip_rem_zero_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.smulOverflow 7#8 = true) → ofBool (21#8 <ₛ x * 7#8) = ofBool (3#8 <ₛ x)

theorem e_2392 :
    4 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) - 7 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) - 3 * (d ||| (e ||| f)) - 6 * (f ^^^  ~~~(d ||| e)) + 2 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 5 *  ~~~(d ^^^ (e &&& f)) + 2 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 11 * ( ~~~d &&& ( ~~~e ||| f)) + 3 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 4 *  ~~~d - 3 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) - 5 *  ~~~(d &&& (e ||| f)) - 11 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 2 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) - 2 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 7 * (f ||| (d ^^^ e)) - 6 * ( ~~~f &&& (d ^^^ e)) + 4 * ((e &&& f) ||| (d &&& (e ||| f))) - 7 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 2 * (e ||| (d ^^^ f)) + 1 * (d ||| f) - 3 * (f ^^^ (d ||| (e &&& f))) - 7 * ( ~~~d &&& (e ||| f)) - 1 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) + 1 * (d ||| e) + 3 * ((d ||| e) &&& (e ^^^ f)) - 6 * (e ^^^  ~~~(d &&& f)) - 2 * (e ||| f) + 2 * (d ||| (e ^^^ f)) - 1 * (e ||| (d &&& f)) + 1 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 1 * (e ^^^ (d &&&  ~~~f)) + 3 * ( ~~~e &&& (d ^^^ f)) - 1 *  ~~~(e ||| f) - 11 *  ~~~(d ^^^ e) + 1 * (d ^^^ f) + 3 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 1 *  ~~~(d |||  ~~~f) + 7 *  ~~~(d ^^^ (e ||| f)) + 7 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 1 * (f ^^^ (d ||| ( ~~~e &&& f))) + 11 *  ~~~( ~~~d &&& (e ||| f)) + 2 * (d ||| ( ~~~e ||| f)) - 1 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) + 4 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) + 5 *  ~~~(e ^^^ f) - 1 * ( ~~~f &&&  ~~~(d ^^^ e)) - 6 * (e &&& (d |||  ~~~f)) + 7 * ((d &&& e) ^^^ (e ||| f)) + 2 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 3 * (f ^^^ (d &&& (e ||| f))) - 11 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 1 * (e |||  ~~~(d ||| f)) + 2 * (e |||  ~~~(d |||  ~~~f)) - 5 * (e ^^^ (d &&& f)) + 1 *  ~~~(d ^^^ f) + 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 11 * (e ^^^  ~~~(d &&& (e ^^^ f))) - 11 * (e ^^^ (d ||| ( ~~~e &&& f))) + 1 * (f ^^^  ~~~(d &&& e)) - 7 * (e ^^^ (d ||| ( ~~~e ||| f))) + 5 * ( ~~~d ||| ( ~~~e ||| f)) + 1 *  ~~~(d &&& ( ~~~e ||| f)) - 2 * (d ||| (e &&& f)) - 1 *  ~~~(d ||| (e ||| f)) + 38 *  ~~~(d ||| ( ~~~e ||| f)) + 13 *  ~~~( ~~~d ||| (e ||| f)) - 1 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 6 * ( ~~~d &&& ( ~~~e &&& f)) + 9 * (d &&& ( ~~~e &&& f)) + 19 * (d &&& (e &&& f)) =  - 2 * (d ||| ( ~~~e &&& f)) - 26 * ( ~~~d &&& (e &&& f))

@[simp] theorem Com.changeVars_rets :
    (Com.rets (d:=d) (Γ:=Γ) (eff := eff) vs).changeVars
    = fun (map : Γ.Hom Δ) => Com.rets (vs.map map)

theorem PR24763_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬1#32 ≥ ↑32 → ¬1#8 ≥ ↑8 → truncate 16 (signExtend 32 x >>> 1#32) = signExtend 16 (x.sshiftRight' 1#8)

theorem sub_zext_trunc_lshr_thm (e : IntW 64) :
  sub (const? 32 10) (zext 32 (trunc 1 (lshr e (const? 64 15)))) ⊑
    add (ashr (shl (trunc 32 e) (const? 32 16)) (const? 32 31)) (const? 32 10)
      { «nsw» := true, «nuw» := false }

theorem lshr_pow2_ult_proof : lshr_pow2_ult_before ⊑ lshr_pow2_ult_after

@[simp]
theorem EnvFin.cons_zero (env : EnvFin w n) (b : BitVec w) :
  (env.cons b) 0 = b

theorem sub_ult_zext_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 8),
  ofBool (x_2 - x_1 <ᵤ zeroExtend 8 x) = ofBool (x_2 == x_1) &&& x

theorem or_and_not_not_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (LLVM.and (LLVM.xor (LLVM.or e_2 e_1) (const? 32 (-1))) e) (LLVM.xor (LLVM.or e e_2) (const? 32 (-1))) ⊑
    LLVM.xor (LLVM.or (LLVM.and e_1 e) e_2) (const? 32 (-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 eq_3210_proof : eq_3210_before ⊑ eq_3210_after

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

theorem ule_and_min_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ule e_1 e) (icmp IntPred.eq e_1 (const? 8 0)) (const? 1 0) ⊑
    icmp IntPred.eq e_1 (const? 8 0)

theorem positive_biggershl_shlnsw_lshrexact_thm (e : IntW 8) :
  shl (lshr e (const? 8 3) { «exact» := true }) (const? 8 6) { «nsw» := true, «nuw» := false } ⊑
    shl e (const? 8 3) { «nsw» := true, «nuw» := true }

theorem test_shift_negative_proof : test_shift_negative_before ⊑ test_shift_negative_after

theorem or_disjoint_with_xor_proof : or_disjoint_with_xor_before ⊑ or_disjoint_with_xor_after

theorem e_643 :
    4 * (x |||  ~~~y) + 1 * (x ||| y) - 1 *  ~~~(x &&&  ~~~y) - 11 *  ~~~(x ^^^ y) + 5 * x + 1 * y + 10 *  ~~~(x ||| y) - 6 *  ~~~(x |||  ~~~y) - 15 * (x &&&  ~~~y) + 3 * (x &&& y) =  - 7 * (x ^^^ y) + 2 *  ~~~(x &&&  ~~~x)

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

theorem eq_smin3_proof : eq_smin3_before ⊑ eq_smin3_after

theorem lshrugt_01_13_proof : lshrugt_01_13_before ⊑ lshrugt_01_13_after

theorem scalar_i32_lshr_and_negC_eq_X_is_constant1_proof : scalar_i32_lshr_and_negC_eq_X_is_constant1_before ⊑ scalar_i32_lshr_and_negC_eq_X_is_constant1_after

theorem p0_thm (e e_1 : IntW 8) :
  icmp IntPred.ugt (shl (const? 8 1) e_1) e ⊑ icmp IntPred.eq (lshr e e_1) (const? 8 0)

theorem e_1419 :
    11 * (z ||| t) - 2 *  ~~~z + 4 * t + 1 *  ~~~(z &&& t) + 1 *  ~~~(z &&&  ~~~t) + 3 *  ~~~(z ^^^ t) + 2 * (z |||  ~~~t) - 3 *  ~~~t - 11 * (z &&&  ~~~t) - 21 * (z &&& t) = 15 *  ~~~(z |||  ~~~t) + 2 *  ~~~(z ||| t)

theorem masked_or_A_slightly_optimized_proof : masked_or_A_slightly_optimized_before ⊑ masked_or_A_slightly_optimized_after

theorem test1_proof : test1_before ⊑ test1_after

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 test_not_const_shr_and_1_ne_0_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 →
    ¬(True ∧ 1#32 <<< x >>> x ≠ 1#32 ∨ x ≥ ↑32) →
      ofBool (42#32 >>> x &&& 1#32 == 0#32) = ofBool (1#32 <<< x &&& 42#32 == 0#32)

theorem icmp_ne_zext_eq_zero_proof : icmp_ne_zext_eq_zero_before ⊑ icmp_ne_zext_eq_zero_after

theorem e_1167 :
     - 11 * (z |||  ~~~t) + 2 *  ~~~(z &&& t) - 6 * (z ||| t) - 11 *  ~~~z + 16 *  ~~~(z ||| t) + 11 *  ~~~(z |||  ~~~t) + 15 * (z &&&  ~~~t) + 13 * (z &&& t) =  - 4 *  ~~~(z &&&  ~~~t)

theorem main11_thm (e : IntW 32) :
  select
      (LLVM.or (icmp IntPred.eq (LLVM.and e (const? 32 64)) (const? 32 0))
        (icmp IntPred.sge (trunc 8 e) (const? 8 0)))
      (const? 32 2) (const? 32 1) ⊑
    select (icmp IntPred.eq (LLVM.and e (const? 32 192)) (const? 32 192)) (const? 32 1) (const? 32 2)

theorem trunc_shl_ashr_var_proof : trunc_shl_ashr_var_before ⊑ trunc_shl_ashr_var_after

theorem test11_proof : test11_before ⊑ test11_after

theorem icmp_ne_and_pow2_shl_pow2_proof : icmp_ne_and_pow2_shl_pow2_before ⊑ icmp_ne_and_pow2_shl_pow2_after

theorem ashr_ugt_noexact_thm (e : IntW 8) :
  icmp IntPred.ugt (ashr e (const? 8 3)) (const? 8 10) ⊑ icmp IntPred.ugt e (const? 8 87)

theorem test_sub_nsw__all_are_safe_proof : test_sub_nsw__all_are_safe_before ⊑ test_sub_nsw__all_are_safe_after

theorem bools_logical_thm.extracted_1._7 : ∀ (x x_1 : BitVec 1), ¬x_1 ^^^ 1#1 = 1#1 → x_1 = 1#1 → 0#1 = 1#1 → False

theorem no_masks_with_logical_or_proof : no_masks_with_logical_or_before ⊑ no_masks_with_logical_or_after

theorem test3_proof : test3_before ⊑ test3_after

theorem lshrugt_03_10_proof : lshrugt_03_10_before ⊑ lshrugt_03_10_after

theorem test5_apint_proof : test5_apint_before ⊑ test5_apint_after

theorem t0_proof : t0_before ⊑ t0_after

theorem ugt_and_min_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.eq e_1 (const? 8 0)) (icmp IntPred.ugt e_1 e) (const? 1 0) ⊑ const? 1 0

theorem select_icmp_ne_0_and_4096_or_32_thm.extracted_1._3 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (0#32 != x_1 &&& 4096#32) = 1#1 → 7#32 ≥ ↑32 → False

theorem differentconsts_thm.extracted_1._6 : ∀ (x : BitVec 32),
  ¬ofBool (x + 16#32 <ᵤ 144#32) = 1#1 →
    ¬ofBool (x <ₛ 128#32) = 1#1 →
      ¬ofBool (127#32 <ₛ x) = 1#1 → ¬ofBool (x <ₛ BitVec.ofInt 32 (-16)) = 1#1 → -1#16 = truncate 16 x

theorem ashrsgt_02_14_exact_thm (e : IntW 4) :
  icmp IntPred.sgt (ashr e (const? 4 2) { «exact» := true }) (const? 4 (-2)) ⊑
    icmp IntPred.ne e (const? 4 (-8))

theorem demorgan_nor_use2a_proof : demorgan_nor_use2a_before ⊑ demorgan_nor_use2a_after

theorem lshrugt_01_00_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 1)) (const? 4 0) ⊑ icmp IntPred.ugt e (const? 4 1)

theorem positive_samevar_shlnuw_thm (e e_1 : IntW 32) : lshr (shl e_1 e { «nsw» := false, «nuw» := true }) e ⊑ e_1

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

theorem p0_proof : p0_before ⊑ p0_after

@[aesop 80% unsafe]
theorem Std.HashMap.mem_keys_insert_old [BEq K] [LawfulBEq K] [Hashable K] [LawfulHashable K] (m : Std.HashMap K V) (k k' : K) :
    k ∈ m → k ∈ m.insert k' v

theorem trunc_sandwich_max_sum_shift_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(20#32 ≥ ↑32 ∨ 11#12 ≥ ↑12) →
    ¬(31#32 ≥ ↑32 ∨
          True ∧ signExtend 32 (truncate 12 (x >>> 31#32)) ≠ x >>> 31#32 ∨
            True ∧ zeroExtend 32 (truncate 12 (x >>> 31#32)) ≠ x >>> 31#32) →
      truncate 12 (x >>> 20#32) >>> 11#12 = truncate 12 (x >>> 31#32)

theorem for_return {t : Arith.Ty} (istart istep: Var Γ Arith.Ty.int)
    (niters : Var Γ .nat) (v : Var Γ t) :
    Expr.denoteOp (for_ (t := t) istart istep niters v (RegionRet t ⟨1, by simp⟩)) Γv = [Γv v]ₕ

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 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 or_logic_or_logic_and_5_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1),
  ¬x_1 ||

theorem uadd_sat_flipped_wrong_bounds4_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (BitVec.ofInt 32 (-8) ≤ᵤ x) = 1#1 → ¬ofBool (BitVec.ofInt 32 (-9) <ᵤ x) = 1#1 → -1#32 = x + 9#32

theorem select_icmp_eq_and_1_0_lshr_tv_thm.extracted_1._4 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 &&& 1#8 != 0#8) = 1#1 → ¬(1#8 ≥ ↑8 ∨ x_1 <<< 1#8 &&& 2#8 ≥ ↑8) → x = x >>> (x_1 <<< 1#8 &&& 2#8)

theorem and_two_ranges_to_mask_and_range_proof : and_two_ranges_to_mask_and_range_before ⊑ and_two_ranges_to_mask_and_range_after

theorem demorgan_nor_use2bc_proof : demorgan_nor_use2bc_before ⊑ demorgan_nor_use2bc_after

theorem test19_commutative1_thm (e e_1 : IntW 32) :
  urem e_1 (add (shl (const? 32 1) e) (LLVM.and (shl (const? 32 1) e) (shl (const? 32 1) e_1))) ⊑
    LLVM.and e_1
      (add
        (add (shl (const? 32 1) e { «nsw» := false, «nuw» := true })
          (LLVM.and (shl (const? 32 1) e { «nsw» := false, «nuw» := true })
            (shl (const? 32 1) e_1 { «nsw» := false, «nuw» := true })))
        (const? 32 (-1)))

theorem uaddo_commute4_proof : uaddo_commute4_before ⊑ uaddo_commute4_after

theorem ashrslt_03_13_thm (e : IntW 4) : icmp IntPred.slt (ashr e (const? 4 3)) (const? 4 (-3)) ⊑ const? 1 0

theorem lsb_mask_sign_zext_commuted_proof : lsb_mask_sign_zext_commuted_before ⊑ lsb_mask_sign_zext_commuted_after

theorem ashrsgt_01_05_proof : ashrsgt_01_05_before ⊑ ashrsgt_01_05_after

theorem e_1202 :
    1 *  ~~~(z &&& t) + 2 *  ~~~(z &&&  ~~~z) + 1 * (z ||| t) - 5 *  ~~~(z &&&  ~~~t) - 1 * z + 2 *  ~~~(z ||| t) + 3 *  ~~~(z |||  ~~~t) + 2 * (z &&&  ~~~t) =  - 3 * t + 5 * (z ^^^ t)

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

theorem e_215 :
     - 6 * (x ||| y) + 5 * (x |||  ~~~y) - 3 *  ~~~y + 2 * x + 13 *  ~~~(x |||  ~~~y) + 9 * (x &&&  ~~~y) + 6 * (x &&& y) = 7 *  ~~~(x &&&  ~~~x) - 5 *  ~~~(x ||| y)

theorem sle_smax1_proof : sle_smax1_before ⊑ sle_smax1_after

theorem t9_proof : t9_before ⊑ t9_after

theorem t1_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 1),
  x_1 = 1#1 → signExtend 8 x_1 + x ^^^ signExtend 8 x_1 = 0#8 - x

theorem testi64i32_proof : testi64i32_before ⊑ testi64i32_after

theorem uge_and_max_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.uge e_1 e) (icmp IntPred.eq e_1 (const? 8 (-1))) (const? 1 0) ⊑
    icmp IntPred.eq e_1 (const? 8 (-1))

theorem test1_thm.extracted_1._2 : ∀ (x : BitVec 33), ¬4096#33 = 0 → ¬12#33 ≥ ↑33 → x / 4096#33 = x >>> 12#33

theorem test5_proof : test5_before ⊑ test5_after

theorem sgt_swap_or_not_min_commute_proof : sgt_swap_or_not_min_commute_before ⊑ sgt_swap_or_not_min_commute_after

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

theorem src_is_notmask_sext_thm (e : IntW 8) (e_1 : IntW 16) :
  icmp IntPred.ule (LLVM.xor e_1 (const? 16 123))
      (LLVM.and (LLVM.xor (sext 16 (shl (const? 8 (-8)) e)) (const? 16 (-1))) (LLVM.xor e_1 (const? 16 123))) ⊑
    icmp IntPred.uge (LLVM.xor e_1 (const? 16 (-128))) (sext 16 (shl (const? 8 (-8)) e))

theorem ashr_lshr_cst2_proof : ashr_lshr_cst2_before ⊑ ashr_lshr_cst2_after

theorem fork_hs_dc_equiv_snd (x : DCOp.TokenStream):
    (DCOp.fork (x)).snd ~ (HandshakeOp.fork (x)).snd

theorem ashrslt_01_00_exact_proof : ashrslt_01_00_exact_before ⊑ ashrslt_01_00_exact_after

theorem icmp_sle5_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (x <<< 1#8).sshiftRight' 1#8 ≠ x ∨ 1#8 ≥ ↑8) → ofBool (x <<< 1#8 ≤ₛ 1#8) = ofBool (x <ₛ 1#8)

theorem ashr_exact_poison_constant_fold_thm.extracted_1._3 : ∀ (x : BitVec 8) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬(True ∧ 42#8 >>> 3#8 <<< 3#8 ≠ 42#8 ∨ 3#8 ≥ ↑8) → (42#8).sshiftRight' 3#8 = 5#8

theorem e_2407 :
     - 7 * (e ^^^ (d ||| ( ~~~e &&& f))) - 2 * (f ^^^ (d &&&  ~~~e)) - 1 * ( ~~~(d &&& e) &&& (e ^^^ f)) - 7 * (f &&&  ~~~(d &&&  ~~~e)) + 2 * (f ^^^ (d &&& e)) - 2 * e - 11 * (d ^^^ (e ^^^ f)) + 5 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 3 *  ~~~(e &&& f) + 11 * ( ~~~d &&& ( ~~~e ||| f)) - 3 * ((d &&& e) |||  ~~~(e ^^^ f)) - 1 * (f ^^^  ~~~(d |||  ~~~e)) - 5 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) - 5 * (f ^^^  ~~~(d &&& (e &&& f))) + 2 * (d ^^^ f) - 3 * (f &&& (d |||  ~~~e)) + 4 *  ~~~(d ||| e) + 5 * (d &&&  ~~~f) - 1 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 1 *  ~~~(d ^^^ (e &&& f)) + 11 * (e |||  ~~~(d |||  ~~~f)) - 7 * (d ^^^ (e &&& f)) - 11 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) + 1 * (d ||| (e ^^^ f)) - 5 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 6 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 2 * (f ^^^ ( ~~~d ||| (e &&& f))) + 1 * ((d |||  ~~~e) &&& (e ^^^ f)) - 1 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 1 * ((d &&& f) ^^^ (e ||| f)) - 1 * (f ^^^  ~~~(d ||| (e &&& f))) + 2 * (d ^^^ ( ~~~e &&& f)) + 1 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 *  ~~~( ~~~d &&& (e &&& f)) - 5 * ( ~~~e &&&  ~~~(d ^^^ f)) - 2 * (e ^^^ (d ||| ( ~~~e ||| f))) + 2 * (d ||| (e ||| f)) + 5 * (f ||| (d &&& e)) + 2 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 5 * (e ^^^ (d &&& f)) - 2 * (d ||| (e &&& f)) + 4 *  ~~~(e &&&  ~~~f) - 1 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 6 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 1 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) + 11 * (f &&&  ~~~(d &&& e)) - 11 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 6 * (f ^^^ (d &&& ( ~~~e ||| f))) - 1 * d + 7 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) + 7 * (f &&& (d ||| e)) + 4 *  ~~~(d &&& (e &&& f)) + 4 * ((d &&& e) |||  ~~~(e ||| f)) + 1 *  ~~~( ~~~d ||| (e &&& f)) - 1 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) + 1 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 2 * ((d &&& e) ^^^ (e ||| f)) + 7 * (f ^^^ ( ~~~d &&& (e ||| f))) + 11 * ((d &&& f) ||| (e &&&  ~~~f)) - 2 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) - 7 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 1 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 *  ~~~( ~~~d ||| (e ^^^ f)) + 1 * (d &&& (e ||| f)) + 2 * (e &&&  ~~~(d ^^^ f)) + 3 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) + 5 *  ~~~(d ||| (e ||| f)) + 27 *  ~~~(d ||| ( ~~~e ||| f)) + 59 *  ~~~( ~~~d ||| (e ||| f)) - 6 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 20 * ( ~~~d &&& ( ~~~e &&& f)) - 6 * (d &&& ( ~~~e &&& f)) - 7 * (d &&& (e &&& f)) = 6 * (e ^^^  ~~~(d &&& (e ||| f)))

theorem a_true_implies_b_false2_comm_thm.extracted_1._6 : ∀ (x x_1 : BitVec 1) (x_2 : BitVec 8),
  ofBool (x_2 == 10#8) = 1#1 → ¬ofBool (20#8 <ᵤ x_2) = 1#1 → x_1 &&& ofBool (20#8 <ᵤ x_2) = 0#1

theorem or_to_nxor4_proof : or_to_nxor4_before ⊑ or_to_nxor4_after

theorem BitVec.shiftConcat_eq_shiftLeft_or (x : BitVec w) (b : Bool) :
  x.shiftConcat b = (x <<< 1) ||

theorem add_eq_xor_add_mul_and_nt (x y : BitVec w) :
    x + y = (x ^^^ y) + 2 * (x &&& y)

theorem trunc_shl_lshr_var_thm (e e_1 : IntW 64) :
  trunc 32 (shl (lshr e_1 e) (const? 64 2)) ⊑ shl (trunc 32 (lshr e_1 e)) (const? 32 2)

@[simp]
theorem ctxt_cons {Γ : DerivedCtxt Δ} :
    (Γ.cons ty).ctxt = Γ.ctxt.cons ty

theorem test_shl_nsw__all_are_safe_thm.extracted_1._1 : ∀ (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 → False

theorem t6_ugt_sgt_128_proof : t6_ugt_sgt_128_before ⊑ t6_ugt_sgt_128_after

theorem t0_thm.extracted_1._18 : ∀ (x x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  ¬x_3 ^^^ 1#1 = 1#1 → ¬x_3 = 1#1 → ¬0#1 = 1#1 → False

theorem test36_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ (x + 7#32 &&& 240#32).msb = true) →
    zeroExtend 64 x + 7#64 &&& 240#64 = zeroExtend 64 (x + 7#32 &&& 240#32)

theorem imp3 (w : Nat) (a : BitVec w) : (a &&& a = 0#w) → a = 0#w

theorem masked_icmps_mask_notallzeros_bmask_mixed_5_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_5_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_5_logical_after

theorem and_xor_common_op_proof : and_xor_common_op_before ⊑ and_xor_common_op_after

theorem test8_proof : test8_before ⊑ test8_after

omit [Fintype S] [DecidableEq S] [LawfulBEq A] in
theorem processOneElem_grow (st : worklist.St A S) (final : S → Bool) (a : A) (sa' : S) (s : State) :
      let st' := processOneElem _ _ final s st (a, sa')
      ∃ sas, List.Perm st'.map.keys (sas ++ st.map.keys) ∧ st'.worklist.toList = st.worklist.toList ++ sas

theorem test1_proof : test1_before ⊑ test1_after

theorem icmp_ne_and_pow2_lshr_pow2_case2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → zeroExtend 32 (ofBool (4#32 >>> x &&& 8#32 == 0#32)) = 1#32

theorem bools_multi_uses1_logical_thm.extracted_1._5 : ∀ (x x_1 : BitVec 1),
  x_1 ^^^ 1#1 = 1#1 → ¬x_1 = 1#1 → x = 1#1 → 1#1 ^^^ x = x ^^^ x

theorem not_and_and_or_not_or_or_commute3_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬((x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true ∨
        (x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true) →
    ¬(x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true →
      (42#32).sdiv x_2 &&& (x_1 ^^^ -1#32) &&& x ||

theorem bitwise_or_logical_or_icmps_comm3_thm.extracted_1._6 : ∀ (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) ||

theorem demorgan_nor_use2bc_thm (e e_1 : IntW 8) :
  LLVM.sdiv
      (LLVM.sdiv (LLVM.xor (LLVM.or (LLVM.xor e_1 (const? 8 (-1))) e) (const? 8 (-1)))
        (mul (LLVM.or (LLVM.xor e_1 (const? 8 (-1))) e) (const? 8 23)))
      (mul e (const? 8 23)) ⊑
    LLVM.sdiv
      (LLVM.sdiv (LLVM.xor (LLVM.or e (LLVM.xor e_1 (const? 8 (-1)))) (const? 8 (-1)))
        (mul (LLVM.or e (LLVM.xor e_1 (const? 8 (-1)))) (const? 8 23)))
      (mul e (const? 8 23))

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

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 not_and_and_or_no_or_commute1_and_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (LLVM.and (LLVM.and e_2 e_1) (LLVM.xor e (const? 32 (-1)))) (LLVM.xor (LLVM.or e_1 e) (const? 32 (-1))) ⊑
    LLVM.and (LLVM.or e_2 (LLVM.xor e_1 (const? 32 (-1)))) (LLVM.xor e (const? 32 (-1)))

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

theorem t0_thm.extracted_1._19 : ∀ (x x_1 x_2 x_3 : BitVec 8) (x_4 : BitVec 1),
  x_4 ^^^ 1#1 = 1#1 → x_4 = 1#1 → ofBool (x_3 == x_2) = 1#1 → x_1 = x

theorem add0 (w : Nat) (a : BitVec w) : (a = a + 0#w)

theorem sgt_n1_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (-1#8 <ₛ truncate 8 x) = ofBool (x &&& 128#32 == 0#32)

theorem max_sub_ult_c1_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x <ᵤ 1#32) = 1#1 → 0#32 = signExtend 32 (ofBool (x == 0#32))

theorem e_370 :
     - 5 *  ~~~x + 1 * (x ||| y) - 6 *  ~~~(x ^^^ y) - 11 *  ~~~(x &&&  ~~~x) + 1 *  ~~~(x &&& y) + 4 * x + 14 *  ~~~(x |||  ~~~y) + 5 * (x &&&  ~~~y) =  - 12 * (x &&& y) - 21 *  ~~~(x ||| y)

theorem ashr_ugt_14_proof : ashr_ugt_14_before ⊑ ashr_ugt_14_after

theorem t0_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  ¬x_2 ^^^ 1#1 = 1#1 → x_2 = 1#1 → 0#1 = 1#1 → False

theorem test10_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬16#32 ≥ ↑32 →
    ¬(16#32 ≥ ↑32 ∨ True ∧ (x >>> 16#32).umulOverflow 65535#32 = true) →
      zeroExtend 64 (x >>> 16#32) * 65535#64 = zeroExtend 64 (x >>> 16#32 * 65535#32)

theorem icmp_sle_x_negy_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool ((x_1 ||| BitVec.ofInt 8 (-128)) &&& x ≤ₛ x) = 1#1

theorem samesign_commute2_thm (e e_1 : IntW 32) :
  LLVM.or (icmp IntPred.slt (LLVM.and e_1 e) (const? 32 0))
      (icmp IntPred.sgt (LLVM.or e e_1) (const? 32 (-1))) ⊑
    icmp IntPred.sgt (LLVM.xor e_1 e) (const? 32 (-1))

theorem shl_shl_thm (e : IntW 32) : shl (shl e (const? 32 6)) (const? 32 28) ⊑ const? 32 0

theorem bool1 (x : Bool) : x = x

theorem t3_ult_sgt_neg1_thm.extracted_1._14 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 <ᵤ 65536#32) = 1#1 → ¬ofBool (-1#32 <ₛ x_2) = 1#1 → ofBool (65535#32 <ₛ x_2) = 1#1 → x = x_1

theorem slt_and_shl_one_thm (e e_1 : IntW 8) :
  icmp IntPred.slt (LLVM.and e_1 (shl (const? 8 1) e)) (shl (const? 8 1) e) ⊑
    icmp IntPred.slt (LLVM.and e_1 (shl (const? 8 1) e { «nsw» := false, «nuw» := true }))
      (shl (const? 8 1) e { «nsw» := false, «nuw» := true })

theorem test15_thm.extracted_1._1 : ∀ (x : BitVec 32), 27#32 ≥ ↑32 ∨ 31#32 ≥ ↑32 → False

theorem e_2095 :
     - 1 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 11 *  ~~~(d &&&  ~~~e) + 1 * (e |||  ~~~(d ||| f)) + 4 * (f ^^^  ~~~(d &&& (e ||| f))) + 1 *  ~~~(d |||  ~~~e) - 11 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 5 * (e ^^^ ( ~~~d ||| (e ||| f))) + 7 *  ~~~(d ^^^ (e &&& f)) - 1 * ( ~~~d ||| ( ~~~e &&& f)) + 1 *  ~~~(d &&& e) - 3 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 3 * (e ^^^  ~~~(d |||  ~~~f)) - 7 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 7 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 6 * ((d &&& f) |||  ~~~(e ||| f)) + 11 * (e ^^^ (d ||| (e ^^^ f))) + 4 * ((d &&& e) ||| (e ^^^ f)) - 1 *  ~~~d - 11 * (f ^^^ (d |||  ~~~e)) + 1 * (f ||| (d ^^^ e)) + 2 * (d ^^^ (e ^^^ f)) - 2 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 5 * ( ~~~d ||| ( ~~~e ||| f)) - 7 * (f ^^^ (d &&& e)) - 1 * (e &&&  ~~~(d &&&  ~~~f)) + 1 * (f &&& (d ||| e)) + 1 * ( ~~~f ||| (d ^^^ e)) - 5 * (d ^^^ ( ~~~e &&& f)) - 1 *  ~~~(d ^^^ ( ~~~e ||| f)) + 7 * ((d &&& e) |||  ~~~(e ||| f)) + 2 * (f |||  ~~~(d ^^^ e)) + 11 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 6 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 5 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 7 * (f ^^^  ~~~(d ||| e)) + 45 *  ~~~(d ||| (e ||| f)) - 1 *  ~~~( ~~~d ||| (e ||| f)) + 53 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 26 * ( ~~~d &&& ( ~~~e &&& f)) + 40 * ( ~~~d &&& (e &&& f)) + 23 * (d &&& ( ~~~e &&& f)) + 18 * (d &&& (e &&& f)) =  - 7 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 5 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f)))

theorem ashrsgt_02_15_exact_proof : ashrsgt_02_15_exact_before ⊑ ashrsgt_02_15_exact_after

theorem main7b_logical_thm.extracted_1._11 : ∀ (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 → 0#1 = 1#1 → 0#32 = zeroExtend 32 (ofBool (x != x_1 &&& x))

theorem PR44545_thm.extracted_1._3 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 == 0#32) = 1#1 →
    ¬(True ∧ x.saddOverflow 1#32 = true ∨ True ∧ x.uaddOverflow 1#32 = true) →
      ¬(True ∧ (truncate 16 (x + 1#32)).saddOverflow (-1#16) = true) → truncate 16 (x + 1#32) + -1#16 = truncate 16 x

theorem and_xor_commute2_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(x_1 = 0 ∨ x = 0 ∨ x = 0) →
    ¬(x = 0 ∨ x_1 = 0) → 42#32 / x_1 &&& 42#32 / x ^^^ 42#32 / x = 42#32 / x &&& (42#32 / x_1 ^^^ -1#32)

theorem add_shl_same_amount_partial_nuw1_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 6),
  ¬(True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑6 ∨ True ∧ x <<< x_1 >>> x_1 ≠ x ∨ x_1 ≥ ↑6) → x_1 ≥ ↑6 → False

theorem ule_swap_or_min_proof : ule_swap_or_min_before ⊑ ule_swap_or_min_after

theorem main15_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (0#16 ≤ₛ truncate 16 x) ||

theorem icmp_slt_0_and_icmp_sgt_neg1_i64_thm (e : IntW 64) :
  LLVM.and (lshr e (const? 64 63)) (zext 64 (icmp IntPred.sgt e (const? 64 (-1)))) ⊑ const? 64 0

theorem and_or_not_not_commute1_proof : and_or_not_not_commute1_before ⊑ and_or_not_not_commute1_after

theorem or_and_not_not_commute4_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ((x_2 ||| x_1) ^^^ -1#32) &&& x ||

theorem or_signbit_select_shl_proof : or_signbit_select_shl_before ⊑ or_signbit_select_shl_after

theorem e_1873 :
    2 * (c ^^^ (a ||| (b ||| c))) + 2 * (b |||  ~~~(a |||  ~~~c)) - 3 * (b ^^^ (a &&&  ~~~c)) - 7 * ( ~~~(a |||  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 1 * (a ||| (b ||| c)) - 5 *  ~~~(a ^^^ (b &&& c)) + 2 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 11 * (c ^^^ (a &&&  ~~~b)) - 6 * ( ~~~(a ^^^ b) ||| (a ^^^ c)) + 4 *  ~~~(a &&& b) + 2 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) + 2 * ((a ^^^ b) |||  ~~~(a ^^^ c)) + 1 *  ~~~(a ||| c) + 4 * (c ^^^  ~~~(a &&& b)) - 1 * (a &&&  ~~~c) - 7 * ( ~~~(a &&& b) &&&  ~~~(b ^^^ c)) + 5 * (c ^^^  ~~~(a &&& (b ||| c))) - 6 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 1 *  ~~~( ~~~a ||| ( ~~~b &&& c)) - 6 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) + 1 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) + 1 * (c ^^^ ( ~~~a ||| (b ||| c))) - 7 * ( ~~~c &&&  ~~~(a ^^^ b)) + 7 *  ~~~(a ||| (b ^^^ c)) + 11 * (b ^^^ ( ~~~a ||| (b &&& c))) - 11 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 3 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 1 * ((a ^^^ b) ||| (a ^^^ c)) + 2 * ( ~~~(a ||| b) ||| (b ^^^ c)) - 2 *  ~~~a + 4 * (c ^^^  ~~~(a |||  ~~~b)) - 6 *  ~~~( ~~~a &&& (b ||| c)) - 5 * (c ^^^ ( ~~~a &&& (b ||| c))) - 11 * ((b &&& c) ||| (a &&& (b ||| c))) - 5 * (a |||  ~~~c) - 1 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 3 * (a ||| b) - 3 * (b |||  ~~~(a ||| c)) - 1 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) + 45 *  ~~~(a ||| (b ||| c)) + 31 *  ~~~(a ||| ( ~~~b ||| c)) + 43 *  ~~~( ~~~a ||| (b ||| c)) + 46 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 16 * ( ~~~a &&& ( ~~~b &&& c)) + 41 * ( ~~~a &&& (b &&& c)) + 22 * (a &&& ( ~~~b &&& c)) + 67 * (a &&& (b &&& c)) = 11 * (c ^^^  ~~~(a &&& (b &&& c))) - 1 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c)))

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

theorem positive_with_aggressive_icmp_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x <ᵤ 128#32) &&& ofBool (x + 256#32 <ᵤ 512#32) = ofBool (x <ᵤ 128#32)

theorem sle_swap_or_not_min_commute_logical_proof : sle_swap_or_not_min_commute_logical_before ⊑ sle_swap_or_not_min_commute_logical_after

theorem logic_or_logic_and_3_thm.extracted_1._6 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬x = 1#1 → x_1 = 1#1 → 0#1 = 1#1 → x_1 = 1#1

theorem main11_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 64#32 == 0#32) ||

theorem scalar0_proof : scalar0_before ⊑ scalar0_after

theorem test7_thm.extracted_1._1 : ∀ (x : BitVec 1024),
  ¬(1023#1024 ≥ ↑1024 ∨ 1023#1024 ≥ ↑1024) → (x ^^^ 1#1024 <<< 1023#1024) + 1#1024 <<< 1023#1024 = x

theorem not_or_or_and_no_and_commute1_or_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (LLVM.or (LLVM.or e_2 e_1) (LLVM.xor e (const? 32 (-1)))) (LLVM.xor (LLVM.and e_1 e) (const? 32 (-1))) ⊑
    LLVM.or (LLVM.and e_2 (LLVM.xor e_1 (const? 32 (-1)))) (LLVM.xor e (const? 32 (-1)))

theorem test5_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ¬(zeroExtend 32 x ≥ ↑32 ∨ 32#32 <<< zeroExtend 32 x = 0) →
    ¬(True ∧ x.msb = true ∨ True ∧ 32#32 <<< zeroExtend 32 x >>> zeroExtend 32 x ≠ 32#32 ∨ zeroExtend 32 x ≥ ↑32) →
      x_1 % 32#32 <<< zeroExtend 32 x = x_1 &&& 32#32 <<< zeroExtend 32 x + -1#32

theorem samesign_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 &&& x <ₛ 0#32) ||

theorem sub_ashr_or_i32_commute_thm (e e_1 : IntW 32) :
  LLVM.or e_1 (ashr (sub e e_1 { «nsw» := true, «nuw» := false }) (const? 32 31)) ⊑
    select (icmp IntPred.slt e e_1) (const? 32 (-1)) e_1

theorem not_and_and_or_not_or_or_commute1_or_proof : not_and_and_or_not_or_or_commute1_or_before ⊑ not_and_and_or_not_or_or_commute1_or_after

theorem xor_to_xor1_proof : xor_to_xor1_before ⊑ xor_to_xor1_after

theorem different_size_sext_sext_sle_proof : different_size_sext_sext_sle_before ⊑ different_size_sext_sext_sle_after

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 allOnes_xor_eq_not (x : BitVec w) : allOnes w ^^^ x = ~~~x

theorem test_shl_nsw__none_are_safe_thm.extracted_1._3 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& BitVec.ofInt 32 (-2) == 0#32) = 1#1 →
    ¬(True ∧ ((x_1 &&& BitVec.ofInt 32 (-2)) <<< 2#32).sshiftRight' 2#32 ≠ x_1 &&& BitVec.ofInt 32 (-2) ∨
          2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& BitVec.ofInt 32 (-2)) <<< 2#32) ≥ ↑64) →
      2#32 ≥ ↑32 ∨
          True ∧ (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)).msb = true ∨
            zeroExtend 64 (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)) ≥ ↑64 →
        False

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_2_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 != 0#32) = 1#1 → ofBool (x &&& 3#32 == 0#32) = 1#1

theorem e_351 :
    5 *  ~~~(x &&&  ~~~y) - 6 * (x ||| y) - 1 * (x ^^^ y) - 1 * y - 4 *  ~~~(x ||| y) + 4 *  ~~~(x |||  ~~~y) + 8 * (x &&&  ~~~y) + 2 * (x &&& y) = 1 *  ~~~(x &&& y)

theorem zext_nneg_sext_ugt_proof : zext_nneg_sext_ugt_before ⊑ zext_nneg_sext_ugt_after

theorem exact_lshr_ne_both_equal_proof : exact_lshr_ne_both_equal_before ⊑ exact_lshr_ne_both_equal_after

theorem not_and_and_or_not_or_or_commute2_and_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  x_2 &&& x_1 &&& (x ^^^ -1#32) ||

theorem test13_thm.extracted_1._1 : ∀ (x : BitVec 1024),
  ¬1016#1024 ≥ ↑1024 → x.sshiftRight' 1016#1024 &&& 255#1024 = x >>> 1016#1024

theorem ne_smin2_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (select (icmp IntPred.slt e_1 e) e_1 e) e ⊑ icmp IntPred.sgt e e_1

theorem lshrugt_02_04_thm.extracted_1._1 : ∀ (x : BitVec 4), ¬2#4 ≥ ↑4 → ofBool (4#4 <ᵤ x >>> 2#4) = 0#1

@[bv_multi_width_normalize↓] theorem not_ite {_ : Decidable p} (q r : Prop) : (¬ite p q r) = ite p (¬q) (¬r)

theorem multiuse_add_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 1#64 + zeroExtend 64 x + 1#64 = 2#64

theorem udiv_shl_pair1_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑32 ∨ True ∧ x_2 <<< x >>> x ≠ x_2 ∨ x ≥ ↑32 ∨ x_2 <<< x = 0) →
    True ∧ 1#32 <<< x_1 >>> x_1 ≠ 1#32 ∨ x_1 ≥ ↑32 ∨ x ≥ ↑32 → False

@[simp]
lemma CNFA.autWidth_stateMax : (autWidth wp n).m.stateMax = n + 2

theorem test2_proof : test2_before ⊑ test2_after

theorem test12_thm (e : IntW 43) : sub (const? 43 0) (ashr e (const? 43 42)) ⊑ lshr e (const? 43 42)

theorem test6_thm (e : IntW 32) :
  sext 64 (mul (lshr e (const? 32 3)) (const? 32 3)) ⊑
    zext 64 (mul (lshr e (const? 32 3)) (const? 32 3) { «nsw» := true, «nuw» := true }) { «nneg» := true }

theorem Predicate.evalUlt_denote_false_iff {w : Nat} (a b : Term) (vars : List (BitVec w)) :
    evalUlt (a.eval (List.map .ofBitVecSext vars)) (b.eval (List.map .ofBitVecSext vars)) w = false ↔
    (Term.denote w a vars < Term.denote w b vars)

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

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

theorem test43_thm (e : IntW 8) :
  sext 64 (add (zext 32 e) (const? 32 (-1))) ⊑
    sext 64 (add (zext 32 e) (const? 32 (-1)) { «nsw» := true, «nuw» := false })

theorem srem2_ashr_mask_proof : srem2_ashr_mask_before ⊑ srem2_ashr_mask_after

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 e_1145 :
    1 *  ~~~(z ^^^ t) - 3 *  ~~~z + 1 *  ~~~(z &&&  ~~~t) + 1 * (z ^^^ t) + 1 * (z ||| t) + 3 * z + 1 *  ~~~(z ||| t) - 6 * (z &&& t) = 5 * (z &&&  ~~~t)

@[simp]
lemma carry_and_xor_false : carry i (a &&& b) (a ^^^ b) false = false

theorem trunc_ashr_thm (e : IntW 32) :
  trunc 32 (ashr (LLVM.or (zext 36 e) (const? 36 (-2147483648))) (const? 36 8)) ⊑
    LLVM.or (lshr e (const? 32 8)) (const? 32 (-8388608))

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 test3_thm (e : IntW 41) :
  select (icmp IntPred.slt e (const? 41 0)) (const? 41 (-1)) (const? 41 0) ⊑ ashr e (const? 41 40)

theorem test_ule_xor_proof : test_ule_xor_before ⊑ test_ule_xor_after

theorem e_912 :
     - 7 *  ~~~(z ^^^ t) + 5 *  ~~~z - 1 * z - 5 *  ~~~(z |||  ~~~t) + 1 * (z &&&  ~~~t) + 8 * (z &&& t) =  - 2 *  ~~~(z ||| t)

theorem sub_to_xor_proof : sub_to_xor_before ⊑ sub_to_xor_after

theorem lshr_shl_pow2_const_case1_proof : lshr_shl_pow2_const_case1_before ⊑ lshr_shl_pow2_const_case1_after

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

theorem or_nosignbit_select_lshr_thm (e : IntW 32) (e_1 : IntW 1) :
  lshr (select e_1 (LLVM.or e (const? 32 2147418112)) e) (const? 32 8) ⊑
    select e_1 (LLVM.or (lshr e (const? 32 8)) (const? 32 8388352)) (lshr e (const? 32 8))

@[simp]
theorem replicate_one_eq_allOnes {w : Nat} : BitVec.replicate w 1#1 = BitVec.cast (by simp) (allOnes w)

theorem t7_ugt_sgt_neg1_proof : t7_ugt_sgt_neg1_before ⊑ t7_ugt_sgt_neg1_after

theorem ashr_sgt_noexact_proof : ashr_sgt_noexact_before ⊑ ashr_sgt_noexact_after

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

theorem scalar_i32_signbit_lshr_and_slt_proof : scalar_i32_signbit_lshr_and_slt_before ⊑ scalar_i32_signbit_lshr_and_slt_after

theorem select_xor_icmp_bad_5_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.ne e_2 (const? 32 0)) (LLVM.xor e_2 e_1) e ⊑
    select (icmp IntPred.eq e_2 (const? 32 0)) e (LLVM.xor e_2 e_1)

theorem srem8_ashr_mask_proof : srem8_ashr_mask_before ⊑ srem8_ashr_mask_after

theorem udiv_shl_mul_nuw_proof : udiv_shl_mul_nuw_before ⊑ udiv_shl_mul_nuw_after

theorem basic_proof : basic_before ⊑ basic_after

theorem and_or3_thm (e : IntW 1) (e_1 e_2 : IntW 32) (e_3 : IntW 1) :
  select (LLVM.and e_3 (icmp IntPred.eq e_2 e_1)) e e_3 ⊑
    select e_3 (select (icmp IntPred.ne e_2 e_1) (const? 1 1) e) (const? 1 0)

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

theorem lshr_xor_or_good_mask_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(4#8 ≥ ↑8 ∨ 4#8 ≥ ↑8) →
    ¬(4#8 ≥ ↑8 ∨ True ∧ ((x ||| x_1) >>> 4#8 &&& 48#8 != 0) = true) →
      x_1 >>> 4#8 ||

theorem bv_AndOrXor_2663 :
    ∀ (e e_1 : LLVM.IntW w),
      LLVM.xor (LLVM.icmp LLVM.IntPred.ule e e_1) (LLVM.icmp LLVM.IntPred.ne e e_1) ⊑ LLVM.icmp LLVM.IntPred.uge e e_1

theorem and_add_bool_to_select_multi_use_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → (-1#32 + zeroExtend 32 x_1 &&& x) + (-1#32 + zeroExtend 32 x_1) = x + -1#32

theorem positive_sameconst_proof : positive_sameconst_before ⊑ positive_sameconst_after

theorem lshrugt_01_07_exact_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 1) { «exact» := true }) (const? 4 7) ⊑ const? 1 0

theorem pr40493_proof : pr40493_before ⊑ pr40493_after

theorem n1_proof : n1_before ⊑ n1_after

theorem t10_almost_highest_bit_proof : t10_almost_highest_bit_before ⊑ t10_almost_highest_bit_after

theorem cmpeq_xor_cst1_commuted_proof : cmpeq_xor_cst1_commuted_before ⊑ cmpeq_xor_cst1_commuted_after

theorem or_or_logic_and_1_proof : or_or_logic_and_1_before ⊑ or_or_logic_and_1_after

theorem xor_or_xor_common_op_commute5_thm (e e_1 e_2 : IntW 32) :
  LLVM.xor (LLVM.or e_2 e_1) (LLVM.xor e_2 e) ⊑ LLVM.xor (LLVM.and e_1 (LLVM.xor e_2 (const? 32 (-1)))) e

theorem e_2264 :
    2 * (e ^^^ f) + 2 * (e ^^^ (d ||| ( ~~~e &&& f))) - 11 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) + 1 * (f ^^^ (d &&&  ~~~e)) - 1 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 4 *  ~~~(e ^^^ f) + 7 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) - 7 * ( ~~~f &&& (d ^^^ e)) - 1 * (f ^^^ (d ||| ( ~~~e &&& f))) + 1 * (e ^^^ (d ||| (e ||| f))) - 1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 5 *  ~~~(d &&& ( ~~~e &&& f)) + 2 *  ~~~(d ^^^ f) + 1 *  ~~~(e &&& f) + 11 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) + 1 * (f &&& (d ^^^ e)) - 1 * (e |||  ~~~f) + 11 * (e ^^^  ~~~(d &&& (e ||| f))) + 1 * (e ^^^  ~~~(d &&&  ~~~f)) - 2 * (f &&& (d ||| e)) + 2 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) + 5 * ( ~~~e &&&  ~~~(d ^^^ f)) + 1 * (e ^^^ (d ||| (e ^^^ f))) - 6 * (e &&& (d ||| f)) - 11 * ( ~~~e &&& (d ^^^ f)) + 2 * (e &&& (d |||  ~~~f)) - 2 * f - 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) - 1 *  ~~~(d ^^^ ( ~~~e ||| f)) + 2 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) + 4 * ((d ^^^ e) &&& (d ^^^ f)) + 11 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 5 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) + 1 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * (e ^^^  ~~~(d &&& f)) - 7 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) - 6 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 1 *  ~~~(d &&& f) - 11 * (e |||  ~~~(d |||  ~~~f)) - 11 * (e |||  ~~~(d ^^^ f)) - 2 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 3 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 7 *  ~~~( ~~~d ||| (e &&& f)) + 11 * (f |||  ~~~(d ^^^ e)) - 11 * (e |||  ~~~(d ||| f)) + 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 11 * ( ~~~d &&& (e ||| f)) - 5 * (e ||| (d ^^^ f)) + 2 * (e ^^^ (d ||| f)) - 11 *  ~~~(d ||| (e ||| f)) + 23 *  ~~~(d ||| ( ~~~e ||| f)) + 8 *  ~~~( ~~~d ||| (e ||| f)) + 1 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 8 * ( ~~~d &&& ( ~~~e &&& f)) + 9 * ( ~~~d &&& (e &&& f)) - 23 * (d &&& ( ~~~e &&& f)) + 24 * (d &&& (e &&& f)) = 1 * (e ^^^  ~~~(d |||  ~~~f)) - 4 *  ~~~(d ||| f)

theorem udiv_illegal_type_c_thm.extracted_1._2 : ∀ (x : BitVec 9),
  ¬10#32 = 0 → ¬(10#9 = 0 ∨ True ∧ (x / 10#9).msb = true) → zeroExtend 32 x / 10#32 = zeroExtend 32 (x / 10#9)

theorem test3_thm (e : IntW 1) (e_1 : IntW 599) :
  LLVM.udiv e_1 (select e (const? 599 70368744177664) (const? 599 4096)) ⊑
    lshr e_1 (select e (const? 599 46) (const? 599 12))

theorem select_xor_icmp_meta_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 == 0#32) = 1#1 → x_2 ^^^ x_1 = x_1

theorem shl_lshr_and_exact_thm (e e_1 e_2 : IntW 32) :
  lshr (LLVM.and (shl e_2 e_1 { «nsw» := false, «nuw» := true }) e) e_1 { «exact» := true } ⊑
    LLVM.and (lshr e e_1) e_2

theorem ashr_ult_15_proof : ashr_ult_15_before ⊑ ashr_ult_15_after

@[simp] theorem inf_pure_eq      : min e pure = pure

theorem lshrugt_03_07_proof : lshrugt_03_07_before ⊑ lshrugt_03_07_after

theorem select_lshr_icmp_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == 0#32) = 1#1 → ¬x_1 ≥ ↑32 → x >>> x_1 = x

theorem test_mul_nsw__nsw_is_safe_proof : test_mul_nsw__nsw_is_safe_before ⊑ test_mul_nsw__nsw_is_safe_after

theorem reused_mul_nuw_xy_z_selectnonzero_ugt_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != 0#8) = 1#1 → ¬ofBool (x_1 == 0#8) = 1#1 → True ∧ x.umulOverflow x_1 = true → False

theorem e_385 :
     - 2 *  ~~~(x &&& y) + 2 *  ~~~x + 7 *  ~~~(x &&&  ~~~y) - 5 * (x |||  ~~~y) - 11 * x - 7 *  ~~~(x |||  ~~~y) + 20 * (x &&&  ~~~y) + 9 * (x &&& y) = 2 *  ~~~y

theorem trunc_signed_both_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  ¬(True ∧ signExtend 16 (truncate 8 x_1) ≠ x_1 ∨
        True ∧ zeroExtend 16 (truncate 8 x_1) ≠ x_1 ∨
          True ∧ signExtend 16 (truncate 8 x) ≠ x ∨ True ∧ zeroExtend 16 (truncate 8 x) ≠ x) →
    ofBool (truncate 8 x_1 <ₛ truncate 8 x) = ofBool (x_1 <ₛ x)

theorem not_lshr_thm.extracted_1._1 : ∀ (x : BitVec 8), ¬5#8 ≥ ↑8 → x >>> 5#8 ^^^ 7#8 = (x ^^^ -1#8) >>> 5#8

omit [Fintype S] in
lemma processOneElem_spec {st : worklist.St A S} (s : State) (sa : S) (k : ℕ) :
    ∀ a sa', (f sa)[k]? = some (a, sa') →
    processOneElem_mot inits final f s sa k st →
    processOneElem_mot inits final f s sa (k+1) (processOneElem A S final s st (a, sa'))

theorem test5_proof : test5_before ⊑ test5_after

theorem slt_swap_and_not_max_proof : slt_swap_and_not_max_before ⊑ slt_swap_and_not_max_after

theorem shl_sub_no_commute_thm (e e_1 : IntW 8) :
  shl (sub e_1 (shl e (const? 8 3))) (const? 8 2) ⊑ sub (shl e_1 (const? 8 2)) (shl e (const? 8 5))

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

theorem ashrslt_02_08_proof : ashrslt_02_08_before ⊑ ashrslt_02_08_after

@[simp] theorem Valuation.comap_cons_consRight {Γ Δ : Ctxt Ty} (Γv : Valuation Γ) (f : Hom Δ Γ) :
    comap (Γv.cons x) (f.consRight) = comap Γv f

theorem udiv_shl_pair1_proof : udiv_shl_pair1_before ⊑ udiv_shl_pair1_after

theorem test53_proof : test53_before ⊑ test53_after

theorem main4e_like_logical_thm.extracted_1._8 : ∀ (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 → 1#32 = zeroExtend 32 (ofBool (x_2 &&& x != x))

theorem bools_multi_uses2_logical_thm.extracted_1._19 : ∀ (x x_1 : BitVec 1),
  ¬x_1 ^^^ 1#1 = 1#1 → ¬x_1 = 1#1 → ¬0#1 = 1#1 → False

theorem smear_set_bit_proof : smear_set_bit_before ⊑ smear_set_bit_after

theorem ashr_eq_noexact_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬3#8 ≥ ↑8 → ofBool (x.sshiftRight' 3#8 == 10#8) = ofBool (x &&& BitVec.ofInt 8 (-8) == 80#8)

theorem and_logic_and_logic_or_6_thm.extracted_1._5 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 = 1#1 → x_1 = 1#1 → 1#1 = x_1 &&& 1#1

Nat.zero_add in Init.Data.Nat.Basic
</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 BVNRel n := ∀ ⦃w⦄, List.Vector (BitVec w) n → Prop

def NFA'.sa (M : NFA' n) := M.σ → BVNRel n

def langRel (R : BVNRel n) : Set (BitVecs n) :=
  { bvs | R bvs.bvs }

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

inductive NFA.msbState : Type where
| i | f
deriving DecidableEq, Fintype

end nfas_relations

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)

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

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

@[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 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
</local_ctx>

<target_theorem>
lemma autOfTermUnop_bv_language op {t : Term} (m : CNFA (t.arity + 1)) :
    m.bv_recognizes t.language →
    (autOfTermUnop op m |>.bv_recognizes (op.subst_arity' ▸ (op.subst t).language)) :=
</target_theorem>

