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
Fin.mk in Init.Prelude
Fin.cast in Init.Data.Fin.Basic
Fin.castLT in Init.Data.Fin.Basic
Fin.subNat in Init.Data.Fin.Basic
List.Vector.get in Mathlib.Data.Vector.Defs
List.Vector.nil in Mathlib.Data.Vector.Defs
Finset in Mathlib.Data.Finset.Defs
Finset.range in Mathlib.Data.Finset.Range
DFA in Mathlib.Computability.DFA
NFA.toDFA in Mathlib.Computability.NFA
List.range in Init.Data.List.Basic
Vector.ofFn in Init.Data.Vector.Basic
Eq in Init.Prelude
Fin.natAdd in Init.Data.Fin.Basic
NeZero in Init.Data.NeZero

syntax "max" : MLIR.Pretty.uniform_op

syntax "slt" : MLIR.Pretty.uniform_op

syntax "xor" : MLIR.Pretty.uniform_op

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

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

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

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

def carry (initCarry : Bool) (x y : BitStream) : BitStream :=
  fun n => (addAux' initCarry x y n).2

def BitStream : Type := Nat → Bool

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

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

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

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

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

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

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

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

abbrev State := Nat

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

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

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

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

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

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

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

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

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

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

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

| shiftL : Term → Nat → Term

deriving Repr, Inhabited, Lean.ToExpr

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def scanAnd (s : BitStream) : BitStream := scanl true Bool.and s

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

def Predicate.evalEq (t₁ t₂ : BitStream) : BitStream := (t₁ ^^^ t₂).concat false |>.scanOr

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

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

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

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

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

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

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

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

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

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

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

| shiftL t .. => arity t

abbrev negOne : BitStream := fun _ => true

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

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

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

abbrev zero   : BitStream := fun _ => false

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@[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 sle_swap_or_min_logical_before := [llvm|
{
^0(%arg148 : i8, %arg149 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "sge" %arg149, %arg148 : i8
  %3 = llvm.icmp "eq" %arg148, %0 : i8
  %4 = "llvm.select"(%2, %1, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def CollectState.logSuspiciousFvars (state : CollectState) : SolverM (Array Expr) := do
  let mut exprs := #[]
  for (e, _w) in state.bvToIx.toArrayAsc do
    if !e.isFVar then
      logWarning m!"abstracted non-variable bitvector: {indentD <| "→ '" ++ toMessageData e ++ "'"}"
      exprs := exprs.push e
  for e in state.wToIx.toArrayAsc do
    if !e.isFVar then
      logWarning m!"abstracted non-variable width: {indentD <| "→ '" ++ toMessageData e ++ "'"}"
      exprs := exprs.push e
  for e in state.pToIx.toArrayAsc do
    if !e.isFVar then
      logWarning m!"abstracted prop: {indentD <| "→ '" ++ toMessageData e ++ "'"}"
      exprs := exprs.push e
  for e in state.boolToIx.toArrayAsc do
    if !e.isFVar then
      logWarning m!"abstracted boolean: {indentD <| "→ '" ++ toMessageData e ++ "'"}"
      exprs := exprs.push e
  return exprs

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

def zext_add_scalar_after := [llvm|
{
^0(%arg40 : i1):
  %0 = llvm.mlir.constant(43 : i32) : i32
  %1 = llvm.mlir.constant(42 : i32) : i32
  %2 = "llvm.select"(%arg40, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

def xor_or_xor_common_op_commute2_after := [llvm|
{
^0(%arg77 : i32, %arg78 : i32, %arg79 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg77, %0 : i32
  %2 = llvm.and %arg78, %1 : i32
  %3 = llvm.xor %2, %arg79 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def forkVal {Γ : Ctxt _}  (a : Γ.Var (MLIR2DCPlus.Ty.valuestream 1)) : Expr (DCPlus) Γ .pure (.valuestream2 1) :=
  Expr.mk
    (op := .forkVal)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

def factorize2_before := [llvm|
{
^0(%arg8 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mul %0, %arg8 : i32
  %3 = llvm.mul %1, %arg8 : i32
  %4 = llvm.sub %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test36_before := [llvm|
{
^0(%arg158 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.lshr %arg158, %0 : i32
  %3 = llvm.trunc %2 : i32 to i8
  %4 = llvm.icmp "eq" %3, %1 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def MatchVar.IsMonotone (f : MatchVar Δ Γ) : Prop :=
    ∀ mapIn, ∀ mapOut ∈ f mapIn,
      mapIn.entries ⊆ mapOut.2.entries

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

def mkReturn (Γ : Ctxt _) (opStx : MLIR.AST.Op 0) : MLIR.AST.ReaderM (DC)
    (Σ eff ty, Com DC Γ eff ty) :=
  if opStx.name == "return"
  then match opStx.args with
  | vStx::[] => do
    let ⟨ty, v⟩ ← MLIR.AST.TypedSSAVal.mkVal Γ vStx
    return ⟨.pure, [ty], Com.ret v⟩
  | _ => throw <| .generic s!"Ill-formed return statement (wrong arity, expected 1, got {opStx.args.length})"
  else throw <| .generic s!"Tried to build return out of non-return statement {opStx.name}"

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 lshr_C1_add_A_C2_i32_after := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(65535 : i32) : i32
  %1 = llvm.mlir.constant(192 : i32) : i32
  %2 = llvm.and %arg6, %0 : i32
  %3 = llvm.shl %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

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

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

def slt_swap_and_not_max_commute_after := [llvm|
{
^0(%arg114 : i8, %arg115 : i8):
  %0 = llvm.icmp "sgt" %arg115, %arg114 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

def negate_add_with_single_negatible_operand_after := [llvm|
{
^0(%arg37 : i8, %arg38 : i8):
  %0 = llvm.mlir.constant(-42 : i8) : i8
  %1 = llvm.sub %0, %arg37 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

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

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

def shl_xor_lshr_comm_before := [llvm|
{
^0(%arg97 : i32, %arg98 : i32, %arg99 : i32):
  %0 = llvm.shl %arg97, %arg98 overflow<nuw> : i32
  %1 = llvm.xor %arg99, %0 : i32
  %2 = llvm.lshr %1, %arg98 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

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 positive_sameconst_shlnuw_before := [llvm|
{
^0(%arg29 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.shl %arg29, %0 overflow<nuw> : i32
  %2 = llvm.lshr %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def c_0_1_0_after := [llvm|
{
^0(%arg29 : i4, %arg30 : i4, %arg31 : i4):
  %0 = llvm.xor %arg29, %arg30 : i4
  %1 = llvm.and %0, %arg31 : i4
  %2 = llvm.xor %1, %arg30 : i4
  "llvm.return"(%2) : (i4) -> ()
}
]

def icmp_equality_test_after := [llvm|
{
^0(%arg34 : i64, %arg35 : i64, %arg36 : i64):
  %0 = llvm.icmp "eq" %arg34, %arg35 : i64
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

def Body.substitute (σ : Substitution) : Body Op T → Body Op T
  | ⟨lets, terminator⟩ => ⟨lets.substitute σ, substituteTerminator σ.apply terminator⟩

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

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

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

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

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

Std.Tactic.BVDecide.BVBinOp in Std.Tactic.BVDecide.Bitblast.BVExpr.Basic

def precondSynthesisUpdateCache (previousLevelCache synthesisComponents: Std.HashMap (GenBVExpr w)  PreconditionSynthesisCacheValue)
    (positiveExamples negativeExamples: List (Std.HashMap Nat BVExpr.PackedBitVec)) (specialConstants : Std.HashMap (GenBVExpr w) BVExpr.PackedBitVec)
    (ops : List (GenBVExpr w → GenBVExpr w → GenBVExpr w)) : GeneralizerStateM ParsedBVExpr GenBVPred (Std.HashMap (GenBVExpr w) PreconditionSynthesisCacheValue) := do
    let mut currentCache := Std.HashMap.emptyWithCapacity
    let mut observationalEquivFilter : Std.HashSet String := Std.HashSet.emptyWithCapacity

    let evaluateCombinations (combos :  List (BVExpr.PackedBitVec × BVExpr.PackedBitVec)) (examples: List (Std.HashMap Nat BVExpr.PackedBitVec))
            (op : GenBVExpr w → GenBVExpr w → GenBVExpr w) : GeneralizerStateM ParsedBVExpr GenBVPred  (List (BitVec w)) := do
          let mut res : List (BitVec w) := []
          let mut index := 0
          for (lhs, rhs) in combos do
            let h : lhs.w = w := sorry
            let h' : rhs.w = w := sorry
            if h : lhs.w = w ∧ rhs.w = w then
              res := (evalBVExpr examples[index]! (op  (GenBVExpr.const (h.left ▸ lhs.bv)) (GenBVExpr.const (h.right ▸ rhs.bv)))) :: res
              index := index + 1
            else
              throwError m! "Invalid width for lhs:{lhs} and rhs:{rhs}"
          pure res

    for (bvExpr, intermediateRes) in previousLevelCache.toArray do
      let intermediateNegValues := intermediateRes.negativeExampleValues
      let intermediatePosValues := intermediateRes.positiveExampleValues

      for op in ops do
        for (var, componentValue) in synthesisComponents.toArray do
          if specialConstants.contains bvExpr && specialConstants.contains var then 
            continue

          
          let negExCombinations := List.zip intermediateNegValues componentValue.negativeExampleValues
          let evaluatedNegativeExs ← evaluateCombinations negExCombinations negativeExamples op

          let posExCombinations := List.zip intermediatePosValues componentValue.positiveExampleValues
          let evaluatedPositiveExs  ← evaluateCombinations posExCombinations positiveExamples op

          let filterCheckStr := toString (evaluatedNegativeExs ++ evaluatedPositiveExs)
          if observationalEquivFilter.contains filterCheckStr then
            continue

          let newExpr := op bvExpr var
          currentCache := currentCache.insert newExpr { negativeExampleValues := evaluatedNegativeExs.map (λ ex => {bv := ex, w := w})
                                                      , positiveExampleValues := evaluatedPositiveExs.map (λ ex => {bv := ex, w := w}) : PreconditionSynthesisCacheValue}
          observationalEquivFilter := observationalEquivFilter.insert filterCheckStr

    return currentCache

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

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

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

def t7_after := [llvm|
{
^0(%arg197 : i8, %arg198 : i1, %arg199 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.shl %0, %arg199 overflow<nsw> : i8
  %3 = "llvm.select"(%arg198, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %4 = llvm.add %3, %arg197 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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

def scalar_i32_lshr_and_signbit_ne_after := [llvm|
{
^0(%arg27 : i32, %arg28 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.lshr %arg27, %arg28 : i32
  %2 = llvm.icmp "slt" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def sdiv_pow2_64 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant (64) : i64
      %0 = llvm.sdiv %x, %c : i64
      llvm.return %0 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64):
      %c0 = llvm.mlir.constant (63) : i64
      %c1 = llvm.mlir.constant (58) : i64
      %c2 = llvm.mlir.constant (6) : i64
      %0 = llvm.ashr %x, %c0 : i64
      %1 = llvm.lshr %0, %c1 : i64
      %2 = llvm.add %x, %1 : i64 
      %3 = llvm.ashr %2, %c2 : i64
      llvm.return %3 : i64
  }]

def ashrsgt_01_13_after := [llvm|
{
^0(%arg304 : i4):
  %0 = llvm.mlir.constant(-5 : i4) : i4
  %1 = llvm.icmp "sgt" %arg304, %0 : i4
  "llvm.return"(%1) : (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 GeneralizerStateM.liftTermElabM
  {parsedExpr : Type}  {genPred : Type}
  [HydrableInstances genPred]
  (m : TermElabM α) : GeneralizerStateM parsedExpr genPred α := do
  let v ← m
  return v

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

private def opRgnAttr0 : Op φ := [mlir_op|
 "module"() ({
  ^entry:
   "func"() ({
     ^bb0(%arg0:i32, %arg1:i32):
      %zero = "std.addi"(%arg0 , %arg1) : (i32, i16) -> (i64)
      "std.return"(%zero) : (i32) -> ()
    }){sym_name = "add"} : () -> ()
   "module_terminator"() : () -> ()
 }) : () -> ()
]

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

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

Std.Associative in Init.Core

def addMax' (a : BitVec o) (wmask : BitVec o) (b : BitVec o) (vmask : BitVec o) : BitVec o :=
    let max := addMax'Mask wmask vmask
    (a + b) 

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

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

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

def printAttributes: RISCV64.Op → String
  | .li imm => s! "\{immediate = { imm.toInt } : i64 }"
  | .addiw (imm : BitVec 12) => s!"\{immediate = { imm.toInt} : si12 }"
  | .lui (imm : BitVec 20) => s!"\{immediate = { imm.toInt} : ui20 } "
  | .auipc (imm : BitVec 20) => s!"\{immediate = { imm.toInt} : si20 }" 
  | .slliw (imm : BitVec 5) => s!"\{immediate = { imm.toNat} : ui5 }"
  | .srliw (imm : BitVec 5) => s!"\{immediate = { imm.toNat} : ui5 }"
  | .sraiw (imm : BitVec 5) => s!"\{immediate = { imm.toNat} : ui5 }"
  | .slli (imm : BitVec 6) => s!"\{immediate = { imm.toNat} : ui6 }"
  | .srli (imm : BitVec 6) => s!"\{immediate = { imm.toNat} : ui6 }"
  | .srai (imm : BitVec 6) => s!"\{immediate = { imm.toNat} : ui6 }"
  | .addi (imm : BitVec 12) => s!"\{immediate = { imm.toInt } : si12 }"
  | .slti (imm : BitVec 12) => s!"\{immediate = { imm.toInt } : si12 }"
  | .sltiu (imm : BitVec 12) => s!"\{immediate = { imm.toInt } : si12 }"
  | .andi (imm : BitVec 12) => s!"\{immediate = { imm.toInt } : si12 }"
  | .ori (imm : BitVec 12) => s!"\{immediate = { imm.toInt } : si12 }"
  | .xori (imm : BitVec 12) => s!"\{immediate = { imm.toInt } : si12 }"
  | .bclri (imm : BitVec 6) => s!"\{immediate = { imm.toInt} : i6 }"
  | .bexti (imm : BitVec 6) =>s!"\{immediate = { imm.toInt} : i6 }"
  | .binvi (imm : BitVec 6) => s!"\{immediate = { imm.toInt} : i6 }"
  | .bseti (imm : BitVec 6) => s!"\{immediate = { imm.toInt} : i6 }"
  | .slliuw (imm : BitVec 6) => s!"\{immediate = { imm.toNat} : ui6 }"
  | .rori (imm : BitVec 6) => s!"\{immediate = { imm.toInt} : i5 }"
  | .roriw (imm : BitVec 5) => s!"\{immediate = { imm.toInt} : i5 }"
  | _ => ""

def lshr_shl_eq_amt_multi_use_before := [llvm|
{
^0(%arg5 : i43):
  %0 = llvm.mlir.constant(23 : i43) : i43
  %1 = llvm.lshr %arg5, %0 : i43
  %2 = llvm.shl %1, %0 : i43
  %3 = llvm.mul %1, %2 : i43
  "llvm.return"(%3) : (i43) -> ()
}
]

def test14_before := [llvm|
{
^0(%arg0 : i32, %arg1 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(128 : i32) : i32
  %2 = llvm.shl %arg0, %0 : i32
  %3 = llvm.sub %2, %arg1 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.mul %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

def t2_before := [llvm|
{
^0(%arg237 : i64, %arg238 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.shl %0, %arg238 : i32
  %2 = llvm.zext %1 : i32 to i64
  %3 = llvm.udiv %arg237, %2 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

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

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

def test29_after := [llvm|
{
^0(%arg260 : i8):
  %0 = llvm.zext %arg260 : i8 to i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def main (args : List String): IO UInt32 :=
  mainCmd.validate args

def trunc_ashr_before := [llvm|
{
^0(%arg98 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i36) : i36
  %1 = llvm.mlir.constant(8 : i36) : i36
  %2 = llvm.zext %arg98 : i32 to i36
  %3 = llvm.or %2, %0 : i36
  %4 = llvm.ashr %3, %1 : i36
  %5 = llvm.trunc %4 : i36 to i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

Lean.initSearchPath in Lean.Util.Path

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

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

def test17_before := [llvm|
{
^0(%arg9 : i1):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.sext %arg9 : i1 to i32
  %2 = llvm.sub %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def sndVal {r} {Γ : Ctxt _} (a : Γ.Var (.valuetokenstream r))  : Expr (DC) Γ .pure (.tokenstream)  :=
  Expr.mk
    (op := .sndVal r)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

def prettifyBVBinOp (op: BVBinOp) : String :=
  match op with
  | .and => "&&&"
  | .or => "|||"
  | .xor => "^^^"
  | _ => op.toString

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

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

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

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

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 : List (Σ Γ, LLVMPeepholeRewriteRefine 64 Γ) :=
[⟨_, visitADD_0⟩,
 ⟨_, visitADD_Sameop⟩,
 ⟨_, visitADD_Neg1⟩,
 ⟨_, visitADD_ZeroNegAPlusB⟩,
 ⟨_, visitADD_APlusZeroNegB⟩,
 ⟨_, visitADD_APlusBNegA⟩,
 ⟨_, visitADD_BNegAPlusA⟩,
 ⟨_, visitADD_ANegBPlusCNegA⟩,
 ⟨_, visitADD_ANegBPlusBNegC⟩,
 ⟨_, visitADD_APlusBNegAPlusC⟩,
 ⟨_, visitADD_APlusBNegCPlusA⟩,
 ⟨_, visitADD_XorNeg1Plus1⟩,
 ⟨_, visitADD_XorNeg1PlusBPlus1⟩,
 ⟨_, visitADD_PlusNeg1⟩]

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 ashrsgt_02_02_after := [llvm|
{
^0(%arg299 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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}

@[simp_denote]
def select_llvm_16 := [LV| {
  ^entry (%cond : i1, %arg0: i16, %arg1: i16):
    %0 = "llvm.select"(%cond, %arg0, %arg1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
    llvm.return %0 : i16
  }]

def or_test2_after := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  "llvm.return"(%0) : (i8) -> ()
}
]

@[simp_denote]
def sext_llvm_i8_to_64 := [LV| {
  ^entry (%arg: i8):
    %0 = llvm.sext %arg: i8 to i64
    llvm.return %0: i64
  }]

def xori_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := xori_llvm_i32
  rhs := xori_riscv_i32

def main4f_like_logical_before := [llvm|
{
^0(%arg115 : i32, %arg116 : i32, %arg117 : i32):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.and %arg115, %arg116 : i32
  %4 = llvm.icmp "ne" %3, %arg116 : i32
  %5 = llvm.and %arg115, %arg117 : i32
  %6 = llvm.icmp "ne" %5, %arg117 : i32
  %7 = "llvm.select"(%4, %0, %6) <{"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 and_umin_after := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

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

def select_zext_different_condition_after := [llvm|
{
^0(%arg15 : i1, %arg16 : i1):
  %0 = llvm.mlir.constant(64) : i64
  %1 = llvm.mlir.constant(1) : i64
  %2 = "llvm.select"(%arg15, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  %3 = llvm.zext %arg16 : i1 to i64
  %4 = llvm.add %2, %3 overflow<nsw,nuw> : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def Tensor1d.fill [Inhabited α] (t: Tensor1d α) (v: α) : Tensor1d α where
  size := t.size
  val := fun ix => if ix < t.size then v else default
  spec := by admit /- proof elided -/

def add_nsw_or_and_after := [llvm|
{
^0(%arg11 : i32, %arg12 : i32):
  %0 = llvm.add %arg11, %arg12 overflow<nsw> : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

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

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

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

def t1_flags_after := [llvm|
{
^0(%arg48 : i8, %arg49 : i8, %arg50 : i8):
  %0 = llvm.add %arg49, %arg50 overflow<nsw,nuw> : i8
  %1 = llvm.sub %arg48, %0 overflow<nsw,nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def logical_and_icmps1_before := [llvm|
{
^0(%arg36 : i32, %arg37 : i1):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.mlir.constant(10086 : i32) : i32
  %3 = llvm.icmp "sgt" %arg36, %0 : i32
  %4 = "llvm.select"(%arg37, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = llvm.icmp "slt" %arg36, %2 : i32
  %6 = "llvm.select"(%4, %5, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

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 test84_before := [llvm|
{
^0(%arg61 : i32):
  %0 = llvm.mlir.constant(-16777216 : i32) : i32
  %1 = llvm.mlir.constant(23 : i32) : i32
  %2 = llvm.add %arg61, %0 overflow<nsw> : i32
  %3 = llvm.lshr exact %2, %1 : i32
  %4 = llvm.trunc %3 : i32 to i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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 BranchEg1 := [handshake_com| {
  ^entry(%0: !Stream_BitVec_1, %1: !Stream_BitVec_1):
    %out = "handshake.branch" (%0, %1) : (!Stream_BitVec_1, !Stream_BitVec_1) -> (!Stream2_BitVec_1)
    %outf = "handshake.fst" (%out) : (!Stream2_BitVec_1) -> (!Stream_BitVec_1)
    %outs = "handshake.snd" (%out) : (!Stream2_BitVec_1) -> (!Stream_BitVec_1)
    %out2 = "handshake.merge" (%outs, %outf) : (!Stream_BitVec_1, !Stream_BitVec_1) -> (!Stream_BitVec_1)
    "return" (%out2) : (!Stream_BitVec_1) -> ()
  }]

def positive_samevar_shlnuw_lshrexact_before := [llvm|
{
^0(%arg32 : i8, %arg33 : i8):
  %0 = llvm.lshr exact %arg32, %arg33 : i8
  %1 = llvm.shl %0, %arg33 overflow<nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def ult_and_max_commute_before := [llvm|
{
^0(%arg364 : i8, %arg365 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.icmp "ult" %arg364, %arg365 : i8
  %2 = llvm.icmp "eq" %arg364, %0 : i8
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (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 test_and_ne_a_b_commuted_before := [llvm|
{
^0(%arg27 : i1, %arg28 : i8, %arg29 : i8):
  %0 = llvm.icmp "ne" %arg28, %arg29 : i8
  %1 = llvm.and %arg27, %0 : i1
  %2 = "llvm.select"(%1, %arg29, %arg28) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def xor_common_op_commute0_after := [llvm|
{
^0(%arg208 : i8, %arg209 : i8):
  %0 = llvm.or %arg209, %arg208 : i8
  "llvm.return"(%0) : (i8) -> ()
}
]

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

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

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

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

instance {n} : ShiftLeft (BitVec n) := ⟨fun x y => x <<< y.toNat⟩

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

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

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

def add_shl_moreOneUse_sh1add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := add_shl_moreOneUse_sh1add
  rhs := add_shl_moreOneUse_sh1add_riscv_ZBA

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

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

Lean.NameMap in Lean.Data.NameMap.Basic

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 neg_nsw_sgt_n1_after := [llvm|
{
^0(%arg18 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.icmp "slt" %arg18, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def src_is_notmask_neg_p2_fail_not_invertable_before := [llvm|
{
^0(%arg51 : i8, %arg52 : i8):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.xor %arg51, %0 : i8
  %3 = llvm.sub %1, %arg52 : i8
  %4 = llvm.and %3, %arg52 : i8
  %5 = llvm.sub %1, %4 : i8
  %6 = llvm.and %5, %2 : i8
  %7 = llvm.icmp "eq" %1, %6 : i8
  "llvm.return"(%7) : (i1) -> ()
}
]

def select_of_truncate : List (Σ Γ, LLVMPeepholeRewriteRefine 32 Γ) :=
  [⟨_, select_of_truncate_rw⟩]

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

def test_mul__nsw_is_safe_before := [llvm|
{
^0(%arg4 : i32):
  %0 = llvm.mlir.constant(-83886080 : i32) : i32
  %1 = llvm.mlir.constant(-83886079 : i32) : i32
  %2 = llvm.mlir.constant(9 : i32) : i32
  %3 = llvm.mlir.constant(-754974711 : i32) : i32
  %4 = llvm.or %arg4, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.mul %4, %2 : i32
  %7 = "llvm.select"(%5, %3, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

def scalar_i32_signbit_shl_and_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 %0, %arg3 : i32
  %3 = llvm.and %2, %arg2 : i32
  %4 = llvm.icmp "slt" %3, %1 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

@[match_pattern] def not    (w : Width φ) : MOp φ := .unary w .not

def test8_after := [llvm|
{
^0(%arg6 : i999):
  %0 = llvm.mlir.constant(0 : i999) : i999
  "llvm.return"(%0) : (i999) -> ()
}
]

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

def negate_shl_xor_after := [llvm|
{
^0(%arg122 : i4, %arg123 : i4):
  %0 = llvm.mlir.constant(-6 : i4) : i4
  %1 = llvm.mlir.constant(1 : i4) : i4
  %2 = llvm.xor %arg122, %0 : i4
  %3 = llvm.add %2, %1 : i4
  %4 = llvm.shl %3, %arg123 : i4
  "llvm.return"(%4) : (i4) -> ()
}
]

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

def product (final? : Prop → Prop → Prop) (M N : NFA' n) : NFA' n where
  σ := _
  M := M.M.product final? N.M

def NFA.autUnsignedCmp (cmp: RelationOrdering) : NFA (BitVec 2) unsignedCmpState where
  step s a := { s' | s' ∈ unsignedCmpStep s a }
  start := {s | s = .eq }
  accept := { s | s ∈ match cmp with | .lt => [unsignedCmpState.lt] | .le => [.lt, .eq] | .gt => [.gt] | .ge => [.gt, .eq] }

def select_t_0 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 1)] where
  lhs := [LV| {
    ^entry (%c: i1, %t: i64):
      %c0 = llvm.mlir.constant (0) : i64
      %0 = llvm.select %c, %t, %c0 : i64
      llvm.return %0 : i64
  }]
  rhs := [LV| {
    ^entry (%c: i1, %t: i64):
      %cext = llvm.sext %c: i1 to i64
      %tfreeze = llvm.freeze %t : i64
      %0 = llvm.and %cext, %tfreeze : i64
      llvm.return %0 : i64
  }]

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 icmp_mul_nsw_slt_before := [llvm|
{
^0(%arg19 : i8, %arg20 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mul %arg19, %0 overflow<nsw> : i8
  %2 = llvm.mul %arg20, %0 overflow<nsw> : i8
  %3 = llvm.icmp "slt" %1, %2 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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 ashr_add_exact_before := [llvm|
{
^0(%arg2 : i8, %arg3 : i8):
  %0 = llvm.mlir.constant(-14 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.and %arg2, %0 : i8
  %3 = llvm.and %arg3, %1 : i8
  %4 = llvm.ashr %2, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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 or_nosignbit_select_lshr_before := [llvm|
{
^0(%arg24 : i32, %arg25 : i1):
  %0 = llvm.mlir.constant(2147418112 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.or %arg24, %0 : i32
  %3 = "llvm.select"(%arg25, %2, %arg24) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.lshr %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def or_nontrivial_mask2_after := [llvm|
{
^0(%arg11 : i16):
  %0 = llvm.mlir.constant(-3841 : i16) : i16
  %1 = llvm.mlir.constant(20607 : i16) : i16
  %2 = llvm.and %arg11, %0 : i16
  %3 = llvm.icmp "ne" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

def and_umax_muchless_before := [llvm|
{
^0(%arg18 : i32):
  %0 = llvm.mlir.constant(12 : i32) : i32
  %1 = llvm.mlir.constant(-32 : i32) : i32
  %2 = llvm.icmp "ugt" %0, %arg18 : i32
  %3 = "llvm.select"(%2, %0, %arg18) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.and %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

def t1_before := [llvm|
{
^0(%arg28 : i8, %arg29 : i1):
  %0 = llvm.sext %arg29 : i1 to i8
  %1 = llvm.sext %arg29 : i1 to i8
  %2 = llvm.add %0, %arg28 : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def or_not_xor_common_op_commute5_after := [llvm|
{
^0(%arg92 : i8, %arg93 : i8, %arg94 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.and %arg93, %arg92 : i8
  %2 = llvm.xor %1, %0 : i8
  %3 = llvm.or %arg94, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

Ne in Init.Core

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

def positive_samevar_before := [llvm|
{
^0(%arg62 : i8, %arg63 : i8):
  %0 = llvm.lshr %arg62, %arg63 : i8
  %1 = llvm.shl %0, %arg63 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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 PR2330_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg0 : i32
  %3 = llvm.and %2, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

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

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

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

Matrix in Mathlib.LinearAlgebra.Matrix.Defs

def udiv_i32_multiuse_after := [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 overflow<nsw,nuw> : i32
  %4 = llvm.mul %2, %3 overflow<nsw,nuw> : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def ule_or_not_min_before := [llvm|
{
^0(%arg272 : i427, %arg273 : i427):
  %0 = llvm.mlir.constant(0 : i427) : i427
  %1 = llvm.icmp "ule" %arg272, %arg273 : i427
  %2 = llvm.icmp "ne" %arg272, %0 : i427
  %3 = llvm.or %1, %2 : 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 or_disjoint_with_xor_before := [llvm|
{
^0(%arg28 : i32, %arg29 : i32):
  %0 = llvm.or disjoint %arg28, %arg29 : i32
  %1 = llvm.xor %0, %arg28 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def sub_ashr_or_i16_after := [llvm|
{
^0(%arg37 : i16, %arg38 : i16):
  %0 = llvm.mlir.constant(-1 : i16) : i16
  %1 = llvm.icmp "slt" %arg38, %arg37 : i16
  %2 = "llvm.select"(%1, %0, %arg37) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
  "llvm.return"(%2) : (i16) -> ()
}
]

def test9_before := [llvm|
{
^0(%arg5 : i1005):
  %0 = llvm.mlir.constant(-1 : i1005) : i1005
  %1 = llvm.and %arg5, %0 : i1005
  "llvm.return"(%1) : (i1005) -> ()
}
]

def PostLegalizerCombiner_RISCV: List (Σ Γ,RISCVPeepholeRewrite  Γ) :=
    RISCV_identity_combines ++
    commute_int_constant_to_rhs ++
    simplify_neg ++
    mulh_to_lshr

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

def or_logic_or_logic_and_3_before := [llvm|
{
^0(%arg42 : i1, %arg43 : i1, %arg44 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.or %arg42, %arg43 : i1
  %3 = "llvm.select"(%arg42, %0, %arg44) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = "llvm.select"(%3, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

@[simp] abbrev FlatCom.denote [DialectDenote d]
    (flatCom : FlatCom d Γ eff Γ_out ts)
    (V : Γ.Valuation) : eff.toMonad d.m (HVector toType ts) :=
  flatCom.lets.denote V >>= (return flatCom.rets.map ·)

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

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

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

def test12_before := [llvm|
{
^0(%arg46 : i32, %arg47 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-1431655766 : i32) : i32
  %2 = llvm.mlir.constant(1431655765 : i32) : i32
  %3 = llvm.add %arg47, %0 overflow<nsw> : i32
  %4 = llvm.or %arg46, %1 : i32
  %5 = llvm.xor %4, %2 : i32
  %6 = llvm.add %3, %5 overflow<nsw> : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def test18_before := [llvm|
{
^0(%arg152 : i8, %arg153 : i8):
  %0 = llvm.mlir.constant(33 : i8) : i8
  %1 = llvm.xor %arg153, %arg152 : i8
  %2 = llvm.xor %arg152, %0 : i8
  %3 = llvm.xor %2, %arg153 : i8
  %4 = llvm.or %3, %1 : i8
  %5 = llvm.mul %4, %3 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

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

def 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 rem_match : List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) := [
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_rem_lower_riscv_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_rem_lower_riscv_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_rem_lower_riscv_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_rem_lower_riscv_64)
]

def sumVarsRight [DecidableEq α] [DecidableEq β] : Circuit (α ⊕ β) → List β
  | tru => []
  | fals => []
  | var _ (Sum.inl _) => []
  | var _ (Sum.inr x) => [x]
  | and c₁ c₂ => (sumVarsRight c₁ ++ sumVarsRight c₂).dedup
  | or c₁ c₂ => (sumVarsRight c₁ ++ sumVarsRight c₂).dedup
  | xor c₁ c₂ => (sumVarsRight c₁ ++ sumVarsRight c₂).dedup

def iso_unary (a : Stream' (BitVec 1)) : Stream' (Vector (BitVec 1) 1) :=
    fun n =>
      {toArray := [a n].toArray, size_toArray := by admit /- proof elided -/

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

def test3_after := [llvm|
{
^0(%arg23 : i32, %arg24 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg23, %arg24 : i32
  %2 = llvm.icmp "sgt" %1, %0 : i32
  %3 = llvm.zext %2 : i1 to i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def sub {Γ : Ctxt (Ty q)} (x y : Var Γ .modLike)
    : Expr (ModArith q) Γ .pure .modLike :=
  Expr.mk
    (op      := .sub)
    (ty_eq   := rfl)
    (eff_le  := by admit /- proof elided -/
    )
    (args    := .cons x (.cons y .nil))
    (regArgs := .nil)

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

def demorgan_nor_use2b_before := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(23 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.mul %arg29, %0 : i8
  %3 = llvm.xor %arg28, %1 : i8
  %4 = llvm.or %3, %arg29 : i8
  %5 = llvm.xor %4, %1 : i8
  %6 = llvm.sdiv %5, %2 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

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

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 or_signbit_lshr_after := [llvm|
{
^0(%arg13 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(16776960 : i32) : i32
  %2 = llvm.lshr %arg13, %0 : i32
  %3 = llvm.or %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def test8_before := [llvm|
{
^0(%arg6 : i999):
  %0 = llvm.mlir.constant(0 : i999) : i999
  %1 = llvm.and %arg6, %0 : i999
  "llvm.return"(%1) : (i999) -> ()
}
]

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

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

def or_signbit_select_ashr_after := [llvm|
{
^0(%arg10 : i32, %arg11 : i1):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(-256 : i32) : i32
  %2 = llvm.ashr %arg10, %0 : i32
  %3 = llvm.or %2, %1 : i32
  %4 = "llvm.select"(%arg11, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test2_before := [llvm|
{
^0(%arg0 : i49, %arg1 : i49, %arg2 : i49):
  %0 = llvm.ashr %arg0, %arg2 : i49
  %1 = llvm.ashr %arg1, %arg2 : i49
  %2 = llvm.xor %0, %1 : i49
  "llvm.return"(%2) : (i49) -> ()
}
]

def mul_unkV_evenC_ne_before := [llvm|
{
^0(%arg12 : i64):
  %0 = llvm.mlir.constant(4) : i64
  %1 = llvm.mlir.constant(0) : i64
  %2 = llvm.mul %arg12, %0 : i64
  %3 = llvm.icmp "ne" %2, %1 : i64
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

instance : DecidableNFA' (NFA'.autMsbSet) where

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

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

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

Lean.Expr.forallE in Lean.Expr

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

def xor_of_icmps_to_ne_commute_after := [llvm|
{
^0(%arg28 : i64):
  %0 = llvm.mlir.constant(5) : i64
  %1 = llvm.icmp "ne" %arg28, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def test_xor_ne_before := [llvm|
{
^0(%arg64 : i8, %arg65 : i8, %arg66 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg66, %0 : i8
  %2 = llvm.xor %arg65, %0 : i8
  %3 = llvm.xor %2, %arg64 : i8
  %4 = llvm.icmp "ne" %1, %3 : i8
  "llvm.return"(%4) : (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 fold_mask_cmps_to_true_logical_before := [llvm|
{
^0(%arg108 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(true) : i1
  %3 = llvm.and %arg108, %0 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.icmp "ne" %arg108, %0 : i32
  %6 = "llvm.select"(%5, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

def eq_21_logical_before := [llvm|
{
^0(%arg104 : i32, %arg105 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.lshr %arg104, %0 : i32
  %4 = llvm.trunc %3 : i32 to i8
  %5 = llvm.lshr %arg104, %1 : i32
  %6 = llvm.trunc %5 : i32 to i8
  %7 = llvm.lshr %arg105, %0 : i32
  %8 = llvm.trunc %7 : i32 to i8
  %9 = llvm.lshr %arg105, %1 : i32
  %10 = llvm.trunc %9 : i32 to i8
  %11 = llvm.icmp "eq" %4, %8 : i8
  %12 = llvm.icmp "eq" %6, %10 : i8
  %13 = "llvm.select"(%12, %11, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%13) : (i1) -> ()
}
]

def irc_constants_AMinusC1PlusC2_2_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.sub %a, %c1 : i64
      %1 = llvm.add %0, %c2 : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%a: i64):
      %c1 = llvm.mlir.constant (2) : i64
      %c2 = llvm.mlir.constant (2) : i64
      %0 = llvm.sub %c2, %c1 : i64
      %1 = llvm.add %a, %0 : i64
      llvm.return %1 : i64
  }]

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

def foo_before := [llvm|
{
^0(%arg113 : i32, %arg114 : i32, %arg115 : i32, %arg116 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.icmp "slt" %arg113, %arg114 : i32
  %2 = llvm.sext %1 : i1 to i32
  %3 = llvm.and %arg115, %2 : i32
  %4 = llvm.xor %2, %0 : i32
  %5 = llvm.and %arg116, %4 : i32
  %6 = llvm.or %3, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

@[simp_denote]
def llvm_xor_32: Com  LLVMPlusRiscV ⟨[.llvm (.bitvec 32), .llvm (.bitvec 32)]⟩
  .pure (.llvm (.bitvec 32)) := [LV| {
  ^entry (%x: i32, %y: i32):
    %0 = llvm.xor    %x, %y : i32
    llvm.return %0 : i32
  }]

instance : Monad PoisonOr where
  pure := value
  bind := fun a f => match a with
    | poison  => poison
    | value a => f a

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

def 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 icmp_select_var_pred_uge_before := [llvm|
{
^0(%arg65 : i8, %arg66 : i8, %arg67 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.add %arg67, %0 overflow<nuw> : i8
  %3 = llvm.icmp "eq" %arg65, %1 : i8
  %4 = "llvm.select"(%3, %arg67, %arg66) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %5 = llvm.icmp "uge" %4, %2 : i8
  "llvm.return"(%5) : (i1) -> ()
}
]

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

def t1_flags_before := [llvm|
{
^0(%arg48 : i8, %arg49 : i8, %arg50 : i8):
  %0 = llvm.sub %arg48, %arg49 overflow<nsw,nuw> : i8
  %1 = llvm.sub %0, %arg50 overflow<nsw,nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def lhs : Com ScfArith ⟨[  t]⟩ .impure t :=
    Com.letPure (cst_nat niters1) <|
    Com.letPure (cst start1) <|
    Com.letPure (cst 1) <|
  
  Com.var (for_ (t := t) ⟨1, by admit /- proof elided -/
  ⟩ ⟨0, by admit /- proof elided -/
  ⟩ ⟨2, by admit /- proof elided -/
  ⟩ ⟨3, by admit /- proof elided -/
  ⟩ rgn) <|
    Com.letPure (cst_nat niters2) <|
    Com.letPure (cst <| niters1 + start1) <|
    Com.letPure (cst 1) <|
  Com.var (for_ (t := t) ⟨1, by admit /- proof elided -/
  ⟩ ⟨0, by admit /- proof elided -/
  ⟩ ⟨2, by admit /- proof elided -/
  ⟩ ⟨3, by admit /- proof elided -/
  ⟩ rgn) <|
  Com.ret ⟨0, rfl⟩

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

def ashr_xor_after := [llvm|
{
^0(%arg46 : i32, %arg47 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(12 : i32) : i32
  %2 = llvm.mlir.constant(7 : i32) : i32
  %3 = llvm.srem %arg47, %0 : i32
  %4 = llvm.ashr %arg46, %1 : i32
  %5 = llvm.ashr %3, %2 : i32
  %6 = llvm.xor %4, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

OptionT in Init.Control.Option

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

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

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

abbrev BitVecs.empty : BitVecs n := ⟨0, List.Vector.replicate n .nil⟩

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

def test1_after := [llvm|
{
^0(%arg153 : i32):
  "llvm.return"(%arg153) : (i32) -> ()
}
]

def bitwise_or_logical_or_icmps_before := [llvm|
{
^0(%arg184 : i8, %arg185 : i8, %arg186 : 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(true) : i1
  %4 = llvm.icmp "eq" %arg185, %0 : i8
  %5 = llvm.and %arg184, %1 : i8
  %6 = llvm.shl %1, %arg186 : i8
  %7 = llvm.and %arg184, %6 : i8
  %8 = llvm.icmp "eq" %5, %2 : i8
  %9 = llvm.icmp "eq" %7, %2 : i8
  %10 = "llvm.select"(%4, %3, %8) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %11 = llvm.or %10, %9 : i1
  "llvm.return"(%11) : (i1) -> ()
}
]

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

def Tensor2d'.map (f : α → β) (t : Tensor2d' α) : Tensor2d' β where
  dim₀ := t.dim₀
  dim₁ := t.dim₁
  mat := t.mat.map f

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 ZeroMinusAPlusB : 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, %a : i64
      %2 = llvm.add %1, %b : i64
      llvm.return %2 : i64
  }]
  rhs := [LV| {
    ^entry (%a: i64, %b: i64):
      %0 = llvm.sub %b, %a : i64
      llvm.return %0 : i64
  }]

def ashrsgt_03_00_exact_before := [llvm|
{
^0(%arg69 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(0 : i4) : i4
  %2 = llvm.ashr exact %arg69, %0 : i4
  %3 = llvm.icmp "sgt" %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 narrow_zext_add_before := [llvm|
{
^0(%arg42 : i16, %arg43 : i32):
  %0 = llvm.zext %arg42 : i16 to i32
  %1 = llvm.add %0, %arg43 : i32
  %2 = llvm.trunc %1 : i32 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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 }

    |

def p0_before := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.shl %0, %arg29 : i8
  %2 = llvm.xor %1, %0 : i8
  %3 = llvm.icmp "uge" %2, %arg28 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

ite in Init.Prelude

private def pretty_test_disjoint :=
  [llvm()|{
  ^bb0(%arg0: i32, %arg1: i32):
    %1 = llvm.or disjoint %arg0, %arg1 : i32
    llvm.return %1 : i32
  }]

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

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

instance : HasUB PoisonOr where
  throwUB := .poison

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

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

def select_icmp_ne_0_and_4096_or_32_after := [llvm|
{
^0(%arg209 : i32, %arg210 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(32 : i32) : i32
  %2 = llvm.lshr %arg209, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.xor %3, %1 : i32
  %5 = llvm.or %arg210, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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 masked_icmps_mask_notallzeros_bmask_mixed_negated_6_after := [llvm|
{
^0(%arg58 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.and %arg58, %0 : i32
  %3 = llvm.icmp "ne" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

instance : Monad SLLVM.m :=

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 visitSUB_ANegBNegC : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%a: i64, %b: i64, %c: i64):
      %0 = llvm.sub %b, %c : i64
      %1 = llvm.sub %a, %0 : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%a: i64, %b: i64, %c: i64):
      %0 = llvm.sub %c, %b : i64
      %1 = llvm.add %a, %0 : i64
      llvm.return %1 : i64
  }]

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 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_after := [llvm|
{
^0(%arg5 : i1005):
  "llvm.return"(%arg5) : (i1005) -> ()
}
]

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

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

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 and_sel_op0_before := [llvm|
{
^0(%arg17 : i1):
  %0 = llvm.mlir.constant(25 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = "llvm.select"(%arg17, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.and %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

instance : ToString (Com d Γ eff t)  where toString com  := s!"{com.print}"

@[simp_denote]
def and_llvm_16 := [LV| {
  ^entry (%lhs: i16, %rhs: i16):
    %1 = llvm.and %lhs, %rhs : i16
    llvm.return %1 : i16
  }]

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 test34_before := [llvm|
{
^0(%arg160 : i16):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.zext %arg160 : i16 to i32
  %2 = llvm.lshr %1, %0 : i32
  %3 = llvm.trunc %2 : i32 to i16
  "llvm.return"(%3) : (i16) -> ()
}
]

abbrev MContext φ := Ctxt <| (MetaLLVM φ).Ty

def test_shl_nuw__nuw_is_safe_before := [llvm|
{
^0(%arg80 : i32, %arg81 : 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 %arg80, %0 : i32
  %4 = llvm.shl %3, %1 overflow<nuw> : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.icmp "eq" %3, %2 : i32
  %7 = llvm.ashr %arg81, %5 : i64
  %8 = "llvm.select"(%6, %arg81, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

def t2_before := [llvm|
{
^0(%arg25 : i8, %arg26 : i1, %arg27 : i1):
  %0 = llvm.sext %arg26 : i1 to i8
  %1 = llvm.sext %arg27 : i1 to i8
  %2 = llvm.add %0, %arg25 : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def sub_ashr_or_i32_nuw_nsw_after := [llvm|
{
^0(%arg30 : i32, %arg31 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.icmp "slt" %arg31, %arg30 : i32
  %2 = "llvm.select"(%1, %0, %arg30) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%2) : (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 srli_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where
  lhs := srli_llvm
  rhs := srli_riscv

@[simp_denote]
def zext_llvm_8_to_64 := [LV| {
  ^entry (%arg: i8):
    %0 = llvm.zext %arg: i8 to i64
    llvm.return %0: i64
  }]

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 shl_add_log_may_cause_poison_pr62175_with_nuw_after := [llvm|
{
^0(%arg2 : i8, %arg3 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.add %arg2, %0 : i8
  %2 = llvm.shl %arg3, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

@[simp_denote]
def sub {Γ : 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.sub w)
    (eff_le := by admit /- proof elided -/
    )
    (ty_eq := rfl)
    (args := .cons ⟨l, lp⟩ <| .cons ⟨r, rp⟩ .nil)
    (regArgs := .nil)

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

def test13_after := [llvm|
{
^0(%arg0 : i1024):
  %0 = llvm.mlir.constant(1016 : i1024) : i1024
  %1 = llvm.lshr %arg0, %0 : i1024
  "llvm.return"(%1) : (i1024) -> ()
}
]

def t9_c0_c2_after := [llvm|
{
^0(%arg13 : i8, %arg14 : i8):
  %0 = llvm.mlir.constant(18 : i8) : i8
  %1 = llvm.sub %0, %arg13 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def source (a: α) : Stream α :=
  Stream.corec (a) fun (a) => (some a, (a))

def sgt_and_min_logical_before := [llvm|
{
^0(%arg350 : i9, %arg351 : i9):
  %0 = llvm.mlir.constant(-256 : i9) : i9
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "sgt" %arg350, %arg351 : i9
  %3 = llvm.icmp "eq" %arg350, %0 : i9
  %4 = "llvm.select"(%2, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def lhsSketchEnumeration  (lhsSketch: GenBVExpr w) (inputVars: List Nat) (lhsSymVars rhsSymVars : Std.HashMap Nat BVExpr.PackedBitVec) : ExpressionSynthesisResult := Id.run do
  let zero := wrap (GenBVExpr.const (BitVec.ofNat w 0))
  let one := wrap (GenBVExpr.const (BitVec.ofNat w 1 ))
  let minusOne := wrap (GenBVExpr.const (BitVec.ofInt w (-1)))

  
  let specialConstants := [zero, one, minusOne]
  let inputCombinations := productsList (List.replicate inputVars.length specialConstants)

  let lhsSymVarsAsBVExprs : List (BVExprWrapper):= lhsSymVars.toList.map (λ (id, pbv) => {bvExpr := GenBVExpr.var id, width := pbv.w})
  let lhsSymVarsPermutation := productsList (List.replicate lhsSymVarsAsBVExprs.length lhsSymVarsAsBVExprs)

  let inputsAndSymVars := List.product inputCombinations lhsSymVarsPermutation

  let mut rhsVarByValue : Std.HashMap (BitVec w) Nat := Std.HashMap.emptyWithCapacity
  for (var, value) in rhsSymVars.toArray do
    let h : value.w = w := sorry
    rhsVarByValue := rhsVarByValue.insert (h ▸ value.bv) var

  let mut res : ExpressionSynthesisResult := Std.HashMap.emptyWithCapacity
  for combo in inputsAndSymVars do
    let inputsSubstitutions := bvExprToSubstitutionValue (Std.HashMap.ofList (List.zip inputVars combo.fst))
    let symVarsSubstitutions := bvExprToSubstitutionValue (Std.HashMap.ofList (List.zip lhsSymVars.keys combo.snd))

    let substitutedExpr := substituteBVExpr lhsSketch (Std.HashMap.union inputsSubstitutions symVarsSubstitutions)
    let evalRes : BitVec w := evalBVExpr lhsSymVars substitutedExpr

    if rhsVarByValue.contains evalRes then
      let existingVar := rhsVarByValue[evalRes]!
      let existingVarRes := res.getD existingVar []

      res := res.insert existingVar (wrap substitutedExpr :: existingVarRes)

  pure res

abbrev AttrVal (φ := 0) := AttrValue φ

def foo_after := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(223 : i32) : i32
  %1 = llvm.mlir.constant(29 : i32) : i32
  %2 = llvm.mlir.constant(1362915575 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.mlir.constant(290 : i32) : i32
  %5 = llvm.mlir.constant(1533579450 : i32) : i32
  %6 = llvm.mlir.constant(749011377 : i32) : i32
  %7 = llvm.and %arg0, %0 : i32
  %8 = llvm.xor %7, %1 : i32
  %9 = llvm.add %8, %2 overflow<nsw,nuw> : i32
  %10 = llvm.shl %8, %3 overflow<nsw,nuw> : i32
  %11 = llvm.and %10, %4 : i32
  %12 = llvm.sub %9, %11 overflow<nsw,nuw> : i32
  %13 = llvm.add %12, %5 overflow<nuw> : i32
  %14 = llvm.xor %13, %6 : i32
  "llvm.return"(%14) : (i32) -> ()
}
]

def test1_after := [llvm|
{
^0(%arg34 : i32, %arg35 : i32):
  %0 = llvm.icmp "ugt" %arg35, %arg34 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

instance : HydrableInstances FpPredicate where

instance : DecidableEq LLVM.Op :=
    inferInstanceAs <| DecidableEq (InstCombine.MOp 0)

def and_sext_to_sel_after := [llvm|
{
^0(%arg41 : i32, %arg42 : i1):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = "llvm.select"(%arg42, %arg41, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def or_not_and_wrong_c_before := [llvm|
{
^0(%arg488 : i32, %arg489 : i32, %arg490 : i32, %arg491 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg488, %arg489 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.and %2, %arg490 : i32
  %4 = llvm.or %arg488, %arg491 : i32
  %5 = llvm.xor %4, %0 : i32
  %6 = llvm.and %5, %arg489 : i32
  %7 = llvm.or %3, %6 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

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

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

List.toArray in Init.Prelude

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

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

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.slliw in RISCV.Instructions

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 ashrsgt_01_14_exact_after := [llvm|
{
^0(%arg87 : i4):
  %0 = llvm.mlir.constant(-4 : i4) : i4
  %1 = llvm.icmp "sgt" %arg87, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def select_icmp_slt_zero_smin_before := [llvm|
{
^0(%arg7 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(-128 : i8) : i8
  %2 = llvm.icmp "slt" %arg7, %0 : i8
  %3 = llvm.xor %arg7, %1 : i8
  %4 = "llvm.select"(%2, %arg7, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (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 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 both_sides_fold_slt_before := [llvm|
{
^0(%arg39 : i32, %arg40 : i1):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(9 : i32) : i32
  %2 = "llvm.select"(%arg40, %0, %arg39) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %3 = "llvm.select"(%arg40, %1, %arg39) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.icmp "slt" %3, %2 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def size : FpExpr e → Nat
  | .var _ => 1
  | .const _ => 1
  | .bin lhs _ rhs => 1 + lhs.size + rhs.size

def invert_both_cmp_operands_add_after := [llvm|
{
^0(%arg38 : i32, %arg39 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.sub %arg38, %arg39 : i32
  %2 = llvm.icmp "slt" %1, %0 : i32
  "llvm.return"(%2) : (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) -> ()
}
]

BitVec.carry in Init.Data.BitVec.Bitblast

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

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

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

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

def andcond.010.inv.inner.cond.in.inner.sel_before := [llvm|
{
^0(%arg65 : i1, %arg66 : i1, %arg67 : i1, %arg68 : i1, %arg69 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg65, %arg66, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = llvm.xor %arg65, %1 : i1
  %4 = "llvm.select"(%3, %arg68, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = "llvm.select"(%2, %arg69, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (i1) -> ()
}
]

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

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

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 llvm00:=
  [LV|{
  ^bb0(%X : i64, %Y : i64 ):
    %1 = llvm.add %X, %Y : i64
    %2 = llvm.sub %X, %X : i64
    %3 = llvm.add %1, %Y : i64
    %4 = llvm.add %3, %Y : i64
    %5 = llvm.add %3, %4 : i64
    llvm.return %5 : i64
  }]

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

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

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

def 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 irc_constants_C1Minus2MinusC2_0_2 : 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 %c1, %a : i64
      %1 = llvm.sub %0, %c2 : i64
      llvm.return %1 : i64
  }]
  rhs := [LV| {
    ^entry (%a: i64):
      %c1 = llvm.mlir.constant (0) : i64
      %c2 = llvm.mlir.constant (2) : i64
      %0 = llvm.sub %c1, %c2 : i64
      %1 = llvm.sub %0, %a : i64
      llvm.return %1 : i64
  }]

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

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

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

def test_sdiv_canonicalize_op0_exact_after := [llvm|
{
^0(%arg13 : i32, %arg14 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.sdiv exact %arg13, %arg14 : i32
  %2 = llvm.sub %0, %1 overflow<nsw> : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

def Refinement.ofEq : Refinement α where
  IsRefinedBy := Eq

def xor_of_icmps_to_eq_before := [llvm|
{
^0(%arg21 : i8):
  %0 = llvm.mlir.constant(126 : i8) : i8
  %1 = llvm.mlir.constant(-128 : i8) : i8
  %2 = llvm.icmp "sgt" %arg21, %0 : i8
  %3 = llvm.icmp "slt" %arg21, %1 : i8
  %4 = llvm.xor %3, %2 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def ashr1_before := [llvm|
{
^0(%arg29 : i64):
  %0 = llvm.mlir.constant(8) : i64
  %1 = llvm.mlir.constant(2) : i64
  %2 = llvm.shl %arg29, %0 : i64
  %3 = llvm.ashr %2, %1 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

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

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

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

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

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 t4_after := [llvm|
{
^0(%arg210 : i8, %arg211 : i1):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(-44 : i8) : i8
  %2 = "llvm.select"(%arg211, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.add %2, %arg210 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

def and_min_7_8_before := [llvm|
{
^0(%arg1 : i8):
  %0 = llvm.mlir.constant(-8 : i8) : i8
  %1 = llvm.icmp "ult" %arg1, %0 : i8
  %2 = "llvm.select"(%1, %arg1, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.and %2, %0 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

def one_inst_concrete_macro :=
  [llvm()|{
  ^bb0(%arg0: i1):
    %0 = llvm.not %arg0 : i1
    llvm.return %0 : i1
  }]

BitVec.sge in Leanwuzla.Aux

def InstCombine.MTy.cast_concrete (mvars : Nat) (ty : InstCombine.MTy mvars)
    (hMvars : mvars = 0) : InstCombine.MTy 0 :=
    hMvars ▸ ty

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

HSub.hSub in Init.Prelude

@[match_pattern] abbrev copy   : Nat → LLVM.Op := MOp.copy   ∘ .concrete

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

def Expr.KInductionCircuits.mkIsLawful_mkN (fsm : Expr) (n : Expr) : MetaM Expr :=
  mkAppM ``ReflectVerif.BvDecide.KInductionCircuits.IsLawful_mkN #[fsm, n]

def lshrult_03_04_before := [llvm|
{
^0(%arg331 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(4 : i4) : i4
  %2 = llvm.lshr %arg331, %0 : i4
  %3 = llvm.icmp "ult" %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 add_mask_ashr28_i32_after := [llvm|
{
^0(%arg2 : i32):
  %0 = llvm.mlir.constant(28 : i32) : i32
  %1 = llvm.mlir.constant(7 : i32) : i32
  %2 = llvm.lshr %arg2, %0 : i32
  %3 = llvm.and %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

def test14_after := [llvm|
{
^0(%arg0 : i32, %arg1 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(128 : i32) : i32
  %3 = llvm.shl %arg0, %0 : i32
  %4 = llvm.sub %1, %arg1 : i32
  %5 = llvm.and %4, %2 : i32
  %6 = llvm.mul %5, %3 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def trunc_signed_nsw_before := [llvm|
{
^0(%arg50 : i16, %arg51 : i16):
  %0 = llvm.trunc %arg50 overflow<nsw> : i16 to i8
  %1 = llvm.trunc %arg51 overflow<nsw> : i16 to i8
  %2 = llvm.icmp "slt" %0, %1 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def 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 sext_sext_ne_before := [llvm|
{
^0(%arg70 : i8, %arg71 : i8):
  %0 = llvm.sext %arg70 : i8 to i32
  %1 = llvm.sext %arg71 : i8 to i32
  %2 = llvm.icmp "ne" %0, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def LLVMIR_identity_combines_64 : List (Σ Γ, LLVMPeepholeRewriteRefine 64 Γ) :=
  select_same_val ++ binop_left_to_zero ++ binop_right_to_zero ++
  select_constant_cmp ++ urem_pow2_to_mask

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 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 size : GenBVPred → Nat
| .bin lhs _ rhs => 1 + lhs.size + rhs.size
| .getLsbD e _ => 1 + e.size

def add_b32_test_no_ZBS_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := add_b32_llvm_i64
  rhs := add_b32_riscv_i64_no_ZBS

def test6 : BitVec 4 :=
  CombEg6.denote (Ctxt.Valuation.ofHVector (.cons bv6c <| .cons bv6₂ <| .cons bv6₁ <| .nil))

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

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

def one_side_fold_eq_before := [llvm|
{
^0(%arg25 : i32, %arg26 : i32, %arg27 : i32, %arg28 : i1):
  %0 = "llvm.select"(%arg28, %arg25, %arg27) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %1 = "llvm.select"(%arg28, %arg26, %arg27) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "eq" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

def src_is_notmask_ashr_after := [llvm|
{
^0(%arg55 : i16, %arg56 : i8, %arg57 : i16):
  %0 = llvm.mlir.constant(-32 : i8) : i8
  %1 = llvm.mlir.constant(-124 : i16) : i16
  %2 = llvm.shl %0, %arg56 : i8
  %3 = llvm.sext %2 : i8 to i16
  %4 = llvm.ashr %3, %arg57 : i16
  %5 = llvm.xor %arg55, %1 : i16
  %6 = llvm.icmp "uge" %5, %4 : i16
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

def Vector.ofArray {α : Type u} (a : Array α) : List.Vector α a.size :=
 Vector.ofList a.toList

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

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

structure DerivedCtxt (Γ : Ctxt Ty) where
  ctxt : Ctxt Ty
  diff : Ctxt.Diff Γ ctxt

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

instance : Coe (MLIRType φ) (AttrValue φ) where
  coe := AttrValue.type

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

def tok1 : CIRCTStream.DCOp.TokenStream := ofList [some (), none, some (), some (), none]

def zext_nneg_after := [llvm|
{
^0(%arg0 : i16):
  %0 = llvm.mlir.constant(32767 : i16) : i16
  %1 = llvm.and %arg0, %0 : i16
  %2 = llvm.zext nneg %1 : i16 to i24
  "llvm.return"(%2) : (i24) -> ()
}
]

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

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

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

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

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

instance : DialectPrint (MetaLLVM φ) where
  printOpName := MetaLLVM.opName
  printTy := MetaLLVM.printType
  printAttributes := MetaLLVM.printAttributes
  dialectName := "llvm"
  printReturn _:= "llvm.return"
  printFunc _:= "^bb0"

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

RV64.lui in RISCV.Instructions

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

def precondSynthesisUpdateCache (previousLevelCache synthesisComponents: Std.HashMap (FpExpr w)  PreconditionSynthesisCacheValue)
      (positiveExamples negativeExamples: List (Std.HashMap Nat FpExprWrapper)) (specialConstants : Std.HashMap (FpExpr w) FpExprWrapper)
      (ops : List (FpExpr w → FpExpr w → FpExpr w)) : GeneralizerStateM ParsedFpExpr FpPredicate (Std.HashMap (FpExpr w) PreconditionSynthesisCacheValue) := do
  return {}

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

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

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

def select_of_anyext : List (Σ Γ, LLVMPeepholeRewriteRefine 64 Γ) :=
  [⟨_, select_of_anyext_rw⟩]

def add_shl_same_amount_partial_nuw1_before := [llvm|
{
^0(%arg35 : i6, %arg36 : i6, %arg37 : i6):
  %0 = llvm.shl %arg35, %arg37 overflow<nuw> : i6
  %1 = llvm.shl %arg36, %arg37 overflow<nuw> : i6
  %2 = llvm.add %0, %1 : i6
  "llvm.return"(%2) : (i6) -> ()
}
]

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

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

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 testExampleFstVal : DCOp.ValueStream (BitVec 8) :=
  exampleFstVal.denote (Ctxt.Valuation.ofHVector (.cons inputFstVal <| .nil))

def sext_diff_i1_xor_sub_1_after := [llvm|
{
^0(%arg12 : i64, %arg13 : i1, %arg14 : i1):
  %0 = llvm.sext %arg13 : i1 to i64
  %1 = llvm.zext %arg14 : i1 to i64
  %2 = llvm.add %1, %0 overflow<nsw> : i64
  "llvm.return"(%2) : (i64) -> ()
}
]

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

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

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

def add_umax_simplify_before := [llvm|
{
^0(%arg45 : i37):
  %0 = llvm.mlir.constant(42 : i37) : i37
  %1 = llvm.add %arg45, %0 overflow<nuw> : i37
  %2 = llvm.icmp "ugt" %1, %0 : i37
  %3 = "llvm.select"(%2, %1, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i37, i37) -> i37
  "llvm.return"(%3) : (i37) -> ()
}
]

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

def test93_after := [llvm|
{
^0(%arg47 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.ashr %arg47, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

def Sexpr.toFormat : Sexpr → Format
| .atom a => a
| .array as => (as.map Sexpr.toFormat) |>.toList |> fun l => Format.joinSep l " "  |>.paren

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

def demorgan_or_zext_before := [llvm|
{
^0(%arg16 : i1, %arg17 : i1):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.zext %arg16 : i1 to i32
  %2 = llvm.zext %arg17 : i1 to i32
  %3 = llvm.xor %1, %0 : i32
  %4 = llvm.xor %2, %0 : i32
  %5 = llvm.or %3, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

Fin.succRec in Init.Data.Fin.Lemmas

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

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

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

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

@[simp_denote]
def add_shl_rhs_constant_llvm := [LV| {
    ^entry (%a0: i64, %a1: i64):
    %0 = llvm.mlir.constant (1) : i64
    %c3 = llvm.mlir.constant (3) : i64
    %c8 = llvm.mlir.constant (-8) : i64
    %1 = llvm.add %a0, %0 : i64
    %2 = llvm.add %a1, %1 : i64
    %3 = llvm.shl %2, %c3 : i64
    %4 = llvm.add %3, %c8 : i64
    llvm.return %4 : i64
  }]

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

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

def sel_zext_constants_after := [llvm|
{
^0(%arg96 : i1):
  %0 = llvm.mlir.constant(255 : i16) : i16
  %1 = llvm.mlir.constant(42 : i16) : i16
  %2 = "llvm.select"(%arg96, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

abbrev Mapping (Γ Δ : Ctxt Ty) : Type :=
  @AList (Σ t, Var Γ t) (fun x => Var Δ x.1)

def n7_wrong_pred2_before := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.sub %arg10, %arg11 : i8
  %1 = llvm.icmp "eq" %0, %arg10 : i8
  "llvm.return"(%1) : (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 bar_after := [llvm|
{
^0(%arg109 : i32, %arg110 : i32, %arg111 : i32, %arg112 : i32):
  %0 = llvm.icmp "slt" %arg109, %arg110 : i32
  %1 = "llvm.select"(%0, %arg111, %arg112) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%1) : (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 test_shl__none_are_safe_after := [llvm|
{
^0(%arg64 : i32, %arg65 : i64):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(-8 : i32) : i32
  %2 = llvm.shl %arg64, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.zext nneg %3 : i32 to i64
  %5 = llvm.ashr %arg65, %4 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def lt_unsigned_to_small_unsigned_before := [llvm|
{
^0(%arg44 : i8):
  %0 = llvm.mlir.constant(17 : i32) : i32
  %1 = llvm.zext %arg44 : i8 to i32
  %2 = llvm.icmp "ult" %1, %0 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

Lean.mkOptionalNode in Init.Meta.Defs

def llvm_const_lower_riscv_li_15 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_15, rhs:= liRiscv_15,
   correct := by admit /- proof elided -/

def no_masks_with_logical_or2_after := [llvm|
{
^0(%arg7 : i32, %arg8 : i32, %arg9 : i32):
  %0 = llvm.mlir.constant(63 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.mlir.constant(true) : i1
  %3 = llvm.icmp "ne" %arg8, %0 : i32
  %4 = llvm.and %arg7, %arg9 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  %6 = "llvm.select"(%5, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

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_after := [llvm|
{
^0(%arg6 : i8):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def sdiv_icmp2_after := [llvm|
{
^0(%arg16 : i64):
  %0 = llvm.mlir.constant(5) : i64
  %1 = llvm.icmp "eq" %arg16, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

def ule_or_not_min_logical_after := [llvm|
{
^0(%arg270 : i427, %arg271 : i427):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

def 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 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 icmp_ule_64_before := [llvm|
{
^0(%arg17 : i128):
  %0 = llvm.mlir.constant(64 : i128) : i128
  %1 = llvm.mlir.constant(18446744073709551615 : i128) : i128
  %2 = llvm.shl %arg17, %0 overflow<nuw> : i128
  %3 = llvm.icmp "ule" %2, %1 : i128
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def logical_and_implies_folds_after := [llvm|
{
^0(%arg248 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.icmp "ugt" %arg248, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def test10_before := [llvm|
{
^0(%arg50 : i32, %arg51 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(-1431655766 : i32) : i32
  %2 = llvm.mlir.constant(1431655765 : i32) : i32
  %3 = llvm.mlir.constant(1 : i32) : i32
  %4 = llvm.ashr %arg50, %0 : i32
  %5 = llvm.or %4, %1 : i32
  %6 = llvm.xor %5, %2 : i32
  %7 = llvm.add %arg51, %3 : i32
  %8 = llvm.add %7, %6 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

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 shl_or_disjoint_lshr_after := [llvm|
{
^0(%arg109 : i32, %arg110 : i32, %arg111 : i32):
  %0 = llvm.lshr %arg111, %arg110 : i32
  %1 = llvm.or disjoint %0, %arg109 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

class HydrableInstances (genPred : Type) where
  beqLogical : BEq genPred := by admit /- proof elided -/

def testi8i8_before := [llvm|
{
^0(%arg10 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(127 : i8) : i8
  %2 = llvm.ashr %arg10, %0 : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

noncomputable def R.fromTensorFinsupp (q : Nat) (coeffs : List Int) : (ZMod q)[X] :=
  Polynomial.ofFinsupp (List.toFinsupp (coeffs.map Int.cast))

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

Stream'.drop in Mathlib.Data.Stream.Defs

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

def eq_smax2_after := [llvm|
{
^0(%arg61 : i32, %arg62 : i32):
  %0 = llvm.icmp "sge" %arg61, %arg62 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

@[simp_denote]
def transformExprLLVM (e : Expr (InstCombine.MetaLLVM 0) (ctxtTransformToLLVM Γ) eff ty) :
  MLIR.AST.ReaderM (LLVMPlusRiscV) (Expr LLVMPlusRiscV Γ eff (.llvm <$> ty)) :=
    match e with
    | Expr.mk op1 ty_eq1 eff_le1 args1 regArgs1 => do
        let args' : HVector (Ctxt.Var Γ) (.llvm <$> DialectSignature.sig op1) ←
          args1.mapM' fun t v => do
            match h : Γ[v.val]? with
            | some ty' => do
              match hty : ty' with
              | .riscv _ =>  
                throw <| .generic s!"INTERNAL ERROR: This case is impossible, LLVM expression is pointing to RISCV variable.
                Should haven been caught by the LLVM parser."
              | .llvm originalLLVMTy =>
                if hty' : originalLLVMTy = t then
                  return ⟨v.val, by admit /- proof elided -/
                  ⟩
                else
                  throw <|.generic s!"INTERNAL ERROR: This case is impossible, LLVM expression is pointing to an incorrect bitwidth LLVM argument."
            | none =>
              
              throw <| .generic s!"INTERNAL ERROR: This case is impossible, as 'ctxtTransformToLLVM' is length-preserving."
        return Expr.mk
          (op := Op.llvm op1)
          (eff_le := eff_le1)
          (ty_eq := by admit /- proof elided -/
          )
          (args := args')
          (regArgs := HVector.nil)

noncomputable def R.toTensor' {q n} (a : R q n) : List Int :=
  let t := a.toTensor
  t ++ List.replicate (2^n - t.length + 1) 0

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

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 add_or_and_before := [llvm|
{
^0(%arg19 : i32, %arg20 : i32):
  %0 = llvm.or %arg19, %arg20 : i32
  %1 = llvm.and %arg19, %arg20 : i32
  %2 = llvm.add %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

@[match_pattern] abbrev bitvec (w : Nat) : LLVM.Ty :=
  MTy.bitvec (.concrete w)

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

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

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 positive_trunc_signbit_after := [llvm|
{
^0(%arg41 : i32):
  %0 = llvm.mlir.constant(128 : i32) : i32
  %1 = llvm.icmp "ult" %arg41, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

def fold_icmp_shl_nuw_c3_before := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(48 : i32) : i32
  %1 = llvm.mlir.constant(144 : i32) : i32
  %2 = llvm.shl %0, %arg5 overflow<nuw> : i32
  %3 = llvm.icmp "uge" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def positive_biggerashr_ashrexact_before := [llvm|
{
^0(%arg40 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.mlir.constant(3 : i8) : i8
  %2 = llvm.ashr exact %arg40, %0 : i8
  %3 = llvm.shl %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

def icmp_equality_test_constant_after := [llvm|
{
^0(%arg32 : i42, %arg33 : i42):
  %0 = llvm.icmp "eq" %arg32, %arg33 : i42
  "llvm.return"(%0) : (i1) -> ()
}
]

def sub_dec_before := [llvm|
{
^0(%arg4 : i8, %arg5 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.add %arg4, %0 : i8
  %2 = llvm.sub %1, %arg5 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def substitute_constant_or_ne_uge_commute_logical_after := [llvm|
{
^0(%arg280 : i8, %arg281 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(43 : i8) : i8
  %2 = llvm.icmp "ne" %arg280, %0 : i8
  %3 = llvm.icmp "ult" %arg281, %1 : i8
  %4 = llvm.or %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

inductive Ty
| bitvec (w : Nat) : Ty 
deriving DecidableEq, Repr, ToExpr

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 x_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(65536 : i32) : i32
  %1 = llvm.mlir.constant(-65536 : i32) : i32
  %2 = llvm.sdiv %arg0, %0 : i32
  %3 = llvm.icmp "slt" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def add_nuw_const_const_sub_nuw_after := [llvm|
{
^0(%arg56 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.sub %0, %arg56 overflow<nuw> : i8
  "llvm.return"(%1) : (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) -> ()
}
]

instance : Coe (Γ.Var t) ((Γ ++ ts).Var t) where coe := appendInl

def add_of_mul_before := [llvm|
{
^0(%arg4 : i8, %arg5 : i8, %arg6 : i8):
  %0 = llvm.mul %arg4, %arg5 overflow<nsw> : i8
  %1 = llvm.mul %arg4, %arg6 overflow<nsw> : i8
  %2 = llvm.add %0, %1 overflow<nsw> : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def or_not_xor_common_op_commute0_after := [llvm|
{
^0(%arg107 : i4, %arg108 : i4, %arg109 : i4):
  %0 = llvm.mlir.constant(-1 : i4) : i4
  %1 = llvm.and %arg107, %arg108 : i4
  %2 = llvm.xor %1, %0 : i4
  %3 = llvm.or %arg109, %2 : i4
  "llvm.return"(%3) : (i4) -> ()
}
]

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

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

def main5c_like_before := [llvm|
{
^0(%arg103 : i32, %arg104 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.and %arg103, %0 : i32
  %4 = llvm.icmp "ne" %3, %0 : i32
  %5 = llvm.and %arg104, %0 : i32
  %6 = llvm.icmp "ne" %5, %0 : i32
  %7 = llvm.or %4, %6 : i1
  %8 = "llvm.select"(%7, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%8) : (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 p14_commutativity1_before := [llvm|
{
^0(%arg26 : i32, %arg27 : i32):
  %0 = llvm.mlir.constant(65536 : i32) : i32
  %1 = llvm.mlir.constant(65535 : i32) : i32
  %2 = llvm.mlir.constant(42 : i32) : i32
  %3 = llvm.icmp "ult" %arg26, %0 : i32
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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 ashrsgt_01_02_after := [llvm|
{
^0(%arg315 : i4):
  %0 = llvm.mlir.constant(5 : i4) : i4
  %1 = llvm.icmp "sgt" %arg315, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def mkLtTwoPowProof (x y : Nat) : Option Expr :=
  match y with
  | 0   => none
  | y'+1 => do
    if x = 0 then
      return mkApp (mkConst ``Nat.two_pow_pos) (toExpr y)
    else
      let h ← mkLtTwoPowProof (x / 2) y'
      return mkApp3 (mkConst ``Nat.lt_two_pow_succ_of_lt) (toExpr x) (toExpr y') h

simproc ↓ reduceModTwoPow ((_ : Nat) % 2 ^ (_ : Nat)) := fun e => do
  let_expr HMod.hMod _α _β _γ _self x rhs := e | return .continue
  let_expr HPow.hPow _α _β _γ _self _ y := rhs | return .continue
  let some xVal := x.nat? | return .continue
  let some yVal := y.nat? | return .continue

  let some ltProof := mkLtTwoPowProof xVal yVal
    | return .continue

  return .done {
    expr := x
    proof? := mkApp3 (mkConst ``Nat.mod_eq_of_lt) x rhs ltProof
  }

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 ashr_lshr2_after := [llvm|
{
^0(%arg125 : i32, %arg126 : i32):
  %0 = llvm.ashr %arg125, %arg126 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

@[simp_denote]
def sext_riscv_i32_to_64 := [LV| {
  ^entry (%arg: i32):
    %0 = "builtin.unrealized_conversion_cast"(%arg) : (i32) -> (!i64)
    %1 = sext.w %0 : !i64
    %res = "builtin.unrealized_conversion_cast"(%1) : (!i64) -> (i64)
    llvm.return %res : i64
  }]

def Lets.vars : Lets d Γ_in eff Γ_out → Var Γ_out t → VarSet Γ_in
  | .nil, v => VarSet.ofVar v
  | .var lets e, v => by admit /- proof elided -/
      | right v => exact lets.vars v
      | left _ => exact lets.varsOfVec e.args

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

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

def shl_add_add_no_const_before := [llvm|
{
^0(%arg122 : i8, %arg123 : i8, %arg124 : i8, %arg125 : i8):
  %0 = llvm.shl %arg122, %arg124 : i8
  %1 = llvm.shl %arg123, %arg124 : i8
  %2 = llvm.add %1, %arg125 : i8
  %3 = llvm.add %0, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

def mul_splat_fold_no_nuw_before := [llvm|
{
^0(%arg79 : i32):
  %0 = llvm.mlir.constant(65537 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mul %arg79, %0 overflow<nsw> : i32
  %3 = llvm.lshr %2, %1 : i32
  "llvm.return"(%3) : (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 main4b_logical_before := [llvm|
{
^0(%arg131 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.mlir.constant(false) : i1
  %4 = llvm.mlir.constant(1 : i32) : i32
  %5 = llvm.and %arg131, %0 : i32
  %6 = llvm.icmp "eq" %5, %0 : i32
  %7 = llvm.and %arg131, %1 : i32
  %8 = llvm.icmp "ne" %7, %2 : i32
  %9 = "llvm.select"(%6, %8, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %10 = "llvm.select"(%9, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%10) : (i32) -> ()
}
]

@[simp_denote]
def add_hi_zero_lo_negone_llvm_i64 := [LV| {
    ^entry (%0: i64):
    %4294967295 = llvm.mlir.constant (4294967295) : i64
    %1 = llvm.add %0, %4294967295 : i64
    llvm.return %1 : i64
  }]

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

def sext_shl_trunc_same_size_after := [llvm|
{
^0(%arg13 : i16, %arg14 : i32):
  %0 = llvm.zext %arg13 : i16 to i32
  %1 = llvm.shl %0, %arg14 : i32
  %2 = llvm.trunc %1 : i32 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

def canonicalize_logic_first_xor_0_nswnuw_before := [llvm|
{
^0(%arg15 : i8):
  %0 = llvm.mlir.constant(96 : i8) : i8
  %1 = llvm.mlir.constant(31 : i8) : i8
  %2 = llvm.add %arg15, %0 overflow<nsw,nuw> : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

def alive_AddSub_1614_tgt :=
[sllvm| {
^bb0(%Y : i64, %X : i64):
  %v1 = llvm.add %X, %Y : i64
  %v2 = llvm.mlir.constant 0 : i64
  %v3 = llvm.sub %v2, %Y : i64
  llvm.return %v3 : i64
}]

def llvm_add_lower_riscv_nuw_nsw_flag_1 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1), Ty.llvm (.bitvec 1)] where
  lhs:= add_llvm_nsw_nuw_flags_1
  rhs:= add_riscv_1

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

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

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

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

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

instance : Inhabited (Region φ) where
  default := Region.empty "INHABITANT"

def no_shift_no_xor_multiuse_cmp_or_before := [llvm|
{
^0(%arg60 : i32, %arg61 : i32, %arg62 : i32, %arg63 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg60, %0 : i32
  %3 = llvm.icmp "eq" %2, %1 : i32
  %4 = llvm.or %arg61, %0 : i32
  %5 = "llvm.select"(%3, %arg61, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = "llvm.select"(%3, %arg62, %arg63) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = llvm.mul %5, %6 : i32
  %8 = llvm.mul %7, %4 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

class HydrableBooleanAlgebra (genPred : Type) (genExpr : Nat → Type) where
  
  
  eq : genExpr n → genExpr n → BoolExpr genPred

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

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

@[simp_riscv]
def snez_pseudo (rs1_val : BitVec 64) : BitVec 64 :=
  RV64.sltu rs1_val 0

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

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

def foo_before := [llvm|
{
^0(%arg0 : i64, %arg1 : i64):
  %0 = llvm.trunc %arg0 : i64 to i32
  %1 = llvm.trunc %arg1 : i64 to i32
  %2 = llvm.and %0, %1 : i32
  %3 = llvm.zext %2 : i32 to i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def xor_signbit_lshr_after := [llvm|
{
^0(%arg11 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(16776960 : i32) : i32
  %2 = llvm.lshr %arg11, %0 : i32
  %3 = llvm.xor %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

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

def inputSnd : (CIRCTStream.DCOp.TokenStream × CIRCTStream.DCOp.TokenStream) := (tok1, tok2)

def select_icmp_eq_0_and_1_or_1_after := [llvm|
{
^0(%arg217 : i64, %arg218 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.trunc %arg217 : i64 to i32
  %2 = llvm.and %1, %0 : i32
  %3 = llvm.or %arg218, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

def test23_after := [llvm|
{
^0(%arg8 : i44):
  %0 = llvm.trunc %arg8 : i44 to i11
  "llvm.return"(%0) : (i11) -> ()
}
]

def negate_zext_before := [llvm|
{
^0(%arg96 : i8, %arg97 : i1):
  %0 = llvm.zext %arg97 : i1 to i8
  %1 = llvm.sub %arg96, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

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

def icmp_shl_nsw_eq_before := [llvm|
{
^0(%arg26 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %arg26, %0 overflow<nsw> : i32
  %3 = llvm.icmp "eq" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def test1_before := [llvm|
{
^0(%arg153 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg153, %0 : i32
  %2 = llvm.xor %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]
</all_available_defs>

<all_available_lemmas>
List.nodup_singleton in Mathlib.Data.List.Nodup
NFA.eval_append_singleton in Mathlib.Computability.NFA
NFA.eval_nil in Mathlib.Computability.NFA
Set.mem_setOf_eq in Mathlib.Data.Set.Operations
Nat.add_comm in Init.Data.Nat.Basic
Fin.add_def in Init.Data.Fin.Lemmas
Fin.castLE_castLE in Init.Data.Fin.Lemmas
Nat.le_of_eq in Init.Data.Nat.Basic
Nat.mod_eq_of_lt in Init.Data.Nat.Div.Basic
Fin.ext_iff in Init.Data.Fin.Lemmas
Nat.mod_le in Init.Data.Nat.Div.Basic
eq_iff_iff in Init.Core
iff_true in Init.SimpLemmas
ite_cond_eq_true in Init.SimpLemmas

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

theorem x_proof : x_before ⊑ x_after

theorem e_2142 :
     - 2 * (d &&& (e ^^^ f)) + 1 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) - 6 * (e ^^^ (d ||| ( ~~~e &&& f))) - 2 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 1 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) - 2 * ( ~~~d &&& ( ~~~e ||| f)) - 1 * (e ^^^ ( ~~~d ||| (e ||| f))) - 1 *  ~~~( ~~~d &&& (e &&& f)) - 2 * ( ~~~e &&& (d ^^^ f)) - 2 *  ~~~(d ||| (e &&& f)) - 11 * (e ^^^  ~~~(d &&& (e ||| f))) + 1 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 1 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) - 11 * ( ~~~e |||  ~~~(d ^^^ f)) + 4 * (e &&&  ~~~(d &&&  ~~~f)) - 1 *  ~~~(d &&& (e ||| f)) + 3 * (f ^^^  ~~~(d &&& (e &&& f))) + 2 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 5 *  ~~~f - 5 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 7 * (e ^^^ (d &&& f)) + 3 * ( ~~~d ||| ( ~~~e ||| f)) + 3 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) - 11 *  ~~~(e ^^^ f) + 4 * (e ^^^  ~~~(d &&&  ~~~f)) + 1 * (e ^^^ (d &&& ( ~~~e ||| f))) + 1 * ((d &&& e) ^^^ (e |||  ~~~f)) - 2 *  ~~~d - 6 * (d &&& f) + 1 * ((d &&& f) ^^^ (e ||| f)) + 2 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 3 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 2 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 4 * (f ^^^  ~~~(d |||  ~~~e)) + 1 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 3 * ((d &&& e) ^^^ (e ||| f)) + 5 * ( ~~~d ||| (e ||| f)) - 11 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 2 * (e |||  ~~~(d |||  ~~~f)) + 24 *  ~~~(d ||| (e ||| f)) - 17 *  ~~~(d ||| ( ~~~e ||| f)) + 37 *  ~~~( ~~~d ||| (e ||| f)) + 26 * ( ~~~d &&& ( ~~~e &&& f)) - 8 * ( ~~~d &&& (e &&& f)) + 7 * (d &&& ( ~~~e &&& f)) + 18 * (d &&& (e &&& f)) =  - 7 * (f |||  ~~~(d |||  ~~~e)) - 1 * (e |||  ~~~(d ||| f))

theorem or_not_and_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ((x_2 ||| x_1) ^^^ -1#32) &&& x ||

theorem test33b_proof : test33b_before ⊑ test33b_after

theorem icmp_eq_and_pow2_minus1_shl1_negative2_thm (e : IntW 32) :
  zext 32 (icmp IntPred.eq (LLVM.and (shl (const? 32 32) e) (const? 32 15)) (const? 32 0)) ⊑ const? 32 1

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 bad_add1_proof : bad_add1_before ⊑ bad_add1_after

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

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

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

theorem slt_zero_ult_i1_proof : slt_zero_ult_i1_before ⊑ slt_zero_ult_i1_after

theorem ashrsgt_01_04_exact_proof : ashrsgt_01_04_exact_before ⊑ ashrsgt_01_04_exact_after

theorem t0_thm.extracted_1._3 : ∀ (x x_1 x_2 x_3 : BitVec 8) (x_4 : BitVec 1),
  (x_4 ^^^ 1#1) &&& ofBool (x_3 == x_2) = 1#1 → ofBool (x_3 != x_2) ||

theorem t2_symmetry_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ofBool (x_1 ≤ᵤ x_1 + x) = ofBool (x ≤ᵤ x_1 ^^^ -1#8)

theorem ashr_sgt_overflow_proof : ashr_sgt_overflow_before ⊑ ashr_sgt_overflow_after

theorem lt_unsigned_to_small_signed_proof : lt_unsigned_to_small_signed_before ⊑ lt_unsigned_to_small_signed_after

theorem e_1700 :
    4 * (c ^^^ (a &&&  ~~~b)) + 4 *  ~~~(a ^^^ (b ^^^ c)) - 7 * (b |||  ~~~(a |||  ~~~c)) - 2 * ((a ^^^ b) &&& (a ^^^ c)) - 6 *  ~~~(a ^^^ ( ~~~b ||| c)) + 7 * ( ~~~b ||| (a ^^^ c)) + 5 * (b ^^^ (a ||| ( ~~~b ||| c))) - 3 * (b ^^^ ( ~~~a &&& (b ^^^ c))) + 3 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 11 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 1 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 2 *  ~~~(b ^^^ c) + 7 * (b ||| (a &&& c)) - 5 *  ~~~( ~~~a &&& (b ^^^ c)) - 2 * ( ~~~a ||| (b ||| c)) - 1 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) - 1 * (b ^^^ (a ||| (b ^^^ c))) + 1 * ((a &&& c) ||| (b &&&  ~~~c)) + 11 * ((a &&& b) ||| (b ^^^ c)) + 1 *  ~~~( ~~~a ||| ( ~~~b &&& c)) + 3 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 11 *  ~~~(a ||| (b ||| c)) + 4 *  ~~~(a ||| ( ~~~b ||| c)) + 6 *  ~~~( ~~~a ||| (b ||| c)) - 5 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 1 * ( ~~~a &&& ( ~~~b &&& c)) + 16 * ( ~~~a &&& (b &&& c)) - 27 * (a &&& ( ~~~b &&& c)) + 5 * (a &&& (b &&& c)) = 7 * (c &&&  ~~~(a &&&  ~~~b))

theorem mul8_low_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(4#8 ≥ ↑8 ∨ 4#8 ≥ ↑8 ∨ 4#8 ≥ ↑8) →
    (x_1 >>> 4#8 * (x &&& 15#8) + (x_1 &&& 15#8) * x >>> 4#8) <<< 4#8 + (x_1 &&& 15#8) * (x &&& 15#8) = x * x_1

@[simp]
theorem eval_bigAnd_eq_true_iff
    (cs : List (Circuit α)) (env : α → Bool):
    (Circuit.bigAnd cs).eval env = true ↔
    (∀ (c : Circuit α), c ∈ cs → c.eval env = true)

theorem src_is_mask_p2_m1_proof : src_is_mask_p2_m1_before ⊑ src_is_mask_p2_m1_after

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

theorem test25_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.sge e (const? 32 50)) (icmp IntPred.slt e (const? 32 100)) ⊑
    icmp IntPred.ult (add e (const? 32 (-50))) (const? 32 50)

theorem main4_logical_proof : main4_logical_before ⊑ main4_logical_after

@[simp]
theorem shiftRight_and_xor_shiftLeft_distrib {x y z : BitVec w} {n : Nat} :
    (x >>> n &&& y ^^^ z) <<< n = x &&& y <<< n ^^^ z <<< n

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

theorem masked_or_allones_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 == 7#32) ||

theorem bv_InstCombineShift__497''' :
    ∀ (e e_1 e_2 : LLVM.IntW w), LLVM.shl (LLVM.add e e_2) e_1 ⊑ LLVM.add (LLVM.shl e e_1) (LLVM.shl e_2 e_1)

theorem scalar_i64_lshr_and_signbit_eq_proof : scalar_i64_lshr_and_signbit_eq_before ⊑ scalar_i64_lshr_and_signbit_eq_after

theorem or_or_logic_and_1_proof : or_or_logic_and_1_before ⊑ or_or_logic_and_1_after

theorem testi64i32_ne_proof : testi64i32_ne_before ⊑ testi64i32_ne_after

theorem test22_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(2147483647#32 == 0 || 32 != 1 && x &&& 2147483647#32 == intMin 32 && 2147483647#32 == -1) = true →
    ¬2147483647#32 = 0 → (x &&& 2147483647#32).srem 2147483647#32 = (x &&& 2147483647#32) % 2147483647#32

theorem not_not_true_thm (e e_1 : IntW 1) :
  select (LLVM.xor e_1 (const? 1 1)) (LLVM.xor e (const? 1 1)) (const? 1 1) ⊑
    select e_1 (const? 1 1) (LLVM.xor e (const? 1 1))

theorem udiv_shl_pair3_proof : udiv_shl_pair3_before ⊑ udiv_shl_pair3_after

@[simp] theorem Valuation.ofHVector_cons :
    ofHVector (Ty:=Ty) (x ::ₕ xs) = x ::ᵥ (ofHVector xs)

theorem srem_common_divisor_defined_cond_thm (e e_1 e_2 : IntW 5) (e_3 : IntW 1) :
  select e_3 (LLVM.srem e_2 e_1) (LLVM.srem e e_1) ⊑ LLVM.srem (select e_3 e_2 e) e_1

theorem PR42691_3_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (0#32 ≤ₛ x) ||

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

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

theorem exact_lshr_ne_opposite_msb_proof : exact_lshr_ne_opposite_msb_before ⊑ exact_lshr_ne_opposite_msb_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_0_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 12#32 == 0#32) = 1#1 → 1#1 = ofBool (x &&& 12#32 == 0#32) ||

theorem shift_no_xor_multiuse_cmp_with_xor_proof : shift_no_xor_multiuse_cmp_with_xor_before ⊑ shift_no_xor_multiuse_cmp_with_xor_after

theorem lshr_and_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(x ≥ ↑8 ∨ x + 1#8 ≥ ↑8) → ¬x ≥ ↑8 → 48#8 >>> x &&& 64#8 >>> (x + 1#8) = 32#8 >>> x

theorem uge_or_max_commute_proof : uge_or_max_commute_before ⊑ uge_or_max_commute_after

theorem zext_nneg_sext_ugt_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ x_1.msb = true) → ofBool (signExtend 32 x <ᵤ zeroExtend 32 x_1) = ofBool (x <ᵤ x_1)

theorem and_sequence_10_eq (w : Nat) :
    and_sequence_10_lhs w  ⊑ and_sequence_10_rhs w

theorem main6c_logical_thm.extracted_1._4 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 != 3#32) = 1#1 →
    ¬ofBool (x &&& 48#32 != 16#32) = 1#1 → 1#32 = zeroExtend 32 (ofBool (x &&& 55#32 == 19#32))

theorem trunc_sandwich_max_sum_shift2_proof : trunc_sandwich_max_sum_shift2_before ⊑ trunc_sandwich_max_sum_shift2_after

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

theorem e_198 :
    5 * x - 3 *  ~~~(x &&&  ~~~x) + 3 *  ~~~(x ||| y) + 1 *  ~~~(x |||  ~~~y) - 2 * (x &&&  ~~~y) - 4 * (x &&& y) =  - 2 * y

theorem t0_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(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) →
    ¬30#32 ≥ ↑32 → x_1 >>> (32#32 - x) >>> (x + BitVec.ofInt 32 (-2)) = x_1 >>> 30#32

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

theorem demorganize_constant2_thm (e : IntW 32) :
  LLVM.xor (LLVM.or e (const? 32 15)) (const? 32 (-1)) ⊑
    LLVM.xor (LLVM.and e (const? 32 (-16))) (const? 32 (-16))

theorem t1_const_shl_lshr_ne_proof : t1_const_shl_lshr_ne_before ⊑ t1_const_shl_lshr_ne_after

theorem mul_constant_partial_nuw_eq_proof : mul_constant_partial_nuw_eq_before ⊑ mul_constant_partial_nuw_eq_after

theorem icmp_eq_x_invertable_y2_proof : icmp_eq_x_invertable_y2_before ⊑ icmp_eq_x_invertable_y2_after

theorem narrow_zext_and_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 16),
  truncate 16 (zeroExtend 32 x_1 &&& x) = x_1 &&& truncate 16 x

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

theorem testi16i8_ne_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 8#16 ≥ ↑16) →
    ofBool ((truncate 8 x).sshiftRight' 7#8 != truncate 8 (x >>> 8#16)) =
      ofBool (x + BitVec.ofInt 16 (-128) <ᵤ BitVec.ofInt 16 (-256))

theorem t1_proof : t1_before ⊑ t1_after

theorem test_add_nsw__nsw_is_safe_proof : test_add_nsw__nsw_is_safe_before ⊑ test_add_nsw__nsw_is_safe_after

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

theorem test46_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬8#32 ≥ ↑32 →
    ¬(8#32 ≥ ↑32 ∨ True ∧ (truncate 32 x <<< 8#32 &&& 10752#32).msb = true) →
      zeroExtend 64 ((truncate 32 x &&& 42#32) <<< 8#32) = zeroExtend 64 (truncate 32 x <<< 8#32 &&& 10752#32)

theorem t2_proof : t2_before ⊑ t2_after

theorem test16_thm.extracted_1._1 : ∀ (x : BitVec 51),
  ¬(1123#51 == 0 || 51 != 1 && x == intMin 51 && 1123#51 == -1) = true →
    (BitVec.ofInt 51 (-1123) == 0 || 51 != 1 && x == intMin 51 && BitVec.ofInt 51 (-1123) == -1) = true → False

theorem PR24763_proof : PR24763_before ⊑ PR24763_after

theorem t0_thm.extracted_1._4 : ∀ (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 and_consts_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (4#32 &&& x == 0#32) = 1#1 → ofBool (8#32 &&& x == 0#32) = ofBool (x &&& 12#32 != 12#32)

theorem positive_different_trunc_both_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.sgt (trunc 15 e) (const? 15 (-1)))
      (icmp IntPred.ult (add (trunc 16 e) (const? 16 128)) (const? 16 256)) ⊑
    LLVM.and (icmp IntPred.eq (LLVM.and e (const? 32 16384)) (const? 32 0))
      (icmp IntPred.ult (add (trunc 16 e) (const? 16 128)) (const? 16 256))

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_0_logical_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 12)) (const? 32 0)) (const? 1 1)
      (icmp IntPred.ne (LLVM.and e (const? 32 3)) (const? 32 1)) ⊑
    LLVM.or (icmp IntPred.eq (LLVM.and e (const? 32 12)) (const? 32 0))
      (icmp IntPred.ne (LLVM.and e (const? 32 3)) (const? 32 1))

theorem test3_thm.extracted_1._1 : ∀ (x : BitVec 1), x &&& 0#1 = 0#1

theorem eq_10_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(8#32 ≥ ↑32 ∨ 8#32 ≥ ↑32) →
    ofBool (truncate 8 x_1 == truncate 8 x) &&& ofBool (truncate 8 (x_1 >>> 8#32) == truncate 8 (x >>> 8#32)) =
      ofBool (truncate 16 x_1 == truncate 16 x)

theorem t_2_63_or_proof : t_2_63_or_before ⊑ t_2_63_or_after

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

theorem getElem?_append :
    (Γ ++ Δ)[i]? = if i < Γ.length then Γ[i]? else Δ[i - Γ.length]?

theorem t7_ugt_sgt_neg1_thm.extracted_1._8 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (143#32 <ᵤ x_1 + 16#32) = 1#1 → ofBool (127#32 <ₛ x_1) = 1#1 → False

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 n0_proof : n0_before ⊑ n0_after

theorem sub_ashr_and_i32_nuw_nsw_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1.ssubOverflow x = true ∨ True ∧ x_1.usubOverflow x = true ∨ 31#32 ≥ ↑32) →
    ofBool (x_1 <ₛ x) = 1#1 → (x_1 - x).sshiftRight' 31#32 &&& x = x

theorem masked_bit_wrong_pred_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x_1 ≥ ↑32 → True ∧ 1#32 <<< x_1 >>> x_1 ≠ 1#32 ∨ x_1 ≥ ↑32 → False

theorem ne_umin2_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (select (icmp IntPred.ult e_1 e) e_1 e) e ⊑ icmp IntPred.ugt e e_1

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

theorem lshr_sext_i1_to_i16_thm (e : IntW 1) : lshr (sext 16 e) (const? 16 4) ⊑ select e (const? 16 4095) (const? 16 0)

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

theorem positive_samevar_proof : positive_samevar_before ⊑ positive_samevar_after

theorem test57_thm (e : IntW 64) :
  zext 64 (lshr (trunc 32 e) (const? 32 8)) ⊑ zext 64 (lshr (trunc 32 e) (const? 32 8)) { «nneg» := true }

theorem t_1_10_thm (e : IntW 8) :
  LLVM.and (select (icmp IntPred.ugt e (const? 8 1)) e (const? 8 1)) (const? 8 10) ⊑
    LLVM.and e (const? 8 10)

theorem eq_nsw_rem_zero_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.smulOverflow (BitVec.ofInt 8 (-5)) = true) →
    ofBool (x * BitVec.ofInt 8 (-5) == 20#8) = ofBool (x == BitVec.ofInt 8 (-4))

theorem reassoc_mul_nuw_proof : reassoc_mul_nuw_before ⊑ reassoc_mul_nuw_after

theorem positive_with_mask_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.eq (LLVM.and e (const? 32 1107296256)) (const? 32 0))
      (icmp IntPred.ult (add e (const? 32 128)) (const? 32 256)) ⊑
    icmp IntPred.ult e (const? 32 128)

@[simp] lemma eval_foldl_or :
  ∀ (s : List α) (f : α → Circuit β) (c : Circuit β) (g : β → Bool),
    (eval (s.foldl (λ c x => c ||| (f x)) c) g : Prop) ↔
      eval c g ∨ (∃ a ∈ s, eval (f a) g)

theorem test11_proof : test11_before ⊑ test11_after

theorem xor_i8_to_i64_shl_save_and_ne_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 8),
  ofBool (x_1 &&& 1#8 != 0#8) = 1#1 →
    ¬63#64 ≥ ↑64 → x ^^^ BitVec.ofInt 64 (-9223372036854775808) = x ^^^ zeroExtend 64 x_1 <<< 63#64

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

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

theorem p_constmask_commutative_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  True ∧ (x_1 &&& BitVec.ofInt 32 (-65281) &&& (x &&& 65280#32) != 0) = true → False

theorem sel_false_val_is_a_masked_lshr_of_true_val1_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ofBool (x_1 &&& 60#32 == 0#32) = 1#1 →
    ¬(2#32 ≥ ↑32 ∨ True ∧ (x_1 >>> 2#32 &&& 15#32).msb = true ∨ zeroExtend 64 (x_1 >>> 2#32 &&& 15#32) ≥ ↑64) →
      x = x.sshiftRight' (zeroExtend 64 (x_1 >>> 2#32 &&& 15#32))

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

theorem trunc_sel_smaller_zext_thm.extracted_1._3 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → zeroExtend 32 42#16 = 42#32

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

theorem e_671 :
     - 1 *  ~~~(x &&&  ~~~x) + 2 * y - 11 * (x ||| y) + 1 *  ~~~(x &&& y) - 6 *  ~~~(x &&&  ~~~y) - 2 *  ~~~x + 1 * (x |||  ~~~y) - 5 *  ~~~(x ^^^ y) + 12 *  ~~~(x ||| y) + 17 *  ~~~(x |||  ~~~y) =  - 10 * (x &&&  ~~~y) - 20 * (x &&& y)

theorem scalar_i64_signbit_lshr_and_eq_proof : scalar_i64_signbit_lshr_and_eq_before ⊑ scalar_i64_signbit_lshr_and_eq_after

theorem testi64i32_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 + 2147483648#64 <ᵤ 4294967296#64)

theorem test44_proof : test44_before ⊑ test44_after

theorem src_is_notmask_x_xor_neg_x_proof : src_is_notmask_x_xor_neg_x_before ⊑ src_is_notmask_x_xor_neg_x_after

theorem 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 zext_sext_add_icmp_eq_minus1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ofBool (zeroExtend 8 x_1 + signExtend 8 x == -1#8) = x &&& (x_1 ^^^ 1#1)

theorem ashrslt_03_13_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬3#4 ≥ ↑4 → ofBool (x.sshiftRight' 3#4 <ₛ BitVec.ofInt 4 (-3)) = 0#1

theorem t9_lshr_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 32),
  ¬(zeroExtend 32 (32#16 - x) ≥ ↑32 ∨ x + BitVec.ofInt 16 (-2) ≥ ↑16) →
    True ∧ (32#16 - x).msb = true ∨ zeroExtend 32 (32#16 - x) ≥ ↑32 ∨ x + BitVec.ofInt 16 (-2) ≥ ↑16 → False

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 sgt_3_impliesF_eq_2_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (3#8 <ₛ x) = 1#1 → ofBool (x <ₛ 4#8) = 1#1 → False

theorem sext_sext_add_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(7#32 ≥ ↑32 ∨ 9#32 ≥ ↑32) →
    7#32 ≥ ↑32 ∨ 9#32 ≥ ↑32 ∨ True ∧ (x.sshiftRight' 7#32).saddOverflow (x.sshiftRight' 9#32) = true → False

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

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

theorem substitute_constant_or_ne_uge_commute_proof : substitute_constant_or_ne_uge_commute_before ⊑ substitute_constant_or_ne_uge_commute_after

theorem ugt_and_not_min_commute_proof : ugt_and_not_min_commute_before ⊑ ugt_and_not_min_commute_after

theorem shl_nsw_add_negative_invalid_constant3_proof : shl_nsw_add_negative_invalid_constant3_before ⊑ shl_nsw_add_negative_invalid_constant3_after

theorem p_proof : p_before ⊑ p_after

theorem ashrslt_02_13_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬2#4 ≥ ↑4 → ofBool (x.sshiftRight' 2#4 <ₛ BitVec.ofInt 4 (-3)) = 0#1

theorem ripple_no_nsw2_proof : ripple_no_nsw2_before ⊑ ripple_no_nsw2_after

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

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

theorem ashrslt_02_10_proof : ashrslt_02_10_before ⊑ ashrslt_02_10_after

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

@[simp]
lemma bitVecToFinFun_inj [FinEnum ar] : Function.Injective (bitVecToFinFun (ar := ar))

theorem bitwise_and_logical_and_masked_icmp_asymmetric_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 255#32 != 0#32) = 1#1 → ofBool (x &&& 11#32 == 11#32) = 1#1 → False

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

theorem R.monomial_zero_c_eq_zero : R.monomial (q := q) (n := n) 0 c = 0

theorem t0_proof : t0_before ⊑ t0_after

theorem fold_inverted_icmp_preds_reverse_proof : fold_inverted_icmp_preds_reverse_before ⊑ fold_inverted_icmp_preds_reverse_after

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

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1_logical_after

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

theorem and_xor_commute4_proof : and_xor_commute4_before ⊑ and_xor_commute4_after

theorem p0_scalar_urem_by_const_proof : p0_scalar_urem_by_const_before ⊑ p0_scalar_urem_by_const_after

theorem t2_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 64),
  ¬(x ≥ ↑32 ∨ zeroExtend 64 (1#32 <<< x) = 0) →
    ¬(True ∧ x.msb = true ∨ zeroExtend 64 x ≥ ↑64) → x_1 / zeroExtend 64 (1#32 <<< x) = x_1 >>> zeroExtend 64 x

theorem e_1127 :
    5 *  ~~~(z &&& t) - 3 *  ~~~z + 2 *  ~~~(z &&&  ~~~z) + 4 *  ~~~t - 8 *  ~~~(z ||| t) - 9 *  ~~~(z |||  ~~~t) - 27 * (z &&&  ~~~t) - 18 * (z &&& t) =  - 5 * (z ||| t) - 11 * z

theorem zext_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → 1#41 = zeroExtend 41 x

theorem a_true_implies_b_true2_thm.extracted_1._2 : ∀ (x : BitVec 1) (x_1 : BitVec 8),
  ofBool (10#8 <ᵤ x_1) = 1#1 → ¬ofBool (20#8 <ᵤ x_1) = 1#1 → ofBool (20#8 <ᵤ x_1) &&& x = 0#1

theorem select_lshr_icmp_bad_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == 1#32) = 1#1 → ¬x_1 ≥ ↑32 → 1#32 ≥ ↑32 → False

theorem test1_proof : test1_before ⊑ test1_after

theorem xor_1_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  ¬x_3 = 1#1 → x_1 ^^^ 123#8 ^^^ x ^^^ -1#8 = x_1 ^^^ BitVec.ofInt 8 (-124) ^^^ x

theorem icmp_sgt10_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (x <<< 7#8).sshiftRight' 7#8 ≠ x ∨ 7#8 ≥ ↑8) →
    ofBool (BitVec.ofInt 8 (-127) <ₛ x <<< 7#8) = ofBool (-1#8 <ₛ x)

theorem test12_proof : test12_before ⊑ test12_after

theorem positive_biggerLshr_proof : positive_biggerLshr_before ⊑ positive_biggerLshr_after

theorem not_and_and_or_not_or_or_commute2_and_proof : not_and_and_or_not_or_or_commute2_and_before ⊑ not_and_and_or_not_or_or_commute2_and_after

theorem n0_proof : n0_before ⊑ n0_after

theorem test_invalid_simplify_eq2_proof : test_invalid_simplify_eq2_before ⊑ test_invalid_simplify_eq2_after

theorem ashr_pow2_ult_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬x ≥ ↑8 → True ∧ BitVec.ofInt 8 (-128) >>> x <<< x ≠ BitVec.ofInt 8 (-128) ∨ x ≥ ↑8 → False

theorem shl1_trunc_eq0_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → ofBool (truncate 16 (1#32 <<< x) == 0#16) = ofBool (15#32 <ᵤ x)

theorem uadd_sat_via_add_swapped_cmp_nonstrict_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x + x_1 ≤ᵤ x_1) = 1#1 → ofBool (x_1 <ᵤ x + x_1) = 1#1 → -1#32 = x + x_1

theorem test65_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬ofBool (x &&& 16#64 != 0#64) = 1#1 → ¬ofBool (x &&& 16#64 == 0#64) = 1#1 → 42#32 = 40#32

theorem test1_proof : test1_before ⊑ test1_after

theorem test1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), (x_1 &&& 7#32 ||| x &&& 8#32) &&& 7#32 = x_1 &&& 7#32

theorem badimm3_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 8#16 ≥ ↑16) →
    ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 8#16)) = 1#1 →
      ¬ofBool (x + 128#16 <ᵤ 256#16) = 1#1 →
        14#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 14#16)) ≠ x.sshiftRight' 14#16 → False

theorem t14_and_with_const0_proof : t14_and_with_const0_before ⊑ t14_and_with_const0_after

theorem e_1695 :
    4 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) + 1 * (b |||  ~~~c) - 3 * ((a &&& c) ^^^ (b ||| c)) + 7 * (b ^^^ (a &&& c)) + 7 * (b ^^^ (a &&& (b ^^^ c))) - 1 *  ~~~( ~~~a &&& (b ^^^ c)) + 1 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 5 * (c ^^^ (a ||| (b &&& c))) + 2 * (a &&&  ~~~b) + 5 * (b ^^^ ( ~~~a &&& (b ^^^ c))) + 4 * (c ^^^ ( ~~~a ||| (b &&& c))) - 5 * a + 7 * ((a &&& b) ^^^ (b ||| c)) - 5 * (c ||| (a ^^^ b)) - 3 * (a ||| c) + 1 * (a ^^^ ( ~~~b &&& c)) + 2 * ( ~~~a ||| ( ~~~b &&& c)) + 4 * (b ^^^ (a &&& ( ~~~b ||| c))) - 2 *  ~~~a - 2 * (a ||| (b &&& c)) - 2 *  ~~~(a ||| (b ||| c)) - 27 *  ~~~(a ||| ( ~~~b ||| c)) + 7 *  ~~~( ~~~a ||| (b ||| c)) - 4 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 9 * ( ~~~a &&& ( ~~~b &&& c)) - 17 * ( ~~~a &&& (b &&& c)) - 22 * (a &&& ( ~~~b &&& c)) + 9 * (a &&& (b &&& c)) = 7 * (b ^^^  ~~~(a &&& ( ~~~b ||| c)))

theorem test_mul__nsw_is_safe_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x ||| BitVec.ofInt 32 (-83886080) == BitVec.ofInt 32 (-83886079)) = 1#1 →
    True ∧ (x ||| BitVec.ofInt 32 (-83886080)).smulOverflow 9#32 = true → False

theorem p_constmask_thm (e e_1 : IntW 32) :
  add (LLVM.and e_1 (const? 32 65280)) (LLVM.and e (const? 32 (-65281))) ⊑
    LLVM.or (LLVM.and e_1 (const? 32 65280)) (LLVM.and e (const? 32 (-65281))) { «disjoint» := true }

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

theorem land_band_left1_thm (e e_1 : IntW 1) : LLVM.and (select e_1 e (const? 1 0)) e_1 ⊑ select e_1 e (const? 1 0)

theorem not_mul_of_pow2_thm (e : IntW 8) (e_1 : IntW 32) :
  icmp IntPred.ugt (mul (LLVM.and e_1 (const? 32 6)) (zext 32 e)) (const? 32 1530) ⊑
    icmp IntPred.ugt (mul (LLVM.and e_1 (const? 32 6)) (zext 32 e) { «nsw» := true, «nuw» := true })
      (const? 32 1530)

theorem sub_const_const_sub_proof : sub_const_const_sub_before ⊑ sub_const_const_sub_after

theorem test1_proof : test1_before ⊑ test1_after

theorem e_2239 :
     - 1 * ( ~~~d ||| (e ||| f)) + 1 * (d &&&  ~~~f) - 1 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 1 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) - 11 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) + 1 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 1 *  ~~~(e &&&  ~~~f) + 3 * (e ^^^  ~~~(d |||  ~~~f)) - 3 * (d ||| (e &&& f)) + 7 * ((e &&& f) ||| (d &&& (e ||| f))) - 5 *  ~~~(e ||| f) - 2 * e - 3 *  ~~~( ~~~d &&& (e ||| f)) + 4 *  ~~~(d |||  ~~~e) - 2 * (f &&&  ~~~(d &&& e)) - 5 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) + 7 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 1 * ( ~~~f |||  ~~~(d ^^^ e)) + 5 * (f ||| (d &&& e)) - 2 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 5 * (d |||  ~~~e) + 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 7 *  ~~~(d &&& ( ~~~e ||| f)) - 1 * (d |||  ~~~f) + 1 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) - 6 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 11 * (f ^^^  ~~~(d ||| e)) + 7 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) - 7 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) + 11 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) - 2 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) + 3 *  ~~~f + 7 * (e ^^^ ( ~~~d &&& (e ||| f))) + 2 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 11 * ( ~~~d &&& (e ^^^ f)) + 7 * (f |||  ~~~(d ||| e)) + 2 * ((d &&& e) ^^^ (e ||| f)) + 3 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 1 * (f ^^^ (d &&&  ~~~e)) - 7 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 2 * (d ||| f) - 5 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) - 6 * ( ~~~e |||  ~~~(d ^^^ f)) - 3 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 1 * (f |||  ~~~(d ^^^ e)) + 5 * ( ~~~d ||| ( ~~~e &&& f)) + 11 * (e |||  ~~~f) + 5 * (e &&& (d |||  ~~~f)) - 18 *  ~~~(d ||| (e ||| f)) - 51 *  ~~~(d ||| ( ~~~e ||| f)) - 2 *  ~~~( ~~~d ||| (e ||| f)) - 26 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 44 * ( ~~~d &&& ( ~~~e &&& f)) - 45 * ( ~~~d &&& (e &&& f)) - 8 * (d &&& ( ~~~e &&& f)) - 51 * (d &&& (e &&& f)) =  - 1 *  ~~~(d &&& ( ~~~e &&& f)) + 1 * ((e &&& f) ||| ( ~~~d &&& (e ||| f)))

theorem factorize3_proof : factorize3_before ⊑ factorize3_after

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

@[simp]
lemma union_accepts (M N : NFA' n) :
    (M.union N).accepts = M.accepts ∪ N.accepts

theorem e_2293 :
     - 1 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 3 * (d &&&  ~~~e) - 5 *  ~~~(e |||  ~~~f) + 2 * (f ^^^ (d ||| e)) + 2 * ((d |||  ~~~e) &&& (e ^^^ f)) - 1 * (f ^^^ (d ||| ( ~~~e &&& f))) - 6 * (f ^^^ ( ~~~d ||| (e &&& f))) - 3 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 2 * (f ^^^ (d &&&  ~~~e)) - 3 * ((d ^^^ e) &&& (d ^^^ f)) - 1 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) + 11 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 * ((d &&& e) ^^^ (e |||  ~~~f)) - 7 * (f ^^^ ( ~~~d ||| (e ||| f))) - 2 * (e ^^^  ~~~(d ||| f)) + 4 * ( ~~~d &&& (e ^^^ f)) - 1 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 2 *  ~~~(d ^^^ ( ~~~e ||| f)) + 7 * (e ||| (d ^^^ f)) - 1 *  ~~~(e &&& f) - 7 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 3 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) - 6 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 5 * (e |||  ~~~f) + 5 *  ~~~(d ||| f) + 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) - 2 * ( ~~~d ||| (e &&& f)) + 2 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) + 5 * (e ^^^  ~~~(d &&& (e ||| f))) + 4 * (e ||| (d &&&  ~~~f)) + 2 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 1 * (f ^^^  ~~~(d ||| e)) - 11 *  ~~~(d &&&  ~~~f) - 5 *  ~~~(d |||  ~~~e) - 2 * ( ~~~d &&& (e ||| f)) - 6 * (e ^^^ (d |||  ~~~f)) - 3 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) - 5 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) - 2 *  ~~~d - 5 * ( ~~~e ||| (d ^^^ f)) + 11 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 1 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 3 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 1 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) + 2 * (e ^^^  ~~~(d ||| (e &&& f))) + 11 *  ~~~(d ^^^ ( ~~~e &&& f)) + 4 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) + 3 * (e &&& f) + 11 * (d ^^^ (e ||| f)) - 1 *  ~~~(d &&&  ~~~e) + 1 * (f ^^^ ( ~~~d &&& (e ||| f))) + 1 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) - 5 *  ~~~(d ||| (e ||| f)) - 23 *  ~~~(d ||| ( ~~~e ||| f)) - 17 *  ~~~( ~~~d ||| (e ||| f)) - 5 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 13 * ( ~~~d &&& ( ~~~e &&& f)) - 16 * ( ~~~d &&& (e &&& f)) + 3 * (d &&& ( ~~~e &&& f)) - 27 * (d &&& (e &&& f)) =  - 4 * (e ^^^ (d ||| ( ~~~e &&& f))) - 3 * (f &&& (d |||  ~~~e))

theorem sext_zext_nneg_ult_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ x.msb = true) → ofBool (signExtend 32 x_1 <ᵤ zeroExtend 32 x) = ofBool (x_1 <ᵤ x)

theorem icmp_ult_x_y_2_proof : icmp_ult_x_y_2_before ⊑ icmp_ult_x_y_2_after

theorem logic_or_logic_and_6_thm.extracted_1._6 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬x = 1#1 → x_1 = 1#1 → x_2 = x

theorem logic_or_logic_and_4_proof : logic_or_logic_and_4_before ⊑ logic_or_logic_and_4_after

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

theorem lshr_lshr_proof : lshr_lshr_before ⊑ lshr_lshr_after

theorem alive_AndOrXor_2647 : alive_AndOrXor_2647_src ⊑ alive_AndOrXor_2647_tgt

theorem test_slt_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 32),
  ¬(True ∧ signExtend 32 (truncate 8 x_1) ≠ x_1 ∨ True ∧ signExtend 16 (truncate 8 x) ≠ x) →
    ofBool (truncate 8 x_1 <ₛ truncate 8 x) = ofBool (x_1 <ₛ signExtend 32 x)

theorem fold_ne_rhs_fail_shift_not_1s_proof : fold_ne_rhs_fail_shift_not_1s_before ⊑ fold_ne_rhs_fail_shift_not_1s_after

theorem trunc_ashr_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬8#36 ≥ ↑36 → 8#32 ≥ ↑32 → False

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

theorem shl_or_lshr_comm_thm (e e_1 e_2 : IntW 32) :
  lshr (LLVM.or e_2 (shl e_1 e { «nsw» := false, «nuw» := true })) e ⊑ LLVM.or (lshr e_2 e) e_1

theorem test19_commutative0_proof : test19_commutative0_before ⊑ test19_commutative0_after

theorem sub_2_thm (e e_1 : IntW 8) (e_2 : IntW 1) (e_3 : IntW 8) :
  LLVM.xor (sub e_3 (select e_2 (LLVM.xor e_1 (const? 8 (-1))) (LLVM.xor e (const? 8 123)))) (const? 8 (-1)) ⊑
    sub (const? 8 (-2)) (add (select e_2 e_1 (LLVM.xor e (const? 8 (-124)))) e_3)

theorem ashr_not_thm (e : IntW 8) :
  ashr (LLVM.xor e (const? 8 (-1))) (const? 8 5) ⊑ LLVM.xor (ashr e (const? 8 5)) (const? 8 (-1))

theorem icmp_ugt_32_proof : icmp_ugt_32_before ⊑ icmp_ugt_32_after

theorem alive_AndOrXor_1253_A__AB___A__B : alive_AndOrXor_1253_A__AB___A__B_src ⊑ alive_AndOrXor_1253_A__AB___A__B_tgt

theorem ult_1_impliesF_eq_1_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (x <ᵤ 1#8) = 1#1 → ofBool (x != 0#8) = 1#1 → False

theorem e_2302 :
    2 * (e &&& (d |||  ~~~f)) + 4 *  ~~~( ~~~d ||| (e &&& f)) + 1 * (e ^^^  ~~~(d ||| (e ^^^ f))) - 1 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) - 3 * (d &&& ( ~~~e ||| f)) - 2 * (e &&& (d ^^^ f)) - 3 * (f ^^^  ~~~(d |||  ~~~e)) + 7 * ( ~~~(d &&& e) &&& (e ^^^ f)) - 7 *  ~~~( ~~~d &&& (e &&& f)) - 5 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) - 5 *  ~~~(d |||  ~~~e) + 11 *  ~~~(d ^^^ (e ^^^ f)) - 1 *  ~~~( ~~~d &&& (e ||| f)) - 2 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 2 * (f ^^^ (d &&& ( ~~~e ||| f))) - 11 * (e ^^^ (d &&& ( ~~~e ||| f))) - 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) + 2 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) - 5 * (e ^^^ f) - 2 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 1 *  ~~~(d ||| (e &&& f)) + 1 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 7 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 1 * (f &&&  ~~~(d &&& e)) - 11 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 2 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) + 1 * (e &&&  ~~~(d &&& f)) - 6 *  ~~~(d &&& ( ~~~e ||| f)) + 7 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 6 * (e &&& f) - 3 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 5 * (d ||| e) + 2 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 3 * (f &&& (d ^^^ e)) - 11 *  ~~~(d ||| ( ~~~e &&& f)) - 1 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * (d &&& (e ^^^ f)) - 6 * (d ^^^ (e ||| f)) + 1 * (d ||| ( ~~~e ||| f)) + 1 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) + 3 * (d ||| (e ^^^ f)) - 11 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 2 * (e &&&  ~~~f) - 2 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) - 3 * (f |||  ~~~(d ^^^ e)) + 11 * (e ^^^  ~~~(d &&& (e &&& f))) - 1 * (d ^^^ e) - 5 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 7 * (f &&& (d ||| e)) + 1 *  ~~~(d &&& (e ||| f)) - 1 *  ~~~(d ||| f) + 2 * (f &&&  ~~~(d ^^^ e)) + 2 *  ~~~(d |||  ~~~f) + 2 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 17 *  ~~~(d ||| (e ||| f)) + 46 *  ~~~(d ||| ( ~~~e ||| f)) + 20 *  ~~~( ~~~d ||| (e ||| f)) + 3 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 4 * ( ~~~d &&& ( ~~~e &&& f)) + 46 * ( ~~~d &&& (e &&& f)) + 16 * (d &&& ( ~~~e &&& f)) + 37 * (d &&& (e &&& f)) =  - 5 * (e ||| (d ^^^ f))

theorem e_597 :
    7 *  ~~~x + 3 *  ~~~y + 5 *  ~~~(x ^^^ y) - 1 * (x ^^^ y) - 5 *  ~~~(x &&&  ~~~y) + 1 *  ~~~(x &&& y) + 2 * (x |||  ~~~y) - 16 *  ~~~(x ||| y) - 5 *  ~~~(x |||  ~~~y) - 8 * (x &&&  ~~~y) = 5 * (x &&& y) - 3 *  ~~~(x &&&  ~~~x)

theorem and_xor_or8_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 64),
  ¬(x_2 = 0 ∨ x_1 = 0 ∨ x_2 = 0 ∨ x = 0) → x_2 = 0 ∨ x_1 = 0 → False

theorem zext_sext_eq_known_nonneg_thm (e e_1 : IntW 8) :
  icmp IntPred.eq (zext 32 (lshr e_1 (const? 8 1))) (sext 32 e) ⊑
    icmp IntPred.eq (lshr e_1 (const? 8 1)) e

theorem zero_sign_bit2_proof : zero_sign_bit2_before ⊑ zero_sign_bit2_after

@[simp]
theorem toBitVec_concat_succ (a : BitStream) :
    (a.concat b).toBitVec (w + 1) = (a.toBitVec w).concat b

@[simp] lemma mem_vars_iff_mem_sumVarsLeft [DecidableEq α] [DecidableEq β] :
    ∀ {c : Circuit (α ⊕ β)} {x : α},
    (x ∈ c.sumVarsLeft) ↔ Sum.inl x ∈ c.vars

theorem AvoidCollision_and_setWidth_allOnes (w' w : Nat) (b : BitVec (w' + w)) :
    b &&& (BitVec.allOnes w).setWidth (w' + w) = 0#w' ++ b.setWidth w

@[simp]
theorem Expr.args_mk {Γ : Ctxt d.Ty} {ty eff op}
    (ty_eq : ty = DialectSignature.returnTypes op)
    (eff_le : DialectSignature.effectKind op ≤ eff)
    (args : HVector (Var Γ) (DialectSignature.sig op)) (regArgs) :
    (Expr.mk op ty_eq eff_le args regArgs).args = args

theorem sub_to_neg'
  (hppot : ppot &&& (ppot - 1) = 0)
  (hqpot : qpot &&& (qpot - 1) = 0)
  (hrpot : rpot &&& (rpot - 1) = 0)
  (hspot : spot &&& (spot - 1) = 0)
  (htpot : tpot &&& (tpot - 1) = 0)
  (hupot : upot &&& (upot - 1) = 0)
  (hpmask : pmask = ppot - 1)
  (hqmask : qmask = qpot - 1)
  (hrmask : rmask = rpot - 1)
  (hsmask : smask = spot - 1)
  (htmask : tmask = tpot - 1)
  (humask : umask = upot - 1) :
  (bw' rmask 
    (subMax' (bw' pmask a') pmask (bw' qmask b') qmask)) =
  (bw' rmask 
    (addMax' 
      (bw' pmask a') pmask 
      (negMax' (bw' qmask b')) qmask))

theorem test5_thm.extracted_1._1 : ∀ (x : BitVec 111),
  ¬(110#111 ≥ ↑111 ∨ 110#111 ≥ ↑111) → (x ^^^ 1#111 <<< 110#111) + 1#111 <<< 110#111 = x

theorem lshrult_01_05_exact_proof : lshrult_01_05_exact_before ⊑ lshrult_01_05_exact_after

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

theorem a_false_implies_b_false2_comm_proof : a_false_implies_b_false2_comm_before ⊑ a_false_implies_b_false2_comm_after

theorem test7_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(4#32 == 0 || 32 != 1 && x * 8#32 == intMin 32 && 4#32 == -1) = true → (x * 8#32).srem 4#32 = 0#32

theorem zext_sext_ule_known_nonneg_op0_wide_proof : zext_sext_ule_known_nonneg_op0_wide_before ⊑ zext_sext_ule_known_nonneg_op0_wide_after

theorem foo1_and_signbit_lshr_without_shifting_signbit_both_sides_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (icmp IntPred.sgt (shl e_2 e_1) (const? 32 (-1))) (icmp IntPred.sgt (shl e_2 e) (const? 32 (-1))) ⊑
    icmp IntPred.sgt (LLVM.and (shl e_2 e_1) (shl e_2 e)) (const? 32 (-1))

theorem lshrult_02_14_thm (e : IntW 4) : icmp IntPred.ult (lshr e (const? 4 2)) (const? 4 (-2)) ⊑ const? 1 1

theorem positive_biggershl_shlnuwnsw_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(3#8 ≥ ↑8 ∨
        True ∧ (x.sshiftRight' 3#8 <<< 6#8).sshiftRight' 6#8 ≠ x.sshiftRight' 3#8 ∨
          True ∧ x.sshiftRight' 3#8 <<< 6#8 >>> 6#8 ≠ x.sshiftRight' 3#8 ∨ 6#8 ≥ ↑8) →
    True ∧ (x <<< 3#8).sshiftRight' 3#8 ≠ x ∨ True ∧ x <<< 3#8 >>> 3#8 ≠ x ∨ 3#8 ≥ ↑8 → False

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

theorem lshr_exact_thm (e : IntW 8) :
  lshr (add (shl e (const? 8 2)) (const? 8 4)) (const? 8 2) ⊑ LLVM.and (add e (const? 8 1)) (const? 8 63)

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_3b_logical_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and e (const? 32 3)) (const? 32 0)) (const? 1 1)
      (icmp IntPred.eq (LLVM.and e (const? 32 15)) (const? 32 0)) ⊑
    LLVM.or (icmp IntPred.ne (LLVM.and e (const? 32 3)) (const? 32 0))
      (icmp IntPred.eq (LLVM.and e (const? 32 15)) (const? 32 0))

theorem add1 (w : Nat) (a : BitVec w) :  (a * 3 = a + a + a)

theorem test_add__nsw_is_safe_proof : test_add__nsw_is_safe_before ⊑ test_add__nsw_is_safe_after

theorem icmp_equality_test_commute_icmp1_proof : icmp_equality_test_commute_icmp1_before ⊑ icmp_equality_test_commute_icmp1_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 3#32 != 0#32) &&& ofBool (x &&& 7#32 == 0#32) = 0#1

theorem foo1_or_commuted_proof : foo1_or_commuted_before ⊑ foo1_or_commuted_after

theorem masked_or_allzeroes_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 == 0#32) ||

theorem ult_2_proof : ult_2_before ⊑ ult_2_after

theorem sle_or_min_thm (e e_1 : IntW 8) :
  LLVM.or (icmp IntPred.sle e_1 e) (icmp IntPred.eq e_1 (const? 8 (-128))) ⊑
    icmp IntPred.sle e_1 e

theorem not_or_xor_proof : not_or_xor_before ⊑ not_or_xor_after

theorem udiv_shl_shl_nuw_nsw2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(True ∧ (x_2 <<< x_1).sshiftRight' x_1 ≠ x_2 ∨
        True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨
          x_1 ≥ ↑8 ∨ True ∧ (x <<< x_1).sshiftRight' x_1 ≠ x ∨ x_1 ≥ ↑8 ∨ x <<< x_1 = 0) →
    x = 0 → False

theorem test10_proof : test10_before ⊑ test10_after

theorem foo3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), ¬x = 0 → x_1 / x = x_1

theorem ne_umin4_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (add e_1 (const? 32 3))
      (select (icmp IntPred.ult e (add e_1 (const? 32 3))) e (add e_1 (const? 32 3))) ⊑
    icmp IntPred.ugt (add e_1 (const? 32 3)) e

theorem max_sub_ugt_c0_proof : max_sub_ugt_c0_before ⊑ max_sub_ugt_c0_after

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

theorem e_1464 :
    2 * (z ||| t) + 2 * (z ^^^ t) - 11 * t + 1 *  ~~~(z &&& t) + 3 *  ~~~t + 2 *  ~~~(z &&&  ~~~t) - 7 *  ~~~z - 7 * z - 1 *  ~~~(z &&&  ~~~z) + 12 *  ~~~(z |||  ~~~t) + 26 * (z &&& t) =  - 13 *  ~~~(z ||| t) + 11 *  ~~~(z ^^^ t)

theorem pr33078_3_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬12#16 ≥ ↑16 →
    12#16 ≥ ↑16 ∨ True ∧ zeroExtend 16 (truncate 4 (signExtend 16 x >>> 12#16)) ≠ signExtend 16 x >>> 12#16 → False

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

theorem lshrult_02_09_exact_proof : lshrult_02_09_exact_before ⊑ lshrult_02_09_exact_after

theorem PR30273_three_bools_thm.extracted_1._8 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 →
    x_1 = 1#1 →
      ¬(True ∧ (zeroExtend 32 x).saddOverflow 1#32 = true) →
        x = 1#1 →
          ¬(True ∧ (2#32).saddOverflow (zeroExtend 32 x_2) = true ∨
                True ∧ (2#32).uaddOverflow (zeroExtend 32 x_2) = true) →
            zeroExtend 32 x + 1#32 = 2#32 + zeroExtend 32 x_2

theorem e_1484 :
    3 * t + 3 *  ~~~(z &&& t) + 5 *  ~~~(z &&&  ~~~z) - 5 *  ~~~(z ^^^ t) - 1 *  ~~~(z &&&  ~~~t) + 2 * (z ^^^ t) + 11 * (z |||  ~~~t) - 8 *  ~~~(z ||| t) - 2 *  ~~~(z |||  ~~~t) - 16 * (z &&&  ~~~t) - 8 * (z &&& t) = 5 * (z ||| t) + 5 *  ~~~z

theorem and_orn_xor_commute8_thm (e e_1 : IntW 32) :
  LLVM.and (LLVM.xor (mul e_1 e_1) (mul e e)) (LLVM.or (mul e_1 e_1) (LLVM.xor (mul e e) (const? 32 (-1)))) ⊑
    LLVM.and (mul e_1 e_1) (LLVM.xor (mul e e) (const? 32 (-1)))

theorem udiv_illegal_type_proof : udiv_illegal_type_before ⊑ udiv_illegal_type_after

theorem e_1959 :
     - 3 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) + 2 *  ~~~(a &&& (b ^^^ c)) + 1 * (a ^^^ (b ||| c)) - 3 * (b ^^^  ~~~(a ||| c)) + 5 * (b ^^^  ~~~(a &&&  ~~~c)) + 2 * (b &&&  ~~~c) - 5 *  ~~~(a ^^^ ( ~~~b ||| c)) - 3 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) - 7 * ( ~~~c |||  ~~~(a ^^^ b)) + 3 *  ~~~( ~~~a &&& ( ~~~b ||| c)) - 1 *  ~~~(a &&& ( ~~~b &&& c)) - 7 * b - 7 * (b ^^^ (a ||| ( ~~~b &&& c))) + 2 * ((a &&& b) ^^^ (b |||  ~~~c)) - 2 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 5 * (b ^^^ (a &&&  ~~~c)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * ( ~~~b &&&  ~~~(a ^^^ c)) - 6 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) + 3 *  ~~~(a ^^^ c) + 5 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 2 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 5 * (b ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 1 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) + 2 * (b ^^^ (a ||| (b ^^^ c))) - 3 * (a ^^^ b) - 2 * (b |||  ~~~c) - 1 * ((a |||  ~~~b) &&& (b ^^^ c)) - 2 * (c &&&  ~~~(a &&& b)) + 1 * (b ^^^  ~~~(a &&& c)) + 1 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) + 3 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 2 *  ~~~(b ^^^ c) - 1 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) - 1 * (a ^^^ c) + 1 * (a ||| ( ~~~b ||| c)) - 1 * (c ^^^ (a &&& b)) + 5 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) - 11 * (b &&& c) - 6 * (c ^^^ (a &&& (b ||| c))) + 11 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 5 * (a ^^^ (b ^^^ c)) - 7 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) - 5 * (b ^^^  ~~~(a &&& (b ^^^ c))) + 1 * ((a ^^^ b) |||  ~~~(a ^^^ c)) + 2 *  ~~~(a &&& c) - 11 * ((a &&& c) |||  ~~~(b ||| c)) - 3 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 7 *  ~~~(a ||| ( ~~~b ||| c)) + 35 *  ~~~( ~~~a ||| (b ||| c)) + 32 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 28 * ( ~~~a &&& ( ~~~b &&& c)) + 42 * ( ~~~a &&& (b &&& c)) + 2 * (a &&& ( ~~~b &&& c)) + 50 * (a &&& (b &&& c)) = 2 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 6 * (a ||| ( ~~~b &&& c))

theorem icmp_slt_0_and_icmp_sge_neg1_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → x >>> 31#32 &&& zeroExtend 32 (ofBool (-1#32 <ₛ x)) = 0#32

theorem ashr_sel_op1_proof : ashr_sel_op1_before ⊑ ashr_sel_op1_after

theorem drop_nsw_trunc_proof : drop_nsw_trunc_before ⊑ drop_nsw_trunc_after

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

theorem not_xor_to_or_not3_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 3),
  x_2 &&& x_1 ^^^ (x_2 ||| x) ^^^ -1#3 = x_2 &&& x_1 ||

theorem e_953 :
    3 * (z ||| t) - 11 *  ~~~(z &&& t) + 4 * t + 11 *  ~~~(z ||| t) + 10 *  ~~~(z |||  ~~~t) + 14 * (z &&&  ~~~t) = 7 * (z &&& t) + 6 * (z ^^^ t)

theorem sextinreg2_proof : sextinreg2_before ⊑ sextinreg2_after

theorem ult_to_sgt_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 ^^^ 127#8 <ᵤ x ^^^ 127#8) = ofBool (x <ₛ x_1)

theorem mul_mask_pow2_sgt0_proof : mul_mask_pow2_sgt0_before ⊑ mul_mask_pow2_sgt0_after

theorem test57_proof : test57_before ⊑ test57_after

theorem shrink_select_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → truncate 8 42#32 = 42#8

theorem sub_sel_op1_proof : sub_sel_op1_before ⊑ sub_sel_op1_after

theorem bar_thm (e e_1 : IntW 64) :
  icmp IntPred.eq (LLVM.and e_1 (LLVM.xor (LLVM.and e_1 e) (const? 64 (-1)))) (const? 64 0) ⊑
    icmp IntPred.eq (LLVM.and e_1 (LLVM.xor e (const? 64 (-1)))) (const? 64 0)

theorem bools2_logical_commute0_thm.extracted_1._5 : ∀ (x x_1 : BitVec 1),
  x_1 = 1#1 → ¬x_1 ^^^ 1#1 = 1#1 → x = 1#1 → 1#1 = x

theorem test_sub__nsw_is_safe_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.or e (const? 32 (-2147483648))) (const? 32 (-2147483647))) (const? 32 (-1))
      (sub (const? 32 (-2147483648)) (LLVM.or e (const? 32 (-2147483648)))) ⊑
    sub (const? 32 (-2147483648)) (LLVM.or e (const? 32 (-2147483648))) { «nsw» := true, «nuw» := false }

theorem t3_exact_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬(True ∧ x >>> 63#64 <<< 63#64 ≠ x ∨ 63#64 ≥ ↑64) →
    ¬(True ∧ x >>> 63#64 <<< 63#64 ≠ x ∨
          63#64 ≥ ↑64 ∨
            True ∧ signExtend 64 (truncate 32 (x >>> 63#64)) ≠ x >>> 63#64 ∨
              True ∧ zeroExtend 64 (truncate 32 (x >>> 63#64)) ≠ x >>> 63#64) →
      0#32 - truncate 32 (x.sshiftRight' 63#64) = truncate 32 (x >>> 63#64)

theorem test_eq_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 1073741823)) (const? 32 0)) (const? 32 0) (shl e (const? 32 2)) ⊑
    shl e (const? 32 2)

@[simp] theorem le_refl (e : EffectKind) : e ≤ e

theorem and_congr (e1 : a ≈ʷ b) (e2 : c ≈ʷ d) : (a &&& c) ≈ʷ (b &&& d)

theorem exact_ashr_ne_both_equal_thm (e : IntW 8) :
  icmp IntPred.ne (ashr (const? 8 (-128)) e { «exact» := true }) (const? 8 (-128)) ⊑
    icmp IntPred.ne e (const? 8 0)

theorem samesign_inverted_commute3_proof : samesign_inverted_commute3_before ⊑ samesign_inverted_commute3_after

theorem t6_no_extrause_proof : t6_no_extrause_before ⊑ t6_no_extrause_after

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

theorem shl_shl_constants_div_proof : shl_shl_constants_div_before ⊑ shl_shl_constants_div_after

theorem main4b_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 == 7#32) = 1#1 →
    ¬ofBool (x &&& 16#32 != 0#32) = 1#1 → 1#32 = zeroExtend 32 (ofBool (x &&& 23#32 != 23#32))

theorem test_cast_select_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → zeroExtend 32 3#16 = 3#32

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

theorem add_or_sub_comb_i8_commuted2_nsw_thm (e : IntW 8) :
  add (mul e e) (LLVM.or (sub (const? 8 0) (mul e e)) (mul e e)) { «nsw» := true, «nuw» := false } ⊑
    LLVM.and (add (mul e e) (const? 8 (-1)) { «nsw» := true, «nuw» := false }) (mul e e)

theorem test3_proof : test3_before ⊑ test3_after

theorem select_icmp_ne_0_and_1073741824_and_not_8_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ofBool (0#32 != x_1 &&& 1073741824#32) = 1#1 →
    ofBool (x_1 &&& 1073741824#32 == 0#32) = 1#1 → x = x &&& BitVec.ofInt 8 (-9)

theorem lshrugt_03_07_proof : lshrugt_03_07_before ⊑ lshrugt_03_07_after

theorem scalar_i64_lshr_and_negC_eq_proof : scalar_i64_lshr_and_negC_eq_before ⊑ scalar_i64_lshr_and_negC_eq_after

@[simp]
lemma determinize_complete (M : NFA α σ) :
    M.toDFA.toNFA.Complete

theorem trunc_shl_15_i16_i32_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬15#32 ≥ ↑32 → ¬15#16 ≥ ↑16 → truncate 16 (x <<< 15#32) = truncate 16 x <<< 15#16

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

theorem bools_logical_commute1_and2_thm.extracted_1._12 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → x_1 = 1#1 → ¬0#1 = 1#1 → x_1 &&& x = x

theorem ugt_swap_and_min_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.ult e_1 e) (icmp IntPred.eq e (const? 8 0)) ⊑ const? 1 0

theorem carryWith_carryWith_eq_carryWith_add (carryState : p.α → Bool) (x : arity → BitStream) :
      p.carryWith (p.carryWith carryState x n) (fun a i => x a (n + i)) m =
      p.carryWith carryState x (n + m)

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

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

theorem p_commutative0_proof : p_commutative0_before ⊑ p_commutative0_after

theorem test5_thm.extracted_1._1 : ∀ (x : BitVec 7), (x ||| 23#7) ^^^ 23#7 = x &&& BitVec.ofInt 7 (-24)

theorem bv_290__292 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.mul (LLVM.shl (LLVM.const? w 1) e) e_1 ⊑ LLVM.shl e_1 e

theorem t20_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ¬x ≥ ↑16 → x_1 - truncate 8 (BitVec.ofInt 16 (-42) <<< x) = x_1 + truncate 8 (42#16 <<< x)

theorem eq_irregular_bit_widths_thm.extracted_1._2 : ∀ (x x_1 : BitVec 31),
  ¬(13#31 ≥ ↑31 ∨ 13#31 ≥ ↑31 ∨ 7#31 ≥ ↑31 ∨ 7#31 ≥ ↑31) →
    ¬(7#31 ≥ ↑31 ∨ 7#31 ≥ ↑31) →
      ofBool (truncate 5 (x_1 >>> 13#31) == truncate 5 (x >>> 13#31)) &&&
          ofBool (truncate 6 (x_1 >>> 7#31) == truncate 6 (x >>> 7#31)) =
        ofBool (truncate 11 (x_1 >>> 7#31) == truncate 11 (x >>> 7#31))

theorem t9_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), 0#8 - (x_1 - x) = x - x_1

theorem slt1 (w : Nat) (a b : BitVec w) : (a.slt b) ∨ (b.sle a)

theorem positive_with_icmp_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x <ᵤ 512#32) = 1#1 → 0#1 = ofBool (x <ᵤ 128#32)

theorem udiv_shl_pair1_thm.extracted_1._2 : ∀ (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) → x_2 <<< x_1 / x_2 <<< x = 1#32 <<< x_1 >>> x

theorem test_and3_proof : test_and3_before ⊑ test_and3_after

theorem eq_21_comm_eq2_thm (e e_1 : IntW 32) :
  LLVM.and (icmp IntPred.eq (trunc 8 (lshr e_1 (const? 32 16))) (trunc 8 (lshr e (const? 32 16))))
      (icmp IntPred.eq (trunc 8 (lshr e (const? 32 8))) (trunc 8 (lshr e_1 (const? 32 8)))) ⊑
    icmp IntPred.eq (trunc 16 (lshr e_1 (const? 32 8))) (trunc 16 (lshr e (const? 32 8)))

@[simp]
lemma NFA'.ofFSM_spec (t : Term) :
    (ofFSM (FSM.ofTerm t)).accepts = t.language

theorem foo_proof : foo_before ⊑ foo_after

theorem p15_commutativity2_proof : p15_commutativity2_before ⊑ p15_commutativity2_after

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

theorem positive_trunc_base_logical_thm (e : IntW 32) :
  select (icmp IntPred.sgt (trunc 16 e) (const? 16 (-1)))
      (icmp IntPred.ult (add (trunc 16 e) (const? 16 128)) (const? 16 256)) (const? 1 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 65408)) (const? 32 0)

lemma eval_assignVars [DecidableEq α] : ∀ {c : Circuit α}
    {f : ∀ (a : α) (_ha : a ∈ c.vars), β ⊕ Bool} {g : β → Bool},
    eval (assignVars c f) g = evalv c (λ a ha => Sum.elim g id (f a ha))

theorem different_size_sext_sext_sgt_proof : different_size_sext_sext_sgt_before ⊑ different_size_sext_sext_sgt_after

theorem ashrsgt_02_15_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬2#4 ≥ ↑4 → ofBool (-1#4 <ₛ x.sshiftRight' 2#4) = ofBool (-1#4 <ₛ x)

theorem test_nsw_dropped_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741823#32 == 0#32) = 1#1 → 2#32 ≥ ↑32 → False

theorem shl_lshr_pow2_const_negative_overflow1_proof : shl_lshr_pow2_const_negative_overflow1_before ⊑ shl_lshr_pow2_const_negative_overflow1_after

theorem and_to_xor4_proof : and_to_xor4_before ⊑ and_to_xor4_after

theorem pr33078_4_proof : pr33078_4_before ⊑ pr33078_4_after

theorem splat_mul_known_lz_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬96#128 ≥ ↑128 → ofBool ((zeroExtend 128 x * 18446744078004518913#128) >>> 96#128 == 0#128) = 1#1

theorem xor_of_icmps_to_ne_commute_proof : xor_of_icmps_to_ne_commute_before ⊑ xor_of_icmps_to_ne_commute_after

theorem ashrslt_01_10_exact_proof : ashrslt_01_10_exact_before ⊑ ashrslt_01_10_exact_after

theorem test5_proof : test5_before ⊑ test5_after

theorem logic_or_logic_and_6_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → ¬x = 1#1 → True → x_1 = 1#1

theorem test8_logical_proof : test8_logical_before ⊑ test8_logical_after

theorem alive_AndOrXor_698 : alive_AndOrXor_698_src ⊑ alive_AndOrXor_698_tgt

theorem eval_zext_multi_use_in_one_inst_proof : eval_zext_multi_use_in_one_inst_before ⊑ eval_zext_multi_use_in_one_inst_after

theorem p0_proof : p0_before ⊑ p0_after

theorem src_is_notmask_lshr_shl_fail_mismatch_shifts_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(x_2 ≥ ↑8 ∨ x_1 ≥ ↑8) →
    ofBool (((-1#8) >>> x_2 <<< x_1 ^^^ -1#8) &&& (x ^^^ 123#8) == x ^^^ 123#8) =
      ofBool ((x ^^^ 123#8) &&& (-1#8) >>> x_2 <<< x_1 == 0#8)

theorem or_and3_thm.extracted_1._7 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 32) (x_3 : BitVec 1),
  ¬x_3 ||

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

theorem scalar_i32_shl_and_signbit_eq_proof : scalar_i32_shl_and_signbit_eq_before ⊑ scalar_i32_shl_and_signbit_eq_after

theorem ripple_nsw2_thm (e e_1 : IntW 16) :
  add (LLVM.and e_1 (const? 16 (-16385))) (LLVM.and e (const? 16 1)) ⊑
    add (LLVM.and e_1 (const? 16 (-16385))) (LLVM.and e (const? 16 1)) { «nsw» := true, «nuw» := true }

theorem lshrult_02_12_proof : lshrult_02_12_before ⊑ lshrult_02_12_after

theorem test13_proof : test13_before ⊑ test13_after

@[simp] theorem carry_zero (x : arity → BitStream) : carry p x 0 = p.initCarry

theorem and_ne_with_one_bit_diff_constants1_proof : and_ne_with_one_bit_diff_constants1_before ⊑ and_ne_with_one_bit_diff_constants1_after

theorem e_1968 :
    7 * (c ^^^  ~~~(a &&&  ~~~b)) - 1 *  ~~~(a ^^^ ( ~~~b ||| c)) - 2 * ((a ||| b) &&& (b ^^^ c)) + 4 * (b &&&  ~~~(a &&& c)) - 2 * ( ~~~b &&&  ~~~(a ^^^ c)) + 1 *  ~~~c + 4 * b - 11 *  ~~~(a &&&  ~~~c) - 1 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 6 *  ~~~(b |||  ~~~c) + 11 * (a ||| ( ~~~b &&& c)) + 2 * ( ~~~c &&& (a ^^^ b)) - 3 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 5 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) - 1 * ( ~~~(a ||| b) |||  ~~~(a ^^^ (b ^^^ c))) - 7 * (b &&&  ~~~c) - 6 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) + 11 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) + 7 * (b ^^^  ~~~(a &&& (b &&& c))) - 7 * (a ^^^ c) + 1 * (c &&&  ~~~(a &&& b)) + 1 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 5 * (c ||| (a &&& b)) + 3 * (b |||  ~~~(a ^^^ c)) + 3 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) + 3 * (c |||  ~~~(a ^^^ b)) + 1 * ((a &&& b) ^^^ (b |||  ~~~c)) - 7 *  ~~~( ~~~a &&& ( ~~~b ||| c)) - 11 * (b ||| c) - 7 *  ~~~(a &&& b) + 7 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) + 2 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 6 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 7 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 5 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) + 2 * (a ||| (b ||| c)) - 11 * (b ^^^  ~~~(a ||| (b &&& c))) - 6 * ((a &&& c) ^^^ (a ^^^ (b &&& c))) + 1 * (b ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 2 * (c &&& (a ||| b)) - 1 * ((a &&& b) ^^^  ~~~(a ^^^ ( ~~~b ||| c))) + 1 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) - 11 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) + 11 *  ~~~(a ||| c) - 1 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) - 1 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 7 * (b ^^^ ( ~~~a &&& (b ^^^ c))) - 6 * ((a ^^^ b) |||  ~~~(a ^^^ c)) + 7 * ( ~~~(a &&& b) &&&  ~~~(b ^^^ c)) - 8 *  ~~~(a ||| (b ||| c)) + 30 *  ~~~(a ||| ( ~~~b ||| c)) + 32 *  ~~~( ~~~a ||| (b ||| c)) + 18 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 32 * ( ~~~a &&& (b &&& c)) + 26 * (a &&& ( ~~~b &&& c)) + 11 * (a &&& (b &&& c)) = 6 * (c ^^^ (a &&&  ~~~b)) - 33 * ( ~~~a &&& ( ~~~b &&& c))

theorem ne_smax2_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x <ₛ x_1) = 1#1 → ofBool (x != x) = ofBool (x <ₛ x_1)

theorem select_icmp_eq_and_32_0_or_8_thm (e e_1 : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e_1 (const? 32 32)) (const? 32 0)) e (LLVM.or e (const? 32 8)) ⊑
    LLVM.or e (LLVM.and (lshr e_1 (const? 32 2)) (const? 32 8))

theorem negate_xor_proof : negate_xor_before ⊑ negate_xor_after

theorem test_const_shr_exact_and_1_ne_0_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ 42#32 >>> x <<< x ≠ 42#32 ∨ x ≥ ↑32) → True ∧ 1#32 <<< x >>> x ≠ 1#32 ∨ x ≥ ↑32 → False

theorem icmp_slt_0_or_icmp_add_1_sge_100_i32_fail_proof : icmp_slt_0_or_icmp_add_1_sge_100_i32_fail_before ⊑ icmp_slt_0_or_icmp_add_1_sge_100_i32_fail_after

theorem e_1061 :
     - 3 *  ~~~(z &&& t) - 7 *  ~~~(z &&&  ~~~t) - 5 * z - 1 *  ~~~z + 8 *  ~~~(z |||  ~~~t) + 5 * (z &&&  ~~~t) + 9 * (z &&& t) =  - 3 * (z ||| t) - 11 *  ~~~(z ||| t)

theorem pr64558_thm (e e_1 : IntW 1) : select (LLVM.and (LLVM.xor e_1 (const? 1 1)) e) e e_1 ⊑ LLVM.or e_1 e

include hinj in
@[simp]
lemma product.prodArray_spec :
    ∀ s₁ s₂, f s₁ s₂ ∈ product.prodArray f hm₁ hm₂ ↔ (s₁.val ∈ m₁ ∧ s₂.val ∈ m₂)

theorem src_x_and_nmask_uge_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8),
  ¬x = 1#1 → x ^^^ 1#1 = 1#1 → ofBool (0#8 ≤ᵤ x_1 &&& 0#8) = 1#1

theorem sge_swap_and_max_logical_proof : sge_swap_and_max_logical_before ⊑ sge_swap_and_max_logical_after

theorem sdiv_ult_smin_thm (e e_1 : IntW 8) :
  icmp IntPred.ult (LLVM.sdiv e_1 e) (const? 8 (-128)) ⊑
    icmp IntPred.sgt (LLVM.sdiv e_1 e) (const? 8 (-1))

private lemma BitVec.sle_iff_slt_or_eq {w : ℕ} (bv1 bv2 : BitVec w):
    (bv1.sle bv2) = true ↔ (bv1.slt bv2) = true ∨ bv1 = bv2

theorem neg_or_ashr_i32_commute_thm (e : IntW 32) :
  ashr (LLVM.or (LLVM.sdiv (const? 32 42) e) (sub (const? 32 0) (LLVM.sdiv (const? 32 42) e))) (const? 32 31) ⊑
    sext 32 (icmp IntPred.ne (LLVM.sdiv (const? 32 42) e) (const? 32 0))

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

theorem shl_nsw_slt_1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ (x_1 <<< x).sshiftRight' x ≠ x_1 ∨ x ≥ ↑8) → ofBool (x_1 <<< x <ₛ 1#8) = ofBool (x_1 <ₛ 1#8)

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

theorem test_shl_nuw_nsw__none_are_safe_thm.extracted_1._4 : ∀ (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) ∨
          True ∧ (x_1 &&& BitVec.ofInt 32 (-2)) <<< 2#32 >>> 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) →
        x.sshiftRight' (zeroExtend 64 ((x_1 &&& BitVec.ofInt 32 (-2)) <<< 2#32)) =
          x.sshiftRight' (zeroExtend 64 (x_1 <<< 2#32 &&& BitVec.ofInt 32 (-8)))

@[simp]
theorem xor_not_xor {a b : Bool} : ((!(a ^^ b)) ^^ b) = !a

theorem and_xor_common_op_commute1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(x_1 = 0 ∨ x = 0 ∨ x_1 = 0) → x_1 = 0 ∨ x = 0 → False

@[simp] theorem Valuation.append_inj_left {V V' : Γ.Valuation} {W : Δ.Valuation} :
    (V ++ W) = (V' ++ W) ↔ V = V'

theorem set_to_clear_decomposebittest_proof : set_to_clear_decomposebittest_before ⊑ set_to_clear_decomposebittest_after

@[simp] theorem toBitVec_ofBitVec (x : BitVec w) (w' : Nat) :
    toBitVec w' (ofBitVecSext x) = x.signExtend w'

theorem alive_AndOrXor_2297  (w : Nat)   : alive_AndOrXor_2297_src w  ⊑ alive_AndOrXor_2297_tgt w

theorem AvoidCollision_setWidth_cast {x : BitVec w} {h : w = v} : (x.cast h).setWidth k = x.setWidth k

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

theorem not_signbit_splat_mask2_proof : not_signbit_splat_mask2_before ⊑ not_signbit_splat_mask2_after

theorem sgt_or_not_min_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x <ₛ x_1) ||

theorem substitute_constant_and_eq_eq_proof : substitute_constant_and_eq_eq_before ⊑ substitute_constant_and_eq_eq_after

theorem fold_eq_lhs_proof : fold_eq_lhs_before ⊑ fold_eq_lhs_after

theorem not_bool_add_lshr_proof : not_bool_add_lshr_before ⊑ not_bool_add_lshr_after

theorem mul_constant_mismatch_wrap_eq_proof : mul_constant_mismatch_wrap_eq_before ⊑ mul_constant_mismatch_wrap_eq_after

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

theorem test8_proof : test8_before ⊑ test8_after

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 neg_eq_not_add_one (x : BitVec w) :
    -x = ~~~ x + 1#w

theorem ashrsgt_01_02_proof : ashrsgt_01_02_before ⊑ ashrsgt_01_02_after

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

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 positive_samevar_shlnsw_lshrexact_proof : positive_samevar_shlnsw_lshrexact_before ⊑ positive_samevar_shlnsw_lshrexact_after

theorem test15_thm (e : IntW 32) :
  sub (const? 64 8) (sext 64 (ashr e (const? 32 1))) ⊑
    sext 64 (sub (const? 32 8) (ashr e (const? 32 1)) { «nsw» := true, «nuw» := false })

theorem shift_xor_multiuse_cmp_xor_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (0#32 != x_2 &&& 4096#32) = 1#1 → ¬ofBool (x_2 &&& 4096#32 == 0#32) = 1#1 → False

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

theorem and_or3_commuted_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 == x_1) &&& x = 1#1 → x = 1#1 → ofBool (x_2 != x_1) = 1#1 → x = 1#1

theorem PR42691_5_proof : PR42691_5_before ⊑ PR42691_5_after

theorem sgt_swap_and_min_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 <ₛ x) = 1#1 → ofBool (x == BitVec.ofInt 8 (-128)) = 0#1

theorem main1_logical_proof : main1_logical_before ⊑ main1_logical_after

theorem substitute_constant_or_ne_swap_sle_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 != 42#8) ||

theorem sel_false_val_is_a_masked_lshr_of_true_val2_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬2#32 ≥ ↑32 →
    ofBool ((x_1 &&& 60#32) >>> 2#32 == 0#32) = 1#1 →
      ¬(2#32 ≥ ↑32 ∨ True ∧ (x_1 >>> 2#32 &&& 15#32).msb = true ∨ zeroExtend 64 (x_1 >>> 2#32 &&& 15#32) ≥ ↑64) →
        x = x.sshiftRight' (zeroExtend 64 (x_1 >>> 2#32 &&& 15#32))

theorem main3b_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 == 0#32) = 1#1 →
    ¬ofBool (x &&& 16#32 != 16#32) = 1#1 → 1#32 = zeroExtend 32 (ofBool (x &&& 23#32 != 0#32))

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 or_xor_common_op_commute7_proof : or_xor_common_op_commute7_before ⊑ or_xor_common_op_commute7_after

theorem test_logical_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬ofBool (13#32 <ᵤ x) = 1#1 → 0#1 = ofBool (x == 15#32)

theorem t_0_1_proof : t_0_1_before ⊑ t_0_1_after

theorem test_shift_nonnegative_proof : test_shift_nonnegative_before ⊑ test_shift_nonnegative_after

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

theorem lshr_add_proof : lshr_add_before ⊑ lshr_add_after

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

theorem logical_and_logical_and_icmps_comm1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(x ≥ ↑8 ∨ ofBool (x_1 &&& 1#8 <<< x != 0#8) = 1#1) → True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8 → False

theorem ne_umax4_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_1 + 3#32 <ᵤ x)

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

theorem ashr_eq_noexact_thm (e : IntW 8) :
  icmp IntPred.eq (ashr e (const? 8 3)) (const? 8 10) ⊑
    icmp IntPred.eq (LLVM.and e (const? 8 (-8))) (const? 8 80)

theorem orn_and_cmp_1_logical_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 37),
  ¬ofBool (x_2 ≤ₛ x_1) = 1#1 → x = 1#1 → ofBool (x_1 <ₛ x_2) = x

theorem lshrult_03_12_proof : lshrult_03_12_before ⊑ lshrult_03_12_after

theorem xor_i8_to_i64_shl_save_and_ne_proof : xor_i8_to_i64_shl_save_and_ne_before ⊑ xor_i8_to_i64_shl_save_and_ne_after

theorem bools2_logical_commute2_thm.extracted_1._13 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → x = 1#1 → ¬0#1 = 1#1 → x_2 ^^^ 1#1 = x

theorem select_icmp_ne_pow2_proof : select_icmp_ne_pow2_before ⊑ select_icmp_ne_pow2_after

theorem e_473 :
    2 *  ~~~x + 11 *  ~~~y + 2 *  ~~~(x &&&  ~~~y) + 7 *  ~~~(x &&&  ~~~x) - 3 * (x ^^^ y) + 1 * (x ||| y) - 22 *  ~~~(x ||| y) - 14 * (x &&&  ~~~y) - 8 * (x &&& y) = 9 *  ~~~(x |||  ~~~y) + 2 * x

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

theorem t3_no_extrause_thm (e e_1 : IntW 8) :
  icmp IntPred.ult (LLVM.xor e_1 (const? 8 (-1))) e ⊑
    icmp IntPred.ugt e (LLVM.xor e_1 (const? 8 (-1)))

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

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

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

theorem test8_thm (e : IntW 999) : LLVM.and e (const? 999 0) ⊑ const? 999 0

theorem negative_trunc_not_arg_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (-1#8 <ₛ truncate 8 x_1) &&& ofBool (x + 128#32 <ᵤ 256#32) =
    ofBool (x_1 &&& 128#32 == 0#32) &&& ofBool (x + 128#32 <ᵤ 256#32)

theorem sel_false_val_is_a_masked_ashr_of_true_val1_thm.extracted_1._4 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& BitVec.ofInt 32 (-2147483588) == 0#32) = 1#1 →
    ¬(2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& BitVec.ofInt 32 (-2147483588)).sshiftRight' 2#32) ≥ ↑64) →
      ¬(2#32 ≥ ↑32 ∨
            True ∧ (x_1.sshiftRight' 2#32 &&& BitVec.ofInt 32 (-536870897)).msb = true ∨
              zeroExtend 64 (x_1.sshiftRight' 2#32 &&& BitVec.ofInt 32 (-536870897)) ≥ ↑64) →
        x.sshiftRight' (zeroExtend 64 ((x_1 &&& BitVec.ofInt 32 (-2147483588)).sshiftRight' 2#32)) =
          x.sshiftRight' (zeroExtend 64 (x_1.sshiftRight' 2#32 &&& BitVec.ofInt 32 (-536870897)))

theorem trunc_shl_32_i32_i64_thm.extracted_1._1 : ∀ (x : BitVec 64), ¬32#64 ≥ ↑64 → truncate 32 (x <<< 32#64) = 0#32

theorem test6_thm (e : IntW 55) : mul (shl e (const? 55 1)) (const? 55 3) ⊑ mul e (const? 55 6)

theorem test_sge_xor_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 ^^^ -1#32 ≤ₛ x_1 ^^^ -1#32 ^^^ x) = ofBool (x ^^^ x_1 ≤ₛ x_1)

theorem e_1886 :
     - 1 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 1 * (c ^^^  ~~~(a &&& b)) - 6 * (c &&& (a ||| b)) - 11 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 1 * (b ^^^  ~~~(a ||| (b ^^^ c))) - 3 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) - 1 * (b &&&  ~~~c) - 2 * (c ^^^  ~~~(a &&& (b &&& c))) + 5 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 6 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 11 * (b ^^^ (a ||| c)) + 4 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 7 * ((b &&& c) ||| (a &&& (b ||| c))) - 1 * (a ||| (b ||| c)) + 7 * (a ^^^ b) + 7 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) - 1 * (a ||| (b &&& c)) + 3 *  ~~~(a |||  ~~~c) + 4 * (c ^^^ (a |||  ~~~b)) - 1 * (b ^^^ (a ||| ( ~~~b &&& c))) + 7 * ((a &&& b) ^^^ (b |||  ~~~c)) + 11 * (c ^^^  ~~~(a ||| (b &&& c))) + 3 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) + 1 * (b &&& (a ^^^ c)) - 7 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 6 * ((b &&&  ~~~c) ^^^ (a ||| (b ^^^ c))) + 2 * ( ~~~b &&& (a ^^^ c)) + 2 * (c &&&  ~~~(a &&& b)) - 2 * ((a &&&  ~~~b) ||| (b ^^^ c)) + 1 * ((a &&& c) ^^^  ~~~(b &&&  ~~~c)) - 7 * (c ^^^ (a ||| b)) - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 3 * ( ~~~a ||| (b &&& c)) + 2 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) + 1 * ( ~~~a &&& (b ||| c)) - 11 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) - 6 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 2 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 7 * ( ~~~a &&& ( ~~~b ||| c)) - 3 * (c ^^^ (a &&& b)) - 2 *  ~~~(a &&&  ~~~c) - 7 *  ~~~(a ||| (b ||| c)) + 3 *  ~~~(a ||| ( ~~~b ||| c)) + 6 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 17 * ( ~~~a &&& ( ~~~b &&& c)) - 11 * ( ~~~a &&& (b &&& c)) + 20 * (a &&& ( ~~~b &&& c)) + 24 * (a &&& (b &&& c)) =  - 4 *  ~~~(a &&& (b ||| c))

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 basic_preserve_nsw_thm (e e_1 : IntW 8) :
  LLVM.xor (add (LLVM.xor e_1 (const? 8 (-1))) e { «nsw» := true, «nuw» := false }) (const? 8 (-1)) ⊑
    sub e_1 e { «nsw» := true, «nuw» := false }

theorem ule_umax4_proof : ule_umax4_before ⊑ ule_umax4_after

theorem and_not_or_commute5_proof : and_not_or_commute5_before ⊑ and_not_or_commute5_after

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

theorem shl_lshr_demand1_thm (e : IntW 8) :
  LLVM.or (lshr (shl (const? 8 40) e) (const? 8 3)) (const? 8 (-32)) ⊑
    LLVM.or (shl (const? 8 5) e) (const? 8 (-32))

theorem test22_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬24#32 ≥ ↑32 → signExtend 32 (truncate 8 x) <<< 24#32 = x <<< 24#32

theorem xor_icmp_invalid_range_thm (e : IntW 8) :
  LLVM.xor (icmp IntPred.eq e (const? 8 0)) (icmp IntPred.ne e (const? 8 4)) ⊑
    icmp IntPred.ne (LLVM.and e (const? 8 (-5))) (const? 8 0)

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 1), ofBool (zeroExtend 32 x != 0#32) = x

theorem andn_or_cmp_1_logical_proof : andn_or_cmp_1_logical_before ⊑ andn_or_cmp_1_logical_after

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

theorem test5_proof : test5_before ⊑ test5_after

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

theorem neg_or_lshr_i32_commute_thm (e : IntW 32) :
  lshr (LLVM.or (LLVM.sdiv (const? 32 42) e) (sub (const? 32 0) (LLVM.sdiv (const? 32 42) e))) (const? 32 31) ⊑
    zext 32 (icmp IntPred.ne (LLVM.sdiv (const? 32 42) e) (const? 32 0))

theorem and_consts_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (4#32 &&& x == 0#32) ||

theorem ashrslt_02_10_exact_proof : ashrslt_02_10_exact_before ⊑ ashrslt_02_10_exact_after

theorem positive_samevar_proof : positive_samevar_before ⊑ positive_samevar_after

theorem xor_common_op_commute3_thm (e e_1 : IntW 8) :
  LLVM.or (LLVM.xor e_1 (const? 8 5)) (LLVM.xor (mul e e) (LLVM.xor e_1 (const? 8 5))) ⊑
    LLVM.or (LLVM.xor e_1 (const? 8 5)) (mul e e)

theorem lowmask_add_zext_proof : lowmask_add_zext_before ⊑ lowmask_add_zext_after

theorem is_ascii_alphabetic_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ x.saddOverflow (BitVec.ofInt 32 (-65)) = true) →
    ¬ofBool (x + BitVec.ofInt 32 (-65) <ᵤ 26#32) = 1#1 →
      ¬(True ∧ x.saddOverflow (BitVec.ofInt 32 (-97)) = true) →
        ofBool (x + BitVec.ofInt 32 (-97) <ᵤ 26#32) =
          ofBool ((x &&& BitVec.ofInt 32 (-33)) + BitVec.ofInt 32 (-65) <ᵤ 26#32)

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

theorem scalar_i64_lshr_and_negC_eq_thm (e e_1 : IntW 64) :
  icmp IntPred.eq (LLVM.and (lshr e_1 e) (const? 64 (-8589934592))) (const? 64 0) ⊑
    icmp IntPred.ult (lshr e_1 e) (const? 64 8589934592)

theorem foo_proof : foo_before ⊑ foo_after

theorem fake_sext_proof : fake_sext_before ⊑ fake_sext_after

theorem PR42691_8_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.slt e (const? 32 14)) (icmp IntPred.ne e (const? 32 (-2147483648))) ⊑
    icmp IntPred.ult (add e (const? 32 2147483647)) (const? 32 (-2147483635))

@[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 test37_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → ofBool (truncate 8 (x >>> 31#32 ||| 512#32) == 11#8) = 0#1

theorem bv_Select_1105 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.select (LLVM.const? 1 0) e_1 e ⊑ e

theorem exact_lshr_ne_both_equal_proof : exact_lshr_ne_both_equal_before ⊑ exact_lshr_ne_both_equal_after

theorem or_test2_thm (e : IntW 7) : LLVM.or (shl e (const? 7 6)) (const? 7 (-64)) ⊑ const? 7 (-64)

theorem shrink_or_proof : shrink_or_before ⊑ shrink_or_after

theorem no_shift_xor_multiuse_cmp_xor_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (0#32 != x_2 &&& 4096#32) = 1#1 → ofBool (x_2 &&& 4096#32 == 0#32) = 1#1 → False

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

theorem neg_test_icmp_non_equality_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741823#32 <ₛ 0#32) = 1#1 → ¬2#32 ≥ ↑32 → 0#32 = x <<< 2#32

theorem not_and_and_or_no_or_commute2_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_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 → False

theorem test12_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬zeroExtend 128 x &&& 31#128 ≥ ↑128 →
    ¬(True ∧ (x &&& 31#32).msb = true ∨ zeroExtend 64 (x &&& 31#32) ≥ ↑64) →
      truncate 64 (zeroExtend 128 x_1 >>> (zeroExtend 128 x &&& 31#128)) =
        zeroExtend 64 x_1 >>> zeroExtend 64 (x &&& 31#32)

theorem scalar_i32_lshr_and_negC_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x ≥ ↑32 → ofBool (x_1 >>> x &&& BitVec.ofInt 32 (-262144) == 0#32) = ofBool (x_1 >>> x <ᵤ 262144#32)

theorem masked_or_A_slightly_optimized_thm (e : IntW 32) :
  LLVM.or (icmp IntPred.ult e (const? 32 8)) (icmp IntPred.eq (LLVM.and e (const? 32 39)) e) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 (-40))) (const? 32 0)

theorem scalar_i32_shl_and_negC_eq_X_is_constant2_proof : scalar_i32_shl_and_negC_eq_X_is_constant2_before ⊑ scalar_i32_shl_and_negC_eq_X_is_constant2_after

theorem eq_umax1_proof : eq_umax1_before ⊑ eq_umax1_after

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

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 test11_proof : test11_before ⊑ test11_after

theorem not_xor_to_or_not1_proof : not_xor_to_or_not1_before ⊑ not_xor_to_or_not1_after

theorem sdiv_icmp5_proof : sdiv_icmp5_before ⊑ sdiv_icmp5_after

theorem udiv_shl_mul_nuw_exact_proof : udiv_shl_mul_nuw_exact_before ⊑ udiv_shl_mul_nuw_exact_after

theorem masked_or_A_slightly_optimized_proof : masked_or_A_slightly_optimized_before ⊑ masked_or_A_slightly_optimized_after

theorem e_2350 :
    1 * (f ^^^ (d ||| ( ~~~e &&& f))) + 11 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 5 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 2 * ((d |||  ~~~e) &&& (e ^^^ f)) - 6 * (f ^^^ (d ||| ( ~~~e ||| f))) - 1 * ( ~~~e &&& (d ^^^ f)) - 2 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 1 * (f ||| (d &&&  ~~~e)) + 1 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) + 11 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) + 2 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) + 1 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 11 * (e ||| (d ^^^ f)) + 4 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 6 * (f &&& (d ^^^ e)) - 7 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 6 * ( ~~~d ||| ( ~~~e ||| f)) - 2 * (e ^^^  ~~~(d |||  ~~~f)) + 2 *  ~~~(d &&& ( ~~~e ||| f)) + 2 *  ~~~( ~~~d &&& ( ~~~e &&& f)) + 1 *  ~~~(d &&& f) - 11 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 1 * ((d &&& e) ||| (e ^^^ f)) + 11 * ((d ^^^ e) ||| (d ^^^ f)) - 6 *  ~~~(d &&&  ~~~d) - 3 * ((d &&& e) ^^^ (e |||  ~~~f)) + 4 * ((d &&& f) ^^^ (e ||| f)) - 3 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) - 1 * ( ~~~f ||| (d ^^^ e)) + 1 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 3 * (e ^^^  ~~~(d ||| (e ^^^ f))) - 6 * ( ~~~e &&&  ~~~(d ^^^ f)) + 3 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) - 5 *  ~~~(d &&& e) - 2 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 3 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 4 * (d ^^^ e) - 1 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 3 * (f |||  ~~~(d ||| e)) - 5 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 2 * (d &&&  ~~~f) + 1 * (f ||| (d ^^^ e)) + 1 * ((d &&& f) ||| (e &&&  ~~~f)) - 7 * (e &&& (d ||| f)) + 2 * (f |||  ~~~(d |||  ~~~e)) - 7 * (e ^^^ (d &&& (e ||| f))) - 5 * ( ~~~d ||| (e &&& f)) + 7 * (e ^^^ (d ||| (e ^^^ f))) + 4 * (e &&& (d ^^^ f)) - 2 * ( ~~~d &&& (e ||| f)) - 1 * (e ^^^ ( ~~~d ||| (e ^^^ f))) + 3 * (d ^^^ (e &&& f)) - 3 * (e ^^^  ~~~(d ||| f)) - 2 * (f |||  ~~~(d ^^^ e)) + 7 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 2 * (e ||| f) + 1 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) - 1 *  ~~~(d |||  ~~~f) + 1 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) + 7 *  ~~~(d ||| (e ||| f)) + 15 *  ~~~(d ||| ( ~~~e ||| f)) - 20 *  ~~~( ~~~d ||| (e ||| f)) + 38 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 18 * ( ~~~d &&& ( ~~~e &&& f)) - 8 * ( ~~~d &&& (e &&& f)) - 15 * (d &&& ( ~~~e &&& f)) + 38 * (d &&& (e &&& f)) =  - 2 * (f ^^^  ~~~(d &&& (e ||| f)))

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_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 test21_proof : test21_before ⊑ test21_after

theorem negAux_eq_not_addAux : a.negAux = (~~~a).addAux 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 ashrsgt_01_09_exact_proof : ashrsgt_01_09_exact_before ⊑ ashrsgt_01_09_exact_after

theorem test11c_proof : test11c_before ⊑ test11c_after

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

@[simp(high)]
theorem ofNat_one (i : Nat) : ofNat 1 i = decide (0 = i)

theorem orn_and_cmp_2_partial_logical_thm (e : IntW 1) (e_1 e_2 : IntW 16) :
  select (LLVM.and (icmp IntPred.sge e_2 e_1) e) (const? 1 1) (icmp IntPred.slt e_2 e_1) ⊑
    LLVM.or e (icmp IntPred.slt e_2 e_1)

theorem ashr_eq_msb_low_second_zero_proof : ashr_eq_msb_low_second_zero_before ⊑ ashr_eq_msb_low_second_zero_after

theorem and_to_xor3_proof : and_to_xor3_before ⊑ and_to_xor3_after

theorem bitwise_and_bitwise_and_icmps_comm2_proof : bitwise_and_bitwise_and_icmps_comm2_before ⊑ bitwise_and_bitwise_and_icmps_comm2_after

theorem e_1262 :
     - 7 *  ~~~(z &&&  ~~~z) + 7 *  ~~~(z &&& t) - 1 * (z |||  ~~~t) - 5 * z + 1 * (z ^^^ t) - 11 * (z ||| t) + 1 *  ~~~(z ||| t) + 10 *  ~~~(z |||  ~~~t) + 16 * (z &&&  ~~~t) =  - 24 * (z &&& t)

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

theorem lor_land_right2_proof : lor_land_right2_before ⊑ lor_land_right2_after

theorem slt_swap_or_not_max_commute_logical_proof : slt_swap_or_not_max_commute_logical_before ⊑ slt_swap_or_not_max_commute_logical_after

theorem trunc_shl_nuw_31_i32_i64_proof : trunc_shl_nuw_31_i32_i64_before ⊑ trunc_shl_nuw_31_i32_i64_after

theorem lshrugt_01_02_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 1)) (const? 4 2) ⊑ icmp IntPred.ugt e (const? 4 5)

theorem slt_swap_or_not_max_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ne e_1 (const? 8 127)) (const? 1 1) (icmp IntPred.sgt e e_1) ⊑
    icmp IntPred.ne e_1 (const? 8 127)

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

theorem lshrugt_01_05_exact_proof : lshrugt_01_05_exact_before ⊑ lshrugt_01_05_exact_after

theorem udiv_eq_zero_iff {x y : BitVec w} (hy : 0#w < y) : udiv x y = 0#w ↔ x < y

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 not_or_or_and_not_and_and_commute4_proof : not_or_or_and_not_and_and_commute4_before ⊑ not_or_or_and_not_and_and_commute4_after

theorem select_xor_icmp_bad_6_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 != 1#32) = 1#1 → ofBool (x_1 == 1#32) = 1#1 → False

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

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

theorem positive_biggerShl_proof : positive_biggerShl_before ⊑ positive_biggerShl_after

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

theorem commutativity_constant_14_vary_proof : commutativity_constant_14_vary_before ⊑ commutativity_constant_14_vary_after

theorem e_49 :
    11 * (x |||  ~~~y) + 2 * x - 12 *  ~~~(x ||| y) - 13 * (x &&&  ~~~y) - 14 * (x &&& y) =  - 1 *  ~~~(x ^^^ y)

theorem test20_proof : test20_before ⊑ test20_after

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 t4_ugt_slt_65536_proof : t4_ugt_slt_65536_before ⊑ t4_ugt_slt_65536_after

theorem masked_or_A_slightly_optimized_proof : masked_or_A_slightly_optimized_before ⊑ masked_or_A_slightly_optimized_after

theorem trunc_lshr_big_mask_proof : trunc_lshr_big_mask_before ⊑ trunc_lshr_big_mask_after

theorem sle_smax4_proof : sle_smax4_before ⊑ sle_smax4_after

theorem add_eq (x : BitVec w) : x = x + 0

theorem mul_add_to_mul_6_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1.smulOverflow x = true ∨
        True ∧ x_1.smulOverflow x = true ∨
          True ∧ (x_1 * x).smulOverflow 5#32 = true ∨ True ∧ (x_1 * x).saddOverflow (x_1 * x * 5#32) = true) →
    ¬(True ∧ x_1.smulOverflow x = true ∨ True ∧ (x_1 * x).smulOverflow 6#32 = true) →
      x_1 * x + x_1 * x * 5#32 = x_1 * x * 6#32

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

theorem ashrslt_03_09_thm (e : IntW 4) : icmp IntPred.slt (ashr e (const? 4 3)) (const? 4 (-7)) ⊑ const? 1 0

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

theorem test_with_3_proof : test_with_3_before ⊑ test_with_3_after

theorem lshr_and_add_proof : lshr_and_add_before ⊑ lshr_and_add_after

@[simp]
lemma eval_scanAnd_succ (x : Unit → BitStream) (n : Nat) :
    (scanAnd.eval x (n+1)) = ((scanAnd.eval x n) && (x () (n+1)))

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_1b_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 14#32 == 0#32) = 1#1 →
    ofBool (x &&& 3#32 != 1#32) = ofBool (x &&& 14#32 == 0#32) ||

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

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 and_xor_or1_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 64),
  ¬(x_2 = 0 ∨ x_1 = 0 ∨ x = 0 ∨ x_1 = 0) →
    ¬(x = 0 ∨ x_1 = 0) → 42#64 / x_2 &&& 42#64 / x_1 ^^^ 42#64 / x ||

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

theorem trunc_shl_shl_infloop_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬(1#64 ≥ ↑64 ∨ 2#64 ≥ ↑64) → ¬3#32 ≥ ↑32 → truncate 32 (x <<< 1#64 <<< 2#64) = truncate 32 x <<< 3#32

theorem lshrult_01_15_proof : lshrult_01_15_before ⊑ lshrult_01_15_after

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

theorem trunc_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32), ofBool (x_2 <ᵤ x_1) = 1#1 → truncate 16 42#32 = 42#16

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

theorem test8_proof : test8_before ⊑ test8_after

theorem test1_thm.extracted_1._1 : ∀ (x : BitVec 61), zeroExtend 61 (truncate 41 x) = x &&& 2199023255551#61

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

theorem test3_thm.extracted_1._1 : ∀ (x : BitVec 32), True ∧ (x &&& 32#32 &&& 8#32 != 0) = true → False

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

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

theorem narrow_zext_ashr_keep_trunc2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 9),
  ¬(True ∧ (signExtend 64 x_1).saddOverflow (signExtend 64 x) = true ∨ 1#64 ≥ ↑64) →
    True ∧ (zeroExtend 16 x_1).saddOverflow (zeroExtend 16 x) = true ∨
        True ∧ (zeroExtend 16 x_1).uaddOverflow (zeroExtend 16 x) = true ∨ 1#16 ≥ ↑16 →
      False

theorem sub_select_zext_op_swapped_non_const_args_thm (e e_1 : IntW 6) (e_2 : IntW 1) :
  sub (zext 6 e_2) (select e_2 e_1 e) ⊑ select e_2 (sub (const? 6 1) e_1) (sub (const? 6 0) e)

theorem xor_common_op_commute0_proof : xor_common_op_commute0_before ⊑ xor_common_op_commute0_after

theorem or_sext_sext_thm.extracted_1._1 : ∀ (x : BitVec 4) (x_1 : BitVec 8),
  signExtend 16 x_1 ||

theorem n10_ugt_slt_proof : n10_ugt_slt_before ⊑ n10_ugt_slt_after

theorem test17_thm.extracted_1._1 : ∀ (x : BitVec 106),
  ¬3#106 ≥ ↑106 → ofBool (x >>> 3#106 == 1234#106) = ofBool (x &&& BitVec.ofInt 106 (-8) == 9872#106)

theorem width0 (w : Nat) (a : BitVec w) : (w ≤ 1) → (a + a = 0#w)

theorem shl1_trunc_sgt4_proof : shl1_trunc_sgt4_before ⊑ shl1_trunc_sgt4_after

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 ashr_ugt_0_proof : ashr_ugt_0_before ⊑ ashr_ugt_0_after

theorem select_icmp_ne_0_and_1073741824_and_not_8_proof : select_icmp_ne_0_and_1073741824_and_not_8_before ⊑ select_icmp_ne_0_and_1073741824_and_not_8_after

theorem ashrslt_02_07_exact_proof : ashrslt_02_07_exact_before ⊑ ashrslt_02_07_exact_after

theorem lshrugt_03_11_proof : lshrugt_03_11_before ⊑ lshrugt_03_11_after

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 n2_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → x ^^^ 1#1 = 1#1 → False

theorem mul_unkV_oddC_sge_proof : mul_unkV_oddC_sge_before ⊑ mul_unkV_oddC_sge_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_3_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_3_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_3_logical_after

theorem p_commutative0_proof : p_commutative0_before ⊑ p_commutative0_after

theorem ashrslt_02_15_proof : ashrslt_02_15_before ⊑ ashrslt_02_15_after

theorem test16_thm (e : IntW 16) :
  sext 32 (icmp IntPred.eq (LLVM.and e (const? 16 8)) (const? 16 8)) ⊑
    sext 32 (ashr (shl e (const? 16 12)) (const? 16 15))

theorem logic_or_logic_and_8_proof : logic_or_logic_and_8_before ⊑ logic_or_logic_and_8_after

theorem n7_proof : n7_before ⊑ n7_after

theorem add_nosignbit_shl_proof : add_nosignbit_shl_before ⊑ add_nosignbit_shl_after

@[simp]
lemma tru_or (c : Circuit α) :
  Circuit.tru ||

theorem e_2143 :
    3 * ( ~~~d &&& (e ^^^ f)) + 4 *  ~~~(e &&&  ~~~f) - 5 * (e &&&  ~~~f) + 7 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 4 * d + 4 *  ~~~(d &&& (e ^^^ f)) - 1 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 1 * (f ^^^ (d ||| e)) + 2 * (d ||| e) - 7 * ( ~~~f ||| (d ^^^ e)) + 11 *  ~~~(d &&& e) + 4 * ((d &&& e) |||  ~~~(e ||| f)) - 1 * (f ^^^  ~~~(d |||  ~~~e)) - 1 * (d |||  ~~~f) - 2 * (e &&&  ~~~(d ^^^ f)) - 1 * (f ^^^  ~~~(d &&& (e &&& f))) + 5 * ( ~~~d ||| (e ^^^ f)) - 1 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) + 1 * (e ^^^  ~~~(d &&& f)) + 5 * ((d &&& e) ^^^ (e |||  ~~~f)) + 2 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) - 1 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 3 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 *  ~~~f + 3 * (e ^^^  ~~~(d ||| (e &&& f))) - 3 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 3 * (e |||  ~~~(d |||  ~~~f)) + 1 * ((d ^^^ e) &&&  ~~~(d ^^^ f)) + 1 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) - 6 *  ~~~(d &&& ( ~~~e ||| f)) - 3 * ( ~~~f &&& (d ^^^ e)) - 2 *  ~~~(e ||| f) - 1 * (f &&& (d |||  ~~~e)) + 1 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) + 2 *  ~~~(d &&& (e ||| f)) - 11 * ( ~~~d ||| ( ~~~e &&& f)) - 1 * (d ^^^ f) + 1 * (f ^^^ (d ||| ( ~~~e ||| f))) - 1 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) - 2 * (e ^^^ (d &&& (e ||| f))) - 24 *  ~~~(d ||| (e ||| f)) + 7 *  ~~~(d ||| ( ~~~e ||| f)) - 19 *  ~~~( ~~~d ||| (e ||| f)) - 26 * ( ~~~d &&& ( ~~~e &&& f)) - 16 * ( ~~~d &&& (e &&& f)) - 12 * (d &&& ( ~~~e &&& f)) - 19 * (d &&& (e &&& f)) =  - 7 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 1 * ( ~~~e &&& (d ^^^ f))

theorem trunc_ashr_trunc_outofrange_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬25#32 ≥ ↑32 →
    25#32 ≥ ↑32 ∨
        True ∧ signExtend 32 (truncate 8 ((truncate 32 x).sshiftRight' 25#32)) ≠ (truncate 32 x).sshiftRight' 25#32 →
      False

theorem icmp_ne_sext_slt_allones_nofold_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (signExtend 32 (ofBool (x <ₛ -1#32)) != x) = ofBool (x != signExtend 32 (ofBool (x <ₛ -1#32)))

theorem test24_proof : test24_before ⊑ test24_after

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

theorem eq_umin1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 <ᵤ x) = 1#1 → ofBool (x == x_1) = ofBool (x_1 ≤ᵤ x)

theorem test12_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 <ᵤ x) &&& ofBool (x_1 ≤ᵤ x) = ofBool (x_1 <ᵤ x)

@[simp]
lemma BitVecs.transport_w {bvs : BitVecs n} : (BitVecs.transport f bvs).w = bvs.w

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

theorem positive_samevar_shlnsw_lshrexact_thm (e e_1 : IntW 8) :
  shl (lshr e_1 e { «exact» := true }) e { «nsw» := true, «nuw» := false } ⊑ e_1

theorem shl_trunc_bigger_lshr_thm (e : IntW 32) :
  shl (trunc 8 (lshr e (const? 32 5))) (const? 8 3) ⊑ LLVM.and (trunc 8 (lshr e (const? 32 2))) (const? 8 (-8))

theorem shl_and_thm.extracted_1._1 : ∀ (x : BitVec 8), ¬(x ≥ ↑8 ∨ x + 1#8 ≥ ↑8) → x ≥ ↑8 → False

theorem scalar_i32_shl_and_negC_eq_X_is_constant1_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → ofBool (12345#32 <<< x &&& BitVec.ofInt 32 (-8) == 0#32) = ofBool (12345#32 <<< x <ᵤ 8#32)

theorem test5_proof : test5_before ⊑ test5_after

theorem sge_or_not_max_commute_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 != 127#8) ||

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

theorem test15_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → ¬2#45 ≥ ↑45 → 3#45 <<< 2#45 = 12#45

theorem not_signbit_proof : not_signbit_before ⊑ not_signbit_after

theorem bitwise_and_logical_and_masked_icmp_allzeros_poison1_thm.extracted_1._6 : ∀ (x : BitVec 1)
  (x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 &&& x_1 == 0#32) = 1#1 →
    ¬ofBool (x_2 &&& (x_1 ||| 7#32) == 0#32) = 1#1 → 0#1 &&& ofBool (x_2 &&& 7#32 == 0#32) = 0#1

theorem icmp_equality_test_constant_samesign_proof : icmp_equality_test_constant_samesign_before ⊑ icmp_equality_test_constant_samesign_after

theorem ne_21_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(16#32 ≥ ↑32 ∨ 16#32 ≥ ↑32 ∨ 8#32 ≥ ↑32 ∨ 8#32 ≥ ↑32) →
    ¬(8#32 ≥ ↑32 ∨ 8#32 ≥ ↑32) →
      ofBool (truncate 8 (x_1 >>> 16#32) != truncate 8 (x >>> 16#32)) ||

theorem allSignBits_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(31#32 ≥ ↑32 ∨ 31#32 ≥ ↑32) →
    ¬ofBool (x_1 <ₛ 0#32) = 1#1 →
      x_2 &&& x_1.sshiftRight' 31#32 ||

theorem e_1086 :
     - 6 *  ~~~(z ^^^ t) - 11 *  ~~~z - 6 * t + 7 *  ~~~(z &&&  ~~~z) - 1 * (z |||  ~~~t) + 11 *  ~~~(z ||| t) + 10 *  ~~~(z |||  ~~~t) - 6 * (z &&&  ~~~t) =  - 6 * (z &&& t)

theorem test7_proof : test7_before ⊑ test7_after

theorem main15_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (0#16 ≤ₛ truncate 16 x) ||

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

theorem foo2_proof : foo2_before ⊑ foo2_after

theorem e_1878 :
     - 1 * (c &&& (a |||  ~~~b)) - 2 * (b ^^^ (a &&&  ~~~c)) + 3 * ( ~~~(a ||| b) ||| (b ^^^ c)) + 3 * (b ||| (a ^^^ c)) + 1 * (c ^^^  ~~~(a |||  ~~~b)) + 1 * (a ^^^ ( ~~~b ||| c)) - 5 * (b ^^^  ~~~(a |||  ~~~c)) + 1 * ( ~~~c &&&  ~~~(a ^^^ b)) - 1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) - 7 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) - 7 *  ~~~( ~~~a ||| (b ^^^ c)) + 11 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) - 1 * (a &&&  ~~~c) + 11 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) + 2 * (b &&& (a |||  ~~~c)) + 11 * (b ^^^ (a ||| (b &&& c))) - 3 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 2 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 4 *  ~~~(a &&& b) + 11 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) + 7 * (a ^^^ (b &&& c)) - 6 *  ~~~(a ^^^ b) + 4 *  ~~~(a ||| b) + 1 * ((a &&& b) ^^^ (b |||  ~~~c)) + 2 *  ~~~(a &&& c) - 5 * (b ^^^  ~~~(a &&& c)) - 3 * (b &&& (a ||| c)) - 1 * (b ^^^  ~~~(a ||| (b &&& c))) + 1 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 2 * (c &&&  ~~~(a &&& b)) + 1 *  ~~~(a ||| (b ^^^ c)) - 7 * (a &&& ( ~~~b ||| c)) + 11 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c))) - 7 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) - 5 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) + 5 * ((a &&& b) ||| (b ^^^ c)) + 4 * ( ~~~a &&& (b ^^^ c)) - 2 * ((a ^^^ b) &&&  ~~~(a ^^^ c)) + 1 *  ~~~(b |||  ~~~c) - 30 *  ~~~(a ||| (b ||| c)) - 19 *  ~~~(a ||| ( ~~~b ||| c)) - 14 *  ~~~( ~~~a ||| (b ||| c)) + 1 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 30 * ( ~~~a &&& ( ~~~b &&& c)) - 28 * ( ~~~a &&& (b &&& c)) - 41 * (a &&& ( ~~~b &&& c)) + 18 * (a &&& (b &&& c)) = 1 * (c ^^^ (a |||  ~~~b))

theorem ult_x_impliesT_eq_umax_todo_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 8),
  ofBool (x_1 <ᵤ x_2) = 1#1 → ofBool (-1#8 != x_1) = 1#1

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

theorem add_nuw_nsw_or_and_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ (x_1 ||| x).saddOverflow (x_1 &&& x) = true ∨ True ∧ (x_1 ||| x).uaddOverflow (x_1 &&& x) = true) →
    True ∧ x_1.saddOverflow x = true ∨ True ∧ x_1.uaddOverflow x = true → False

theorem icmp_eq_and_pow2_shl_pow2_negative3_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → zeroExtend 32 (ofBool (32#32 <<< x &&& 16#32 == 0#32)) = 1#32

theorem and_signbit_select_ashr_proof : and_signbit_select_ashr_before ⊑ and_signbit_select_ashr_after

theorem test2_thm (e : IntW 1) : LLVM.xor e e ⊑ const? 1 0

@[simp] theorem le_impure (e : EffectKind) : e ≤ impure

theorem and_two_ranges_to_mask_and_range_no_add_on_one_range_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ofBool (12#16 ≤ᵤ x) &&& (ofBool (x <ᵤ 16#16) ||| ofBool (28#16 ≤ᵤ x)) =
    ofBool (11#16 <ᵤ x &&& BitVec.ofInt 16 (-20))

theorem e_420 :
    3 *  ~~~(x &&&  ~~~x) - 1 *  ~~~y + 1 * (x ||| y) - 6 * x + 7 * (x |||  ~~~y) - 9 *  ~~~(x ||| y) - 4 * (x &&&  ~~~y) - 6 * (x &&& y) = 5 *  ~~~(x |||  ~~~y) - 1 * y

theorem sgt_swap_and_min_logical_proof : sgt_swap_and_min_logical_before ⊑ sgt_swap_and_min_logical_after

theorem lshrult_02_07_thm (e : IntW 4) : icmp IntPred.ult (lshr e (const? 4 2)) (const? 4 7) ⊑ const? 1 1

theorem test1_thm.extracted_1._1 : ∀ (x : BitVec 333),
  ¬70368744177664#333 = 0 → x % 70368744177664#333 = x &&& 70368744177663#333

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

theorem test14_thm (e e_1 : IntW 8) :
  LLVM.xor (icmp IntPred.eq e_1 e) (icmp IntPred.ne e e_1) ⊑ const? 1 1

theorem rem_euclid_wrong_sign_test_thm (e : IntW 32) :
  select (icmp IntPred.sgt (LLVM.srem e (const? 32 8)) (const? 32 0))
      (add (LLVM.srem e (const? 32 8)) (const? 32 8)) (LLVM.srem e (const? 32 8)) ⊑
    select (icmp IntPred.sgt (LLVM.srem e (const? 32 8)) (const? 32 0))
      (add (LLVM.srem e (const? 32 8)) (const? 32 8) { «nsw» := true, «nuw» := false })
      (LLVM.srem e (const? 32 8))

theorem lshr_ne_opposite_msb_proof : lshr_ne_opposite_msb_before ⊑ lshr_ne_opposite_msb_after

theorem not_and_and_or_no_or_commute2_and_proof : not_and_and_or_no_or_commute2_and_before ⊑ not_and_and_or_no_or_commute2_and_after

theorem t0_ult_slt_128_thm.extracted_1._8 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 + 16#32 <ᵤ 144#32) = 1#1 →
    ¬ofBool (x_1 <ₛ 128#32) = 1#1 →
      ¬ofBool (127#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ BitVec.ofInt 32 (-16)) = 1#1 → False

theorem t1_ult_slt_0_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.ult e_2 (const? 32 65536)) e_2 (select (icmp IntPred.slt e_2 (const? 32 0)) e_1 e) ⊑
    select (icmp IntPred.sgt e_2 (const? 32 65535)) e
      (select (icmp IntPred.slt e_2 (const? 32 0)) e_1 e_2)

theorem icmp_mul_nsw_slt_thm (e e_1 : IntW 8) :
  icmp IntPred.slt (mul e_1 (const? 8 7) { «nsw» := true, «nuw» := false })
      (mul e (const? 8 7) { «nsw» := true, «nuw» := false }) ⊑
    icmp IntPred.slt e_1 e

lemma env_to_bvs (φ : Formula) (ρ : Fin φ.arity → BitVec w) :
    let bvs : BitVecs φ.arity := ⟨w, List.Vector.ofFn fun k => ρ k⟩
    ρ = fun k => bvs.bvs.get k

theorem add_umax_simplify_thm.extracted_1._1 : ∀ (x : BitVec 37),
  ¬(True ∧ x.uaddOverflow 42#37 = true) → ¬ofBool (42#37 <ᵤ x + 42#37) = 1#1 → 42#37 = x + 42#37

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

theorem test_sub_nsw__all_are_safe_proof : test_sub_nsw__all_are_safe_before ⊑ test_sub_nsw__all_are_safe_after

theorem test14_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ x_1.saddOverflow 1#32 = true ∨
        True ∧ (x_1 + 1#32).saddOverflow ((x ||| BitVec.ofInt 32 (-1431655767)) ^^^ 1431655766#32) = true) →
    x_1 + 1#32 + ((x ||| BitVec.ofInt 32 (-1431655767)) ^^^ 1431655766#32) = x_1 - (x &&& 1431655766#32)

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

theorem e_170 :
     - 2 *  ~~~(x &&& y) - 11 * (x ||| y) + 9 *  ~~~(x ||| y) + 20 *  ~~~(x |||  ~~~y) + 20 * (x &&&  ~~~y) + 18 * (x &&& y) = 7 *  ~~~(x &&&  ~~~x)

theorem no_shift_xor_multiuse_or_thm (e e_1 : IntW 32) :
  mul (select (icmp IntPred.ne (const? 32 0) (LLVM.and e_1 (const? 32 4096))) e (LLVM.or e (const? 32 4096)))
      (LLVM.or e (const? 32 4096)) ⊑
    mul (LLVM.or e (LLVM.xor (LLVM.and e_1 (const? 32 4096)) (const? 32 4096))) (LLVM.or e (const? 32 4096))

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

theorem and_logic_and_logic_or_8_thm.extracted_1._8 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → ¬0#1 = 1#1 → x &&& x_1 = x_1 &&& x

theorem positive_sameconst_lshrexact_proof : positive_sameconst_lshrexact_before ⊑ positive_sameconst_lshrexact_after

theorem reassoc_add_nuw_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ x.uaddOverflow 4#32 = true ∨ True ∧ (x + 4#32).uaddOverflow 64#32 = true) →
    ¬(True ∧ x.uaddOverflow 68#32 = true) → x + 4#32 + 64#32 = x + 68#32

theorem eq_smin3_proof : eq_smin3_before ⊑ eq_smin3_after

theorem positive_with_extra_and_logical_thm.extracted_1._3 : ∀ (x : BitVec 1) (x_1 : BitVec 32),
  ¬(ofBool (x_1 + 128#32 <ᵤ 256#32) = 1#1 ∧ ofBool (-1#32 <ₛ x_1) = 1#1) → ofBool (x_1 <ᵤ 128#32) = 1#1 → 0#1 = x

theorem mul_of_udiv_fail_bad_remainder_proof : mul_of_udiv_fail_bad_remainder_before ⊑ mul_of_udiv_fail_bad_remainder_after

@[simp]
lemma BitVec.cons_ugt_iff {w} {bv1 bv2 : BitVec w} :
    ((BitVec.cons b2 bv2).ult (BitVec.cons b1 bv1)) ↔ (if b1 = b2 then bv2.ult bv1 else b1)

theorem not_and_and_or_not_or_or_commute4_proof : not_and_and_or_not_or_or_commute4_before ⊑ not_and_and_or_not_or_or_commute4_after

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

theorem sgt_smin1_proof : sgt_smin1_before ⊑ sgt_smin1_after

theorem test95_thm (e : IntW 32) :
  zext 32 (LLVM.or (LLVM.and (lshr (trunc 8 e) (const? 8 6)) (const? 8 2)) (const? 8 40)) ⊑
    zext 32 (LLVM.or (LLVM.and (lshr (trunc 8 e) (const? 8 6)) (const? 8 2)) (const? 8 40) { «disjoint» := true })
      { «nneg» := true }

theorem t7_proof : t7_before ⊑ t7_after

theorem or_basic_commuted_proof : or_basic_commuted_before ⊑ or_basic_commuted_after

theorem PR60818_eq_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (0#32 - x == x) = ofBool (x &&& 2147483647#32 == 0#32)

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

theorem select_xor_icmp_bad_5_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 != 0#32) = 1#1 → ofBool (x_1 == 0#32) = 1#1 → False

theorem ashr_can_be_lshr_2_proof : ashr_can_be_lshr_2_before ⊑ ashr_can_be_lshr_2_after

theorem zext_sub_thm.extracted_1._1 : ∀ (x : BitVec 8),
  BitVec.ofInt 16 (-5) - zeroExtend 16 x &&& zeroExtend 16 x = zeroExtend 16 (BitVec.ofInt 8 (-5) - x &&& x)

theorem p14_commutativity1_proof : p14_commutativity1_before ⊑ p14_commutativity1_after

theorem t0_proof : t0_before ⊑ t0_after

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

theorem exact_lshr_eq_noexactdiv_proof : exact_lshr_eq_noexactdiv_before ⊑ exact_lshr_eq_noexactdiv_after

theorem trunc_ashr_trunc_proof : trunc_ashr_trunc_before ⊑ trunc_ashr_trunc_after

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

theorem sub_ashr_or_i16_proof : sub_ashr_or_i16_before ⊑ sub_ashr_or_i16_after

theorem urem_i32_c_multiuse_thm (e : IntW 8) :
  add (zext 32 e) (urem (zext 32 e) (const? 32 10)) ⊑
    add (urem (zext 32 e) (const? 32 10)) (zext 32 e) { «nsw» := true, «nuw» := true }

theorem alive_283   : alive_283_src ⊑ alive_283_tgt

theorem test_and2_proof : test_and2_before ⊑ test_and2_after

theorem xor_ugt_2_thm (e e_1 e_2 : IntW 8) :
  icmp IntPred.ugt (add e_2 e_1) (LLVM.xor (add e_2 e_1) (LLVM.or (LLVM.and e (const? 8 63)) (const? 8 64))) ⊑
    icmp IntPred.ugt (add e_2 e_1)
      (LLVM.xor (add e_2 e_1) (LLVM.or (LLVM.and e (const? 8 63)) (const? 8 64) { «disjoint» := true }))

theorem and_or_not_not_commute4_proof : and_or_not_not_commute4_before ⊑ and_or_not_not_commute4_after

theorem sub_sel_op1_thm.extracted_1._2 : ∀ (x : BitVec 1),
  ¬x = 1#1 → ¬(True ∧ (42#32).ssubOverflow 41#32 = true) → 42#32 - 41#32 = zeroExtend 32 (x ^^^ 1#1)

theorem icmp_eq_select_proof : icmp_eq_select_before ⊑ icmp_eq_select_after

theorem sge_swap_or_max_proof : sge_swap_or_max_before ⊑ sge_swap_or_max_after

theorem positive_sameconst_thm (e : IntW 8) : shl (ashr e (const? 8 3)) (const? 8 3) ⊑ LLVM.and e (const? 8 (-8))

theorem foo2_proof : foo2_before ⊑ foo2_after

theorem test_and3_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x <ₛ x_1 &&& 2147483647#32) = 1#1 → ofBool (0#32 ≤ₛ x) = ofBool (x <ᵤ x_1 &&& 2147483647#32)

theorem mul_eleven'' (x : BitVec w) : 11 * x =
  x <<< (3 : ℕ) + x <<< (1 : ℕ) + x

theorem no_shift_xor_multiuse_cmp_xor_proof : no_shift_xor_multiuse_cmp_xor_before ⊑ no_shift_xor_multiuse_cmp_xor_after

theorem fold_ne_rhs_thm (e e_1 : IntW 8) :
  icmp IntPred.ne (LLVM.and (LLVM.xor e_1 (const? 8 123)) (shl (const? 8 (-1)) e)) (const? 8 0) ⊑
    icmp IntPred.ne (lshr (LLVM.xor e_1 (const? 8 123)) e) (const? 8 0)

theorem t4_const_after_fold_lshr_shl_ne_proof : t4_const_after_fold_lshr_shl_ne_before ⊑ t4_const_after_fold_lshr_shl_ne_after

theorem t14_x_is_one_proof : t14_x_is_one_before ⊑ t14_x_is_one_after

theorem no_shift_xor_multiuse_cmp_with_and_proof : no_shift_xor_multiuse_cmp_with_and_before ⊑ no_shift_xor_multiuse_cmp_with_and_after

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

theorem eq_21_proof : eq_21_before ⊑ eq_21_after

theorem test0_thm.extracted_1._1 : ∀ (x : BitVec 39), x &&& 0#39 = 0#39

theorem and_logic_and_logic_or_4_thm.extracted_1._7 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 &&& x_1 = 1#1 → x = 1#1 → ¬x_1 = 1#1 → x_1 = 0#1

theorem and_sel_op0_proof : and_sel_op0_before ⊑ and_sel_op0_after

theorem shl_and_add_proof : shl_and_add_before ⊑ shl_and_add_after

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

theorem add_umax_simplify2_proof : add_umax_simplify2_before ⊑ add_umax_simplify2_after

theorem e_1814 :
    5 * (b ^^^  ~~~(a &&& (b ||| c))) - 1 * ( ~~~(a ||| b) ||| (b ^^^ c)) + 2 * (a &&& (b ^^^ c)) + 3 *  ~~~(b |||  ~~~c) + 7 *  ~~~c + 7 * (b ^^^ (a |||  ~~~c)) + 1 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 2 * (b ^^^ (a ||| c)) + 2 * (b ^^^ ( ~~~a ||| (b ||| c))) + 1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 4 * (b ^^^ (a ||| (b &&& c))) - 1 * (c ^^^  ~~~(a ||| b)) - 11 * (b ^^^ (a &&& (b ^^^ c))) - 7 *  ~~~(a ^^^ (b ^^^ c)) + 2 * (b ||| (a &&& c)) - 6 *  ~~~( ~~~a ||| ( ~~~b &&& c)) + 11 * (b |||  ~~~(a ||| c)) + 1 * (c ^^^ (a &&& (b ||| c))) + 7 *  ~~~(b ||| c) - 3 * (c |||  ~~~(a |||  ~~~b)) + 4 * ( ~~~(a |||  ~~~b) |||  ~~~(b ^^^ c)) + 2 *  ~~~(b ^^^ c) - 1 * (b ^^^ (a ||| (b ||| c))) + 2 * (a |||  ~~~c) - 3 * (b ^^^ (a ||| ( ~~~b ||| c))) - 1 *  ~~~(a &&&  ~~~c) + 11 * ( ~~~a ||| (b &&& c)) - 2 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 5 *  ~~~(a ||| c) + 11 * (b ^^^ ( ~~~a &&& (b ||| c))) - 2 * (c ||| (a &&& b)) - 2 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) + 1 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) - 11 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 48 *  ~~~(a ||| (b ||| c)) - 26 *  ~~~(a ||| ( ~~~b ||| c)) - 18 *  ~~~( ~~~a ||| (b ||| c)) - 26 * ( ~~~a &&& ( ~~~b &&& c)) - 4 * ( ~~~a &&& (b &&& c)) + 19 * (a &&& ( ~~~b &&& c)) - 23 * (a &&& (b &&& c)) = 24 *  ~~~( ~~~a ||| ( ~~~b ||| c))

theorem test1_proof : test1_before ⊑ test1_after

theorem main6_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 == 3#32) = 1#1 →
    ofBool (x &&& 48#32 == 16#32) = 1#1 → 0#32 = zeroExtend 32 (ofBool (x &&& 55#32 != 19#32))

theorem main4b_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 == 7#32) &&& ofBool (x &&& 16#32 != 0#32) = 1#1 →
    0#32 = zeroExtend 32 (ofBool (x &&& 23#32 != 23#32))

theorem e_113 :
     - 5 *  ~~~(x ^^^ y) - 11 *  ~~~(x &&&  ~~~y) + 14 *  ~~~(x ||| y) + 9 *  ~~~(x |||  ~~~y) - 2 * (x &&&  ~~~y) + 14 * (x &&& y) =  - 2 *  ~~~(x &&&  ~~~x)

theorem fold_inverted_icmp_preds_reverse_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 <ₛ x_1) = 1#1 → ofBool (x_1 ≤ₛ x_2) = 1#1 → 0#32 ||

theorem fold_inverted_icmp_preds_reverse_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 <ₛ x_1) = 1#1 → ofBool (x_1 ≤ₛ x_2) = 1#1 → False

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

theorem udiv_eq_umax_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x = 0 → ofBool (x_1 / x == -1#8) = ofBool (x_1 == -1#8) &&& ofBool (x == 1#8)

theorem test8_proof : test8_before ⊑ test8_after

theorem or_test1_thm.extracted_1._1 : ∀ (x : BitVec 32), x &&& 1#32 ||

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

theorem udiv_common_dividend_defined_cond_thm (e e_1 e_2 : IntW 5) (e_3 : IntW 1) :
  select e_3 (LLVM.udiv e_2 e_1) (LLVM.udiv e_2 e) ⊑ LLVM.udiv e_2 (select e_3 e_1 e)

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

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

theorem lshrugt_02_14_proof : lshrugt_02_14_before ⊑ lshrugt_02_14_after

theorem and_two_ranges_to_mask_and_range_not_pow2_diff_proof : and_two_ranges_to_mask_and_range_not_pow2_diff_before ⊑ and_two_ranges_to_mask_and_range_not_pow2_diff_after

theorem sgt_or_not_min_proof : sgt_or_not_min_before ⊑ sgt_or_not_min_after

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

theorem lshr_32_add_not_known_32_leading_zeroes_proof : lshr_32_add_not_known_32_leading_zeroes_before ⊑ lshr_32_add_not_known_32_leading_zeroes_after

theorem test2_thm.extracted_1._1 : ∀ (x : BitVec 49),
  ¬(11#49 ≥ ↑49 ∨ 4096#49 <<< 11#49 = 0) → x % 4096#49 <<< 11#49 = x &&& 8388607#49

theorem sext_true_val_must_be_all_ones_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → signExtend 32 x = -1#32

theorem test13_thm (e : IntW 1024) :
  LLVM.and (ashr e (const? 1024 1016)) (const? 1024 255) ⊑ lshr e (const? 1024 1016)

theorem lshrult_03_01_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬3#4 ≥ ↑4 → ofBool (x >>> 3#4 <ᵤ 1#4) = ofBool (-1#4 <ₛ x)

theorem icmp_slt_0_or_icmp_sgt_0_i64_thm.extracted_1._1 : ∀ (x : BitVec 64),
  zeroExtend 64 (ofBool (x <ₛ 0#64)) ||

theorem e_938 :
    11 *  ~~~(z &&& t) + 4 *  ~~~(z &&&  ~~~t) + 3 * (z ||| t) - 26 *  ~~~(z ||| t) - 25 * (z &&&  ~~~t) - 7 * (z &&& t) = 18 *  ~~~(z |||  ~~~t) - 11 *  ~~~t

theorem e_799 :
     - 1 *  ~~~(z &&&  ~~~t) + 11 * z + 3 *  ~~~t - 12 * (z &&&  ~~~t) - 9 * (z &&& t) = 2 * (z |||  ~~~t) - 1 * t

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

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 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 test7_thm (e : IntW 77) : sub (const? 77 (-1)) e ⊑ LLVM.xor e (const? 77 (-1))

theorem test_sext_proof : test_sext_before ⊑ test_sext_after

theorem e_1553 :
     - 6 *  ~~~(a ^^^ c) - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 5 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) - 1 * (b ||| (a ^^^ c)) - 1 *  ~~~( ~~~a &&& ( ~~~b ||| c)) + 5 * ( ~~~a &&& (b ||| c)) - 5 * ((a &&& c) ||| (b &&&  ~~~c)) + 12 *  ~~~(a ||| (b ||| c)) + 8 *  ~~~(a ||| ( ~~~b ||| c)) + 8 *  ~~~( ~~~a ||| (b ||| c)) + 8 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 3 * ( ~~~a &&& (b &&& c)) + 13 * (a &&& ( ~~~b &&& c)) + 14 * (a &&& (b &&& c)) =  - 2 * ( ~~~a &&& ( ~~~b &&& c)) + 1 *  ~~~(a ^^^ b)

theorem ashr_1_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  ¬x_3 = 1#1 → ¬x ≥ ↑8 → (x_1 ^^^ 123#8).sshiftRight' x ^^^ -1#8 = (x_1 ^^^ BitVec.ofInt 8 (-124)).sshiftRight' x

lemma RawCNFA.Simul.rel_preserved_letter {m : RawCNFA A} {M : NFA A Q} (hsim : m.Simul M R ⊤ ∅) :
    R.set_eq S₁ Q₁ → ∃ S₂, R.set_eq S₂ (M.stepSet Q₁ a)

theorem C0zero_thm.extracted_1._4 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 + 10#8 <ᵤ 0#8) = 1#1 → ¬ofBool (x_1 <ₛ BitVec.ofInt 8 (-10)) = 1#1 → False

theorem badimm2_thm (e : IntW 16) :
  select (icmp IntPred.eq (ashr (trunc 8 e) (const? 8 6)) (trunc 8 (lshr e (const? 16 8)))) (trunc 8 e)
      (LLVM.xor (trunc 8 (ashr e (const? 16 15))) (const? 8 127)) ⊑
    select
      (icmp IntPred.eq (ashr (trunc 8 e) (const? 8 6))
        (trunc 8 (lshr e (const? 16 8)) { «nsw» := false, «nuw» := true }))
      (trunc 8 e) (select (icmp IntPred.sgt e (const? 16 (-1))) (const? 8 127) (const? 8 (-128)))

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

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

theorem a_false_implies_b_true_thm (e e_1 : IntW 1) (e_2 : IntW 8) :
  select (icmp IntPred.ugt e_2 (const? 8 10)) (const? 1 1)
      (select (icmp IntPred.ult e_2 (const? 8 20)) e_1 e) ⊑
    select (icmp IntPred.ugt e_2 (const? 8 10)) (const? 1 1) e_1

theorem negative_with_wrong_mask_logical_proof : negative_with_wrong_mask_logical_before ⊑ negative_with_wrong_mask_logical_after

theorem sub_ashr_or_i8_thm (e e_1 : IntW 8) :
  LLVM.or (ashr (sub e_1 e { «nsw» := true, «nuw» := false }) (const? 8 7)) e ⊑
    select (icmp IntPred.slt e_1 e) (const? 8 (-1)) e

theorem slt_zero_ult_i1_fail1_proof : slt_zero_ult_i1_fail1_before ⊑ slt_zero_ult_i1_fail1_after

theorem main3_proof : main3_before ⊑ main3_after

theorem lshr_C1_add_A_C2_i32_thm (e : IntW 32) :
  shl (const? 32 6) (add (LLVM.and e (const? 32 65535)) (const? 32 5)) ⊑
    shl (const? 32 192) (LLVM.and e (const? 32 65535))

theorem masked_or_allzeroes_notoptimised_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 15#32 == 0#32) = 1#1 →
    ofBool (x &&& 39#32 == 0#32) = ofBool (x &&& 15#32 == 0#32) ||

theorem main5f_like_logical_thm.extracted_1._9 : ∀ (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 ashrsgt_01_02_exact_proof : ashrsgt_01_02_exact_before ⊑ ashrsgt_01_02_exact_after
</all_available_lemmas>

<local_ctx>
import Batteries.Data.Fin.Basic

import Batteries.Data.Fin.Lemmas

import Blase.SingleWidth.Defs

import Blase.AutoStructs.Constructions

import Blase.AutoStructs.Defs

import Blase.AutoStructs.FiniteStateMachine

import Mathlib.Tactic.Ring

import Mathlib.Data.Nat.Size -- TODO: remove and get rid of shiftLeft_eq_mul_pow use

import Mathlib.Data.BitVec

import Mathlib.Tactic.FinCases

open Fin.NatCast

open Mathlib

def NFA.sa (_ : NFA α σ) := σ → Language α

structure NFA.correct (M : NFA α σ) (ζ : M.sa) (L : Language α) where
  cond1 : ∀ w, (w ∈ L ↔ ∃ q ∈ M.accept, w ∈ ζ q)
  cond2 : ∀ w q, q ∈ M.eval w ↔ w ∈ ζ q

abbrev 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 liftOp n : Fin (n + 1) → Fin (n + 3) :=
  fun k =>
    if k = n then Fin.last (n+2) else k.castLE (by admit /- proof elided -/
    )

@[simp]
def liftOp_unchanged (k : Fin n) : liftOp n k.castSucc = k.castLE (by simp) :=

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

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

def TermBinop.subst (op : TermBinop) (t₁ t₂ : Term) : Term :=
  match op with
  | .and => .and t₁ t₂
  | .or => .or t₁ t₂
  | .xor => .xor t₁ t₂
  | .add => .add t₁ t₂
  | .sub => .sub t₁ t₂

def TermBinop.openTerm (op : TermBinop) : Term := op.subst (.var 0) (.var 1)

@[simp]
def TermBinop.openTerm_arity (op : TermBinop) : op.openTerm.arity + 1 = 3 :=

def TermBinop.termGadget (t : TermBinop) : CNFA 3 :=
  match t with
  | .and => FSM.ofTerm (.and (.var 0) (.var 1)) |> CNFA.ofFSM
  | .or => FSM.ofTerm (.or (.var 0) (.var 1)) |> CNFA.ofFSM
  | .xor => FSM.ofTerm (.xor (.var 0) (.var 1)) |> CNFA.ofFSM
  | .add => FSM.ofTerm (.add (.var 0) (.var 1)) |> CNFA.ofFSM
  | .sub => FSM.ofTerm (.sub (.var 0) (.var 1)) |> CNFA.ofFSM

def autOfTermBinop (op : TermBinop) (m₁ : CNFA (n + 1)) (m₂ : CNFA (m + 1)) : CNFA ((n ⊔ m) + 1 ) :=
  let mop : CNFA 3 := op.termGadget
  let f₁ := liftMaxSuccSucc1 n m
  let m1' := m₁.lift f₁
  let f₂ := liftMaxSuccSucc2 n m
  let m2' := m₂.lift f₂
  let mop := mop.lift $ liftLast3 (max (FinEnum.card (Fin n)) (FinEnum.card (Fin m)))
  let m := CNFA.inter m1' m2' |> CNFA.inter mop
  let mfinal := m.proj (liftOp _)
  mfinal.minimize

def swapLastTwoBlock (x : Fin (n + 3)) : Fin (n + 3) :=
  if x = Fin.last (n+2) then n
  else if x = n+1 then Fin.last (n + 2)
  else if x = n then n + 1
  else x

inductive TermUnop where
| neg | not | shiftL (k : Nat)

def TermUnop.openTerm (op : TermUnop) : Term :=
  match op with
  | .neg => .neg (.var 0)
  | .not => .not (.var 0)
  | .shiftL k => .shiftL (.var 0) k

def TermUnop.openTerm_arity (op : TermUnop) : op.openTerm.arity = 1 :=

@[simp]
def TermUnop.openTerm_arity' (op : TermUnop) : op.openTerm.arity + 1 = 2 :=

def TermUnop.subst (op : TermUnop) (t : Term) : Term :=
  match op with
  | .neg => .neg t
  | .not => .not t
  | .shiftL k => .shiftL t k

def TermUnop.termGadget (t : TermUnop) : CNFA 2 :=
  match t with
  | .neg => FSM.ofTerm (.neg (.var 0)) |> CNFA.ofFSM
  | .not => FSM.ofTerm (.not (.var 0)) |> CNFA.ofFSM
  | .shiftL k => FSM.ofTerm (.shiftL (.var 0) k) |> CNFA.ofFSM

def autOfTermUnop (op : TermUnop) (m : CNFA (n + 1)) : CNFA (n + 1) :=
  let mop : CNFA 2 := op.termGadget
  let mop : CNFA (n + 2) := mop.lift (λ i ↦ i.natAdd n)
  let m : CNFA (n + 2) := m.lift (λ i ↦ i.castLE (by admit /- proof elided -/
  ))
  let m := CNFA.inter m mop
  let mfinal := m.proj (liftUnop n)
  mfinal.minimize

def nfaOfTerm (t : Term) : CNFA (t.arity + 1) :=
  match t with
  | .var n => FSM.ofTerm (.var n) |> CNFA.ofFSM
  | .zero => FSM.ofTerm .zero |> CNFA.ofFSM
  | .negOne => FSM.ofTerm .negOne |> CNFA.ofFSM
  | .one => FSM.ofTerm .one |> CNFA.ofFSM
  | .ofNat n => FSM.ofTerm (.ofNat n) |> CNFA.ofFSM
  | .and t₁ t₂ => autOfTermBinop .and (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .or t₁ t₂ => autOfTermBinop .or (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .xor t₁ t₂ => autOfTermBinop .xor (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .add t₁ t₂ => autOfTermBinop .add (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .sub t₁ t₂ => autOfTermBinop .sub (nfaOfTerm t₁) (nfaOfTerm t₂)
  | .neg t => autOfTermUnop .neg (nfaOfTerm t)
  | .not t => autOfTermUnop .not (nfaOfTerm t)
  | .shiftL t k => autOfTermUnop (.shiftL k) (nfaOfTerm t)

def swapLastTwo (x : Fin (n + 2)) : Fin (n + 2) :=
  if x = Fin.last (n + 1) then n else if x = n then Fin.last (n + 1) else x
</local_ctx>

<target_theorem>
lemma nfaOfTerm_bv_language (t : Term) :
    nfaOfTerm t |>.bv_recognizes t.language :=
</target_theorem>

