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>
DecidableEq in Init.Prelude
Lean.ToExpr in Lean.ToExpr
List in Init.Prelude
Repr in Init.Data.Repr
Nat in Init.Prelude
Fin in Init.Prelude
Option in Init.Prelude
reduceDIte in Lean.Meta.Tactic.Simp.BuiltinSimprocs.Core
ZMod in Mathlib.Data.ZMod.Defs
Int in Init.Data.Int.Basic
BitVec in Init.Prelude
String in Init.Prelude
Id in Init.Control.Id
Vector in Init.Data.Vector.Basic
StateM in Init.Control.State
Inhabited in Init.Prelude
Lean.Expr in Lean.Expr
Stream' in Mathlib.Data.Stream.Defs
Unit in Init.Prelude
Stream'.tail in Mathlib.Data.Stream.Defs
Id.run in Init.Control.Id
Bool in Init.Prelude
bool in Init.Control.Basic
List.replicate in Init.Data.List.Basic
BitVec.ofInt in Init.Data.BitVec.Basic
inferInstanceAs in Init.Prelude
Hashable in Init.Prelude
id in Init.Prelude
Std.HashMap in Std.Data.HashMap.Basic

protected instance HVector.decidableEqReg [DecidableEq d.Op] [DecidableEq d.Ty] :
    ∀ {l : RegionSignature d.Ty}, DecidableEq (HVector (fun t => Com d t.1 .impure t.2) l)
  | _, .nil, .nil => isTrue rfl
  | _, .cons x₁ v₁, .cons x₂ v₂ =>
    letI := HVector.decidableEqReg v₁ v₂
    letI := Com.decidableEq x₁ x₂
    decidable_of_iff (x₁ = x₂ ∧ v₁ = v₂) (by admit /- proof elided -/
    )

def idxOf? (x : A a) {as} [DecidableEq α] [∀ a, DecidableEq (A a)] :
    HVector A as → Option { i : Fin <| as.length // as.get i = a }
  | .nil => none
  | .cons (a:=b) y ys =>
      if h : ∃ h : a = b, x = h ▸ y then
        some ⟨(0 : Fin <| _ + 1), h.1 ▸ rfl⟩
      else
        (ys.idxOf? x).map fun ⟨i, h⟩ =>
          ⟨i.succ, by admit /- proof elided -/
          ⟩

def map (f : ∀ (a : α), A a → B a) :
    ∀ {l : List α}, HVector A l → HVector B l
  | [],   .nil        => .nil
  | t::_, .cons a as  => .cons (f t a) (map f as)

structure HVectorLiteral where
  u : Level
  v : Level
  α : Q(Type $u)
  A : Q($α → Type $v)
  elems : Array ((a : Q($α)) × Q($A $a))

instance : TyDenote Unit where toType := fun _ => Unit

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

inductive Ty (q : Nat) (n : Nat)
  | index : Ty q n
  | integer : Ty q n
  | tensor : Ty q n
  | polynomialLike : Ty q n
  deriving DecidableEq, Repr

instance : TyDenote ISL.Ty where
  toType := fun
    | .regIndex => RegIndex
    | .bits w => BitVec w

def_denote for ISL
  | .regConst r   => [r]ₕ
  | .regRead      => fun r regFile => ([regFile.read r]ₕ, regFile)
  | .regWrite     => fun r v regFile => ([]ₕ, regFile.write r v)
  | .bitsConst x  => [x]ₕ
  | .bitsAdd _    => fun (x y : BitVec _) => [x + y]ₕ

def ExplicitISL : Dialect where
  Op := ISLOp
  Ty := ExpTy
  m := Id

inductive ExpTy where
  | isl : ISL.Ty → ExpTy
  | regFile

def ISL : Dialect where
  Ty := ISLTy
  Op := ISLOp
  m := StateM RegFile

inductive ISLTy
  | regIndex
  | bits (w : Nat)
  deriving DecidableEq, ToExpr, Repr

inductive ISLOp
  | regConst (r : RegIndex)
  | regRead
  | regWrite
  | bitsConst {w : Nat} (x : BitVec w)
  | bitsAdd (w : Nat)
  deriving DecidableEq, ToExpr, Repr

def RegIndex := Fin RegFile.numRegisters

def RegFile.numRegisters := 32

structure Dialect where
  (Op : Type)
  (Ty : Type)
  (m : Type → Type := Id)

inductive Op (q : Nat) (n : Nat)
  | add : Op q n
  | sub : Op q n
  | mul : Op q n
  | mul_constant : Op q n
    
    
  | leading_term : Op q n
  | monomial : Op q n
  | monomial_mul : Op q n
  | from_tensor : Op q n
  | to_tensor : Op q n
  | const (c : R q n) : Op q n
  | const_int (c : Int) : Op q n
  | const_idx (i : Nat) : Op q n

structure RegFile where
  regs : Vector (BitVec RegFile.registerWidth) RegFile.numRegisters

def RegFile.registerWidth := 64

def read (self : RegFile) (r : RegIndex) : BitVec registerWidth :=
  self.regs[r.val]

def write (self : RegFile) (r : RegIndex) (v : BitVec registerWidth) : RegFile :=
  RegFile.mk <| self.regs.set r.val v

instance instDCTyDenote : TyDenote Ty where
toType := fun
| Ty.tokenstream => CIRCTStream.DCPlusOp.TokenStream
| Ty.tokenstream2 => CIRCTStream.DCPlusOp.TokenStream × CIRCTStream.DCPlusOp.TokenStream
| Ty.valuestream w => CIRCTStream.DCPlusOp.ValueStream (BitVec w)
| Ty.valuestream2 w => CIRCTStream.DCPlusOp.ValueStream (BitVec w) × CIRCTStream.DCPlusOp.ValueStream (BitVec w)
| Ty.valuetokenstream w => CIRCTStream.DCPlusOp.ValueStream (BitVec w) × CIRCTStream.DCPlusOp.TokenStream
| Ty.variadicvaluetokenstream w => CIRCTStream.DCPlusOp.VariadicValueStream w × CIRCTStream.DCPlusOp.TokenStream

def_denote for DCPlus where
  | .fst => fun s => [s.fst]ₕ
  | .fstVal _ => fun s => [s.fst]ₕ
  | .fstValPure _ => fun s => [s.fst]ₕ
  | .fstVal' _ => fun s => [s.fst.mapOpt (·[0]?)]ₕ
  | .snd => fun s => [s.snd]ₕ
  | .sndValPure _ => fun s => [s.snd]ₕ
  | .pair _ => fun s₁ s₂ => [(s₁, s₂)]ₕ
  | .sndVal _ => fun s => [s.snd]ₕ
  | .sndVal' _ => fun s => [s.fst.mapOpt (·[0]?)]ₕ
  | .tokVal' _ => fun s => [s.snd]ₕ
  | .merge => fun s₁ s₂ => [CIRCTStream.DCPlusOp.merge s₁ s₂]ₕ
  | .branch => fun s₁ s₂ => [CIRCTStream.DCPlusOp.branch s₁ s₂]ₕ
  | .fork => fun s => [CIRCTStream.DCPlusOp.fork s]ₕ
  | .forkVal => fun s => [CIRCTStream.DCPlusOp.forkVal s]ₕ
  | .join => fun s₁ s₂ => [CIRCTStream.DCPlusOp.join s₁ s₂]ₕ
  | .mux => fun s₁ s₂ c => [CIRCTStream.DCPlusOp.mux s₁ s₂ c]ₕ
  | .muxVal => fun s₁ s₂ c => [CIRCTStream.DCPlusOp.muxVal s₁ s₂ c]ₕ
  | .sink => fun s => [CIRCTStream.DCPlusOp.sink s]ₕ
  | .source => [CIRCTStream.DCPlusOp.source]ₕ
  | .sourceOnes => [CIRCTStream.DCPlusOp.sourceOnes]ₕ
  | .cMerge => fun s₁ s₂ => [CIRCTStream.DCPlusOp.cMerge s₁ s₂]ₕ
  | .supp => fun s₁ s₂ => [CIRCTStream.DCPlusOp.supp s₁ s₂]ₕ
  | .not => fun s₁ => [CIRCTStream.DCPlusOp.not s₁]ₕ

abbrev DCPlus : Dialect where
  Op := Op
  Ty := Ty

def_signature for DCPlus where
  | .fst => (Ty.tokenstream2) → (Ty.tokenstream)
  | .fstVal t => (Ty.valuetokenstream t) → Ty.valuestream t
  | .fstVal' t => (Ty.variadicvaluetokenstream t) → Ty.valuestream t
  | .fstValPure t => (Ty.valuestream2 t) → Ty.valuestream t
  | .snd => (Ty.tokenstream2) → (Ty.tokenstream)
  | .sndValPure t => (Ty.valuestream2 t) → Ty.valuestream t
  | .pair w => (Ty.valuestream w, Ty.valuestream w) → Ty.valuestream2 w
  | .sndVal t => (Ty.valuetokenstream t) → Ty.tokenstream
  | .sndVal' t => (Ty.variadicvaluetokenstream t) → Ty.valuestream t
  | .tokVal' t => (Ty.variadicvaluetokenstream t) → Ty.tokenstream
  | .merge => (Ty.tokenstream, Ty.tokenstream) → Ty.valuestream 1
  | .branch => (Ty.valuestream 1, Ty.tokenstream) → Ty.tokenstream2
  | .fork => (Ty.tokenstream) → Ty.tokenstream2
  | .forkVal => (Ty.valuestream 1) → Ty.valuestream2 1
  | .join => (Ty.tokenstream, Ty.tokenstream) → Ty.tokenstream
  | .mux => (Ty.tokenstream, Ty.tokenstream, Ty.valuestream 1) → Ty.tokenstream
  | .muxVal => (Ty.valuestream 1, Ty.valuestream 1, Ty.valuestream 1) → Ty.valuestream 1
  | .sink => (Ty.tokenstream) → Ty.tokenstream
  | .source => () → Ty.tokenstream
  | .sourceOnes => () → Ty.valuestream 1
  | .cMerge => (Ty.tokenstream, Ty.tokenstream) → Ty.valuetokenstream 1
  | .supp => (Ty.valuestream 1, Ty.tokenstream) → Ty.tokenstream
  | .not => (Ty.valuestream 1) → Ty.valuestream 1

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

inductive Ty
| tokenstream : Ty
| tokenstream2 : Ty
| valuestream (w : Nat) : Ty 
| valuestream2 (w : Nat) : Ty 
| valuetokenstream (w : Nat) : Ty 
| variadicvaluetokenstream (w : Nat) : Ty 
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

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

def Context (Ty : Type) : Type :=
  List (VarName × Ty)

def VarName : Type := String

def hasType (Γ : Context Ty) (v : VarName) (ty : Ty) : Prop :=
  Γ.lookup v = some ty

protected instance Expr.decidableEq [DecidableEq d.Op] [DecidableEq d.Ty] :
    {Γ : Ctxt d.Ty} → {ty : List d.Ty} → DecidableEq (Expr d Γ eff ty)
  | Γ, _, .mk op₁ rfl eff_le₁ arg₁ regArgs₁, .mk op₂ eq eff_le₂ arg₂ regArgs₂ =>
    if ho : op₁ = op₂ then by
      subst ho
      letI := HVector.decidableEq arg₁ arg₂
      letI := HVector.decidableEqReg regArgs₁ regArgs₂
      exact decidable_of_iff (arg₁ = arg₂ ∧ regArgs₁ = regArgs₂) (by admit /- proof elided -/
      )
    else isFalse (by admit /- proof elided -/
    )

inductive AffineExpr
  | Var: String -> AffineExpr
  deriving DecidableEq, Repr

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 branch {Γ : Ctxt _} (c : Γ.Var (MLIR2DCPlus.Ty.valuestream 1)) (a : Γ.Var (MLIR2DCPlus.Ty.tokenstream)) : Expr (DCPlus) Γ .pure (.tokenstream2) :=
  Expr.mk
    (op := .branch)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons c <| .cons a <| .nil)
    (regArgs := .nil)

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

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

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

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

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

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

inductive Op
| fst
| snd
| pair (w : Nat)
| fstVal (w : Nat)
| fstValPure (w : Nat)
| sndVal (w : Nat)
| sndValPure (w : Nat)
| fstVal' (w : Nat)
| sndVal' (w : Nat)
| tokVal' (w : Nat)
| fork
| forkVal
| join
| merge
| mux
| muxVal
| cMerge
| branch
| source
| sourceOnes
| sink
| supp
| not
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

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 sink {Γ : Ctxt _} (a : Γ.Var (MLIR2DCPlus.Ty.tokenstream)) : Expr (DCPlus) Γ .pure (.tokenstream) :=
  Expr.mk
    (op := .sink)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

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

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

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

def sourceOnes : Expr (DCPlus) Γ .pure (.valuestream 1) :=
  Expr.mk
    (op := .sourceOnes)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .nil)
    (regArgs := .nil)

def snd {Γ} (a : Γ.Var (MLIR2DCPlus.Ty.tokenstream2)) : Expr (DCPlus) Γ .pure (.tokenstream) :=
    Expr.mk
    (op := .snd)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

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

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

def TokenStream := Stream Unit

def Stream (β : Type) := Stream' (Option β)

def ValueStream := Stream

def VariadicValueStream (w : Nat) := CIRCTStream.Stream (List (BitVec w))

def branch (c : ValueStream (BitVec 1)) (x : TokenStream) : TokenStream × TokenStream  :=
  Stream.corec₂ (β := ValueStream (BitVec 1) × TokenStream) (c, x) fun ⟨c, x⟩ =>
    Id.run <| do
      match c 0 with
        | none => (none, none, (c.tail, x))
        | some x₀ =>
          if x₀.msb then
            (some (), none, (c.tail, x.tail))
          else
            (none, some (), (c.tail, x.tail))

def tail : Stream α → Stream α := Stream'.tail

def corec₂ {β} (s0 : β) (f : β → (Option α × Option γ × β)) : Stream α × Stream γ :=
  let f' := fun b =>
    let x := f b
    (x.fst, x.snd.fst)
  let g := (f · |>.snd.snd)
  let x := Stream'.corec f' g s0
  (
    fun i => (x i).fst,
    fun i => (x i).snd,
  )

def cMerge (x y : TokenStream) : ValueStream (BitVec 1) × TokenStream :=
  Stream.corec₂ (β := TokenStream × TokenStream) (x, y) fun ⟨x, y⟩ =>
    match x 0, y 0 with
    | some x', some _ => (some 1, some x', (x.tail, y))
    | some x', none => (some 1, some x', (x.tail, y.tail))
    | none, some y' => (some 0, some y', (x.tail, y.tail))
    | none, none => (none, none, (x.tail, y.tail))

def fork (x : TokenStream) : TokenStream × TokenStream  :=
  Stream.corec₂ (β := TokenStream) x
    fun x => Id.run <| do
      (x 0, x 0, x.tail)

def forkVal (x : ValueStream (BitVec 1)) : ValueStream (BitVec 1) × ValueStream (BitVec 1)  :=
  Stream.corec₂ (β := ValueStream (BitVec 1)) x
    fun x => Id.run <| do
      (x 0, x 0, x.tail)

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

def corec {α} {β} (s0 : β) (f : β → (Option α × β)) : Stream α :=
  Stream'.corec (f · |>.fst) (f · |>.snd) s0

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

def mux (x y : TokenStream) (c : ValueStream (BitVec 1)): TokenStream :=
  Stream.corec (β := TokenStream × TokenStream × ValueStream (BitVec 1)) (x, y, c)
  fun ⟨x, y, c⟩ =>
    match (c 0) with
    | none => (none, x, y, c.tail) 
    | some 1#1 =>
      match (x 0) with
      | none => (none, x.tail, y, c) 
      | some _ => (some (), x.tail, y, c.tail) 
    | some 0#1 =>
      match (y 0) with
      | none => (none, x, y.tail, c) 
      | some _ => (some (), x, y.tail, c.tail)

def muxVal (x y c : ValueStream (BitVec 1)): ValueStream (BitVec 1) :=
  Stream.corec (β := ValueStream (BitVec 1) × ValueStream (BitVec 1) × ValueStream (BitVec 1)) (x, y, c)
  fun ⟨x, y, c⟩ =>
    match (c 0) with
    | none => (none, x, y, c.tail) 
    | some 1#1 =>
      match (x 0) with
      | none => (none, x.tail, y, c) 
      | some e => (some e, x.tail, y, c.tail) 
    | some 0#1 =>
      match (y 0) with
      | none => (none, x, y.tail, c) 
      | some e => (some e, x, y.tail, c.tail)

def not (c : ValueStream (BitVec 1)) : (ValueStream (BitVec 1)) :=
  Stream.corec (β := ValueStream (BitVec 1)) c fun c =>
  match c 0 with
  | some 1 => (some 0, c.tail)
  | some 0 => (some 1, c.tail)
  | _ => (none, c.tail)

def sink (x : TokenStream) : TokenStream :=
  Stream.corec (β := TokenStream) x fun x => (none, x.tail)

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

