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

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

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

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

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

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

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

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

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

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

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

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

open Set
open Mathlib
open SetRel

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

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

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

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

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

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

@[simp]
</local_ctx>

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

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

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

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

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

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

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

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

### Your task:
<all_available_defs>
Vector in Init.Data.Vector.Basic
Fin in Init.Prelude
String in Init.Prelude
Unit in Init.Prelude
List in Init.Prelude
Field in Mathlib.Algebra.Field.Defs
Bool in Init.Prelude
DecidableEq in Init.Prelude
FinEnum in Mathlib.Data.FinEnum
Hashable in Init.Prelude
Sum in Init.Core
Sum.elim in Init.Data.Sum.Basic
Sum.inl in Init.Core
Sum.inr in Init.Core
Nat in Init.Prelude
Repr in Init.Data.Repr
Inhabited in Init.Prelude
Lean.ToExpr in Lean.ToExpr
Nat.max in Init.Data.Nat.Basic
Nat.min in Init.Data.Nat.Basic
BitVec in Init.Prelude
BitVec.ofBool in Init.Data.BitVec.Basic
BitVec.ofNat in Init.Prelude
Int.xor in Mathlib.Data.Int.Bitwise
Nat.testBit in Init.Data.Nat.Bitwise.Basic
Empty in Init.Prelude
Empty.elim in Init.Core

syntax "min" : MLIR.Pretty.uniform_op

syntax "slt" : 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 composeBinaryAux'
    (p : FSM Bool)
    (qtrue : FSM α)
    (qfalse : FSM α) :
    FSM α :=
  p.compose (α)
    (λ _ => α)
    (λ _ i => i)
    (λ b => match b with
      | true => qtrue
      | false => qfalse)

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 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 latchImmediate (initVal : Bool) : FSM Bool where
  α := Unit
  initCarry := fun _ => initVal
  outputCirc :=
    let xval := Circuit.var true (inr false)
    let control := Circuit.var true (inr true)
    let state := Circuit.var true (inl ())
    Circuit.ite control xval state
  nextStateCirc := fun () =>
    let xval := Circuit.var true (inr false)
    let control := Circuit.var true (inr true)
    let state := Circuit.var true (inl ())
    Circuit.ite control xval state

def ite (cond t f : Circuit α) : Circuit α :=
  (cond &&& t) ||| (~~~ cond &&& f)

inductive Term
| ofNat (w : WidthExpr) (n : Nat) : Term
| var (v : Nat) (w : WidthExpr) : Term
| add (w : WidthExpr) (a b : Term) : Term
| zext (a : Term) (wnew : WidthExpr) : Term
| setWidth (a : Term) (wnew : WidthExpr) : Term
| sext (a : Term) (wnew : WidthExpr) : Term
| bor (w : WidthExpr) (a b : Term) : Term
| band (w : WidthExpr) (a b : Term) : Term
| bxor (w : WidthExpr) (a b : Term) : Term
| bnot (w : WidthExpr)  (a : Term) : Term
| mul (w : WidthExpr) (a b : Term) : Term
| udiv (w : WidthExpr) (a b : Term) : Term
| umod (w : WidthExpr) (a b : Term) : Term
| boolVar (v : Nat) : Term
| boolConst (b : Bool) : Term
| shiftl (w : WidthExpr) (a : Term) (k : Nat) : Term
| junk (s : String)  : Term 
deriving DecidableEq, Inhabited, Repr, Lean.ToExpr

structure TermFSM (wcard tcard bcard ncard icard pcard : Nat) (t : Nondep.Term) where
  toFsmZext : FSM (StateSpace wcard tcard bcard ncard icard pcard)
  width : NatFSM wcard tcard bcard ncard icard pcard t.width

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

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

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

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

def 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

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

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

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

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

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

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

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

def BitStream : Type := Nat → Bool

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

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

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

def Term.BoolEnv (bcard : Nat) : Type := Fin bcard → Bool

def Term.IntEnv (icard : Nat) : Type := Fin icard → Nat

abbrev ofBitVecZext {w} (x : BitVec w) : BitStream :=
  fun i => x.getLsbD i

structure HTermFSMToBitStream {w : WidthExpr wcard}
  {tctx : Term.Ctx wcard tcard}
  {t : Term bcard ncard icard pcard tctx (.bv w)}
  (fsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm t)) : Prop where
  heq :
    ∀ {wenv : WidthExpr.Env wcard}
      (benv : Term.BoolEnv bcard)
      (nenv : Term.NatEnv ncard)
      (ienv : Term.IntEnv icard)
      (penv : Predicate.Env pcard) (tenv : tctx.Env wenv)
      (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream),
      (henv : HTermEnv fsmEnv tenv benv) →
        fsm.toFsmZext.eval fsmEnv =
        BitStream.ofBitVecZext (t.toBV benv nenv ienv penv tenv)

def Predicate.Env (pcard : Nat) : Type :=
  Fin pcard → Prop

inductive TermKind (wcard : Nat) : Type
| bool
| bv (w : WidthExpr wcard)  : TermKind wcard
| prop
| nat
| int

structure HTermEnv {wcard tcard bcard : Nat}
    {wenv : Fin wcard → Nat} {tctx : Term.Ctx wcard tcard}
    (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream)
    (tenv : tctx.Env wenv)
    (benv : Term.BoolEnv bcard) : Prop
  extends HWidthEnv fsmEnv wenv where
    heq_term : ∀ (v : Fin tcard),
      fsmEnv (StateSpace.termVar v) = BitStream.ofBitVecZext (tenv v)
    heq_bool : ∀ (v : Fin bcard),
      fsmEnv (StateSpace.boolVar v) = BitStream.ofBool (benv v)

noncomputable def BitStream.ofBool (b : Bool) : BitStream := fun _i => b

abbrev Term.Ctx.Env
  (tctx : Term.Ctx wcard tcard)
  (wenv : WidthExpr.Env wcard) :=
  (v : Fin tcard) → BitVec ((tctx v).toNat wenv)

def Term.NatEnv (ncard : Nat) : Type := Fin ncard → Nat

def Term.toBV {wenv : WidthExpr.Env wcard}
    {tctx : Term.Ctx wcard tcard}
    (benv : Term.BoolEnv bcard)
    (nenv : Term.NatEnv ncard)
    (ienv : Term.IntEnv icard)
    (penv : Predicate.Env pcard)
    (tenv : tctx.Env wenv)
    (t : Term bcard ncard icard pcard tctx k) : k.denote wenv :=
match t with
| .ofNat w n => BitVec.ofNat (w.toNat wenv) n
| .boolConst b => b
| .var v => tenv.get v.1 v.2
| .add (w := w) a b =>
    let a : BitVec (w.toNat wenv) := (a.toBV benv nenv ienv penv tenv)
    let b : BitVec (w.toNat wenv) := (b.toBV benv nenv ienv penv tenv)
    a + b
| .zext a v => (a.toBV benv nenv ienv penv tenv).zeroExtend (v.toNat wenv)
| .setWidth a v => (a.toBV benv nenv ienv penv tenv).zeroExtend (v.toNat wenv)
| .sext a v => (a.toBV benv nenv ienv penv tenv).signExtend (v.toNat wenv)
| .bor a b (w := w) =>
    let a : BitVec (w.toNat wenv) := (a.toBV benv nenv ienv penv tenv)
    let b : BitVec (w.toNat wenv) := (b.toBV benv nenv ienv penv tenv)
    a ||| b
| .band (w := w) a b =>
    let a : BitVec (w.toNat wenv) := (a.toBV benv nenv ienv penv tenv)
    let b : BitVec (w.toNat wenv) := (b.toBV benv nenv ienv penv tenv)
    a &&& b
| .bxor (w := w) a b =>
    let a : BitVec (w.toNat wenv) := (a.toBV benv nenv ienv penv tenv)
    let b : BitVec (w.toNat wenv) := (b.toBV benv nenv ienv penv tenv)
    a ^^^ b
| .bnot (w := w) a =>
    let a : BitVec (w.toNat wenv) := (a.toBV benv nenv ienv penv tenv)
    ~~~ a
| .boolVar v => benv v
| .shiftl (w := w) a k =>
    let a : BitVec (w.toNat wenv) := (a.toBV benv nenv ienv penv tenv)
    a <<< k
| .bvOfBool b => BitVec.ofBool (b.toBV benv nenv ienv penv tenv)

| .binWidthRel rel wa wb =>
  match rel with
  | .eq => wa.toNat wenv = wb.toNat wenv
  | .le => wa.toNat wenv ≤ wb.toNat wenv
| .binRel rel _w a b =>
  match rel with
  | .eq => a.toBV benv nenv ienv penv tenv = b.toBV benv nenv ienv penv tenv
  | .ne => a.toBV benv nenv ienv penv tenv ≠ b.toBV benv nenv ienv penv tenv
  | .ult => (a.toBV benv nenv ienv penv tenv).ult (b.toBV benv nenv ienv penv tenv) = true
  | .ule => (a.toBV benv nenv ienv penv tenv).ule (b.toBV benv nenv ienv penv tenv) = true
  | .slt => (a.toBV benv nenv ienv penv tenv).slt (b.toBV benv nenv ienv penv tenv) = true
  | .sle => (a.toBV benv nenv ienv penv tenv).sle (b.toBV benv nenv ienv penv tenv) = true
| .and p1 p2 => p1.toBV benv nenv ienv penv tenv  ∧ p2.toBV benv nenv ienv penv tenv
| .or p1 p2 => p1.toBV benv nenv ienv penv tenv ∨ p2.toBV benv nenv ienv penv tenv
| .boolBinRel rel a b =>
  match rel with
  
  | .eq => (a.toBV benv nenv ienv penv tenv) = (b.toBV benv nenv ienv penv tenv)
| .pvar v => penv v

inductive Term {wcard tcard : Nat} (bcard : Nat) (ncard : Nat) (icard : Nat) (pcard : Nat)
  (tctx : Term.Ctx wcard tcard) : TermKind wcard → Type

| ofNat (w : WidthExpr wcard) (n : Nat) : Term bcard ncard icard pcard tctx (.bv w)
 
| var (v : Fin tcard) : Term bcard ncard icard pcard tctx (.bv (tctx v))
 
| add (a : Term bcard ncard icard pcard tctx (.bv w))
  (b : Term bcard ncard icard pcard tctx (.bv w)) : Term bcard ncard icard pcard tctx (.bv w)
 
| shiftl (a : Term bcard ncard icard pcard tctx (.bv w)) (k : Nat) : Term bcard ncard icard pcard tctx (.bv w)
 
| bor (a b : Term bcard ncard icard pcard tctx (.bv w)) : Term bcard ncard icard pcard tctx (.bv w)
 
| band (a b : Term bcard ncard icard pcard tctx (.bv w)) : Term bcard ncard icard pcard tctx (.bv w)
 
| bxor (a b : Term bcard ncard icard pcard tctx (.bv w)) : Term bcard ncard icard pcard tctx (.bv w)
 
| bnot (a : Term bcard ncard icard pcard tctx (.bv w)) : Term bcard ncard icard pcard tctx (.bv w)
 
| zext (a : Term bcard ncard icard pcard tctx (.bv w)) (v : WidthExpr wcard) : Term bcard ncard icard pcard tctx (.bv v)
 
| setWidth (a : Term bcard ncard icard pcard tctx (.bv w)) (v : WidthExpr wcard) : Term bcard ncard icard pcard tctx (.bv v)
 
| sext (a : Term bcard ncard icard pcard tctx (.bv w)) (v : WidthExpr wcard) : Term bcard ncard icard pcard tctx (.bv v)
 
| bvOfBool (b : Term bcard ncard icard pcard tctx .bool) : Term bcard ncard icard pcard tctx (.bv (.const 1))

| boolConst (b : Bool) : Term bcard ncard icard pcard tctx .bool
| boolVar (v : Fin bcard) : Term bcard ncard icard pcard tctx .bool
| binWidthRel (k : WidthBinaryRelationKind) (wa wb : WidthExpr wcard) :
    Term bcard ncard icard pcard tctx .prop
| binRel
    (k : BinaryRelationKind)
    (w : WidthExpr wcard)
    (a : Term bcard ncard icard pcard tctx (.bv w))
    (b : Term bcard ncard icard pcard tctx (.bv w)) :
    Term bcard ncard icard pcard tctx .prop
| and (p1 p2 : Term bcard ncard icard pcard tctx (.prop)) : Term bcard ncard icard pcard tctx (.prop)
| or (p1 p2 : Term bcard ncard icard pcard tctx (.prop)) : Term bcard ncard icard pcard tctx (.prop)
| pvar (v : Fin pcard) : Term bcard ncard icard pcard tctx (.prop)

| boolBinRel
  (k : BoolBinaryRelationKind)
  (a b : Term bcard ncard icard pcard tctx .bool) :
  Term bcard ncard icard pcard tctx (.prop)

def Term.Ctx.Env.get {tcard : Nat}
  {wcard : Nat} {wenv : Fin wcard → Nat}
  {tctx : Term.Ctx wcard tcard}
  (tenv : tctx.Env wenv) (i : Nat) (hi : i < tcard) :
  BitVec ((tctx ⟨i, hi⟩).toNat wenv) :=
  tenv ⟨i, hi⟩

inductive BinaryRelationKind
| eq
| ne
| ule
| slt
| sle
| ult 
deriving DecidableEq, Repr, Inhabited, Lean.ToExpr

inductive WidthBinaryRelationKind
| eq
| le

deriving DecidableEq, Repr, Inhabited, Lean.ToExpr

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 Term.eval (t : Term) (vars : List BitStream) : BitStream :=
  match t with
  | var n       => vars.getD n default
  | zero        => BitStream.zero
  | one         => BitStream.one
  | negOne      => BitStream.negOne
  | ofNat n     => BitStream.ofNat n
  | and t₁ t₂   => (t₁.eval vars) &&& (t₂.eval vars)
  | or t₁ t₂    => (t₁.eval vars) ||| (t₂.eval vars)
  | xor t₁ t₂   => (t₁.eval vars) ^^^ (t₂.eval vars)
  | not t       => ~~~(t.eval vars)
  | add t₁ t₂   => (Term.eval t₁ vars) + (Term.eval t₂ vars)
  | sub t₁ t₂   => (Term.eval t₁ vars) - (Term.eval t₂ vars)
  | neg t       => -(Term.eval t vars)

| shiftL t n  => BitStream.shiftLeft (Term.eval t vars) n

def Predicate.eval (p : Predicate) (vars : List 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
  | lor p q => Predicate.evalLor (p.eval vars) (q.eval vars)
  | land p q => Predicate.evalLand (p.eval vars) (q.eval vars)
  | binary .eq t₁ t₂ => Predicate.evalEq (t₁.eval vars) (t₂.eval vars)
   
  | binary .neq t1 t2 => Predicate.evalNeq (t1.eval vars) (t2.eval vars)
  | binary .ult t₁ t₂ => Predicate.evalUlt (t₁.eval vars) (t₂.eval vars)
  | binary .ule t₁ t₂ =>
     Predicate.evalLor
       (Predicate.evalEq (t₁.eval vars) (t₂.eval vars))
       (Predicate.evalUlt (t₁.eval vars) (t₂.eval vars))
  | binary .slt t₁ t₂ => Predicate.evalSlt (t₁.eval vars) (t₂.eval vars)
  | binary .sle t₁ t₂ => Predicate.evalLor
       (Predicate.evalEq (t₁.eval vars) (t₂.eval vars))
       (Predicate.evalSlt (t₁.eval vars) (t₂.eval vars))

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

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.evalLor (t₁ t₂ : BitStream) : BitStream := (t₁ &&& t₂)

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

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

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

abbrev falseIffLt (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)

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

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 and : FSM Bool :=
  { α := Empty,
    initCarry := Empty.elim,
    nextStateCirc := fun a => a.elim,
    outputCirc := Circuit.var true (inr true) &&& Circuit.var true (inr false),
  }

def bools_logical_commute0_and1_and2_before := [llvm|
{
^0(%arg99 : i1, %arg100 : i1, %arg101 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg101, %0 : i1
  %2 = llvm.and %1, %arg99 : i1
  %3 = llvm.and %arg101, %arg100 : i1
  %4 = "llvm.select"(%2, %0, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def sub_select_sext_after := [llvm|
{
^0(%arg24 : i1, %arg25 : i64):
  %0 = llvm.mlir.constant(65) : i64
  %1 = "llvm.select"(%arg24, %0, %arg25) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%1) : (i64) -> ()
}
]

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

reduceDIte in Lean.Meta.Tactic.Simp.BuiltinSimprocs.Core

def llvm_add_lower_riscv_nuw_nsw_flag_32 : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)]
where
  lhs:= add_llvm_nsw_nuw_flags_32
  rhs:= add_riscv_32

def not_xor_to_or_not2_before := [llvm|
{
^0(%arg36 : i3, %arg37 : i3, %arg38 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg38, %arg37 : i3
  %2 = llvm.and %arg36, %arg38 : i3
  %3 = llvm.xor %2, %1 : i3
  %4 = llvm.xor %3, %0 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

private def attrVal10Float : AttrVal := [mlir_attr_val| 0.0023 ]

def ashr_bitwidth_mask_before := [llvm|
{
^0(%arg127 : i8, %arg128 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.ashr %arg127, %0 : i8
  %2 = llvm.and %1, %arg128 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def test_zext_nneg_before := [llvm|
{
^0(%arg25 : i32, %arg26 : i64, %arg27 : i64):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(-5) : i64
  %2 = llvm.xor %arg25, %0 : i32
  %3 = llvm.zext nneg %2 : i32 to i64
  %4 = llvm.add %arg26, %1 : i64
  %5 = llvm.add %3, %arg27 : i64
  %6 = llvm.sub %4, %5 : i64
  "llvm.return"(%6) : (i64) -> ()
}
]

def and_xor_or7_after := [llvm|
{
^0(%arg655 : i64, %arg656 : i64, %arg657 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.udiv %0, %arg656 : i64
  %2 = llvm.udiv %0, %arg657 : i64
  %3 = llvm.or %1, %2 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

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

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

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

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

def test11_after := [llvm|
{
^0(%arg30 : i23):
  %0 = llvm.mlir.constant(6 : i23) : i23
  %1 = llvm.mlir.constant(-4096 : i23) : i23
  %2 = llvm.mul %arg30, %0 : i23
  %3 = llvm.and %2, %1 : i23
  "llvm.return"(%3) : (i23) -> ()
}
]

def demorgan_or_apint2_before := [llvm|
{
^0(%arg60 : i129, %arg61 : i129):
  %0 = llvm.mlir.constant(-1 : i129) : i129
  %1 = llvm.xor %arg60, %0 : i129
  %2 = llvm.xor %arg61, %0 : i129
  %3 = llvm.or %1, %2 : i129
  "llvm.return"(%3) : (i129) -> ()
}
]

Lean.Syntax.TSepArray in Init.Prelude

def changeBVLogicalExprWidth (pred: GenBVPred) (target: Nat) : GenBVPred :=
  match pred with
  | GenBVPred.bin lhs op rhs => (GenBVPred.bin (changeBVExprWidth lhs target) op (changeBVExprWidth rhs target))
  | GenBVPred.getLsbD .. => pred

def slt_and_not_max_after := [llvm|
{
^0(%arg126 : i8, %arg127 : i8):
  %0 = llvm.icmp "slt" %arg126, %arg127 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

def uge_or_not_max_commute_before := [llvm|
{
^0(%arg300 : i8, %arg301 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.icmp "uge" %arg300, %arg301 : i8
  %2 = llvm.icmp "ne" %arg300, %0 : i8
  %3 = llvm.or %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def urem_illegal_type_before := [llvm|
{
^0(%arg15 : i9, %arg16 : i9):
  %0 = llvm.zext %arg15 : i9 to i32
  %1 = llvm.zext %arg16 : i9 to i32
  %2 = llvm.urem %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def both_after := [llvm|
{
^0(%arg9 : i8, %arg10 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.shl %0, %arg10 overflow<nuw> : i8
  %3 = llvm.lshr %2, %arg9 : i8
  %4 = llvm.icmp "ne" %3, %1 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def tacName : String := "bv_multi_width"

def and_sext_sext_before := [llvm|
{
^0(%arg52 : i8, %arg53 : i4):
  %0 = llvm.sext %arg52 : i8 to i16
  %1 = llvm.sext %arg53 : i4 to i16
  %2 = llvm.and %1, %0 : i16
  "llvm.return"(%2) : (i16) -> ()
}
]

def test10_before := [llvm|
{
^0(%arg13 : i32):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.mlir.constant(65535) : i64
  %2 = llvm.lshr %arg13, %0 : i32
  %3 = llvm.zext %2 : i32 to i64
  %4 = llvm.mul %3, %1 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

def testi16i8_ne_com_after := [llvm|
{
^0(%arg9 : i16):
  %0 = llvm.mlir.constant(-128 : i16) : i16
  %1 = llvm.mlir.constant(-256 : i16) : i16
  %2 = llvm.add %arg9, %0 : i16
  %3 = llvm.icmp "ult" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

def or_sext_sext_before := [llvm|
{
^0(%arg50 : i8, %arg51 : i4):
  %0 = llvm.sext %arg50 : i8 to i16
  %1 = llvm.sext %arg51 : i4 to i16
  %2 = llvm.or %0, %1 : i16
  "llvm.return"(%2) : (i16) -> ()
}
]

instance : Coe (AttrEntry φ) (String × AttrValue φ) where
  coe
  | AttrEntry.mk key val => (key, val)

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

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

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

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

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

def sra_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := sra_llvm_i64
  rhs := sra_riscv_i64

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

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

def shl_or_disjoint_lshr_before := [llvm|
{
^0(%arg109 : i32, %arg110 : i32, %arg111 : i32):
  %0 = llvm.shl %arg109, %arg110 overflow<nuw> : i32
  %1 = llvm.or disjoint %0, %arg111 : i32
  %2 = llvm.lshr %1, %arg110 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

def a_before := [llvm|
{
^0(%arg48 : i1, %arg49 : i1):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.zext %arg48 : i1 to i32
  %3 = llvm.zext %arg49 : i1 to i32
  %4 = llvm.sub %0, %3 : i32
  %5 = llvm.add %2, %1 : i32
  %6 = llvm.add %5, %4 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

def mul_of_pow2s_after := [llvm|
{
^0(%arg79 : i32, %arg80 : i32):
  %0 = llvm.mlir.constant(128 : i32) : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def alive_AddSub_1202_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.sub %C, %v3
  %v5 = llvm.sub %v4, %x
  llvm.return %v5
}]

def testi16i8_ne_before := [llvm|
{
^0(%arg10 : i16):
  %0 = llvm.mlir.constant(8 : i16) : i16
  %1 = llvm.mlir.constant(7 : i8) : i8
  %2 = llvm.lshr %arg10, %0 : i16
  %3 = llvm.trunc %2 : i16 to i8
  %4 = llvm.trunc %arg10 : i16 to i8
  %5 = llvm.ashr %4, %1 : i8
  %6 = llvm.icmp "ne" %5, %3 : i8
  "llvm.return"(%6) : (i1) -> ()
}
]

def bool_zext_before := [llvm|
{
^0(%arg172 : i1):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.sext %arg172 : i1 to i16
  %2 = llvm.lshr %1, %0 : i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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

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

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

def xor_to_xor1_before := [llvm|
{
^0(%arg85 : i32, %arg86 : i32):
  %0 = llvm.and %arg85, %arg86 : i32
  %1 = llvm.or %arg85, %arg86 : i32
  %2 = llvm.xor %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def or_simplify_ule_after := [llvm|
{
^0(%arg18 : i8, %arg19 : i8, %arg20 : i1):
  %0 = llvm.mlir.constant(-2 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.and %arg19, %0 : i8
  %3 = llvm.or %arg18, %arg19 : i8
  %4 = llvm.or %3, %1 : i8
  %5 = llvm.icmp "ule" %4, %2 : i8
  "llvm.return"(%5) : (i1) -> ()
}
]

def three_inst_concrete_com_proof :
    three_inst_concrete_com ⊑ three_inst_concrete_com :=

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

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

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

def checkForPreconditions (constantAssignments : List (Std.HashMap Nat BVExpr.PackedBitVec)) (maxConjunctions: Nat)
                                                : GeneralizerStateM ParsedBVExpr GenBVPred (Option (BoolExpr GenBVPred)) := do
  let state ← get
  let parsedBVLogicalExpr := state.parsedLogicalExpr

  let positiveExamples := constantAssignments.map (fun assignment => assignment.filter (fun key _ => parsedBVLogicalExpr.lhs.symVars.contains key))

  for numConjunctions in (List.range (maxConjunctions + 1)) do
    logInfo m! "Running with {numConjunctions} allowed conjunctions"
    for expr in state.needsPreconditionsExprs.reverse do
        let negativeExamples ← getNegativeExamples expr 3
        logInfo m! "Negative examples for {expr} : {negativeExamples}"

        let mut preconditions := none
        if !negativeExamples.isEmpty then
          preconditions ← withTraceNode `Generalize (fun _ => return m! "Attempted to generate weak precondition for {expr}") do
                      generatePreconditions expr positiveExamples negativeExamples numConjunctions

        let widthRelations ← getWidthRelations
        match (preconditions, widthRelations) with
        | (none, none) => logInfo m! "Could not generate precondition for expr: {expr} with negative examples: {negativeExamples}"
        | (some weakPC, some widthRel) =>
                return BoolExpr.ite (BoolExpr.gate Gate.and weakPC widthRel) expr (BoolExpr.const False)
        | (some weakPC, none) =>
                return BoolExpr.ite weakPC expr (BoolExpr.const False)
        | (none, some widthRel) =>
                return BoolExpr.ite widthRel expr (BoolExpr.const False)
        checkTimeout
  return none

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

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

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

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

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

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

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

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

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

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

def map : ∀ (_c : Circuit α) (_f : α → β), Circuit β
  | tru, _ => tru
  | fals, _ => fals
  | var b x, f => var b (f x)
  | and c₁ c₂, f => (map c₁ f) &&& (map c₂ f)
  | or c₁ c₂, f => (map c₁ f) ||| (map c₂ f)
  | xor c₁ c₂, f => (map c₁ f) ^^^ (map c₂ f)

def icmp_shl_ule_2_after := [llvm|
{
^0(%arg8 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.add %arg8, %0 : i8
  %3 = llvm.icmp "sgt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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 xor_icmp_to_ne_before := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.mlir.constant(6 : i32) : i32
  %2 = llvm.icmp "sgt" %arg6, %0 : i32
  %3 = llvm.icmp "slt" %arg6, %1 : i32
  %4 = llvm.xor %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def oppositesign_before := [llvm|
{
^0(%arg32 : i16, %arg33 : i16):
  %0 = llvm.mlir.constant(-32768 : i16) : i16
  %1 = llvm.mlir.constant(32767 : i16) : i16
  %2 = llvm.or %arg32, %0 : i16
  %3 = llvm.and %arg33, %1 : i16
  %4 = llvm.add %2, %3 : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

def test1_after := [llvm|
{
^0(%arg3 : i33):
  %0 = llvm.mlir.constant(12 : i33) : i33
  %1 = llvm.lshr %arg3, %0 : i33
  "llvm.return"(%1) : (i33) -> ()
}
]

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

instance : ToString (MetaLLVM φ).Ty := ⟨MetaLLVM.printType⟩

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

def substitute  (bvPred: GenBVPred) (assignment: Std.HashMap Nat (SubstitutionValue GenBVExpr)) :
          GenBVPred :=
  match bvPred with
  | (GenBVPred.bin lhs op rhs) => (GenBVPred.bin (substituteBVExpr lhs assignment) op (substituteBVExpr rhs assignment))
  
  | _ => bvPred

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

private def mkElab (ext : NameExt) (ty : Lean.Expr) : Elab.Term.TermElabM Lean.Expr := do
  let mut stx := #[]
  for (_, n4) in ext.getState (← getEnv) do
    stx := stx.push $ ← `($(mkIdent n4):ident)
  let listStx := (← `([$stx,*]))
  let list ← `($listStx)
  Elab.Term.elabTerm list (some ty)

def positive_biggerLshr_shlnuw_before := [llvm|
{
^0(%arg27 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(10 : i32) : i32
  %2 = llvm.shl %arg27, %0 overflow<nuw> : i32
  %3 = llvm.lshr %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def Var.tryDelete? [TyDenote Ty] {Γ Γ' : Ctxt Ty} {delv : DeleteRange Γ}
  (DEL : Deleted Γ delv Γ') (vs : HVector Γ.Var β) :
    Option { v' : HVector Γ'.Var β // vs = v'.map DEL.toHom } := do
  match vs with
  | .nil => some ⟨.nil, rfl⟩
  | v ::ₕ vs => do
      let ⟨v, hv⟩ ← tryDeleteOne? DEL v
      let ⟨vs, hvs⟩ ← tryDelete? DEL vs
      return ⟨v ::ₕ vs, by admit /- proof elided -/
      ⟩

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

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

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

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

def andn_or_cmp_2_after := [llvm|
{
^0(%arg170 : i16, %arg171 : i16, %arg172 : i16):
  %0 = llvm.mlir.constant(42 : i16) : i16
  %1 = llvm.icmp "slt" %arg170, %arg171 : i16
  %2 = llvm.icmp "ugt" %arg172, %0 : i16
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def or_and3_commuted_before := [llvm|
{
^0(%arg100 : i1, %arg101 : i1, %arg102 : i32, %arg103 : i32):
  %0 = llvm.icmp "eq" %arg102, %arg103 : i32
  %1 = llvm.or %0, %arg100 : i1
  %2 = "llvm.select"(%1, %arg100, %arg101) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def and_or1_wrong_operand_after := [llvm|
{
^0(%arg176 : i1, %arg177 : i1, %arg178 : i1, %arg179 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg176, %0 : i1
  %2 = llvm.or %arg178, %1 : i1
  %3 = "llvm.select"(%2, %arg179, %arg177) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%3) : (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}

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

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

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

def OrZextOr_after := [llvm|
{
^0(%arg4 : i3):
  %0 = llvm.mlir.constant(11 : i5) : i5
  %1 = llvm.zext %arg4 : i3 to i5
  %2 = llvm.or %1, %0 : i5
  "llvm.return"(%2) : (i5) -> ()
}
]

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

def test_sub_nuw__nsw_is_safe_after := [llvm|
{
^0(%arg22 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.or %arg22, %0 : i32
  %2 = llvm.sub %0, %1 overflow<nsw> : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def test14_after := [llvm|
{
^0(%arg26 : i35):
  %0 = llvm.mlir.constant(-19760 : i35) : i35
  %1 = llvm.mlir.constant(19744 : i35) : i35
  %2 = llvm.and %arg26, %0 : i35
  %3 = llvm.or disjoint %2, %1 : i35
  "llvm.return"(%3) : (i35) -> ()
}
]

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

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

def test48_after := [llvm|
{
^0(%arg137 : i8, %arg138 : i8):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.zext %arg137 : i8 to i32
  %2 = llvm.shl %1, %0 overflow<nsw,nuw> : i32
  %3 = llvm.or disjoint %2, %1 : i32
  %4 = llvm.zext nneg %3 : i32 to i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

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

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

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

def test5_before := [llvm|
{
^0(%arg104 : i32):
  %0 = llvm.mlir.constant(16 : i128) : i128
  %1 = llvm.zext %arg104 : i32 to i128
  %2 = llvm.lshr %1, %0 : i128
  %3 = llvm.trunc %2 : i128 to i32
  "llvm.return"(%3) : (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 or_nosignbit_select_shl_after := [llvm|
{
^0(%arg40 : i32, %arg41 : i1):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(-16777216 : i32) : i32
  %2 = llvm.shl %arg40, %0 : i32
  %3 = llvm.or %2, %1 : i32
  %4 = "llvm.select"(%arg41, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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 add₂: Stream (BitVec w) → Stream (BitVec w) → Stream (BitVec w) :=
  syncMap₂ (· + ·)

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

noncomputable def toArgResult
    (mapOut : MatchVarResult lets v (.var matchLets matchExpr) w.appendInl mapIn) :
    let args := mapOut.getPureExpr_eq_some.choose
    MatchArgResult lets matchLets args matchExpr.args mapIn :=
  ⟨mapOut.1, by admit /- proof elided -/
  ⟩

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

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 llvm_const_lower_riscv_li39 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM39, rhs:= liRiscv39,
   correct := by admit /- proof elided -/

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

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

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

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

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

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

def alive_AddSub_1539_2_tgt :=
[sllvm| {
^bb0(%x : i64, %C : i64):
  %v1 = llvm.neg %C : i64
  %v2 = llvm.add %x, %v1 : i64
  llvm.return %v2 : i64
}]

def mkPostcondSafety (_circs : KInductionCircuits fsm n) :
    Circuit (Vars fsm.α arity (n + 1)) :=
  mkUnsatImpliesCircuit
    
    (castCircLe <| (mkInitCarryAssignCircuit fsm))
    
    (mkOutEqZeroCircuitLeN fsm n)

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

def unaryMax (pmask qmask : BitVec o) : BitVec o := (pmask ||| qmask)

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

def demorgan_and_apint5_before := [llvm|
{
^0(%arg50 : i47, %arg51 : i47):
  %0 = llvm.mlir.constant(-1 : i47) : i47
  %1 = llvm.xor %arg50, %0 : i47
  %2 = llvm.xor %arg51, %0 : i47
  %3 = llvm.and %1, %2 : i47
  "llvm.return"(%3) : (i47) -> ()
}
]

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

List.Subset in Init.Data.List.Basic

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

OrOp in Init.Prelude

def select_ashr_icmp_bad_after := [llvm|
{
^0(%arg45 : i32, %arg46 : i32, %arg47 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.icmp "eq" %arg45, %0 : i32
  %2 = llvm.ashr %arg47, %0 : i32
  %3 = "llvm.select"(%1, %2, %arg46) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def fold_xor_zext_sandwich_before := [llvm|
{
^0(%arg101 : i1):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.zext %arg101 : i1 to i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.zext %2 : i32 to i64
  "llvm.return"(%3) : (i64) -> ()
}
]

def lshr_or_after := [llvm|
{
^0(%arg69 : i8, %arg70 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(4 : i8) : i8
  %2 = llvm.mlir.constant(-16 : i8) : i8
  %3 = llvm.srem %arg69, %0 : i8
  %4 = llvm.shl %3, %1 : i8
  %5 = llvm.and %arg70, %2 : i8
  %6 = llvm.or %5, %4 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

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

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

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

RV64.divw in RISCV.Instructions

def alive_InstCombineShift__497'''_src  (w : Nat)   :=
[llvm( w )| {
^bb0(%X : _, %C : _, %C2 : _):
  %v1 = llvm.add %X, %C2
  %v2 = llvm.shl %v1, %C
  llvm.return %v2
}]

Min in Init.Prelude

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

@[simp_denote]
def sra_riscv_i16 :=
  [LV| {
    ^entry (%arg0: i16, %arg1: i16):
    %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64)
    %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64)
    %0 = slli %a0, 48 : !i64
    %1 = srai %0, 48 : !i64
    %2 = sra %1, %a1 : !i64
    %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16)
    llvm.return %3 :i16
  }]

def test1_before := [llvm|
{
^0(%arg5 : i23):
  %0 = llvm.mlir.constant(-1 : i23) : i23
  %1 = llvm.xor %0, %arg5 : i23
  %2 = llvm.or %arg5, %1 : i23
  "llvm.return"(%2) : (i23) -> ()
}
]

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 srli_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := srli_llvm_i64
  rhs := srli_riscv_i64

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

def main4d_before := [llvm|
{
^0(%arg122 : 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 %arg122, %0 : i32
  %5 = llvm.icmp "ne" %4, %0 : i32
  %6 = llvm.and %arg122, %1 : i32
  %7 = llvm.icmp "eq" %6, %2 : 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 ashrsgt_02_09_exact_before := [llvm|
{
^0(%arg76 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.mlir.constant(-7 : i4) : i4
  %2 = llvm.ashr exact %arg76, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

def testExampleAdd : DCOp.ValueStream (BitVec 8) :=
  exampleAdd.denote (Ctxt.Valuation.ofHVector (.cons val1 <| .cons val2 <| .nil))

def shl_xor_lshr_before := [llvm|
{
^0(%arg100 : i32, %arg101 : i32, %arg102 : i32):
  %0 = llvm.shl %arg100, %arg101 overflow<nuw> : i32
  %1 = llvm.xor %0, %arg102 : i32
  %2 = llvm.lshr %1, %arg101 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def not_xor_to_or_not2_after := [llvm|
{
^0(%arg36 : i3, %arg37 : i3, %arg38 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg38, %arg37 : i3
  %2 = llvm.and %arg36, %arg38 : i3
  %3 = llvm.xor %1, %0 : i3
  %4 = llvm.or %2, %3 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

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

def main_before := [llvm|
{
^0(%arg2 : i32):
  %0 = llvm.mlir.constant(-17 : i8) : i8
  %1 = llvm.mlir.constant(122 : i8) : i8
  %2 = llvm.mlir.constant(6 : i8) : i8
  %3 = llvm.mlir.constant(7 : i8) : i8
  %4 = llvm.mlir.constant(64 : i8) : i8
  %5 = llvm.trunc %arg2 : i32 to i8
  %6 = llvm.or %5, %0 : i8
  %7 = llvm.and %5, %1 : i8
  %8 = llvm.xor %7, %0 : i8
  %9 = llvm.shl %8, %2 : i8
  %10 = llvm.xor %9, %8 : i8
  %11 = llvm.xor %6, %10 : i8
  %12 = llvm.lshr %11, %3 : i8
  %13 = llvm.mul %12, %4 : i8
  %14 = llvm.zext %13 : i8 to i32
  "llvm.return"(%14) : (i32) -> ()
}
]

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

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

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

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

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

def lor_band_left2_after := [llvm|
{
^0(%arg72 : i1, %arg73 : i1):
  "llvm.return"(%arg72) : (i1) -> ()
}
]

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

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

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

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

def llvm_mul_lower_riscv_nsw_flag_32 : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where
  lhs := mul_llvm_nsw_32
  rhs := mul_riscv_32

instance [ToString w] : ToString (DCOp.ValueStream w) where
  toString s := toString (Stream.toList 10 s)

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

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

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

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

def not_ashr_not_after := [llvm|
{
^0(%arg139 : i32, %arg140 : i32):
  %0 = llvm.ashr %arg139, %arg140 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def badimm2_after := [llvm|
{
^0(%arg27 : i16):
  %0 = llvm.mlir.constant(8 : i16) : i16
  %1 = llvm.mlir.constant(6 : i8) : i8
  %2 = llvm.mlir.constant(-1 : i16) : i16
  %3 = llvm.mlir.constant(127 : i8) : i8
  %4 = llvm.mlir.constant(-128 : i8) : i8
  %5 = llvm.lshr %arg27, %0 : i16
  %6 = llvm.trunc %5 overflow<nuw> : i16 to i8
  %7 = llvm.trunc %arg27 : i16 to i8
  %8 = llvm.ashr %7, %1 : i8
  %9 = llvm.icmp "eq" %8, %6 : i8
  %10 = llvm.icmp "sgt" %arg27, %2 : i16
  %11 = "llvm.select"(%10, %3, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %12 = "llvm.select"(%9, %7, %11) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%12) : (i8) -> ()
}
]

def icmp_eq_and_pow2_shl_pow2_negative1_after := [llvm|
{
^0(%arg61 : i32):
  %0 = llvm.mlir.constant(11 : i32) : i32
  %1 = llvm.mlir.constant(4 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.shl %0, %arg61 : i32
  %4 = llvm.lshr %3, %1 : i32
  %5 = llvm.and %4, %2 : i32
  %6 = llvm.xor %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def redundant_binop_in_equality_XPlusYEqX : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.add %x, %y : i64
      %1 = llvm.icmp.eq %0, %x : i64
      llvm.return %1 : i1
  }]
  rhs := [LV| {
    ^entry (%x: i64, %y: i64):
      %0 = llvm.mlir.constant (0) : i64
      %1 = llvm.icmp.eq %y, %0 : i64
      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 constLLVM40 : Com LLVMPlusRiscV ⟨[]⟩ .pure (.llvm (.bitvec 64)) := [LV| {
  ^entry ():
    %1 = llvm.mlir.constant (40) : i64
    llvm.return %1 : i64
  }]

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

def main5f_like_logical_after := [llvm|
{
^0(%arg95 : i32, %arg96 : i32, %arg97 : i32):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.and %arg95, %arg96 : i32
  %2 = llvm.icmp "eq" %1, %arg95 : i32
  %3 = llvm.and %arg95, %arg97 : i32
  %4 = llvm.icmp "eq" %3, %arg95 : i32
  %5 = "llvm.select"(%2, %4, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %6 = llvm.zext %5 : i1 to i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

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 lshrugt_01_03_exact_after := [llvm|
{
^0(%arg218 : i4):
  %0 = llvm.mlir.constant(6 : i4) : i4
  %1 = llvm.icmp "ugt" %arg218, %0 : i4
  "llvm.return"(%1) : (i1) -> ()
}
]

def test2_after := [llvm|
{
^0(%arg0 : i167):
  %0 = llvm.mlir.constant(9 : i167) : i167
  %1 = llvm.mlir.constant(8 : i167) : i167
  %2 = llvm.lshr %arg0, %0 : i167
  %3 = llvm.shl %arg0, %1 : i167
  %4 = llvm.or %2, %3 : i167
  "llvm.return"(%4) : (i167) -> ()
}
]

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

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

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

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

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

def test_sge_xor_before := [llvm|
{
^0(%arg38 : i32, %arg39 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg38, %0 : i32
  %2 = llvm.xor %1, %arg39 : i32
  %3 = llvm.icmp "sge" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

instance : DecidableNFA' (NFA'.autEq) where

def Lets.ofUnTyped (lets : UnTyped.Lets Op VarName) {Γ_in}
    (h : ∃ Γ_out, Lets.WellTyped Γ_in lets Γ_out) :
    Lets Op Γ_in (Lets.outContext lets Γ_in) :=
  ⟨lets, Lets.WellTyped.exists_iff.mp h⟩

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

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

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

def trunc_sel_equal_zext_after := [llvm|
{
^0(%arg65 : i32, %arg66 : i1):
  %0 = llvm.mlir.constant(65535 : i32) : i32
  %1 = llvm.mlir.constant(42 : i32) : i32
  %2 = llvm.and %arg65, %0 : i32
  %3 = "llvm.select"(%arg66, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

Subtype in Init.Prelude

def TermBinop.openTerm (op : TermBinop) : Term := op.subst (.var 0) (.var 1)

def test_sext_zext_after := [llvm|
{
^0(%arg105 : i16):
  %0 = llvm.zext %arg105 : i16 to i64
  "llvm.return"(%0) : (i64) -> ()
}
]

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

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

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

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 and_xor_or5_after := [llvm|
{
^0(%arg661 : i64, %arg662 : i64, %arg663 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.udiv %0, %arg662 : i64
  %2 = llvm.udiv %0, %arg663 : i64
  %3 = llvm.or %1, %2 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

Stream'.head in Mathlib.Data.Stream.Defs

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

def canonicalize_logic_first_or0_after := [llvm|
{
^0(%arg40 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(112 : i32) : i32
  %2 = llvm.or %arg40, %0 : i32
  %3 = llvm.add %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def test10b_before := [llvm|
{
^0(%arg105 : i32, %arg106 : i32):
  %0 = llvm.xor %arg105, %arg106 : i32
  %1 = llvm.and %arg106, %arg105 : i32
  %2 = llvm.xor %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def and_two_ranges_to_mask_and_range_different_sizes_before := [llvm|
{
^0(%arg250 : i8):
  %0 = llvm.mlir.constant(-97 : i8) : i8
  %1 = llvm.mlir.constant(25 : i8) : i8
  %2 = llvm.mlir.constant(-65 : i8) : i8
  %3 = llvm.mlir.constant(24 : i8) : i8
  %4 = llvm.add %arg250, %0 : i8
  %5 = llvm.icmp "ugt" %4, %1 : i8
  %6 = llvm.add %arg250, %2 : i8
  %7 = llvm.icmp "ugt" %6, %3 : i8
  %8 = llvm.and %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

def PR24873_after := [llvm|
{
^0(%arg130 : i64):
  %0 = llvm.mlir.constant(61) : i64
  %1 = llvm.icmp "ugt" %arg130, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

def select_constants_and_icmp_eq0_after := [llvm|
{
^0(%arg46 : i1, %arg47 : i1):
  %0 = llvm.xor %arg46, %arg47 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test_shl_nuw__none_are_safe_before := [llvm|
{
^0(%arg68 : i32, %arg69 : i64):
  %0 = llvm.mlir.constant(-2 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.and %arg68, %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 %arg69, %5 : i64
  %8 = "llvm.select"(%6, %arg69, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

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

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

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

def tryFactorization_xor_ashr_lshr_before := [llvm|
{
^0(%arg40 : i32):
  %0 = llvm.mlir.constant(-3 : i32) : i32
  %1 = llvm.mlir.constant(5 : i32) : i32
  %2 = llvm.ashr %0, %arg40 : i32
  %3 = llvm.lshr %1, %arg40 : i32
  %4 = llvm.xor %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def module
      (arg_0 : Stream' (BitVec 1))
      (arg_0_valid : Stream' (BitVec 1))
      (arg_1 : Stream' (BitVec 1))
      (arg_1_valid : Stream' (BitVec 1))
      (out0_ready : Stream' (BitVec 1))
      (out1_ready : Stream' (BitVec 1))
      (out2_ready : Stream' (BitVec 1))
  : Vector (Stream' (BitVec 1)) 8 :=
    let vec_streams := streams_to_vec
                        (#v[arg_0, arg_0_valid, arg_1, arg_1_valid, out0_ready, out1_ready, out2_ready])
    vec_to_streams <| register_wrapper
      (inputs := vec_streams)
      (init_regs := #v[0#1, 0#1])
      (update_fun := 
        fun (inp, regs) =>
          let v2 := BitVec.xor regs[0] 1#1
          let v3 := BitVec.and v2 inp[1]
          let v4 := BitVec.and inp[4] v3
          let v5 := BitVec.or v4 regs[0]
          let v8 := BitVec.xor regs[1] 1#1
          let v9 := BitVec.and v8 inp[1]
          let v10 := BitVec.and inp[5] v9
          let v11 := BitVec.or v10 regs[1]
          let v12 := BitVec.and v5 v11
          let v6 := BitVec.xor v12 1#1
          let v7 := BitVec.and v11 v6
          let v0 := BitVec.xor v12 1#1
          let v1 := BitVec.and v5 v0
          let updated_reg0 := v1
          let updated_reg1 := v7
          (#v[v12, inp[6], 0#1, v3, 0#1, v9, inp[2], inp[3]], #v[updated_reg0, updated_reg1])
      )

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

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

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

def substituteBVExpr (bvExpr: FpExpr w) (assignment: Std.HashMap Nat (SubstitutionValue FpExpr)) : FpExpr w :=
    match bvExpr with
    | .var idx =>
      if assignment.contains idx then
          let value := assignment[idx]!
          match value with
          | .genExpr (w := wbv) bv =>
            if h : w = wbv then
              
              h ▸ bv
            else
              default
          | .packedBV packedBitVec =>
            FpExpr.const (packedBitVec.bv.setWidth _)
      else FpExpr.var idx
    | .bin lhs op rhs =>
        FpExpr.bin (substituteBVExpr lhs assignment) op (substituteBVExpr rhs assignment)
    | .const x => .const x

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

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

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

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

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

def zext_nneg_sext_ule_op0_wide_after := [llvm|
{
^0(%arg46 : i9, %arg47 : i8):
  %0 = llvm.sext %arg47 : i8 to i9
  %1 = llvm.icmp "ule" %arg46, %0 : i9
  "llvm.return"(%1) : (i1) -> ()
}
]

def t0_before := [llvm|
{
^0(%arg23 : i32, %arg24 : i16):
  %0 = llvm.mlir.constant(32 : i16) : i16
  %1 = llvm.mlir.constant(-24 : i16) : i16
  %2 = llvm.sub %0, %arg24 : i16
  %3 = llvm.zext %2 : i16 to i32
  %4 = llvm.shl %arg23, %3 : i32
  %5 = llvm.trunc %4 : i32 to i16
  %6 = llvm.add %arg24, %1 : i16
  %7 = llvm.shl %5, %6 : i16
  "llvm.return"(%7) : (i16) -> ()
}
]

def test9_before := [llvm|
{
^0(%arg14 : i42):
  %0 = llvm.mlir.constant(3 : i42) : i42
  %1 = llvm.mul %0, %arg14 : i42
  %2 = llvm.sub %arg14, %1 : i42
  "llvm.return"(%2) : (i42) -> ()
}
]

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

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

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

def printException : Except Exception α → IO String
  | Except.ok _ => throw <| IO.userError "printException called on Except.ok"
  | Except.error e => e.toMessageData.toString

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

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

def Valuation.ofHVector {types : List Ty} : HVector toType types → Valuation (Ctxt.ofList types)
  | .nil        => (nil : Ctxt.Valuation ∅)
  | .cons x xs  => cons x (ofHVector xs)

class HydrableCheckForPreconditions (parsedExpr : Type) (genPred : Type) (genExpr : Nat → Type) extends
    HydrableInstances genPred
    where
  checkForPreconditions : (positiveExamples : List (Std.HashMap Nat BVExpr.PackedBitVec)) → (maxConjunctions : Nat)
                          → GeneralizerStateM parsedExpr genPred (Option (BoolExpr genPred))

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

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

def t8_lshr_exact_flag_preservation_before := [llvm|
{
^0(%arg27 : i32, %arg28 : i32):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.mlir.constant(-2 : i32) : i32
  %2 = llvm.sub %0, %arg28 : i32
  %3 = llvm.lshr exact %arg27, %2 : i32
  %4 = llvm.add %arg28, %1 : i32
  %5 = llvm.lshr exact %3, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

Lean.Expr.isFVar in Lean.Expr

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

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

instance : ToMessageData Gate where
  toMessageData g := m!"{g.toString}"

deriving instance Hashable for BoolExpr
deriving instance BEq for BoolExpr
deriving instance DecidableEq for BoolExpr

inductive Ty
| int
| bool
| nat
 deriving DecidableEq, Repr

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

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

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

def lshrugt_03_08_exact_after := [llvm|
{
^0(%arg181 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (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 n10_wrong_low_bit_mask_before := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(31 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.mlir.constant(16 : i8) : i8
  %3 = llvm.mlir.constant(-16 : i8) : i8
  %4 = llvm.and %arg11, %0 : i8
  %5 = llvm.icmp "eq" %4, %1 : i8
  %6 = llvm.add %arg11, %2 : i8
  %7 = llvm.and %6, %3 : i8
  %8 = "llvm.select"(%5, %arg11, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%8) : (i8) -> ()
}
]

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

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

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

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

def Vars.castLe {n m : Nat} (v : Vars σ ι n) (hnm : n ≤ m) : Vars σ ι m :=
  match v with
  | .state ss => .state (ss.castLe (by admit /- proof elided -/
  ))
  | .inputs is => .inputs (is.castLe hnm)
  | .outputs os =>
    .outputs (os.castLE (by admit /- proof elided -/
    ))

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

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

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

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

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

def t1_flags_nuw_nsw_second_before := [llvm|
{
^0(%arg30 : i8, %arg31 : i8, %arg32 : i8):
  %0 = llvm.sub %arg30, %arg31 : i8
  %1 = llvm.sub %0, %arg32 overflow<nsw,nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

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

def ult_192_before := [llvm|
{
^0(%arg51 : i32):
  %0 = llvm.mlir.constant(-64 : i8) : i8
  %1 = llvm.trunc %arg51 : i32 to i8
  %2 = llvm.icmp "ult" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

CoeHead in Init.Coe

LT.lt in Init.Prelude

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

def falseAfterIncluding (n : Nat) : FSM (Fin 0) := trueUptoExcluding n

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

def test0_before := [llvm|
{
^0(%arg6 : i41, %arg7 : i41, %arg8 : i41):
  %0 = llvm.shl %arg6, %arg8 : i41
  %1 = llvm.shl %arg7, %arg8 : i41
  %2 = llvm.and %0, %1 : i41
  "llvm.return"(%2) : (i41) -> ()
}
]

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

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

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

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

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

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

def xor_nosignbit_select_shl_after := [llvm|
{
^0(%arg36 : i32, %arg37 : i1):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(-16777216 : i32) : i32
  %2 = llvm.shl %arg36, %0 : i32
  %3 = llvm.xor %2, %1 : i32
  %4 = "llvm.select"(%arg37, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

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

def test40_after := [llvm|
{
^0(%arg153 : i16):
  %0 = llvm.mlir.constant(9 : i16) : i16
  %1 = llvm.mlir.constant(8 : i16) : i16
  %2 = llvm.lshr %arg153, %0 : i16
  %3 = llvm.shl %arg153, %1 : i16
  %4 = llvm.or disjoint %2, %3 : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

Lean.Syntax.mkNumLit in Init.Meta.Defs

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

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

def or_not_and_commute9_before := [llvm|
{
^0(%arg510 : i32, %arg511 : i32, %arg512 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg510 : i32
  %3 = llvm.sdiv %0, %arg511 : i32
  %4 = llvm.sdiv %0, %arg512 : i32
  %5 = llvm.or %2, %3 : i32
  %6 = llvm.xor %5, %1 : i32
  %7 = llvm.and %6, %4 : i32
  %8 = llvm.or %2, %4 : i32
  %9 = llvm.xor %8, %1 : i32
  %10 = llvm.and %3, %9 : i32
  %11 = llvm.or %7, %10 : i32
  "llvm.return"(%11) : (i32) -> ()
}
]

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

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

def is_ascii_alphabetic_after := [llvm|
{
^0(%arg248 : i32):
  %0 = llvm.mlir.constant(-33 : i32) : i32
  %1 = llvm.mlir.constant(-65 : i32) : i32
  %2 = llvm.mlir.constant(26 : i32) : i32
  %3 = llvm.and %arg248, %0 : i32
  %4 = llvm.add %3, %1 : i32
  %5 = llvm.icmp "ult" %4, %2 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

def ashr_can_be_lshr_2_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(4278190080) : i64
  %1 = llvm.mlir.constant(34) : i64
  %2 = llvm.mlir.constant(32) : i64
  %3 = llvm.zext %arg0 : i32 to i64
  %4 = llvm.or %3, %0 : i64
  %5 = llvm.shl %4, %1 : i64
  %6 = llvm.ashr exact %5, %2 : i64
  %7 = llvm.trunc %6 overflow<nsw> : i64 to i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

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 test2 : DCOp.TokenStream :=
  BranchEg.denote (Ctxt.Valuation.ofHVector (.cons c <| .cons x <| .cons u <| .nil)) |>.getN 0

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

@[simp_denote]
def add_positive_low_bound_reject_llvm := [LV| {
    ^entry (%a: i32):
    %0 = llvm.mlir.constant (2047) : i32
    %1 = llvm.add %a, %0 : i32
    llvm.return %1 :i32
  }]

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

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

def sdiv_exact_eq_9_no_of_after := [llvm|
{
^0(%arg8 : i8, %arg9 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(9 : i8) : i8
  %2 = llvm.and %arg9, %0 : i8
  %3 = llvm.mul %2, %1 overflow<nsw,nuw> : i8
  %4 = llvm.icmp "eq" %3, %arg8 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def test26_after := [llvm|
{
^0(%arg48 : i32, %arg49 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg49 overflow<nsw> : i32
  %3 = llvm.xor %2, %0 : i32
  %4 = llvm.and %arg48, %3 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  "llvm.return"(%5) : (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) -> ()
}
]

def ne_210_after := [llvm|
{
^0(%arg76 : i32, %arg77 : i32):
  %0 = llvm.trunc %arg76 : i32 to i24
  %1 = llvm.trunc %arg77 : i32 to i24
  %2 = llvm.icmp "ne" %0, %1 : i24
  "llvm.return"(%2) : (i1) -> ()
}
]

def test1_before := [llvm|
{
^0(%arg1 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(1431655765 : i32) : i32
  %2 = llvm.mlir.constant(-1 : i32) : i32
  %3 = llvm.ashr %arg1, %0 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.xor %4, %2 : i32
  %6 = llvm.add %5, %0 overflow<nsw> : i32
  %7 = llvm.add %arg1, %6 overflow<nsw> : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

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

def substitute_constant_or_ne_uge_commute_logical_before := [llvm|
{
^0(%arg280 : i8, %arg281 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "ne" %arg280, %0 : i8
  %3 = llvm.icmp "uge" %arg280, %arg281 : i8
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

instance [ToString α] [ToString β] [Hashable α] [BEq α] : ToString (Std.HashMap α β) where
  toString map :=
    "{" ++ String.intercalate ", " (map.toList.map (λ (k, v) => toString k ++ " → " ++ toString v)) ++ "}"

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

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

def add_shl_same_amount_partial_nuw2_before := [llvm|
{
^0(%arg32 : i6, %arg33 : i6, %arg34 : i6):
  %0 = llvm.shl %arg32, %arg34 overflow<nuw> : i6
  %1 = llvm.shl %arg33, %arg34 : i6
  %2 = llvm.add %0, %1 overflow<nuw> : i6
  "llvm.return"(%2) : (i6) -> ()
}
]

structure Signature (Ty : Type) where
  arguments : List Ty
  regions : List (RegionType Ty)
  returnType : Ty

def test_shift_negative_before := [llvm|
{
^0(%arg2 : i32, %arg3 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(7 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.or %arg2, %0 : i32
  %4 = llvm.and %arg3, %1 : i32
  %5 = llvm.shl %3, %4 overflow<nsw> : i32
  %6 = llvm.icmp "slt" %5, %2 : i32
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

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

def alive_InstCombineShift__497_src  (w : Nat)   :=
[llvm( w )| {
^bb0(%X : _, %C : _, %C2 : _):
  %v1 = llvm.xor %X, %C2
  %v2 = llvm.lshr %v1, %C
  llvm.return %v2
}]

RV64.remuw in RISCV.Instructions

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

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

Int.sub in Init.Data.Int.Basic

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

def test_zext_nneg_after := [llvm|
{
^0(%arg25 : i32, %arg26 : i64, %arg27 : i64):
  %0 = llvm.mlir.constant(-4) : i64
  %1 = llvm.add %arg26, %0 : i64
  %2 = llvm.sext %arg25 : i32 to i64
  %3 = llvm.sub %2, %arg27 : i64
  %4 = llvm.add %1, %3 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

def alive_239_tgt  (w : Nat)  :=
[llvm( w )| {
^bb0(%Y : _, %X : _):
  %v1 = llvm.mlir.constant 0
  %v2 = llvm.sub %v1, %X
  %v3 = llvm.mlir.constant 0
  %v4 = llvm.sub %v3, %Y
  %v5 = llvm.mul %X, %Y
  llvm.return %v5
}]

def eq_nsw_rem_nz_before := [llvm|
{
^0(%arg158 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.mlir.constant(-11 : i8) : i8
  %2 = llvm.mul %arg158, %0 overflow<nsw> : i8
  %3 = llvm.icmp "eq" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def test5_commuted_x_y_after := [llvm|
{
^0(%arg220 : i64, %arg221 : i64):
  %0 = llvm.mlir.constant(-1) : i64
  %1 = llvm.and %arg221, %arg220 : i64
  %2 = llvm.xor %1, %0 : i64
  "llvm.return"(%2) : (i64) -> ()
}
]

def Hom.unCons (f : Hom (Γ.cons t) Δ) : Hom Γ Δ :=
  fun _ v => f v.toCons

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

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

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

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

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

def foo1_or_before := [llvm|
{
^0(%arg154 : i32, %arg155 : i32, %arg156 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg155 : i32
  %3 = llvm.shl %0, %arg156 : i32
  %4 = llvm.and %2, %arg154 : i32
  %5 = llvm.icmp "ne" %4, %1 : i32
  %6 = llvm.and %3, %arg154 : i32
  %7 = llvm.icmp "ne" %6, %1 : i32
  %8 = llvm.and %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

instance [SIG : DialectSignature d] [DENOTE : DialectDenote d] {Γ : Ctxt d.Ty} {t}
    (com : Com d Γ .pure t) : Inhabited (DCEType com) where
  default :=
    ⟨Γ, Hom.id, com, by admit /- proof elided -/
    ⟩

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

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

instance : Refinement AllocState where
  IsRefinedBy s t := s = t

def and_to_xor4_after := [llvm|
{
^0(%arg113 : i32, %arg114 : i32):
  %0 = llvm.xor %arg114, %arg113 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def test12_after := [llvm|
{
^0(%arg46 : i32, %arg47 : i32):
  %0 = llvm.mlir.constant(1431655765 : i32) : i32
  %1 = llvm.and %arg46, %0 : i32
  %2 = llvm.sub %arg47, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

abbrev EnumerativeSearchCache :=  Std.HashMap BVExprWrapper BVExpr.PackedBitVec

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

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

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

def lshr_32_add_zext_basic_multiuse_before := [llvm|
{
^0(%arg23 : i32, %arg24 : i32):
  %0 = llvm.mlir.constant(32) : i64
  %1 = llvm.zext %arg23 : i32 to i64
  %2 = llvm.zext %arg24 : i32 to i64
  %3 = llvm.add %1, %2 : i64
  %4 = llvm.lshr %3, %0 : i64
  %5 = llvm.or %4, %2 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def MatchVarResult.toHom
    (map : MatchVarResult lets v matchLets w mapIn)
    (hvars : ∀ t (v : Var Δ_in t), ⟨t, v⟩ ∈ matchLets.vars w) :
    Δ_in.Hom Γ_out :=
  map.val.toHom <| map.isTotal_of hvars

def lshr_not_nneg2_after := [llvm|
{
^0(%arg20 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(-128 : i8) : i8
  %2 = llvm.lshr %arg20, %0 : i8
  %3 = llvm.or disjoint %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def matchMulO: List (Σ Γ, LLVMPeepholeRewriteRefine 64 Γ) :=
  [⟨_, mulo_by_2_unsigned_signed⟩,
  ⟨_, mulo_by_2_unsigned⟩,
  ⟨_, mulo_by_2_signed⟩]

def or_not_and_wrong_c_after := [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 %arg490, %2 : i32
  %4 = llvm.or %arg488, %arg491 : i32
  %5 = llvm.xor %4, %0 : i32
  %6 = llvm.and %arg489, %5 : i32
  %7 = llvm.or %3, %6 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

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

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

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

LE.le in Init.Prelude

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

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

Lean.initSearchPath in Lean.Util.Path

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

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

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

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

def lshrugt_02_10_after := [llvm|
{
^0(%arg389 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (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 CollectState.mkBenvExpr (reader : CollectState) : SolverM Expr := do
  CollectState.mkEnvExpr
    (mkBoolEnvEmpty)
    (mkBoolEnvCons) (reader.boolToIx.toArrayAsc.reverse)

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

def AndAshrAshr : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64, %z: i64):
      %0 = llvm.ashr %x, %z : i64
      %1 = llvm.ashr %y, %z : i64
      %2 = llvm.and %0, %1 : i64
      llvm.return %2 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64, %y: i64, %z: i64):
      %0 = llvm.and %x, %y : i64
      %1 = llvm.ashr %0, %z : i64
      llvm.return %1 : i64
  }]

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

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

def lshr_sext_i1_to_i128_before := [llvm|
{
^0(%arg53 : i1):
  %0 = llvm.mlir.constant(42 : i128) : i128
  %1 = llvm.sext %arg53 : i1 to i128
  %2 = llvm.lshr %1, %0 : i128
  "llvm.return"(%2) : (i128) -> ()
}
]

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

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 add_nsw_mul_nsw_before := [llvm|
{
^0(%arg33 : i16):
  %0 = llvm.add %arg33, %arg33 overflow<nsw> : i16
  %1 = llvm.add %0, %arg33 overflow<nsw> : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

def mul_of_bool_after := [llvm|
{
^0(%arg95 : i32, %arg96 : i8):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

def Eqn.reflectEqZero (w : Nat) (eqn : Eqn) (env : Env w) : Prop :=
  Eqn.reflect eqn env = BitVec.ofInt w 0

def llvm_const_lower_riscv_li_10 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_10, rhs:= liRiscv_10,
   correct := by admit /- proof elided -/

def or_sext_sext_after := [llvm|
{
^0(%arg50 : i8, %arg51 : i4):
  %0 = llvm.sext %arg51 : i4 to i8
  %1 = llvm.or %arg50, %0 : i8
  %2 = llvm.sext %1 : i8 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

@[simp_denote]
def slli_llvm_i64 := [LV| {
    ^entry (%a: i64):
    %0 = llvm.mlir.constant (7) : i64
    %1 = llvm.shl %a, %0 : i64
    llvm.return %1 : i64
  }]

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

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

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

def eq (v : Γ.Var t) (w : Γ.Var u) : Prop :=
  ∃ (h : t = u), v = h ▸ w

def Expr.mkVerifyCircuit (c cert : Expr) : MetaM Expr :=
  mkAppM ``Circuit.verifyCircuit #[c, cert]

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

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

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

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

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

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

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

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

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

   
  printTy : d.Ty → String

   
  dialectName : String
  

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

def udiv_shl_mul_nuw_swap_after := [llvm|
{
^0(%arg145 : i5, %arg146 : i5, %arg147 : i5):
  %0 = llvm.mlir.constant(1 : i5) : i5
  %1 = llvm.shl %0, %arg147 overflow<nuw> : i5
  %2 = llvm.udiv %1, %arg146 : i5
  "llvm.return"(%2) : (i5) -> ()
}
]

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

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

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

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

def fold_add_udiv_urem_after := [llvm|
{
^0(%arg10 : i32):
  %0 = llvm.mlir.constant(10 : i32) : i32
  %1 = llvm.mlir.constant(6 : i32) : i32
  %2 = llvm.udiv %arg10, %0 : i32
  %3 = llvm.mul %2, %1 overflow<nuw> : i32
  %4 = llvm.add %3, %arg10 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def addValToMapping (Γ : Ctxt d.Ty) (name : String) (ty : d.Ty) :
    BuilderM d (Σ (Γ' : DerivedCtxt Γ), Ctxt.Var Γ'.ctxt ty) := do
  let some nm := (←get).add name
    | throw <| .nameAlreadyDeclared name
  set nm
  return ⟨DerivedCtxt.ofCtxt Γ |>.cons ty, Ctxt.Var.last ..⟩

def test13_before := [llvm|
{
^0(%arg288 : i32, %arg289 : i32):
  %0 = llvm.icmp "ult" %arg288, %arg289 : i32
  %1 = llvm.icmp "ugt" %arg288, %arg289 : i32
  %2 = llvm.and %0, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def trunc_equality_both_sext_before := [llvm|
{
^0(%arg12 : i32, %arg13 : i8):
  %0 = llvm.trunc %arg12 overflow<nsw,nuw> : i32 to i16
  %1 = llvm.sext %arg13 : i8 to i16
  %2 = llvm.icmp "ne" %0, %1 : i16
  "llvm.return"(%2) : (i1) -> ()
}
]

def test_nuw_nsw_and_unsigned_pred_after := [llvm|
{
^0(%arg55 : i64):
  %0 = llvm.mlir.constant(6) : i64
  %1 = llvm.icmp "ugt" %arg55, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

def not_shl_before := [llvm|
{
^0(%arg86 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(-128 : i8) : i8
  %2 = llvm.shl %arg86, %0 : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

def land_land_left2_after := [llvm|
{
^0(%arg100 : i1, %arg101 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = "llvm.select"(%arg101, %arg100, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def mkReturn (Γ : Ctxt _) (opStx : MLIR.AST.Op 0) : MLIR.AST.ReaderM (DCPlusOp)
    (Σ eff ty, Com DCPlus Γ 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 no_shift_xor_multiuse_cmp_and_after := [llvm|
{
^0(%arg40 : i32, %arg41 : i32, %arg42 : i32, %arg43 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(-4097 : i32) : i32
  %3 = llvm.and %arg40, %0 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  %5 = llvm.and %arg41, %2 : i32
  %6 = "llvm.select"(%4, %5, %arg41) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = "llvm.select"(%4, %arg43, %arg42) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %8 = llvm.mul %6, %7 : i32
  %9 = llvm.mul %8, %5 : i32
  "llvm.return"(%9) : (i32) -> ()
}
]

@[simp_denote]
def sltu_llvm_i32 := [LV| {
    ^entry (%a: i32, %b: i32):
    %0 = llvm.icmp.ult %a, %b : i32
    %1 = llvm.zext %0 : i1 to i32
    llvm.return %1 : i32
  }]

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

def different_size_zext_zext_ugt_before := [llvm|
{
^0(%arg28 : i7, %arg29 : i4):
  %0 = llvm.zext %arg28 : i7 to i25
  %1 = llvm.zext %arg29 : i4 to i25
  %2 = llvm.icmp "ugt" %0, %1 : i25
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

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

def lowmask_add_zext_commute_before := [llvm|
{
^0(%arg233 : i16, %arg234 : i32):
  %0 = llvm.mlir.constant(65535 : i32) : i32
  %1 = llvm.mul %arg234, %arg234 : i32
  %2 = llvm.zext %arg233 : i16 to i32
  %3 = llvm.add %1, %2 : i32
  %4 = llvm.and %3, %0 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

def band_lor_right1_after := [llvm|
{
^0(%arg30 : i1, %arg31 : i1):
  "llvm.return"(%arg30) : (i1) -> ()
}
]

def slt_and_not_max_commute_after := [llvm|
{
^0(%arg122 : i8, %arg123 : i8):
  %0 = llvm.icmp "slt" %arg122, %arg123 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def source : Expr (DC) Γ .pure (.tokenstream) :=
  Expr.mk
    (op := .source)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .nil)
    (regArgs := .nil)

def runM (x : M α) : MetaM (α × State) := x.run {}

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

RV64.divu in RISCV.Instructions

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 t0_before := [llvm|
{
^0(%arg22 : i8):
  %0 = llvm.mlir.constant(32 : i8) : i8
  %1 = llvm.sdiv exact %arg22, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

def t10_c1_c2_after := [llvm|
{
^0(%arg11 : i8, %arg12 : i8):
  %0 = llvm.mlir.constant(-66 : i8) : i8
  %1 = llvm.add %arg11, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

def sext_shl_trunc_smaller_before := [llvm|
{
^0(%arg11 : i16, %arg12 : i32):
  %0 = llvm.sext %arg11 : i16 to i32
  %1 = llvm.shl %0, %arg12 : i32
  %2 = llvm.trunc %1 : i32 to i5
  "llvm.return"(%2) : (i5) -> ()
}
]

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

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

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

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

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

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

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

def scalar_i8_shl_uge_const_before := [llvm|
{
^0(%arg13 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.mlir.constant(64 : i8) : i8
  %2 = llvm.shl %arg13, %0 : i8
  %3 = llvm.icmp "uge" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def fold_or_zext_icmp_after := [llvm|
{
^0(%arg94 : i64, %arg95 : i64, %arg96 : i64):
  %0 = llvm.icmp "sgt" %arg94, %arg95 : i64
  %1 = llvm.icmp "slt" %arg94, %arg96 : i64
  %2 = llvm.or %0, %1 : i1
  %3 = llvm.zext %2 : i1 to i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

def mul_after := [llvm|
{
^0(%arg17 : i32, %arg18 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.mul %arg17, %arg18 : i32
  %2 = llvm.and %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def exactly_one_set_signbit_after := [llvm|
{
^0(%arg46 : i8, %arg47 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.xor %arg46, %arg47 : i8
  %2 = llvm.icmp "slt" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def zext_nneg_sext_ule_op0_wide_before := [llvm|
{
^0(%arg46 : i9, %arg47 : i8):
  %0 = llvm.zext nneg %arg46 : i9 to i32
  %1 = llvm.sext %arg47 : i8 to i32
  %2 = llvm.icmp "ule" %0, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def llvm_const_lower_riscv_li_23 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_23, rhs:= liRiscv_23,
   correct := by admit /- proof elided -/

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

def p_constmask2_before := [llvm|
{
^0(%arg41 : i32, %arg42 : i32):
  %0 = llvm.mlir.constant(61440 : i32) : i32
  %1 = llvm.mlir.constant(-65281 : i32) : i32
  %2 = llvm.and %arg41, %0 : i32
  %3 = llvm.and %arg42, %1 : i32
  %4 = llvm.or %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

Except.error in Init.Prelude

inductive DecideIfZerosOutput
 
| safetyFailure (iter : Nat)
 
| exhaustedIterations (numIters : Nat)
 
| provenByKIndCycleBreaking (numIters : Nat) (safetyCert : BVDecide.Frontend.LratCert) (indCertCycleBreaking : BVDecide.Frontend.LratCert)

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

def sgt_smax1_after := [llvm|
{
^0(%arg39 : i32, %arg40 : i32):
  %0 = llvm.icmp "sgt" %arg40, %arg39 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

def t2_commutative_before := [llvm|
{
^0(%arg20 : i8, %arg21 : i8):
  %0 = llvm.sub %arg20, %arg21 : i8
  %1 = llvm.icmp "uge" %arg20, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

def test6_after := [llvm|
{
^0(%arg117 : i32):
  %0 = llvm.mlir.constant(1234 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.xor %arg117, %0 : i32
  %3 = llvm.lshr %arg117, %1 : i32
  %4 = llvm.add %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

instLEBitVec in Init.Prelude

def test4_after := [llvm|
{
^0(%arg193 : i32, %arg194 : i32):
  %0 = llvm.icmp "slt" %arg193, %arg194 : i32
  %1 = llvm.zext %0 : i1 to i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

def or_xor_and_commuted1_before := [llvm|
{
^0(%arg50 : i32, %arg51 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.mul %arg51, %arg51 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.xor %2, %arg50 : i32
  %4 = llvm.or %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def trunc_nuw_xor_before := [llvm|
{
^0(%arg5 : i8, %arg6 : i8):
  %0 = llvm.xor %arg5, %arg6 : i8
  %1 = llvm.trunc %0 overflow<nuw> : i8 to i1
  "llvm.return"(%1) : (i1) -> ()
}
]

Except in Init.Prelude

def icmp_ugt_16_before := [llvm|
{
^0(%arg16 : i64):
  %0 = llvm.mlir.constant(16) : i64
  %1 = llvm.mlir.constant(1048575) : i64
  %2 = llvm.shl %arg16, %0 overflow<nuw> : i64
  %3 = llvm.icmp "ugt" %2, %1 : i64
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def zext_sext_add_icmp_slt_1_rhs_not_const_after := [llvm|
{
^0(%arg49 : i1, %arg50 : i1, %arg51 : i8):
  %0 = llvm.zext %arg49 : i1 to i8
  %1 = llvm.sext %arg50 : i1 to i8
  %2 = llvm.add %0, %1 overflow<nsw> : i8
  %3 = llvm.icmp "slt" %2, %arg51 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def ashr_1_before := [llvm|
{
^0(%arg97 : i8, %arg98 : i1, %arg99 : i8, %arg100 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(123 : i8) : i8
  %2 = llvm.xor %arg99, %0 : i8
  %3 = llvm.xor %arg100, %1 : i8
  %4 = "llvm.select"(%arg98, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %5 = llvm.ashr %4, %arg97 : i8
  %6 = llvm.xor %5, %0 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

def alive_AndOrXor_2297_src :=
[sllvm| {
^bb0(%A : i64, %B : i64):
  %v1 = llvm.and %A, %B : i64
  %v2 = llvm.mlir.constant -1 : i64
  %v3 = llvm.xor %A, %v2 : i64
  %v4 = llvm.xor %v3, %B : i64
  %v5 = llvm.or %v1, %v4 : i64
  llvm.return %v5 : i64
}]

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

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

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 shift_xor_multiuse_cmp_before := [llvm|
{
^0(%arg84 : i32, %arg85 : i32, %arg86 : i32, %arg87 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(2048 : i32) : i32
  %3 = llvm.and %arg84, %0 : i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  %5 = llvm.or %arg85, %2 : i32
  %6 = "llvm.select"(%4, %arg85, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %7 = "llvm.select"(%4, %arg86, %arg87) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %8 = llvm.mul %6, %7 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

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

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

def shl_add_and_before := [llvm|
{
^0(%arg96 : i8, %arg97 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(123 : i8) : i8
  %2 = llvm.shl %arg96, %0 : i8
  %3 = llvm.shl %arg97, %0 : i8
  %4 = llvm.add %3, %1 : i8
  %5 = llvm.and %2, %4 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def ripple_nsw5_after := [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 overflow<nsw> : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

def select_constants_and_icmp_ne0_after := [llvm|
{
^0(%arg26 : i1, %arg27 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg26, %arg27 : i1
  %2 = llvm.xor %1, %0 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def shl_and_lshr_comm_after := [llvm|
{
^0(%arg91 : i32, %arg92 : i32, %arg93 : i32):
  %0 = llvm.lshr %arg93, %arg92 : i32
  %1 = llvm.and %0, %arg91 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

@[simp_llvm]
def sext? {w: Nat} (w': Nat) (x: BitVec w) : IntW w' := do
  .value <| (BitVec.signExtend w' x)

def neg_mask_const_before := [llvm|
{
^0(%arg0 : i16):
  %0 = llvm.mlir.constant(1000 : i32) : i32
  %1 = llvm.mlir.constant(15 : i16) : i16
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.sext %arg0 : i16 to i32
  %4 = llvm.sub %0, %3 overflow<nsw> : i32
  %5 = llvm.lshr %arg0, %1 : i16
  %6 = llvm.zext %5 : i16 to i32
  %7 = llvm.sub %2, %6 overflow<nsw> : i32
  %8 = llvm.and %4, %7 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

def test11_before := [llvm|
{
^0(%arg43 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.icmp "ule" %arg43, %0 : i1
  "llvm.return"(%1) : (i1) -> ()
}
]

abbrev Arith : Dialect := {Op, Ty}

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

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

def alive_AndOrXor_2265_tgt :=
[sllvm| {
^bb0(%A : i64, %B : i64):
  %v1 = llvm.and %A, %B : i64
  %v2 = llvm.xor %A, %B : i64
  %v3 = llvm.or %A, %B : i64
  llvm.return %v3 : i64
}]

instance : Coe String SSAVal where
  coe (s: String) := SSAVal.name s

def test_mul_nuw__nuw_is_safe_before := [llvm|
{
^0(%arg10 : i32):
  %0 = llvm.mlir.constant(268435457 : i32) : i32
  %1 = llvm.mlir.constant(268435456 : i32) : i32
  %2 = llvm.mlir.constant(9 : i32) : i32
  %3 = llvm.mlir.constant(-1879048192 : i32) : i32
  %4 = llvm.and %arg10, %0 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.mul %4, %2 overflow<nuw> : i32
  %7 = "llvm.select"(%5, %3, %6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%7) : (i32) -> ()
}
]

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

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

abbrev WidthExpr := Expr

def or_ugt_before := [llvm|
{
^0(%arg58 : i8, %arg59 : i8):
  %0 = llvm.or %arg58, %arg59 : i8
  %1 = llvm.icmp "ugt" %0, %arg58 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

def icmp_equality_test_commute_select2_before := [llvm|
{
^0(%arg14 : i64, %arg15 : i64, %arg16 : i64):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "eq" %arg14, %arg16 : i64
  %3 = llvm.icmp "eq" %arg15, %arg16 : i64
  %4 = llvm.icmp "eq" %arg14, %arg15 : i64
  %5 = llvm.xor %2, %0 : i1
  %6 = "llvm.select"(%3, %1, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %7 = "llvm.select"(%5, %6, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def sub_shl_same_amount_after := [llvm|
{
^0(%arg29 : i6, %arg30 : i6, %arg31 : i6):
  %0 = llvm.sub %arg29, %arg30 : i6
  %1 = llvm.shl %0, %arg31 : i6
  "llvm.return"(%1) : (i6) -> ()
}
]

def PR52261_before := [llvm|
{
^0(%arg208 : i1):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(-2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = "llvm.select"(%arg208, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.sub %2, %3 overflow<nsw> : i32
  %5 = llvm.and %3, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def test_nsw_and_signed_pred_after := [llvm|
{
^0(%arg56 : i64):
  %0 = llvm.mlir.constant(-7) : i64
  %1 = llvm.icmp "slt" %arg56, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def false_statement {w : ℕ} (x y : BitVec w) : x = y :=

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

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

def demorgan_and_apint2_after := [llvm|
{
^0(%arg56 : i129, %arg57 : i129):
  %0 = llvm.mlir.constant(-1 : i129) : i129
  %1 = llvm.or %arg56, %arg57 : i129
  %2 = llvm.xor %1, %0 : i129
  "llvm.return"(%2) : (i129) -> ()
}
]

def getVarWidth {Γ : Ctxt HSxComb.Ty} : (Σ t, Γ.Var t) → Nat
  | ⟨.stream _, _⟩ => 1
  | ⟨.stream2 _, _⟩ => 1
  | ⟨.stream2token (.bitvec w), _⟩ => w

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

def sub_match : List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) := [
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_lower_riscv_no_flag_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nsw_lower_riscv_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nuw_lower_riscv_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nsw_nuw_lower_riscv_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_lower_riscv_no_flag_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nsw_lower_riscv_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nuw_lower_riscv_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nsw_nuw_lower_riscv_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_lower_riscv_no_flag_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nsw_lower_riscv_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nuw_lower_riscv_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_sub_nsw_nuw_lower_riscv_64)
]

def land_lor_left1_after := [llvm|
{
^0(%arg94 : i1, %arg95 : i1):
  "llvm.return"(%arg94) : (i1) -> ()
}
]

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

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

def icmp_eq_select_before := [llvm|
{
^0(%arg3 : i1, %arg4 : i32, %arg5 : i32):
  %0 = "llvm.select"(%arg3, %arg4, %arg5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %1 = "llvm.select"(%arg3, %arg5, %arg4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "eq" %0, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

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 test8_before := [llvm|
{
^0(%arg92 : i32):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.shl %arg92, %0 : i32
  %3 = llvm.srem %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

structure Context extends Config where

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

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

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

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

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

partial def existsForAll
    [H : HydrableExistsForall parsedExpr genPred genExpr]
    (origExpr : BoolExpr genPred) (existsVars: List Nat) (forAllVars: List Nat)  (numExamples: Nat := 1) :
    GeneralizerStateM parsedExpr genPred (List (Std.HashMap Nat BVExpr.PackedBitVec)) := do

    let rec constantsSynthesis (bvExpr: BoolExpr genPred) (existsVars: List Nat) (forAllVars: List Nat)
            : GeneralizerStateM parsedExpr genPred (Option (Std.HashMap Nat BVExpr.PackedBitVec)) := do
      let existsRes ← solve bvExpr

      match existsRes with
        | none => trace[Generalize] m! "Could not satisfy exists formula for {bvExpr}"
                  return none
        | some assignment =>
          let existsVals := assignment.filter fun c _ => existsVars.contains c
          let substExpr := subsituteGenLogicalExpr bvExpr (H.packedBitVecToSubstitutionValue existsVals)
          let forAllRes ← solve (BoolExpr.not substExpr)

          match forAllRes with
            | none =>
              return some existsVals
            | some counterEx =>
                let newExpr := subsituteGenLogicalExpr bvExpr (H.packedBitVecToSubstitutionValue counterEx)
                constantsSynthesis (BoolExpr.gate .and bvExpr newExpr) existsVars forAllVars

    let mut res : List (Std.HashMap Nat BVExpr.PackedBitVec) := []
    let identityAndAbsorptionConstraints := getIdentityAndAbsorptionConstraints origExpr (Std.HashSet.ofList existsVars)
    let targetExpr := (BoolExpr.gate .and origExpr (bigAnd (identityAndAbsorptionConstraints)))

    match numExamples with
    | 0 => return res
    | n + 1 =>  let consts ← constantsSynthesis targetExpr existsVars forAllVars
                match consts with
                | none => return res
                | some assignment =>
                      res := assignment :: res
                      let newConstraints := assignment.toList.map (fun c => H.eq (H.genExprVar c.fst) (H.genExprConst c.snd.bv))
                      let constrainedBVExpr := BoolExpr.not (bigAnd newConstraints)
                      return res ++ (← existsForAll (BoolExpr.gate .and origExpr constrainedBVExpr) existsVars forAllVars n)

RV64.div in RISCV.Instructions

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

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

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

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

Equivalence.mk in Init.Core

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

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

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

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

instance : HydrableReduceWidth ParsedFpExpr FpPredicate FpExpr where
  shrink := shrink

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

def worklist.St.meas (st : worklist.St A S) : ℕ :=
  Finset.card $ Finset.univ |>.filter fun x => x ∉ st.map.keys ∨ x ∈ st.worklist.toList

def CliTest.params : CliTest → Type
| test => natParams test.mvars

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

def sll_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where
  lhs := sll_llvm_i32
  rhs := sll_riscv_i32

def or_or_xor_before := [llvm|
{
^0(%arg106 : i4, %arg107 : i4, %arg108 : i4):
  %0 = llvm.or %arg108, %arg106 : i4
  %1 = llvm.or %arg108, %arg107 : i4
  %2 = llvm.xor %0, %1 : i4
  "llvm.return"(%2) : (i4) -> ()
}
]

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 test4_after := [llvm|
{
^0(%arg206 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

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

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

List.toFinsupp in Mathlib.Data.List.ToFinsupp

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

def fold_xor_zext_icmp_before := [llvm|
{
^0(%arg91 : i64, %arg92 : i64, %arg93 : i64):
  %0 = llvm.icmp "sgt" %arg91, %arg92 : i64
  %1 = llvm.zext %0 : i1 to i8
  %2 = llvm.icmp "slt" %arg91, %arg93 : i64
  %3 = llvm.zext %2 : i1 to i8
  %4 = llvm.xor %1, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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

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

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

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

def udiv_exact_ne_30_no_of_before := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(30 : i8) : i8
  %2 = llvm.and %arg1, %0 : i8
  %3 = llvm.udiv exact %arg0, %2 : i8
  %4 = llvm.icmp "ne" %3, %1 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

def foo_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(223 : i32) : i32
  %1 = llvm.mlir.constant(29 : i32) : i32
  %2 = llvm.mlir.constant(-784568073 : i32) : i32
  %3 = llvm.mlir.constant(1874836915 : i32) : i32
  %4 = llvm.mlir.constant(221 : i32) : i32
  %5 = llvm.mlir.constant(1 : i32) : i32
  %6 = llvm.mlir.constant(1533579450 : i32) : i32
  %7 = llvm.mlir.constant(-2147483648 : i32) : i32
  %8 = llvm.mlir.constant(749011377 : i32) : i32
  %9 = llvm.and %arg0, %0 : i32
  %10 = llvm.xor %9, %1 : i32
  %11 = llvm.add %10, %2 overflow<nuw> : i32
  %12 = llvm.or %10, %3 : i32
  %13 = llvm.and %10, %4 : i32
  %14 = llvm.xor %13, %3 : i32
  %15 = llvm.xor %12, %14 : i32
  %16 = llvm.shl %15, %5 overflow<nsw,nuw> : i32
  %17 = llvm.sub %11, %16 : i32
  %18 = llvm.add %17, %6 overflow<nsw> : i32
  %19 = llvm.or %18, %7 : i32
  %20 = llvm.xor %19, %8 : i32
  "llvm.return"(%20) : (i32) -> ()
}
]

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

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

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

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

def select_icmp_x_and_8_ne_0_y_xor_8_after := [llvm|
{
^0(%arg177 : i32, %arg178 : i64):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.and %arg177, %0 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.zext nneg %2 : i32 to i64
  %4 = llvm.xor %arg178, %3 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

def sdiv_pow2_256 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64):
      %c = llvm.mlir.constant (256) : 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 (56) : i64
      %c2 = llvm.mlir.constant (8) : 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 or_test1_before := [llvm|
{
^0(%arg2 : i32, %arg3 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.and %arg2, %0 : i32
  %2 = llvm.or %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

RV64.rolw in RISCV.Instructions

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

def add_smax_simplify_before := [llvm|
{
^0(%arg25 : i8):
  %0 = llvm.mlir.constant(126 : i8) : i8
  %1 = llvm.mlir.constant(-2 : i8) : i8
  %2 = llvm.add %arg25, %0 overflow<nsw> : i8
  %3 = llvm.icmp "sgt" %2, %1 : i8
  %4 = "llvm.select"(%3, %2, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

def fsmMsbAux : FSM Bool where
  
  α := Unit
  initCarry := fun () => false
  outputCirc :=
    let s : Circuit (Unit ⊕ (Bool)) := Circuit.var (positive := true) (.inl ())
    let x : Circuit (Unit ⊕ (Bool)) := Circuit.var (positive := true) (.inr false)
    let w : Circuit (Unit ⊕ (Bool))  := Circuit.var (positive := true) (.inr true)
    Circuit.ite w 
    x 
    s 
  nextStateCirc := fun () =>
    let s : Circuit (Unit ⊕ (Bool)) := Circuit.var (positive := true) (.inl ())
    let x : Circuit (Unit ⊕ (Bool)) := Circuit.var (positive := true) (.inr false)
    let w : Circuit (Unit ⊕ (Bool)) := Circuit.var (positive := true) (.inr true)
    
    Circuit.ite w 
      x 
      s  

def addMax (a : BitVec v) (b : BitVec w) : BitVec (max v w + 1) :=
   a.zeroExtend _ + b.zeroExtend _

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

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

def test_before := [llvm|
{
^0(%arg1 : i32):
  %0 = llvm.mlir.constant(12 : i32) : i32
  %1 = llvm.mlir.constant(-6 : i32) : i32
  %2 = llvm.sdiv %arg1, %0 : i32
  %3 = llvm.icmp "ne" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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

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

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

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

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

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

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

@[simp]
abbrev LLVMPlusRiscV : Dialect where
  Op := Op
  Ty := Ty

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

def icmp_equality_test_commute_select1_before := [llvm|
{
^0(%arg17 : i64, %arg18 : i64, %arg19 : i64):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.icmp "eq" %arg17, %arg19 : i64
  %2 = llvm.icmp "eq" %arg18, %arg19 : i64
  %3 = llvm.icmp "eq" %arg17, %arg18 : i64
  %4 = "llvm.select"(%2, %0, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = "llvm.select"(%1, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (i1) -> ()
}
]

Lean.Parser.Term.matchAltExpr in Lean.Parser.Term
</all_available_defs>

<all_available_lemmas>
BitVec.getElem_signExtend in Init.Data.BitVec.Lemmas
BitVec.getLsbD_signExtend in Init.Data.BitVec.Lemmas
BitVec.msb_eq_getLsbD_last in Init.Data.BitVec.Lemmas

@[simp] theorem and_eq : (x &&& y) i = (x i && y i)

@[simp]
theorem FSM.eval_and' (a b : FSM arity) : (a &&& b).eval env = a.eval env &&& b.eval env

theorem FSM.and_eq (a b : FSM arity) : (a &&& b) = composeBinaryAux' FSM.and a b

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

theorem ashr_ult_noexact_proof : ashr_ult_noexact_before ⊑ ashr_ult_noexact_after

theorem select_non_const_sides_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  x_1 = 1#1 → x - zeroExtend 64 x_1 = x + -1#64

theorem unsigned_sign_bit_extract_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → ofBool (x >>> 31#32 != 0#32) = ofBool (x <ₛ 0#32)

@[simp] theorem tail_corec : tail (corec b f) = corec (f b).snd f

theorem sge_swap_or_not_max_commute_proof : sge_swap_or_not_max_commute_before ⊑ sge_swap_or_not_max_commute_after

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

theorem e_1374 :
     - 1 *  ~~~(z ^^^ t) - 2 *  ~~~(z &&&  ~~~t) - 6 * t + 7 * (z |||  ~~~t) + 1 * (z ||| t) + 7 *  ~~~(z &&&  ~~~z) - 2 *  ~~~z + 7 *  ~~~t + 2 *  ~~~(z |||  ~~~t) - 6 * (z &&& t) = 22 * (z &&&  ~~~t) + 16 *  ~~~(z ||| t)

theorem scalar_i32_shl_and_negC_eq_nonzero_proof : scalar_i32_shl_and_negC_eq_nonzero_before ⊑ scalar_i32_shl_and_negC_eq_nonzero_after

theorem t1_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 16),
  ¬(x ≥ ↑32 ∨ (2#32 <<< x == 0 || 32 != 1 && zeroExtend 32 x_1 == intMin 32 && 2#32 <<< x == -1) = true) →
    x + 1#32 ≥ ↑32 → False

theorem cond_eq_or_const_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != 10#8) = 1#1 → ofBool (x_1 <ᵤ x) = ofBool (10#8 <ᵤ x)

theorem or_not_and_and_not_and_xor_commute5_proof : or_not_and_and_not_and_xor_commute5_before ⊑ or_not_and_and_not_and_xor_commute5_after

theorem sge_swap_and_max_commute_logical_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬ofBool (x == 127#8) = 1#1 → 0#1 = ofBool (x == 127#8)

theorem and_sext_sext_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 4),
  signExtend 16 x_1 &&& signExtend 16 x = signExtend 16 (x &&& signExtend 8 x_1)

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

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

@[simp]
theorem FSM.eval_ite_eq_decide {α : Type}
    (cond t e : FSM α)
    (env : α → BitStream) (i : Nat) :
    (FSM.ite cond t e).eval env i =
    if (cond.eval env i) then t.eval env i else e.eval env i

theorem add_eq_xor_add_mul_and_2 (x y : BitVec w) :
    x + y = (x ^^^ y) + (x &&& y) <<< 1

theorem xor_signbit_select_ashr_proof : xor_signbit_select_ashr_before ⊑ xor_signbit_select_ashr_after

theorem xor_icmp_true_signed_thm (e : IntW 32) :
  LLVM.xor (icmp IntPred.sgt e (const? 32 5)) (icmp IntPred.slt e (const? 32 6)) ⊑ const? 1 1

theorem icmp_equality_test_commute_select2_proof : icmp_equality_test_commute_select2_before ⊑ icmp_equality_test_commute_select2_after

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

theorem prove_exact_with_high_mask_limit_proof : prove_exact_with_high_mask_limit_before ⊑ prove_exact_with_high_mask_limit_after

theorem or_not_and_commute8_proof : or_not_and_commute8_before ⊑ or_not_and_commute8_after

theorem alive_AddSub_1539_2  (w : Nat)   : alive_AddSub_1539_2_src w  ⊑ alive_AddSub_1539_2_tgt w

theorem or_not_and_and_not_and_xor_commute3_proof : or_not_and_and_not_and_xor_commute3_before ⊑ or_not_and_and_not_and_xor_commute3_after

theorem e_1390 :
     - 6 *  ~~~(z ^^^ t) + 5 * t + 2 *  ~~~z - 11 *  ~~~(z &&&  ~~~z) + 11 * (z ||| t) - 6 * (z ^^^ t) - 7 * (z |||  ~~~t) - 1 *  ~~~(z |||  ~~~t) + 18 * (z &&&  ~~~t) + 13 * (z &&& t) = 5 * z - 22 *  ~~~(z ||| t)

theorem trunc_sel_smaller_sext_proof : trunc_sel_smaller_sext_before ⊑ trunc_sel_smaller_sext_after

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

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

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

theorem lshrugt_03_08_exact_proof : lshrugt_03_08_exact_before ⊑ lshrugt_03_08_exact_after

theorem shl_and_lshr_proof : shl_and_lshr_before ⊑ shl_and_lshr_after

theorem test15c_proof : test15c_before ⊑ test15c_after

theorem test1_proof : test1_before ⊑ test1_after

theorem width2 {v w : Nat} (x : BitVec v) :
    x.signExtend (max v (min v w)) = x.zeroExtend (max v (min v w))

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

theorem e_1168 :
     - 1 * t + 4 *  ~~~t + 5 *  ~~~(z ^^^ t) - 11 *  ~~~(z &&&  ~~~t) + 13 *  ~~~(z ||| t) + 23 *  ~~~(z |||  ~~~t) + 7 * (z &&&  ~~~t) + 7 * (z &&& t) = 11 *  ~~~(z &&& t)

theorem test9_proof : test9_before ⊑ test9_after

theorem foo1_or_commuted_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (icmp IntPred.ne (LLVM.and (mul e_2 e_2) (shl (const? 32 1) e_1)) (const? 32 0))
      (icmp IntPred.ne (LLVM.and (shl (const? 32 1) e) (mul e_2 e_2)) (const? 32 0)) ⊑
    icmp IntPred.eq
      (LLVM.and (mul e_2 e_2)
        (LLVM.or (shl (const? 32 1) e_1 { «nsw» := false, «nuw» := true })
          (shl (const? 32 1) e { «nsw» := false, «nuw» := true })))
      (LLVM.or (shl (const? 32 1) e_1 { «nsw» := false, «nuw» := true })
        (shl (const? 32 1) e { «nsw» := false, «nuw» := true }))

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 addsub_combine_constants_thm (e e_1 : IntW 7) :
  add (add e_1 (const? 7 42)) (sub (const? 7 10) e) { «nsw» := true, «nuw» := false } ⊑
    add (sub e_1 e) (const? 7 52)

theorem sgt_smin4_proof : sgt_smin4_before ⊑ sgt_smin4_after

theorem ashrslt_01_05_thm.extracted_1._1 : ∀ (x : BitVec 4), ¬1#4 ≥ ↑4 → ofBool (x.sshiftRight' 1#4 <ₛ 5#4) = 1#1

theorem xor_i8_to_i64_shl_save_and_ne_thm (e : IntW 64) (e_1 : IntW 8) :
  select (icmp IntPred.ne (LLVM.and e_1 (const? 8 1)) (const? 8 0)) (LLVM.xor e (const? 64 (-9223372036854775808)))
      e ⊑
    LLVM.xor e (shl (zext 64 e_1) (const? 64 63))

theorem e_1549 :
     - 1 * ((a &&& c) ||| (b &&&  ~~~c)) + 1 * (b ^^^  ~~~(a &&& (b ||| c))) + 1 * ((a &&& c) |||  ~~~(b ||| c)) + 3 * ((a ||| b) &&&  ~~~(b ^^^ c)) + 5 * (c ||| (a &&&  ~~~b)) + 11 * (c ^^^ ( ~~~a ||| (b ||| c))) - 10 *  ~~~(a ||| ( ~~~b ||| c)) - 10 *  ~~~( ~~~a ||| (b ||| c)) - 11 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 6 * ( ~~~a &&& ( ~~~b &&& c)) - 8 * ( ~~~a &&& (b &&& c)) - 5 * (a &&& ( ~~~b &&& c)) - 9 * (a &&& (b &&& c)) = 13 *  ~~~(a ||| (b ||| c))

theorem badimm4_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 (127#16 <ₛ x) = 1#1 → truncate 8 x = 126#8

theorem select_add_icmp_bad_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 == 1#32) = 1#1 → x_2 + x_1 = x_1 + 1#32

theorem shift_xor_multiuse_cmp_with_xor_thm.extracted_1._3 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ofBool (0#32 != x_3 &&& 4096#32) = 1#1 → ofBool (x_3 &&& 4096#32 == 0#32) = 1#1 → x_2 * x_1 = (x_2 ^^^ 2048#32) * x

theorem e_1721 :
     - 1 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 2 * (a ^^^ c) - 3 * ((a ^^^ b) ||| (a ^^^ c)) - 5 * ((a |||  ~~~b) &&& (b ^^^ c)) - 1 * (c ^^^ (a &&& ( ~~~b ||| c))) + 5 * ( ~~~a ||| (b ^^^ c)) - 7 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) + 2 * (a ^^^ ( ~~~b &&& c)) + 2 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 7 * (c |||  ~~~(a ||| b)) + 7 * ( ~~~(a |||  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 6 * (b ^^^ ( ~~~a ||| (b &&& c))) + 11 * (c &&&  ~~~(a ^^^ b)) + 1 * (a ^^^ ( ~~~b ||| c)) - 1 * (a ||| (b ^^^ c)) - 5 * (b ^^^ (a &&& c)) - 6 * (b |||  ~~~(a |||  ~~~c)) + 5 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) + 2 * (a &&& (b ||| c)) - 1 * ((a &&& c) ||| (b &&&  ~~~c)) - 3 * (a |||  ~~~c) - 7 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) - 11 * (c ||| (a &&& b)) + 16 *  ~~~(a ||| (b ||| c)) + 16 *  ~~~(a ||| ( ~~~b ||| c)) + 13 *  ~~~( ~~~a ||| (b ||| c)) + 41 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 25 * ( ~~~a &&& ( ~~~b &&& c)) + 28 * ( ~~~a &&& (b &&& c)) + 20 * (a &&& ( ~~~b &&& c)) + 10 * (a &&& (b &&& c)) = 3 * (a &&& ( ~~~b ||| c))

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

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

theorem e_2282 :
    1 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 11 *  ~~~(d &&& (e &&& f)) + 4 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 1 * (d &&&  ~~~f) - 1 * (e ^^^  ~~~(d &&& (e ||| f))) + 5 * (f ^^^  ~~~(d &&& (e ||| f))) - 2 * ((d ^^^ e) &&& (d ^^^ f)) + 1 * (d ^^^ ( ~~~e &&& f)) + 2 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) - 1 * (e ||| (d ^^^ f)) + 4 * (f |||  ~~~(d ^^^ e)) + 5 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * (d ^^^ (e ^^^ f)) - 1 * ( ~~~d ||| ( ~~~e &&& f)) - 1 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 4 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) + 2 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) - 2 *  ~~~e - 5 * ((d &&& f) ^^^ (e ||| f)) - 5 *  ~~~(d &&& e) + 4 * (d ||| (e &&& f)) - 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 2 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 2 *  ~~~d + 7 *  ~~~(d ||| ( ~~~e &&& f)) + 3 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 3 * ((d &&& e) ^^^ (e ||| f)) - 7 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) - 11 *  ~~~( ~~~d &&& (e ||| f)) - 6 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 7 * ((e &&& f) ||| (d &&& (e ||| f))) + 11 * (d &&&  ~~~e) - 1 *  ~~~(d |||  ~~~f) - 1 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 11 * ( ~~~d &&& (e ||| f)) - 1 * (e &&& (d ||| f)) + 1 *  ~~~(d ^^^ (e ||| f)) - 1 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) - 2 * ( ~~~e &&&  ~~~(d ^^^ f)) - 11 *  ~~~(e &&& f) + 2 * (e ^^^ (d ||| (e ||| f))) + 4 * (e ^^^ ( ~~~d ||| (e &&& f))) + 3 * (f &&& (d ^^^ e)) + 2 * (e ^^^ (d ||| ( ~~~e &&& f))) - 6 * (f ^^^ (d &&& e)) + 2 * ( ~~~e |||  ~~~(d ^^^ f)) - 7 *  ~~~(d ^^^ (e ^^^ f)) - 11 *  ~~~(e &&&  ~~~f) - 11 * (d ||| f) - 11 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 7 * ( ~~~d &&& (e ^^^ f)) + 2 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 25 *  ~~~(d ||| (e ||| f)) + 4 *  ~~~(d ||| ( ~~~e ||| f)) + 44 *  ~~~( ~~~d ||| (e ||| f)) + 13 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 33 * ( ~~~d &&& ( ~~~e &&& f)) + 28 * ( ~~~d &&& (e &&& f)) + 7 * (d &&& ( ~~~e &&& f)) + 33 * (d &&& (e &&& f)) = 5 * (d ^^^ (e ||| f)) + 7 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f))

theorem badimm4_thm.extracted_1._5 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 8#16 ≥ ↑16) →
    ¬ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 8#16)) = 1#1 →
      ¬15#16 ≥ ↑16 →
        ¬ofBool (127#16 <ₛ x) = 1#1 →
          ¬ofBool (x <ₛ BitVec.ofInt 16 (-128)) = 1#1 → truncate 8 (x.sshiftRight' 15#16) ^^^ 126#8 = truncate 8 x

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

theorem t3_ult_sgt_neg1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 + 16#32 <ᵤ 144#32) = 1#1 → ofBool (127#32 <ₛ x_1) = 1#1 → x_1 = x

theorem t3_const_after_fold_lshr_shl_ne_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(32#32 - x_1 ≥ ↑32 ∨ x_1 + -1#32 ≥ ↑32) → 31#32 ≥ ↑32 → False

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

theorem test3_apint_thm (e e_1 : IntW 47) :
  LLVM.xor (LLVM.and (LLVM.xor e_1 (const? 47 (-1))) (LLVM.xor e (const? 47 (-1)))) (const? 47 (-1)) ⊑
    LLVM.or e_1 e

theorem test_ule_xor_proof : test_ule_xor_before ⊑ test_ule_xor_after

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

theorem test_proof : test_before ⊑ test_after

theorem only_one_masked_proof : only_one_masked_before ⊑ only_one_masked_after

@[simp_denote] theorem HVector.cons_inj {α : Type u_1} {f : α → Type u_2}
    {as : List α} {a : α}  (x y : f a) (xs ys : HVector f as) :
    @Eq (no_index _) (x ::ₕ xs) (y ::ₕ ys) ↔ (x = y ∧ xs = ys)

theorem ugt_or_not_min_commute_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 != 0#8) = 1#1 → 1#1 = ofBool (x_1 != 0#8)

theorem icmp_equality_test_wrong_and_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 64),
  ¬ofBool (x_2 == x_1) = 1#1 → ofBool (x == x_1) ^^^ 1#1 = 1#1 → ofBool (x == x_1) = 1#1 → 0#1 = ofBool (x_2 == x)

theorem testi8i8_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬7#8 ≥ ↑8 → ofBool (-1#8 <ₛ x) = 1#1 → x.sshiftRight' 7#8 ^^^ 127#8 = 127#8

theorem mul_of_udiv_fail_bad_remainder_proof : mul_of_udiv_fail_bad_remainder_before ⊑ mul_of_udiv_fail_bad_remainder_after

@[simp] theorem Com.outContextHom_var :
    (var e body : Com d Γ eff t).outContextHom
    = e.contextHom.comp body.outContextHom

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

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

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

theorem AvoidCollision_toNat_signExtend (x : BitVec w) {v : Nat} :
    (x.signExtend v).toNat = (x.setWidth v).toNat + if x.msb then 2^v - 2^w else 0

theorem ashr_lshr_inv2_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 <ₛ 7#32) = 1#1 → ¬x ≥ ↑32 → x_1 >>> x = x_1.sshiftRight' x

theorem icmp_select_var_pred_uge_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == 0#8) = 1#1 → ¬(True ∧ x.uaddOverflow 2#8 = true) → ofBool (x_1 != 0#8) = 1#1 → False

theorem or_xor_tree_0001_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  x_2 * 42#32 ^^^ x_1 * 42#32 ||

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

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

theorem lshr_xor_thm (e e_1 : IntW 8) :
  shl (LLVM.xor (lshr e_1 (const? 8 3)) (LLVM.srem e (const? 8 42))) (const? 8 3) ⊑
    LLVM.xor (LLVM.and e_1 (const? 8 (-8))) (shl (LLVM.srem e (const? 8 42)) (const? 8 3))

lemma unopNfa_bv_language (op : Unop) :
    m.bv_recognizes L → (unopNfa op m).bv_recognizes Lᶜ

theorem zext_sext_add_icmp_slt_1_type_not_i1_proof : zext_sext_add_icmp_slt_1_type_not_i1_before ⊑ zext_sext_add_icmp_slt_1_type_not_i1_after

theorem both_proof : both_before ⊑ both_after

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

theorem or_or_logic_and_1_thm.extracted_1._4 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 ||

theorem and_sequence_15_eq (w : Nat) :
    and_sequence_15_lhs w  ⊑ and_sequence_15_rhs w

theorem or_logic_or_logic_and_3_thm (e e_1 e_2 : IntW 1) :
  select (select e_2 (const? 1 1) e_1) (LLVM.or e_2 e) (const? 1 0) ⊑
    select e_2 (const? 1 1) (select e_1 e (const? 1 0))

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

theorem icmp_eq_x_invertable_y2_todo_proof : icmp_eq_x_invertable_y2_todo_before ⊑ icmp_eq_x_invertable_y2_todo_after

theorem mul_select_sext_thm (e : IntW 1) :
  mul (select e (const? 64 64) (const? 64 1)) (sext 64 e) ⊑ select e (const? 64 (-64)) (const? 64 0)

theorem t2_proof : t2_before ⊑ t2_after

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

theorem alive_InstCombineShift__582 : alive_InstCombineShift__582_src ⊑ alive_InstCombineShift__582_tgt

theorem zext_sext_add_icmp_ne_1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ofBool (zeroExtend 8 x_1 + signExtend 8 x != 1#8) = x ||

theorem const_sub_sub_const_thm (e : IntW 32) : sub (sub (const? 32 8) e) (const? 32 2) ⊑ sub (const? 32 6) e

theorem testi64i32_ne_proof : testi64i32_ne_before ⊑ testi64i32_ne_after

theorem test5_thm.extracted_1._1 : ∀ (x : BitVec 700),
  (x ||| 288230376151711743#700) ^^^ 288230376151711743#700 = x &&& BitVec.ofInt 700 (-288230376151711744)

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 test16_proof : test16_before ⊑ test16_after

theorem ashrsgt_01_00_thm (e : IntW 4) :
  icmp IntPred.sgt (ashr e (const? 4 1)) (const? 4 0) ⊑ icmp IntPred.sgt e (const? 4 1)

theorem logic_or_logic_and_8_proof : logic_or_logic_and_8_before ⊑ logic_or_logic_and_8_after

theorem test6_proof : test6_before ⊑ test6_after

theorem lshrult_02_00_proof : lshrult_02_00_before ⊑ lshrult_02_00_after

theorem positive_with_extra_and_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(ofBool (x + 128#32 <ᵤ 256#32) = 1#1 ∧ ofBool (-1#32 <ₛ x) = 1#1) → ofBool (x <ᵤ 128#32) = 1#1 → False

theorem test_zext_nneg_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 32) (x_2 : BitVec 64),
  ¬(True ∧ (x_1 ^^^ -1#32).msb = true) →
    x_2 + BitVec.ofInt 64 (-5) - (zeroExtend 64 (x_1 ^^^ -1#32) + x) =
      x_2 + BitVec.ofInt 64 (-4) + (signExtend 64 x_1 - x)

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

theorem EqualUpTo_ofBitVecZext_add (a b : BitVec w) :
    EqualUpTo w
    (BitStream.ofBitVecZext a + BitStream.ofBitVecZext b)
    (BitStream.ofBitVecZext (a + b))

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

theorem evalAux_eq_zero_of_set {arity : Type _} (p : FSM arity)
    (R : Set (p.α → Bool)) (hR : ∀ x s, (p.nextBit s x).1 ∈ R → s ∈ R)
    (hi : p.initCarry ∉ R) (hr1 : ∀ x s, (p.nextBit s x).2 = true → s ∈ R)
    (x : arity → BitStream) (n : ℕ) : p.eval x n = false ∧ p.carry x n ∉ R

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

theorem test9_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& BitVec.ofInt 32 (-2147483648) != 0#32) = ofBool (x <ₛ 0#32)

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

theorem eq_mul_constants_with_tz_proof : eq_mul_constants_with_tz_before ⊑ eq_mul_constants_with_tz_after

theorem n7_proof : n7_before ⊑ n7_after

theorem main6d_logical_thm (e : IntW 32) :
  select
      (select (icmp IntPred.ne (LLVM.and e (const? 32 7)) (const? 32 3)) (const? 1 1)
        (icmp IntPred.eq (LLVM.and e (const? 32 16)) (const? 32 0)))
      (const? 32 0) (const? 32 1) ⊑
    zext 32 (icmp IntPred.eq (LLVM.and e (const? 32 23)) (const? 32 19))

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

theorem zext_sext_sle_known_nonneg_op0_narrow_proof : zext_sext_sle_known_nonneg_op0_narrow_before ⊑ zext_sext_sle_known_nonneg_op0_narrow_after

theorem bitwise_and_logical_and_masked_icmp_allzeros_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 8#32 == 0#32) = 1#1 →
    ¬ofBool (x &&& 15#32 == 0#32) = 1#1 → 0#1 &&& ofBool (x &&& 7#32 == 0#32) = 0#1

theorem ashrsgt_01_01_exact_proof : ashrsgt_01_01_exact_before ⊑ ashrsgt_01_01_exact_after

theorem shl_nsw_add_negative_invalid_constant3_proof : shl_nsw_add_negative_invalid_constant3_before ⊑ shl_nsw_add_negative_invalid_constant3_after

omit [Fintype S] [DecidableEq S] [LawfulBEq A] in
theorem addOrCreateState_grow (st : worklist.St A S) (b : Bool) (sa : S) :
    let (_, st') := st.addOrCreateState _ _ b sa
    ∃ sas, List.Perm st'.map.keys (sas ++ st.map.keys) ∧ st'.worklist.toList = st.worklist.toList ++ sas

theorem lshr_mul_times_5_div_4_exact_thm (e : IntW 32) :
  lshr (mul e (const? 32 5) { «nsw» := true, «nuw» := false }) (const? 32 2) { «exact» := true } ⊑
    add e (lshr e (const? 32 2) { «exact» := true }) { «nsw» := true, «nuw» := false }

theorem ashrsgt_03_01_thm (e : IntW 4) : icmp IntPred.sgt (ashr e (const? 4 3)) (const? 4 1) ⊑ const? 1 0

theorem t2_proof : t2_before ⊑ t2_after

theorem uge_and_max_proof : uge_and_max_before ⊑ uge_and_max_after

theorem rawspeed_signbit_proof : rawspeed_signbit_before ⊑ rawspeed_signbit_after

theorem or_logic_or_logic_and_7_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → ¬True → x ||

theorem ne_umax1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x <ᵤ x_1) = 1#1 → ofBool (x != x_1) = ofBool (x_1 <ᵤ x)

theorem negate_sdiv_thm (e e_1 : IntW 8) :
  sub e_1 (LLVM.sdiv e (const? 8 42)) ⊑ add (LLVM.sdiv e (const? 8 (-42))) e_1

theorem lshr_or_and_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ¬(5#8 ≥ ↑8 ∨ 5#8 ≥ ↑8) → 5#8 ≥ ↑8 → False

theorem test_shift_and_cmp_changed1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(5#8 ≥ ↑8 ∨ 5#8 ≥ ↑8) →
    ¬5#8 ≥ ↑8 →
      ofBool (((x_1 &&& 8#8 ||| x &&& 6#8) <<< 5#8).sshiftRight' 5#8 <ₛ 1#8) =
        ofBool (x <<< 5#8 &&& BitVec.ofInt 8 (-64) <ₛ 32#8)

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 sdiv_exact_eq_9_no_of_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ x_1.smod (x &&& 7#8) ≠ 0 ∨ (x &&& 7#8 == 0 || 8 != 1 && x_1 == intMin 8 && x &&& 7#8 == -1) = true) →
    ¬(True ∧ (x &&& 7#8).smulOverflow 9#8 = true ∨ True ∧ (x &&& 7#8).umulOverflow 9#8 = true) →
      ofBool (x_1.sdiv (x &&& 7#8) == 9#8) = ofBool ((x &&& 7#8) * 9#8 == x_1)

theorem e_1864 :
    7 * (c &&&  ~~~(a &&& b)) + 3 * (c ^^^  ~~~(a &&& (b ||| c))) - 2 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c))) - 1 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 11 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) - 7 * ((a &&& b) |||  ~~~(b ||| c)) + 7 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) + 3 * (a &&&  ~~~c) + 3 *  ~~~(b &&& c) - 3 *  ~~~c + 4 * ( ~~~c &&& (a ^^^ b)) - 6 * (b ^^^ (a &&& (b ||| c))) + 5 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) - 11 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 2 * (c ^^^ ( ~~~a ||| (b &&& c))) + 1 *  ~~~( ~~~a &&& (b ^^^ c)) + 2 * (b |||  ~~~(a ||| c)) - 7 * ((a &&& c) ^^^  ~~~(b &&&  ~~~c)) - 1 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) - 1 * (b ||| c) - 6 * (a &&&  ~~~b) - 3 *  ~~~(a ||| ( ~~~b &&& c)) + 1 *  ~~~( ~~~a ||| (b ^^^ c)) - 11 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) + 1 * (b ^^^ (a ||| ( ~~~b &&& c))) - 11 * (b ^^^ (a &&& (b ^^^ c))) - 5 * ( ~~~a &&& (b ^^^ c)) - 6 * (b ^^^  ~~~(a |||  ~~~c)) + 5 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c))) + 7 *  ~~~(a &&& (b ||| c)) - 7 * (c &&&  ~~~(a ^^^ b)) - 1 * (c ^^^  ~~~(a &&& b)) + 4 * (b ^^^ (a ||| ( ~~~b ||| c))) + 11 * (b ^^^  ~~~( ~~~a &&& (b &&& c))) - 1 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 1 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 1 * ( ~~~(a ||| b) ||| (b ^^^ c)) - 2 *  ~~~(a ||| (b &&& c)) + 5 * ( ~~~b &&&  ~~~(a ^^^ c)) + 1 *  ~~~(a ||| (b ||| c)) + 27 *  ~~~(a ||| ( ~~~b ||| c)) - 1 *  ~~~( ~~~a ||| (b ||| c)) + 20 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 18 * ( ~~~a &&& (b &&& c)) + 10 * (a &&& ( ~~~b &&& c)) + 40 * (a &&& (b &&& c)) = 7 * (b &&& (a |||  ~~~c)) + 2 *  ~~~(a &&& c)

theorem icmp_slt_0_or_icmp_sgt_0_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  zeroExtend 32 (ofBool (x <ₛ 0#32)) ||

theorem srem2_ashr_mask_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬((2#32 == 0 || 32 != 1 && x == intMin 32 && 2#32 == -1) = true ∨ 31#32 ≥ ↑32) →
    (2#32 == 0 || 32 != 1 && x == intMin 32 && 2#32 == -1) = true → False

theorem p_constmask2_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ (x_1 &&& 61440#32 &&& (x &&& BitVec.ofInt 32 (-65281)) != 0) = true) →
    x_1 &&& 61440#32 ^^^ x &&& BitVec.ofInt 32 (-65281) = x_1 &&& 61440#32 ||

theorem canonicalize_logic_first_or0_nsw_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.saddOverflow 112#32 = true) → True ∧ (x ||| 15#32).saddOverflow 112#32 = true → False

@[simp]
theorem shiftLeft_and_distrib' {x y : BitVec w} {n m : Nat} :
    x <<< n &&& y <<< (m + n) = (x &&& y <<< m) <<< n

theorem t0_thm (e : IntW 8) :
  LLVM.sdiv e (const? 8 32) { «exact» := true } ⊑ ashr e (const? 8 5) { «exact» := true }

theorem n1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x_1 ≥ ↑8 → True ∧ ((-1#8) <<< x_1).sshiftRight' x_1 ≠ -1#8 ∨ x_1 ≥ ↑8 → False

theorem ult_and_max_commute_proof : ult_and_max_commute_before ⊑ ult_and_max_commute_after

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

theorem eval_mkInitCarryAssignCircuit_eq_false_iff {arity : Type _}
  [DecidableEq arity]
  [Fintype arity]
  [Hashable arity]
  (p : FSM arity)
  {env : Vars p.α arity 0 → Bool} :
  (mkInitCarryAssignCircuit p).eval env = false ↔
  (∀ (s : p.α), p.initCarry s = env (Vars.state0 s))

theorem shl_nsw_sgt_n1_proof : shl_nsw_sgt_n1_before ⊑ shl_nsw_sgt_n1_after

@[simp] theorem neg_ofNat_one_eq : - (BitStream.ofNat 1) = negOne

@[simp] theorem poison_bind : poison >>= f = poison

theorem two_signed_truncation_checks_proof : two_signed_truncation_checks_before ⊑ two_signed_truncation_checks_after

theorem icmp_select_implied_cond_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == 0#8) = 1#1 → ofBool (0#8 == x_1) = 1#1

theorem e_63 :
     - 2 *  ~~~x + 11 *  ~~~(x &&&  ~~~x) - 5 * x - 9 *  ~~~(x |||  ~~~y) - 6 * (x &&& y) = 6 * (x &&&  ~~~y) + 9 *  ~~~(x ||| y)

@[simp]
theorem Term.toBV_and {wenv : WidthExpr.Env wcard}
    {tctx : Term.Ctx wcard tcard}
    (benv : Term.BoolEnv bcard)
    (tenv : tctx.Env wenv)
    (p1 p2 : Term bcard ncard icard pcard tctx (.prop)) :
  Term.toBV benv nenv ienv penv tenv (.and p1 p2) = (p1.toBV benv nenv ienv penv tenv ∧ p2.toBV benv nenv ienv penv tenv)

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 trunc_unsigned_nsw_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  ¬(True ∧ signExtend 16 (truncate 8 x_1) ≠ x_1 ∨ True ∧ signExtend 16 (truncate 8 x) ≠ x) →
    ofBool (truncate 8 x_1 <ᵤ truncate 8 x) = ofBool (x_1 <ᵤ x)

theorem t0_const_after_fold_lshr_shl_ne_thm (e : IntW 64) (e_1 e_2 : IntW 32) :
  icmp IntPred.ne
      (LLVM.and (lshr e_2 (sub (const? 32 32) e_1)) (trunc 32 (shl e (zext 64 (add e_1 (const? 32 (-1)))))))
      (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and e (zext 64 (lshr e_2 (const? 32 31)) { «nneg» := true })) (const? 64 0)

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

theorem multiuse_lshr_lshr_thm.extracted_1._1 : ∀ (x : BitVec 9),
  ¬(2#9 ≥ ↑9 ∨ 2#9 ≥ ↑9 ∨ 3#9 ≥ ↑9) → 2#9 ≥ ↑9 ∨ 5#9 ≥ ↑9 → False

theorem add_nsw_or_and_thm (e e_1 : IntW 32) :
  add (LLVM.or e_1 e) (LLVM.and e_1 e) { «nsw» := true, «nuw» := false } ⊑
    add e_1 e { «nsw» := true, «nuw» := false }

theorem mul_of_pow2_commute_thm (e e_1 : IntW 32) :
  icmp IntPred.ugt (mul (LLVM.and e_1 (const? 32 255)) (LLVM.and e (const? 32 4))) (const? 32 1020) ⊑
    const? 1 0

@[simp]
lemma product_accept {M : NFA α σ} {N : NFA α ς} :
    (q1, q2) ∈ (M.product accept? N).accept ↔ accept? (q1 ∈ M.accept) (q2 ∈ N.accept)

theorem ashrsgt_01_13_thm (e : IntW 4) :
  icmp IntPred.sgt (ashr e (const? 4 1)) (const? 4 (-3)) ⊑ icmp IntPred.sgt e (const? 4 (-5))

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 dec_mask_commute_neg_i32_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬((x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨
        (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true) →
    ¬((x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨
          True ∧ ((42#32).sdiv x).saddOverflow (-1#32) = true ∨
            (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true) →
      ((42#32).sdiv x &&& 0#32 - (42#32).sdiv x) + -1#32 = (42#32).sdiv x + -1#32 &&& ((42#32).sdiv x ^^^ -1#32)

theorem icmp_slt_0_and_icmp_sge_neg2_i64_proof : icmp_slt_0_and_icmp_sge_neg2_i64_before ⊑ icmp_slt_0_and_icmp_sge_neg2_i64_after

@[simp] theorem ExtEq.rfl {Γ : Context Ty} : Γ.ExtEq Γ

theorem set_bits_proof : set_bits_before ⊑ set_bits_after

theorem e_1893 :
    11 * ((a &&& b) ^^^ (b ||| c)) + 4 * ( ~~~(a ||| b) |||  ~~~(a ^^^ (b ^^^ c))) + 2 * (c ^^^  ~~~(a &&&  ~~~b)) + 5 * (b ^^^ (a &&&  ~~~c)) + 5 * (b ^^^ (a ||| c)) + 5 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) - 2 * ((a &&& b) ^^^ (b |||  ~~~c)) + 11 * (a ||| (b ^^^ c)) + 3 * (a &&& (b ^^^ c)) + 7 * (b &&&  ~~~c) + 7 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) + 3 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 5 * (c ||| (a ^^^ b)) - 3 * (b ||| c) - 1 * (b |||  ~~~(a ^^^ c)) - 11 * (a ^^^ (b &&& c)) + 7 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 7 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 11 *  ~~~(a ^^^ c) + 2 * (c ^^^ (a |||  ~~~b)) - 1 * ( ~~~c ||| (a ^^^ b)) - 2 * (b ^^^ ( ~~~a &&& (b ^^^ c))) - 7 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) + 1 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) - 3 * (b |||  ~~~(a ||| c)) - 2 * (b |||  ~~~(a |||  ~~~c)) + 7 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 1 * (c ^^^  ~~~(a |||  ~~~b)) - 6 * ((b &&& c) ||| (a &&& (b ||| c))) + 1 *  ~~~(b ^^^ c) + 3 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c))) - 5 *  ~~~(a &&& b) - 6 * ( ~~~(a ||| b) ||| (b ^^^ c)) + 3 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) + 4 * (a ||| b) + 11 * ( ~~~c |||  ~~~(a ^^^ b)) + 1 * (b ^^^ c) - 7 *  ~~~( ~~~a &&& ( ~~~b ||| c)) - 7 *  ~~~(a &&&  ~~~a) - 2 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c))) - 2 * (c ^^^ (a ||| ( ~~~b ||| c))) - 13 *  ~~~(a ||| (b ||| c)) - 34 *  ~~~(a ||| ( ~~~b ||| c)) - 10 *  ~~~( ~~~a ||| (b ||| c)) - 14 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 30 * ( ~~~a &&& ( ~~~b &&& c)) + 3 * ( ~~~a &&& (b &&& c)) - 1 * (a &&& ( ~~~b &&& c)) - 22 * (a &&& (b &&& c)) =  - 2 * (b ^^^  ~~~(a ||| (b &&& c)))

theorem C0zero_thm.extracted_1._5 : ∀ (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 e_5 :
     - 1 *  ~~~y + 2 *  ~~~(x &&& y) - 1 *  ~~~(x |||  ~~~y) - 1 * (x &&&  ~~~y) = 1 *  ~~~x

theorem PR42691_8_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x <ₛ 14#32) = 1#1 →
    ofBool (x != BitVec.ofInt 32 (-2147483648)) = ofBool (x + 2147483647#32 <ᵤ BitVec.ofInt 32 (-2147483635))

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

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

theorem mul_selectp2_x_propegate_nuw_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 1),
  x_1 = 1#1 →
    ¬(True ∧ (2#8).smulOverflow x = true ∨ True ∧ (2#8).umulOverflow x = true) →
      ¬(True ∧ x <<< 1#8 >>> 1#8 ≠ x ∨ 1#8 ≥ ↑8) → 2#8 * x = x <<< 1#8

@[bv_automata_nnf] theorem Bool.and_eq_false : ((a && b) = false) = (a = false ∨ b = false)

theorem e_1355 :
     - 1 * z + 5 * (z |||  ~~~t) - 1 *  ~~~z - 2 *  ~~~(z &&& t) + 2 *  ~~~(z &&&  ~~~t) + 5 *  ~~~(z &&&  ~~~z) + 4 *  ~~~(z ^^^ t) - 13 *  ~~~(z ||| t) - 7 * (z &&&  ~~~t) - 15 * (z &&& t) = 4 *  ~~~(z |||  ~~~t)

theorem icmp_sle8_proof : icmp_sle8_before ⊑ icmp_sle8_after

theorem t1_flags_nuw_only_proof : t1_flags_nuw_only_before ⊑ t1_flags_nuw_only_after

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

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

theorem test70_thm (e e_1 : IntW 8) :
  select (icmp IntPred.slt e_1 (const? 8 0)) (LLVM.or e (const? 8 2)) e ⊑
    LLVM.or e (LLVM.and (lshr e_1 (const? 8 6)) (const? 8 2))

lemma reduce_stepSet' {M : NFA α σ} (q : M.Reachable) (S1 : Set M.Reachable) (S2 : Set σ) :
    (∀ q, (∃ hq, S1 ⟨q, hq⟩) ↔ S2 q) →
    (q ∈ M.reduce.stepSet S1 a → q.val ∈ M.stepSet S2 a)

theorem and_umax_less_proof : and_umax_less_before ⊑ and_umax_less_after

theorem ugt_and_not_min_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.ugt e_1 e) (icmp IntPred.ne e_1 (const? 8 0)) ⊑ icmp IntPred.ugt e_1 e

theorem test_lshr__exact_is_unsafe_thm.extracted_1._3 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 63#32 == 0#32) = 1#1 →
    ¬(2#32 ≥ ↑32 ∨ zeroExtend 64 ((x_1 &&& 63#32) >>> 2#32) ≥ ↑64) →
      2#32 ≥ ↑32 ∨ True ∧ (x_1 >>> 2#32 &&& 15#32).msb = true ∨ zeroExtend 64 (x_1 >>> 2#32 &&& 15#32) ≥ ↑64 → False

theorem or_and_not_not_wrong_a_proof : or_and_not_not_wrong_a_before ⊑ or_and_not_not_wrong_a_after

theorem sgt_or_not_min_proof : sgt_or_not_min_before ⊑ sgt_or_not_min_after

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

theorem select_icmp_ne_0_and_4096_xor_32_proof : select_icmp_ne_0_and_4096_xor_32_before ⊑ select_icmp_ne_0_and_4096_xor_32_after

theorem main5f_like_logical_thm.extracted_1._8 : ∀ (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 → ¬True → 0#32 = zeroExtend 32 0#1

theorem test23_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (1#32 <ₛ x) &&& ofBool (x ≤ₛ 2#32) = ofBool (x == 2#32)

theorem and_zext_eq_odd_proof : and_zext_eq_odd_before ⊑ and_zext_eq_odd_after

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

theorem trunc_shl_shl_infloop_proof : trunc_shl_shl_infloop_before ⊑ trunc_shl_shl_infloop_after

theorem test17_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬x = 0 → 1#32 % x = zeroExtend 32 (ofBool (x != 1#32))

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

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 f_var0_commutative_and_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 &&& x == 0#32) = 1#1 → 1#32 = zeroExtend 32 (ofBool (x &&& (x_1 ||| 2#32) != 0#32))

theorem sub_shl_same_amount_partial_nsw2_proof : sub_shl_same_amount_partial_nsw2_before ⊑ sub_shl_same_amount_partial_nsw2_after

theorem main7e_logical_thm.extracted_1._16 : ∀ (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 (ofBool (x_1 &&& x &&& x_2 != x_1 &&& x))

theorem or_and2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), x_1 ^^^ 1#1 ||

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

theorem test68_xor_thm.extracted_1._4 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 128#32 == 0#32) = 1#1 → ¬6#32 ≥ ↑32 → x ^^^ 2#32 = x ^^^ x_1 >>> 6#32 &&& 2#32

theorem test11_thm (e : IntW 737) :
  icmp IntPred.ne (LLVM.and e (const? 737 (-2147483648))) (const? 737 0) ⊑
    icmp IntPred.ugt e (const? 737 2147483647)

theorem bad_shl2_sub_i32_proof : bad_shl2_sub_i32_before ⊑ bad_shl2_sub_i32_after

theorem lshr_lshr_pow2_const_negative_nopow2_1_thm (e : IntW 16) :
  LLVM.and (lshr (lshr (const? 16 2047) e) (const? 16 6)) (const? 16 4) ⊑
    LLVM.and (lshr (const? 16 31) e) (const? 16 4)

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

theorem icmp_eq_or_z_or_pow2orz_proof : icmp_eq_or_z_or_pow2orz_before ⊑ icmp_eq_or_z_or_pow2orz_after

theorem src_x_and_nmask_sge_proof : src_x_and_nmask_sge_before ⊑ src_x_and_nmask_sge_after

theorem ashr_mul_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬8#20 ≥ ↑20 → True ∧ (signExtend 16 x_1).smulOverflow (signExtend 16 x) = true ∨ 8#16 ≥ ↑16 → False

theorem f_t15_t01_t09_thm.extracted_1._1 : ∀ (x : BitVec 40),
  ¬(31#40 ≥ ↑40 ∨ 16#32 ≥ ↑32) →
    15#40 ≥ ↑40 ∨ True ∧ signExtend 40 (truncate 32 (x.sshiftRight' 15#40)) ≠ x.sshiftRight' 15#40 → False

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

theorem t2_proof : t2_before ⊑ t2_after

theorem bv_AndOrXor_2231__A__B__B__C__A___A__B__C :
    ∀ (e e_1 e_2 : LLVM.IntW w), LLVM.or (LLVM.xor e e_2) (LLVM.xor (LLVM.xor e_2 e_1) e) ⊑ LLVM.or (LLVM.xor e e_2) e_1

theorem test8_proof : test8_before ⊑ test8_after

theorem test68_proof : test68_before ⊑ test68_after

theorem main3_logical_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 0#32) = 1#1 → 0#1 = 1#1 → 0#32 = zeroExtend 32 (ofBool (x &&& 55#32 != 0#32))

theorem sub_zext_trunc_lshr_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬15#64 ≥ ↑64 →
    ¬(16#32 ≥ ↑32 ∨ 31#32 ≥ ↑32 ∨ True ∧ ((truncate 32 x <<< 16#32).sshiftRight' 31#32).saddOverflow 10#32 = true) →
      10#32 - zeroExtend 32 (truncate 1 (x >>> 15#64)) = (truncate 32 x <<< 16#32).sshiftRight' 31#32 + 10#32

theorem test8_proof : test8_before ⊑ test8_after

theorem neg_mask_const_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(True ∧ (1000#32).ssubOverflow (signExtend 32 x) = true ∨
        15#16 ≥ ↑16 ∨ True ∧ (0#32).ssubOverflow (zeroExtend 32 (x >>> 15#16)) = true) →
    ofBool (x <ₛ 0#16) = 1#1 → True ∧ (1000#32).ssubOverflow (signExtend 32 x) = true → False

@[simp] theorem lt_length (v : Γ.Var t) : v.1 < Γ.length

theorem test12_proof : test12_before ⊑ test12_after

theorem foo1_and_signbit_lshr_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (icmp IntPred.eq (LLVM.and (shl (const? 32 1) e_2) e_1) (const? 32 0))
      (icmp IntPred.eq (LLVM.and (lshr (const? 32 (-2147483648)) e) e_1) (const? 32 0)) ⊑
    icmp IntPred.ne
      (LLVM.and e_1
        (LLVM.or (shl (const? 32 1) e_2 { «nsw» := false, «nuw» := true })
          (lshr (const? 32 (-2147483648)) e { «exact» := true })))
      (LLVM.or (shl (const? 32 1) e_2 { «nsw» := false, «nuw» := true })
        (lshr (const? 32 (-2147483648)) e { «exact» := true }))

theorem or_nosignbit_ashr_proof : or_nosignbit_ashr_before ⊑ or_nosignbit_ashr_after

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

theorem ult_toNat (x y : BitVec n) :
    (BitVec.ult (n := n) x y) = decide (x.toNat < y.toNat)

theorem select_1_thm.extracted_1._14 : ∀ (x x_1 : BitVec 8) (x_2 x_3 : BitVec 1),
  ¬x_3 = 1#1 → x_2 = 1#1 → x_1 ^^^ -1#8 ^^^ -1#8 = x_1

theorem icmp_ne_and_pow2_minus1_shl1_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → zeroExtend 32 (ofBool (1#32 <<< x &&& 15#32 != 0#32)) = zeroExtend 32 (ofBool (x <ᵤ 4#32))

theorem ne_shift_in_zeros_thm (e e_1 : IntW 32) :
  LLVM.or (icmp IntPred.ne (trunc 24 (lshr e_1 (const? 32 16))) (trunc 24 (lshr e (const? 32 16))))
      (icmp IntPred.ne (trunc 8 (lshr e_1 (const? 32 8))) (trunc 8 (lshr e (const? 32 8)))) ⊑
    icmp IntPred.ugt (LLVM.xor e_1 e) (const? 32 255)

private theorem BitVec.getLsbD_zeroExtend_eq_getLsbD (x : BitVec wold) (wnew : Nat) :
    (x.zeroExtend wnew).getLsbD i = ((x.getLsbD i) ∧ (i ≤ wnew - 1) ∧ (wnew ≠ 0))

theorem shl_add_nuw_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x &&& 2#8 ≥ ↑8 → True ∧ (x_1 &&& 63#8) <<< (x &&& 2#8) >>> (x &&& 2#8) ≠ x_1 &&& 63#8 ∨ x &&& 2#8 ≥ ↑8 → False

theorem positive_with_extra_and_logical_thm (e : IntW 1) (e_1 : IntW 32) :
  select (icmp IntPred.ult (add e_1 (const? 32 128)) (const? 32 256))
      (select (icmp IntPred.sgt e_1 (const? 32 (-1))) e (const? 1 0)) (const? 1 0) ⊑
    select (icmp IntPred.ult e_1 (const? 32 128)) e (const? 1 0)

theorem sext_sext_ult_proof : sext_sext_ult_before ⊑ sext_sext_ult_after

theorem lshrugt_01_12_exact_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 1) { «exact» := true }) (const? 4 (-4)) ⊑ const? 1 0

theorem src_is_notmask_ashr_thm (e : IntW 16) (e_1 : IntW 8) (e_2 : IntW 16) :
  icmp IntPred.eq (LLVM.xor e_2 (const? 16 123))
      (LLVM.and (LLVM.xor e_2 (const? 16 123))
        (LLVM.xor (ashr (sext 16 (shl (const? 8 (-32)) e_1)) e) (const? 16 (-1)))) ⊑
    icmp IntPred.uge (LLVM.xor e_2 (const? 16 (-124))) (ashr (sext 16 (shl (const? 8 (-32)) e_1)) e)

theorem ne_3210_proof : ne_3210_before ⊑ ne_3210_after

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

theorem and_xor_common_op_commute2_proof : and_xor_common_op_commute2_before ⊑ and_xor_common_op_commute2_after

theorem shl_sub_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(3#8 ≥ ↑8 ∨ 2#8 ≥ ↑8) → ¬(5#8 ≥ ↑8 ∨ 2#8 ≥ ↑8) → (x_1 <<< 3#8 - x) <<< 2#8 = x_1 <<< 5#8 - x <<< 2#8

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

@[grind =, simp, aesop 50% unsafe]
lemma states_addFinal (m : RawCNFA A) (s' : State) :
    (m.addFinal s').states = m.states

theorem positive_samevar_proof : positive_samevar_before ⊑ positive_samevar_after

theorem bitwise_and_logical_and_masked_icmp_allzeros_poison1_proof : bitwise_and_logical_and_masked_icmp_allzeros_poison1_before ⊑ bitwise_and_logical_and_masked_icmp_allzeros_poison1_after

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

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

theorem e_1601 :
    4 * (b ^^^ ( ~~~a ||| (b ^^^ c))) + 7 * (b |||  ~~~c) - 3 *  ~~~b + 5 * ( ~~~b &&& (a ^^^ c)) + 1 * (c ^^^  ~~~(a &&& b)) + 2 * (b ||| (a ^^^ c)) + 4 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 1 *  ~~~( ~~~a &&& (b ^^^ c)) + 1 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 11 * (c ^^^ (a &&& ( ~~~b ||| c))) - 8 *  ~~~(a ||| (b ||| c)) - 14 *  ~~~(a ||| ( ~~~b ||| c)) - 19 *  ~~~( ~~~a ||| (b ||| c)) - 15 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 24 * ( ~~~a &&& ( ~~~b &&& c)) - 22 * ( ~~~a &&& (b &&& c)) + 3 * (a &&& ( ~~~b &&& c)) - 15 * (a &&& (b &&& c)) = 6 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c)))

theorem src_x_and_nmask_slt_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(x ≥ ↑8 ∨ x ≥ ↑8) → True ∧ ((-1#8) <<< x).sshiftRight' x ≠ -1#8 ∨ x ≥ ↑8 → False

theorem sub_undemanded_low_bits_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬4#32 ≥ ↑32 → ((x ||| 15#32) - 1616#32) >>> 4#32 = (x + BitVec.ofInt 32 (-1616)) >>> 4#32

theorem main14_logical_thm.extracted_1._1 : ∀ (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 → 1#32 = 2#32

theorem or_not_and_commute6_proof : or_not_and_commute6_before ⊑ or_not_and_commute6_after

theorem t0_proof : t0_before ⊑ t0_after

theorem test20_proof : test20_before ⊑ test20_after

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

theorem test_lshr__exact_is_safe_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))

theorem sextinreg2_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(24#32 ≥ ↑32 ∨ True ∧ x <<< 24#32 >>> 24#32 <<< 24#32 ≠ x <<< 24#32 ∨ 24#32 ≥ ↑32) →
    (x &&& 255#32 ^^^ 128#32) + BitVec.ofInt 32 (-128) = (x <<< 24#32).sshiftRight' 24#32

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

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

theorem e_88 :
    1 *  ~~~(x &&&  ~~~x) - 2 *  ~~~(x ||| y) - 3 *  ~~~(x |||  ~~~y) - 2 * (x &&&  ~~~y) - 3 * (x &&& y) =  - 1 *  ~~~y - 2 * y

theorem add_constant_equal_with_the_top_bit_of_demandedbits_insertpt_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  (x_1 + 16#32 ||| x) &&& 24#32 = (x_1 ^^^ 16#32 ||| x) &&& 24#32

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

@[bv_multi_width_normalize]
theorem allOnes_eq_minus_one : BitVec.allOnes w = -1#w

@[simp]
lemma Fin.clamp_neq_bound : Fin.clamp m n ≠ Fin.last n ↔ m < n

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

theorem e_2253 :
    1 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) - 1 *  ~~~(d ||| (e &&& f)) - 2 * ( ~~~e ||| (d ^^^ f)) + 1 * (f ^^^ ( ~~~d ||| (e ||| f))) + 2 * (e &&& f) - 11 * (e ^^^ (d ||| ( ~~~e &&& f))) - 2 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) - 6 *  ~~~(d &&& ( ~~~e ||| f)) - 1 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 4 *  ~~~( ~~~d &&& (e ||| f)) - 11 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 6 * (e ^^^  ~~~(d &&& (e ||| f))) - 11 * (d ||| ( ~~~e &&& f)) + 1 *  ~~~(e ||| f) - 7 *  ~~~(d &&& ( ~~~e &&& f)) - 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 2 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) - 1 * (d &&& e) - 2 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 1 * (f &&& (d |||  ~~~e)) + 5 * ( ~~~d ||| ( ~~~e &&& f)) + 1 *  ~~~(d |||  ~~~e) + 11 *  ~~~( ~~~d ||| (e ^^^ f)) + 11 * (e ^^^  ~~~(d &&& (e ^^^ f))) - 5 * (e ||| f) - 2 * d - 6 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 1 * (e ^^^ ( ~~~d ||| (e &&& f))) + 3 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) + 11 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 5 * (e &&&  ~~~f) + 1 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 7 *  ~~~d + 2 *  ~~~( ~~~d &&& ( ~~~e &&& f)) - 7 * (d ^^^ (e ^^^ f)) + 4 * (d |||  ~~~e) - 2 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 2 *  ~~~(e |||  ~~~f) - 6 * (e |||  ~~~f) - 2 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) - 6 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 3 *  ~~~( ~~~d ||| ( ~~~e &&& f)) + 3 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) - 5 * (e ^^^ (d ||| (e &&& f))) + 1 * ( ~~~(d &&& e) &&& (e ^^^ f)) - 7 *  ~~~( ~~~d ||| (e &&& f)) - 3 * ((d ||| e) &&& (e ^^^ f)) + 7 * (e ^^^ ( ~~~d ||| (e ||| f))) + 7 * ( ~~~e &&&  ~~~(d ^^^ f)) - 17 *  ~~~(d ||| (e ||| f)) + 27 *  ~~~(d ||| ( ~~~e ||| f)) + 26 *  ~~~( ~~~d ||| (e ||| f)) + 43 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 36 * ( ~~~d &&& ( ~~~e &&& f)) + 33 * ( ~~~d &&& (e &&& f)) + 18 * (d &&& ( ~~~e &&& f)) + 21 * (d &&& (e &&& f)) =  - 2 * (f ^^^  ~~~(d ||| (e &&& f)))

theorem mul64_low_thm.extracted_1._1 : ∀ (x x_1 : BitVec 64),
  ¬(32#64 ≥ ↑64 ∨ 32#64 ≥ ↑64 ∨ 32#64 ≥ ↑64) →
    (x_1 >>> 32#64 * (x &&& 4294967295#64) + (x_1 &&& 4294967295#64) * x >>> 32#64) <<< 32#64 +
        (x_1 &&& 4294967295#64) * (x &&& 4294967295#64) =
      x * x_1

theorem expand_thm (e : IntW 32) :
  LLVM.and (LLVM.or (LLVM.and e (const? 32 1)) (const? 32 2)) (const? 32 1) ⊑ LLVM.and e (const? 32 1)

theorem reduce_xor_common_op_commute0_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 4),
  x_2 ^^^ x_1 ^^^ x ||

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

theorem badimm1_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 9#16 ≥ ↑16) →
    ¬ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 9#16)) = 1#1 →
      ¬15#16 ≥ ↑16 →
        7#8 ≥ ↑8 ∨
            9#16 ≥ ↑16 ∨
              True ∧ signExtend 16 (truncate 8 (x >>> 9#16)) ≠ x >>> 9#16 ∨
                True ∧ zeroExtend 16 (truncate 8 (x >>> 9#16)) ≠ x >>> 9#16 →
          False

theorem ne_smax3_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (add e_1 (const? 32 3))
      (select (icmp IntPred.sgt (add e_1 (const? 32 3)) e) (add e_1 (const? 32 3)) e) ⊑
    icmp IntPred.slt (add e_1 (const? 32 3)) e

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

theorem testi16i8_ne_proof : testi16i8_ne_before ⊑ testi16i8_ne_after

theorem negative3_proof : negative3_before ⊑ negative3_after

theorem t0_commutative_thm.extracted_1._3 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 x_3 : BitVec 8),
  ofBool (x_3 == x_2) = 1#1 → ofBool (x_3 != x_2) = 1#1 → x_1 ^^^ 1#1 = 1#1 → False

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 e_1608 :
     - 1 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 5 *  ~~~(a &&& (b &&& c)) - 2 * c - 7 *  ~~~(a &&& c) - 1 *  ~~~(b ||| c) + 11 *  ~~~(a ||| ( ~~~b &&& c)) - 7 *  ~~~(a &&& (b ^^^ c)) - 6 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) - 2 * (b ||| (a &&&  ~~~c)) - 1 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 2 * (b ^^^ ( ~~~a &&& (b ^^^ c))) + 2 * (c ^^^ (a &&& (b ||| c))) + 1 *  ~~~(a ||| ( ~~~b ||| c)) + 19 *  ~~~( ~~~a ||| (b ||| c)) + 12 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 17 * ( ~~~a &&& ( ~~~b &&& c)) + 9 * ( ~~~a &&& (b &&& c)) + 4 * (a &&& ( ~~~b &&& c)) + 12 * (a &&& (b &&& c)) =  - 2 * (c &&&  ~~~(a ^^^ b))

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)

@[simp] theorem toList_append : (Γ ++ Δ).toList = Γ.toList ++ Δ.toList

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

theorem select_icmp_eq_0_and_1_xor_1_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 64),
  ofBool (x_1 &&& 1#64 == 0#64) = 1#1 → x = x ^^^ truncate 32 x_1 &&& 1#32

theorem xor_ashr_not_fail_lshr_ashr_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(x_1 ≥ ↑8 ∨ x_1 ≥ ↑8) →
    x_2 >>> x_1 ^^^ (x.sshiftRight' x_1 ^^^ -1#8) = x.sshiftRight' x_1 ^^^ x_2 >>> x_1 ^^^ -1#8

theorem add_of_mul_thm (e e_1 e_2 : IntW 8) :
  add (mul e_2 e_1 { «nsw» := true, «nuw» := false }) (mul e_2 e { «nsw» := true, «nuw» := false })
      { «nsw» := true, «nuw» := false } ⊑
    mul e_2 (add e_1 e)

theorem test_mul_nsw__none_are_safe_proof : test_mul_nsw__none_are_safe_before ⊑ test_mul_nsw__none_are_safe_after

theorem t2_thm (e : IntW 7) : sext 16 (trunc 4 (lshr e (const? 7 3))) ⊑ sext 16 (ashr e (const? 7 3))

theorem sub_sel_op1_thm.extracted_1._1 : ∀ (x : BitVec 1),
  x = 1#1 → ¬(True ∧ (42#32).ssubOverflow 42#32 = true) → 42#32 - 42#32 = zeroExtend 32 (x ^^^ 1#1)

theorem positive_biggershl_shlnuwnsw_proof : positive_biggershl_shlnuwnsw_before ⊑ positive_biggershl_shlnuwnsw_after

theorem test_sub_0_Y_eq_0_proof : test_sub_0_Y_eq_0_before ⊑ test_sub_0_Y_eq_0_after

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

theorem fold_add_udiv_urem_proof : fold_add_udiv_urem_before ⊑ fold_add_udiv_urem_after

theorem simplify_or_common_op_commute2_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 4),
  x_3 * x_3 &&& (x_2 &&& x_1) &&& x ^^^ -1#4 ||

theorem ugt_253_proof : ugt_253_before ⊑ ugt_253_after

theorem test_thm.extracted_1._1 : ∀ (x : BitVec 32), x + 5#32 + BitVec.ofInt 32 (-5) = x

theorem test_const_shr_and_1_ne_0_i1_negative_thm (e : IntW 1) :
  icmp IntPred.ne (LLVM.and (lshr (const? 1 1) e) (const? 1 1)) (const? 1 0) ⊑ const? 1 1

theorem or_or_and_pat3_proof : or_or_and_pat3_before ⊑ or_or_and_pat3_after

theorem n8_wrong_pred3_proof : n8_wrong_pred3_before ⊑ n8_wrong_pred3_after

theorem nonexact_lshr_ne_proof : nonexact_lshr_ne_before ⊑ nonexact_lshr_ne_after

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

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

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

theorem test3_proof : test3_before ⊑ test3_after

theorem sle_smax3_proof : sle_smax3_before ⊑ sle_smax3_after

theorem add_select_not_zext_proof : add_select_not_zext_before ⊑ add_select_not_zext_after

theorem t1_sub_of_falseval_proof : t1_sub_of_falseval_before ⊑ t1_sub_of_falseval_after

theorem ugt_and_min_commute_logical_proof : ugt_and_min_commute_logical_before ⊑ ugt_and_min_commute_logical_after

theorem main3f_like_logical_thm.extracted_1._6 : ∀ (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 → ¬True → 0#32 = zeroExtend 32 (ofBool (x_2 &&& x == 0#32))

theorem negate_select_of_op_vs_negated_op_nsw_commuted_proof : negate_select_of_op_vs_negated_op_nsw_commuted_before ⊑ negate_select_of_op_vs_negated_op_nsw_commuted_after

@[simp] theorem map'_cons : map' f g (cons x xs) = cons (g _ x) (map' f g xs)

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

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 test8_proof : test8_before ⊑ test8_after

theorem select1_thm.extracted_1._5 : ∀ (x x_1 x_2 : BitVec 32) (x_3 : BitVec 1),
  ¬x_3 = 1#1 → zeroExtend 32 (truncate 8 x_1 + truncate 8 x) = x_1 + x &&& 255#32

theorem mul_splat_fold_no_nuw_thm (e : IntW 32) :
  lshr (mul e (const? 32 65537) { «nsw» := true, «nuw» := false }) (const? 32 16) ⊑
    add e (lshr e (const? 32 16)) { «nsw» := true, «nuw» := false }

theorem test13_proof : test13_before ⊑ test13_after

theorem test_ne_11_and_15_add_10_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (x + 10#8 &&& 15#8 != 11#8) = ofBool (x &&& 15#8 != 1#8)

@[grind =, simp, aesop 50% unsafe]
lemma newState_finals (m : RawCNFA A) :
    m.newState.2.finals = m.finals

theorem sdiv2_proof : sdiv2_before ⊑ sdiv2_after

theorem shl_xor_proof : shl_xor_before ⊑ shl_xor_after

theorem f2_proof : f2_before ⊑ f2_after

theorem zext_mul_proof : zext_mul_before ⊑ zext_mul_after

theorem zext_mul_thm (e : IntW 8) :
  LLVM.and (mul (zext 16 e) (const? 16 3)) (zext 16 e) ⊑ zext 16 (LLVM.and (mul e (const? 8 3)) e)

theorem test13_proof : test13_before ⊑ test13_after

theorem f_var0_proof : f_var0_before ⊑ f_var0_after

theorem test45_proof : test45_before ⊑ test45_after

theorem poo_thm (e e_1 e_2 e_3 : IntW 32) :
  LLVM.or (LLVM.and (select (icmp IntPred.slt e_3 e_2) (const? 32 (-1)) (const? 32 0)) e_1)
      (LLVM.and (select (icmp IntPred.slt e_3 e_2) (const? 32 0) (const? 32 (-1))) e) ⊑
    select (icmp IntPred.slt e_3 e_2) e_1 e

theorem sub_ule_sext_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 8),
  ofBool (x_2 - x_1 ≤ᵤ signExtend 8 x) = ofBool (x_2 == x_1) ||

theorem icmp_slt_0_xor_icmp_sgt_neg2_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 →
    x >>> 31#32 ^^^ zeroExtend 32 (ofBool (BitVec.ofInt 32 (-2) <ₛ x)) = zeroExtend 32 (ofBool (x != -1#32))

@[simp] theorem Hom.castDomain_rfl {h : Δ = Δ} {f : Γ.Hom Δ} :
    (f.castCodomain h) = f

theorem shift_xor_multiuse_cmp_and_thm.extracted_1._3 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ofBool (0#32 != x_3 &&& 4096#32) = 1#1 →
    ofBool (x_3 &&& 4096#32 == 0#32) = 1#1 →
      x_2 * x_1 * (x_2 &&& 2048#32) = (x_2 &&& 2048#32) * x * (x_2 &&& 2048#32)

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

theorem e_2432 :
    11 * ( ~~~e ||| (d ^^^ f)) - 1 * (e &&& f) + 1 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 1 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 1 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 6 * (d ||| (e ||| f)) + 1 * (e &&&  ~~~(d ^^^ f)) - 6 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) - 7 * (d ||| e) + 2 * (e ^^^ f) + 2 * (e |||  ~~~(d ^^^ f)) - 5 * (f ^^^  ~~~(d &&&  ~~~e)) + 1 * (f ^^^  ~~~(d ||| (e &&& f))) - 7 * (f ^^^ ( ~~~d ||| (e ||| f))) + 3 * (d ^^^ e) - 6 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) - 5 * (e |||  ~~~f) + 1 * (d ^^^ f) - 2 * (e ||| (d ^^^ f)) - 1 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 3 *  ~~~(d ||| ( ~~~e &&& f)) - 11 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) - 3 *  ~~~(d ^^^ (e ^^^ f)) + 7 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) - 5 * (d ^^^ ( ~~~e &&& f)) + 4 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) + 3 *  ~~~(d ^^^ ( ~~~e &&& f)) - 1 * ((d ^^^ e) &&& (d ^^^ f)) - 5 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) - 5 *  ~~~( ~~~d &&& ( ~~~e &&& f)) - 2 * ( ~~~f ||| (d ^^^ e)) + 1 * (e ^^^  ~~~(d &&& (e ||| f))) + 2 * (f ^^^ (d &&& (e ||| f))) + 1 * ((d ^^^ e) ||| (d ^^^ f)) + 2 * (d ^^^ (e &&& f)) - 5 * (e |||  ~~~(d ||| f)) - 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 4 * (e ^^^  ~~~(d &&& (e &&& f))) - 1 * (d ||| ( ~~~e &&& f)) + 7 * (f &&& (d ^^^ e)) + 5 *  ~~~(d &&& ( ~~~e &&& f)) + 11 * (d &&& f) + 1 * (f &&&  ~~~(d ^^^ e)) + 1 * d + 2 * (f &&&  ~~~(d &&&  ~~~e)) - 2 *  ~~~( ~~~d &&& ( ~~~e ||| f)) - 3 * ( ~~~d ||| ( ~~~e &&& f)) + 11 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) + 7 * ( ~~~(d &&& e) &&& (e ^^^ f)) - 2 *  ~~~( ~~~d &&& (e &&& f)) - 11 *  ~~~( ~~~d ||| ( ~~~e &&& f)) - 1 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) - 2 * (f ^^^  ~~~(d &&& (e ||| f))) - 2 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 5 * (d ^^^ (e ^^^ f)) + 2 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) + 7 * (e ||| (d &&& f)) - 1 * (d &&& ( ~~~e ||| f)) - 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 5 * ( ~~~d ||| (e ^^^ f)) + 5 * ( ~~~d ||| (e &&& f)) + 11 * (f ||| (d ^^^ e)) + 1 * ( ~~~d ||| (e ||| f)) + 2 * ((d &&& e) |||  ~~~(e ^^^ f)) - 2 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) - 1 * ( ~~~d &&& (e ||| f)) + 4 * ((e &&& f) ^^^  ~~~(d &&& (e ^^^ f))) - 2 *  ~~~(d ||| (e ||| f)) - 2 *  ~~~(d ||| ( ~~~e ||| f)) + 16 *  ~~~( ~~~d ||| (e ||| f)) + 15 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 41 * ( ~~~d &&& ( ~~~e &&& f)) - 26 * ( ~~~d &&& (e &&& f)) - 29 * (d &&& ( ~~~e &&& f)) - 17 * (d &&& (e &&& f)) = 1 * (e ||| (d &&&  ~~~f)) - 4 *  ~~~(d ^^^ ( ~~~e ||| f))

theorem ashr_xor_proof : ashr_xor_before ⊑ ashr_xor_after

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

theorem or_sext_to_sel_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → signExtend 32 x_1 ||

theorem test3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 49), ¬1#49 ≥ ↑49 → (x_1 ||| x <<< 1#49) &&& 1#49 = x_1 &&& 1#49

theorem neg_or_ashr_i32_proof : neg_or_ashr_i32_before ⊑ neg_or_ashr_i32_after

theorem or_test1_proof : or_test1_before ⊑ or_test1_after

theorem sgt_swap_and_min_commute_logical_proof : sgt_swap_and_min_commute_logical_before ⊑ sgt_swap_and_min_commute_logical_after

theorem zext_proof : zext_before ⊑ zext_after

theorem bool_eq0_logical_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ofBool (0#64 <ₛ x) = 1#1 → ofBool (ofBool (x == 1#64) == 0#1) = ofBool (1#64 <ₛ x)

theorem icmp_eq_x_invertable_y2_todo_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  x_2 = 1#1 → ofBool (7#8 == x ||| 7#8) = ofBool (x &&& BitVec.ofInt 8 (-8) == 0#8)

theorem bitwise_or_logical_or_icmps_comm1_thm (e e_1 e_2 : IntW 8) :
  LLVM.or (icmp IntPred.eq (LLVM.and e_2 (shl (const? 8 1) e_1)) (const? 8 0))
      (select (icmp IntPred.eq e (const? 8 42)) (const? 1 1)
        (icmp IntPred.eq (LLVM.and e_2 (const? 8 1)) (const? 8 0))) ⊑
    select (icmp IntPred.eq e (const? 8 42)) (const? 1 1)
      (icmp IntPred.ne
        (LLVM.and e_2 (LLVM.or (shl (const? 8 1) e_1 { «nsw» := false, «nuw» := true }) (const? 8 1)))
        (LLVM.or (shl (const? 8 1) e_1 { «nsw» := false, «nuw» := true }) (const? 8 1)))

theorem mul_splat_fold_too_narrow_proof : mul_splat_fold_too_narrow_before ⊑ mul_splat_fold_too_narrow_after

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

theorem not_xor_to_or_not4_proof : not_xor_to_or_not4_before ⊑ not_xor_to_or_not4_after

theorem bitwise_and_bitwise_and_icmps_comm2_proof : bitwise_and_bitwise_and_icmps_comm2_before ⊑ bitwise_and_bitwise_and_icmps_comm2_after

theorem test11_thm (e e_1 : IntW 32) :
  trunc 64 (shl (zext 128 e_1) (LLVM.and (zext 128 e) (const? 128 31))) ⊑
    shl (zext 64 e_1) (zext 64 (LLVM.and e (const? 32 31)) { «nneg» := true }) { «nsw» := true, «nuw» := true }

theorem eval_zext_multi_use_in_one_inst_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ (truncate 16 x &&& 5#16).smulOverflow (truncate 16 x &&& 5#16) = true ∨
        True ∧ (truncate 16 x &&& 5#16).umulOverflow (truncate 16 x &&& 5#16) = true) →
    True ∧ (truncate 16 x &&& 5#16).smulOverflow (truncate 16 x &&& 5#16) = true ∨
        True ∧ (truncate 16 x &&& 5#16).umulOverflow (truncate 16 x &&& 5#16) = true ∨
          True ∧ ((truncate 16 x &&& 5#16) * (truncate 16 x &&& 5#16)).msb = true →
      False

theorem fold_icmp_shl_nuw_c3_thm (e : IntW 32) :
  icmp IntPred.uge (shl (const? 32 48) e { «nsw» := false, «nuw» := true }) (const? 32 144) ⊑
    icmp IntPred.ugt e (const? 32 1)

theorem bools_thm (e e_1 e_2 : IntW 1) :
  LLVM.or (LLVM.and (LLVM.xor e_2 (const? 1 1)) e_1) (LLVM.and e_2 e) ⊑ select e_2 e e_1

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

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

theorem test_sext_zext_proof : test_sext_zext_before ⊑ test_sext_zext_after

theorem x_thm (e : IntW 32) :
  icmp IntPred.slt (LLVM.sdiv e (const? 32 65536)) (const? 32 (-65536)) ⊑ const? 1 0

theorem zext_or_eq_ult_add_thm.extracted_1._1 : ∀ (x : BitVec 32),
  zeroExtend 32 (ofBool (x + BitVec.ofInt 32 (-3) <ᵤ 3#32) ||| ofBool (x == 5#32)) =
    zeroExtend 32 (ofBool (x + BitVec.ofInt 32 (-3) <ᵤ 3#32))

@[simp]
theorem Array.not_elem_back_pop (a : Array X) (x : X) : a.toList.Nodup → a.back? = some x → x ∉ a.pop

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

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 basic_com_add_proof : basic_com_add_before ⊑ basic_com_add_after

theorem dialect_mul_f_eq_zero (a : R q n) : a * (f q n) = 0

theorem udiv_i80_proof : udiv_i80_before ⊑ udiv_i80_after

theorem eval_eq_false_iff_toAIG_unsat {α : Type}
    [DecidableEq α] [Fintype α] [Hashable α]
    {c : Circuit α} :
    (∀ env, c.eval env = false) ↔ c.toAIG.val.Unsat

theorem xor_icmp_true_signed_commuted_proof : xor_icmp_true_signed_commuted_before ⊑ xor_icmp_true_signed_commuted_after

theorem test38_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ (x &&& 240#32).msb = true) → (zeroExtend 64 x ^^^ 7#64) &&& 240#64 = zeroExtend 64 (x &&& 240#32)

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

theorem test_sext_zext_thm (e : IntW 16) : sext 64 (zext 32 e) ⊑ zext 64 e

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 masked_and_notallzeroes_logical_proof : masked_and_notallzeroes_logical_before ⊑ masked_and_notallzeroes_logical_after

theorem or_xor_tree_0111_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  x_2 * 42#32 ^^^ x_1 * 42#32 ||

theorem test56_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬5#32 ≥ ↑32 → 5#32 ≥ ↑32 ∨ True ∧ (signExtend 32 x >>> 5#32).msb = true → 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 e_1427 :
     - 11 *  ~~~(z &&& t) - 11 *  ~~~(z &&&  ~~~t) - 2 * z - 5 * t - 1 *  ~~~(z ^^^ t) + 1 * (z ||| t) + 23 *  ~~~(z ||| t) + 25 *  ~~~(z |||  ~~~t) + 11 * (z &&&  ~~~t) + 18 * (z &&& t) =  - 1 * (z ^^^ t)

theorem AvoidCollision_toNat_setWidth_of_le {w w' : Nat} {b : BitVec w} (h : w ≤ w') : (b.setWidth w').toNat = b.toNat

theorem cmpeq_xor_cst1_commuted_proof : cmpeq_xor_cst1_commuted_before ⊑ cmpeq_xor_cst1_commuted_after

theorem mul_add_to_mul_1_proof : mul_add_to_mul_1_before ⊑ mul_add_to_mul_1_after

theorem test7_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (0#32 ≤ᵤ x) = 1#1

theorem xor_icmp_true_signed_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (5#32 <ₛ x) ^^^ ofBool (x <ₛ 6#32) = 1#1

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

theorem lshr_16_to_64_add_zext_basic_proof : lshr_16_to_64_add_zext_basic_before ⊑ lshr_16_to_64_add_zext_basic_after

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

theorem sub_zext_trunc_lshr_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬15#64 ≥ ↑64 →
    16#32 ≥ ↑32 ∨ 31#32 ≥ ↑32 ∨ True ∧ ((truncate 32 x <<< 16#32).sshiftRight' 31#32).saddOverflow 10#32 = true →
      False

theorem fold_eq_lhs_fail_eq_nonzero_proof : fold_eq_lhs_fail_eq_nonzero_before ⊑ fold_eq_lhs_fail_eq_nonzero_after

theorem absdiff_thm.extracted_1._1 : ∀ (x x_1 : BitVec 64),
  ofBool (x_1 <ᵤ x) = 1#1 →
    (signExtend 64 (ofBool (x_1 <ᵤ x)) ^^^ x_1 - x) - signExtend 64 (ofBool (x_1 <ᵤ x)) = 0#64 - (x_1 - x)

@[simp] theorem appendCases_appendInr (v : Γ.Var t) :
    appendCases (motive := motive) left right v.appendInr = (right v)

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

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

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

theorem factorize3_proof : factorize3_before ⊑ factorize3_after

theorem udiv_i80_thm (e : IntW 80) :
  LLVM.udiv (lshr e (const? 80 2)) (const? 80 100) ⊑ LLVM.udiv e (const? 80 400)

theorem negative_with_uniform_bad_mask_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& BitVec.ofInt 32 (-16777152) == 0#32) = 1#1 →
    ofBool (x + 128#32 <ᵤ 256#32) =
      ofBool (x &&& BitVec.ofInt 32 (-16777152) == 0#32) &&& ofBool (x + 128#32 <ᵤ 256#32)

theorem not_mul_of_pow2_proof : not_mul_of_pow2_before ⊑ not_mul_of_pow2_after

theorem cmpeq_xor_cst1_commuted_thm (e e_1 : IntW 32) :
  icmp IntPred.eq (mul e_1 e_1) (LLVM.xor e (const? 32 10)) ⊑
    icmp IntPred.eq (LLVM.xor e (mul e_1 e_1)) (const? 32 10)

theorem e_1283 :
     - 11 * t - 6 *  ~~~t + 4 *  ~~~(z &&&  ~~~t) - 7 *  ~~~z - 1 *  ~~~(z ^^^ t) - 6 * (z ^^^ t) + 10 *  ~~~(z ||| t) + 12 * (z &&&  ~~~t) + 8 * (z &&& t) =  - 20 *  ~~~(z |||  ~~~t)

theorem ne_210_proof : ne_210_before ⊑ ne_210_after

theorem alive_AndOrXor_1683_2 : alive_AndOrXor_1683_2_src ⊑ alive_AndOrXor_1683_2_tgt

theorem bools_logical_commute0_proof : bools_logical_commute0_before ⊑ bools_logical_commute0_after

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

theorem land_bor_right1_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → x ||

theorem sgt_smax4_thm (e e_1 : IntW 32) :
  icmp IntPred.slt (add e_1 (const? 32 3))
      (select (icmp IntPred.sgt e (add e_1 (const? 32 3))) e (add e_1 (const? 32 3))) ⊑
    icmp IntPred.sgt e (add e_1 (const? 32 3))

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

theorem n8_proof : n8_before ⊑ n8_after

theorem t0_thm.extracted_1._2 : ∀ (x : BitVec 16) (x_1 : BitVec 32),
  ¬(zeroExtend 32 (32#16 - x) ≥ ↑32 ∨ x + -1#16 ≥ ↑16) →
    ¬(31#32 ≥ ↑32 ∨
          True ∧ signExtend 32 (truncate 16 (x_1 >>> 31#32)) ≠ x_1 >>> 31#32 ∨
            True ∧ zeroExtend 32 (truncate 16 (x_1 >>> 31#32)) ≠ x_1 >>> 31#32) →
      truncate 16 (x_1 >>> zeroExtend 32 (32#16 - x)) >>> (x + -1#16) = truncate 16 (x_1 >>> 31#32)

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

theorem mul_of_pow2_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ofBool (510#32 <ᵤ (x_1 &&& 2#32) * zeroExtend 32 x) = 0#1

theorem n15_variable_shamts_thm (e e_1 : IntW 32) (e_2 e_3 : IntW 64) :
  icmp IntPred.ne (LLVM.and (trunc 32 (shl e_3 e_2)) (lshr e_1 e)) (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and (lshr e_1 e) (trunc 32 (shl e_3 e_2))) (const? 32 0)

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

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

theorem test_thm (e : IntW 32) :
  icmp IntPred.eq (LLVM.and (lshr (const? 32 3968) e) (const? 32 1)) (const? 32 0) ⊑
    icmp IntPred.eq (LLVM.and (shl (const? 32 1) e { «nsw» := false, «nuw» := true }) (const? 32 3968))
      (const? 32 0)

theorem bools_multi_uses2_logical_proof : bools_multi_uses2_logical_before ⊑ bools_multi_uses2_logical_after

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

theorem test13_proof : test13_before ⊑ test13_after

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

@[simp]
theorem denote_toAIG_eq_eval
    {α : Type} [DecidableEq α] [Fintype α] [Hashable α]
    {c : Circuit α}
    {env : α → Bool} :
    Std.Sat.AIG.denote env c.toAIG = c.eval env

theorem test_shl_nsw__nsw_is_safe_thm (e : IntW 32) :
  mul
      (mul
        (select (icmp IntPred.eq (LLVM.or e (const? 32 (-83886080))) (const? 32 (-83886079)))
          (const? 32 (-335544316))
          (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false }))
        (LLVM.or e (const? 32 (-83886080))))
      (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false }) ⊑
    mul
      (mul (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false })
        (LLVM.or e (const? 32 (-83886080))))
      (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false })

theorem ashr_and_proof : ashr_and_before ⊑ ashr_and_after

theorem lshr_C1_add_A_C2_i32_proof : lshr_C1_add_A_C2_i32_before ⊑ lshr_C1_add_A_C2_i32_after

theorem sub_to_xor_or_commuted_proof : sub_to_xor_or_commuted_before ⊑ sub_to_xor_or_commuted_after

theorem or_simplify_ugt_fail_proof : or_simplify_ugt_fail_before ⊑ or_simplify_ugt_fail_after

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

theorem mul_add_to_mul_3_thm (e : IntW 16) :
  add (mul e (const? 16 2)) (mul e (const? 16 3)) { «nsw» := true, «nuw» := false } ⊑ mul e (const? 16 5)

theorem ule_umax4_proof : ule_umax4_before ⊑ ule_umax4_after

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

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

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

theorem icmp_select_const_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == 0#8) = 1#1 → ofBool (0#8 == 0#8) = 1#1

theorem positive_sameconst_shlnuw_proof : positive_sameconst_shlnuw_before ⊑ positive_sameconst_shlnuw_after

theorem testi16i8_com_proof : testi16i8_com_before ⊑ testi16i8_com_after

theorem scalar_i32_shl_and_signbit_ne_proof : scalar_i32_shl_and_signbit_ne_before ⊑ scalar_i32_shl_and_signbit_ne_after

theorem bv_276_2 :
    ∀ (e e_1 : LLVM.IntW 5), LLVM.mul (LLVM.udiv e_1 e) (LLVM.sub (LLVM.const? 5 0) e) ⊑ LLVM.sub (LLVM.urem e_1 e) e_1

theorem test37_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → ofBool (truncate 8 (x >>> 31#32 ||| 512#32) == 11#8) = 0#1

include hinj in
omit [BEq α] [Hashable α] [LawfulBEq α] in
lemma product.prodArray_spec_helper
    (is : Array γ) (hnd : is.toList.Nodup)
    (s : S₁) (hnew : ∀ s₂, f s s₂ ∉ is):
  let motive (a : Array γ) (S : Set S₂)  :=
    a.toList.Nodup ∧
    (∃ r, a.toList = is.toList ++ r ∧ (∀ z ∈ r, ∃ s₁ s₂, z = f s₁ s₂)) ∧
    ∀ s1 s2, f s1 s2 ∈ a ↔ s1 ≠ s ∧ f s1 s2 ∈ is ∨ s1 = s ∧ s2 ∈ S
  let body := m₂.attachWith _ hm₂ |>.fold (init := is) fun is s2 =>
      is.push (f s s2)
  motive body (m₂.attachWith _ hm₂).toSet

theorem lshr_shl_demand4_proof : lshr_shl_demand4_before ⊑ lshr_shl_demand4_after

theorem select_icmp_slt_zero_smin_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬ofBool (x <ₛ 0#8) = 1#1 → x ^^^ BitVec.ofInt 8 (-128) = x ||

theorem lshrult_01_14_proof : lshrult_01_14_before ⊑ lshrult_01_14_after

@[simp]
theorem MatchVar.liftM_bind_eq_some_iff (x? : Option α)
    (f : α → MatchVarM Δ Γ β) :
    ((liftM x? >>= f) mapIn = some mapOut)
    ↔ ( ∃ h : x?.isSome,
        f (x?.get h) mapIn = some mapOut )

theorem or_eq_with_one_bit_diff_constants2_thm (e : IntW 32) :
  LLVM.or (icmp IntPred.eq e (const? 32 97)) (icmp IntPred.eq e (const? 32 65)) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 (-33))) (const? 32 65)

theorem and_not_or_or_not_or_xor_commute3_proof : and_not_or_or_not_or_xor_commute3_before ⊑ and_not_or_or_not_or_xor_commute3_after

theorem egZextMin (u v : Nat) (x : BitVec w) :
    u ≤ v → (x.zeroExtend v).zeroExtend u = x.zeroExtend u

theorem positive_samevar_shlnuw_proof : positive_samevar_shlnuw_before ⊑ positive_samevar_shlnuw_after

theorem differentconsts_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x + 16#32 <ᵤ 144#32) = 1#1 → ofBool (x <ₛ 128#32) = 1#1 → ofBool (127#32 <ₛ x) = 1#1 → 256#16 = -1#16

theorem negAux_eq_addAux (x : BitStream) (i : Nat) :
    (negAux x i).1 =  (addAux (~~~ x) one i).1 ∧
    (negAux x i).2 =  (addAux (~~~ x) one i).2

theorem ashrslt_02_00_proof : ashrslt_02_00_before ⊑ ashrslt_02_00_after

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

theorem icmp_power2_and_icmp_shifted_mask_swapped_2147483648_1610612736_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.ne (LLVM.and e (const? 32 1610612736)) (const? 32 1610612736))
      (icmp IntPred.ult e (const? 32 (-2147483648))) ⊑
    icmp IntPred.ult e (const? 32 1610612736)

theorem or_ranges_adjacent_proof : or_ranges_adjacent_before ⊑ or_ranges_adjacent_after

theorem le_thm.extracted_1._3 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 <ₛ x) = 1#1 → ¬ofBool (x <ₛ x_1) = 1#1 → ofBool (0#32 ≤ₛ 0#32) = ofBool (x_1 ≤ₛ x)

theorem fold_inverted_icmp_preds_reverse_thm.extracted_1._4 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ofBool (x_3 <ₛ x_2) = 1#1 → ofBool (x_2 ≤ₛ x_3) = 1#1 → 0#32 ||

omit [Fintype S] [DecidableEq S] [LawfulBEq A] in
lemma addOrCreateState_preserves_mem (st : worklist.St A S) (final? : Bool) (sa sa' : S) :
    let (_, st') := st.addOrCreateState _ _  final? sa'
    sa ∈ st.map →
    sa ∈ st'.map

theorem shl_lshr_eq_amt_multi_use_thm.extracted_1._2 : ∀ (x : BitVec 44),
  ¬(33#44 ≥ ↑44 ∨ 33#44 ≥ ↑44 ∨ 33#44 ≥ ↑44) →
    ¬(33#44 ≥ ↑44 ∨ True ∧ (x <<< 33#44 &&& (x &&& 2047#44) != 0) = true) →
      x <<< 33#44 + x <<< 33#44 >>> 33#44 = x <<< 33#44 ||

theorem ashrsgt_03_05_exact_proof : ashrsgt_03_05_exact_before ⊑ ashrsgt_03_05_exact_after

theorem not_or_or_and_no_and_commute2_or_proof : not_or_or_and_no_and_commute2_or_before ⊑ not_or_or_and_no_and_commute2_or_after

theorem const_sub_add_const_proof : const_sub_add_const_before ⊑ const_sub_add_const_after

theorem test10_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(6#8 ≥ ↑8 ∨ 6#8 ≥ ↑8) →
    ¬(30#32 ≥ ↑32 ∨ True ∧ x <<< 30#32 >>> 30#32 <<< 30#32 ≠ x <<< 30#32 ∨ 30#32 ≥ ↑32) →
      signExtend 32 ((truncate 8 x <<< 6#8).sshiftRight' 6#8) = (x <<< 30#32).sshiftRight' 30#32

theorem lshrult_03_09_exact_proof : lshrult_03_09_exact_before ⊑ lshrult_03_09_exact_after

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

theorem test_ashr__exact_is_safe_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 lt_unsigned_to_small_unsigned_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (zeroExtend 32 x <ᵤ 17#32) = ofBool (x <ᵤ 17#8)

theorem demorgan_nand_apint2_thm (e e_1 : IntW 117) :
  LLVM.xor (LLVM.and (LLVM.xor e_1 (const? 117 (-1))) e) (const? 117 (-1)) ⊑
    LLVM.or e_1 (LLVM.xor e (const? 117 (-1)))

theorem icmp_slt_0_or_icmp_sge_100_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → x >>> 31#32 ||

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

@[simp, grind=] theorem getElem_ofList (i : Nat) (h : _) : (ofList ts)[i]'h = ts[i]'h

theorem lshrult_01_00_proof : lshrult_01_00_before ⊑ lshrult_01_00_after

theorem test_thm (e e_1 : IntW 1) : add e_1 e ⊑ LLVM.xor e_1 e

theorem icmp_select_implied_cond_ne_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == 0#8) = 1#1 → ofBool (x_1 != 0#8) = 1#1 → ofBool (0#8 != x_1) = ofBool (x != x_1)

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

theorem select_constants_and_icmp_eq0_zero_tval_proof : select_constants_and_icmp_eq0_zero_tval_before ⊑ select_constants_and_icmp_eq0_zero_tval_after

theorem icmp_power2_and_icmp_shifted_mask_2147483648_2147483647_proof : icmp_power2_and_icmp_shifted_mask_2147483648_2147483647_before ⊑ icmp_power2_and_icmp_shifted_mask_2147483648_2147483647_after

theorem trunc_lshr_sext_wide_input_exact_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(True ∧ signExtend 32 x >>> 9#32 <<< 9#32 ≠ signExtend 32 x ∨ 9#32 ≥ ↑32) →
    True ∧ x >>> 9#16 <<< 9#16 ≠ x ∨
        9#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 9#16)) ≠ x.sshiftRight' 9#16 →
      False

theorem neg_sgt_42_proof : neg_sgt_42_before ⊑ neg_sgt_42_after

theorem test17_thm (e : IntW 32) : urem (const? 32 1) e ⊑ zext 32 (icmp IntPred.ne e (const? 32 1))

theorem sext_negate_thm (e : IntW 1) : sub (const? 64 0) (sext 64 e) ⊑ zext 64 e

theorem test_ashr__exact_is_safe_thm (e : IntW 64) (e_1 : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e_1 (const? 32 (-2147483588))) (const? 32 0)) e
      (ashr e (zext 64 (ashr (LLVM.and e_1 (const? 32 (-2147483588))) (const? 32 2)))) ⊑
    ashr e (zext 64 (LLVM.and (ashr e_1 (const? 32 2)) (const? 32 (-536870897))) { «nneg» := true })

theorem e_1900 :
    2 * (b ^^^ (a &&&  ~~~c)) - 11 * (b ^^^  ~~~(a &&& (b ^^^ c))) - 3 * (b &&&  ~~~(a &&&  ~~~c)) - 1 * (b ^^^ (a |||  ~~~c)) - 2 * (a ||| ( ~~~b &&& c)) + 11 * ( ~~~a ||| (b ||| c)) + 2 * (c ||| (a &&&  ~~~b)) - 1 * (a ||| b) - 5 * (c ^^^ (a &&& b)) + 7 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 4 *  ~~~(b &&&  ~~~c) + 7 * (a ^^^ c) - 1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 7 * (b ^^^ ( ~~~a &&& ( ~~~b ||| c))) + 11 * (b ^^^ ( ~~~a ||| (b &&& c))) + 1 * (b &&& c) + 1 * ((a ^^^ b) ||| (a ^^^ c)) - 5 * (b ^^^ (a ||| (b ^^^ c))) - 6 * (a &&& (b ||| c)) - 2 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) + 7 *  ~~~(a ^^^ (b ||| c)) + 2 *  ~~~(a ||| (b &&& c)) - 7 * ( ~~~b &&&  ~~~(a ^^^ c)) + 3 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) - 6 * c - 2 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 11 *  ~~~(a &&&  ~~~b) - 3 * ( ~~~(a |||  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 7 *  ~~~(a |||  ~~~b) + 2 * (a &&&  ~~~c) - 11 *  ~~~(a &&&  ~~~c) + 11 *  ~~~( ~~~a &&& (b ||| c)) - 2 * (b ^^^ ( ~~~a &&& (b ||| c))) + 4 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c))) + 4 * (a ^^^ (b &&& c)) + 1 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) - 2 *  ~~~(b |||  ~~~c) + 1 * ( ~~~b |||  ~~~(a ^^^ c)) + 2 *  ~~~(b &&& c) + 11 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) + 1 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) - 56 *  ~~~(a ||| (b ||| c)) - 28 *  ~~~(a ||| ( ~~~b ||| c)) - 27 *  ~~~( ~~~a ||| (b ||| c)) - 52 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 24 * ( ~~~a &&& ( ~~~b &&& c)) - 18 * ( ~~~a &&& (b &&& c)) + 5 * (a &&& ( ~~~b &&& c)) - 37 * (a &&& (b &&& c)) =  - 1 * ((a &&&  ~~~b) ||| (b ^^^ c))

theorem t0_commutative_thm.extracted_1._17 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1) (x_3 x_4 : BitVec 8),
  ¬ofBool (x_4 == x_3) = 1#1 → ¬ofBool (x_4 != x_3) = 1#1 → 0#1 = 1#1 → x_2 = 1#1 → x_1 = x

theorem trunc_sandwich_max_sum_shift_proof : trunc_sandwich_max_sum_shift_before ⊑ trunc_sandwich_max_sum_shift_after

theorem test5_proof : test5_before ⊑ test5_after

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

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

theorem masked_or_allzeroes_logical_proof : masked_or_allzeroes_logical_before ⊑ masked_or_allzeroes_logical_after

theorem uadd_sat_flipped_wrong_bounds7_proof : uadd_sat_flipped_wrong_bounds7_before ⊑ uadd_sat_flipped_wrong_bounds7_after

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

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

theorem a_thm (e : IntW 32) :
  LLVM.and (sub (const? 32 8) e) (const? 32 7) ⊑ LLVM.and (sub (const? 32 0) e) (const? 32 7)

theorem positive_sameconst_shlnsw_lshrexact_proof : positive_sameconst_shlnsw_lshrexact_before ⊑ positive_sameconst_shlnsw_lshrexact_after

theorem n2_thm (e : IntW 16) :
  LLVM.and (shl (zext 32 e) (const? 32 15)) (const? 32 (-2147483648)) ⊑ const? 32 0

theorem and_or2_wrong_operand_thm (e e_1 e_2 e_3 : IntW 1) :
  select (LLVM.and (LLVM.xor e_3 (const? 1 1)) e_2) e_1 e ⊑
    select (LLVM.and e_2 (LLVM.xor e_3 (const? 1 1))) e_1 e

theorem slt_or_not_max_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 <ₛ x) = 1#1 → 1#1 = ofBool (x_1 != 127#8)

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 main4_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 7#32) &&& ofBool (x &&& 48#32 == 48#32) = 1#1 →
    1#32 = zeroExtend 32 (ofBool (x &&& 55#32 != 55#32))

theorem sdiv_mul_shl_nsw_proof : sdiv_mul_shl_nsw_before ⊑ sdiv_mul_shl_nsw_after

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

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

theorem select_non_const_sides_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → x - zeroExtend 64 x_1 = x

theorem scalar1_thm (e e_1 : IntW 4) :
  LLVM.xor (LLVM.and (LLVM.xor e_1 e) (const? 4 (-2))) e ⊑
    LLVM.or (LLVM.and e_1 (const? 4 (-2))) (LLVM.and e (const? 4 1)) { «disjoint» := true }

theorem ule_bignum_proof : ule_bignum_before ⊑ ule_bignum_after

theorem test4_proof : test4_before ⊑ test4_after

theorem scalar_i32_lshr_and_negC_slt_thm (e e_1 : IntW 32) :
  icmp IntPred.slt (LLVM.and (lshr e_1 e) (const? 32 (-8))) (const? 32 0) ⊑
    icmp IntPred.slt (lshr e_1 e) (const? 32 0)

theorem lshr_add_proof : lshr_add_before ⊑ lshr_add_after

theorem test71_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and e (const? 32 128)) (const? 32 0)) (const? 32 40) (const? 32 42) ⊑
    select (icmp IntPred.eq (LLVM.and e (const? 32 128)) (const? 32 0)) (const? 32 42) (const? 32 40)

theorem eq_21_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(16#32 ≥ ↑32 ∨ 16#32 ≥ ↑32) →
    ¬ofBool (truncate 8 (x_1 >>> 16#32) == truncate 8 (x >>> 16#32)) = 1#1 → 8#32 ≥ ↑32 ∨ 8#32 ≥ ↑32 → False

theorem p2_slt_65536_thm.extracted_1._3 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 <ₛ 65536#32) = 1#1 → ¬ofBool (65535#32 <ₛ x_1) = 1#1 → 65535#32 = x

theorem eq_signed_to_small_unsigned_thm (e : IntW 8) :
  icmp IntPred.eq (sext 32 e) (const? 32 17) ⊑ icmp IntPred.eq e (const? 8 17)

theorem p0_proof : p0_before ⊑ p0_after

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

theorem negation_of_increment_via_or_disjoint_thm (e e_1 : IntW 8) :
  sub e_1 (LLVM.or e (const? 8 1) { «disjoint» := true }) ⊑ add e_1 (LLVM.xor e (const? 8 (-1)))

theorem shrink_or_thm.extracted_1._1 : ∀ (x : BitVec 6),
  truncate 3 (x ||| BitVec.ofInt 6 (-31)) = truncate 3 x ||

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

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

theorem no_shift_xor_multiuse_cmp_and_thm.extracted_1._3 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ofBool (0#32 != x_3 &&& 4096#32) = 1#1 →
    ofBool (x_3 &&& 4096#32 == 0#32) = 1#1 →
      x_2 * x_1 * (x_2 &&& BitVec.ofInt 32 (-4097)) =
        (x_2 &&& BitVec.ofInt 32 (-4097)) * x * (x_2 &&& BitVec.ofInt 32 (-4097))

omit [LawfulBEq A] [Fintype S] [DecidableEq S] in
lemma processOneElem_states (st : worklist.St A S) (final : S → Bool) (a : A) (sa : S) (s : State) :
  (processOneElem A S final s st (a, sa)).m.states =
    if sa ∉ st.map then st.m.newState.2.states else st.m.states

theorem lt_signed_to_small_unsigned_thm (e : IntW 8) :
  icmp IntPred.ult (sext 32 e) (const? 32 17) ⊑ icmp IntPred.ult e (const? 8 17)

theorem and_signbit_select_lshr_proof : and_signbit_select_lshr_before ⊑ and_signbit_select_lshr_after

theorem ashrsgt_01_14_thm (e : IntW 4) :
  icmp IntPred.sgt (ashr e (const? 4 1)) (const? 4 (-2)) ⊑ icmp IntPred.sgt e (const? 4 (-3))

theorem Eqn.forall_width_reflect_zero_of_width_one_denote_zero (e : Eqn) (w : Nat) (env : List (BitVec w))
    (h : (∀ env1 : EnvFin 1 e.numVars, Eqn.denoteFin e env1 = 0)) :
    Eqn.reflectEqZero w e env

theorem test3_proof : test3_before ⊑ test3_after

theorem ashr_ult_8_thm (e : IntW 4) :
  icmp IntPred.ult (ashr e (const? 4 1)) (const? 4 (-8)) ⊑ icmp IntPred.sgt e (const? 4 (-1))

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

theorem test5_proof : test5_before ⊑ test5_after

theorem exact_ashr_eq_proof : exact_ashr_eq_before ⊑ exact_ashr_eq_after

theorem negate_sext_proof : negate_sext_before ⊑ negate_sext_after

@[simp, simp_denote] theorem effToMonadRefinement_impure (x : impure.toMonad m α) (y : impure.toMonad n β) :
    x ⊑ y ↔ (@id (m α) x) ⊑ (@id (n β) y)

theorem ashrsgt_02_06_proof : ashrsgt_02_06_before ⊑ ashrsgt_02_06_after

theorem e_1406 :
     - 7 * z - 7 *  ~~~t - 3 *  ~~~(z &&&  ~~~z) - 6 * (z |||  ~~~t) + 1 *  ~~~z - 7 *  ~~~(z ^^^ t) + 5 * t + 22 *  ~~~(z ||| t) - 10 *  ~~~(z |||  ~~~t) + 11 * (z &&& t) =  - 7 * (z ||| t) - 16 * (z &&&  ~~~t)

theorem test_shl__nsw_is_safe_proof : test_shl__nsw_is_safe_before ⊑ test_shl__nsw_is_safe_after

theorem ashr_ult_14_proof : ashr_ult_14_before ⊑ ashr_ult_14_after

omit [Fintype S] [DecidableEq S] [LawfulBEq A] in
lemma processOneElem_preserves_mem (st : worklist.St A S) (final : S → Bool) (a : A) (sa sa' : S) (s : State) :
    let st' := processOneElem _ _  final s st (a, sa')
    sa ∈ st.map →
    sa ∈ st'.map

theorem sub_from_constant_of_sub_from_constant_thm (e : IntW 8) : sub (const? 8 11) (sub (const? 8 42) e) ⊑ add e (const? 8 (-31))

theorem e_2117 :
     - 5 *  ~~~(d |||  ~~~e) + 1 * (f &&& (d |||  ~~~e)) - 1 * ((d &&& e) |||  ~~~(e ||| f)) - 11 * ( ~~~d ||| (e &&& f)) - 7 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 11 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) + 1 * (e &&& f) + 11 * (d &&& e) + 2 * (d ||| ( ~~~e ||| f)) + 4 * (e ^^^ (d ||| ( ~~~e &&& f))) + 3 * (e ^^^  ~~~(d &&&  ~~~f)) - 3 *  ~~~(d &&& ( ~~~e &&& f)) - 2 * (d ^^^ e) + 3 * (f &&&  ~~~(d ^^^ e)) - 2 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 3 * d - 5 *  ~~~(d &&& ( ~~~e ||| f)) - 11 * (e ^^^ ( ~~~d ||| (e ||| f))) - 2 * (e &&&  ~~~(d &&& f)) + 2 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 7 * ( ~~~d ||| (e ^^^ f)) + 5 *  ~~~(d ^^^ (e ||| f)) + 2 * (e |||  ~~~f) + 1 * e - 2 * (f ^^^ (d &&&  ~~~e)) + 7 * ((d &&& e) ^^^ (e |||  ~~~f)) + 3 * (f &&& (d ^^^ e)) + 11 *  ~~~(d &&& (e ||| f)) + 4 * (e |||  ~~~(d ^^^ f)) + 5 *  ~~~( ~~~d &&& (e &&& f)) + 1 * (e ^^^  ~~~(d &&& f)) + 5 * (f ^^^ (d |||  ~~~e)) - 1 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) - 3 * ( ~~~d ||| (e ||| f)) + 3 * (e ^^^ (d ||| (e ||| f))) + 2 * (f ^^^ ( ~~~d ||| (e ||| f))) - 2 *  ~~~(d ||| (e ||| f)) + 5 *  ~~~(d ||| ( ~~~e ||| f)) - 34 *  ~~~( ~~~d ||| (e ||| f)) - 26 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 2 * ( ~~~d &&& ( ~~~e &&& f)) - 14 * ( ~~~d &&& (e &&& f)) - 8 * (d &&& ( ~~~e &&& f)) - 7 * (d &&& (e &&& f)) =  - 2 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f))

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

theorem xor_logic_and_or2_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → x_1 = 1#1 → 0#1 ^^^ (x_1 ||| x) = x_2 ^^^ 1#1

@[simp, simp_denote, simp_sllvm]
lemma run_map (x : EffectM α) :
    StateT.run (f <$> x : EffectM β) s = (fun p => (f p.1, p.2)) <$> StateT.run x s

theorem e_1159 :
     - 7 *  ~~~t - 5 * t - 11 * z - 1 *  ~~~(z &&& t) - 2 *  ~~~z + 8 *  ~~~(z ||| t) + 8 *  ~~~(z |||  ~~~t) + 17 * (z &&&  ~~~t) =  - 14 * (z &&& t) - 2 * (z |||  ~~~t)

theorem positive_samevar_shlnuwnsw_lshrexact_proof : positive_samevar_shlnuwnsw_lshrexact_before ⊑ positive_samevar_shlnuwnsw_lshrexact_after

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

theorem test_zext3_proof : test_zext3_before ⊑ test_zext3_after

theorem e_2032 :
    11 * (e ^^^ (d ||| ( ~~~e ||| f))) - 1 *  ~~~(e ^^^ f) + 11 * ( ~~~d ||| (e &&& f)) - 3 * (f &&&  ~~~(d &&& e)) + 3 * ((d &&& e) ^^^ (e |||  ~~~f)) - 2 *  ~~~(d &&& (e &&& f)) + 1 * (f |||  ~~~(d ^^^ e)) - 2 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) - 6 * (f ^^^ (d ||| (e ||| f))) + 4 * (e ^^^  ~~~(d ||| (e ^^^ f))) + 4 *  ~~~( ~~~d &&& (e &&& f)) + 1 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 5 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 2 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 2 * (f ^^^ (d ||| ( ~~~e ||| f))) - 5 * ( ~~~d ||| ( ~~~e &&& f)) - 3 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 2 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) + 11 *  ~~~( ~~~d ||| (e ^^^ f)) + 7 * (e |||  ~~~(d ^^^ f)) + 3 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 11 * (e ^^^  ~~~(d &&& f)) - 1 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 1 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 2 * (f ^^^  ~~~( ~~~d &&& (e &&& f))) - 7 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 41 *  ~~~(d ||| (e ||| f)) - 19 *  ~~~(d ||| ( ~~~e ||| f)) - 37 *  ~~~( ~~~d ||| (e ||| f)) - 11 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 19 * ( ~~~d &&& ( ~~~e &&& f)) - 8 * ( ~~~d &&& (e &&& f)) - 7 * (d &&& ( ~~~e &&& f)) - 54 * (d &&& (e &&& f)) =  - 1 * ((d &&& e) |||  ~~~(e ||| f))

theorem  mkIndHypCycleBreaking_eval_eq_false_thm_aux
  {circs : KInductionCircuits fsm n}
  (hcircs : circs.IsLawful)
  (h : ∀ (env : _), (mkIndHypCycleBreaking circs).eval env = false) :
  (∀ (envBitstream : _) (s0 : _), (∀ (i : Nat) (j : Nat), i < j ∧ j ≤ n →
      (fsm.carryWith s0 envBitstream i) ≠ (fsm.carryWith s0 envBitstream j)) →
      (∀ (k : Nat), k < n + 1 → fsm.evalWith s0 envBitstream k = false) →
      (fsm.evalWith s0 envBitstream (n + 1) = false))

theorem n7_proof : n7_before ⊑ n7_after

theorem select_constants_and_icmp_eq0_zero_fval_proof : select_constants_and_icmp_eq0_zero_fval_before ⊑ select_constants_and_icmp_eq0_zero_fval_after

theorem test14_proof : test14_before ⊑ test14_after

theorem ult_192_thm (e : IntW 32) :
  icmp IntPred.ult (trunc 8 e) (const? 8 (-64)) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 192)) (const? 32 192)

theorem p0_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x &&& 3#8 <ₛ x) = ofBool (3#8 <ₛ x)

theorem sext_diff_i1_xor_sub_1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  True ∧ (zeroExtend 64 x).saddOverflow (signExtend 64 x_1) = true → False

theorem or_xor_tree_1001_proof : or_xor_tree_1001_before ⊑ or_xor_tree_1001_after

theorem ashrsgt_02_15_exact_proof : ashrsgt_02_15_exact_before ⊑ ashrsgt_02_15_exact_after

theorem neg_nsw_sgt_n1_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (0#8).ssubOverflow x = true) → ofBool (-1#8 <ₛ 0#8 - x) = ofBool (x <ₛ 1#8)

theorem andn_or_cmp_1_logical_thm (e e_1 e_2 : IntW 37) :
  select (icmp IntPred.sle e_2 e_1)
      (select (icmp IntPred.ugt e (const? 37 42)) (const? 1 1) (icmp IntPred.sgt e_2 e_1)) (const? 1 0) ⊑
    select (icmp IntPred.sle e_2 e_1) (icmp IntPred.ugt e (const? 37 42)) (const? 1 0)

theorem src_thm.extracted_1._1 : ∀ (x : BitVec 1),
  ¬(zeroExtend 32 x ≥ ↑32 ∨ zeroExtend 32 x ≥ ↑32) →
    True ∧ ((-1#32) <<< zeroExtend 32 x).sshiftRight' (zeroExtend 32 x) ≠ -1#32 ∨
        zeroExtend 32 x ≥ ↑32 ∨
          True ∧
              ((((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x) <<< zeroExtend 32 x).sshiftRight'
                  (zeroExtend 32 x) ≠
                ((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x ∨
            True ∧
                (((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x) <<< zeroExtend 32 x >>> zeroExtend 32 x ≠
                  ((-1#32) <<< zeroExtend 32 x ^^^ -1#32) &&& zeroExtend 32 x ∨
              zeroExtend 32 x ≥ ↑32 →
      False

theorem Std.HashSet.toSet_toList[BEq α] [LawfulBEq α] [Hashable α] (m : HashSet α) : m.toSet = { x | x ∈ m.toList }

theorem no_shift_xor_multiuse_cmp_proof : no_shift_xor_multiuse_cmp_before ⊑ no_shift_xor_multiuse_cmp_after

theorem bools_multi_uses2_logical_thm.extracted_1._6 : ∀ (x x_1 : BitVec 1),
  x_1 ^^^ 1#1 = 1#1 → ¬x_1 = 1#1 → ¬x = 1#1 → 0#1 = 1#1 → x + 0#1 = 0#1

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

theorem test18a_thm (e : IntW 8) :
  icmp IntPred.eq (LLVM.and e (const? 8 (-2))) (const? 8 0) ⊑ icmp IntPred.ult e (const? 8 2)

theorem trunc_shl_nsw_31_i32_i64_proof : trunc_shl_nsw_31_i32_i64_before ⊑ trunc_shl_nsw_31_i32_i64_after

theorem select_xor_inv_icmp_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 == 0#32) = 1#1 → x_1 ^^^ x_2 = x_1

theorem test_zext_nneg_proof : test_zext_nneg_before ⊑ test_zext_nneg_after

theorem udiv_ne_big_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x = 0 → ofBool (x_1 / x != BitVec.ofInt 8 (-128)) = ofBool (x_1 != BitVec.ofInt 8 (-128)) ||

theorem test9_thm (e : IntW 16) : trunc 16 (sext 32 e) ⊑ e

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

theorem ne_smax1_proof : ne_smax1_before ⊑ ne_smax1_after

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

theorem lt_two_pow_succ_of_lt (x y : Nat) :
    (x / 2) < 2 ^ y → x < 2 ^ (y + 1)

theorem e_1098 :
    7 *  ~~~t + 5 *  ~~~(z &&& t) - 3 *  ~~~z + 11 * z - 3 *  ~~~(z ||| t) + 4 *  ~~~(z |||  ~~~t) - 23 * (z &&&  ~~~t) - 5 * (z &&& t) = 6 *  ~~~(z &&&  ~~~t)

theorem or_xor_tree_0011_proof : or_xor_tree_0011_before ⊑ or_xor_tree_0011_after

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

theorem not_mul_of_pow2_commute_proof : not_mul_of_pow2_commute_before ⊑ not_mul_of_pow2_commute_after

@[simp]
lemma BitVecs.transport_w {bvs : BitVecs n} : (BitVecs.transport f bvs).w = bvs.w

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

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

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

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 neg_or_add (i : Nat) :
    (b.negAux i).2 = false ∨ (a.addAux b.neg i).2 = false

theorem sgt_swap_or_not_min_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.slt e_1 e) (const? 1 1) (icmp IntPred.ne e (const? 8 (-128))) ⊑
    icmp IntPred.ne e (const? 8 (-128))

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

theorem test11_proof : test11_before ⊑ test11_after

theorem main5c_like_thm (e e_1 : IntW 32) :
  select
      (LLVM.or (icmp IntPred.ne (LLVM.and e_1 (const? 32 7)) (const? 32 7))
        (icmp IntPred.ne (LLVM.and e (const? 32 7)) (const? 32 7)))
      (const? 32 0) (const? 32 1) ⊑
    zext 32 (icmp IntPred.eq (LLVM.and (LLVM.and e_1 e) (const? 32 7)) (const? 32 7))

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

theorem add_nuw_const_const_sub_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.uaddOverflow 1#8 = true) → BitVec.ofInt 8 (-127) - (x + 1#8) = BitVec.ofInt 8 (-128) - x

theorem add_or_sub_comb_i8_negative_y_add_proof : add_or_sub_comb_i8_negative_y_add_before ⊑ add_or_sub_comb_i8_negative_y_add_after

theorem trunc_shl_ashr_infloop_proof : trunc_shl_ashr_infloop_before ⊑ trunc_shl_ashr_infloop_after

theorem bv_AndOrXor_1288_A__B__B__C__A___A__B__C :
    ∀ (e e_1 e_2 : LLVM.IntW w),
      LLVM.and (LLVM.xor e e_2) (LLVM.xor (LLVM.xor e_2 e_1) e) ⊑
        LLVM.and (LLVM.xor e e_2) (LLVM.xor e_1 (LLVM.const? w (-1)))

theorem test16_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬1#32 ≥ ↑32 → 1#32 ≥ ↑32 ∨ True ∧ (BitVec.ofInt 32 (-2)).usubOverflow (x >>> 1#32) = true → False

theorem ugt_zext_thm (e : IntW 8) (e_1 : IntW 1) :
  icmp IntPred.ugt (zext 8 e_1) e ⊑ LLVM.and (icmp IntPred.eq e (const? 8 0)) e_1

theorem fold_inverted_icmp_preds_reverse_proof : fold_inverted_icmp_preds_reverse_before ⊑ fold_inverted_icmp_preds_reverse_after

theorem a_false_implies_b_false_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.ugt e_2 (const? 8 20)) e_1 e) ⊑
    select (icmp IntPred.ugt e_2 (const? 8 10)) (const? 1 1) e

theorem e_1662 :
    5 * ((a &&&  ~~~b) ||| (b ^^^ c)) - 1 * ( ~~~c ||| (a ^^^ b)) - 1 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) + 2 * ((a &&& b) |||  ~~~(b |||  ~~~c)) - 6 *  ~~~( ~~~a ||| (b ^^^ c)) + 5 *  ~~~( ~~~a &&& (b &&& c)) + 11 * (b &&&  ~~~(a ^^^ c)) + 11 *  ~~~(a |||  ~~~c) + 4 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 7 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) - 2 * ((a &&& b) ^^^ (b |||  ~~~c)) - 3 * ((a &&& b) ^^^ (b ||| c)) + 3 * (b ^^^ ( ~~~a ||| (b &&& c))) + 7 * (a &&& ( ~~~b ||| c)) - 3 * (c &&& (a |||  ~~~b)) - 18 *  ~~~(a ||| (b ||| c)) - 19 *  ~~~(a ||| ( ~~~b ||| c)) - 22 *  ~~~( ~~~a ||| (b ||| c)) - 19 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 30 * ( ~~~a &&& ( ~~~b &&& c)) - 6 * ( ~~~a &&& (b &&& c)) - 15 * (a &&& ( ~~~b &&& c)) - 19 * (a &&& (b &&& c)) =  - 2 *  ~~~( ~~~a &&& (b ||| c))

theorem test_shl__nsw_is_safe_proof : test_shl__nsw_is_safe_before ⊑ test_shl__nsw_is_safe_after

theorem ashr_xor_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬((42#32 == 0 || 32 != 1 && x_1 == intMin 32 && 42#32 == -1) = true ∨ 5#32 ≥ ↑32 ∨ 7#32 ≥ ↑32) →
    ¬(12#32 ≥ ↑32 ∨ (42#32 == 0 || 32 != 1 && x_1 == intMin 32 && 42#32 == -1) = true ∨ 7#32 ≥ ↑32) →
      (x_1.srem 42#32 ^^^ x.sshiftRight' 5#32).sshiftRight' 7#32 =
        x.sshiftRight' 12#32 ^^^ (x_1.srem 42#32).sshiftRight' 7#32

theorem shl_nsw_ule_Csle0_fail_missing_flag_proof : shl_nsw_ule_Csle0_fail_missing_flag_before ⊑ shl_nsw_ule_Csle0_fail_missing_flag_after

theorem ashrslt_02_12_proof : ashrslt_02_12_before ⊑ ashrslt_02_12_after

theorem lshrugt_03_14_proof : lshrugt_03_14_before ⊑ lshrugt_03_14_after

theorem xor_logic_and_or1_thm (e e_1 e_2 : IntW 1) :
  LLVM.xor (select e_2 e_1 (const? 1 0)) (LLVM.or e e_2) ⊑ select e_2 (LLVM.xor e_1 (const? 1 1)) e

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

theorem test21_proof : test21_before ⊑ test21_after

theorem gt_unsigned_to_small_negative_proof : gt_unsigned_to_small_negative_before ⊑ gt_unsigned_to_small_negative_after

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

theorem test20_thm (e : IntW 13) : icmp IntPred.eq (ashr e (const? 13 12)) (const? 13 123) ⊑ const? 1 0

theorem ExtEq.symm {Γ Δ : Context Ty} : Γ.ExtEq Δ → Δ.ExtEq Γ

theorem test5_thm.extracted_1._1 : ∀ (x x_1 : BitVec 399),
  x_1 + (x &&& 18446742974197923840#399) &&& (274877906943#399 ^^^ -1#399) ||

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

theorem neg_sgt_42_thm (e : IntW 32) :
  icmp IntPred.sgt (sub (const? 32 0) e) (const? 32 42) ⊑
    icmp IntPred.slt (add e (const? 32 (-1))) (const? 32 (-43))

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

theorem or_ranges_single_elem_right_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (5#8 ≤ᵤ x) &&& ofBool (x ≤ᵤ 10#8) ||

theorem t3_const_after_fold_lshr_shl_ne_proof : t3_const_after_fold_lshr_shl_ne_before ⊑ t3_const_after_fold_lshr_shl_ne_after

theorem bools_multi_uses2_logical_thm.extracted_1._29 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 ^^^ 1#1 = 1#1 → x_2 = 1#1 → 0#1 = 1#1 → x = 1#1 → ¬True → 0#1 + x = 0#1 ^^^ x

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

lemma CNFA.ofFSM_spec (p : FSM arity) :
    (CNFA.ofFSM p).Sim (NFA'.ofFSM p)

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

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

theorem t0_proof : t0_before ⊑ t0_after

theorem test_shift_negative_proof : test_shift_negative_before ⊑ test_shift_negative_after

theorem sub_select_sext_proof : sub_select_sext_before ⊑ sub_select_sext_after

@[simp]
theorem LLVM.lshr?_eq_poison {a b : BitVec w} (hb : b ≥ w) : LLVM.lshr? a b = .poison

theorem PR42691_6_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x <ᵤ BitVec.ofInt 32 (-2147483647)) = 1#1 → 1#1 = ofBool (x + 1#32 <ᵤ BitVec.ofInt 32 (-2147483646))

theorem ashr_ugt_4_proof : ashr_ugt_4_before ⊑ ashr_ugt_4_after

theorem ripple_nsw1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  True ∧ (x_1 &&& 1#16).saddOverflow (x &&& BitVec.ofInt 16 (-16385)) = true ∨
      True ∧ (x_1 &&& 1#16).uaddOverflow (x &&& BitVec.ofInt 16 (-16385)) = true →
    False

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

theorem xor_or_thm (e e_1 : IntW 32) (e_2 : IntW 1) :
  LLVM.xor (select e_2 (const? 1 1) (icmp IntPred.ult e_1 e)) (const? 1 1) ⊑
    select (LLVM.xor e_2 (const? 1 1)) (icmp IntPred.uge e_1 e) (const? 1 0)

theorem icmp_eq_and_pow2_shl_pow2_negative3_proof : icmp_eq_and_pow2_shl_pow2_negative3_before ⊑ icmp_eq_and_pow2_shl_pow2_negative3_after

@[simp] theorem toBitVec_ofBitVec (x : BitVec w) (w' : Nat) :
    toBitVec w' (ofBitVecSext x) = x.signExtend w'

theorem or_xor_tree_0010_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (LLVM.xor (mul e_2 (const? 32 42)) (mul e_1 (const? 32 42)))
      (LLVM.xor (LLVM.xor (mul e (const? 32 42)) (mul e_1 (const? 32 42))) (mul e_2 (const? 32 42))) ⊑
    LLVM.or (LLVM.xor (mul e_2 (const? 32 42)) (mul e_1 (const? 32 42))) (mul e (const? 32 42))

theorem ne_basic_equal_minus_7_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.ne e_1 (const? 8 (-7))) (icmp IntPred.ule (add e_1 (const? 8 7)) e) ⊑
    icmp IntPred.ult (add e_1 (const? 8 6)) e

theorem icmp_slt_0_and_icmp_ne_neg2_i32_fail_proof : icmp_slt_0_and_icmp_ne_neg2_i32_fail_before ⊑ icmp_slt_0_and_icmp_ne_neg2_i32_fail_after

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

theorem com_Γ : com.1 = (Γn 1)

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

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

theorem bv_InstCombineShift__239 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.lshr (LLVM.shl e e_1) e_1 ⊑ LLVM.and e (LLVM.lshr (LLVM.const? w (-1)) e_1)

theorem mul_add_to_mul_8_proof : mul_add_to_mul_8_before ⊑ mul_add_to_mul_8_after

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

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 icmp_equality_test_commute_icmp2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 64),
  ofBool (x_2 == x_1) = 1#1 → ofBool (x == x_2) = ofBool (x == x_1)

theorem test1_proof : test1_before ⊑ test1_after

theorem add_nsw_const_const_sub_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.saddOverflow 1#8 = true) → BitVec.ofInt 8 (-127) - (x + 1#8) = BitVec.ofInt 8 (-128) - x

theorem trunc_shl_ashr_var_proof : trunc_shl_ashr_var_before ⊑ trunc_shl_ashr_var_after

theorem positive_sameconst_lshrexact_proof : positive_sameconst_lshrexact_before ⊑ positive_sameconst_lshrexact_after

theorem lshr_mul_nuw_nsw_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(True ∧ x.smulOverflow 52#64 = true ∨ True ∧ x.umulOverflow 52#64 = true ∨ 2#64 ≥ ↑64) →
    True ∧ x.smulOverflow 13#64 = true ∨ True ∧ x.umulOverflow 13#64 = true → False

theorem badimm1_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 9#16 ≥ ↑16) →
    ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 9#16)) = 1#1 →
      7#8 ≥ ↑8 ∨
          9#16 ≥ ↑16 ∨
            True ∧ signExtend 16 (truncate 8 (x >>> 9#16)) ≠ x >>> 9#16 ∨
              True ∧ zeroExtend 16 (truncate 8 (x >>> 9#16)) ≠ x >>> 9#16 →
        False

theorem lshrugt_01_09_thm.extracted_1._1 : ∀ (x : BitVec 4),
  ¬1#4 ≥ ↑4 → ofBool (BitVec.ofInt 4 (-7) <ᵤ x >>> 1#4) = 0#1

theorem and_ne_with_one_bit_diff_constants3_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (x != 65#8) &&& ofBool (x != BitVec.ofInt 8 (-63)) = ofBool (x &&& 127#8 != 65#8)

theorem udiv1_proof : udiv1_before ⊑ udiv1_after

theorem and_xor_or3_proof : and_xor_or3_before ⊑ and_xor_or3_after

theorem n3_constmask_samemask_proof : n3_constmask_samemask_before ⊑ n3_constmask_samemask_after

theorem or_not_xor_common_op_commute5_proof : or_not_xor_common_op_commute5_before ⊑ or_not_xor_common_op_commute5_after

@[simp] theorem Valuation.cons_toCons {t t' : Ty} (s : Γ.Valuation)
    (x : toType t) (v : Γ.Var t') :
    (s.cons x) v.toCons = s v

theorem urem_i8_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ¬zeroExtend 32 x = 0 → x = 0 → False

theorem xor_icmp_invalid_range_proof : xor_icmp_invalid_range_before ⊑ xor_icmp_invalid_range_after

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

theorem xor_with_or_disjoint_ab_proof : xor_with_or_disjoint_ab_before ⊑ xor_with_or_disjoint_ab_after

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

theorem ashr_ult_1_proof : ashr_ult_1_before ⊑ ashr_ult_1_after

@[simp]
theorem Std.HashSet.mem_attachWith_mem [BEq α] [Hashable α] [LawfulBEq α] (m : HashSet α) {P H} (x : α) h :
    ⟨x, h⟩ ∈ m.attachWith P H ↔ x ∈ m

theorem icmp_equality_test_commute_icmp1_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 64),
  ¬ofBool (x_2 == x_1) = 1#1 → ¬ofBool (x_2 == x) ^^^ 1#1 = 1#1 → 0#1 = ofBool (x == x_1)

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

theorem positive_easyinvert_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ofBool (x_1 <ₛ 0#8) ^^^ ofBool (x <ₛ 0#16) ^^^ 1#1 = ofBool (x_1 <ₛ 0#8) ^^^ ofBool (-1#16 <ₛ x)

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

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

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

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

theorem fold_mask_cmps_to_false_logical_proof : fold_mask_cmps_to_false_logical_before ⊑ fold_mask_cmps_to_false_logical_after

theorem wide_source_matching_signbits_proof : wide_source_matching_signbits_before ⊑ wide_source_matching_signbits_after

theorem if_if_eq_if_and (x y : Prop) [Decidable x] [Decidable y] :
   (if x then if y then a else b else b) = if x ∧ y then a else b

theorem BitVec.even_mul_eq_shiftLeft_mul_of_eq_mul_two
    (w : Nat) (x : BitVec w) (n e : Nat) (he : e = n * 2) :
    (BitVec.ofNat w e) * x = (BitVec.ofNat w n) * (x <<< (1 : Nat))

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

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

theorem sub_2_proof : sub_2_before ⊑ sub_2_after

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

theorem and_or1_proof : and_or1_before ⊑ and_or1_after

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

theorem p_constmask2_proof : p_constmask2_before ⊑ p_constmask2_after

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

theorem sub_ashr_or_i32_commute_thm (e e_1 : IntW 32) :
  LLVM.or e_1 (ashr (sub e e_1 { «nsw» := true, «nuw» := false }) (const? 32 31)) ⊑
    select (icmp IntPred.slt e e_1) (const? 32 (-1)) e_1

@[simp]
theorem Std.HashSet.mem_union' [BEq α] [Hashable α] [LawfulBEq α] {m₁ m₂ : HashSet α} :
    x ∈ m₁ ∪ m₂ ↔ x ∈ m₁ ∨ x ∈ m₂

theorem substitute_constant_or_ne_uge_commute_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x ≤ᵤ x_1) = 1#1 → 1#1 = ofBool (x_1 != 42#8) ||

theorem xor_or_thm.extracted_1._3 : ∀ (x : BitVec 32) (x_1 : BitVec 1), x_1 = 1#1 → x_1 ^^^ 1#1 = 1#1 → False

theorem shift_xor_multiuse_cmp_and_thm.extracted_1._4 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ¬ofBool (0#32 != x_3 &&& 4096#32) = 1#1 →
    ¬ofBool (x_3 &&& 4096#32 == 0#32) = 1#1 →
      (x_2 &&& 2048#32) * x * (x_2 &&& 2048#32) = x_2 * x_1 * (x_2 &&& 2048#32)

theorem ashr_xor_proof : ashr_xor_before ⊑ ashr_xor_after

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

theorem select_constants_and_icmp_eq0_proof : select_constants_and_icmp_eq0_before ⊑ select_constants_and_icmp_eq0_after

theorem p_constmask_commutative_proof : p_constmask_commutative_before ⊑ p_constmask_commutative_after

theorem not_ashr_not_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x ≥ ↑32 → (x_1 ^^^ -1#32).sshiftRight' x ^^^ -1#32 = x_1.sshiftRight' x

theorem shl_add_lshr_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑32 ∨ True ∧ (x_2 <<< x_1).uaddOverflow x = true ∨ x_1 ≥ ↑32) →
    x_1 ≥ ↑32 ∨ True ∧ (x >>> x_1).uaddOverflow x_2 = true → False

@[simp]
lemma CNFA.autUnsignedCmp_stateMax cmp : (autUnsignedCmp cmp).m.stateMax = 3

theorem test_mul__none_are_safe_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x == 805306368#32) = 1#1 → BitVec.ofInt 32 (-1342177280) = x * 9#32

theorem sext_ule_sext_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8),
  ofBool (signExtend 16 (x_1 * x_1) ≤ᵤ signExtend 16 x) = ofBool (x_1 * x_1 == 0#8) ||

theorem e_630 :
    1 *  ~~~(x &&&  ~~~x) + 7 *  ~~~(x &&& y) + 7 * (x ^^^ y) - 1 *  ~~~(x ^^^ y) - 5 * y - 7 *  ~~~x - 2 *  ~~~y + 2 *  ~~~(x ||| y) - 8 *  ~~~(x |||  ~~~y) - 18 * (x &&&  ~~~y) =  - 5 * (x ||| y)

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 bv_AndOrXor_2617 :
    ∀ (e e_1 : LLVM.IntW w),
      LLVM.xor (LLVM.and e (LLVM.xor e_1 (LLVM.const? w (-1)))) (LLVM.and (LLVM.xor e (LLVM.const? w (-1))) e_1) ⊑
        LLVM.xor e e_1

theorem test_shift_and_cmp_changed1_proof : test_shift_and_cmp_changed1_before ⊑ test_shift_and_cmp_changed1_after

theorem sub_shl_same_amount_partial_nuw1_proof : sub_shl_same_amount_partial_nuw1_before ⊑ sub_shl_same_amount_partial_nuw1_after

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

theorem or_not_and_commute4_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 icmp_ne_zext_ne_zero_proof : icmp_ne_zext_ne_zero_before ⊑ icmp_ne_zext_ne_zero_after

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

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

theorem ashr_and_thm.extracted_1._1 : ∀ (x : BitVec 8), ¬(x ≥ ↑8 ∨ x + 1#8 ≥ ↑8) → x ≥ ↑8 → False

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 test_ult_nuw_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 32),
  ¬(True ∧ signExtend 32 (truncate 8 x_1) ≠ x_1 ∨
        True ∧ zeroExtend 32 (truncate 8 x_1) ≠ x_1 ∨
          True ∧ signExtend 16 (truncate 8 x) ≠ x ∨ True ∧ zeroExtend 16 (truncate 8 x) ≠ x) →
    ofBool (truncate 8 x_1 <ᵤ truncate 8 x) = ofBool (x_1 <ᵤ zeroExtend 32 x)

theorem e_710 :
    2 *  ~~~(x &&&  ~~~y) + 1 * (x |||  ~~~y) + 5 *  ~~~(x ^^^ y) - 2 * y + 2 * (x ^^^ y) + 1 * x - 9 *  ~~~(x ||| y) - 3 *  ~~~(x |||  ~~~y) - 5 * (x &&&  ~~~y) - 7 * (x &&& y) =  - 1 *  ~~~(x &&& y)

theorem fold_mask_cmps_to_false_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x == 2147483647#32) &&& ofBool (x &&& 2147483647#32 == 0#32) = 0#1

theorem e_1798 :
     - 1 *  ~~~(a ^^^ ( ~~~b &&& c)) + 11 * (b &&&  ~~~(a ^^^ c)) - 1 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 3 * ( ~~~b &&&  ~~~(a ^^^ c)) + 11 * (b &&&  ~~~(a &&&  ~~~c)) - 5 *  ~~~( ~~~a &&& (b ||| c)) - 2 * (a ||| (b ||| c)) - 11 * (a ||| ( ~~~b ||| c)) + 3 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) + 5 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) + 7 * ((a ||| b) &&&  ~~~(b ^^^ c)) + 1 * a - 2 * (b &&& c) + 1 *  ~~~(b |||  ~~~c) - 1 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) - 7 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) + 3 * (b |||  ~~~c) - 1 * (c ^^^  ~~~(a &&& (b &&& c))) - 1 * ( ~~~(a ^^^ b) ||| (a ^^^ c)) - 1 *  ~~~(a ^^^ (b &&& c)) + 1 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) + 4 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 11 *  ~~~b - 1 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 2 * (a ^^^ (b ||| c)) + 5 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 4 *  ~~~(a ^^^ (b ||| c)) + 5 *  ~~~(a ||| c) - 7 * ( ~~~(a |||  ~~~b) |||  ~~~(b ^^^ c)) - 3 * ((a ^^^ b) |||  ~~~(a ^^^ c)) + 11 * (b ^^^  ~~~(a |||  ~~~c)) - 7 * (b ^^^  ~~~(a ||| c)) + 34 *  ~~~(a ||| (b ||| c)) - 37 *  ~~~(a ||| ( ~~~b ||| c)) + 22 *  ~~~( ~~~a ||| (b ||| c)) - 1 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 5 * ( ~~~a &&& ( ~~~b &&& c)) - 1 * ( ~~~a &&& (b &&& c)) - 7 * (a &&& (b &&& c)) =  - 26 * (a &&& ( ~~~b &&& c))

theorem icmp_slt_0_or_icmp_sge_neg1_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 ≥ ↑32 → x >>> 31#32 ||

theorem select_constants_and_icmp_ne0_thm.extracted_1._4 : ∀ (x x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬x = 1#1 → ofBool (1#8 &&& 1#8 != 0#8) = x_1 ^^^ x ^^^ 1#1

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

theorem e_1926 :
     - 3 * (a ^^^ (b ^^^ c)) + 11 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) + 5 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) - 3 * (c &&& (a ||| b)) - 1 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) + 1 * a - 11 * (c ^^^ ( ~~~a ||| (b ||| c))) - 1 * (b ||| (a &&&  ~~~c)) + 2 * (a &&&  ~~~c) + 3 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 1 * c + 11 * ( ~~~(a ||| b) |||  ~~~(a ^^^ (b ^^^ c))) - 3 * (b ^^^  ~~~( ~~~a ||| (b ^^^ c))) - 11 * ( ~~~a ||| (b ^^^ c)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) - 3 * (b &&& c) - 1 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) - 5 * ((a ||| b) &&& (b ^^^ c)) - 1 * (b ||| (a &&& c)) + 5 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) + 1 * ( ~~~a &&& (b ^^^ c)) + 2 * (b ^^^  ~~~( ~~~a &&& (b &&& c))) - 2 * (c &&&  ~~~(a &&& b)) + 4 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 6 * (a ||| (b &&& c)) - 3 * ((a &&& b) ^^^ (b ||| c)) + 1 * (a ||| c) + 4 * ((a ^^^ b) |||  ~~~(a ^^^ c)) - 2 * (b ^^^  ~~~(a &&& (b &&& c))) - 11 * ( ~~~(a |||  ~~~b) |||  ~~~(b ^^^ c)) + 1 * (c ^^^  ~~~(a &&& (b &&& c))) + 7 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 1 * (b ^^^ (a &&& (b ||| c))) + 7 * (b ^^^ (a ||| c)) - 11 * (b ^^^  ~~~(a &&& (b ^^^ c))) - 1 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) - 5 * (c |||  ~~~(a |||  ~~~b)) + 2 * (a ^^^ ( ~~~b &&& c)) + 5 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) - 2 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) + 1 *  ~~~(a &&& ( ~~~b ||| c)) + 2 *  ~~~( ~~~a ||| (b &&& c)) - 6 * (c ^^^  ~~~(a &&& (b ||| c))) + 21 *  ~~~(a ||| (b ||| c)) + 28 *  ~~~(a ||| ( ~~~b ||| c)) - 2 *  ~~~( ~~~a ||| (b ||| c)) + 5 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 6 * ( ~~~a &&& ( ~~~b &&& c)) + 15 * ( ~~~a &&& (b &&& c)) + 9 * (a &&& (b &&& c)) =  - 13 * (a &&& ( ~~~b &&& c))

theorem e_1499 :
    2 * (z ||| t) + 11 * (z |||  ~~~t) + 7 *  ~~~(z &&&  ~~~z) + 1 *  ~~~(z &&& t) - 7 *  ~~~z + 11 *  ~~~(z ^^^ t) - 1 * (z ^^^ t) - 23 *  ~~~(z ||| t) + 5 *  ~~~(z |||  ~~~t) - 19 * (z &&&  ~~~t) - 23 * (z &&& t) = 1 * z + 7 * t

theorem test1_proof : test1_before ⊑ test1_after

theorem test85_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ x.uaddOverflow (BitVec.ofInt 32 (-16777216)) = true ∨
        True ∧ (x + BitVec.ofInt 32 (-16777216)) >>> 23#32 <<< 23#32 ≠ x + BitVec.ofInt 32 (-16777216) ∨ 23#32 ≥ ↑32) →
    ¬23#32 ≥ ↑32 →
      truncate 8 ((x + BitVec.ofInt 32 (-16777216)) >>> 23#32) = truncate 8 ((x + 2130706432#32) >>> 23#32)

theorem t4_ugt_slt_65536_proof : t4_ugt_slt_65536_before ⊑ t4_ugt_slt_65536_after

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

theorem test6a_proof : test6a_before ⊑ test6a_after

theorem mul16_low_miss_shift_amount_proof : mul16_low_miss_shift_amount_before ⊑ mul16_low_miss_shift_amount_after

theorem or_signbit_select_shl_proof : or_signbit_select_shl_before ⊑ or_signbit_select_shl_after

theorem mul_add_to_mul_7_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(True ∧ x.smulOverflow 32767#16 = true ∨ True ∧ x.saddOverflow (x * 32767#16) = true) → 15#16 ≥ ↑16 → False

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

theorem lshrult_03_06_exact_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 3) { «exact» := true }) (const? 4 6) ⊑ const? 1 1

@[grind ., simp]
lemma sim_toNFA_eq_accepts {m : CNFA n} {M : NFA' n} (hsim : m.Sim M) :
    m.toNFA.accepts = M.M.accepts

theorem lshrult_02_08_exact_proof : lshrult_02_08_exact_before ⊑ lshrult_02_08_exact_after

@[simp] theorem appendList_eq : Γ ++ tys = Γ ++ ⟨tys⟩

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

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

theorem src_is_mask_or_proof : src_is_mask_or_before ⊑ src_is_mask_or_after

theorem eq_smin3_thm.extracted_1._2 : ∀ (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 or_not_xor_common_op_commute0_thm (e e_1 e_2 : IntW 4) :
  LLVM.or (LLVM.or (LLVM.xor e_2 (const? 4 (-1))) e_1) (LLVM.xor e_2 e) ⊑
    LLVM.or e_1 (LLVM.xor (LLVM.and e_2 e) (const? 4 (-1)))

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

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

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

theorem select_constants_and_icmp_ne0_zero_tval_proof : select_constants_and_icmp_ne0_zero_tval_before ⊑ select_constants_and_icmp_ne0_zero_tval_after

theorem test95_proof : test95_before ⊑ test95_after

theorem test16_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬1#32 ≥ ↑32 →
    ¬(1#32 ≥ ↑32 ∨ True ∧ (BitVec.ofInt 32 (-2)).usubOverflow (x >>> 1#32) = true) →
      4294967294#64 - zeroExtend 64 (x >>> 1#32) = zeroExtend 64 (BitVec.ofInt 32 (-2) - x >>> 1#32)

theorem sdiv_exact_eq_9_no_of_proof : sdiv_exact_eq_9_no_of_before ⊑ sdiv_exact_eq_9_no_of_after

theorem lshr_add_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(5#8 ≥ ↑8 ∨ (42#8 == 0 || 8 != 1 && x == intMin 8 && 42#8 == -1) = true ∨ 5#8 ≥ ↑8) →
    ¬((42#8 == 0 || 8 != 1 && x == intMin 8 && 42#8 == -1) = true ∨ 5#8 ≥ ↑8) →
      (x_1 >>> 5#8 + x.srem 42#8) <<< 5#8 = x_1 + x.srem 42#8 <<< 5#8 &&& BitVec.ofInt 8 (-32)

theorem trunc_sel_larger_zext_proof : trunc_sel_larger_zext_before ⊑ trunc_sel_larger_zext_after

theorem ule_umax3_proof : ule_umax3_before ⊑ ule_umax3_after

theorem not_signbit_trunc_proof : not_signbit_trunc_before ⊑ not_signbit_trunc_after

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

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

theorem test17_proof : test17_before ⊑ test17_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_3_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 15#32 == 0#32) ||
</all_available_lemmas>

<local_ctx>
import Blase.Fast.FiniteStateMachine

import Blase.Vars

import Blase.MultiWidth.Defs

import Blase.KInduction.KInduction

import Lean

namespace MultiWidth

def fsmMsb (x w : FSM α) : FSM α :=
  composeBinaryAux'
    (FSM.latchImmediate false)
    (qfalse := x)
    (qtrue := w)

def fsmSext (x wold wnew : FSM α) : FSM α :=
  (fsmMsb x wold) &&& wnew
</local_ctx>

<target_theorem>
theorem fsmSext_eval_eq
    (woldFsm : NatFSM wcard tcard bcard ncard icard pcard (.ofDep wold))
    (wnewFsm : NatFSM wcard tcard bcard ncard icard pcard (.ofDep wnew))
    {wenv : WidthExpr.Env wcard}
    {fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream}
    (hwnew : HNatFSMToBitstream wnewFsm)
    (hwold : HNatFSMToBitstream woldFsm)
    {tctx : Term.Ctx wcard tcard}
    (tenv : Term.Ctx.Env tctx wenv)
    (benv : Term.BoolEnv bcard)
    (nenv : Term.NatEnv ncard)
    (ienv : Term.IntEnv icard)
    (t : Term bcard ncard icard pcard tctx (.bv wold))
    (tFsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm t))
    (htfsm : HTermFSMToBitStream tFsm)
    (htenv : HTermEnv fsmEnv tenv benv) :
    (fsmSext tFsm.toFsmZext woldFsm.toFsm  wnewFsm.toFsm).eval fsmEnv = fun i =>
      ((BitStream.ofBitVecZext ((Term.sext t wnew).toBV benv nenv ienv penv tenv))) i :=
</target_theorem>