def sourceOnes : ValueStream (BitVec 1) :=
  Stream.corec () fun () => (1#1, ())

def supp (c : ValueStream (BitVec 1)) (x : TokenStream) : TokenStream := (branch c x).snd

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

instance : TyDenote Ty where toType
  | .felt => Fin BabyBear

def BabyBear := 2^31 - 2^27 + 1

inductive Ty
  | felt

instance instDCTyDenote : TyDenote Ty where
toType := fun
| Ty.tokenstream => CIRCTStream.DCOp.TokenStream
| Ty.tokenstream2 => CIRCTStream.DCOp.TokenStream × CIRCTStream.DCOp.TokenStream
| Ty.valuestream w => CIRCTStream.DCOp.ValueStream (BitVec w)
| Ty.valuestream2 w => CIRCTStream.DCOp.ValueStream (BitVec w) × CIRCTStream.DCOp.ValueStream (BitVec w)
| Ty.valuetokenstream w => CIRCTStream.DCOp.ValueStream (BitVec w) × CIRCTStream.DCOp.TokenStream
| Ty.variadicvaluetokenstream w => CIRCTStream.DCOp.VariadicValueStream w × CIRCTStream.DCOp.TokenStream

def_denote for DC where
  | .fst => fun s => [s.fst]ₕ
  | .fstVal _ => fun s => [s.fst]ₕ
  | .fstVal' _ => fun s => [s.fst.mapOpt (·[0]?)]ₕ
  | .snd => fun s => [s.snd]ₕ
  | .pair _ => fun s₁ s₂ => [(s₁, s₂)]ₕ
  | .sndVal _ => fun s => [s.snd]ₕ
  | .sndVal' _ => fun s => [s.fst.mapOpt (·[0]?)]ₕ
  | .tokVal' _ => fun s => [s.snd]ₕ
  | .merge => fun s₁ s₂ => [CIRCTStream.DCOp.merge s₁ s₂]ₕ
  | .branch => fun s => [CIRCTStream.DCOp.branch s]ₕ
  | .fork => fun s => [CIRCTStream.DCOp.fork s]ₕ
  | .join => fun s₁ s₂ => [CIRCTStream.DCOp.join s₁ s₂]ₕ
  | .select => fun s₁ s₂ c => [CIRCTStream.DCOp.select s₁ s₂ c]ₕ
  | .sink => fun s => [CIRCTStream.DCOp.sink s]ₕ
  | .source => [CIRCTStream.DCOp.source]ₕ
  | .pack _ => fun s₁ s₂ => [CIRCTStream.DCOp.pack s₁ s₂]ₕ
  | .pack2 _ => fun s₁ => [CIRCTStream.DCOp.pack2 s₁]ₕ
  | .unpack _ => fun s => [CIRCTStream.DCOp.unpack s]ₕ
  | .unpack2 _ => fun s₁ s₂ => [CIRCTStream.DCOp.unpack2 s₁ s₂]ₕ

def branch (x : ValueStream (BitVec 1)): TokenStream × TokenStream  :=
  Stream.corec₂ (β := ValueStream (BitVec 1)) x fun x =>
    Id.run <| do
      match x 0 with
        | none => (none, none, (x.tail))
        | some x₀ =>
          if x₀.msb then
            (some (), none, (x.tail))
          else
            (none, some (), (x.tail))

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

| shiftL : Term → Nat → Term

deriving Repr, Inhabited, Lean.ToExpr

def pack (x : ValueStream α) (y : TokenStream) : ValueStream α :=
  Stream.corec (β := ValueStream α × TokenStream) (x, y) fun ⟨x, y⟩ =>
    match x 0, y 0 with
    | some x₀, some _ => (x₀, (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 (x y : TokenStream) (c : ValueStream (BitVec 1)): TokenStream :=
  Stream.corec (β := TokenStream × TokenStream × Stream (BitVec 1)) (x, y, c)
  fun ⟨x, y, c⟩ =>
    match (c 0) with
    | none => (none, x, y, c.tail) 
    | some 1#1 =>
      match (x 0) with
      | none => (none, x.tail, y, c) 
      | some _ => (some (), x.tail, y, c.tail) 
    | some 0#1 =>
      match (y 0) with
      | none => (none, x, y.tail, c) 
      | some _ => (some (), x, y.tail, c.tail)

def unpack (x : ValueStream (BitVec w)) : ValueStream (BitVec w) × TokenStream :=
  Stream.corec₂ (β := Stream (BitVec w)) (x)
    fun x => Id.run <| do
      match x 0 with
      | some _ => return (x 0, some (), x.tail)
      | none => return (none, none, x.tail)

abbrev DC : Dialect where
  Op := Op
  Ty := Ty

def_signature for DC where
  | .fst => (Ty.tokenstream2) → (Ty.tokenstream)
  | .fstVal t => (Ty.valuetokenstream t) → Ty.valuestream t
  | .fstVal' t => (Ty.variadicvaluetokenstream t) → Ty.valuestream t
  | .snd => (Ty.tokenstream2) → (Ty.tokenstream)
  | .pair w => (Ty.valuestream w, Ty.valuestream w) → Ty.valuestream2 w
  | .sndVal t => (Ty.valuetokenstream t) → Ty.tokenstream
  | .sndVal' t => (Ty.variadicvaluetokenstream t) → Ty.valuestream t
  | .tokVal' t => (Ty.variadicvaluetokenstream t) → Ty.tokenstream
  | .merge => (Ty.tokenstream, Ty.tokenstream) → Ty.valuestream 1
  | .branch => (Ty.valuestream 1) → Ty.tokenstream2
  | .fork => (Ty.tokenstream) → Ty.tokenstream2
  | .join => (Ty.tokenstream, Ty.tokenstream) → Ty.tokenstream
  | .select => (Ty.tokenstream, Ty.tokenstream, Ty.valuestream 1) → Ty.tokenstream
  | .sink => (Ty.tokenstream) → Ty.tokenstream
  | .source => () → Ty.tokenstream
  | .pack t => (Ty.valuestream t, Ty.tokenstream) → Ty.valuestream t
  | .pack2 t => (Ty.variadicvaluetokenstream t) → Ty.valuestream2 t
  | .unpack t => (Ty.valuestream t) → Ty.valuetokenstream t
  | .unpack2 t => (Ty.valuestream t, Ty.valuestream t) → Ty.variadicvaluetokenstream t

inductive Op
| fst
| snd
| pair (w : Nat)
| fstVal (w : Nat)
| sndVal (w : Nat)
| fstVal' (w : Nat)
| sndVal' (w : Nat)
| tokVal' (w : Nat)
| merge
| branch
| fork
| join
| select
| sink
| source
| pack (w : Nat)
| pack2 (w : Nat)
| unpack (w : Nat)
| unpack2 (w : Nat)
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

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

def fork (a : Γ.Var (.tokenstream)) : Expr (DC) Γ .pure (.tokenstream2) :=
  Expr.mk
    (op := .fork)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def pack2 (x : VariadicValueStream α × TokenStream) : (ValueStream (BitVec α)) × (ValueStream (BitVec α))  :=
  Stream.corec₂ (β := VariadicValueStream α × TokenStream) (x) fun ⟨x, y⟩ =>
    match x 0, y 0 with
    | some x', some _ => (x'[0]?, x'[1]?, (x.tail, y.tail))
    | some _, none => (none, none, (x, y.tail))
    | none, some _ => (none, none, (x.tail, y)) 
    | none, none => (none, none, (x.tail, y.tail))

def unpack2 (x : ValueStream (BitVec w)) (y : ValueStream (BitVec w)) : VariadicValueStream w × TokenStream :=
  Stream.corec₂ (β := CIRCTStream.Stream (BitVec w) × CIRCTStream.Stream (BitVec w)) (x, y)
    fun (x, y) => Id.run <| do
      match x 0, y 0 with
      | some x', some y' => return (some [x', y'], some .unit, (x.tail, y.tail))
      | some _, none => return (none, none, (x, y.tail))
      | none, some _ => return (none, none, (x.tail, y)) 
      | none, none => return (none, none, (x.tail, y.tail))

@[reducible]
instance : TyDenote ExTy where
  toType
    | .nat => Nat
    | .bool => Bool

inductive ExTy
  | nat
  | bool
  deriving DecidableEq

instance : TyDenote Ty where toType := Ty.toType

def Ty.toType : Ty → Type
| .int => Int
| .ix => Index
| .tensor2d => Tensor2d' Int

instance : TyDenote Ty where
  toType
  | .int => Int
  | .ix => Index
  | .tensor1d => Tensor1d Int

abbrev Index := ℕ

structure Tensor1d (α : Type) [Inhabited α] where
  size : Index
  val :  Index → α
  spec : ∀ (ix: Index), ix >= size -> val ix = default

structure Tensor2d (α : Type) where
  size0 : Nat
  size1 : Nat
  val :  Fin size0 → Fin size1 → α

instance : TyDenote TestDialect.Ty where toType
  | .int => Int
  | .int2 => Int × Int

def_signature for TestDialect
  | .noop => () -> []
  | .mkPair => (.int, .int) -> .int2
  | .unPair => (.int2) -> [.int, .int]

def_denote for TestDialect
  | .noop => []ₕ
  | .unPair => fun (x, y) => [x, y]ₕ
  | .mkPair => fun x y => [(x, y)]ₕ

inductive Op
  | noop
  | mkPair
  | unPair
  deriving Lean.ToExpr

def TestDialect : Dialect where
  Ty := Ty
  Op := Op

inductive Ty
  | int
   
  | int2
  deriving DecidableEq, Lean.ToExpr

instance : TyDenote Ty where
  toType
  | Ty.bv => BitVec 64

inductive Ty
  | bv : Ty
  deriving DecidableEq, Repr, Inhabited, Lean.ToExpr

instance : TyDenote LLVM.Ty where
  toType := fun
    | bitvec w => LLVM.IntW w

def IntW w := PoisonOr <| BitVec w

structure PoisonOr (α : Type) where
  val : α
  poisonous : Bool
deriving Inhabited, DecidableEq

@[reducible]
instance : TyDenote Ty where
  toType
    | .int => BitVec 32

abbrev SimpleReg.int : SimpleReg.Ty := .int

instance : TyDenote Ty where toType
  | .int => BitVec 32

inductive ExTy
  | nat
  | bool
  deriving DecidableEq, Repr

instance : TyDenote Ty2 where
toType := fun
|  Ty2.bitvec w => BitVec w

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

instance instHandshakeTyDenote : TyDenote Ty where
toType := fun
| Ty.stream ty2 => CIRCTStream.Stream (TyDenote.toType ty2)
| Ty.stream2 ty2 => CIRCTStream.Stream (TyDenote.toType ty2) × CIRCTStream.Stream (TyDenote.toType ty2)
| Ty.stream2token ty2 => CIRCTStream.Stream (TyDenote.toType ty2) × CIRCTStream.Stream (TyDenote.toType (Ty2.bitvec 1))

def_denote for Handshake where
| .fst _ => fun s => [s.fst]ₕ
| .snd _ => fun s => [s.snd]ₕ
| .branch _ => fun s c => [HandshakeOp.branch s c]ₕ
| .merge _ => fun s₁ s₂ => [HandshakeOp.merge s₁ s₂]ₕ
| .altMerge _ => fun s₁ s₂ => [HandshakeOp.altMerge s₁ s₂]ₕ
| .fork _ => fun s => [HandshakeOp.fork s]ₕ
| .controlMerge _ => fun s₁ s₂ => [HandshakeOp.controlMerge s₁ s₂]ₕ
| .join _ => fun s₁ s₂ => [HandshakeOp.join s₁ s₂]ₕ
| .mux _ => fun s₁ s₂ c => [HandshakeOp.mux s₁ s₂ c]ₕ
| .sink _ => fun s => [HandshakeOp.sink s]ₕ
| .sync _ => fun s₁ s₂ => [HandshakeOp.sync s₁ s₂]ₕ
| .supp _ => fun s₁ s₂ => [HandshakeOp.supp s₁ s₂]ₕ
| .not => fun s₁ => [HandshakeOp.not s₁]ₕ

abbrev Handshake : Dialect where
  Op := Op
  Ty := Ty

def_signature for Handshake where
| .fst t => (Ty.stream2 t) → Ty.stream t
| .snd t => (Ty.stream2 t) → Ty.stream t
| .branch t => (Ty.stream t, Ty.stream (Ty2.bitvec 1)) → Ty.stream2 t
| .merge t => (Ty.stream t, Ty.stream t) → Ty.stream t
| .altMerge t => (Ty.stream t, Ty.stream t) → Ty.stream t
| .fork t => (Ty.stream t) → Ty.stream2 t 
| .controlMerge t => (Ty.stream t, Ty.stream t) → (Ty.stream2token t)
| .join t => (Ty.stream t, Ty.stream t) → (Ty.stream (Ty2.bitvec 1))
| .mux t => (Ty.stream t, Ty.stream t, Ty.stream (Ty2.bitvec 1)) → Ty.stream t
| .sink t => (Ty.stream t) → (Ty.stream (Ty2.bitvec 1))
| .sync t => (Ty.stream t, Ty.stream t) → Ty.stream2 t
| .supp t => (Ty.stream t, Ty.stream (Ty2.bitvec 1)) → Ty.stream t
| .not => (Ty.stream (Ty2.bitvec 1)) → Ty.stream (Ty2.bitvec 1)

inductive Ty
| stream (ty2 : Ty2) : Ty 
| stream2 (ty2 : Ty2) : Ty 
| stream2token (ty2 : Ty2) : Ty 
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

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

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

inductive Op
| fst (t : Ty2)
| snd (t : Ty2)
| branch (t : Ty2)
| merge (t : Ty2)
| altMerge (t : Ty2)
| fork (t : Ty2)
| controlMerge (t : Ty2)
| join (t : Ty2)
| mux (t : Ty2)
| sink (t : Ty2)
| sync (t : Ty2)
| supp (t : Ty2)
| not
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

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

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

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

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

def altMerge (x y : Stream α) : Stream α :=
  Stream.corec (β := Stream α × Stream α × ConsumeFrom) (x, y, .left) fun ⟨x, y, consume⟩ =>
    match consume with
      | .left  =>
        let x0 := x.head
        let x := x.tail
        let nextConsume := match x0 with
          | some _ => .right
          | none   => .left
        (x0, x, y, nextConsume)
      | .right =>
        let y0 := y.head
        let y := y.tail
        let nextConsume := match y0 with
          | some _ => .left
          | none   => .right
        (y0, x, y, nextConsume)

def branch (x : Stream α) (c : Stream (BitVec 1)) : Stream α × Stream α :=
  Stream.corec₂ (β := Stream α × Stream (BitVec 1)) (x, c)
    fun ⟨x, c⟩ => Id.run <| do
      let c₀ := c 0
      let c' := c.tail
      let x₀ := x 0
      let x' := x.tail
      match c₀, x₀ with
        | none, _ => (none, none, (x, c'))
        | _, none => (none, none, (x', c))
        | some c₀, some x₀ =>
          if c₀ = 1 then
            (some x₀, none, (x', c'))
          else
            (none, some x₀, (x', c'))

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

def fork (x : Stream α) : Stream α × Stream α :=
  Stream.corec₂ (β := Stream α) x
    fun x => Id.run <| do
      let x0 := x 0
      let x' := x.tail
      (x0, x0, x')

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 merge (x y : Stream α) : Stream α :=
  Stream.corec (β := Stream α × Stream α) (x, y) fun ⟨x, y⟩ =>
    match x 0, y 0 with
    | some x', some _ => (some x', (x.tail, y))
    | some x', none => (some x', (x.tail, y.tail))
    | none, some y' => (some y', (x.tail, y.tail))
    | none, none => (none, (x.tail, y.tail))

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

def not (x : Stream (BitVec 1)) : Stream (BitVec 1) :=
  Stream.corec (β := Stream (BitVec 1)) x fun x =>
    match x 0 with
    | some 1 => (some 0, (x.tail))
    | some 0 => (some 0,  (x.tail))
    | none => (none, (x.tail))

def sink (x : Stream α) : Stream (BitVec 1) :=
  Stream.corec (β := Stream α) (x) fun (x) => (none, x.tail)

def supp (x : Stream α) (c : Stream (BitVec 1)) : Stream α := (branch x c).snd

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

@[simp]
instance : TyDenote LLVMPlusRiscV.Ty where
  toType := fun
    | .llvm llvmTy => TyDenote.toType llvmTy
    | .riscv riscvTy => TyDenote.toType riscvTy

inductive Op where
  | llvm : LLVM.Op -> Op
  | riscv : RISCV64.RV64.Op -> Op
  | castRiscv : Nat → Op
  | castLLVM : Nat → Op
  deriving DecidableEq, Repr, Lean.ToExpr

inductive ExTy
  | nat
  deriving DecidableEq, Repr

@[reducible]
instance : TyDenote ExTy where
  toType
    | .nat => Nat

instance : TyDenote (Dialect.Ty VariadicDialect) where
  toType := fun | .int => BitVec 32

def_denote for VariadicDialect where
  | .const z => BitVec.ofInt _ z
  | .add _   => fun xs => xs.foldl (fun ⟨⟩ => (· + ·)) 0#32

inductive Op : Type
| add (n : Nat) : Op
| const : (val : ℤ) → Op
deriving DecidableEq, Repr

def VariadicDialect : Dialect where
  Op := Op
  Ty := Ty

def_signature for VariadicDialect where
  | .const _  => () -> .int
  | .add n    => ${List.replicate n .int} → .int

inductive Ty
| int
deriving DecidableEq, Repr

instance : TyDenote (Dialect.Ty Comb) where
  toType := fun
  | .bitvec w => BitVec w

instance : TyDenote (Scf d).Ty := inferInstanceAs (TyDenote d.Ty)

class TyDenote (β : Type) : Type 1 where
  toType : β → Type

instance : TyDenote Ty where
  toType
    | .int => ℤ
    | .bool => Bool
    | .nat => Nat

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

instance : TyDenote SLLVM.Ty where
  toType
  | .arith t => ⟦t⟧
  | .ptr => SLLVM.Ptr
  | .mem => MemorySSAState

inductive SLLVMOp where
  | arith (o : LLVM.Op)
  | ptradd
  | load (w : Nat)
  | store (w : Nat)
  | alloca (w : Nat)
  | loadPure (w : Nat)
  | storePure (w : Nat)
  deriving DecidableEq, Lean.ToExpr

@[match_pattern] abbrev Ty.mem : SLLVM.Ty := .mem

@[match_pattern] nonrec abbrev Op.arith : LLVM.Op → SLLVM.Op := .arith

@[match_pattern] nonrec abbrev Op.neg (w : Nat) : SLLVM.Op := arith <| Op.neg w
@[match_pattern] nonrec abbrev Op.not (w : Nat) : SLLVM.Op := arith <| Op.not w
@[match_pattern] nonrec abbrev Op.copy (w : Nat) : SLLVM.Op := arith <| Op.copy w
@[match_pattern] nonrec abbrev Op.freeze (w : Nat) : SLLVM.Op := arith <| Op.freeze w
@[match_pattern] nonrec abbrev Op.sext (w w' : Nat) : SLLVM.Op := arith <| Op.sext w w'
@[match_pattern] nonrec abbrev Op.zext (w w' : Nat) (flag : LLVM.NonNegFlag := { }) : SLLVM.Op := arith <| Op.zext w w' flag
@[match_pattern] nonrec abbrev Op.trunc (w w' : Nat) (flags : LLVM.NoWrapFlags := { }) : SLLVM.Op := arith <| Op.trunc w w' flags

@[match_pattern] nonrec abbrev Op.and (w : Nat) : SLLVM.Op := arith <| Op.and w
@[match_pattern] nonrec abbrev Op.or (w : Nat) (flag : LLVM.DisjointFlag := { }) : SLLVM.Op := arith <| Op.or w flag
@[match_pattern] nonrec abbrev Op.xor (w : Nat) : SLLVM.Op := arith <| Op.xor w
@[match_pattern] nonrec abbrev Op.shl (w : Nat) (flags : LLVM.NoWrapFlags := { }) : SLLVM.Op := arith <| Op.shl w flags
@[match_pattern] nonrec abbrev Op.lshr (w : Nat) (flag : LLVM.ExactFlag := { }) : SLLVM.Op := arith <| Op.lshr w flag
@[match_pattern] nonrec abbrev Op.ashr (w : Nat) (flag : LLVM.ExactFlag := { }) : SLLVM.Op := arith <| Op.ashr w flag
@[match_pattern] nonrec abbrev Op.add (w : Nat) (flags : LLVM.NoWrapFlags := { }) : SLLVM.Op := arith <| Op.add w flags
@[match_pattern] nonrec abbrev Op.mul (w : Nat) (flags : LLVM.NoWrapFlags := { }) : SLLVM.Op := arith <| Op.mul w flags
@[match_pattern] nonrec abbrev Op.sub (w : Nat) (flags : LLVM.NoWrapFlags := { }) : SLLVM.Op := arith <| Op.sub w flags

@[match_pattern] nonrec abbrev Op.icmp (c : LLVM.IntPred) (w : Nat) : SLLVM.Op := arith <| Op.icmp c w
@[match_pattern] nonrec abbrev Op.const (w : Nat) (val : Int) : SLLVM.Op := arith <| Op.const w val
@[match_pattern] nonrec abbrev Op.select (w : Nat) : SLLVM.Op := arith <| Op.select w

@[match_pattern] nonrec abbrev Op.udiv (w : Nat) (flag : LLVM.ExactFlag := { }) : SLLVM.Op := arith <| Op.udiv w flag
@[match_pattern] nonrec abbrev Op.sdiv (w : Nat) (flag : LLVM.ExactFlag := { }) : SLLVM.Op := arith <| Op.sdiv w flag
@[match_pattern] nonrec abbrev Op.urem : Nat → SLLVM.Op := arith ∘ Op.urem
@[match_pattern] nonrec abbrev Op.srem : Nat → SLLVM.Op := arith ∘ Op.srem

@[match_pattern] abbrev Ty.ptr : SLLVM.Ty := .ptr

def MemorySSAState := PoisonOr MemoryState

structure PoisonOr (α : Type) where
  ofOption :: toOption : Option α
  deriving DecidableEq

structure MemoryState where
  mem : Std.HashMap BlockId Block
  deriving Inhabited

structure GlobalState where
  alloc : AllocState
  mem : MemoryState

structure BlockId where
  id : Nat
  deriving DecidableEq, Hashable, Inhabited

inductive Block where
   
  | dead
   
  | live (b : LiveBlock)

structure LiveBlock where
  (length : Nat)
  (bytes : BitVec (8 * length))

def Ptr : Type := PoisonOr Pointer

infixr:50 "::ₕ" => HVector.cons

def test24_before := [llvm|
{
^0(%arg53 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.urem %arg53, %0 : i32
  %3 = llvm.icmp "ne" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def test2_before := [llvm|
{
^0(%arg2 : i49):
  %0 = llvm.mlir.constant(4096 : i49) : i49
  %1 = llvm.mlir.constant(11 : i49) : i49
  %2 = llvm.shl %0, %1 : i49
  %3 = llvm.urem %arg2, %2 : i49
  "llvm.return"(%3) : (i49) -> ()
}
]

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

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

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

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

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

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

partial def getBitVecTypeWidths (t : Expr) (out : Std.HashSet Expr) :
    MetaM (Std.HashSet Expr) := do
  if let some w ← getBitVecTypeWidth? t then do
    
    if let some 1 ← getNatValue? w then
      return out
    return out.insert w
  else
    let (_f, args) := t.getAppFnArgs
    let mut out := out
    for arg in args do
      out ← getBitVecTypeWidths arg out
    return out

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

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

def shl_lshr_pow2_const_negative_overflow1_before := [llvm|
{
^0(%arg70 : i16):
  %0 = llvm.mlir.constant(4096 : i16) : i16
  %1 = llvm.mlir.constant(6 : i16) : i16
  %2 = llvm.mlir.constant(8 : i16) : i16
  %3 = llvm.shl %0, %arg70 : i16
  %4 = llvm.lshr %3, %1 : i16
  %5 = llvm.and %4, %2 : i16
  "llvm.return"(%5) : (i16) -> ()
}
]

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

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

def 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 Sexpr.ofString (s : String) : Sexpr :=
  Sexpr.atom (format s)

@[simp_denote]
def sext_riscv_i1_to_i16 := [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) -> (i16)
    llvm.return %res : i16
  }]

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

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

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

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

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

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

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

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

def pr33078_2_before := [llvm|
{
^0(%arg4 : i8):
  %0 = llvm.mlir.constant(4 : i16) : i16
  %1 = llvm.sext %arg4 : i8 to i16
  %2 = llvm.lshr %1, %0 : i16
  %3 = llvm.trunc %2 : i16 to i12
  "llvm.return"(%3) : (i12) -> ()
}
]

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

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

def test6_before := [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 %2, %1 : i32
  %4 = llvm.add %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def zext_sext_add_icmp_sgt_minus2_before := [llvm|
{
^0(%arg90 : i1, %arg91 : i1):
  %0 = llvm.mlir.constant(-2 : i8) : i8
  %1 = llvm.zext %arg90 : i1 to i8
  %2 = llvm.sext %arg91 : i1 to i8
  %3 = llvm.add %1, %2 : i8
  %4 = llvm.icmp "sgt" %3, %0 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def test25_before := [llvm|
{
^0(%arg51 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.srem %arg51, %0 : i32
  %3 = llvm.icmp "ne" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

def testExampleMergeAdd : Stream (BitVec 8) :=
  exampleMergeAdd.denote (Ctxt.Valuation.ofHVector (.cons input3 <| .cons input2 <| .cons input1 <| .nil))

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

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

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

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

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

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

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

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

instance : ToString IntPred where
  toString
  | .eq => "eq"
  | .ne => "ne"
  | .ugt => "ugt"
  | .uge => "uge"
  | .ult => "ult"
  | .ule => "ule"
  | .sgt => "sgt"
  | .sge => "sge"
  | .slt => "slt"
  | .sle => "sle"

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

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

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

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

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

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

def sel_zext_before := [llvm|
{
^0(%arg89 : i32, %arg90 : i1):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = "llvm.select"(%arg90, %arg89, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.zext %1 : i32 to i64
  "llvm.return"(%2) : (i64) -> ()
}
]

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

def eq_3210_before := [llvm|
{
^0(%arg126 : i32, %arg127 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.mlir.constant(24 : i32) : i32
  %3 = llvm.trunc %arg126 : i32 to i8
  %4 = llvm.lshr %arg126, %0 : i32
  %5 = llvm.trunc %4 : i32 to i8
  %6 = llvm.lshr %arg126, %1 : i32
  %7 = llvm.trunc %6 : i32 to i8
  %8 = llvm.lshr %arg126, %2 : i32
  %9 = llvm.trunc %8 : i32 to i8
  %10 = llvm.trunc %arg127 : i32 to i8
  %11 = llvm.lshr %arg127, %0 : i32
  %12 = llvm.trunc %11 : i32 to i8
  %13 = llvm.lshr %arg127, %1 : i32
  %14 = llvm.trunc %13 : i32 to i8
  %15 = llvm.lshr %arg127, %2 : i32
  %16 = llvm.trunc %15 : i32 to i8
  %17 = llvm.icmp "eq" %3, %10 : i8
  %18 = llvm.icmp "eq" %5, %12 : i8
  %19 = llvm.icmp "eq" %7, %14 : i8
  %20 = llvm.icmp "eq" %9, %16 : i8
  %21 = llvm.and %17, %18 : i1
  %22 = llvm.and %19, %21 : i1
  %23 = llvm.and %20, %22 : i1
  "llvm.return"(%23) : (i1) -> ()
}
]

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

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

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

def extract (x : BitVec w) (lb : Nat) : BitVec (w - lb) :=
  BitVec.truncate (w - lb) (BitVec.ushiftRight x lb)

@[simp_llvm]
def shl? {n} (op1 : BitVec n) (op2 : BitVec n) : IntW n :=
  if op2 >= n
  then .poison
  else .value (op1 <<< op2)

One in Init.Prelude

def not_signbit_trunc_before := [llvm|
{
^0(%arg16 : i16):
  %0 = llvm.mlir.constant(-1 : i16) : i16
  %1 = llvm.mlir.constant(15 : i16) : i16
  %2 = llvm.xor %arg16, %0 : i16
  %3 = llvm.lshr %2, %1 : i16
  %4 = llvm.trunc %3 : i16 to i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

instance instHandshakeTyDenote : TyDenote Ty where
toType := fun
| Ty.stream ty2 => CIRCTStream.Stream (TyDenote.toType ty2)
| Ty.stream2 ty2 => CIRCTStream.Stream (TyDenote.toType ty2) × CIRCTStream.Stream (TyDenote.toType ty2)
| Ty.stream2token ty2 => CIRCTStream.Stream (TyDenote.toType ty2) × CIRCTStream.Stream (TyDenote.toType (Ty2.bitvec 1))

def_denote for Handshake where
| .fst _ => fun s => [s.fst]ₕ
| .snd _ => fun s => [s.snd]ₕ
| .branch _ => fun s c => [HandshakeOp.branch s c]ₕ
| .merge _ => fun s₁ s₂ => [HandshakeOp.merge s₁ s₂]ₕ
| .altMerge _ => fun s₁ s₂ => [HandshakeOp.altMerge s₁ s₂]ₕ
| .fork _ => fun s => [HandshakeOp.fork s]ₕ
| .controlMerge _ => fun s₁ s₂ => [HandshakeOp.controlMerge s₁ s₂]ₕ
| .join _ => fun s₁ s₂ => [HandshakeOp.join s₁ s₂]ₕ
| .mux _ => fun s₁ s₂ c => [HandshakeOp.mux s₁ s₂ c]ₕ
| .sink _ => fun s => [HandshakeOp.sink s]ₕ
| .sync _ => fun s₁ s₂ => [HandshakeOp.sync s₁ s₂]ₕ
| .supp _ => fun s₁ s₂ => [HandshakeOp.supp s₁ s₂]ₕ
| .not => fun s₁ => [HandshakeOp.not s₁]ₕ

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

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

def fold_and_zext_icmp_after := [llvm|
{
^0(%arg97 : i64, %arg98 : i64, %arg99 : i64):
  %0 = llvm.icmp "sgt" %arg97, %arg98 : i64
  %1 = llvm.icmp "slt" %arg97, %arg99 : i64
  %2 = llvm.and %0, %1 : i1
  %3 = llvm.zext %2 : i1 to i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def WidthExpr.castLe {wcard : Nat} (e : WidthExpr wcard) (hw : wcard ≤ wcard') : WidthExpr wcard' :=
  match e with
  | .const n => .const n
  | .var v => .var ⟨v, by admit /- proof elided -/
  ⟩
  | .min v w => .min (v.castLe hw) (w.castLe hw)
  | .max v w => .max (v.castLe hw) (w.castLe hw)
  | .addK v k => .addK (v.castLe hw) k
  | .kadd k v => .kadd k (v.castLe hw)

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

def narrow_zext_sub_before := [llvm|
{
^0(%arg38 : i16, %arg39 : i32):
  %0 = llvm.zext %arg38 : i16 to i32
  %1 = llvm.sub %0, %arg39 : i32
  %2 = llvm.trunc %1 : i32 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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

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

def test6_before := [llvm|
{
^0(%arg302 : i1):
  %0 = llvm.and %arg302, %arg302 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

private def natParams : Nat → Type
  | 0 => Unit
  | 1 => Nat
  | n + 1 => Nat × (natParams n)

def t1_flags_nuw_second_before := [llvm|
{
^0(%arg36 : i8, %arg37 : i8, %arg38 : i8):
  %0 = llvm.sub %arg36, %arg37 : i8
  %1 = llvm.sub %0, %arg38 overflow<nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

def test_lshr__exact_is_unsafe_after := [llvm|
{
^0(%arg56 : i32, %arg57 : i64):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(15 : i32) : i32
  %2 = llvm.lshr %arg56, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.zext nneg %3 : i32 to i64
  %5 = llvm.ashr %arg57, %4 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

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

instance {φ} : DialectSignature (MetaLLVM φ) where
  signature op := ⟨op.sig, [], [op.outTy], .pure⟩

Lean.DefinitionSafety.safe in Lean.Declaration

def add_2_after := [llvm|
{
^0(%arg121 : i8, %arg122 : i1, %arg123 : i8, %arg124 : i8):
  %0 = llvm.mlir.constant(-124 : i8) : i8
  %1 = llvm.xor %arg124, %0 : i8
  %2 = "llvm.select"(%arg122, %arg123, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.sub %2, %arg121 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

def different_size_zext_zext_slt_after := [llvm|
{
^0(%arg18 : i7, %arg19 : i4):
  %0 = llvm.zext %arg19 : i4 to i7
  %1 = llvm.icmp "ult" %arg18, %0 : i7
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

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

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

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

def add_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := add_lo_negone_llvm_i64
  rhs := add_lo_negone_riscv_i64

inductive SLLVMTy where
  | arith (t : LLVM.Ty)
  | ptr
  | mem
  deriving DecidableEq, Lean.ToExpr

NFA.step in Mathlib.Computability.NFA

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 unaryTwo {o : Nat} : BitVec o := 3

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

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

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

def or_and_not_not_commute1_after := [llvm|
{
^0(%arg422 : i32, %arg423 : i32, %arg424 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg423 : i32
  %3 = llvm.and %arg424, %2 : i32
  %4 = llvm.or %3, %arg422 : i32
  %5 = llvm.xor %4, %1 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

def sub_to_xor_and_commuted_after := [llvm|
{
^0(%arg5 : i32, %arg6 : i32):
  %0 = llvm.xor %arg6, %arg5 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def PR24763_before := [llvm|
{
^0(%arg50 : i8):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.sext %arg50 : i8 to i32
  %2 = llvm.lshr %1, %0 : i32
  %3 = llvm.trunc %2 : i32 to i16
  "llvm.return"(%3) : (i16) -> ()
}
]

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

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

@[simp_denote]
def sub_riscv_32 := [LV| {
  ^entry (%x: i32, %y: i32 ):
    %0 = "builtin.unrealized_conversion_cast"(%x) : (i32) -> (!i64)
    %1 = "builtin.unrealized_conversion_cast"(%y) : (i32) -> (!i64)
    %2 = sub %0, %1 : !i64
    %3 = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i32)
    llvm.return %3 : i32
  }]

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

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

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

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

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

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

def add_or_sub_comb_i64_commuted4_after := [llvm|
{
^0(%arg13 : i64):
  %0 = llvm.mlir.constant(-1) : i64
  %1 = llvm.mul %arg13, %arg13 : i64
  %2 = llvm.add %1, %0 : i64
  %3 = llvm.and %2, %1 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

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

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

Lean.mkOptionalNode in Init.Meta.Defs

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

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

def zext_nneg_sext_sgt_before := [llvm|
{
^0(%arg62 : i8, %arg63 : i8):
  %0 = llvm.zext nneg %arg62 : i8 to i32
  %1 = llvm.sext %arg63 : i8 to i32
  %2 = llvm.icmp "sgt" %0, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def ashrsgt_01_01_exact_after := [llvm|
{
^0(%arg100 : i4):
  %0 = llvm.mlir.constant(2 : i4) : i4
  %1 = llvm.icmp "sgt" %arg100, %0 : i4
  "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 Region.WellTyped : UnTyped.Region Op VarName → RegionType Ty → Prop
  | ⟨entry, _⟩ => BasicBlock.WellTyped entry

def sub_from_constant_commute_before := [llvm|
{
^0(%arg4 : i5, %arg5 : i5):
  %0 = llvm.mlir.constant(10 : i5) : i5
  %1 = llvm.mul %arg5, %arg5 : i5
  %2 = llvm.sub %0, %arg4 overflow<nsw> : i5
  %3 = llvm.add %1, %2 overflow<nsw> : i5
  "llvm.return"(%3) : (i5) -> ()
}
]

def src_is_mask_and_fail_mixed_before := [llvm|
{
^0(%arg119 : i8, %arg120 : i8, %arg121 : i8):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(-8 : i8) : i8
  %2 = llvm.mlir.constant(-1 : i8) : i8
  %3 = llvm.xor %arg119, %0 : i8
  %4 = llvm.ashr %1, %arg120 : i8
  %5 = llvm.lshr %2, %arg121 : i8
  %6 = llvm.and %4, %5 : i8
  %7 = llvm.and %3, %6 : i8
  %8 = llvm.icmp "eq" %3, %7 : i8
  "llvm.return"(%8) : (i1) -> ()
}
]

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

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

ToString in Init.Data.ToString.Basic

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

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

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

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

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

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

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

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

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

def add_shl_rhs_constant_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64),Ty.llvm (.bitvec 64) ] where
  lhs := add_shl_rhs_constant_llvm
  rhs := add_shl_rhs_constant_riscv

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

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

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

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

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

def no_shift_no_xor_multiuse_or_after := [llvm|
{
^0(%arg140 : i32, %arg141 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.and %arg140, %0 : i32
  %2 = llvm.or %arg141, %0 : i32
  %3 = llvm.or %arg141, %1 : i32
  %4 = llvm.mul %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

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

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

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 shrink_and_after := [llvm|
{
^0(%arg9 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.and %arg9, %0 : i64
  %2 = llvm.trunc %1 overflow<nsw,nuw> : i64 to i31
  "llvm.return"(%2) : (i31) -> ()
}
]

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

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

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

Prod in Init.Prelude

@[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 p_after := [llvm|
{
^0(%arg73 : i32, %arg74 : i32, %arg75 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg75, %0 : i32
  %2 = llvm.or %arg73, %1 : i32
  %3 = llvm.or %arg74, %arg75 : i32
  %4 = llvm.and %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def neg_or_lshr_i32_before := [llvm|
{
^0(%arg7 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(31 : i32) : i32
  %2 = llvm.sub %0, %arg7 : i32
  %3 = llvm.or %2, %arg7 : i32
  %4 = llvm.lshr %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def shl (x y : BitVec w) : BitVec w :=
  x <<< y

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

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

unseal String.splitOnAux in

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

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

def binop_left_to_zero: List (Σ Γ, LLVMPeepholeRewriteRefine 64 Γ) :=
  [⟨_, binop_left_to_zero_shl⟩,
  ⟨_, binop_left_to_zero_lshr⟩,
  ⟨_, binop_left_to_zero_ashr⟩,
  ⟨_, binop_left_to_zero_sdiv⟩,
  ⟨_, binop_left_to_zero_udiv⟩,
  ⟨_, binop_left_to_zero_srem⟩,
  ⟨_, binop_left_to_zero_urem⟩,
  ⟨_, binop_left_to_zero_mul⟩]

@[simp_denote]
def trunc_llvm_64_to_1_nuw := [LV| {
  ^entry (%lhs: i64):
    %0 = llvm.trunc %lhs overflow<nuw> : i64 to i1
    llvm.return %0 : i1
  }]

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

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

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

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

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

def or_xor_xor_normal_variant1_after := [llvm|
{
^0(%arg17 : i1, %arg18 : i1):
  %0 = llvm.xor %arg17, %arg18 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

def ripple_nsw4_before := [llvm|
{
^0(%arg17 : i16, %arg18 : i16):
  %0 = llvm.mlir.constant(-21845 : i16) : i16
  %1 = llvm.mlir.constant(21843 : i16) : i16
  %2 = llvm.and %arg18, %0 : i16
  %3 = llvm.and %arg17, %1 : i16
  %4 = llvm.add %3, %2 : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

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

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

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

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

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

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

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

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 sdiv_exact_ne_1_before := [llvm|
{
^0(%arg12 : i8, %arg13 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sdiv exact %arg12, %arg13 : i8
  %2 = llvm.icmp "eq" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def lshr_and_after := [llvm|
{
^0(%arg59 : i64, %arg60 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.mlir.constant(12) : i64
  %2 = llvm.mlir.constant(7) : i64
  %3 = llvm.srem %arg60, %0 : i64
  %4 = llvm.lshr %arg59, %1 : i64
  %5 = llvm.lshr %3, %2 : i64
  %6 = llvm.and %4, %5 : i64
  "llvm.return"(%6) : (i64) -> ()
}
]

def shl_sub_lshr_reverse_nsw_on_op1_before := [llvm|
{
^0(%arg130 : i32, %arg131 : i32, %arg132 : i32):
  %0 = llvm.shl %arg130, %arg131 overflow<nsw,nuw> : i32
  %1 = llvm.sub %arg132, %0 overflow<nuw> : i32
  %2 = llvm.lshr exact %1, %arg131 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def p_constmask_before := [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.xor %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def lhs :=
[poly q, n, hq| {
^bb0(%A : ! R, %B : ! R):
  %v1 = "poly.add" (%A,%B) : (! R, ! R) -> (! R)
  "return" (%v1) : (! R) -> ()
}]

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

def or_or_and_complex_before := [llvm|
{
^0(%arg82 : i64):
  %0 = llvm.mlir.constant(8) : i64
  %1 = llvm.mlir.constant(71776119061217280) : i64
  %2 = llvm.mlir.constant(-72057594037927936) : i64
  %3 = llvm.mlir.constant(1095216660480) : i64
  %4 = llvm.mlir.constant(280375465082880) : i64
  %5 = llvm.mlir.constant(16711680) : i64
  %6 = llvm.mlir.constant(4278190080) : i64
  %7 = llvm.mlir.constant(255) : i64
  %8 = llvm.mlir.constant(65280) : i64
  %9 = llvm.lshr %arg82, %0 : i64
  %10 = llvm.and %9, %1 : i64
  %11 = llvm.shl %arg82, %0 : i64
  %12 = llvm.and %11, %2 : i64
  %13 = llvm.or %10, %12 : i64
  %14 = llvm.and %9, %3 : i64
  %15 = llvm.or %13, %14 : i64
  %16 = llvm.and %11, %4 : i64
  %17 = llvm.or %15, %16 : i64
  %18 = llvm.and %9, %5 : i64
  %19 = llvm.or %17, %18 : i64
  %20 = llvm.and %11, %6 : i64
  %21 = llvm.or %19, %20 : i64
  %22 = llvm.and %9, %7 : i64
  %23 = llvm.or %21, %22 : i64
  %24 = llvm.and %11, %8 : i64
  %25 = llvm.or %23, %24 : i64
  "llvm.return"(%25) : (i64) -> ()
}
]

def IsTotal (m : Mapping Γ Δ) : Prop :=
  ∀ {t} v, ⟨t, v⟩ ∈ m

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

partial def consumeCloseBracket(c: Bracket)
  (startPos: String.Pos.Raw)
  (i: String.Pos.Raw)
  (brackets: List Bracket)
  (ctx: ParserContext)
  (s: ParserState): ParserState := Id.run do
    match brackets with
    | b::bs =>
      if b == c
      then
        if bs == []
        then
          let parser_fn := Lean.Parser.mkNodeToken `balanced_brackets startPos
          parser_fn ctx (s.setPos (ctx.next i)) 
        else balancedBracketsFnAux startPos (ctx.next i) bs ctx s
      else s.mkError $ "| found Opened `" ++ toString b ++ "` expected to close at `" ++
      toString c ++ "`"
    | _ => s.mkError $ "| found Closed `" ++ toString c ++ "`, but have no opened brackets on stack"

def src_is_mask_shl_lshr_fail_not_allones_before := [llvm|
{
^0(%arg100 : i8, %arg101 : i8, %arg102 : i1):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(-2 : i8) : i8
  %2 = llvm.mlir.constant(-1 : i8) : i8
  %3 = llvm.mlir.constant(0 : i8) : i8
  %4 = llvm.xor %arg100, %0 : i8
  %5 = llvm.shl %1, %arg101 : i8
  %6 = llvm.lshr %5, %arg101 : i8
  %7 = llvm.xor %6, %2 : i8
  %8 = llvm.and %4, %7 : i8
  %9 = llvm.icmp "ne" %3, %8 : i8
  "llvm.return"(%9) : (i1) -> ()
}
]

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

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

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

@[simp]
def decLe (e e' : EffectKind) : Decidable (le e e') :=
  match e with
  | .pure => match e' with
    | .pure => isTrue (by admit /- proof elided -/
    )
    | .impure => isTrue (by admit /- proof elided -/
    )
  | .impure => match e' with
    | .pure => isFalse (by admit /- proof elided -/
    )
    | .impure => isTrue (by admit /- proof elided -/
    )

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

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

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

def udiv_mul_shl_nuw_after := [llvm|
{
^0(%arg166 : i5, %arg167 : i5, %arg168 : i5):
  %0 = llvm.lshr %arg167, %arg168 : i5
  "llvm.return"(%0) : (i5) -> ()
}
]

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

def add_constant_equal_with_the_top_bit_of_demandedbits_pass_after := [llvm|
{
^0(%arg9 : i32):
  %0 = llvm.mlir.constant(24 : i32) : i32
  %1 = llvm.mlir.constant(16 : i32) : i32
  %2 = llvm.and %arg9, %0 : i32
  %3 = llvm.xor %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

structure BVExprWrapper where
  width : Nat
  bvExpr: GenBVExpr width

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

def llvm_const_lower_riscv_li11 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM11, rhs:= liRiscv11,
   correct := by admit /- proof elided -/

@[simp_denote]
def intro_example_correct_lhs := [LV| {
  ^entry (%arg0: i64):
    %c = llvm.mlir.constant (4) : i64
    %1 = llvm.mul %arg0, %c : i64
    llvm.return %1 : i64
  }]

def t2_after := [llvm|
{
^0(%arg202 : i8, %arg203 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.shl %0, %arg203 : i8
  %2 = llvm.add %1, %arg202 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

def src_is_mask_const_sge_after := [llvm|
{
^0(%arg45 : i8):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(32 : i8) : i8
  %2 = llvm.xor %arg45, %0 : i8
  %3 = llvm.icmp "slt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def main3e_like_after := [llvm|
{
^0(%arg149 : i32, %arg150 : i32, %arg151 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.or %arg150, %arg151 : i32
  %2 = llvm.and %arg149, %1 : i32
  %3 = llvm.icmp "ne" %2, %0 : i32
  %4 = llvm.zext %3 : i1 to i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

def sub_1_after := [llvm|
{
^0(%arg113 : i8, %arg114 : i1, %arg115 : i8, %arg116 : i8):
  %0 = llvm.mlir.constant(-124 : i8) : i8
  %1 = llvm.xor %arg116, %0 : i8
  %2 = "llvm.select"(%arg114, %arg115, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.add %2, %arg113 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

instance instRefinement : HRefinement (Id α) (Id β) := inst

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

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

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

def 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 lt_unsigned_to_large_unsigned_after := [llvm|
{
^0(%arg47 : i8):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

elab "#fpgeneralize" expr:term : command =>

def urem_constant_dividend_select_of_constants_divisor_0_arm_after := [llvm|
{
^0(%arg23 : i1):
  %0 = llvm.mlir.constant(6 : i32) : i32
  "llvm.return"(%0) : (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 lshr_shl_pow2_const_case1_after := [llvm|
{
^0(%arg60 : i16):
  %0 = llvm.mlir.constant(7 : i16) : i16
  %1 = llvm.mlir.constant(8 : i16) : i16
  %2 = llvm.mlir.constant(0 : i16) : i16
  %3 = llvm.icmp "eq" %arg60, %0 : i16
  %4 = "llvm.select"(%3, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i16, i16) -> i16
  "llvm.return"(%4) : (i16) -> ()
}
]

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

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

abbrev WidthExpr := Expr

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

def ugt_3_before := [llvm|
{
^0(%arg47 : i32):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.trunc %arg47 : i32 to i8
  %2 = llvm.icmp "ugt" %1, %0 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

Std.HashMap.map in Std.Data.HashMap.AdditionalOperations

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

def add {Γ : Ctxt _} (e₁ e₂ : Var Γ .nat) : Expr Γ .nat :=
  Expr.mk
    (op := .add)
    (ty_eq := rfl)
    (eff_le := EffectKind.pure_le _)
    (args := .cons e₁ <| .cons e₂ .nil)
    (regArgs := .nil)

@[simp_denote]
def slti_riscv :=
  [LV| {
    ^entry (%arg: i16):
    %a =  "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64)
    %0 = slli %a, 48 : !i64
    %1 = srai %0, 48 : !i64
    %2 = slti %1, 2 : !i64
    %3 =  "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16)
    llvm.return %3 :i16
  }]

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

def add_2_after := [llvm|
{
^0(%arg121 : i8, %arg122 : i1, %arg123 : i8, %arg124 : i8):
  %0 = llvm.mlir.constant(-124 : i8) : i8
  %1 = llvm.xor %arg124, %0 : i8
  %2 = "llvm.select"(%arg122, %arg123, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.sub %2, %arg121 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

def no_shift_no_xor_multiuse_or_after := [llvm|
{
^0(%arg140 : i32, %arg141 : i32):
  %0 = llvm.mlir.constant(4096 : i32) : i32
  %1 = llvm.and %arg140, %0 : i32
  %2 = llvm.or %arg141, %0 : i32
  %3 = llvm.or %arg141, %1 : i32
  %4 = llvm.mul %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def add (op1 : FpExpr w) (op2 : FpExpr w) : FpExpr w :=
  FpExpr.bin op1 FpBinOp.add op2

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

def t0_before := [llvm|
{
^0(%arg17 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.lshr %arg17, %0 : i8
  %2 = llvm.trunc %1 : i8 to i4
  %3 = llvm.sext %2 : i4 to i16
  "llvm.return"(%3) : (i16) -> ()
}
]

instance : MLIR.AST.TransformExpr (DC) 0 where
  mkExpr := mkExpr

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

def uge_umin2_before := [llvm|
{
^0(%arg50 : i32, %arg51 : i32):
  %0 = llvm.icmp "ult" %arg51, %arg50 : i32
  %1 = "llvm.select"(%0, %arg51, %arg50) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "uge" %1, %arg50 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

def Term.IntEnv.empty : Term.IntEnv 0 :=
  fun x => x.elim0

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

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

def lshrult_03_07_after := [llvm|
{
^0(%arg328 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (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 sub_from_constant_of_sub_from_constant_after := [llvm|
{
^0(%arg170 : i8):
  %0 = llvm.mlir.constant(-31 : i8) : i8
  %1 = llvm.add %arg170, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

def sext_after := [llvm|
{
^0(%arg9 : i16):
  %0 = llvm.sext %arg9 : i16 to i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

abbrev MetaLLVM (φ : Nat) : Dialect where
  Op := MOp φ
  Ty := MTy φ

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

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

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

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

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

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

BitVec.sdiv in Init.Data.BitVec.Basic

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

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

instLTBitVec in Init.Prelude

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

def 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 xor_of_icmps_commute_after := [llvm|
{
^0(%arg30 : i64):
  %0 = llvm.mlir.constant(1) : i64
  %1 = llvm.icmp "sgt" %arg30, %0 : i64
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def test_or2_before := [llvm|
{
^0(%arg32 : i32, %arg33 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.and %arg33, %0 : i32
  %3 = llvm.icmp "sle" %arg32, %1 : i32
  %4 = llvm.icmp "sgt" %arg32, %2 : i32
  %5 = llvm.or %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

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

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

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

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

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

inductive Expr : (Γ : Ctxt d.Ty) → (eff : EffectKind) → (ty : List d.Ty) → Type where
  | mk {Γ} {ty} (op : d.Op)
    (ty_eq : ty = DialectSignature.returnTypes op)
    (eff_le : DialectSignature.effectKind op ≤ eff)
    (args : HVector (Var Γ) <| DialectSignature.sig op)
     
    (regArgs : HVector (fun t : Ctxt d.Ty × List d.Ty => Com t.1 .impure t.2)
      (DialectSignature.regSig op)) : Expr Γ eff ty

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

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

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

Mul in Init.Prelude

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

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

@[simp_denote]
def shl_llvm_8 := [LV| {
  ^entry (%x: i8, %y: i8):
    %1 = llvm.shl %x, %y : i8
    llvm.return %1 : i8
  }]

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

def ult_to_sgt_before := [llvm|
{
^0(%arg24 : i8, %arg25 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.xor %arg24, %0 : i8
  %2 = llvm.xor %arg25, %0 : i8
  %3 = llvm.icmp "ult" %1, %2 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def lt_signed_to_large_negative_after := [llvm|
{
^0(%arg51 : i8):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (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 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 t7_before := [llvm|
{
^0(%arg6 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sub %0, %arg6 overflow<nsw> : i8
  %2 = llvm.icmp "ule" %1, %arg6 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def Term.denote (w : Nat) (t : Term) (vars : List (BitVec w)) : BitVec w :=
  match t with
  | ofNat n => BitVec.ofNat w n
  | var n => vars.getD n default
  | zero => 0#w
  | negOne => -1#w
  | one  => 1#w
  | and a b => (a.denote w vars) &&& (b.denote w vars)
  | or a b => (a.denote w vars) ||| (b.denote w vars)
  | xor a b => (a.denote w vars) ^^^ (b.denote w vars)
  | not a => ~~~ (a.denote w vars)
  | add a b => (a.denote w vars) + (b.denote w vars)
  | sub a b => (a.denote w vars) - (b.denote w vars)
  | neg a => - (a.denote w vars)
  
  
  | shiftL a n => (a.denote w vars) <<< n

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

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

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

def not_xor_to_or_not1_before := [llvm|
{
^0(%arg39 : i3, %arg40 : i3, %arg41 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg40, %arg41 : i3
  %2 = llvm.and %arg39, %arg41 : i3
  %3 = llvm.xor %2, %1 : i3
  %4 = llvm.xor %3, %0 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

instance (n : Nat) : CoeHead (ParsedArgs Γ (some n)) (ParsedArgs Γ) where
  coe args := .ofList args.toList

def scalar_i8_shl_ult_const_2_before := [llvm|
{
^0(%arg18 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.mlir.constant(64 : i8) : i8
  %2 = llvm.shl %arg18, %0 : i8
  %3 = llvm.icmp "ult" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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

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

def n2_after := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(-2 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.shl %0, %arg1 overflow<nsw> : i8
  %4 = llvm.xor %3, %1 : i8
  %5 = llvm.and %arg0, %4 : i8
  %6 = llvm.icmp "ne" %5, %2 : i8
  "llvm.return"(%6) : (i1) -> ()
}
]

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

def EnvFin.getLsb {w : Nat} (env : EnvFin (w + 1) n) : EnvFin 1 n := fun n => BitVec.ofBool <| (env n)[0]

def src_is_mask_const_sge_after := [llvm|
{
^0(%arg45 : i8):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(32 : i8) : i8
  %2 = llvm.xor %arg45, %0 : i8
  %3 = llvm.icmp "slt" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def foo1_or_after := [llvm|
{
^0(%arg154 : i32, %arg155 : i32, %arg156 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.shl %0, %arg155 overflow<nuw> : i32
  %2 = llvm.shl %0, %arg156 overflow<nuw> : i32
  %3 = llvm.or %1, %2 : i32
  %4 = llvm.and %arg154, %3 : i32
  %5 = llvm.icmp "eq" %4, %3 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

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

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

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 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 add_negative_low_bound_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := add_negative_low_bound_accept_llvm
  rhs := add_negative_low_bound_accept_riscv

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 egLhs : Com SimpleReg ⟨[int]⟩ .pure [int] :=
  Com.var (cst 0) <|
  Com.var (add ⟨0, rfl⟩ ⟨1, rfl⟩) <| 
  Com.var (iterate (k := 0) (⟨0, rfl⟩) (
      Com.letPure (cst 0) <|
      Com.letPure (add ⟨0, rfl⟩ ⟨1, rfl⟩) 
      <| Com.rets [⟨0, rfl⟩]ₕ
  )) <|
  Com.rets [⟨0, rfl⟩]ₕ

def constant_macro_proof (w : Nat) :
    constant_macro w ⊑ constant_macro w :=

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

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

def BasicBlock (ty : RegionType Ty) : Type :=
  { block : UnTyped.BasicBlock Op VarName // BasicBlock.WellTyped block ty }

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

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

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

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

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

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

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

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

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

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

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

def or_or_and_pat2_before := [llvm|
{
^0(%arg70 : i8, %arg71 : i8, %arg72 : i8, %arg73 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.udiv %0, %arg72 : i8
  %2 = llvm.and %arg70, %arg71 : i8
  %3 = llvm.and %arg73, %arg70 : i8
  %4 = llvm.or %1, %3 : i8
  %5 = llvm.or %4, %2 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

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

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

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

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

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

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

def neg_not_signbit3_after := [llvm|
{
^0(%arg3 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.ashr %arg3, %0 : i8
  %3 = llvm.zext %2 : i8 to i32
  %4 = llvm.sub %1, %3 overflow<nsw> : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def llvm_add_lower_riscv_noflags_16 : LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16)] where
  lhs:= add_llvm_no_flags_16
  rhs:= add_riscv_16

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

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

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

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

def BasicBlock.substitute (σ : Substitution) : BasicBlock Op T → BasicBlock Op T
  | ⟨label, args, program⟩ =>
      let σ' := args.foldl Substitution.removeMappingFor σ
      ⟨label, args, program.substitute σ'⟩

def flip_add_of_shift_neg_after := [llvm|
{
^0(%arg12 : i8, %arg13 : i8, %arg14 : i8):
  %0 = llvm.shl %arg12, %arg13 : i8
  %1 = llvm.sub %arg14, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

def zext_sext_ugt_known_nonneg_before := [llvm|
{
^0(%arg22 : i8, %arg23 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.and %arg22, %0 : i8
  %2 = llvm.zext %1 : i8 to i32
  %3 = llvm.sext %arg23 : i8 to i32
  %4 = llvm.icmp "ugt" %2, %3 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

def test_zext4_after := [llvm|
{
^0(%arg35 : i1, %arg36 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg36, %0 : i1
  %2 = "llvm.select"(%1, %0, %arg35) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = llvm.zext %2 : i1 to i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def Expr.regArgs {Γ ts} (e : Expr d Γ eff ts) :
    Regions d (DialectSignature.regSig e.op) :=
  Expr.casesOn e (fun _ _ _ _ regArgs => regArgs)

def verifyAIG {α : Type} [DecidableEq α] [Hashable α] (x : Entrypoint α) (cert : String) : Bool :=
  let y := (Entrypoint.relabelNat x)
  let z := AIG.toCNF y
  Std.Tactic.BVDecide.Reflect.verifyCert z cert

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

def add_hi_one_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := add_hi_one_lo_negone_llvm_i64
  rhs := add_hi_one_lo_negone_riscv_i64

List in Init.Prelude

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

def ashr_mul_sign_bits_after := [llvm|
{
^0(%arg101 : i8, %arg102 : i8):
  %0 = llvm.mlir.constant(3 : i16) : i16
  %1 = llvm.sext %arg101 : i8 to i16
  %2 = llvm.sext %arg102 : i8 to i16
  %3 = llvm.mul %1, %2 overflow<nsw> : i16
  %4 = llvm.ashr %3, %0 : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

def lshr_neg_slt_zero_before := [llvm|
{
^0(%arg52 : i8):
  %0 = llvm.mlir.constant(-17 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.lshr %0, %arg52 : i8
  %3 = llvm.icmp "slt" %2, %1 : i8
  "llvm.return"(%3) : (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 PR42691_8_logical_after := [llvm|
{
^0(%arg328 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-2147483635 : i32) : i32
  %2 = llvm.add %arg328, %0 : i32
  %3 = llvm.icmp "ult" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def invert_icmp_before := [llvm|
{
^0(%arg151 : i32, %arg152 : i32):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.icmp "sle" %arg151, %arg152 : i32
  %2 = llvm.xor %1, %0 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def test_shift_and_cmp_changed1_before := [llvm|
{
^0(%arg6 : i8, %arg7 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.mlir.constant(8 : i8) : i8
  %2 = llvm.mlir.constant(5 : i8) : i8
  %3 = llvm.mlir.constant(1 : i8) : i8
  %4 = llvm.and %arg6, %0 : i8
  %5 = llvm.and %arg7, %1 : i8
  %6 = llvm.or %5, %4 : i8
  %7 = llvm.shl %6, %2 : i8
  %8 = llvm.ashr %7, %2 : i8
  %9 = llvm.icmp "slt" %8, %3 : i8
  "llvm.return"(%9) : (i1) -> ()
}
]

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

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

def select2_after := [llvm|
{
^0(%arg9 : i1, %arg10 : i8, %arg11 : i8, %arg12 : i8):
  %0 = llvm.add %arg10, %arg11 : i8
  %1 = "llvm.select"(%arg9, %arg12, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

def test_and2_before := [llvm|
{
^0(%arg48 : i32, %arg49 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.and %arg49, %0 : i32
  %3 = llvm.icmp "sgt" %arg48, %1 : i32
  %4 = llvm.icmp "sle" %arg48, %2 : i32
  %5 = llvm.and %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

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

def test27_before := [llvm|
{
^0(%arg178 : i32, %arg179 : i32, %arg180 : i32):
  %0 = llvm.xor %arg180, %arg178 : i32
  %1 = llvm.xor %arg180, %arg179 : i32
  %2 = llvm.icmp "eq" %0, %1 : i32
  %3 = llvm.zext %2 : i1 to i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def negative_and_odd_after := [llvm|
{
^0(%arg76 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.lshr %arg76, %0 : i32
  %2 = llvm.and %1, %arg76 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

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

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

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

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

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

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

def t0_after := [llvm|
{
^0(%arg42 : i32, %arg43 : i32, %arg44 : i32, %arg45 : i32):
  %0 = llvm.icmp "ne" %arg42, %arg43 : i32
  %1 = llvm.icmp "ne" %arg44, %arg45 : i32
  %2 = llvm.or %1, %0 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

def one_inst_com_proof (w : Nat) :
    one_inst_com w ⊑ one_inst_com w :=

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

@[simp]
def NFA'.autWidth_spec : (autWidth wp n).accepts = { bv | wp.sat bv.w n } :=

def multiuse3_after := [llvm|
{
^0(%arg9 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(48 : i32) : i32
  %2 = llvm.mlir.constant(6 : i32) : i32
  %3 = llvm.mlir.constant(8064 : i32) : i32
  %4 = llvm.mlir.constant(15 : i32) : i32
  %5 = llvm.lshr %arg9, %0 : i32
  %6 = llvm.and %5, %1 : i32
  %7 = llvm.shl %arg9, %2 : i32
  %8 = llvm.and %7, %3 : i32
  %9 = llvm.lshr %arg9, %0 : i32
  %10 = llvm.and %9, %4 : i32
  %11 = llvm.or disjoint %6, %10 : i32
  %12 = llvm.or disjoint %11, %8 : i32
  "llvm.return"(%12) : (i32) -> ()
}
]

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

def NFA'.autMsbSet : NFA' 1 := ⟨_, NFA.autMsbSet⟩

@[simp_denote]
def sub_riscv_self_ex := [LV| {
  ^entry (%x: i64):
    %0 = "builtin.unrealized_conversion_cast"(%x) : (i64) -> (!i64)
    %2 = sub %0, %0 : !i64
    %4 = sltu %0, %0 : !i64
    %3 = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i64)
    llvm.return %3 : i64
  }]

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

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

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

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

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

def worklistRun_init_post (inits : Array S) (final : S → Bool)
    (map : Std.HashMap S State) (m : RawCNFA A) :=
  (forall sa, sa ∈ map ↔ sa ∈ inits) ∧
  (∀ s a, m.tr s a = ∅) ∧
  ∀ sa s, map[sa]? = some s → (s ∈ m.initials) ∧ (s ∈ m.finals ↔ final sa)

def shl_and_and_after := [llvm|
{
^0(%arg172 : i8, %arg173 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.mlir.constant(80 : i8) : i8
  %2 = llvm.and %arg173, %arg172 : i8
  %3 = llvm.shl %2, %0 : i8
  %4 = llvm.and %3, %1 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

def neg_not_signbit2_before := [llvm|
{
^0(%arg4 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.lshr %arg4, %0 : i8
  %3 = llvm.zext %2 : i8 to i32
  %4 = llvm.sub %1, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

def or_not_xor_common_op_commute7_before := [llvm|
{
^0(%arg86 : i8, %arg87 : i8, %arg88 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.sub %0, %arg88 : i8
  %3 = llvm.xor %arg86, %1 : i8
  %4 = llvm.xor %arg87, %arg86 : i8
  %5 = llvm.or %2, %3 : i8
  %6 = llvm.or %5, %4 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

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

def xor_or_xor_common_op_commute3_after := [llvm|
{
^0(%arg74 : i32, %arg75 : i32, %arg76 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg74, %0 : i32
  %2 = llvm.and %arg75, %1 : i32
  %3 = llvm.xor %2, %arg76 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def masked_or_allones_after := [llvm|
{
^0(%arg127 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.and %arg127, %0 : i32
  %2 = llvm.icmp "eq" %1, %0 : i32
  "llvm.return"(%2) : (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 trunc_shl_ashr_infloop_before := [llvm|
{
^0(%arg36 : i64):
  %0 = llvm.mlir.constant(3) : i64
  %1 = llvm.mlir.constant(2) : i64
  %2 = llvm.ashr %arg36, %0 : i64
  %3 = llvm.shl %2, %1 : i64
  %4 = llvm.trunc %3 : i64 to i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def original_sdiv_srem := [LV| {
  ^entry (%a: i64, %b: i64):
    %0= llvm.sdiv exact %a, %b : i64
    %1 = llvm.srem %a, %b : i64
    llvm.return %1 : i64
  }]

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

elab "[poly" qi:term "," ni:term "," hq:term " | " reg:mlir_region "]" : term => do
  let q : Q(Nat) ← elabTermEnsuringTypeQ qi q(Nat)
  let n : Q(Nat) ← elabTermEnsuringTypeQ ni q(Nat)
  let _factval ← elabTermEnsuringTypeQ hq q(Fact ($q > 1))

  SSA.elabIntoCom reg q(FHE $q $n)

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

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

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

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

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

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

def n2_after := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(-2 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.shl %0, %arg1 overflow<nsw> : i8
  %4 = llvm.xor %3, %1 : i8
  %5 = llvm.and %arg0, %4 : i8
  %6 = llvm.icmp "eq" %5, %2 : i8
  "llvm.return"(%6) : (i1) -> ()
}
]

def t2_after := [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 %arg25, %0 : i8
  %3 = llvm.xor %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

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

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

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

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

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

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

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

def test14a_before := [llvm|
{
^0(%arg25 : i79):
  %0 = llvm.mlir.constant(4 : i79) : i79
  %1 = llvm.mlir.constant(1234 : i79) : i79
  %2 = llvm.shl %arg25, %0 : i79
  %3 = llvm.and %2, %1 : i79
  %4 = llvm.lshr %3, %0 : i79
  "llvm.return"(%4) : (i79) -> ()
}
]

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

Ideal in Mathlib.RingTheory.Ideal.Defs

Matrix.map in Mathlib.LinearAlgebra.Matrix.Defs

BEq in Init.Prelude

def filterCandidatePredicates  (bvLogicalExpr: BoolExpr GenBVPred) (preconditionCandidates visited: Std.HashSet (BoolExpr GenBVPred))
                                                    : GeneralizerStateM ParsedBVExpr GenBVPred (List (BoolExpr GenBVPred)) :=
  withTraceNode `Generalize (fun _ => return "Filtered out invalid expression sketches") do
    let state ← get
    let widthId := state.widthId
    let bitwidth := state.processingWidth

    let mut res : List (BoolExpr GenBVPred) := []
    
    
    
    
    let widthConstraint : BoolExpr GenBVPred :=
      BoolExpr.literal (GenBVPred.bin (GenBVExpr.var widthId) BVBinPred.eq (GenBVExpr.const (BitVec.ofNat bitwidth bitwidth)))

    let mut numInvocations := 0
    let mut currentCandidates := preconditionCandidates.filter (λ cand => !visited.contains cand)
    logInfo m! "Originally processing {currentCandidates.size} candidates"

    
    while !currentCandidates.isEmpty do
      let expressionsConstraints : BoolExpr GenBVPred := bigOr (currentCandidates.toList)
      let bvLogicalExpr := bvLogicalExpr
      let expr := BoolExpr.gate Gate.and (BoolExpr.gate .and expressionsConstraints widthConstraint) (BoolExpr.not bvLogicalExpr)

      let mut newCandidates : Std.HashSet (BoolExpr GenBVPred) := Std.HashSet.emptyWithCapacity
      numInvocations := numInvocations + 1
      match (← solve expr) with
      | none => break
      | some assignment =>
          newCandidates ← withTraceNode `Generalize (fun _ => return "Evaluated expressions for filtering") do
            let mut res : Std.HashSet (BoolExpr GenBVPred) := Std.HashSet.emptyWithCapacity
            for candidate in currentCandidates do
              let widthSubstitutedCandidate := subsituteGenLogicalExpr candidate (bvExprToSubstitutionValue (Std.HashMap.ofList [(widthId, wrap (GenBVExpr.const (BitVec.ofNat bitwidth bitwidth)))]))
              if !(evalBoolExpr widthSubstitutedCandidate (fun v => v.eval assignment)) then
                res := res.insert candidate
            pure res

      currentCandidates := newCandidates

    logInfo m! "Invoked the solver {numInvocations} times for {preconditionCandidates.size} potential candidates."
    res := currentCandidates.toList
    pure res

def Reflect.Map.append (w : Nat) (s : BitVec w)  (m : List (BitVec w)) : List (BitVec w) := m.append [s]

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

@[tactic bvAutomataFragmentCheckReflected]
def evalBvAutomataFragmentCheckReflected : Tactic := fun
| `(tactic| bv_automata_fragment_reflect) => do
  let g ← getMainGoal
  g.withContext do
    let ws ← findExprBitwidths (← g.getType)
    let ws := ws.toArray
    if h0: ws.size = 0 then throwError m!"found no bitvector in the target: {indentD (← g.getType)}"
    else if hgt: ws.size > 1 then
      let (w1, wExample1) := ws[0]
      let (w2, wExample2) := ws[1]
      let mExample := m!"{w1} → {wExample1}; {w2} → {wExample2}"
      throwError m!"found multiple bitvector widths in the target: {indentD mExample}"
    else
      
      let (w, wExample) := ws[0]

      
      let g ← revertBvHyps g

      
      
      let .some g ← NNF.runNNFSimpSet g
        | trace[Bits.Frontend] m!"Converting to negation normal form automatically closed goal."
          return ()
      trace[Bits.Frontend] m!"goal after NNF: {indentD g}"

      let .some g ← Simplifications.runPreprocessing g
        | trace[Bits.Frontend] m!"Preprocessing automatically closed goal."
          return ()
      trace[Bits.Frontend] m!"goal after preprocessing: {indentD g}"
      
      let result ← reflectPredicateAux ∅ (← g.getType) w
      let bvToIxMapVal ← result.exprToIx.toExpr w

      let target := (mkAppN (mkConst ``Predicate.denote) #[result.e.quote, w, bvToIxMapVal])
      let g ← g.replaceTargetDefEq target
      trace[Bits.Frontend] m!"goal after reflection: {indentD g}"
      return ()
| _  => throwUnsupportedSyntax

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

def icmp_eq_and_pow2_minus1_shl1_negative2_before := [llvm|
{
^0(%arg49 : i32):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.mlir.constant(15 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.shl %0, %arg49 : 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 ne_umin2_before := [llvm|
{
^0(%arg42 : i32, %arg43 : i32):
  %0 = llvm.icmp "ult" %arg43, %arg42 : i32
  %1 = "llvm.select"(%0, %arg43, %arg42) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "ne" %1, %arg42 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def StreamWithoutNones.hasStream (x : StreamWithoutNones α) : Set (Stream α):=
  { y | x = Quotient.mk _ y }

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

def rhs : Com ScfArith ⟨[  .int,  .int,   .nat,   t]⟩ .impure t :=
   
  Com.letPure (axpy ⟨1, by admit /- proof elided -/
  ⟩ ⟨2, by admit /- proof elided -/
  ⟩ ⟨0, by admit /- proof elided -/
  ⟩) <|
   
  Com.letPure (neg ⟨2, rfl⟩) <|
  Com.var (for_ (t := t)
                        ⟨  2, rfl⟩
                        ⟨  3, rfl⟩
                        ⟨  4, rfl⟩
                        ⟨  5, rfl⟩  rgn) <|
  Com.rets [⟨0, rfl⟩]ₕ

def bools_logical_commute0_and2_after := [llvm|
{
^0(%arg102 : i1, %arg103 : i1, %arg104 : i1):
  %0 = "llvm.select"(%arg104, %arg103, %arg102) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def HVector.vars {l : List d.Ty} (T : HVector (Var Γ) l) : VarSet Γ :=
  T.foldl (fun _ s a => insert ⟨_, a⟩ s) ∅

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

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

List.toFinsupp in Mathlib.Data.List.ToFinsupp

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

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

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

Lean.trace in Lean.Util.Trace

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

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

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

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

def OrShlShl : 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.shl %x, %z : i64
      %1 = llvm.shl %y, %z : i64
      %2 = llvm.or %0, %1 : i64
      llvm.return %2 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64, %y: i64, %z: i64):
      %0 = llvm.or %x, %y : i64
      %1 = llvm.shl %0, %z : i64
      llvm.return %1 : i64
  }]

def uge_to_slt_before := [llvm|
{
^0(%arg15 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.mlir.constant(15 : i8) : i8
  %2 = llvm.xor %arg15, %0 : i8
  %3 = llvm.icmp "uge" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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 xor_1_before := [llvm|
{
^0(%arg137 : i8, %arg138 : i1, %arg139 : i8, %arg140 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(123 : i8) : i8
  %2 = llvm.xor %arg139, %0 : i8
  %3 = llvm.xor %arg140, %1 : i8
  %4 = "llvm.select"(%arg138, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %5 = llvm.xor %4, %arg137 : i8
  %6 = llvm.xor %5, %0 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

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

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

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

def sub_from_constant_commute_before := [llvm|
{
^0(%arg4 : i5, %arg5 : i5):
  %0 = llvm.mlir.constant(10 : i5) : i5
  %1 = llvm.mul %arg5, %arg5 : i5
  %2 = llvm.sub %0, %arg4 overflow<nsw> : i5
  %3 = llvm.add %1, %2 overflow<nsw> : i5
  "llvm.return"(%3) : (i5) -> ()
}
]

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

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

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

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

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

def alive_AndOrXor_2627_tgt  (w : Nat)  :=
[llvm( w )| {
^bb0(%a : _, %c : _, %b : _):
  %v1 = llvm.mlir.constant -1
  %v2 = llvm.xor %a, %v1
  %v3 = llvm.and %v2, %b
  %v4 = llvm.xor %a, %c
  %v5 = llvm.or %a, %b
  %v6 = llvm.xor %v3, %c
  llvm.return %v6
}]

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

def xor_1_after := [llvm|
{
^0(%arg137 : i8, %arg138 : i1, %arg139 : i8, %arg140 : i8):
  %0 = llvm.mlir.constant(-124 : i8) : i8
  %1 = llvm.xor %arg140, %0 : i8
  %2 = "llvm.select"(%arg138, %arg139, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.xor %2, %arg137 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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 and_not_or_before := [llvm|
{
^0(%arg481 : i32, %arg482 : i32, %arg483 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg481, %arg482 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.or %2, %arg483 : i32
  %4 = llvm.and %arg481, %arg483 : i32
  %5 = llvm.xor %4, %0 : i32
  %6 = llvm.or %5, %arg482 : i32
  %7 = llvm.and %3, %6 : i32
  "llvm.return"(%7) : (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 uge_to_sgt_after := [llvm|
{
^0(%arg19 : i8):
  %0 = llvm.mlir.constant(-114 : i8) : i8
  %1 = llvm.icmp "sgt" %arg19, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

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

def attrDict0 : AttrDict 0 := [mlir_attr_dict| {}]

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

def mul_of_pow2_commute_before := [llvm|
{
^0(%arg81 : i32, %arg82 : i32):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.mlir.constant(255 : i32) : i32
  %2 = llvm.mlir.constant(1020 : i32) : i32
  %3 = llvm.and %arg81, %0 : i32
  %4 = llvm.and %arg82, %1 : i32
  %5 = llvm.mul %4, %3 : i32
  %6 = llvm.icmp "ugt" %5, %2 : i32
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

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

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

def anyext_trunc_fold_zext_32 : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := [LV| {
    ^entry (%x: i32):
      %0 = llvm.zext %x: i32 to i64
      %1 = llvm.trunc %0: i64 to i32
      llvm.return %1 : i32
  }]
  rhs := [LV| {
    ^entry (%x: i32):
      llvm.return %x : i32
  }]

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

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

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

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

def test_ne_11_and_15_add_10_before := [llvm|
{
^0(%arg0 : i8):
  %0 = llvm.mlir.constant(10 : i8) : i8
  %1 = llvm.mlir.constant(15 : i8) : i8
  %2 = llvm.mlir.constant(11 : i8) : i8
  %3 = llvm.add %arg0, %0 : i8
  %4 = llvm.and %3, %1 : i8
  %5 = llvm.icmp "ne" %4, %2 : i8
  "llvm.return"(%5) : (i1) -> ()
}
]

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

def same_signbit_wrong_type_before := [llvm|
{
^0(%arg34 : i8, %arg35 : i32):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.lshr %arg34, %0 : i8
  %3 = llvm.icmp "sgt" %arg35, %1 : i32
  %4 = llvm.zext %3 : i1 to i8
  %5 = llvm.icmp "ne" %2, %4 : i8
  "llvm.return"(%5) : (i1) -> ()
}
]

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

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

def or_and_or_pat7_before := [llvm|
{
^0(%arg14 : i8, %arg15 : i8, %arg16 : i8, %arg17 : i8):
  %0 = llvm.and %arg14, %arg15 : i8
  %1 = llvm.and %arg15, %arg17 : i8
  %2 = llvm.or %1, %arg16 : i8
  %3 = llvm.or %0, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

@[elab_as_elim, induction_eliminator]
def Expr.recOn {motive : Expr Op Γ ty → Sort u}
    (mk : ∀ varName op ty_eq args regions, motive (Expr.mk varName op ty_eq args regions)) :
    ∀ e, motive e
  | ⟨⟨varName, op, args, regions⟩, h⟩ =>
      have := by admit /- proof elided -/

def low_bitmask_ult_before := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(31 : i8) : i8
  %1 = llvm.add %arg11, %0 : i8
  %2 = llvm.and %1, %0 : i8
  %3 = llvm.icmp "ult" %2, %arg11 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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

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

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

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

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 sge_smin1_before := [llvm|
{
^0(%arg79 : i32, %arg80 : i32):
  %0 = llvm.icmp "slt" %arg79, %arg80 : i32
  %1 = "llvm.select"(%0, %arg79, %arg80) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %2 = llvm.icmp "sge" %1, %arg79 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

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

def test4_after := [llvm|
{
^0(%arg226 : i32, %arg227 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg226, %0 : i32
  %2 = llvm.or %arg227, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def foo1_and_signbit_lshr_before := [llvm|
{
^0(%arg136 : i32, %arg137 : i32, %arg138 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.shl %0, %arg137 : i32
  %4 = llvm.lshr %1, %arg138 : i32
  %5 = llvm.and %3, %arg136 : i32
  %6 = llvm.icmp "eq" %5, %2 : i32
  %7 = llvm.and %4, %arg136 : i32
  %8 = llvm.icmp "eq" %7, %2 : i32
  %9 = llvm.or %6, %8 : i1
  "llvm.return"(%9) : (i1) -> ()
}
]

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

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

def src_is_notmask_sext_before := [llvm|
{
^0(%arg75 : i16, %arg76 : i8):
  %0 = llvm.mlir.constant(123 : i16) : i16
  %1 = llvm.mlir.constant(-8 : i8) : i8
  %2 = llvm.mlir.constant(-1 : i16) : i16
  %3 = llvm.xor %arg75, %0 : i16
  %4 = llvm.shl %1, %arg76 : i8
  %5 = llvm.sext %4 : i8 to i16
  %6 = llvm.xor %5, %2 : i16
  %7 = llvm.and %6, %3 : i16
  %8 = llvm.icmp "ule" %3, %7 : i16
  "llvm.return"(%8) : (i1) -> ()
}
]

def srem_common_dividend_defined_cond_after := [llvm|
{
^0(%arg21 : i1, %arg22 : i5, %arg23 : i5, %arg24 : i5):
  %0 = "llvm.select"(%arg21, %arg24, %arg23) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i5, i5) -> i5
  %1 = llvm.srem %arg22, %0 : i5
  "llvm.return"(%1) : (i5) -> ()
}
]

WithBot in Mathlib.Order.TypeTags
</all_available_defs>

<all_available_lemmas>
List.get_eq_getElem in Init.Data.List.Lemmas
List.length_cons in Init.Data.List.Basic

@[simp] theorem map_cons {A B : α → Type u} {as : List α} {f : (a : α) → A a → B a}
    {x : A a} {xs : HVector A as} :
    map f (cons x xs) = cons (f _ x) (map f xs)

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

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

theorem icmp_select_var_select_proof : icmp_select_var_select_before ⊑ icmp_select_var_select_after

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

theorem trunc_nuw_xor_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ zeroExtend 8 (truncate 1 (x_1 ^^^ x)) ≠ x_1 ^^^ x) → truncate 1 (x_1 ^^^ x) = ofBool (x_1 != x)

@[bv_multi_width_normalize] theorem ofBool_and_ofBool (x y : Bool) :
  (BitVec.ofBool x &&& BitVec.ofBool y) = BitVec.ofBool (x && y)

theorem test42_thm.extracted_1._1 : ∀ (x : BitVec 32), zeroExtend 32 (truncate 8 x) = x &&& 255#32

theorem two_signed_truncation_checks_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.ult (add e (const? 32 512)) (const? 32 1024))
      (icmp IntPred.ult (add e (const? 32 128)) (const? 32 256)) ⊑
    icmp IntPred.ult (add e (const? 32 128)) (const? 32 256)

theorem widget_proof : widget_before ⊑ widget_after

theorem shl_lshr_pow2_const_negative_overflow2_proof : shl_lshr_pow2_const_negative_overflow2_before ⊑ shl_lshr_pow2_const_negative_overflow2_after

theorem test1_proof : test1_before ⊑ test1_after

theorem e_765 :
     - 7 * t + 7 *  ~~~(z &&&  ~~~t) + 1 * z - 1 * (z &&& t) = 7 *  ~~~(z ||| t) + 1 * (z &&&  ~~~t)

theorem t0_proof : t0_before ⊑ t0_after

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

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

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

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

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

theorem and_add_bool_to_select_multi_use_proof : and_add_bool_to_select_multi_use_before ⊑ and_add_bool_to_select_multi_use_after

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

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

theorem fold_nested_logic_zext_icmp_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 64),
  zeroExtend 8 (ofBool (x_2 <ₛ x_3)) &&& zeroExtend 8 (ofBool (x_3 <ₛ x_1)) ||

theorem sext_multiuse_thm.extracted_1._2 : ∀ (x : BitVec 4),
  ¬(True ∧ (zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8))).saddOverflow (BitVec.ofInt 7 (-8)) = true ∨
        (zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) + BitVec.ofInt 7 (-8) == 0 ||
              7 != 1 && zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) == intMin 7 &&
                zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) + BitVec.ofInt 7 (-8) == -1) =
            true ∨
          (x ^^^ BitVec.ofInt 4 (-8) == 0 ||
              4 != 1 &&
                  truncate 4
                      ((zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8))).sdiv
                        (zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) + BitVec.ofInt 7 (-8))) ==
                    intMin 4 &&
                x ^^^ BitVec.ofInt 4 (-8) == -1) =
            true) →
    ¬((signExtend 7 x == 0 || 7 != 1 && zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) == intMin 7 && signExtend 7 x == -1) =
            true ∨
          (x ^^^ BitVec.ofInt 4 (-8) == 0 ||
              4 != 1 && truncate 4 ((zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8))).sdiv (signExtend 7 x)) == intMin 4 &&
                x ^^^ BitVec.ofInt 4 (-8) == -1) =
            true) →
      (truncate 4
              ((zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8))).sdiv
                (zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8)) + BitVec.ofInt 7 (-8)))).sdiv
          (x ^^^ BitVec.ofInt 4 (-8)) =
        (truncate 4 ((zeroExtend 7 (x ^^^ BitVec.ofInt 4 (-8))).sdiv (signExtend 7 x))).sdiv
          (x ^^^ BitVec.ofInt 4 (-8))

theorem lshrult_01_07_exact_proof : lshrult_01_07_exact_before ⊑ lshrult_01_07_exact_after

theorem e_466 :
     - 1 *  ~~~(x &&& y) - 1 * (x |||  ~~~y) + 1 *  ~~~(x &&&  ~~~y) + 3 * (x ^^^ y) + 7 *  ~~~(x &&&  ~~~x) - 7 *  ~~~(x ||| y) - 10 *  ~~~(x |||  ~~~y) - 9 * (x &&&  ~~~y) - 7 * (x &&& y) =  - 1 *  ~~~y

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

theorem test13_proof : test13_before ⊑ test13_after

theorem trunc_shl_33_i32_i64_thm.extracted_1._1 : ∀ (x : BitVec 64), ¬33#64 ≥ ↑64 → truncate 32 (x <<< 33#64) = 0#32

theorem e_181 :
     - 11 *  ~~~y + 2 * (x ^^^ y) + 4 *  ~~~(x &&& y) - 1 *  ~~~x - 5 *  ~~~(x |||  ~~~y) + 5 * (x &&&  ~~~y) =  - 8 *  ~~~(x ||| y)

theorem ashr_xor_thm (e e_1 : IntW 32) :
  ashr (LLVM.xor (LLVM.srem e_1 (const? 32 42)) (ashr e (const? 32 5))) (const? 32 7) ⊑
    LLVM.xor (ashr e (const? 32 12)) (ashr (LLVM.srem e_1 (const? 32 42)) (const? 32 7))

theorem test86_thm (e : IntW 16) : trunc 16 (ashr (sext 32 e) (const? 32 4)) ⊑ ashr e (const? 16 4)

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

theorem src5_proof : src5_before ⊑ src5_after

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

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

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

theorem foo_thm.extracted_1._2 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ¬ofBool (x_2 <ₛ x_1) = 1#1 →
    x_3 &&& signExtend 32 (ofBool (x_2 <ₛ x_1)) ||

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

theorem andn_or_cmp_4_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == x) = 1#1 → ofBool (x_1 != x) = 1#1 → True → False

@[simp] theorem Valuation.append_inj_left {V V' : Γ.Valuation} {W : Δ.Valuation} :
    (V ++ W) = (V' ++ W) ↔ V = V'

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

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

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

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

theorem lshr_or_proof : lshr_or_before ⊑ lshr_or_after

theorem e_2401 :
     - 1 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) - 5 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) + 5 *  ~~~(d ||| f) - 5 * (e |||  ~~~(d |||  ~~~f)) + 1 * (e ||| f) - 2 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) - 5 * ((d &&& e) ^^^ (e |||  ~~~f)) - 2 * f - 11 * (f ^^^  ~~~(d |||  ~~~e)) + 4 *  ~~~(d ^^^ ( ~~~e ||| f)) + 1 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) + 1 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 3 * ( ~~~d ||| (e &&& f)) + 3 * (e ^^^ (d ||| (e &&& f))) + 3 * (f ^^^  ~~~(d &&&  ~~~e)) + 11 * (e ^^^ (d ||| (e ^^^ f))) + 1 *  ~~~(d ||| ( ~~~e &&& f)) - 1 * (e ||| (d &&&  ~~~f)) - 1 * (d ^^^ ( ~~~e ||| f)) - 1 * (f ^^^ (d ||| ( ~~~e ||| f))) - 1 * (f &&& (d ||| e)) - 3 * (f |||  ~~~(d ^^^ e)) + 1 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 1 * (f ^^^ (d ||| (e ||| f))) + 4 * (d ^^^ f) + 1 * (e |||  ~~~(d ^^^ f)) - 6 * (f &&& (d ^^^ e)) - 5 *  ~~~(d |||  ~~~e) + 2 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 5 * (e &&&  ~~~(d ^^^ f)) - 1 * (e ^^^ (d ||| f)) + 1 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) + 2 * (f ||| (d &&& e)) + 2 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) + 7 *  ~~~( ~~~d &&& (e ||| f)) + 5 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) - 7 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 6 * ((d &&& e) |||  ~~~(e ||| f)) + 1 * (f ^^^  ~~~(d ||| (e &&& f))) - 1 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 1 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 11 * (f ^^^ (d ||| e)) - 2 * (e ^^^  ~~~(d ||| f)) + 2 *  ~~~(d &&&  ~~~f) - 2 * (e ^^^ ( ~~~d &&& (e ^^^ f))) + 2 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 1 * (f ^^^  ~~~(d &&& (e ||| f))) - 5 *  ~~~(d &&& (e ||| f)) - 6 * (d ^^^ (e ^^^ f)) - 3 * ( ~~~d ||| (e ^^^ f)) - 3 * e + 5 * (d |||  ~~~e) - 3 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * ((d &&& e) |||  ~~~(e |||  ~~~f)) - 7 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 6 *  ~~~(d ^^^ (e ^^^ f)) + 4 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 2 * (e ^^^  ~~~(d |||  ~~~f)) - 1 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 2 * (f ^^^ (d &&&  ~~~e)) - 2 * (f ^^^ ( ~~~d ||| (e ||| f))) - 7 * ( ~~~e ||| (d ^^^ f)) - 1 * ((d ||| e) &&& (d ^^^ (e ^^^ f))) + 11 * ((d |||  ~~~e) &&& (e ^^^ f)) + 1 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) + 13 *  ~~~(d ||| (e ||| f)) + 18 *  ~~~(d ||| ( ~~~e ||| f)) - 4 *  ~~~( ~~~d ||| (e ||| f)) + 10 * ( ~~~d &&& ( ~~~e &&& f)) + 29 * ( ~~~d &&& (e &&& f)) - 7 * (d &&& ( ~~~e &&& f)) + 23 * (d &&& (e &&& f)) = 5 * (e ^^^  ~~~(d &&& f)) - 7 *  ~~~( ~~~d ||| ( ~~~e ||| f))

theorem t1_flags_nuw_only_proof : t1_flags_nuw_only_before ⊑ t1_flags_nuw_only_after

theorem t2_commutative_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ofBool (x_1 <ᵤ x_1 - x) = ofBool (x_1 <ᵤ x)

theorem select_icmp_ne_0_and_8_and_not_1073741824_proof : select_icmp_ne_0_and_8_and_not_1073741824_before ⊑ select_icmp_ne_0_and_8_and_not_1073741824_after

theorem t10_c1_c2_thm (e : IntW 8) : sub (sub e (const? 8 42)) (const? 8 24) ⊑ add e (const? 8 (-66))

theorem alive_AddSub_1156  (w : Nat)   : alive_AddSub_1156_src w  ⊑ alive_AddSub_1156_tgt w

theorem udiv_mul_shl_nuw_thm (e e_1 e_2 : IntW 5) :
  LLVM.udiv (mul e_2 e_1 { «nsw» := false, «nuw» := true }) (shl e_2 e { «nsw» := false, «nuw» := true }) ⊑
    lshr e_1 e

theorem mul_constant_nuw_eq_proof : mul_constant_nuw_eq_before ⊑ mul_constant_nuw_eq_after

private lemma BitVec.sle_iff_slt_or_eq {w : ℕ} (bv1 bv2 : BitVec w):
    (bv1.sle bv2) = true ↔ (bv1.slt bv2) = true ∨ bv1 = bv2

theorem not_or_or_and_not_and_and_commute2_thm.extracted_1._2 : ∀ (x x_1 x_2 : 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 →
      (x_2 ^^^ -1#32 ||| x_1 ||| (42#32).sdiv x) &&& ((42#32).sdiv x &&& (x_1 &&& x_2) ^^^ -1#32) =
        (42#32).sdiv x ^^^ x_1 ||

theorem test_or4_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 2147483647#32 <ₛ x) = 1#1 → ofBool (x <ₛ 0#32) = ofBool (x_1 &&& 2147483647#32 <ᵤ x)

theorem test11_thm (e e_1 : IntW 32) :
  mul (LLVM.and (add (shl e_1 (const? 32 8)) e) (const? 32 128)) (shl e_1 (const? 32 8)) ⊑
    mul (LLVM.and e (const? 32 128)) (shl e_1 (const? 32 8))

theorem select_icmp_ne_0_and_32_xor_4096_proof : select_icmp_ne_0_and_32_xor_4096_before ⊑ select_icmp_ne_0_and_32_xor_4096_after

theorem test10_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(True ∧ (x &&& 3#8 &&& 4#8 != 0) = true) → x &&& 3#8 ^^^ 4#8 = x &&& 3#8 ||

theorem shl_add_add_fail_thm (e e_1 : IntW 8) :
  add (lshr e_1 (const? 8 2)) (add (lshr e (const? 8 2)) (const? 8 48)) ⊑
    add (lshr e_1 (const? 8 2)) (add (lshr e (const? 8 2)) (const? 8 48) { «nsw» := true, «nuw» := true })
      { «nsw» := false, «nuw» := true }

theorem arbitrary_mask_sub_i8_thm (e : IntW 8) :
  sub (const? 8 11) (LLVM.and e (const? 8 10)) ⊑
    sub (const? 8 11) (LLVM.and e (const? 8 10)) { «nsw» := true, «nuw» := true }

theorem select_icmp_ne_0_and_32_and_not_4096_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (0#32 != x_1 &&& 32#32) = 1#1 → ofBool (x_1 &&& 32#32 == 0#32) = 1#1 → x = x &&& BitVec.ofInt 32 (-4097)

theorem e_345 :
    1 *  ~~~y + 1 * y + 11 *  ~~~(x ^^^ y) + 7 *  ~~~(x &&& y) + 2 * (x ^^^ y) - 19 *  ~~~(x ||| y) - 10 *  ~~~(x |||  ~~~y) - 10 * (x &&&  ~~~y) = 12 * (x &&& y)

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

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

theorem e_1855 :
     - 7 * ( ~~~b &&& (a ^^^ c)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 4 *  ~~~( ~~~a ||| (b &&& c)) + 2 * (c ^^^  ~~~(a ||| b)) - 3 * ((a |||  ~~~b) &&& (b ^^^ c)) - 5 *  ~~~(a ||| ( ~~~b &&& c)) + 2 * ( ~~~c ||| (a ^^^ b)) + 2 * (c ^^^ (a ||| ( ~~~b &&& c))) - 2 * (b ^^^  ~~~( ~~~a ||| (b ^^^ c))) + 2 * (c ^^^  ~~~(a |||  ~~~b)) - 6 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) + 1 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 7 *  ~~~(a &&& (b &&& c)) + 7 * (b ^^^ (a &&& (b ||| c))) + 4 *  ~~~(a &&& b) + 1 *  ~~~(a &&& c) + 7 *  ~~~( ~~~a ||| (b ^^^ c)) - 11 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) - 2 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 2 * (b ^^^  ~~~(a &&& c)) + 1 * ((a &&& b) ^^^ (a ^^^ ( ~~~b ||| c))) - 3 * (b ^^^  ~~~(a &&&  ~~~c)) + 2 * (b ^^^  ~~~(a &&& (b ||| c))) - 5 * (a ||| ( ~~~b ||| c)) + 1 *  ~~~(a ||| b) - 1 *  ~~~b - 11 * (c &&& (a ^^^ b)) - 2 * (c ||| (a ^^^ b)) + 1 *  ~~~( ~~~a &&& (b ^^^ c)) - 1 * ((a &&&  ~~~b) ||| (b ^^^ c)) + 5 * (b ^^^ (a &&& c)) + 5 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) + 5 * (c ^^^ (a ||| ( ~~~b ||| c))) + 3 * (b ^^^ ( ~~~a &&& (b ||| c))) + 3 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 1 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 1 * ((b &&& c) ||| (a &&& (b ||| c))) - 2 *  ~~~(a |||  ~~~c) + 21 *  ~~~(a ||| (b ||| c)) + 4 *  ~~~(a ||| ( ~~~b ||| c)) - 9 *  ~~~( ~~~a ||| (b ||| c)) - 19 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 16 * ( ~~~a &&& ( ~~~b &&& c)) + 1 * ( ~~~a &&& (b &&& c)) + 22 * (a &&& ( ~~~b &&& c)) = 1 * (a &&& (b &&& c)) + 11 * (c ^^^  ~~~(a ||| ( ~~~b &&& c)))

theorem test_add_nsw__all_are_safe_proof : test_add_nsw__all_are_safe_before ⊑ test_add_nsw__all_are_safe_after

theorem shl_add_thm (e e_1 : IntW 8) :
  lshr (add (shl e_1 (const? 8 2)) e) (const? 8 2) ⊑ LLVM.and (add (lshr e (const? 8 2)) e_1) (const? 8 63)

theorem shr_umax_proof : shr_umax_before ⊑ shr_umax_after

theorem test43_proof : test43_before ⊑ test43_after

theorem trunc_shl_lshr_var_proof : trunc_shl_lshr_var_before ⊑ trunc_shl_lshr_var_after

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

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

theorem pr33078_4_thm (e : IntW 3) :
  trunc 8 (lshr (sext 16 e) (const? 16 13)) ⊑
    trunc 8 (lshr (sext 16 e) (const? 16 13)) { «nsw» := true, «nuw» := true }

theorem lshrult_02_04_exact_proof : lshrult_02_04_exact_before ⊑ lshrult_02_04_exact_after

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

theorem sge_and_max_proof : sge_and_max_before ⊑ sge_and_max_after

theorem sle_swap_or_min_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x ≤ₛ x_1) ||

theorem zext_nneg_signbit_extract_thm (e : IntW 32) : lshr (zext 64 e { «nneg» := true }) (const? 64 31) ⊑ const? 64 0

theorem basic_com_add_thm (e e_1 : IntW 8) :
  LLVM.xor (add e_1 (LLVM.xor e (const? 8 (-1)))) (const? 8 (-1)) ⊑ sub e e_1

lemma Ctxt.delete_cons {vs : DeleteRange (Γ.cons t)} {h : vs.start ≠ 0} :
    (Γ.cons t |>.delete vs) = (Γ.delete (vs.pred h) |>.cons t)

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

theorem shl_sub_proof : shl_sub_before ⊑ shl_sub_after

theorem trunc_shl_31_i32_i64_thm (e : IntW 64) : trunc 32 (shl e (const? 64 31)) ⊑ shl (trunc 32 e) (const? 32 31)

theorem zext_sext_add_icmp_eq_1_proof : zext_sext_add_icmp_eq_1_before ⊑ zext_sext_add_icmp_eq_1_after

theorem xor_and_thm.extracted_1._5 : ∀ (x x_1 : BitVec 32) (x_2 : BitVec 1),
  x_2 = 1#1 → x_2 ^^^ 1#1 = 1#1 → ofBool (x_1 <ᵤ x) ^^^ 1#1 = 1#1

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

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

@[simp] theorem args_changeVars : (e.changeVars f).args = e.args.map f

theorem lshrult_02_10_proof : lshrult_02_10_before ⊑ lshrult_02_10_after

theorem sgt_x_impliesF_eq_smin_todo_proof : sgt_x_impliesF_eq_smin_todo_before ⊑ sgt_x_impliesF_eq_smin_todo_after

theorem e_1981 :
     - 1 * ( ~~~(a &&& b) &&& (b ^^^ c)) + 3 * (a &&& c) - 11 * ( ~~~b ||| (a ^^^ c)) + 5 *  ~~~(a |||  ~~~c) - 1 * (b ||| (a &&&  ~~~c)) - 1 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) + 2 *  ~~~(a &&& (b ||| c)) - 3 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 1 * (a ||| (b ||| c)) - 1 * (c |||  ~~~(a |||  ~~~b)) - 11 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) + 3 * (a ^^^ (b &&& c)) + 7 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 11 * ((a ||| b) &&&  ~~~(b ^^^ c)) + 1 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) - 6 * (c ^^^ (a ||| b)) - 7 * (a |||  ~~~c) - 5 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 1 *  ~~~(a &&& c) + 1 * ( ~~~a &&& ( ~~~b ||| c)) - 2 *  ~~~(a ||| c) + 7 * (b ^^^ ( ~~~a ||| (b ||| c))) - 3 *  ~~~( ~~~a &&& ( ~~~b ||| c)) - 5 * (c &&&  ~~~(a &&&  ~~~b)) + 1 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) - 1 * ((b &&& c) ||| (a &&& (b ||| c))) - 6 * (c ^^^ (a &&& b)) - 2 * (c |||  ~~~(a ||| b)) + 1 * (b |||  ~~~(a ^^^ c)) - 3 * ((a &&& b) ^^^ (b ||| c)) + 1 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) - 1 * (a ||| b) + 5 * (c ^^^  ~~~(a &&& (b &&& c))) - 11 * (b &&& c) + 2 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) + 3 * (a ^^^ (b ^^^ c)) + 5 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) + 3 * c - 7 * ((a |||  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) + 1 * (b ^^^ (a ||| (b ||| c))) + 4 *  ~~~(a &&&  ~~~b) - 11 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) - 5 * (b ^^^  ~~~(a ||| (b ^^^ c))) + 3 * ( ~~~a ||| (b ||| c)) - 7 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) + 7 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 2 * ( ~~~(a |||  ~~~b) |||  ~~~(b ^^^ c)) + 1 * (a &&& b) + 4 *  ~~~(a &&&  ~~~c) + 19 *  ~~~(a ||| (b ||| c)) + 13 *  ~~~(a ||| ( ~~~b ||| c)) + 14 *  ~~~( ~~~a ||| (b ||| c)) + 57 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 9 * ( ~~~a &&& ( ~~~b &&& c)) + 3 * ( ~~~a &&& (b &&& c)) + 7 * (a &&& ( ~~~b &&& c)) - 11 * (a &&& (b &&& c)) =  - 11 * (b ^^^ (a &&& (b ||| c)))

theorem ne_rem_zero_nonuw_proof : ne_rem_zero_nonuw_before ⊑ ne_rem_zero_nonuw_after

theorem test9_logical_proof : test9_logical_before ⊑ test9_logical_after

theorem test_and1_logical_proof : test_and1_logical_before ⊑ test_and1_logical_after

theorem add_mask_ashr28_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(28#32 ≥ ↑32 ∨ 28#32 ≥ ↑32) → 28#32 ≥ ↑32 → False

theorem ashr_lshr_shift_wrong_pred2_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.sge e_2 (const? 32 0)) (lshr e_1 e) (ashr e_1 e) ⊑
    select (icmp IntPred.slt e_2 (const? 32 0)) (ashr e_1 e) (lshr e_1 e)

theorem e_1434 :
     - 1 *  ~~~z - 11 * z - 2 * (z ^^^ t) - 7 *  ~~~(z &&&  ~~~z) - 1 * (z ||| t) - 1 * t + 1 *  ~~~t + 11 *  ~~~(z &&&  ~~~t) - 5 *  ~~~(z ||| t) + 9 * (z &&& t) =  - 1 *  ~~~(z &&& t) - 19 * (z &&&  ~~~t)

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

@[bv_automata_nnf] theorem not_eq_prop (p q : Prop) : (¬(p = q)) = (p = ¬q)

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

theorem sel_sext_constants_proof : sel_sext_constants_before ⊑ sel_sext_constants_after

theorem and_nosignbit_select_ashr_proof : and_nosignbit_select_ashr_before ⊑ and_nosignbit_select_ashr_after

theorem select_sub_icmp_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.eq e_2 (const? 32 0)) (sub e_1 e_2) e ⊑
    select (icmp IntPred.eq e_2 (const? 32 0)) e_1 e

theorem eq_umax2_proof : eq_umax2_before ⊑ eq_umax2_after

theorem samesign_commute2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 &&& x <ₛ 0#32) ||

@[simp]
theorem Vars.castLe_inputs_eq_inputs {n i m : Nat} (hi : i < n) (hnm : n ≤ m) :
  (Vars.inputN inp i hi : Vars σ ι n).castLe hnm =
  Vars.inputN inp i (by omega)

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

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

theorem icmp_ne_sext_eq_otherwise_proof : icmp_ne_sext_eq_otherwise_before ⊑ icmp_ne_sext_eq_otherwise_after

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

theorem shl1_trunc_sgt4_proof : shl1_trunc_sgt4_before ⊑ shl1_trunc_sgt4_after

theorem e_1545 :
     - 2 * ( ~~~a ||| ( ~~~b &&& c)) - 2 * (a &&& (b ||| c)) + 3 *  ~~~(a ^^^ ( ~~~b &&& c)) - 5 * (c ^^^  ~~~(a &&& (b &&& c))) - 1 * (b ^^^  ~~~(a &&& (b ||| c))) - 2 * ((a &&& b) |||  ~~~(b ^^^ c)) + 7 *  ~~~(a ||| (b ||| c)) + 4 *  ~~~(a ||| ( ~~~b ||| c)) + 8 *  ~~~( ~~~a ||| (b ||| c)) + 10 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 3 * ( ~~~a &&& ( ~~~b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) + 10 * (a &&& (b &&& c)) =  - 1 * ( ~~~a &&& (b &&& c))

theorem foo1_or_signbit_lshr_without_shifting_signbit_both_sides_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (icmp IntPred.slt (shl e_2 e_1) (const? 32 0)) (icmp IntPred.slt (shl e_2 e) (const? 32 0)) ⊑
    icmp IntPred.slt (LLVM.and (shl e_2 e_1) (shl e_2 e)) (const? 32 0)

theorem trunc_sandwich_max_sum_shift2_thm (e : IntW 32) :
  lshr (trunc 12 (lshr e (const? 32 30))) (const? 12 1) ⊑
    trunc 12 (lshr e (const? 32 31)) { «nsw» := true, «nuw» := true }

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

theorem test1_thm.extracted_1._1 : ∀ (x : BitVec 61), zeroExtend 61 (truncate 41 x) = x &&& 2199023255551#61

theorem basic_preserve_nsw_thm (e e_1 : IntW 8) :
  LLVM.xor (add (LLVM.xor e_1 (const? 8 (-1))) e { «nsw» := true, «nuw» := false }) (const? 8 (-1)) ⊑
    sub e_1 e { «nsw» := true, «nuw» := false }

@[simp] theorem Lets.addComToEnd_var {lets : Lets d Γ_in eff Γ_out} {com : Com d _ eff t} :
    addComToEnd lets (Com.var e com) = addComToEnd (lets.var e) com

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

theorem test19_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 icmp_eq_mul_nsw_nonequal_proof : icmp_eq_mul_nsw_nonequal_before ⊑ icmp_eq_mul_nsw_nonequal_after

theorem bools_logical_commute0_and1_proof : bools_logical_commute0_and1_before ⊑ bools_logical_commute0_and1_after

theorem sub_to_xor_and_commuted_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  (x_1 &&& x) - (x ||| x_1) = 0#32 - (x_1 ^^^ x)

theorem t9_ashr_proof : t9_ashr_before ⊑ t9_ashr_after

theorem select_zext_or_eq_ult_add_thm (e : IntW 32) :
  select (icmp IntPred.ult (add e (const? 32 (-3))) (const? 32 2)) (const? 32 1)
      (zext 32 (icmp IntPred.eq e (const? 32 5))) ⊑
    zext 32 (icmp IntPred.ult (add e (const? 32 (-3))) (const? 32 3))

theorem p0_thm (e e_1 : IntW 8) :
  icmp IntPred.ult (LLVM.xor (shl (const? 8 (-1)) e_1) (const? 8 (-1))) e ⊑
    icmp IntPred.ne (lshr e e_1) (const? 8 0)

@[simp] lemma liftMaxSuccSucc2_cast {x : Fin m} : liftMaxSuccSucc2 n m x.castSucc = x.castLE (by omega)

theorem xor_ugt_2_thm (e e_1 e_2 : IntW 8) :
  icmp IntPred.ugt (add e_2 e_1) (LLVM.xor (add e_2 e_1) (LLVM.or (LLVM.and e (const? 8 63)) (const? 8 64))) ⊑
    icmp IntPred.ugt (add e_2 e_1)
      (LLVM.xor (add e_2 e_1) (LLVM.or (LLVM.and e (const? 8 63)) (const? 8 64) { «disjoint» := true }))

theorem tryFactorization_add_nuw_mul_nuw_mul_var_proof : tryFactorization_add_nuw_mul_nuw_mul_var_before ⊑ tryFactorization_add_nuw_mul_nuw_mul_var_after

theorem test_sext_proof : test_sext_before ⊑ test_sext_after

theorem eq_21_comm_eq2_proof : eq_21_comm_eq2_before ⊑ eq_21_comm_eq2_after

theorem not_lshr_const_thm (e : IntW 8) : LLVM.xor (lshr (const? 8 42) e) (const? 8 (-1)) ⊑ ashr (const? 8 (-43)) e

theorem test3_proof : test3_before ⊑ test3_after

theorem main7d_thm.extracted_1._2 : ∀ (x x_1 x_2 x_3 x_4 : BitVec 32),
  ¬ofBool (x_4 &&& (x_3 &&& x_2) == x_3 &&& x_2) &&& ofBool (x_4 &&& (x_1 &&& x) == x_1 &&& x) = 1#1 →
    1#32 = zeroExtend 32 (ofBool (x_4 &&& (x_3 &&& x_2 ||| x_1 &&& x) != x_3 &&& x_2 ||| x_1 &&& x))

theorem e_1720 :
    3 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 5 * (c ^^^ (a &&& ( ~~~b ||| c))) - 3 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 3 * (c ^^^  ~~~(a &&& (b &&& c))) - 1 *  ~~~( ~~~a ||| (b ^^^ c)) + 7 * (a &&&  ~~~c) + 7 * (b ^^^  ~~~(a &&& c)) - 1 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) - 1 * ((a &&& b) ^^^  ~~~(a ^^^ ( ~~~b ||| c))) - 2 * (b ^^^  ~~~(a ||| (b &&& c))) - 1 * (b ^^^  ~~~(a ||| (b ^^^ c))) - 7 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) + 4 * ((a &&& b) ||| (b ^^^ c)) - 5 * (a &&& ( ~~~b ||| c)) + 1 * ((a ^^^ b) ||| (a ^^^ c)) - 5 * (a |||  ~~~b) + 5 * (a ^^^ (b ^^^ c)) - 11 *  ~~~(a &&& (b &&& c)) - 1 *  ~~~( ~~~a ||| (b &&& c)) + 4 * (c ^^^  ~~~(a &&&  ~~~b)) - 1 * (b &&&  ~~~c) + 5 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) - 2 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) + 2 * ( ~~~b ||| (a ^^^ c)) + 4 *  ~~~(a ||| (b ||| c)) + 5 *  ~~~(a ||| ( ~~~b ||| c)) + 23 *  ~~~( ~~~a ||| (b ||| c)) + 12 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 9 * ( ~~~a &&& ( ~~~b &&& c)) + 10 * (a &&& ( ~~~b &&& c)) + 8 * (a &&& (b &&& c)) =  - 24 * ( ~~~a &&& (b &&& c)) - 3 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c)))

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

theorem main6_proof : main6_before ⊑ main6_after

theorem ashr_ugt_10_thm (e : IntW 4) :
  icmp IntPred.ugt (ashr e (const? 4 1)) (const? 4 (-6)) ⊑ icmp IntPred.slt e (const? 4 0)

theorem sext_xor_sub_3_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  x_1 = 1#1 → signExtend 64 x_1 - (signExtend 64 x_1 ^^^ x) = x

theorem masked_or_A_logical_proof : masked_or_A_logical_before ⊑ masked_or_A_logical_after

theorem trunc_lshr_big_mask_thm (e : IntW 8) :
  LLVM.and (trunc 6 (lshr e (const? 8 2))) (const? 6 31) ⊑
    LLVM.and (trunc 6 (lshr e (const? 8 2)) { «nsw» := false, «nuw» := true }) (const? 6 31)

theorem p0_thm (e : IntW 8) :
  icmp IntPred.ne (ashr (shl e (const? 8 5)) (const? 8 5) { «exact» := true }) e ⊑
    icmp IntPred.ult (add e (const? 8 (-4))) (const? 8 (-8))

theorem test5_proof : test5_before ⊑ test5_after

theorem xor_or2_thm.extracted_1._1 : ∀ (x : BitVec 8), x ^^^ 33#8 ||

theorem and_xor_or7_proof : and_xor_or7_before ⊑ and_xor_or7_after

theorem pb_thm (e : IntW 65) :
  icmp IntPred.ne e (ashr (shl e (const? 65 1)) (const? 65 1) { «exact» := true }) ⊑
    icmp IntPred.slt (add e (const? 65 9223372036854775808)) (const? 65 0)

theorem negative1_logical_proof : negative1_logical_before ⊑ negative1_logical_after

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

theorem testtrunclowhigh_thm.extracted_1._3 : ∀ (x x_1 : BitVec 16) (x_2 : BitVec 32),
  ¬ofBool (x_2 + 128#32 <ᵤ 256#32) = 1#1 → ofBool (-1#32 <ₛ x_2) = 1#1 → ofBool (x_2 <ₛ 0#32) = 1#1 → x_1 = x

theorem test25_proof : test25_before ⊑ test25_after

theorem exact_ashr_ne_proof : exact_ashr_ne_before ⊑ exact_ashr_ne_after

@[simp] theorem Valuation.cons_inj {t : Ty} {x y : ⟦t⟧} :
    (x ::ᵥ V) = (y ::ᵥ V) ↔ x = y

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_4_logical_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and e (const? 32 15)) (const? 32 8)) (const? 1 1)
      (icmp IntPred.eq (LLVM.and e (const? 32 255)) (const? 32 0)) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 15)) (const? 32 8)

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

theorem test_sext3_thm.extracted_1._3 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → x_1 ^^^ 1#1 = 1#1 → 0#32 = signExtend 32 x

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

theorem shl_lshr_demand4_thm (e : IntW 8) :
  LLVM.or (lshr (shl (const? 8 44) e) (const? 8 3)) (const? 8 (-32)) ⊑
    LLVM.or (lshr (shl (const? 8 44) e) (const? 8 3)) (const? 8 (-32)) { «disjoint» := true }

theorem select_of_symmetric_selects_thm.extracted_1._4 : ∀ (x : BitVec 32) (x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → x_1 = 1#1 → ¬x_1 ^^^ x_2 = 1#1 → False

theorem select_1_thm.extracted_1._7 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 x_3 : BitVec 8) (x_4 : BitVec 1),
  ¬x_4 = 1#1 → x_1 = 1#1 → x ^^^ -1#8 ^^^ -1#8 = x

theorem scalar_i32_lshr_and_signbit_ne_proof : scalar_i32_lshr_and_signbit_ne_before ⊑ scalar_i32_lshr_and_signbit_ne_after

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

theorem uge_swap_and_max_commute_proof : uge_swap_and_max_commute_before ⊑ uge_swap_and_max_commute_after

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

theorem icmp_ne_zext_ne_one_thm (e : IntW 32) :
  icmp IntPred.ne (zext 32 (icmp IntPred.ne e (const? 32 1))) e ⊑ const? 1 1

theorem e_1610 :
    1 * (a &&&  ~~~c) - 2 * (b &&&  ~~~(a &&& c)) - 5 * ((a &&& b) ||| (a ^^^ (b ^^^ c))) - 6 * (c ^^^  ~~~(a &&& (b ||| c))) - 6 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 4 * (c ||| (a &&& b)) + 11 * ( ~~~a ||| ( ~~~b ||| c)) - 1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) + 11 *  ~~~(a |||  ~~~c) - 2 * ( ~~~(a ||| b) ||| (b ^^^ c)) - 2 * (a ^^^ (b &&& c)) - 2 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 6 *  ~~~(a ||| (b ||| c)) + 12 *  ~~~(a ||| ( ~~~b ||| c)) + 7 *  ~~~( ~~~a ||| (b ||| c)) + 13 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 14 * ( ~~~a &&& ( ~~~b &&& c)) - 5 * (a &&& ( ~~~b &&& c)) - 2 * (a &&& (b &&& c)) = 21 * ( ~~~a &&& (b &&& c)) - 1 * (c &&& (a |||  ~~~b))

theorem n7_wrong_pred2_proof : n7_wrong_pred2_before ⊑ n7_wrong_pred2_after

theorem bigOr_append_equiv_or_bigOr {α : Type _}
    (c : Circuit α) (cs : List (Circuit α)) :
    Equiv (Circuit.bigOr (cs ++ [c])) (c ||| Circuit.bigOr cs)

theorem test11_proof : test11_before ⊑ test11_after

theorem orcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond_proof : orcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond_before ⊑ orcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond_after

theorem fold_inverted_icmp_preds_proof : fold_inverted_icmp_preds_before ⊑ fold_inverted_icmp_preds_after

theorem e_1988 :
     - 2 *  ~~~(a ^^^ (b ^^^ c)) + 11 * (b ^^^ ( ~~~a ||| (b ^^^ c))) + 5 *  ~~~(a &&& b) + 4 * (b ||| (a &&& c)) + 4 *  ~~~(b ||| c) + 7 * ( ~~~a ||| ( ~~~b ||| c)) + 2 * (b ^^^  ~~~(a &&&  ~~~c)) + 1 * (a ||| (b ||| c)) - 1 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) + 2 * (b ^^^  ~~~(a &&& (b ||| c))) + 1 * ( ~~~(a ^^^ b) ||| (a ^^^ c)) - 7 * (a ^^^ b) - 2 * (c ^^^ (a ||| b)) + 11 * (c ||| (a &&&  ~~~b)) - 1 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) - 7 * ((b &&&  ~~~c) ^^^ (a ||| (b ^^^ c))) + 1 * (a ||| (b ^^^ c)) + 2 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) - 2 * (c ^^^ ( ~~~a &&& (b ||| c))) + 5 * b - 1 * (b ^^^ (a &&& c)) + 5 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 6 *  ~~~(a ||| (b &&& c)) - 7 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) - 1 * (b ^^^  ~~~(a &&& (b ^^^ c))) - 6 *  ~~~(a ^^^ b) + 3 * (c |||  ~~~(a ^^^ b)) - 11 *  ~~~(a |||  ~~~c) - 1 * c + 4 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) - 2 *  ~~~( ~~~a &&& (b ||| c)) - 7 * (b &&& (a |||  ~~~c)) + 1 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 5 * (c ^^^ (a ||| (b &&& c))) + 2 * (a &&& c) + 4 * ((a &&& c) ^^^  ~~~(b &&&  ~~~c)) - 3 * (a &&& ( ~~~b ||| c)) - 2 * ( ~~~b &&&  ~~~(a ^^^ c)) + 2 *  ~~~a + 2 *  ~~~(b |||  ~~~c) - 11 *  ~~~c - 2 * ( ~~~b ||| (a ^^^ c)) - 7 * (a ^^^ ( ~~~b ||| c)) + 1 * (a |||  ~~~c) + 7 * (b ||| (a ^^^ c)) - 7 * (b ^^^ (a |||  ~~~c)) + 2 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) - 5 * (c ^^^ (a |||  ~~~b)) + 1 * (b ^^^  ~~~( ~~~a ||| (b ^^^ c))) + 3 *  ~~~(a &&&  ~~~b) - 3 *  ~~~(a ||| (b ||| c)) - 6 *  ~~~(a ||| ( ~~~b ||| c)) - 16 *  ~~~( ~~~a ||| (b ||| c)) - 7 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 38 * ( ~~~a &&& ( ~~~b &&& c)) - 8 * ( ~~~a &&& (b &&& c)) - 25 * (a &&& ( ~~~b &&& c)) - 33 * (a &&& (b &&& c)) =  - 5 * (a |||  ~~~b)

theorem icmp_power2_and_icmp_shifted_mask_2147483648_1610612736_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.ult e (const? 32 (-2147483648)))
      (icmp IntPred.ne (LLVM.and e (const? 32 1610612736)) (const? 32 1610612736)) ⊑
    icmp IntPred.ult e (const? 32 1610612736)

theorem test_sext_proof : test_sext_before ⊑ test_sext_after

theorem e_1082 :
     - 3 *  ~~~z - 3 *  ~~~(z &&&  ~~~t) + 11 * (z |||  ~~~t) + 7 *  ~~~(z &&&  ~~~z) + 2 * (z ||| t) - 15 *  ~~~(z ||| t) - 3 *  ~~~(z |||  ~~~t) - 23 * (z &&&  ~~~t) =  - 3 *  ~~~t + 17 * (z &&& t)

theorem sub_2_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 : BitVec 8),
  ¬x_1 = 1#1 → x_2 - (x ^^^ 123#8) ^^^ -1#8 = BitVec.ofInt 8 (-2) - ((x ^^^ BitVec.ofInt 8 (-124)) + x_2)

theorem e_1561 :
    4 * (a &&& (b ||| c)) + 11 * (a ^^^ ( ~~~b &&& c)) - 2 * (b ||| (a &&&  ~~~c)) - 7 * (c &&&  ~~~(a ^^^ b)) - 3 *  ~~~(a ^^^ b) - 5 * (b ||| (a ^^^ c)) - 3 *  ~~~a + 6 *  ~~~(a ||| (b ||| c)) + 10 *  ~~~(a ||| ( ~~~b ||| c)) - 4 *  ~~~( ~~~a ||| (b ||| c)) - 5 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 10 * ( ~~~a &&& (b &&& c)) - 4 * (a &&& ( ~~~b &&& c)) + 2 * (a &&& (b &&& c)) =  - 7 * ( ~~~a &&& ( ~~~b &&& c))

theorem test3_thm (e : IntW 32) :
  LLVM.xor (LLVM.and (LLVM.or e (const? 32 145)) (const? 32 177)) (const? 32 153) ⊑
    LLVM.or (LLVM.and e (const? 32 32)) (const? 32 8) { «disjoint» := true }

theorem test_sub_nuw_nsw__nsw_is_safe_proof : test_sub_nuw_nsw__nsw_is_safe_before ⊑ test_sub_nuw_nsw__nsw_is_safe_after

theorem zext_negate_proof : zext_negate_before ⊑ zext_negate_after

theorem lshrult_02_08_proof : lshrult_02_08_before ⊑ lshrult_02_08_after

theorem logical_and_icmps2_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → 0#1 = 1#1 → ofBool (x == 10086#32) = 0#1

theorem demorgan_or_zext_proof : demorgan_or_zext_before ⊑ demorgan_or_zext_after

theorem add_umin_simplify2_proof : add_umin_simplify2_before ⊑ add_umin_simplify2_after

theorem tctx_at_0 : tctx ⟨0, by omega⟩ = WidthExpr.var ⟨0, by omega⟩

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

theorem reassoc_x2_sub_nuw_proof : reassoc_x2_sub_nuw_before ⊑ reassoc_x2_sub_nuw_after

theorem and_umin_proof : and_umin_before ⊑ and_umin_after

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

theorem xor_or2_proof : xor_or2_before ⊑ xor_or2_after

theorem shift_xor_multiuse_cmp_or_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (0#32 != x_2 &&& 4096#32) = 1#1 → ¬ofBool (x_2 &&& 4096#32 == 0#32) = 1#1 → False

theorem logical_and_icmps1_proof : logical_and_icmps1_before ⊑ logical_and_icmps1_after

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

theorem sextbool_add_proof : sextbool_add_before ⊑ sextbool_add_after

theorem test27_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  zeroExtend 32 (ofBool (x_2 ^^^ x_1 == x_2 ^^^ x)) = zeroExtend 32 (ofBool (x_1 == x))

theorem riscVArgsFromHybrid_nil_eq : riscvArgsFromHybrid (HVector.nil) = HVector.nil

theorem trunc_lshr_sext_thm (e : IntW 8) : trunc 8 (lshr (sext 32 e) (const? 32 6)) ⊑ ashr e (const? 8 6)

theorem main5_like_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 7#32) = 1#1 → ofBool (x &&& 7#32 != 7#32) = 1#1 → 0#1 = 1#1 → 0#32 = zeroExtend 32 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 n14_wrong_comparison_constant_proof : n14_wrong_comparison_constant_before ⊑ n14_wrong_comparison_constant_after

theorem negate_ashr_proof : negate_ashr_before ⊑ negate_ashr_after

theorem select_or_icmp_bad_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == 3#32) = 1#1 → x_1 ||

theorem xor_logic_and_or2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 = 1#1 → x_1 = 1#1 → x_1 ^^^ (x_1 ||| x) = x_2 ^^^ 1#1

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

theorem and_not_or_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 bools2_logical_commute1_and1_thm.extracted_1._7 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 &&& x_1 = 1#1 → x_1 ^^^ 1#1 = 1#1 → x_1 = 1#1 → x = x_2

theorem test19a_thm (e : IntW 39) :
  icmp IntPred.eq (ashr e (const? 39 2)) (const? 39 (-1)) ⊑ icmp IntPred.ugt e (const? 39 (-5))

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

theorem e_2012 :
     - 5 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 4 * (f |||  ~~~(d ^^^ e)) - 3 * (e ^^^ (d |||  ~~~f)) - 1 * (f ^^^  ~~~(d &&&  ~~~e)) + 4 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) + 2 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) - 6 * (e ^^^ (d ||| (e &&& f))) - 1 * (f ^^^ (d ||| (e &&& f))) - 5 *  ~~~(e ||| f) - 7 * ( ~~~d &&& ( ~~~e ||| f)) + 11 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 1 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 4 *  ~~~(d ^^^ (e ^^^ f)) - 6 * (f ^^^ (d ||| (e ||| f))) - 6 *  ~~~(d &&& f) - 7 * ((d &&& e) ^^^ (e ||| f)) - 1 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 3 *  ~~~(d ^^^ ( ~~~e &&& f)) + 2 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) - 5 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 2 * (e |||  ~~~(d ^^^ f)) + 3 * ( ~~~d ||| (e &&& f)) + 3 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 1 *  ~~~( ~~~d ||| ( ~~~e &&& f)) - 7 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 1 * (e ^^^  ~~~(d &&& (e &&& f))) - 11 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 3 * (e ^^^ (d &&& (e ||| f))) + 11 *  ~~~(d ||| (e ||| f)) + 18 * ( ~~~d &&& ( ~~~e &&& f)) + 12 * ( ~~~d &&& (e &&& f)) - 1 * (d &&& ( ~~~e &&& f)) - 2 * (d &&& (e &&& f)) =  - 42 *  ~~~( ~~~d ||| (e ||| f)) - 41 *  ~~~(d ||| ( ~~~e ||| f))

theorem rem_euclid_pow2_true_arm_folded_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(2#32 == 0 || 32 != 1 && x == intMin 32 && 2#32 == -1) = true →
    ofBool (x.srem 2#32 <ₛ 0#32) = 1#1 → 1#32 = x &&& 1#32

theorem ult_swap_or_not_max_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x <ᵤ x_1) ||

theorem multiuse2_proof : multiuse2_before ⊑ multiuse2_after

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

theorem R.fromPoly_representatitive'_toFun (a : R q n) :
    (R.fromPoly (q := q) (n := n)).toFun (R.representative' q n a) = ↑a

theorem is_rem4_neg_i16_proof : is_rem4_neg_i16_before ⊑ is_rem4_neg_i16_after

theorem test92_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬32#96 ≥ ↑96 → ¬32#64 ≥ ↑64 → truncate 64 (signExtend 96 x >>> 32#96) = x.sshiftRight' 32#64

theorem carry_changeInitCarry_succ
    (p : FSM arity) (c : p.α → Bool) (x : arity → BitStream) : ∀ n,
    (p.changeInitCarry c).carry x (n+1) =
      (p.changeInitCarry (p.nextBit c (fun a => x a 0)).1).carry
        (fun a i => x a (i+1)) n

theorem sdiv_mul_shl_nsw_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 5),
  ¬(True ∧ x_2.smulOverflow x_1 = true ∨
        True ∧ (x_2 <<< x).sshiftRight' x ≠ x_2 ∨
          x ≥ ↑5 ∨ (x_2 <<< x == 0 || 5 != 1 && x_2 * x_1 == intMin 5 && x_2 <<< x == -1) = true) →
    True ∧ 1#5 <<< x >>> x ≠ 1#5 ∨ x ≥ ↑5 ∨ (1#5 <<< x == 0 || 5 != 1 && x_1 == intMin 5 && 1#5 <<< x == -1) = true →
      False

theorem sle_or_not_min_proof : sle_or_not_min_before ⊑ sle_or_not_min_after

theorem differentconsts_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x + 16#32 <ᵤ 144#32) = 1#1 →
    ¬ofBool (127#32 <ₛ x) = 1#1 → ofBool (x <ₛ BitVec.ofInt 32 (-16)) = 1#1 → truncate 16 x = 256#16

theorem or_xor_tree_0000_proof : or_xor_tree_0000_before ⊑ or_xor_tree_0000_after

@[bv_automata_nnf] theorem imp_false_eq (p : Prop) : (p → False) = ¬p

theorem ashrsgt_03_13_exact_proof : ashrsgt_03_13_exact_before ⊑ ashrsgt_03_13_exact_after

theorem pow2_or_zero_is_negative_commute_proof : pow2_or_zero_is_negative_commute_before ⊑ pow2_or_zero_is_negative_commute_after

theorem or_logic_or_logic_and_2_proof : or_logic_or_logic_and_2_before ⊑ or_logic_or_logic_and_2_after

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

theorem test13_proof : test13_before ⊑ test13_after

theorem bor_lor_right2_proof : bor_lor_right2_before ⊑ bor_lor_right2_after

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

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

theorem test16_thm.extracted_1._1 : ∀ (x : BitVec 16), 12#16 ≥ ↑16 ∨ 15#16 ≥ ↑16 → False

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

theorem add_of_selects_proof : add_of_selects_before ⊑ add_of_selects_after

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

theorem masked_bit_wrong_pred_proof : masked_bit_wrong_pred_before ⊑ masked_bit_wrong_pred_after

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

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

theorem shl_and_and_proof : shl_and_and_before ⊑ shl_and_and_after

theorem test8_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬16#32 ≥ ↑32 →
    ¬(16#32 ≥ ↑32 ∨ True ∧ (x.sshiftRight' 16#32).smulOverflow 32767#32 = true) →
      signExtend 64 (x.sshiftRight' 16#32) * 32767#64 = signExtend 64 (x.sshiftRight' 16#32 * 32767#32)

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

@[simp] theorem hasType_push {Γ : Context Ty} :
    (Γ.push v ty).hasType v ty

theorem PR42691_8_logical_proof : PR42691_8_logical_before ⊑ PR42691_8_logical_after

theorem neg_slt_0_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (0#8 - x <ₛ 0#8) = ofBool (-1#8 <ₛ x + -1#8)

theorem invert_signbit_splat_mask_thm.extracted_1._2 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ¬7#8 ≥ ↑8 → ¬ofBool (-1#8 <ₛ x_1) = 1#1 → signExtend 16 (x_1.sshiftRight' 7#8 ^^^ -1#8) &&& x = 0#16

theorem BitVec.any_iff_exists {bv : BitVec w} :
    bv.any p ↔ ∃ (i : Fin w), p i (bv.getLsbD i)

theorem lowmask_mul_zext_proof : lowmask_mul_zext_before ⊑ lowmask_mul_zext_after

theorem sub_shl_same_amount_partial_nsw1_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 6),
  ¬(True ∧ (x_2 <<< x_1).sshiftRight' x_1 ≠ x_2 ∨ x_1 ≥ ↑6 ∨ True ∧ (x <<< x_1).sshiftRight' x_1 ≠ x ∨ x_1 ≥ ↑6) →
    ¬x_1 ≥ ↑6 → x_2 <<< x_1 - x <<< x_1 = (x_2 - x) <<< x_1

theorem test22_proof : test22_before ⊑ test22_after

theorem positive_sameconst_shlnuwnsw_proof : positive_sameconst_shlnuwnsw_before ⊑ positive_sameconst_shlnuwnsw_after

theorem icmp_eq_x_invertable_y2_todo_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → ofBool (x_1 ^^^ -1#8 == x ||| x_1 ^^^ -1#8) = ofBool (x &&& x_1 == 0#8)

theorem slt_smin2_proof : slt_smin2_before ⊑ slt_smin2_after

theorem zext_sext_add_icmp_slt_0_proof : zext_sext_add_icmp_slt_0_before ⊑ zext_sext_add_icmp_slt_0_after

theorem exact_lshr_eq_noexactdiv_proof : exact_lshr_eq_noexactdiv_before ⊑ exact_lshr_eq_noexactdiv_after

theorem andn_or_cmp_2_partial_logical_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 16),
  ofBool (x_1 ≤ₛ x_2) ||

theorem ripple_nsw5_thm (e e_1 : IntW 16) :
  add (LLVM.or e_1 (const? 16 (-21845))) (LLVM.or e (const? 16 (-10923))) ⊑
    add (LLVM.or e_1 (const? 16 (-21845))) (LLVM.or e (const? 16 (-10923))) { «nsw» := true, «nuw» := false }

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

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

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

theorem test14a_proof : test14a_before ⊑ test14a_after

theorem sext_sub_nuw_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8),
  ¬(True ∧ x_1.usubOverflow (signExtend 8 x) = true) → x_1 - signExtend 8 x = x_1 + zeroExtend 8 x

theorem sge_and_max_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.sge e_1 e) (icmp IntPred.eq e_1 (const? 8 127)) ⊑
    icmp IntPred.eq e_1 (const? 8 127)

theorem main8_logical_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 64#32 != 0#32) = 1#1 →
    ofBool (x &&& 192#32 == 0#32) = 1#1 → ofBool (truncate 8 x <ₛ 0#8) = 1#1 → 2#32 = 1#32

theorem lshrugt_01_02_proof : lshrugt_01_02_before ⊑ lshrugt_01_02_after

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

theorem test12_proof : test12_before ⊑ test12_after

theorem test_sext3_thm.extracted_1._3 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → x_1 ^^^ 1#1 = 1#1 → 0#32 = signExtend 32 x

theorem srem_constant_dividend_select_of_constants_divisor_0_arm_proof : srem_constant_dividend_select_of_constants_divisor_0_arm_before ⊑ srem_constant_dividend_select_of_constants_divisor_0_arm_after

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

theorem canonicalize_logic_first_or0_nsw_thm (e : IntW 32) :
  LLVM.or (add e (const? 32 112) { «nsw» := true, «nuw» := false }) (const? 32 15) ⊑
    add (LLVM.or e (const? 32 15)) (const? 32 112) { «nsw» := true, «nuw» := false }

@[simp_denote, simp]
theorem toOption_getSome : (PoisonOr.value x).toOption.getD y = x

theorem select_1_proof : select_1_before ⊑ select_1_after

theorem xor_orn_commute1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ¬(x_1 = 0 ∨ x_1 = 0) → x_1 = 0 → False

theorem lshr_ne_opposite_msb_proof : lshr_ne_opposite_msb_before ⊑ lshr_ne_opposite_msb_after

theorem main10_logical_thm.extracted_1._4 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 64#32 == 0#32) = 1#1 → ¬ofBool (x &&& 192#32 == 0#32) = 1#1 → 0#1 = 1#1 → 2#32 = 1#32

theorem foo1_or_proof : foo1_or_before ⊑ foo1_or_after

theorem foo_proof : foo_before ⊑ foo_after

theorem alive_AddSub_1624 : alive_AddSub_1624_src ⊑ alive_AddSub_1624_tgt

theorem bv_AndOrXor_794 :
    ∀ (e e_1 : LLVM.IntW w),
      LLVM.and (LLVM.icmp LLVM.IntPred.sgt e e_1) (LLVM.icmp LLVM.IntPred.ne e e_1) ⊑ LLVM.icmp LLVM.IntPred.sgt e e_1

theorem e_1430 :
    2 *  ~~~(z ^^^ t) - 3 * z - 11 *  ~~~(z &&&  ~~~t) + 11 *  ~~~z - 11 *  ~~~(z &&& t) - 3 *  ~~~(z &&&  ~~~z) + 11 *  ~~~(z ||| t) + 15 *  ~~~(z |||  ~~~t) + 17 * (z &&&  ~~~t) + 15 * (z &&& t) = 1 * (z ^^^ t) - 1 *  ~~~t

theorem ugt_253_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (BitVec.ofInt 8 (-3) <ᵤ truncate 8 x) = ofBool (x &&& 254#32 == 254#32)

theorem main7f_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 icmp_sle8_proof : icmp_sle8_before ⊑ icmp_sle8_after

theorem xor_or_xor_common_op_commute3_proof : xor_or_xor_common_op_commute3_before ⊑ xor_or_xor_common_op_commute3_after

theorem narrow_zext_sub_proof : narrow_zext_sub_before ⊑ narrow_zext_sub_after

theorem c_proof : c_before ⊑ c_after

theorem and_sext_to_sel_proof : and_sext_to_sel_before ⊑ and_sext_to_sel_after

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

theorem sext_xor_sub_3_proof : sext_xor_sub_3_before ⊑ sext_xor_sub_3_after

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 1), ofBool (zeroExtend 32 x != 0#32) = x

theorem foo_thm (e : IntW 1) : e ⊑ e

theorem ashrsgt_03_14_exact_proof : ashrsgt_03_14_exact_before ⊑ ashrsgt_03_14_exact_after

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

theorem eq_basic_proof : eq_basic_before ⊑ eq_basic_after

theorem zext_false_val_must_be_zero_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → zeroExtend 32 x = 0#32

theorem e_2210 :
    11 * (e ^^^ ( ~~~d ||| (e ^^^ f))) - 5 *  ~~~( ~~~d &&& ( ~~~e &&& f)) + 2 *  ~~~(d &&&  ~~~f) + 1 * (e ^^^ (d &&& (e ||| f))) + 4 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 4 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) + 1 * ((d &&& e) |||  ~~~(e ^^^ f)) + 11 * ( ~~~e &&& (d ^^^ f)) - 6 * (d ^^^ ( ~~~e ||| f)) + 11 *  ~~~(d ^^^ e) + 1 * (d &&& (e ||| f)) - 7 *  ~~~e - 6 * (e ^^^ (d |||  ~~~f)) - 2 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 1 *  ~~~(e ^^^ f) + 7 * (f ^^^ (d ||| ( ~~~e ||| f))) + 7 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 1 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 5 * (e ^^^ (d ||| (e ^^^ f))) + 7 * (d ||| (e ^^^ f)) - 1 *  ~~~f - 3 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 2 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 4 * (f &&& (d ||| e)) - 2 * ( ~~~e ||| (d ^^^ f)) + 3 * f + 11 *  ~~~(e ||| f) - 2 * (f ^^^ (d &&& e)) - 1 * (f ^^^ (d &&& (e ||| f))) + 1 * ( ~~~e |||  ~~~(d ^^^ f)) + 3 * (f ||| (d &&& e)) + 2 * (f &&& (d |||  ~~~e)) - 7 *  ~~~(d ^^^ f) + 1 * ((d &&& e) ^^^ (e ||| f)) + 2 * (e ^^^ f) - 5 * (f ^^^ (d ||| (e ||| f))) + 1 * ( ~~~f &&&  ~~~(d ^^^ e)) - 1 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 1 * ((d &&& e) ||| (e ^^^ f)) + 1 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 3 * (e ^^^  ~~~(d ||| f)) + 2 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 2 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) + 1 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 2 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) + 3 * (e &&&  ~~~(d &&&  ~~~f)) - 4 *  ~~~(d ||| (e ||| f)) - 3 *  ~~~(d ||| ( ~~~e ||| f)) - 27 *  ~~~( ~~~d ||| (e ||| f)) - 22 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 59 * ( ~~~d &&& ( ~~~e &&& f)) - 5 * ( ~~~d &&& (e &&& f)) - 15 * (d &&& ( ~~~e &&& f)) = 43 * (d &&& (e &&& f))

theorem mul_unkV_oddC_sge_proof : mul_unkV_oddC_sge_before ⊑ mul_unkV_oddC_sge_after

theorem logical_or_cond_reuse_proof : logical_or_cond_reuse_before ⊑ logical_or_cond_reuse_after

theorem zext_sext_add_icmp_ult_minus1_proof : zext_sext_add_icmp_ult_minus1_before ⊑ zext_sext_add_icmp_ult_minus1_after

theorem same_source_not_matching_signbits_proof : same_source_not_matching_signbits_before ⊑ same_source_not_matching_signbits_after

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

theorem sub_ult_zext_proof : sub_ult_zext_before ⊑ sub_ult_zext_after

theorem lshrult_01_01_proof : lshrult_01_01_before ⊑ lshrult_01_01_after

theorem scalar_i8_lshr_and_signbit_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x ≥ ↑8 → ofBool (x_1 >>> x &&& BitVec.ofInt 8 (-128) == 0#8) = ofBool (-1#8 <ₛ x_1 >>> x)

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

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

theorem multiuse_lshr_lshr_thm.extracted_1._2 : ∀ (x : BitVec 9),
  ¬(2#9 ≥ ↑9 ∨ 2#9 ≥ ↑9 ∨ 3#9 ≥ ↑9) → ¬(2#9 ≥ ↑9 ∨ 5#9 ≥ ↑9) → x >>> 2#9 * x >>> 2#9 >>> 3#9 = x >>> 2#9 * x >>> 5#9

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

theorem test7_thm.extracted_1._1 : ∀ (x : BitVec 32),
  True ∧ (20000#32).ssubOverflow (x &&& 511#32) = true ∨
      True ∧ (20000#32).usubOverflow (x &&& 511#32) = true ∨ True ∧ (20000#32 - (x &&& 511#32)).msb = true →
    False

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

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

theorem p1_ugt_proof : p1_ugt_before ⊑ p1_ugt_after

theorem sgt_and_min_commute_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == BitVec.ofInt 8 (-128)) &&& ofBool (x <ₛ x_1) = 0#1

theorem test10_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.eq (LLVM.and e (const? 32 2)) (const? 32 0)) (icmp IntPred.ult e (const? 32 4)) ⊑
    icmp IntPred.ult e (const? 32 2)

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

theorem sel_false_val_is_a_masked_ashr_of_true_val1_proof : sel_false_val_is_a_masked_ashr_of_true_val1_before ⊑ sel_false_val_is_a_masked_ashr_of_true_val1_after

theorem sgt_and_min_logical_proof : sgt_and_min_logical_before ⊑ sgt_and_min_logical_after

theorem PR38781_proof : PR38781_before ⊑ PR38781_after

theorem test2_proof : test2_before ⊑ test2_after

theorem shl_add_lshr_comm_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_1 <<< x >>> x ≠ x_1 ∨ x ≥ ↑32 ∨ True ∧ (x_2 * x_2).uaddOverflow (x_1 <<< x) = true ∨ x ≥ ↑32) →
    ¬(x ≥ ↑32 ∨ True ∧ ((x_2 * x_2) >>> x).uaddOverflow x_1 = true) →
      (x_2 * x_2 + x_1 <<< x) >>> x = (x_2 * x_2) >>> x + x_1

theorem ashr_mul_sign_bits_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬3#32 ≥ ↑32 → True ∧ (signExtend 16 x_1).smulOverflow (signExtend 16 x) = true ∨ 3#16 ≥ ↑16 → False

theorem main3f_like_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 &&& x != 0#32) = 1#1 → ofBool (x_1 &&& x == 0#32) = 1#1 → True → False

theorem select_non_const_sides_thm.extracted_1._4 : ∀ (x x_1 : BitVec 64) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → x - zeroExtend 64 x_2 = x

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

theorem decideIfZerosAux_correct {arity : Type _} [DecidableEq arity]
    (p : FSM arity) (c : Circuit p.α)
    (hc : ∀ s, c.eval s = true →
      ∃ m y, (p.changeInitCarry s).eval y m = true)
    (hc₂ : ∀ (x : arity → Bool) (s : p.α → Bool),
      (FSM.nextBit p s x).snd = true → Circuit.eval c s = true) :
    decideIfZerosAux p c = true ↔ ∀ n x, p.eval x n = false

theorem xor_sext_to_sel_thm (e : IntW 32) (e_1 : IntW 1) : LLVM.xor (sext 32 e_1) e ⊑ LLVM.xor e (sext 32 e_1)

theorem test6_proof : test6_before ⊑ test6_after

theorem fold_mask_cmps_to_true_logical_proof : fold_mask_cmps_to_true_logical_before ⊑ fold_mask_cmps_to_true_logical_after

theorem lshrugt_03_00_exact_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 3) { «exact» := true }) (const? 4 0) ⊑
    icmp IntPred.ne e (const? 4 0)

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 different_size_zext_zext_slt_proof : different_size_zext_zext_slt_before ⊑ different_size_zext_zext_slt_after

theorem test66_proof : test66_before ⊑ test66_after

theorem PR1817_2_logical_proof : PR1817_2_logical_before ⊑ PR1817_2_logical_after

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

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

@[simp] theorem AttrDict.find_none :
    AttrDict.find (@AttrDict.mk φ []) n' = none

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

theorem test2_proof : test2_before ⊑ test2_after

theorem bitwise_and_logical_and_masked_icmp_allones_poison1_proof : bitwise_and_logical_and_masked_icmp_allones_poison1_before ⊑ bitwise_and_logical_and_masked_icmp_allones_poison1_after

theorem icmp_sgt9_proof : icmp_sgt9_before ⊑ icmp_sgt9_after

theorem sext_diff_i1_xor_sub_proof : sext_diff_i1_xor_sub_before ⊑ sext_diff_i1_xor_sub_after

theorem sge_and_max_commute_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.eq e_1 (const? 8 127)) (icmp IntPred.sge e_1 e) ⊑
    icmp IntPred.eq e_1 (const? 8 127)

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

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

theorem ashrsgt_03_07_proof : ashrsgt_03_07_before ⊑ ashrsgt_03_07_after

theorem mul8_low_miss_half_width_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(3#8 ≥ ↑8 ∨ 3#8 ≥ ↑8 ∨ 3#8 ≥ ↑8) →
    3#8 ≥ ↑8 ∨ 3#8 ≥ ↑8 ∨ 3#8 ≥ ↑8 ∨ True ∧ (x_1 &&& 15#8).umulOverflow (x &&& 15#8) = true → False

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

theorem xor_ashr_not_fail_invalid_xor_constant_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(x_1 ≥ ↑8 ∨ x_1 ≥ ↑8) →
    ¬x_1 ≥ ↑8 →
      x_2.sshiftRight' x_1 ^^^ (x.sshiftRight' x_1 ^^^ BitVec.ofInt 8 (-2)) =
        (x ^^^ x_2).sshiftRight' x_1 ^^^ BitVec.ofInt 8 (-2)

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

lemma eval_eq_of_eq_on_vars [DecidableEq α] : ∀ {c : Circuit α} {f g : α → Bool}
    (_h : ∀ x ∈ c.vars, f x = g x), eval c f = eval c g

theorem test2_thm (e e_1 : IntW 23) : LLVM.xor (LLVM.and e_1 e) (LLVM.or e_1 e) ⊑ LLVM.xor e_1 e

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

theorem not_and_eq_not_or_not (x y : BitVec 64) :
  ~~~ (x &&& y) + x  = (~~~ x ||| ~~~ y) + x

theorem test7_proof : test7_before ⊑ test7_after

theorem lshrult_03_00_proof : lshrult_03_00_before ⊑ lshrult_03_00_after

theorem ashrsgt_01_07_exact_proof : ashrsgt_01_07_exact_before ⊑ ashrsgt_01_07_exact_after

theorem src_srem_shl_demand_eliminate_signbit_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬((1073741824#32 == 0 || 32 != 1 && x == intMin 32 && 1073741824#32 == -1) = true ∨ 1#32 ≥ ↑32) →
    (1073741824#32 == 0 || 32 != 1 && x == intMin 32 && 1073741824#32 == -1) = true ∨
        True ∧ (x.srem 1073741824#32 <<< 1#32).sshiftRight' 1#32 ≠ x.srem 1073741824#32 ∨ 1#32 ≥ ↑32 →
      False

theorem test_add__nuw_is_safe_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 2147483647#32 == 2147483647#32) = 1#1 →
    True ∧ (x &&& 2147483647#32).uaddOverflow 1#32 = true → False

theorem a_false_implies_b_false2_comm_proof : a_false_implies_b_false2_comm_before ⊑ a_false_implies_b_false2_comm_after

theorem lshrugt_03_12_proof : lshrugt_03_12_before ⊑ lshrugt_03_12_after

theorem lshrugt_03_03_proof : lshrugt_03_03_before ⊑ lshrugt_03_03_after

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

theorem not_sub_proof : not_sub_before ⊑ not_sub_after

theorem slt_negative_multip_rem_zero_thm (e : IntW 8) :
  icmp IntPred.slt (mul e (const? 8 (-7)) { «nsw» := true, «nuw» := false }) (const? 8 21) ⊑
    icmp IntPred.sgt e (const? 8 (-3))

theorem bools_multi_uses2_logical_thm.extracted_1._13 : ∀ (x x_1 : BitVec 1),
  ¬x_1 ^^^ 1#1 = 1#1 → x_1 = 1#1 → 0#1 = 1#1 → x = 1#1 → ¬True → 0#1 + x = 0#1 ^^^ x

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

theorem gt_unsigned_to_small_negative_proof : gt_unsigned_to_small_negative_before ⊑ gt_unsigned_to_small_negative_after

theorem xor_common_op_commute0_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), x_1 ^^^ x ||

theorem ashrsgt_01_15_exact_proof : ashrsgt_01_15_exact_before ⊑ ashrsgt_01_15_exact_after

theorem narrow_zext_xor_thm (e : IntW 32) (e_1 : IntW 16) :
  trunc 16 (LLVM.xor (zext 32 e_1) e) ⊑ LLVM.xor e_1 (trunc 16 e)

theorem shl_bad_sub_i32_thm (e : IntW 32) :
  shl (const? 32 1) (sub (const? 32 32) e) ⊑
    shl (const? 32 1) (sub (const? 32 32) e) { «nsw» := false, «nuw» := true }

theorem alive_InstCombineShift__582  (w : Nat)   : alive_InstCombineShift__582_src w  ⊑ alive_InstCombineShift__582_tgt w

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 main7d_logical_proof : main7d_logical_before ⊑ main7d_logical_after

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

theorem ne_smax1_proof : ne_smax1_before ⊑ ne_smax1_after

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

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

theorem shl_or_lshr_proof : shl_or_lshr_before ⊑ shl_or_lshr_after

theorem lshrugt_02_03_exact_proof : lshrugt_02_03_exact_before ⊑ lshrugt_02_03_exact_after

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

theorem sge_smin1_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 xor_ashr_not_proof : xor_ashr_not_before ⊑ xor_ashr_not_after

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

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

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

theorem uaddo_wrong_pred2_proof : uaddo_wrong_pred2_before ⊑ uaddo_wrong_pred2_after

theorem low_mask_nsw_nuw_proof : low_mask_nsw_nuw_before ⊑ low_mask_nsw_nuw_after

theorem or_xor_or_proof : or_xor_or_before ⊑ or_xor_or_after

theorem or_not_and_commute5_thm (e e_1 e_2 : IntW 32) :
  LLVM.or
      (LLVM.and (LLVM.sdiv (const? 32 42) e_2) (LLVM.xor (LLVM.or (LLVM.sdiv (const? 32 42) e_1) e) (const? 32 (-1))))
      (LLVM.and (LLVM.xor (LLVM.or (LLVM.sdiv (const? 32 42) 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 (LLVM.sdiv (const? 32 42) e_1) (const? 32 (-1)))

theorem neg0 (w : Nat) (a : BitVec w) : (w = 2) → ((a = - a) → (a = 0#w ∨ a = 2#w))

theorem lshr_mul_times_3_div_2_exact_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ x.smulOverflow 3#32 = true ∨ True ∧ (x * 3#32) >>> 1#32 <<< 1#32 ≠ x * 3#32 ∨ 1#32 ≥ ↑32) →
    ¬(True ∧ x >>> 1#32 <<< 1#32 ≠ x ∨ 1#32 ≥ ↑32 ∨ True ∧ x.saddOverflow (x >>> 1#32) = true) →
      (x * 3#32) >>> 1#32 = x + x >>> 1#32

@[simp] theorem eval_logicalShiftRight {x : BitStream} {k : Nat} :
  (logicalShiftRight x k) i = x (k + i)

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

theorem is_ascii_alphabetic_proof : is_ascii_alphabetic_before ⊑ is_ascii_alphabetic_after

theorem masked_and_notallones_proof : masked_and_notallones_before ⊑ masked_and_notallones_after

theorem main4e_like_proof : main4e_like_before ⊑ main4e_like_after

theorem eval_eq_of_eq_on_sumVarsLeft_right
    [DecidableEq α] [DecidableEq β] :
    ∀ {c : Circuit (α ⊕ β)} {f g : α ⊕ β → Bool}
    (_h₁ : ∀ x ∈ c.sumVarsLeft, f (Sum.inl x) = g (Sum.inl x))
    (_h₂ : ∀ x ∈ c.sumVarsRight, f (Sum.inr x) = g (Sum.inr x)),
    eval c f = eval c g

theorem test3_thm (e e_1 : IntW 32) : LLVM.and e_1 (LLVM.and e e_1) ⊑ LLVM.and e e_1

theorem e_1616 :
    1 * ( ~~~c &&& (a ^^^ b)) + 7 * ((a |||  ~~~b) &&& (b ^^^ c)) + 1 * (b ||| (a &&&  ~~~c)) - 5 * (a |||  ~~~c) + 5 * (b ^^^ c) + 1 * (b &&& c) + 1 * ((a ||| b) &&& (b ^^^ c)) + 7 * (a &&& (b ||| c)) + 4 * (a &&&  ~~~c) - 5 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) + 1 * (b &&&  ~~~(a ^^^ c)) - 3 *  ~~~(a ^^^ ( ~~~b ||| c)) + 10 *  ~~~(a ||| (b ||| c)) - 1 *  ~~~(a ||| ( ~~~b ||| c)) + 8 *  ~~~( ~~~a ||| (b ||| c)) - 20 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 12 * ( ~~~a &&& ( ~~~b &&& c)) - 1 * ( ~~~a &&& (b &&& c)) - 11 * (a &&& ( ~~~b &&& c)) + 4 * (a &&& (b &&& c)) = 1 * ((a &&& b) ^^^ (a ^^^ (b &&& c)))

theorem logic_or_logic_and_4_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), x_1 = 1#1 → ¬x = 1#1 → True → x_1 = 1#1

theorem shl_sub_lshr_reverse_no_nsw_thm (e e_1 e_2 : IntW 32) :
  lshr (sub e_2 (shl e_1 e { «nsw» := false, «nuw» := true }) { «nsw» := false, «nuw» := true }) e { «exact» := true } ⊑
    sub (lshr e_2 e { «exact» := true }) e_1 { «nsw» := false, «nuw» := true }

theorem Lets.denote_eq_denoteIntoSubtype (lets : Lets d Γ_in eff Γ_out) (Γv : Valuation Γ_in) :
    lets.denote Γv = Subtype.val <$> (lets.denoteIntoSubtype Γv)

theorem and_or1_commuted_thm.extracted_1._8 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 ||

theorem masked_or_allones_logical_proof : masked_or_allones_logical_before ⊑ masked_or_allones_logical_after

theorem e_1645 :
     - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 7 *  ~~~(a &&&  ~~~b) + 5 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) + 2 * ((a ^^^ b) &&&  ~~~(a ^^^ c)) + 5 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) - 7 * ( ~~~c &&&  ~~~(a ^^^ b)) + 5 * (a ||| ( ~~~b ||| c)) + 1 * (b &&& (a ||| c)) + 11 * (c &&&  ~~~(a &&&  ~~~b)) - 11 * (b ^^^ (a ||| c)) - 5 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) - 6 * (b |||  ~~~(a ^^^ c)) - 5 * (b &&& c) - 1 * (a ^^^ (b &&& c)) - 7 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) - 3 *  ~~~(a ||| (b ||| c)) + 19 *  ~~~(a ||| ( ~~~b ||| c)) - 3 *  ~~~( ~~~a ||| (b ||| c)) + 8 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 10 * ( ~~~a &&& ( ~~~b &&& c)) - 11 * ( ~~~a &&& (b &&& c)) + 18 * (a &&& ( ~~~b &&& c)) - 19 * (a &&& (b &&& c)) =  - 1 * (b ^^^  ~~~( ~~~a ||| (b &&& c)))

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

theorem is_ascii_alphabetic_inverted_proof : is_ascii_alphabetic_inverted_before ⊑ is_ascii_alphabetic_inverted_after

theorem select_or_icmp_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.eq e_2 (const? 32 0)) (LLVM.or e_2 e_1) e ⊑
    select (icmp IntPred.eq e_2 (const? 32 0)) e_1 e

theorem test18_thm.extracted_1._1 : ∀ (x : BitVec 128),
  ¬(2#128 ≥ ↑128 ∨ 2#128 ≥ ↑128) → x <<< 2#128 - x <<< 2#128 = 0#128

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

theorem and_signbit_select_ashr_proof : and_signbit_select_ashr_before ⊑ and_signbit_select_ashr_after

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

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

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

theorem testi32i8_proof : testi32i8_before ⊑ testi32i8_after

theorem test15_proof : test15_before ⊑ test15_after

theorem test9_thm.extracted_1._1 : ∀ (x : BitVec 77), True ∧ (x &&& 562949953421310#77 &&& 1#77 != 0) = true → False

theorem test2_thm (e : IntW 8) :
  ashr (add (zext 32 e) (const? 32 7)) (const? 32 3) ⊑
    lshr (add (zext 32 e) (const? 32 7) { «nsw» := true, «nuw» := true }) (const? 32 3)

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

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 n5_thm.extracted_1._4 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 2#32 == 0#32) = 1#1 → ¬1#32 ≥ ↑32 → 1#32 = x >>> 1#32 &&& 1#32

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

theorem test9_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(True ∧ (0#64).ssubOverflow x = true) → 0#64 - x &&& 1#64 = x &&& 1#64

theorem srem_common_divisor_defined_cond_proof : srem_common_divisor_defined_cond_before ⊑ srem_common_divisor_defined_cond_after

theorem shl_bad_sub_i8_proof : shl_bad_sub_i8_before ⊑ shl_bad_sub_i8_after

theorem sle_or_not_min_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ne e_1 (const? 8 (-128))) (const? 1 1) (icmp IntPred.sle e_1 e) ⊑ const? 1 1

theorem e_1284 :
    1 *  ~~~t - 5 * (z ||| t) - 2 * z - 1 * t - 2 * (z |||  ~~~t) + 6 *  ~~~(z ||| t) + 6 *  ~~~(z |||  ~~~t) + 8 * (z &&&  ~~~t) + 15 * (z &&& t) = 5 *  ~~~(z ^^^ t)

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

theorem test35_proof : test35_before ⊑ test35_after

theorem gt_signed_to_large_unsigned_thm (e : IntW 8) :
  icmp IntPred.ugt (sext 32 e) (const? 32 1024) ⊑ icmp IntPred.slt e (const? 8 0)

theorem pr40493_neg3_proof : pr40493_neg3_before ⊑ pr40493_neg3_after

theorem mul_constant_nuw_eq_proof : mul_constant_nuw_eq_before ⊑ mul_constant_nuw_eq_after

theorem icmp_ne_and_pow2_shl_pow2_proof : icmp_ne_and_pow2_shl_pow2_before ⊑ icmp_ne_and_pow2_shl_pow2_after

theorem sgt_smax1_proof : sgt_smax1_before ⊑ sgt_smax1_after

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

theorem icmp_eq_select_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → ofBool (x == x_1) = ofBool (x_1 == x)

theorem select_zext_or_eq_ult_add_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x + BitVec.ofInt 32 (-3) <ᵤ 2#32) = 1#1 →
    zeroExtend 32 (ofBool (x == 5#32)) = zeroExtend 32 (ofBool (x + BitVec.ofInt 32 (-3) <ᵤ 3#32))

theorem main7e_thm.extracted_1._2 : ∀ (x x_1 x_2 x_3 x_4 : BitVec 32),
  ¬ofBool (x_4 &&& x_3 &&& x_2 == x_4 &&& x_3) &&& ofBool (x_1 &&& x &&& x_2 == x_1 &&& x) = 1#1 →
    1#32 = zeroExtend 32 (ofBool (x_2 &&& (x_4 &&& x_3 ||| x_1 &&& x) != x_4 &&& x_3 ||| x_1 &&& x))

theorem icmp_sle8_thm (e : IntW 8) :
  icmp IntPred.sle (shl e (const? 8 1) { «nsw» := true, «nuw» := false }) (const? 8 125) ⊑
    icmp IntPred.ne e (const? 8 63)

theorem shl_bad_sub_i32_proof : shl_bad_sub_i32_before ⊑ shl_bad_sub_i32_after

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

theorem slt_zero_ult_i1_fail2_proof : slt_zero_ult_i1_fail2_before ⊑ slt_zero_ult_i1_fail2_after

theorem e_1592 :
     - 1 * ( ~~~b &&&  ~~~(a ^^^ c)) + 11 * (b ^^^ (a ||| (b &&& c))) - 6 * (b ^^^  ~~~(a |||  ~~~c)) + 1 * (c |||  ~~~(a ^^^ b)) + 11 * ( ~~~(a |||  ~~~b) |||  ~~~(b ^^^ c)) - 11 * (b ^^^ ( ~~~a ||| (b ||| c))) - 6 * (c |||  ~~~(a ||| b)) + 5 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) - 6 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 2 * (c ^^^ (a &&& (b ||| c))) + 11 * (b ^^^  ~~~(a &&& (b &&& c))) - 11 * (a &&& b) - 16 *  ~~~(a ||| ( ~~~b ||| c)) - 27 *  ~~~( ~~~a ||| (b ||| c)) + 15 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 3 * ( ~~~a &&& ( ~~~b &&& c)) - 1 * (a &&& (b &&& c)) = 8 * ( ~~~a &&& (b &&& c))

theorem select_zext_or_eq_ult_add_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x + BitVec.ofInt 32 (-3) <ᵤ 2#32) = 1#1 → 1#32 = zeroExtend 32 (ofBool (x + BitVec.ofInt 32 (-3) <ᵤ 3#32))

theorem test16_proof : test16_before ⊑ test16_after

theorem foo_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ (x &&& 223#32 ^^^ 29#32).uaddOverflow (BitVec.ofInt 32 (-784568073)) = true ∨
        True ∧
            (((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                      ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                    1#32).sshiftRight'
                1#32 ≠
              (x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^ ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32) ∨
          True ∧
              ((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                      ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                    1#32 >>>
                  1#32 ≠
                (x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^ ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32) ∨
            1#32 ≥ ↑32 ∨
              True ∧
                ((x &&& 223#32 ^^^ 29#32) + BitVec.ofInt 32 (-784568073) -
                        ((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                            ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                          1#32).saddOverflow
                    1533579450#32 =
                  true) →
    True ∧ (x &&& 223#32 ^^^ 29#32).saddOverflow 1362915575#32 = true ∨
        True ∧ (x &&& 223#32 ^^^ 29#32).uaddOverflow 1362915575#32 = true ∨
          True ∧ ((x &&& 223#32 ^^^ 29#32) <<< 1#32).sshiftRight' 1#32 ≠ x &&& 223#32 ^^^ 29#32 ∨
            True ∧ (x &&& 223#32 ^^^ 29#32) <<< 1#32 >>> 1#32 ≠ x &&& 223#32 ^^^ 29#32 ∨
              1#32 ≥ ↑32 ∨
                True ∧
                    ((x &&& 223#32 ^^^ 29#32) + 1362915575#32).ssubOverflow
                        ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32) =
                      true ∨
                  True ∧
                      ((x &&& 223#32 ^^^ 29#32) + 1362915575#32).usubOverflow
                          ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32) =
                        true ∨
                    True ∧
                      ((x &&& 223#32 ^^^ 29#32) + 1362915575#32 -
                              ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32)).uaddOverflow
                          1533579450#32 =
                        true →
      False

theorem add_const_const_sub_nuw_proof : add_const_const_sub_nuw_before ⊑ add_const_const_sub_nuw_after

theorem ripple_nsw4_thm (e e_1 : IntW 16) :
  add (LLVM.and e_1 (const? 16 21843)) (LLVM.and e (const? 16 (-21845))) ⊑
    add (LLVM.and e_1 (const? 16 21843)) (LLVM.and e (const? 16 (-21845))) { «nsw» := true, «nuw» := true }

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 main1_proof : main1_before ⊑ main1_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_2_proof : masked_icmps_mask_notallzeros_bmask_mixed_2_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_2_after

theorem main6d_proof : main6d_before ⊑ main6d_after

theorem p0_proof : p0_before ⊑ p0_after

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

theorem cmpeq_bitwise_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 8),
  ofBool (x_3 ^^^ x_2 ||| x_1 ^^^ x == 0#8) = ofBool (x_3 == x_2) &&& ofBool (x_1 == x)

theorem scalar_i32_signbit_lshr_and_eq_proof : scalar_i32_signbit_lshr_and_eq_before ⊑ scalar_i32_signbit_lshr_and_eq_after

theorem map_map {A B C : α → Type*} {l : List α} (t : HVector A l)
    (f : ∀ a, A a → B a) (g : ∀ a, B a → C a) :
    (t.map f).map g = t.map (fun a v => g a (f a v))

theorem e_2463 :
     - 1 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 1 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 5 * d + 1 *  ~~~(e |||  ~~~f) + 2 * (d &&& f) - 2 * ( ~~~d ||| (e ||| f)) - 2 * (e ^^^ (d |||  ~~~f)) - 6 * (e ^^^  ~~~(d ||| (e ^^^ f))) + 2 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 6 * ((d &&& e) ||| (e ^^^ f)) - 3 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) - 1 * (f |||  ~~~(d ||| e)) - 6 *  ~~~(d &&& (e ^^^ f)) - 11 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) - 11 * (d ||| (e &&& f)) + 1 * (f ^^^ ( ~~~d &&& (e ||| f))) + 11 * (f ^^^ (d &&& (e ||| f))) + 5 * ( ~~~f &&& (d ^^^ e)) + 1 * ( ~~~d ||| (e &&& f)) + 7 * (d ^^^ ( ~~~e &&& f)) + 1 * ((d ^^^ e) &&& (d ^^^ f)) + 2 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) - 1 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) - 6 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 5 * f - 1 * (f ^^^  ~~~(d &&& (e ||| f))) - 2 *  ~~~(d &&& f) + 7 * (f &&&  ~~~(d &&& e)) - 11 * ((d &&& e) |||  ~~~(e |||  ~~~f)) - 1 * (f ^^^ ( ~~~d ||| (e &&& f))) - 3 * (f ^^^  ~~~(d ||| e)) + 5 *  ~~~(d &&& (e ||| f)) - 3 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 7 * (e ||| (d &&& f)) - 5 * ( ~~~f ||| (d ^^^ e)) - 2 *  ~~~( ~~~d &&& ( ~~~e &&& f)) + 1 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 5 * (f ^^^ (d ||| ( ~~~e &&& f))) - 5 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) + 1 * ((d &&& f) |||  ~~~(e ||| f)) + 11 * (d &&&  ~~~e) - 3 * (d ||| f) - 7 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 7 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 3 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 2 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 1 * (e ^^^ (d &&& (e ^^^ f))) + 1 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 3 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 1 * (f ^^^  ~~~(d |||  ~~~e)) + 2 * (d ||| ( ~~~e &&& f)) - 1 * (f &&& (d |||  ~~~e)) + 7 * ( ~~~d ||| ( ~~~e &&& f)) + 3 *  ~~~(d ^^^ ( ~~~e ||| f)) - 1 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) - 11 * (e |||  ~~~(d |||  ~~~f)) + 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 7 * (f ^^^ (d ||| (e ||| f))) + 1 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) - 2 *  ~~~(d &&&  ~~~d) + 2 * (e ^^^ (d &&& (e ||| f))) - 2 * (f ||| (d &&& e)) + 1 * (e ^^^ (d ||| ( ~~~e &&& f))) + 4 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 3 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 11 * (d &&& (e ^^^ f)) + 3 * e - 7 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) + 2 * (e ^^^  ~~~(d &&& f)) + 4 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 44 *  ~~~(d ||| (e ||| f)) + 25 *  ~~~(d ||| ( ~~~e ||| f)) + 24 *  ~~~( ~~~d ||| (e ||| f)) + 45 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 12 * ( ~~~d &&& ( ~~~e &&& f)) + 44 * ( ~~~d &&& (e &&& f)) + 21 * (d &&& ( ~~~e &&& f)) + 62 * (d &&& (e &&& f)) =  - 1 * (f ||| (d ^^^ e)) + 7 * (d ||| ( ~~~e ||| f))

@[simp]
theorem EnvFin.getLsbD_getNonLsbs {w : Nat} (env : EnvFin (w + 1) n) (bit : Nat) :
    (env.getNonLsbs i).getLsbD bit = (decide (bit < w) && (env i).getLsbD (bit + 1))

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

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

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

theorem test73_thm (e : IntW 32) :
  select (icmp IntPred.sgt (trunc 8 e) (const? 8 (-1))) (const? 32 40) (const? 32 42) ⊑
    select (icmp IntPred.eq (LLVM.and e (const? 32 128)) (const? 32 0)) (const? 32 40) (const? 32 42)

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

theorem not_xor_to_or_not2_proof : not_xor_to_or_not2_before ⊑ not_xor_to_or_not2_after

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

theorem signed_sign_bit_extract_proof : signed_sign_bit_extract_before ⊑ signed_sign_bit_extract_after

theorem test47_proof : test47_before ⊑ test47_after

theorem bor_land_left1_proof : bor_land_left1_before ⊑ bor_land_left1_after

theorem nonexact_lshr_ne_noexactdiv_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬x ≥ ↑8 → ofBool (80#8 >>> x != 31#8) = 1#1

theorem lt_signed_to_small_negative_proof : lt_signed_to_small_negative_before ⊑ lt_signed_to_small_negative_after

@[simp, simp_denote, simp_sllvm]
lemma run_pure : StateT.run (pure x : EffectM α) s = .value (x, s)

theorem negate_select_of_op_vs_negated_op_nsw_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 : BitVec 8),
  x_1 = 1#1 → ¬(True ∧ (0#8).ssubOverflow x = true) → x_2 - (0#8 - x) = x + x_2

theorem shl_add_log_may_cause_poison_pr62175_with_nsw_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ (4#8 <<< x).sshiftRight' x ≠ 4#8 ∨ x ≥ ↑8) → x + 2#8 ≥ ↑8 → False

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

theorem t9_highest_bit_proof : t9_highest_bit_before ⊑ t9_highest_bit_after

theorem signbit_splat_mask_thm (e : IntW 16) (e_1 : IntW 8) :
  LLVM.and (sext 16 (ashr e_1 (const? 8 7))) e ⊑
    select (icmp IntPred.slt e_1 (const? 8 0)) e (const? 16 0)

theorem e_1604 :
     - 5 * ((a &&& b) |||  ~~~(b ||| c)) + 2 * (b ^^^ ( ~~~a &&& (b ||| c))) + 1 * (a ^^^ (b ||| c)) - 2 * (b &&&  ~~~(a ^^^ c)) - 1 * (c ^^^ ( ~~~a ||| (b &&& c))) - 1 * ( ~~~b &&&  ~~~(a ^^^ c)) + 2 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 1 *  ~~~(a &&& ( ~~~b &&& c)) - 6 *  ~~~( ~~~a &&& (b ||| c)) + 2 *  ~~~(a ^^^ (b &&& c)) + 5 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 3 *  ~~~(a ||| (b ||| c)) - 10 *  ~~~(a ||| ( ~~~b ||| c)) - 3 *  ~~~( ~~~a ||| (b ||| c)) + 3 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 13 * ( ~~~a &&& ( ~~~b &&& c)) - 9 * ( ~~~a &&& (b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) + 6 * (a &&& (b &&& c)) =  - 7 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c)))

theorem allOnes_sub_eq_xor (x :BitVec w) : (allOnes w) - x = x ^^^ (allOnes w)

theorem tryFactorization_add_nuw_mul_nuw_int_max_proof : tryFactorization_add_nuw_mul_nuw_int_max_before ⊑ tryFactorization_add_nuw_mul_nuw_int_max_after

theorem rem_euclid_non_const_pow2_proof : rem_euclid_non_const_pow2_before ⊑ rem_euclid_non_const_pow2_after

theorem ugt_rem_zero_proof : ugt_rem_zero_before ⊑ ugt_rem_zero_after

theorem not_match_inconsistent_values_proof : not_match_inconsistent_values_before ⊑ not_match_inconsistent_values_after

theorem ashrslt_03_12_exact_proof : ashrslt_03_12_exact_before ⊑ ashrslt_03_12_exact_after

theorem main7d_thm.extracted_1._2 : ∀ (x x_1 x_2 x_3 x_4 : BitVec 32),
  ¬ofBool (x_4 &&& (x_3 &&& x_2) == x_3 &&& x_2) &&& ofBool (x_4 &&& (x_1 &&& x) == x_1 &&& x) = 1#1 →
    1#32 = zeroExtend 32 (ofBool (x_4 &&& (x_3 &&& x_2 ||| x_1 &&& x) != x_3 &&& x_2 ||| x_1 &&& x))

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

theorem mul_setnzV_unkV_nuw_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(True ∧ (x_1 ||| 2#8).umulOverflow x = true) → ofBool ((x_1 ||| 2#8) * x == 0#8) = ofBool (x == 0#8)

theorem shl_or_thm (e e_1 : IntW 16) :
  shl (LLVM.or (LLVM.srem e_1 (const? 16 42)) (shl e (const? 16 5))) (const? 16 7) ⊑
    LLVM.or (shl e (const? 16 12))
      (shl (LLVM.srem e_1 (const? 16 42)) (const? 16 7) { «nsw» := true, «nuw» := false })

theorem e_1607 :
    1 * ( ~~~c |||  ~~~(a ^^^ b)) + 5 * (b ^^^  ~~~(a |||  ~~~c)) - 3 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 11 * (b ^^^  ~~~(a &&&  ~~~c)) + 7 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) - 2 * (b ^^^ c) - 2 * (b ||| (a &&&  ~~~c)) + 2 * (c ^^^  ~~~(a |||  ~~~b)) + 4 * (c ||| (a &&&  ~~~b)) + 4 *  ~~~(a ^^^ ( ~~~b ||| c)) - 1 * ((a &&& b) ^^^ (b ||| c)) - 3 * (b ^^^  ~~~( ~~~a ||| (b ^^^ c))) - 16 *  ~~~(a ||| (b ||| c)) - 8 *  ~~~(a ||| ( ~~~b ||| c)) - 1 *  ~~~( ~~~a ||| (b ||| c)) - 14 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 20 * ( ~~~a &&& ( ~~~b &&& c)) + 2 * ( ~~~a &&& (b &&& c)) - 21 * (a &&& (b &&& c)) = 22 * (a &&& ( ~~~b &&& c))

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

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

theorem Std.HashMap.keys_nodup [BEq K] [LawfulBEq K] [Hashable K] (m : Std.HashMap K V) : m.keys.Nodup

theorem zext_negate_thm.extracted_1._1 : ∀ (x : BitVec 1), 0#64 - zeroExtend 64 x = signExtend 64 x

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

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

theorem select1_proof : select1_before ⊑ select1_after

@[simp, simp_denote] theorem nil_isRefinedBy_nil    : (nil : HVector A _) ⊑ (nil : HVector B _)

theorem sdiv400_yes_proof : sdiv400_yes_before ⊑ sdiv400_yes_after

theorem test3_proof : test3_before ⊑ test3_after

theorem select_icmp_x_and_8_ne_0_y_xor_8_proof : select_icmp_x_and_8_ne_0_y_xor_8_before ⊑ select_icmp_x_and_8_ne_0_y_xor_8_after

theorem icmp_ugt_proof : icmp_ugt_before ⊑ icmp_ugt_after

theorem xor_nosignbit_lshr_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬8#32 ≥ ↑32 → (x ^^^ 2147418112#32) >>> 8#32 = x >>> 8#32 ^^^ 8388352#32

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

theorem lshrugt_01_01_exact_proof : lshrugt_01_01_exact_before ⊑ lshrugt_01_01_exact_after

theorem e_1881 :
     - 1 * (a |||  ~~~b) - 1 * (b ^^^ (a ||| (b ^^^ c))) + 5 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) + 4 * ( ~~~a ||| (b ||| c)) - 2 * (b ^^^ (a &&&  ~~~c)) + 1 * (a ||| ( ~~~b ||| c)) + 4 *  ~~~c - 5 *  ~~~(a ||| ( ~~~b &&& c)) - 11 * (c ^^^ (a ||| (b ||| c))) - 3 * (c ^^^ (a ||| (b &&& c))) + 7 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) - 3 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) - 1 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 2 * (b &&&  ~~~(a &&&  ~~~c)) + 7 *  ~~~( ~~~a &&& (b &&& c)) + 1 * (c &&& (a |||  ~~~b)) + 4 * (c ^^^  ~~~(a ||| b)) - 6 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) - 7 * (b ^^^ (a &&& ( ~~~b ||| c))) + 5 *  ~~~(a ^^^ ( ~~~b ||| c)) - 7 * ((a &&& b) ^^^ (b |||  ~~~c)) + 3 *  ~~~(a &&&  ~~~a) + 5 * (a &&&  ~~~c) + 4 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 1 * ( ~~~b &&& (a ^^^ c)) - 5 * (b ^^^ (a &&& (b ^^^ c))) + 2 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 4 * (c |||  ~~~(a ||| b)) + 2 * ( ~~~(a &&& b) &&&  ~~~(b ^^^ c)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) - 2 *  ~~~(a ^^^ (b ||| c)) - 7 * ((a &&& c) |||  ~~~(b ||| c)) + 1 * (c |||  ~~~(a |||  ~~~b)) - 11 * ( ~~~c ||| (a ^^^ b)) - 1 * (b ^^^  ~~~(a |||  ~~~c)) - 2 * (c ^^^  ~~~(a ||| (b &&& c))) + 11 * (a &&& ( ~~~b ||| c)) + 1 * (b &&&  ~~~c) - 1 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) - 1 *  ~~~(a &&& ( ~~~b ||| c)) + 1 *  ~~~(a ||| (b ||| c)) + 29 *  ~~~(a ||| ( ~~~b ||| c)) - 3 *  ~~~( ~~~a ||| (b ||| c)) + 4 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 19 * ( ~~~a &&& ( ~~~b &&& c)) + 29 * ( ~~~a &&& (b &&& c)) - 14 * (a &&& ( ~~~b &&& c)) - 19 * (a &&& (b &&& c)) =  - 2 * ( ~~~a ||| ( ~~~b ||| c))

theorem eval_fsmTermSle_eq_decide_sle {wcard tcard bcard : Nat}
    (tctx : Term.Ctx wcard tcard)
    {wenv : WidthExpr.Env wcard}
    (tenv : tctx.Env wenv)
    (benv : Term.BoolEnv bcard)
    (nenv : Term.NatEnv ncard)
    (ienv : Term.IntEnv icard)
    (w : WidthExpr wcard)
    (wfsm : NatFSM wcard tcard bcard ncard icard pcard (.ofDep w))
    (hwfsm : HNatFSMToBitstream wfsm)
    (a : Term bcard ncard icard pcard tctx (.bv w))
    (b : Term bcard ncard icard pcard tctx (.bv w))
    (afsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm a))
    (hafsm : HTermFSMToBitStream afsm)
    (bfsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm b))
    (hbfsm : HTermFSMToBitStream bfsm)
    (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream)
    (henv : HTermEnv fsmEnv tenv benv)
    :
    ((fsmTermSle
      wfsm
      afsm
      bfsm)).eval fsmEnv i =
       decide (((a.toBV benv nenv ienv penv tenv).signExtend i).sle
       ((b.toBV benv nenv ienv penv tenv).signExtend i))

@[simp] theorem one_eq  : one i = (i == 0)

theorem ashr_lshr_cst_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x <ₛ 1#32) = 1#1 → ¬(True ∧ x >>> 8#32 <<< 8#32 ≠ x ∨ 8#32 ≥ ↑32) → 8#32 ≥ ↑32 → False

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

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 ashrsgt_02_03_exact_proof : ashrsgt_02_03_exact_before ⊑ ashrsgt_02_03_exact_after

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

theorem test3_thm.extracted_1._2 : ∀ (x : BitVec 1) (x_1 : BitVec 59),
  ¬x = 1#1 → ¬4096#59 = 0 → x_1 % 4096#59 = x_1 &&& 4095#59

theorem test_mul_nsw__all_are_safe_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 255#32 == 17#32) = 1#1 →
    True ∧ (x &&& 255#32).smulOverflow 9#32 = true ∨ True ∧ (x &&& 255#32).umulOverflow 9#32 = true → False

theorem test94_thm.extracted_1._1 : ∀ (x : BitVec 32),
  signExtend 64 (signExtend 8 (ofBool (x == BitVec.ofInt 32 (-2))) ^^^ -1#8) =
    signExtend 64 (ofBool (x != BitVec.ofInt 32 (-2)))

theorem select_icmp_eq_and_1_0_or_2_proof : select_icmp_eq_and_1_0_or_2_before ⊑ select_icmp_eq_and_1_0_or_2_after

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

theorem e_1729 :
    2 * ((a ||| b) &&&  ~~~(b ^^^ c)) - 1 * (b ^^^ (a &&&  ~~~c)) + 7 *  ~~~(b &&& c) - 1 * ((a &&& b) ^^^ (b |||  ~~~c)) - 1 *  ~~~(a &&&  ~~~b) - 1 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) + 3 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 3 * (b &&&  ~~~(a &&&  ~~~c)) + 1 * (b &&&  ~~~(a ^^^ c)) - 6 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 2 *  ~~~(a |||  ~~~c) - 1 *  ~~~( ~~~a &&& ( ~~~b &&& c)) + 1 * ( ~~~a &&& ( ~~~b ||| c)) + 11 * (a &&& b) + 7 *  ~~~(a ||| b) - 2 * (a ^^^ (b ^^^ c)) + 7 * (a ||| (b &&& c)) - 3 *  ~~~( ~~~a &&& (b &&& c)) + 3 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 4 * (a ||| b) + 11 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 5 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) + 1 *  ~~~(a &&& ( ~~~b ||| c)) - 13 *  ~~~(a ||| (b ||| c)) - 13 *  ~~~(a ||| ( ~~~b ||| c)) - 32 *  ~~~( ~~~a ||| (b ||| c)) - 17 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 14 * ( ~~~a &&& ( ~~~b &&& c)) - 16 * ( ~~~a &&& (b &&& c)) - 32 * (a &&& ( ~~~b &&& c)) - 25 * (a &&& (b &&& c)) =  - 4 * (b ^^^ (a ||| c))

theorem exact_lshr_ne_both_equal_proof : exact_lshr_ne_both_equal_before ⊑ exact_lshr_ne_both_equal_after

theorem trunc_nuw_xor_proof : trunc_nuw_xor_before ⊑ trunc_nuw_xor_after

theorem sub_ashr_or_i16_thm (e e_1 : IntW 16) :
  LLVM.or (ashr (sub e_1 e { «nsw» := true, «nuw» := false }) (const? 16 15)) e ⊑
    select (icmp IntPred.slt e_1 e) (const? 16 (-1)) e

theorem masked_or_A_proof : masked_or_A_before ⊑ masked_or_A_after

theorem sle_smax1_thm (e e_1 : IntW 32) :
  icmp IntPred.sle (select (icmp IntPred.sgt e_1 e) e_1 e) e_1 ⊑ icmp IntPred.sle e e_1

theorem test7_thm (e : IntW 1024) :
  add (LLVM.xor e (shl (const? 1024 1) (const? 1024 1023))) (shl (const? 1024 1) (const? 1024 1023)) ⊑ e

theorem trunc_nsw_xor_proof : trunc_nsw_xor_before ⊑ trunc_nsw_xor_after

theorem zext_shl_thm (e : IntW 8) :
  LLVM.and (shl (zext 16 e) (const? 16 3)) (zext 16 e) ⊑ zext 16 (LLVM.and (shl e (const? 8 3)) e)

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

theorem main3_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 7#32 == 0#32) &&& ofBool (x &&& 48#32 == 0#32) = 1#1 →
    1#32 = zeroExtend 32 (ofBool (x &&& 55#32 != 0#32))

theorem and_add_bool_to_select_multi_use_proof : and_add_bool_to_select_multi_use_before ⊑ and_add_bool_to_select_multi_use_after

theorem test6_proof : test6_before ⊑ test6_after

@[simp]
theorem BitVec.intCast_eq_ofInt : ((i : Int) : BitVec w) = BitVec.ofInt w i

theorem sdiv_icmp4_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(True ∧ x.smod (BitVec.ofInt 64 (-5)) ≠ 0 ∨
        (BitVec.ofInt 64 (-5) == 0 || 64 != 1 && x == intMin 64 && BitVec.ofInt 64 (-5) == -1) = true) →
    ofBool (x.sdiv (BitVec.ofInt 64 (-5)) == 0#64) = ofBool (x == 0#64)

theorem shl_and_proof : shl_and_before ⊑ shl_and_after

theorem different_size_sext_sext_eq_proof : different_size_sext_sext_eq_before ⊑ different_size_sext_sext_eq_after

theorem scalar_i32_shl_and_negC_ne_proof : scalar_i32_shl_and_negC_ne_before ⊑ scalar_i32_shl_and_negC_ne_after

theorem sdiv_icmp3_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(True ∧ x.smod 5#64 ≠ 0 ∨ (5#64 == 0 || 64 != 1 && x == intMin 64 && 5#64 == -1) = true) →
    ofBool (x.sdiv 5#64 == -1#64) = ofBool (x == BitVec.ofInt 64 (-5))

theorem icmp_slt_0_or_icmp_sge_100_i32_proof : icmp_slt_0_or_icmp_sge_100_i32_before ⊑ icmp_slt_0_or_icmp_sge_100_i32_after

theorem and_not_or_commute9_proof : and_not_or_commute9_before ⊑ and_not_or_commute9_after

theorem and_or3_commuted_proof : and_or3_commuted_before ⊑ and_or3_commuted_after

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

theorem test14_thm.extracted_1._1 : ∀ (x : BitVec 35),
  ¬(4#35 ≥ ↑35 ∨ 4#35 ≥ ↑35) → True ∧ (x &&& BitVec.ofInt 35 (-19760) &&& 19744#35 != 0) = true → False

theorem e_1016 :
    1 *  ~~~t + 2 * t + 1 *  ~~~(z ^^^ t) - 7 * (z ^^^ t) - 1 * z - 2 *  ~~~(z ||| t) + 5 *  ~~~(z |||  ~~~t) = 2 * (z &&& t) - 7 * (z &&&  ~~~t)

theorem ashr_sel_op1_thm (e : IntW 1) :
  ashr (const? 32 (-2)) (select e (const? 32 2) (const? 32 0)) ⊑ select e (const? 32 (-1)) (const? 32 (-2))

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

theorem test_sub_4_Y_ne_4_proof : test_sub_4_Y_ne_4_before ⊑ test_sub_4_Y_ne_4_after

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

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

theorem shl_lshr_demand3_proof : shl_lshr_demand3_before ⊑ shl_lshr_demand3_after

theorem test2_thm (e : IntW 1005) : LLVM.xor e (const? 1005 0) ⊑ e

theorem ugt_and_min_commute_proof : ugt_and_min_commute_before ⊑ ugt_and_min_commute_after

theorem ashr_ugt_12_thm (e : IntW 4) :
  icmp IntPred.ugt (ashr e (const? 4 1)) (const? 4 (-4)) ⊑ icmp IntPred.ugt e (const? 4 (-7))

theorem p1_ugt_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (65534#32 <ᵤ x_1) = 1#1 → ofBool (x_1 <ᵤ 65535#32) = 1#1 → x = 65535#32

theorem urem_common_divisor_proof : urem_common_divisor_before ⊑ urem_common_divisor_after

theorem lshr_and_proof : lshr_and_before ⊑ lshr_and_after

theorem select_icmp_ne_0_and_32_and_not_4096_proof : select_icmp_ne_0_and_32_and_not_4096_before ⊑ select_icmp_ne_0_and_32_and_not_4096_after

theorem ashrslt_01_08_proof : ashrslt_01_08_before ⊑ ashrslt_01_08_after

theorem sub_from_variable_of_sub_from_constant_thm (e e_1 : IntW 8) : sub e_1 (sub (const? 8 42) e) ⊑ add (add e (const? 8 (-42))) e_1

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

theorem eq_commuted_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(x == 0 || 8 != 1 && 43#8 == intMin 8 && x == -1) = true →
    ofBool (x_1 == 0#8) ||

theorem zero_sign_bit_proof : zero_sign_bit_before ⊑ zero_sign_bit_after

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

@[simp] theorem not_impure_le_pure : ¬(impure ≤ pure)

theorem uge_or_not_max_proof : uge_or_not_max_before ⊑ uge_or_not_max_after

theorem test29_proof : test29_before ⊑ test29_after

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

theorem mul_unkV_oddC_eq_thm.extracted_1._1 : ∀ (x : BitVec 32), ofBool (x * 3#32 == 0#32) = ofBool (x == 0#32)

theorem masked_icmps_bmask_notmixed_and_expected_false_proof : masked_icmps_bmask_notmixed_and_expected_false_before ⊑ masked_icmps_bmask_notmixed_and_expected_false_after

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

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

theorem zext_add_thm (e : IntW 8) :
  LLVM.and (add (zext 16 e) (const? 16 44)) (zext 16 e) ⊑ zext 16 (LLVM.and (add e (const? 8 44)) e)

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

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

@[simp]
theorem castLe_eq_self {α : Type _} {n : Nat} (i : Inputs α n) (h : n ≤ n) :
    i.castLe h = i

theorem n6_proof : n6_before ⊑ n6_after

theorem PR42691_10_proof : PR42691_10_before ⊑ PR42691_10_after

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

theorem testi16i8_ne_com_thm (e : IntW 16) :
  icmp IntPred.ne (trunc 8 (lshr e (const? 16 8))) (ashr (trunc 8 e) (const? 8 7)) ⊑
    icmp IntPred.ult (add e (const? 16 (-128))) (const? 16 (-256))

theorem e_814 :
    7 * (z ||| t) - 7 *  ~~~(z ||| t) - 13 *  ~~~(z |||  ~~~t) - 6 * (z &&&  ~~~t) - 14 * (z &&& t) = 1 * (z ^^^ t) - 7 *  ~~~(z &&&  ~~~t)

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

@[simp] theorem lt_length (v : Γ.Var t) : v.1 < Γ.length

theorem main5e_like_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 &&& x_1 == x_2) &&& ofBool (x_2 &&& x == x_2) = 1#1 →
    0#32 = zeroExtend 32 (ofBool (x_2 &&& (x_1 &&& x) != x_2))

theorem sext_zext_nneg_uge_op0_wide_proof : sext_zext_nneg_uge_op0_wide_before ⊑ sext_zext_nneg_uge_op0_wide_after

theorem e_1581 :
     - 11 *  ~~~(a &&&  ~~~a) - 7 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) + 1 *  ~~~(a ||| (b &&& c)) - 3 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 11 *  ~~~(a ^^^ c) - 7 * (c ^^^  ~~~(a &&&  ~~~b)) - 1 *  ~~~(a |||  ~~~c) - 5 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 1 * (b ^^^  ~~~(a ||| (b &&& c))) - 1 * ((a &&& b) |||  ~~~(b ^^^ c)) + 36 *  ~~~(a ||| (b ||| c)) + 33 *  ~~~(a ||| ( ~~~b ||| c)) + 27 *  ~~~( ~~~a ||| (b ||| c)) + 21 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 30 * ( ~~~a &&& ( ~~~b &&& c)) + 29 * (a &&& ( ~~~b &&& c)) + 39 * (a &&& (b &&& c)) = 5 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) - 25 * ( ~~~a &&& (b &&& c))

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

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

theorem e_1514 :
     - 3 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 1 * (b ^^^ (a ||| ( ~~~b ||| c))) + 11 * (c ^^^ (a |||  ~~~b)) - 12 *  ~~~(a ||| (b ||| c)) - 1 *  ~~~(a ||| ( ~~~b ||| c)) - 9 *  ~~~( ~~~a ||| (b ||| c)) + 10 * ( ~~~a &&& ( ~~~b &&& c)) + 3 * ( ~~~a &&& (b &&& c)) + 2 * (a &&& ( ~~~b &&& c)) + 11 * (a &&& (b &&& c)) = 11 * (b ^^^ ( ~~~a &&& (b ^^^ c)))

@[simp] theorem bv_isRefinedBy_iff (x y : BitVec w) : x ⊑ y ↔ x = y

theorem p0_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x_1 ≥ ↑8 → ofBool (x ≤ᵤ (-1#8) <<< x_1 ^^^ -1#8) = ofBool (x >>> x_1 == 0#8)

theorem shl_or_with_or_disjoint_instead_of_add_proof : shl_or_with_or_disjoint_instead_of_add_before ⊑ shl_or_with_or_disjoint_instead_of_add_after

@[simp]
lemma lift_accepts (M : NFA (BitVec n) σ) (f : Fin n → Fin m) :
    (M.lift f).accepts = BitVecs'.transport f ⁻¹' M.accepts

theorem sext_false_val_must_be_zero_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → signExtend 32 x = 0#32

theorem trunc_shl_ashr_infloop_thm (e : IntW 64) :
  trunc 32 (shl (ashr e (const? 64 3)) (const? 64 2)) ⊑
    LLVM.and (trunc 32 (lshr e (const? 64 1))) (const? 32 (-4))

theorem e_505 :
     - 3 * (x ^^^ y) - 2 *  ~~~(x &&&  ~~~x) - 11 * y - 2 *  ~~~(x &&&  ~~~y) + 3 *  ~~~y + 8 *  ~~~(x ||| y) + 32 *  ~~~(x |||  ~~~y) + 16 * (x &&&  ~~~y) + 22 * (x &&& y) = 7 * (x ||| y) + 7 *  ~~~(x &&& y)

theorem positive_sameconst_shlnsw_lshrexact_proof : positive_sameconst_shlnsw_lshrexact_before ⊑ positive_sameconst_shlnsw_lshrexact_after

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

theorem c_1_0_0_thm (e e_1 e_2 : IntW 4) :
  LLVM.xor (LLVM.and (LLVM.xor e_2 e_1) (LLVM.xor e (const? 4 (-1)))) e_2 ⊑
    LLVM.xor (LLVM.and (LLVM.xor e_2 e_1) e) e_1

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

theorem e_1898 :
     - 1 * ((a &&& b) |||  ~~~(b ^^^ c)) + 2 * (b ^^^ ( ~~~a ||| (b ^^^ c))) + 7 *  ~~~(a &&& (b ^^^ c)) + 3 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 7 * (c ^^^ (a ||| b)) - 5 *  ~~~(a ||| (b ^^^ c)) + 11 * a + 1 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) - 3 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 1 * c - 1 *  ~~~(a ||| ( ~~~b &&& c)) + 5 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c))) + 11 * (b ^^^ ( ~~~a &&& ( ~~~b ||| c))) + 5 *  ~~~(a ^^^ b) + 2 * (c ^^^  ~~~(a &&& (b ||| c))) + 1 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) - 11 * (c &&& (a ^^^ b)) + 4 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) - 5 * ((a &&& c) |||  ~~~(b ||| c)) + 11 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 1 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) + 3 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 1 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) - 6 * ( ~~~b &&&  ~~~(a ^^^ c)) - 1 *  ~~~(a ||| b) + 1 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) - 1 * ( ~~~(a ^^^ b) ||| (a ^^^ c)) + 1 * (a ||| ( ~~~b ||| c)) - 11 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 11 *  ~~~(b &&&  ~~~c) + 2 * (c &&& (a |||  ~~~b)) - 6 * ((a &&& b) |||  ~~~(b ||| c)) - 5 * (c ^^^  ~~~(a &&& (b &&& c))) + 1 * (c ^^^  ~~~(a &&&  ~~~b)) + 1 * (a &&& ( ~~~b ||| c)) + 3 * (c ^^^ (a ||| (b &&& c))) - 7 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) + 4 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 6 * ((b &&&  ~~~c) ^^^ (a ||| (b ^^^ c))) + 4 *  ~~~(a &&& c) + 5 * ( ~~~(a ||| b) |||  ~~~(a ^^^ (b ^^^ c))) - 1 *  ~~~(b ||| c) + 9 *  ~~~(a ||| (b ||| c)) - 39 *  ~~~(a ||| ( ~~~b ||| c)) - 7 *  ~~~( ~~~a ||| (b ||| c)) - 31 * ( ~~~a &&& ( ~~~b &&& c)) + 7 * ( ~~~a &&& (b &&& c)) + 25 * (a &&& ( ~~~b &&& c)) - 4 * (a &&& (b &&& c)) = 50 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 1 * (a ||| (b &&& c))

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

theorem n2_badmask_proof : n2_badmask_before ⊑ n2_badmask_after

theorem xor_lshr_multiuse_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 8),
  ¬(x_2 ≥ ↑8 ∨
        x_2 ≥ ↑8 ∨
          x_2 ≥ ↑8 ∨
            (x_3 >>> x_2 ^^^ x_1 ^^^ x >>> x_2 == 0 ||
                8 != 1 && x_3 >>> x_2 ^^^ x_1 == intMin 8 && x_3 >>> x_2 ^^^ x_1 ^^^ x >>> x_2 == -1) =
              true) →
    x_2 ≥ ↑8 ∨
        x_2 ≥ ↑8 ∨
          ((x_3 ^^^ x) >>> x_2 ^^^ x_1 == 0 ||
              8 != 1 && x_3 >>> x_2 ^^^ x_1 == intMin 8 && (x_3 ^^^ x) >>> x_2 ^^^ x_1 == -1) =
            true →
      False

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

theorem shl_add_proof : shl_add_before ⊑ shl_add_after

theorem shl_xor_xor_no_const_thm (e e_1 e_2 e_3 : IntW 8) :
  LLVM.xor (shl e_3 e_2) (LLVM.xor (shl e_1 e_2) e) ⊑ LLVM.xor (shl (LLVM.xor e_1 e_3) e_2) e

theorem add_shl_same_amount_partial_nuw2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 6),
  ¬(True ∧ x_2 <<< x_1 >>> x_1 ≠ x_2 ∨ x_1 ≥ ↑6 ∨ x_1 ≥ ↑6 ∨ True ∧ (x_2 <<< x_1).uaddOverflow (x <<< x_1) = true) →
    x_1 ≥ ↑6 → False

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

theorem positive_sameconst_proof : positive_sameconst_before ⊑ positive_sameconst_after

theorem masked_bit_set_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x_1 ≥ ↑32 → zeroExtend 32 (ofBool (1#32 <<< x_1 &&& x != 0#32)) = x >>> x_1 &&& 1#32

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

theorem zext_sub_const_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 42#64 - zeroExtend 64 x = 42#64

theorem and_ranges_overlap_single_proof : and_ranges_overlap_single_before ⊑ and_ranges_overlap_single_after

@[simp] theorem Expr.denoteOp_changeVars  :
    (e.changeVars f).denoteOp V = e.denoteOp (V.comap f)

theorem test3_thm (e : IntW 8) :
  icmp IntPred.sge e (const? 8 (-127)) ⊑ icmp IntPred.ne e (const? 8 (-128))

theorem not_shl_proof : not_shl_before ⊑ not_shl_after

theorem test7_proof : test7_before ⊑ test7_after

theorem scf.for.peel_end (n : Nat) (f : Nat → β → β) (seed : β) :
  scf.for.loop f (n + 1) 0 (f n seed) = f n (scf.for.loop f n 0 seed)

theorem test8_thm.extracted_1._1 : ∀ (x : BitVec 7), ¬(4#7 ≥ ↑7 ∨ 3#7 ≥ ↑7) → x <<< 4#7 <<< 3#7 = 0#7

theorem test_sub_nuw_nsw__nsw_is_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x ||| BitVec.ofInt 32 (-2147483648) == BitVec.ofInt 32 (-2147483647)) = 1#1 →
    ¬(True ∧ (BitVec.ofInt 32 (-2147483648)).ssubOverflow (x ||| BitVec.ofInt 32 (-2147483648)) = true) →
      -1#32 = BitVec.ofInt 32 (-2147483648) - (x ||| BitVec.ofInt 32 (-2147483648))

theorem test1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 &&& 65280#32 != x &&& 65280#32) = ofBool ((x_1 ^^^ x) &&& 65280#32 != 0#32)

theorem test_lshr_exact__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 test15_proof : test15_before ⊑ test15_after

theorem foo1_or_signbit_lshr_without_shifting_signbit_proof : foo1_or_signbit_lshr_without_shifting_signbit_before ⊑ foo1_or_signbit_lshr_without_shifting_signbit_after

theorem test_const_shr_and_1_ne_0_proof : test_const_shr_and_1_ne_0_before ⊑ test_const_shr_and_1_ne_0_after

theorem select_constants_and_icmp_eq0_zero_fval_thm.extracted_1._4 : ∀ (x x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬x = 1#1 → ofBool (0#8 &&& 0#8 == 0#8) = 0#1 ^^^ 1#1

theorem lshr_shl_pow2_const_overflow_proof : lshr_shl_pow2_const_overflow_before ⊑ lshr_shl_pow2_const_overflow_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 eq_smax3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x <ₛ x_1 + 3#32) = 1#1 → ofBool (x_1 + 3#32 == x_1 + 3#32) = ofBool (x ≤ₛ x_1 + 3#32)

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

theorem e_2362 :
    2 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) - 5 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) + 3 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) - 2 * (e ^^^ (d ||| (e ^^^ f))) - 11 * ((d &&& e) ||| (e ^^^ f)) + 7 * (d |||  ~~~e) + 4 * (e &&& (d ||| f)) + 11 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 2 * (d &&& f) + 3 * (f ^^^ ( ~~~d &&& (e ||| f))) - 1 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) - 2 *  ~~~(d ||| (e ^^^ f)) + 4 *  ~~~(d &&& e) + 2 * (f ^^^  ~~~(d &&& e)) - 5 * (e ^^^ ( ~~~d ||| (e ^^^ f))) + 1 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 7 *  ~~~(d ^^^ (e ||| f)) - 5 * (f &&& (d ^^^ e)) - 5 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 2 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 5 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 2 *  ~~~(d |||  ~~~e) - 2 *  ~~~(d &&&  ~~~d) - 6 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 1 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) - 7 * ( ~~~e ||| (d ^^^ f)) - 11 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 3 *  ~~~( ~~~d &&& (e &&& f)) + 2 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 *  ~~~(e &&& f) + 5 * ( ~~~f |||  ~~~(d ^^^ e)) + 2 * ( ~~~d ||| (e &&& f)) - 7 * (f &&& (d ||| e)) + 5 * (d &&& (e ^^^ f)) - 11 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) + 2 *  ~~~( ~~~d &&& (e ^^^ f)) + 5 * (f ^^^  ~~~(d ||| e)) + 11 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 3 *  ~~~(d &&& ( ~~~e &&& f)) + 3 * (f ^^^  ~~~(d |||  ~~~e)) + 1 * (e ^^^  ~~~(d ||| (e ^^^ f))) - 2 * ((d &&& e) |||  ~~~(e ||| f)) + 5 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 2 *  ~~~(d ^^^ (e ^^^ f)) - 1 * (f ||| (d ^^^ e)) - 7 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 5 * (e ^^^ (d ||| f)) - 1 *  ~~~(d &&& (e ||| f)) - 11 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) - 1 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 1 * ( ~~~e &&&  ~~~(d ^^^ f)) - 1 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 6 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 6 * (d ||| (e &&& f)) + 4 * ((e &&& f) ^^^  ~~~(d &&& (e ^^^ f))) + 2 * (d ||| e) - 1 *  ~~~(d ||| ( ~~~e &&& f)) + 1 * (f ^^^ (d ||| (e &&& f))) - 2 * (e |||  ~~~(d |||  ~~~f)) + 24 *  ~~~(d ||| (e ||| f)) + 50 *  ~~~(d ||| ( ~~~e ||| f)) + 39 *  ~~~( ~~~d ||| (e ||| f)) + 34 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 22 * ( ~~~d &&& ( ~~~e &&& f)) + 26 * ( ~~~d &&& (e &&& f)) + 56 * (d &&& ( ~~~e &&& f)) + 45 * (d &&& (e &&& f)) =  - 1 * (f ^^^ (d ||| (e ||| f))) + 7 * ((d ||| e) &&& (e ^^^ f))

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

theorem test_and_ne_a_b_commuted_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  x_2 &&& ofBool (x_1 != x) = 1#1 → ¬x_2 = 1#1 → x = x_1

theorem zext_zext_eq_proof : zext_zext_eq_before ⊑ zext_zext_eq_after

theorem test40_proof : test40_before ⊑ test40_after

theorem main3c_proof : main3c_before ⊑ main3c_after

theorem ashrslt_02_14_proof : ashrslt_02_14_before ⊑ ashrslt_02_14_after

theorem test13_thm (e : IntW 1024) :
  LLVM.and (ashr e (const? 1024 1016)) (const? 1024 255) ⊑ lshr e (const? 1024 1016)

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

theorem shl_lshr_pow2_const_case2_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 3#16 ≥ ↑16) → ofBool (x == 2#16) = 1#1 → 16#16 <<< x >>> 3#16 &&& 8#16 = 8#16

theorem p1_scalar_urem_by_nonconst_proof : p1_scalar_urem_by_nonconst_before ⊑ p1_scalar_urem_by_nonconst_after

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

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

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 lshrult_02_07_thm.extracted_1._1 : ∀ (x : BitVec 4), ¬2#4 ≥ ↑4 → ofBool (x >>> 2#4 <ᵤ 7#4) = 1#1

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

@[simp]
theorem f_eq_zero : (f q n) = (0 : R q n)

theorem ashr_exact_thm (e : IntW 8) (e_1 : IntW 1) :
  ashr (select e_1 e (const? 8 16)) (const? 8 3) { «exact» := true } ⊑
    select e_1 (ashr e (const? 8 3) { «exact» := true }) (const? 8 2)

theorem and_or_not_not_proof : and_or_not_not_before ⊑ and_or_not_not_after

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

theorem ashr_can_be_lshr_2_proof : ashr_can_be_lshr_2_before ⊑ ashr_can_be_lshr_2_after

theorem test_sub_nuw__nuw_is_safe_proof : test_sub_nuw__nuw_is_safe_before ⊑ test_sub_nuw__nuw_is_safe_after

theorem alive_276_2  (w : Nat)   : alive_276_2_src w  ⊑ alive_276_2_tgt w

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

theorem test_nuw_nsw_and_unsigned_pred_thm (e : IntW 64) :
  icmp IntPred.ule (sub (const? 64 10) e { «nsw» := true, «nuw» := true }) (const? 64 3) ⊑
    icmp IntPred.ugt e (const? 64 6)

theorem sext_diff_i1_xor_sub_1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1),
  ¬(True ∧ (zeroExtend 64 x).saddOverflow (signExtend 64 x_1) = true) →
    signExtend 64 x_1 - signExtend 64 x = zeroExtend 64 x + signExtend 64 x_1

theorem PR23309_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ (x_1 + BitVec.ofInt 32 (-4)).ssubOverflow x = true) →
    truncate 1 (x_1 + BitVec.ofInt 32 (-4) - x) = truncate 1 (x_1 - x)

theorem reassoc_sub_nuw_proof : reassoc_sub_nuw_before ⊑ reassoc_sub_nuw_after

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

theorem e_1533 :
    4 * (c ^^^  ~~~(a ||| (b &&& c))) - 6 * (b ^^^ c) - 3 *  ~~~(a &&& (b ||| c)) - 5 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 9 *  ~~~(a ||| (b ||| c)) + 15 *  ~~~(a ||| ( ~~~b ||| c)) + 8 *  ~~~( ~~~a ||| (b ||| c)) + 11 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 14 * ( ~~~a &&& ( ~~~b &&& c)) - 1 * ( ~~~a &&& (b &&& c)) + 2 * (a &&& ( ~~~b &&& c)) - 4 * (a &&& (b &&& c)) = 5 *  ~~~(a ||| c)

theorem andn_or_cmp_2_partial_logical_proof : andn_or_cmp_2_partial_logical_before ⊑ andn_or_cmp_2_partial_logical_after

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

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

theorem e_1972 :
    1 * (b |||  ~~~c) + 2 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 7 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) + 2 * (a &&& c) - 2 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 1 * ((a ^^^ b) ||| (a ^^^ c)) + 4 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) + 1 * (c ^^^ (a |||  ~~~b)) - 3 * (a ||| b) + 4 * (b ^^^  ~~~(a &&& c)) - 2 * (c ^^^ (a ||| (b ||| c))) - 11 * (c ||| (a ^^^ b)) + 7 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 2 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) - 1 * (c ^^^  ~~~(a ||| (b &&& c))) - 11 *  ~~~(a &&&  ~~~b) - 1 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 7 * (c ^^^ (a ||| ( ~~~b &&& c))) - 6 *  ~~~(a &&& c) + 1 * (c ^^^ (a &&& (b ||| c))) + 2 *  ~~~(a &&& ( ~~~b ||| c)) - 1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) - 7 * (c ^^^ ( ~~~a &&& (b ||| c))) - 11 * (a |||  ~~~c) + 5 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 1 *  ~~~(a ||| (b ^^^ c)) + 5 *  ~~~(a |||  ~~~c) - 6 * (a ||| (b ^^^ c)) + 1 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) - 7 *  ~~~(a &&&  ~~~c) + 3 *  ~~~(a ||| (b &&& c)) + 2 * ( ~~~c ||| (a ^^^ b)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * (c |||  ~~~(a ^^^ b)) - 1 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) - 6 * (a ||| ( ~~~b &&& c)) - 1 * (a &&&  ~~~c) + 4 *  ~~~(a ||| ( ~~~b &&& c)) - 11 * ((a &&& c) ^^^ (b ||| c)) - 5 * (b ^^^ ( ~~~a ||| (b &&& c))) + 1 * ((a |||  ~~~b) &&& (b ^^^ c)) + 1 * (a &&& ( ~~~b ||| c)) + 7 * (c ^^^  ~~~(a |||  ~~~b)) - 5 * (a ^^^ c) + 3 *  ~~~(a ^^^ c) + 3 * ( ~~~b ||| (a ^^^ c)) + 3 * (c &&&  ~~~(a ^^^ b)) + 1 *  ~~~(b ||| c) + 1 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) + 6 *  ~~~(a ||| (b ||| c)) + 45 *  ~~~(a ||| ( ~~~b ||| c)) + 28 *  ~~~( ~~~a ||| (b ||| c)) + 41 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 43 * ( ~~~a &&& ( ~~~b &&& c)) + 29 * (a &&& ( ~~~b &&& c)) + 46 * (a &&& (b &&& c)) =  - 15 * ( ~~~a &&& (b &&& c))

theorem rem_euclid_1_proof : rem_euclid_1_before ⊑ rem_euclid_1_after

theorem or_or_logic_and_1_proof : or_or_logic_and_1_before ⊑ or_or_logic_and_1_after

theorem sext_zext_ult_known_nonneg_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬6#8 ≥ ↑8 → ofBool (signExtend 32 x_1 <ᵤ zeroExtend 32 (x >>> 6#8)) = ofBool (x_1 <ᵤ x >>> 6#8)

theorem or_eq_with_diff_one_signed_logical_thm (e : IntW 32) :
  select (icmp IntPred.eq e (const? 32 0)) (const? 1 1) (icmp IntPred.eq e (const? 32 (-1))) ⊑
    icmp IntPred.ult (add e (const? 32 1)) (const? 32 2)

theorem not_lshr_proof : not_lshr_before ⊑ not_lshr_after

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

theorem not_invert_signbit_splat_mask1_proof : not_invert_signbit_splat_mask1_before ⊑ not_invert_signbit_splat_mask1_after

theorem main7e_logical_thm.extracted_1._7 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ¬ofBool (x_3 &&& x_2 &&& x_1 == x_3 &&& x_2) = 1#1 →
    ¬ofBool (x_3 &&& x_2 &&& x_1 != x_3 &&& x_2) = 1#1 → 0#1 = 1#1 → False

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

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

theorem sub_to_and_and_commuted_proof : sub_to_and_and_commuted_before ⊑ sub_to_and_and_commuted_after

theorem not_cond_proof : not_cond_before ⊑ not_cond_after

theorem reduce_xor_common_op_commute0_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 4),
  x_2 ^^^ x_1 ^^^ x ||

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

theorem test_and4_proof : test_and4_before ⊑ test_and4_after

theorem bools_multi_uses2_logical_thm.extracted_1._30 : ∀ (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

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

theorem positive_trunc_base_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (-1#16 <ₛ truncate 16 x) = 1#1 → ofBool (truncate 16 x + 128#16 <ᵤ 256#16) = ofBool (x &&& 65408#32 == 0#32)

@[simp]
theorem delta_eq_carryWith_one (carryState : p.α → Bool) (x : arity → BitStream) :
    p.delta carryState x = p.carryWith carryState x 1

theorem test11_proof : test11_before ⊑ test11_after
</all_available_lemmas>

<local_ctx>
import Mathlib.Data.Fintype.Basic

import LeanMLIR.HVector

class TyDenote (β : Type) : Type 1 where
  toType : β → Type

notation "⟦" x "⟧" => TyDenote.toType x

structure Ctxt (Ty : Type) : Type where
  ofList :: toList : List Ty
  
  deriving Repr, Lean.ToExpr, DecidableEq

variable {Ty : Type} {Γ Δ : Ctxt Ty}

namespace Ctxt

section Instances

open Lean in

end Instances

@[match_pattern]
def cons (hd : Ty) : Ctxt Ty → Ctxt Ty
| ⟨tl⟩ => ⟨hd :: tl⟩

section GetElemLemmas

end GetElemLemmas

section Lemmas

variable (Γ : Ctxt Ty) (ts us : List Ty)

variable {m} [Monad m] [LawfulMonad m] (t u : m _) in

section Lemmas

variable {Γ Δ : Ctxt Ty} {tys : List Ty}

end Lemmas

end Lemmas

section Rec

end Rec

def Var (Γ : Ctxt Ty) (t : Ty) : Type :=
  { i : Nat // Γ[i]? = some t }

namespace Var

section Lemmas

variable {Γ : Ctxt Ty} {t : Ty}

end Lemmas

section Lemmas

variable {t} (v : Var Γ t)

end Lemmas

section Lemmas

variable {t : Ty} {v : Γ.Var t}

end Lemmas

section Lemmas

end Lemmas

end Var

end Ctxt

open Ctxt

namespace HVector

variable {A : α → _} {as : List α} (xs : HVector A as) {Γ : Ctxt α}

end HVector

namespace Ctxt

section Comp

variable {Γ Δ Ξ : Ctxt Ty} (f : Hom Γ Δ) (g : Hom Δ Ξ)

end Comp

section Lemmas

end Lemmas

variable {Γ Δ Δ' : Ctxt Ty} in

section Valuation

variable [TyDenote Ty]

def Valuation (Γ : Ctxt Ty) : Type :=
  ⦃t : Ty⦄ → Γ.Var t → (toType t)

def Valuation.nil : Ctxt.Valuation (∅ : Ctxt Ty) := fun _ v => v.emptyElim

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

variable {m} [Monad m] [LawfulMonad m] in

variable {V : Γ.Valuation} {W : Δ.Valuation}

@[simp]
instance Valuation.instAppendHVector (Γ : Ctxt Ty) (ts : List Ty) :
    HAppend (HVector toType ts) (Valuation Γ) (Valuation <| ⟨ts⟩ ++ Γ) where
  hAppend vals V :=
    (Valuation.ofHVector vals) ++ V

section Lemmas

variable {ts : List Ty}

end Lemmas

def Valuation.reassignVars [DecidableEq Ty] {ts : List Ty} {Γ : Ctxt Ty}
    (V : Γ.Valuation) (var : HVector Γ.Var ts) (val : HVector toType ts) : Γ.Valuation :=
  fun _ vneedle =>
    match var.idxOf? vneedle with
    | none => V vneedle
    | some ⟨i, h⟩ => h ▸ val.get i
</local_ctx>

<target_theorem>
@[simp] theorem Valuation.reassignVars_eq [DecidableEq Ty] (V : Γ.Valuation) :
    V.reassignVars vs (vs.map V) = V :=
</target_theorem>

