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
decidable_of_iff in Init.PropLemmas
String in Init.Prelude
Nat in Init.Prelude
Valuation.mk in Mathlib.RingTheory.Valuation.Basic
List.map in Init.Prelude
Option in Init.Prelude
id in Init.Prelude
PUnit in Init.Prelude
Function.comp in Init.Prelude
Subtype in Init.Prelude
List.length in Init.Prelude
Lean.Parser.Term.matchAlts in Lean.Parser.Term
bool in Init.Control.Basic
Id in Init.Control.Id
Inhabited in Init.Prelude
Stream' in Mathlib.Data.Stream.Defs

structure Ctxt (Ty : Type) : Type where
  ofList :: toList : List Ty
  
  deriving Repr, Lean.ToExpr, DecidableEq

inductive EffectKind
| pure 
| impure 
deriving Repr, DecidableEq, Lean.ToExpr

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

def Valuation.nil : Ctxt.Valuation (∅ : Ctxt Ty) := fun _ v => v.emptyElim

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

def Var (Γ : Ctxt Ty) (t : Ty) : Type :=
  { i : Nat // Γ[i]? = some t }

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

abbrev Hom (Γ Γ' : Ctxt Ty) := ⦃t : Ty⦄ → Γ.Var t → Γ'.Var t

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

@[elab_as_elim]
def appendCases
    {motive : (Γ ++ Δ).Var t → Sort u}
    (left : (v : Var Γ t) → motive (appendInl v))
    (right : (v : Var Δ t) → motive (appendInr v)) :
    (v : (Γ ++ Δ).Var t) → motive v
  | ⟨idx, h⟩ =>
    if hv : idx < Γ.length then
      left ⟨idx, by admit /- proof elided -/
      ⟩
    else
      let v' : Var _ _ := ⟨idx - Γ.length, by admit /- proof elided -/
      ⟩
      have eq : v'.appendInr = ⟨idx, h⟩ := by admit /- proof elided -/

def Hom.castCodomain (h : Δ = Δ') (f : Γ.Hom Δ) : Γ.Hom Δ' :=
  fun _t v => (f v).castCtxt h

def appendInl (v : Γ.Var t) : (Γ ++ Δ).Var t :=
  ⟨v.val, by admit /- proof elided -/
  ⟩

def Valuation.cast {Γ Δ : Ctxt Ty} (h : Γ = Δ) (V : Valuation Γ) : Valuation Δ :=
  fun _ v => V <| v.castCtxt h.symm

abbrev dropUntilHom : Hom (Γ.dropUntil v) Γ := dropUntilDiff.toHom

def dropUntilDiff : Diff (Γ.dropUntil v) Γ :=
  ⟨v.val+1, by admit /- proof elided -/
  ⟩

def emptyElim {α : Sort _} {t : Ty} : Ctxt.Var ∅ t → α :=
  fun ⟨_, h⟩ => by admit /- proof elided -/

@[match_pattern]
def cons (hd : Ty) : Ctxt Ty → Ctxt Ty
| ⟨tl⟩ => ⟨hd :: tl⟩

def Diff (Γ₁ Γ₂ : Ctxt Ty) : Type :=
  {d : Nat // Diff.Valid Γ₁ Γ₂ d}

@[simp]
abbrev Diff.Valid (Γ₁ Γ₂ : Ctxt Ty) (d : Nat) : Prop :=
  ∀ {i t}, Γ₁[i]? = some t → Γ₂[i+d]? = some t

@[simp] abbrev Hom.id {Γ : Ctxt Ty} : Γ.Hom Γ :=
  fun _ v => v

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

@[grind=]
def length (Γ : Ctxt Ty) : Nat := Γ.toList.length

instance : DialectSignature $dialect where
        signature := fun op => match op with $matchAlts:matchAlts
    )

noncomputable instance (q : ℕ) [Fact (q > 1)] : DialectDenote (ModArith q) where
denote
  | .add, arg, _ =>
      
      (fun args : R q × R q => args.1 + args.2) arg.toPair
  | .sub, arg, _ =>
      
      (fun args : R q × R q => args.1 - args.2) arg.toPair
  | .mul, arg, _ =>
      
      (fun args : R q × R q => args.1 * args.2) arg.toPair
  | .const _ c, _, _ =>
      
      c

@[simp, reducible]
def Op.signature : Op q n → Signature (Ty q n) :=
  fun o => {sig := Op.sig o, returnTypes := [Op.outTy o], regSig := []}

@[simp, reducible]
def Op.sig : Op q n → List (Ty q n)
| Op.add => [Ty.polynomialLike, Ty.polynomialLike]
| Op.sub => [Ty.polynomialLike, Ty.polynomialLike]
| Op.mul => [Ty.polynomialLike, Ty.polynomialLike]
| Op.mul_constant => [Ty.polynomialLike, Ty.integer]
| Op.leading_term => [Ty.polynomialLike]
| Op.monomial => [Ty.integer, Ty.index]
| Op.monomial_mul => [Ty.polynomialLike, Ty.index]
| Op.from_tensor => [Ty.tensor]
| Op.to_tensor => [Ty.polynomialLike]
| Op.const _ => []
| Op.const_int _ => []
| Op.const_idx _ => []

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

@[simp, reducible]
def Op.outTy : Op q n → Ty q n
| Op.add | Op.sub | Op.mul | Op.mul_constant | Op.leading_term | Op.monomial
| Op.monomial_mul | Op.from_tensor | Op.const _  => Ty.polynomialLike
| Op.to_tensor => Ty.tensor
| Op.const_int _ => Ty.integer
| Op.const_idx _ => Ty.index

@[reducible, simp]
def Op.regSig : Op → RegionSignature Ty
  | .map2d => [([Ty.int], [.int])]
  | _ => []

instance : DialectSignature Ex where
  signature
    | .add    => ⟨[.nat, .nat], [], [.nat], .pure⟩
    | .beq    => ⟨[.nat, .nat], [], [.bool], .pure⟩
    | .cst _  => ⟨[], [], [.nat], .pure⟩

inductive ExOp :  Type
  | add : ExOp
  | beq : ExOp
  | cst : ℕ → ExOp
  deriving DecidableEq

inductive ExTy
  | nat
  | bool
  deriving DecidableEq

def add {Γ : Ctxt _} (e₁ e₂ : Ctxt.Var Γ .nat) : Expr Ex Γ .pure [.nat] :=
  Expr.mk
    (op := .add)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons e₁ <| .cons e₂ .nil)
    (regArgs := .nil)

abbrev Ex : Dialect where
  Op := ExOp
  Ty := ExTy

def cst {Γ : Ctxt _} (n : ℕ) : Expr Ex Γ .pure [.nat]  :=
  Expr.mk
    (op := .cst n)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .nil)
    (regArgs := .nil)

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

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

@[reducible]
instance : DialectSignature Tensor2D where
  signature op := { sig := op.sig, regSig := op.regSig, returnTypes := [op.outTy] }

instance : DialectSignature Tensor1D where
  signature op := { sig := op.sig, regSig := op.regSig, returnTypes := [op.outTy], effectKind := .pure }

instance : DialectSignature RV64 where
  signature o := {sig := Op.sig o, returnTypes := [Op.outTy o], regSig := []}

@[simp, reducible]
def Op.sig : Op → List Ty
  | .li _ => []
  | .mulh  => [Ty.bv, Ty.bv]
  | .mulhu  => [Ty.bv, Ty.bv]
  | .mulhsu  => [Ty.bv, Ty.bv]
  | .divu =>  [Ty.bv, Ty.bv]
  | .remuw  => [Ty.bv, Ty.bv]
  | .remu  =>  [Ty.bv, Ty.bv]
  | .addiw (_imm : BitVec 12) => [Ty.bv]
  | .lui (_imm : BitVec 20) => [Ty.bv]
  | .auipc (_imm : BitVec 20)  => [Ty.bv]
  | .slliw (_shamt : BitVec 5)  => [Ty.bv]
  | .srliw (_shamt : BitVec 5) => [Ty.bv]
  | .sraiw (_shamt : BitVec 5) => [Ty.bv]
  | .slli (_shamt : BitVec 6) => [Ty.bv]
  | .srli (_shamt : BitVec 6) => [Ty.bv]
  | .srai (_shamt : BitVec 6) => [Ty.bv]
  | .addw => [Ty.bv, Ty.bv]
  | .subw => [Ty.bv, Ty.bv]
  | .sllw => [Ty.bv, Ty.bv]
  | .srlw => [Ty.bv, Ty.bv]
  | .sraw => [Ty.bv, Ty.bv]
  | .add => [Ty.bv, Ty.bv]
  | .slt => [Ty.bv, Ty.bv]
  | .sltu => [Ty.bv, Ty.bv]
  | .and => [Ty.bv, Ty.bv]
  | .or => [Ty.bv, Ty.bv]
  | .xor => [Ty.bv, Ty.bv]
  | .sll => [Ty.bv, Ty.bv]
  | .srl => [Ty.bv, Ty.bv]
  | .sub => [Ty.bv, Ty.bv]
  | .sra => [Ty.bv, Ty.bv]
  | .remw  => [Ty.bv, Ty.bv]
  | .rem  =>  [Ty.bv, Ty.bv]
  | .mul => [Ty.bv, Ty.bv]
  | .mulw => [Ty.bv, Ty.bv]
  | .div  =>  [Ty.bv, Ty.bv]
  | .divw  =>  [Ty.bv, Ty.bv]
  | .divuw  =>  [Ty.bv, Ty.bv]
  | .addi (_imm : BitVec 12) => [Ty.bv]
  | .slti (_imm : BitVec 12) => [Ty.bv]
  | .sltiu (_imm : BitVec 12) => [Ty.bv]
  | .andi (_imm : BitVec 12) => [Ty.bv]
  | .ori (_imm : BitVec 12) => [Ty.bv]
  | .xori (_imm : BitVec 12) => [Ty.bv]
  | .bclr => [Ty.bv, Ty.bv]
  | .bext => [Ty.bv, Ty.bv]
  | .binv => [Ty.bv, Ty.bv]
  | .bset  => [Ty.bv, Ty.bv]
  | .bclri (_shamt : BitVec 6) => [Ty.bv]
  | .bexti (_shamt : BitVec 6) => [Ty.bv]
  | .binvi (_shamt : BitVec 6) => [Ty.bv]
  | .bseti (_shamt : BitVec 6) => [Ty.bv]
  | .adduw => [Ty.bv, Ty.bv]
  | .sh1adduw => [Ty.bv, Ty.bv]
  | .sh2adduw => [Ty.bv, Ty.bv]
  | .sh3adduw => [Ty.bv, Ty.bv]
  | .sh1add => [Ty.bv, Ty.bv]
  | .sh2add => [Ty.bv, Ty.bv]
  | .sh3add => [Ty.bv, Ty.bv]
  | .slliuw (_shamt : BitVec 6) => [Ty.bv]
  | .andn => [Ty.bv, Ty.bv]
  | .orn => [Ty.bv, Ty.bv]
  | .xnor => [Ty.bv, Ty.bv]
  | .clz
  | .clzw
  | .ctz
  | .ctzw
  | .max => [Ty.bv, Ty.bv]
  | .maxu => [Ty.bv, Ty.bv]
  | .min  => [Ty.bv, Ty.bv]
  | .minu  => [Ty.bv, Ty.bv]
  | .sextb => [Ty.bv]
  | .sexth => [Ty.bv]
  | .zexth => [Ty.bv]
  | .rol => [Ty.bv, Ty.bv]
  | .rolw => [Ty.bv, Ty.bv]
  | .ror => [Ty.bv, Ty.bv]
  | .rori (_shamt : BitVec 6) =>[Ty.bv]
  | .roriw (_shamt : BitVec 5) =>[Ty.bv]
  | .rorw => [Ty.bv, Ty.bv]
  | .pack => [Ty.bv, Ty.bv]
  | .packh => [Ty.bv, Ty.bv]
  | .packw => [Ty.bv, Ty.bv]
  | .mv => [Ty.bv]
  | .not => [Ty.bv]
  | .neg => [Ty.bv]
  | .negw => [Ty.bv]
  | .sextw => [Ty.bv]
  | .zextb => [Ty.bv]
  | .zextw => [Ty.bv]
  | .seqz => [Ty.bv]
  | .snez => [Ty.bv]
  | .sltz => [Ty.bv]
  | .sgtz => [Ty.bv]

inductive Op
   
  | li : (val : BitVec 64) → Op
  | lui (imm : BitVec 20)
  | auipc (imm : BitVec 20)
  | addi (imm : BitVec 12)
  | andi (imm : BitVec 12)
  | ori (imm : BitVec 12)
  | xori (imm : BitVec 12)
  | addiw (imm : BitVec 12)
  | add
  | slli (shamt : BitVec 6)
  | sub
  | and
  | or
  | xor
  | sll
  | srl
  | sra
  | addw
  | subw
  | sllw
  | srlw
  | sraw
  | slti (imm : BitVec 12)
  | sltiu (imm : BitVec 12)
  | srli (shamt : BitVec 6)
  | srai (shamt : BitVec 6)
  | slliw (shamt : BitVec 5)
  | srliw (shamt : BitVec 5)
  | sraiw (shamt : BitVec 5)
  | slt
  | sltu
   
  | mul
  | mulw
  | mulh
  | mulhu
  | mulhsu
  | divw
  | divuw
  | div
  | divu
  | remw
  | rem
  | remuw
  | remu
   
   
  | adduw
  | sh1adduw
  | sh2adduw
  | sh3adduw
  | sh1add
  | sh2add
  | sh3add
  | slliuw (shamt : BitVec 6)
   
  | andn
  | orn
  | xnor
  | clz
  | clzw
  | ctz
  | ctzw
  | max
  | maxu
  | min
  | minu
  | sextb
  | sexth
  | zexth
  | rol
  | rolw
  | ror
  | rori (_shamt : BitVec 6)
  | roriw (_shamt : BitVec 5)
  | rorw
   
  | bclr
  | bclri (shamt : BitVec 6)
  | bext
  | bexti (shamt : BitVec 6)
  | binv
  | binvi (shamt : BitVec 6)
  | bset
  | bseti (shamt : BitVec 6)
   
  | pack
  | packh
  | packw
   
  | mv
  | not
  | neg
  | negw
  | sextw
  | zextb
  | zextw
  | seqz
  | snez
  | sltz
  | sgtz
  deriving DecidableEq, Repr, Lean.ToExpr

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

instance : DialectSignature (FHE q n) := ⟨Op.signature⟩

instance : DialectSignature LLVM where
  signature op := ⟨op.sig, [], [op.outTy], .pure⟩

instance : DialectSignature HSxComb where
  signature := fun op =>
    match op with
    | .comb o => liftSig (signature o) 
    
    
    | .hs o => MLIR2Handshake.instDialectSignatureHandshake.signature o

inductive Op : Type _
  | comb (o : MLIR2Comb.Comb.Op)
  | hs (o : MLIR2Handshake.Handshake.Op)
  deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

def liftSig (sig : Signature MLIR2Comb.Ty) : Signature MLIR2Handshake.Ty :=
  Signature.mk (sig.sig.map liftTy) [] (liftTy sig.outTy)

def liftTy : MLIR2Comb.Ty → MLIR2Handshake.Ty
| .bitvec w => .stream (.bitvec w)

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

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

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

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

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

instance : DialectSignature DCxComb where
  signature := fun op =>
    match op with
    | .comb o => liftSig (signature o) 
    
    
    | .dc o => MLIR2DC.instDialectSignatureDC.signature o

inductive Op : Type _
  | comb (o : MLIR2Comb.Comb.Op)
  | dc (o : MLIR2DC.DC.Op)
  deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

def liftSig (sig : Signature MLIR2Comb.Ty) : Signature MLIR2DC.Ty :=
  Signature.mk (sig.sig.map liftTy) [] (liftTy sig.outTy)

def liftTy : MLIR2Comb.Ty → MLIR2DC.Ty
| .bitvec w => .valuestream w

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

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

inductive ExTy
  | nat
  | bool
  deriving DecidableEq, Repr

def cst {Γ : Ctxt _} (n : ℕ) : Expr Ex Γ .pure [.nat] :=
  Expr.mk
    (op := .cst n)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .nil)
    (regArgs := .nil)

@[simp]
instance LLVMPlusRiscVSignature : DialectSignature LLVMPlusRiscV where
  signature
  | .llvm llvmOp => .llvm <$> DialectSignature.signature llvmOp
  | .riscv riscvOp => .riscv <$> DialectSignature.signature riscvOp
  | .castRiscv w =>
      {sig := [Ty.riscv .bv], returnTypes := [Ty.llvm (.bitvec w)], regSig := []}
  | .castLLVM w =>
      {sig := [Ty.llvm (.bitvec w)], returnTypes := [Ty.riscv .bv], regSig := []}

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

inductive Ty where
  | llvm : LLVM.Ty -> Ty
  | riscv : RISCV64.RV64.Ty -> Ty
  deriving DecidableEq, Repr, Lean.ToExpr

instance : DialectSignature ExOp ExTy where
  signature
    | .add    => ⟨[.nat, .nat], [], .nat, .pure⟩
    | .beq    => ⟨[.nat, .nat], [], .bool, .pure⟩
    | .cst _  => ⟨[], [], .nat, .pure⟩

inductive ExOp :  Type
  | add : ExOp
  | beq : ExOp
  | cst : ℕ → ExOp
  deriving DecidableEq, Repr

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

inductive ExTy
  | nat
  deriving DecidableEq, Repr

abbrev Expr (Γ) (ty) := _root_.Expr ExOp Γ .pure ty

def cst {Γ : Ctxt _} (n : ℕ) : Expr Γ .nat  :=
  Expr.mk
    (op := .cst n)
    (ty_eq := rfl)
    (eff_le := EffectKind.le_refl _)
    (args := .nil)
    (regArgs := .nil)

instance : DialectSignature ExOp ExTy where
  signature
  | .add    => ⟨[.nat, .nat], [], .nat, .pure⟩
  | .runK _ => ⟨[.nat], [([.nat], .nat)], .nat, .pure⟩

inductive ExOp :  Type
  | add : ExOp
  | runK : ℕ → ExOp
  deriving DecidableEq, Repr

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)

@[reducible]
instance [TyDenote d.Ty] [DialectSignature d] [DialectDenote d]
    [B : HasBool d] [N : HasNat d] [I : HasInt d] : DialectSignature (Scf d) where
   signature
   | .coe o => signature (d:=d) o
    | .if t t' => ⟨[B.ty, t], [(⟨[t]⟩, [t']), (⟨[t]⟩, [t'])], [t'], .impure⟩
      
      
      
      
      
    | .for t => ⟨[ I.ty,  I.ty,  N.ty, t], [(⟨[I.ty, t]⟩, [t])], [t], .impure⟩
    | .run t => ⟨[t], [(⟨[t]⟩, [t])], [t], .impure⟩
    | .iterate _k => ⟨[I.ty], [(⟨[I.ty]⟩, [I.ty])], [I.ty], .impure⟩

class HasTy (d : Dialect) (DenotedTy : Type) [TyDenote d.Ty] [DialectSignature d] where
    ty : d.Ty
    denote_eq : toType ty = DenotedTy := by admit /- proof elided -/

inductive Scf.Op (Op' Ty' : Type) (m') [TyDenote Ty'] [DialectSignature ⟨Op', Ty', m'⟩]
    [DialectDenote ⟨Op', Ty', m'⟩] : Type _
  | coe (o : Op')
  | iterate (k : ℕ) 
  | run (inputty : Ty')  
  | if (inputty retty' : Ty')  
  | for (ty : Ty')
  deriving DecidableEq, Repr

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

abbrev ScfArith := Scf Arith

def Scf (d : Dialect) [TyDenote d.Ty] [DialectSignature d] [DialectDenote d] : Dialect where
  Op := Scf.Op d.Op d.Ty d.m
  Ty := d.Ty
  m  := d.m

inductive Op
  | add : Op  
  | add_nat : Op  
  | axpy : Op  
  | neg : Op  
  | const : (val : ℤ) → Op
  | const_nat : (val : ℕ) → Op

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

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

@[simp]
instance Valuation.instAppendHVector (Γ : Ctxt Ty) (ts : List Ty) :
    HAppend (HVector toType ts) (Valuation Γ) (Valuation <| ⟨ts⟩ ++ Γ) where
  hAppend vals V :=
    (Valuation.ofHVector vals) ++ V

@[simp_denote] def neg {Γ : Ctxt _} (a : Var Γ .int) : Expr ScfArith Γ .pure .int :=
  Expr.mk
    (op := .coe <| .neg)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .nil)
    (regArgs := .nil)

@[simp_denote] def axpy {Γ : Ctxt _} (a : Var Γ .int) (x : Var Γ .nat) (b: Var Γ .int) :
    Expr ScfArith Γ .pure .int :=
  Expr.mk
    (op := .coe <| .axpy)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons a <| .cons x <| .cons b .nil)
    (regArgs := .nil)

@[simp_denote] def add_nat (e₁ e₂ : Var Γ .nat) : Expr ScfArith Γ .pure .nat :=
  Expr.mk
    (op := .coe <| .add_nat)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons e₁ <| .cons e₂ .nil)
    (regArgs := .nil)

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

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

abbrev Arith : Dialect := {Op, Ty}

@[reducible]
instance : DialectSignature Arith where
  signature
    | .axpy => ⟨[.int, .nat, .int], [], [.int], .pure⟩
    | .neg => ⟨[.int], [], [.int], .pure⟩
    | .const _ => ⟨[], [], [.int], .pure⟩
    | .const_nat _ => ⟨[], [], [.nat], .pure⟩
    | .add   => ⟨[.int, .int], [], [.int], .pure⟩
    | .add_nat   => ⟨[.nat, .nat], [], [.nat], .pure⟩

@[simp_denote] def add {Γ : Ctxt _} (e₁ e₂ : Var Γ .int) : Expr ScfArith Γ .pure .int :=
  Expr.mk
    (op := .coe <| .add)
    (ty_eq := rfl)
    (eff_le := by admit /- proof elided -/
    )
    (args := .cons e₁ <| .cons e₂ .nil)
    (regArgs := .nil)

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

notation "⟦" x "⟧" => TyDenote.toType x

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

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 scalar_i16_lshr_and_signbit_eq_after := [llvm|
{
^0(%arg33 : i16, %arg34 : i16):
  %0 = llvm.mlir.constant(-1 : i16) : i16
  %1 = llvm.lshr %arg33, %arg34 : i16
  %2 = llvm.icmp "sgt" %1, %0 : i16
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

def 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 anyext_trunc_fold: List (Σ Γ, LLVMPeepholeRewriteRefine 32 Γ) :=
  [⟨_, anyext_trunc_fold_sext_32⟩,
  ⟨_, anyext_trunc_fold_zext_32⟩]

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

def bools2_logical_commute3_and1_after := [llvm|
{
^0(%arg24 : i1, %arg25 : i1, %arg26 : i1):
  %0 = "llvm.select"(%arg26, %arg24, %arg25) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

def sdiv_shl_pair2_before := [llvm|
{
^0(%arg40 : i32, %arg41 : i32, %arg42 : i32):
  %0 = llvm.shl %arg40, %arg41 overflow<nsw,nuw> : i32
  %1 = llvm.shl %arg40, %arg42 overflow<nsw> : i32
  %2 = llvm.sdiv %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

@[simp_sllvm]
def srem (x y : LLVM.IntW w) : EffectM (LLVM.IntW w) := do
  if y.canBe 0#w then
    throwUB
  else
    pure <| LLVM.srem x y

instance : TyDenote Ty where toType := Ty.toType

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 lshrugt_03_11_before := [llvm|
{
^0(%arg372 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(-5 : i4) : i4
  %2 = llvm.lshr %arg372, %0 : i4
  %3 = llvm.icmp "ugt" %2, %1 : i4
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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

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

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

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 constLLVM31 : Com LLVMPlusRiscV ⟨[]⟩ .pure (.llvm (.bitvec 64)) := [LV| {
  ^entry ():
    %1 = llvm.mlir.constant (31) : i64
    llvm.return %1 : i64
  }]

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

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

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

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

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

def Holor.pointwise_mul [Mul α] (h₁ h₂ : Holor α ds) : Holor α ds := fun ix => (h₁ ix) * (h₂ ix)

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

def ashr_mul_times_5_div_4_before := [llvm|
{
^0(%arg16 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mul %arg16, %0 overflow<nsw,nuw> : i32
  %3 = llvm.ashr %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

def scalar_i32_shl_and_signbit_eq_X_is_constant1_before := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(12345 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : 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 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 ule_swap_or_not_min_before := [llvm|
{
^0(%arg264 : i8, %arg265 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "uge" %arg265, %arg264 : i8
  %2 = llvm.icmp "ne" %arg264, %0 : i8
  %3 = llvm.or %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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

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

def urem_i32_multiuse_before := [llvm|
{
^0(%arg17 : i8, %arg18 : i8):
  %0 = llvm.zext %arg17 : i8 to i32
  %1 = llvm.zext %arg18 : i8 to i32
  %2 = llvm.urem %0, %1 : i32
  %3 = llvm.add %0, %1 : i32
  %4 = llvm.mul %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

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

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

def test_sub_0_Y_eq_0_before := [llvm|
{
^0(%arg49 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sub %0, %arg49 : i8
  %2 = llvm.icmp "eq" %1, %0 : i8
  "llvm.return"(%2) : (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 llvm_urem_lower_riscv_64: LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] :=
  {lhs := llvm_urem_64, rhs := urem_riscv_64}

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

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

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

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

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

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

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

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

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

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

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

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

instance : AST.TransformReturn (MetaLLVM φ) φ := { mkReturn }

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

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

instance : HydrablePackedBitvecToSubstitutionValue GenBVPred GenBVExpr where
  packedBitVecToSubstitutionValue := packedBitVecToSubstitutionValue

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

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

@[match_pattern] abbrev udiv (w : Nat) (flag : ExactFlag := {} ) : LLVM.Op := MOp.udiv (.concrete w) flag

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

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

instance : LawfulGetElem (Ctxt Ty) Nat Ty (fun as i => i < as.length) where
  getElem?_def Γ i _ := by admit /- proof elided -/

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

def different_size_zext_zext_ne_commute_after := [llvm|
{
^0(%arg20 : i7, %arg21 : i4):
  %0 = llvm.zext %arg21 : i4 to i7
  %1 = llvm.icmp "ne" %arg20, %0 : i7
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def ashr_mul_before := [llvm|
{
^0(%arg99 : i8, %arg100 : i8):
  %0 = llvm.mlir.constant(8 : i20) : i20
  %1 = llvm.sext %arg99 : i8 to i20
  %2 = llvm.sext %arg100 : i8 to i20
  %3 = llvm.mul %1, %2 : i20
  %4 = llvm.ashr %3, %0 : i20
  %5 = llvm.trunc %4 : i20 to i16
  "llvm.return"(%5) : (i16) -> ()
}
]

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

inductive AttrDefn where
  | mk: (name: String) -> (val: AttrValue φ) -> AttrDefn

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

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

def srem {w : Nat} (x y : IntW w) : IntW w := do
  let x' ← x
  let y' ← y
  srem? x' y'

def toAagFile (aig : Aiger α) (file : IO.FS.Stream) : IO Unit := do
  let maxVar := aig.aig.decls.size
  let numInputs := aig.inputs.size
  let numLatches := aig.latches.size
  let ⟨numAnds, body, _⟩ : _ × _ × _ := aig.aig.decls.foldl
      (fun ⟨numAnds, s, idx⟩ term =>
        match term with
        | Decl.gate l r => ⟨numAnds + 1, s ++ s!"{toVarFalseLit idx} {toVarFanin l} {toVarFanin r}\n", idx + 1⟩
        | _ => ⟨numAnds, s, idx + 1⟩)
      ⟨0, "", 0⟩

  y

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

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

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

def sgt_or_not_min_commute_before := [llvm|
{
^0(%arg26 : i8, %arg27 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.icmp "sgt" %arg26, %arg27 : i8
  %2 = llvm.icmp "ne" %arg26, %0 : i8
  %3 = llvm.or %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def ROfZComputable_impl (z : ℤ) : R q n :=
  let zq : ZMod q := z
  let p : (ZMod q)[X] := {
      toFinsupp := Finsupp.mk
        (support := List.toFinset (if zq = 0 then  [] else [0]))
        (toFun := fun i => if i = 0 then z else 0)
        (mem_support_toFun := by admit /- proof elided -/
        )
      : (ZMod q)[X]
  }
  R.fromPoly p

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

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

def t1_after := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.sext %arg11 : i8 to i32
  %2 = llvm.and %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

getThe in Init.Prelude

def Expr.ctxt : Expr d Γ eff [t] → Ctxt d.Ty := fun _ => Γ

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

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

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

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

RV64.sh1adduw in RISCV.Instructions

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

abbrev HasNat (d : Dialect) [TyDenote d.Ty] [DialectSignature d] : Type := HasTy d Nat

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

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

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

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

def neg_mask_after := [llvm|
{
^0(%arg1 : i32, %arg2 : i16):
  %0 = llvm.mlir.constant(0 : i16) : i16
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.sext %arg2 : i16 to i32
  %3 = llvm.sub %arg1, %2 overflow<nsw> : i32
  %4 = llvm.icmp "slt" %arg2, %0 : i16
  %5 = "llvm.select"(%4, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

def hv_cast_gen {l : List Nat} (h : HVector (fun i => Stream (BitVec i)) l) :
    Stream (HVector (fun i => BitVec i) l) :=
  fun n => is_ready (hv_cast_gen' h n)

def and_not_or_commute7_after := [llvm|
{
^0(%arg460 : i32, %arg461 : i32, %arg462 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg461, %arg462 : i32
  %2 = llvm.and %1, %arg460 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def x : DCOp.ValueStream Int := ofList [some 1, none, some 2, some 5, none]

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

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

inductive GenBVExpr : Nat → Type where
   
  | var (idx : Nat) : GenBVExpr w
   
  | const (val : BitVec w) : GenBVExpr w
   
  | extract (start len : Nat) (expr : GenBVExpr w) : GenBVExpr len
   
  | bin (lhs : GenBVExpr w) (op : BVBinOp) (rhs : GenBVExpr w) : GenBVExpr w
   
  | un (op : BVUnOp) (operand : GenBVExpr w) : GenBVExpr w
   
  | append (lhs : GenBVExpr l) (rhs : GenBVExpr r) (h : w = l + r) : GenBVExpr w
   
  | replicate (n : Nat) (expr : GenBVExpr w) (h : w' = w * n) : GenBVExpr w'
   
  | shiftLeft (lhs : GenBVExpr m) (rhs : GenBVExpr n) : GenBVExpr m
   
  | shiftRight (lhs : GenBVExpr m) (rhs : GenBVExpr n) : GenBVExpr m
   
  | arithShiftRight (lhs : GenBVExpr m) (rhs : GenBVExpr n) : GenBVExpr m
  | signExtend (v : Nat) (expr : GenBVExpr w) : GenBVExpr v
  | zeroExtend (v : Nat) (expr : GenBVExpr w) : GenBVExpr v
  | truncate (v : Nat) (expr : GenBVExpr w) : GenBVExpr v
with

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

instance {Γ' : DerivedCtxt Γ} : Coe (Ctxt.Var Γ t) (Ctxt.Var (Γ' : Ctxt Ty) t) where
  coe v := Γ'.diff.toHom v

def uaddo_commute4_after := [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 "ugt" %arg22, %1 : i32
  %4 = "llvm.select"(%3, %arg24, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test51_before := [llvm|
{
^0(%arg133 : i64, %arg134 : i1):
  %0 = llvm.mlir.constant(-2 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.trunc %arg133 : i64 to i32
  %3 = llvm.and %2, %0 : i32
  %4 = llvm.or %2, %1 : i32
  %5 = "llvm.select"(%arg134, %3, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = llvm.sext %5 : i32 to i64
  "llvm.return"(%6) : (i64) -> ()
}
]

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

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

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

def IsGoodTermBoolFSM_mkTermFSM (wcard tcard bcard ncard icard pcard : Nat) {tctx : Term.Ctx wcard tcard}
    (t : Term bcard ncard icard pcard tctx .bool) :
    (HTermBoolFSMToBitStream (mkTermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm t))) :=

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

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

def zext_nneg_sext_sle_op0_narrow_after := [llvm|
{
^0(%arg50 : i8, %arg51 : i16):
  %0 = llvm.sext %arg50 : i8 to i16
  %1 = llvm.icmp "sge" %arg51, %0 : i16
  "llvm.return"(%1) : (i1) -> ()
}
]

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

def timeElapsedMs (x : IO α) : IO (α × Int) := do
    let tStart ← IO.monoMsNow
    let b ← x
    let tEnd ← IO.monoMsNow
    return (b, tEnd - tStart)

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

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

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

    |

@[simp]
def envBitstream_set_self_eq_self (x : arity → BitStream) (n : Nat) :
    (envBitstream_set x n (fun a => x a n)) = x :=

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

def State.envToExpr (w : WidthExpr) (s : State) : MetaM Expr := do
  let mut ix2e : Std.HashMap Nat Expr := {}
  for (e, ix) in s.e2ix do
    ix2e := ix2e.insert ix e
  let bvTy := w.toBitVecType
  let mut env :=  mkApp (mkConst ``List.nil [Level.zero]) bvTy
  for i in [0:ix2e.size] do
    let i := ix2e.size - 1 - i
    env := mkApp3 (mkConst ``List.cons [Level.zero]) bvTy  ix2e[i]! env
  return env

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

def toString : FpPredicate → String
| bin lhs op rhs => s!"({lhs.toString} {op.toString} {rhs.toString})"

private def Expr.isBitVecOfWidth (e : Expr) (w : Expr) : MetaM Bool := do
  match_expr ← inferType e with
  | BitVec w' => return w == w'
  | _ => return false

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

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

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

BitVec.instHShiftLeft in Init.Data.BitVec.Basic

def in_constant_6_vary_invmask_before := [llvm|
{
^0(%arg35 : i4, %arg36 : i4):
  %0 = llvm.mlir.constant(-1 : i4) : i4
  %1 = llvm.mlir.constant(6 : i4) : i4
  %2 = llvm.xor %arg36, %0 : i4
  %3 = llvm.xor %arg35, %1 : i4
  %4 = llvm.and %3, %2 : i4
  %5 = llvm.xor %4, %arg35 : i4
  "llvm.return"(%5) : (i4) -> ()
}
]

def negate_zext_after := [llvm|
{
^0(%arg112 : i8, %arg113 : i1):
  %0 = llvm.sext %arg113 : i1 to i8
  %1 = llvm.add %arg112, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

def Tensor2d'.error (α : Type) : Tensor2d' α where
  dim₀ := 0
  dim₁ := 0
  mat := Matrix.of fun x _y => x.elim0

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

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

RV64.srl in RISCV.Instructions

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

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

def n2_after := [llvm|
{
^0(%arg1 : i8, %arg2 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.shl %0, %arg2 overflow<nuw> : i8
  %2 = llvm.icmp "ult" %1, %arg1 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def shl_add_log_may_cause_poison_pr62175_with_nsw_before := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(4 : i8) : i8
  %1 = llvm.shl %0, %arg0 overflow<nsw> : i8
  %2 = llvm.mul %arg1, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

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

def Term.numVars (t : Term) : Nat := t.f.numVars

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

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

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

def icmp_equality_test_swift_optional_pointers_after := [llvm|
{
^0(%arg28 : i64, %arg29 : i64):
  %0 = llvm.icmp "eq" %arg28, %arg29 : i64
  "llvm.return"(%0) : (i1) -> ()
}
]

instance {cmp} : DecidableNFA' (NFA'.autSignedCmp cmp) where

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

def mkPredicateEnvCons (penv : Expr) (p : Expr) : SolverM Expr := do
  let out ← mkAppM (``MultiWidth.Predicate.Env.cons)
    #[penv, p]
  debugCheck out
  return out

@[simp_llvm_option]
def and {w : Nat} (x y : IntW w) : IntW w := do
  let x' ← x
  let y' ← y
  and? x' y'

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

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

def or_match : List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) := [
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_noflag_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_disjoint_8),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_noflag_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_disjoint_16),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_noflag_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_disjoint_32),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_noflag_64),
  mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND llvm_or_lower_riscv_disjoint_64)
]

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

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

@[simp_denote]
def ctxtTransformToLLVM  (Γ : Ctxt LLVMPlusRiscV.Ty) :=
  Ctxt.map  (fun ty  =>
    match ty with
    | .llvm someLLVMTy => someLLVMTy
    | .riscv _  => .bitvec 999
  ) Γ

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

def testi128i128_before := [llvm|
{
^0(%arg7 : i128):
  %0 = llvm.mlir.constant(127 : i128) : i128
  %1 = llvm.mlir.constant(27 : i128) : i128
  %2 = llvm.ashr %arg7, %0 : i128
  %3 = llvm.xor %2, %1 : i128
  "llvm.return"(%3) : (i128) -> ()
}
]

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

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

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

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

def test12_before := [llvm|
{
^0(%arg292 : i32, %arg293 : i32):
  %0 = llvm.icmp "ult" %arg292, %arg293 : i32
  %1 = llvm.icmp "ule" %arg292, %arg293 : i32
  %2 = llvm.and %0, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

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

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

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

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

noncomputable def dropLeadingNones (x : Stream α) (not_stuck : x ≠ stuck α) : Stream α:=
  x.drop (nonesUntilSome x not_stuck)

def llvm_const_lower_riscv_li21 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM21, rhs:= liRiscv21,
   correct := by admit /- proof elided -/

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

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

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

def riscv_asm := [RV64_com| {
 ^bb0(%r1 : !riscv.reg, %r2 : !riscv.reg ):
 %0 = and %r1, %r2 : !riscv.reg
 %1 = div %0, %r1 : !riscv.reg
    ret %1 : !riscv.reg
}]

instance : ToMessageData (ParsedInputState) where
  toMessageData s := printParsedFpExprState s

IO.getEnv in Init.System.IO

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

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

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

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

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

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

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

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

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

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

def Expr.changeDialect : Expr d Γ eff ty → Expr d' (Γ.map f.mapTy) eff (f.mapTy <$> ty)
  | ⟨op, Eq.refl _, effLe, args, regs⟩ => ⟨
      f.mapOp op,
      (f.preserves_returnTypes _).symm,
      f.preserves_effectKind _ ▸ effLe,
      f.preserves_sig _ ▸ args.map' f.mapTy fun _ => Var.toMap (f:=f.mapTy),
      f.preserves_regSig _ ▸
        HVector.changeDialect regs
    ⟩
termination_by e => sizeOf e

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

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

def srem_constant_dividend_select_of_constants_divisor_before := [llvm|
{
^0(%arg37 : i1):
  %0 = llvm.mlir.constant(12 : i32) : i32
  %1 = llvm.mlir.constant(-3 : i32) : i32
  %2 = llvm.mlir.constant(42 : i32) : i32
  %3 = "llvm.select"(%arg37, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.srem %2, %3 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

def vecCast (h : as = bs) : HVector A as → HVector A bs := (h ▸ ·)


def_denote for HSxComb where
  | .comb op =>
      let opDenote :=
        (DialectDenote.denote op · (vecCast (by admit /- proof elided -/
        ) HVector.nil))
      let opDenote : HVector _ _ → ⟦_⟧ :=
        EffectKind.coe_toMonad ∘ opDenote
      liftComb opDenote
  | .hs op => MLIR2Handshake.instDialectDenoteHandshake.denote op

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

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

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

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

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

def Expr.mkPredicateEvalEqFSM (p : Expr) : Expr :=
    mkApp (.const ``predicateEvalEqFSM []) p

Array.isEmpty in Init.Data.Array.Basic

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

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

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

instance: HRefinement (Expr d Γ eff₁ t) (Expr d Γ eff₂ t) where
  IsRefinedBy e₁ e₂ :=
    ∀ V, e₁.denote V ⊑ e₂.denote V

Stream' in Mathlib.Data.Stream.Defs

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

def test18_before := [llvm|
{
^0(%arg6 : i128):
  %0 = llvm.mlir.constant(2 : i128) : i128
  %1 = llvm.shl %arg6, %0 : i128
  %2 = llvm.shl %arg6, %0 : i128
  %3 = llvm.sub %1, %2 : i128
  "llvm.return"(%3) : (i128) -> ()
}
]

def Region.appendOps (bb: Region φ) (ops: List (Op φ)): Region φ :=
  match bb with
  | Region.mk name args bbs => Region.mk name args (bbs ++ ops)

def test_after := [llvm|
{
^0(%arg0 : i16, %arg1 : i16):
  %0 = llvm.sext %arg0 : i16 to i32
  %1 = llvm.sext %arg1 : i16 to i32
  %2 = llvm.add %0, %1 overflow<nsw> : i32
  %3 = llvm.sext %2 : i32 to i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

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

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

def llvm_udiv_lower_riscv_flag_32: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] :=
  {lhs := udiv_llvm_exact_32, rhs := udiv_riscv_32, correct := sorry }

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

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

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

def RISCV_identity_combines: List (Σ Γ, RISCVPeepholeRewrite Γ) :=
  right_identity_zero ++ binop_same_val ++ right_identity_one ++ add_sub_reg_frags

def trimTensor (tensor : List Int) : List Int
  := tensor.reverse.dropWhile (· = 0) |>.reverse

def Lets.addComToEnd {Γ_out} {eff} (lets : Lets d Γ_in eff Γ_out) :
      (com : Com d Γ_out eff ty) → Lets d Γ_in eff com.outContext
  | Com.rets _       => lets
  | Com.var e body => addComToEnd (Lets.var lets e) body

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

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

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

def t0_after := [llvm|
{
^0(%arg32 : i8):
  %0 = llvm.mlir.constant(15 : i8) : i8
  %1 = llvm.mlir.constant(-16 : i8) : i8
  %2 = llvm.add %arg32, %0 : i8
  %3 = llvm.and %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def ashr_overshift_before := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(17 : i32) : i32
  %2 = llvm.ashr %arg6, %0 : i32
  %3 = llvm.ashr %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

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

Pure in Init.Prelude

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

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

def negate_lshr_after := [llvm|
{
^0(%arg108 : i8, %arg109 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.ashr %arg109, %0 : i8
  %2 = llvm.add %1, %arg108 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def basic_after := [llvm|
{
^0(%arg25 : i8, %arg26 : i8):
  %0 = llvm.sub %arg25, %arg26 : i8
  "llvm.return"(%0) : (i8) -> ()
}
]

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

def not_mul_of_pow2_after := [llvm|
{
^0(%arg77 : i32, %arg78 : i8):
  %0 = llvm.mlir.constant(6 : i32) : i32
  %1 = llvm.mlir.constant(1530 : i32) : i32
  %2 = llvm.and %arg77, %0 : i32
  %3 = llvm.zext %arg78 : i8 to i32
  %4 = llvm.mul %2, %3 overflow<nsw,nuw> : i32
  %5 = llvm.icmp "ugt" %4, %1 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

def ashrsgt_03_06_exact_before := [llvm|
{
^0(%arg63 : i4):
  %0 = llvm.mlir.constant(3 : i4) : i4
  %1 = llvm.mlir.constant(6 : i4) : i4
  %2 = llvm.ashr exact %arg63, %0 : i4
  %3 = llvm.icmp "sgt" %2, %1 : i4
  "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 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 eq_umax3_before := [llvm|
{
^0(%arg56 : i32, %arg57 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.add %arg56, %0 : i32
  %2 = llvm.icmp "ugt" %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 demorgan_nand_after := [llvm|
{
^0(%arg38 : i8, %arg39 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg39, %0 : i8
  %2 = llvm.or %arg38, %1 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

RV64.rem in RISCV.Instructions

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

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

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

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

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

@[simp]
def Op.denote (o : LLVM.Op) (op : HVector TyDenote.toType (DialectSignature.sig o)) :
    (TyDenote.toType (β := LLVM.Ty) o.outTy) :=
  match o with
  | LLVM.Op.const _ val    => const? _ val
  | LLVM.Op.copy _         =>               (op.getN 0 (by admit /- proof elided -/
  ))
  | LLVM.Op.freeze _       => LLVM.freeze   (op.getN 0 (by admit /- proof elided -/
  ))
  | LLVM.Op.not _          => LLVM.not      (op.getN 0 (by admit /- proof elided -/
  ))
  | LLVM.Op.neg _          => LLVM.neg      (op.getN 0 (by admit /- proof elided -/
  ))
  | LLVM.Op.trunc w w'    flags => LLVM.trunc w' (op.getN 0 (by admit /- proof elided -/
  )) flags
  | LLVM.Op.zext w w' flag => LLVM.zext  w' (op.getN 0 (by admit /- proof elided -/
  )) flag
  | LLVM.Op.sext w w'      => LLVM.sext  w' (op.getN 0 (by admit /- proof elided -/
  ))
  | LLVM.Op.and _          => LLVM.and      (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  ))
  | LLVM.Op.or _ flag      => LLVM.or       (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flag
  | LLVM.Op.xor _          => LLVM.xor      (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  ))
  | LLVM.Op.shl _ flags    => LLVM.shl      (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flags
  | LLVM.Op.lshr _ flag    => LLVM.lshr     (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flag
  | LLVM.Op.ashr _ flag    => LLVM.ashr     (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flag
  | LLVM.Op.sub _ flags    => LLVM.sub      (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flags
  | LLVM.Op.add _ flags    => LLVM.add      (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flags
  | LLVM.Op.mul _ flags    => LLVM.mul      (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flags
  | LLVM.Op.sdiv _ flag    => LLVM.sdiv     (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flag
  | LLVM.Op.udiv _ flag    => LLVM.udiv     (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) flag
  | LLVM.Op.urem _         => LLVM.urem     (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  ))
  | LLVM.Op.srem _         => LLVM.srem     (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  ))
  | LLVM.Op.icmp c _       => LLVM.icmp  c  (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  ))
  | LLVM.Op.select _       => LLVM.select   (op.getN 0 (by admit /- proof elided -/
  )) (op.getN 1 (by admit /- proof elided -/
  )) (op.getN 2 (by admit /- proof elided -/
  ))

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

def reassoc_x2_mul_nuw_after := [llvm|
{
^0(%arg18 : i32, %arg19 : i32):
  %0 = llvm.mlir.constant(45 : i32) : i32
  %1 = llvm.mul %arg18, %arg19 : i32
  %2 = llvm.mul %1, %0 overflow<nuw> : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def ashr_ashr_before := [llvm|
{
^0(%arg7 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(7 : i32) : i32
  %2 = llvm.ashr %arg7, %0 : i32
  %3 = llvm.ashr %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

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

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

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

def test4a_before := [llvm|
{
^0(%arg10 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.ashr %arg10, %0 : i32
  %4 = llvm.sub %1, %arg10 : i32
  %5 = llvm.lshr %4, %0 : i32
  %6 = llvm.or %3, %5 : i32
  %7 = llvm.icmp "slt" %6, %2 : i32
  "llvm.return"(%7) : (i1) -> ()
}
]

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

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

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

def test87_before := [llvm|
{
^0(%arg58 : i16):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.sext %arg58 : i16 to i32
  %2 = llvm.mul %1, %0 overflow<nsw> : i32
  %3 = llvm.ashr %2, %0 : i32
  %4 = llvm.trunc %3 : i32 to i16
  "llvm.return"(%4) : (i16) -> ()
}
]

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

def ValueStream := Stream

def i : Stream (BitVec 8) := ofList [1#8, none, 1#8, 4#8, 0#8]

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

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

def not_mul_of_pow2_commute_before := [llvm|
{
^0(%arg75 : i32, %arg76 : i32):
  %0 = llvm.mlir.constant(12 : i32) : i32
  %1 = llvm.mlir.constant(255 : i32) : i32
  %2 = llvm.mlir.constant(3060 : i32) : i32
  %3 = llvm.and %arg75, %0 : i32
  %4 = llvm.and %arg76, %1 : i32
  %5 = llvm.mul %4, %3 : i32
  %6 = llvm.icmp "ugt" %5, %2 : i32
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

def PR42691_4_before := [llvm|
{
^0(%arg337 : i32):
  %0 = llvm.mlir.constant(-2147483648 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.icmp "uge" %arg337, %0 : i32
  %3 = llvm.icmp "eq" %arg337, %1 : i32
  %4 = llvm.or %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def llvm_const_lower_riscv_li31 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM31, rhs:= liRiscv31,
   correct := by admit /- proof elided -/

def eval (assign : Std.HashMap Nat BVExpr.PackedBitVec) : FpExpr e → PackedFloat e mfixed
  | .var idx =>
    let packedBv := assign[idx]!
     
    if h : packedBv.w = 1 + e + mfixed then
     PackedFloat.ofBV (packedBv.bv.cast h)
    else
      
      PackedFloat.ofBV (packedBv.bv.setWidth _)
  | .const val => PackedFloat.ofBV val
  | .bin lhs op rhs =>
      match op with
        
      | .add => add (eval assign lhs) (eval assign rhs) .RNE

Stream'.corec in Mathlib.Data.Stream.Defs

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

def narrow_sext_or_before := [llvm|
{
^0(%arg52 : i16, %arg53 : i32):
  %0 = llvm.sext %arg52 : i16 to i32
  %1 = llvm.or %0, %arg53 : i32
  %2 = llvm.trunc %1 : i32 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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

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

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

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

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

def x : DCOp.ValueStream Int := ofList [some 1, none, some 2, some 5, none]

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

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

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

def shl_add_add_fail_after := [llvm|
{
^0(%arg166 : i8, %arg167 : i8):
  %0 = llvm.mlir.constant(2 : i8) : i8
  %1 = llvm.mlir.constant(48 : i8) : i8
  %2 = llvm.lshr %arg166, %0 : i8
  %3 = llvm.lshr %arg167, %0 : i8
  %4 = llvm.add %3, %1 overflow<nsw,nuw> : i8
  %5 = llvm.add %2, %4 overflow<nuw> : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

String.Pos in Init.Data.String.Defs

def and_nosignbit_ashr_after := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(8388352 : i32) : i32
  %2 = llvm.lshr %arg6, %0 : i32
  %3 = llvm.and %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

instance : Hashable Empty where
  hash x := x.elim

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

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

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

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

def ofList (vals : List (Option α)) : Stream α :=
  fun i => vals[i]?.join

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

def ashr_overshift_before := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(17 : i32) : i32
  %2 = llvm.ashr %arg6, %0 : i32
  %3 = llvm.ashr %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def demorgan_or_apint1_before := [llvm|
{
^0(%arg62 : i43, %arg63 : i43):
  %0 = llvm.mlir.constant(-1 : i43) : i43
  %1 = llvm.xor %arg62, %0 : i43
  %2 = llvm.xor %arg63, %0 : i43
  %3 = llvm.or %1, %2 : i43
  "llvm.return"(%3) : (i43) -> ()
}
]

def test_op_op_before := [llvm|
{
^0(%arg20 : i32, %arg21 : i32, %arg22 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.icmp "sgt" %arg20, %0 : i32
  %2 = llvm.sext %1 : i1 to i32
  %3 = llvm.icmp "sgt" %arg21, %0 : i32
  %4 = llvm.sext %3 : i1 to i32
  %5 = llvm.icmp "sgt" %arg22, %0 : i32
  %6 = "llvm.select"(%5, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

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

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

def absdiff2_after := [llvm|
{
^0(%arg0 : i64, %arg1 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.icmp "ugt" %arg0, %arg1 : i64
  %2 = llvm.sub %arg1, %arg0 : i64
  %3 = llvm.sub %0, %2 : i64
  %4 = "llvm.select"(%1, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def test_sle_xor_before := [llvm|
{
^0(%arg42 : i32, %arg43 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg43, %0 : i32
  %2 = llvm.xor %1, %arg42 : i32
  %3 = llvm.icmp "sle" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def test_after := [llvm|
{
^0(%arg0 : i31):
  %0 = llvm.mlir.constant(16384 : i32) : i32
  %1 = llvm.mlir.constant(15 : i32) : i32
  %2 = llvm.zext %arg0 : i31 to i32
  %3 = llvm.add %2, %0 overflow<nuw> : i32
  %4 = llvm.lshr %3, %1 : i32
  %5 = llvm.trunc %4 : i32 to i16
  "llvm.return"(%5) : (i16) -> ()
}
]

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

def src_srem_shl_demand_max_mask_hit_demand_after := [llvm|
{
^0(%arg18 : i32):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.mlir.constant(-4 : i32) : i32
  %3 = llvm.srem %arg18, %0 : i32
  %4 = llvm.shl %3, %1 overflow<nsw> : i32
  %5 = llvm.and %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

macro "[llvm| " reg:mlir_region "]" : term => `([llvm()| $reg])

def udiv_mul_shl_nuw_exact_commute1_after := [llvm|
{
^0(%arg163 : i5, %arg164 : i5, %arg165 : i5):
  %0 = llvm.lshr exact %arg164, %arg165 : i5
  "llvm.return"(%0) : (i5) -> ()
}
]

def ashr_and_or_disjoint_before := [llvm|
{
^0(%arg41 : i8, %arg42 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.mlir.constant(13 : i8) : i8
  %3 = llvm.srem %arg41, %0 : i8
  %4 = llvm.ashr %arg42, %1 : i8
  %5 = llvm.and %4, %2 : i8
  %6 = llvm.or disjoint %3, %5 : i8
  %7 = llvm.shl %6, %1 : i8
  "llvm.return"(%7) : (i8) -> ()
}
]

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

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

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

def icmp_eq_or_z_or_pow2orz_fail_nonzero_const_after := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.sub %0, %arg11 : i8
  %3 = llvm.and %arg11, %2 : i8
  %4 = llvm.icmp "eq" %arg10, %1 : i8
  %5 = llvm.icmp "eq" %arg10, %3 : i8
  %6 = llvm.or %4, %5 : i1
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

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 llvm_add_lower_riscv_nsw_flag_1 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1), Ty.llvm (.bitvec 1)] where
  lhs:= add_llvm_nsw_flags_1
  rhs:= add_riscv_1

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

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

def xor_ashr_not_fail_invalid_xor_constant_before := [llvm|
{
^0(%arg15 : i8, %arg16 : i8, %arg17 : i8):
  %0 = llvm.mlir.constant(-2 : i8) : i8
  %1 = llvm.ashr %arg15, %arg17 : i8
  %2 = llvm.ashr %arg16, %arg17 : i8
  %3 = llvm.xor %2, %0 : i8
  %4 = llvm.xor %1, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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

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

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

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

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

def ult_and_max_commute_logical_after := [llvm|
{
^0(%arg362 : i8, %arg363 : i8):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (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 carry' (initCarry : Bool) (x y : BitStream) : BitStream :=
  fun n =>
  match n with
  | 0 => initCarry
  | n + 1 => (addAux' initCarry x y n).2

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

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

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

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 negative5_after := [llvm|
{
^0(%arg2 : i32, %arg3 : i32):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

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

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

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 and_add_bool_to_select_after := [llvm|
{
^0(%arg5 : i1, %arg6 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = "llvm.select"(%arg5, %0, %arg6) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

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

def ugt_swap_or_not_min_before := [llvm|
{
^0(%arg6 : i8, %arg7 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "ult" %arg7, %arg6 : i8
  %2 = llvm.icmp "ne" %arg6, %0 : i8
  %3 = llvm.or %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def t10_before := [llvm|
{
^0(%arg205 : i32, %arg206 : i32):
  %0 = llvm.shl %arg205, %arg206 overflow<nsw> : i32
  %1 = llvm.sdiv %0, %arg205 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

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

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

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

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

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

def src_srem_shl_demand_max_signbit_before := [llvm|
{
^0(%arg24 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(30 : i32) : i32
  %2 = llvm.mlir.constant(-2147483648 : i32) : i32
  %3 = llvm.srem %arg24, %0 : i32
  %4 = llvm.shl %3, %1 : i32
  %5 = llvm.and %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

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

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

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

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

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

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

def test9_before := [llvm|
{
^0(%arg87 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.and %arg87, %0 : i32
  %2 = llvm.trunc %1 : i32 to i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

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

@[simp] def Predicate.arity : Predicate → Nat
| .width _ _ => 0
| .binary .eq t1 t2 => max t1.arity t2.arity
| .binary .neq t₁ t₂ => max t₁.arity t₂.arity
| .binary .ult t₁ t₂ => max t₁.arity t₂.arity
| .binary .ule t₁ t₂ => t₁.arity ⊔ t₂.arity ⊔ (t₁.arity ⊔ t₂.arity)
| .binary .slt t₁ t₂ => (t₁.arity ⊔ t₂.arity ⊔ (t₁.arity ⊔ t₂.arity))
| .binary .sle t₁ t₂ => (t₁.arity ⊔ t₂.arity ⊔ (t₁.arity ⊔ t₂.arity) ⊔ (t₁.arity ⊔ t₂.arity))
| .lor p q => max p.arity q.arity
| .land p q => max p.arity q.arity

def alive_AddSub_1152_src   :=
[llvm()| {
^bb0(%y : i1, %x : i1):
  %v1 = llvm.add %x, %y : i1
  llvm.return %v1 : 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 sub_select_sext_op_swapped_non_const_args_before := [llvm|
{
^0(%arg6 : i1, %arg7 : i6, %arg8 : i6):
  %0 = "llvm.select"(%arg6, %arg7, %arg8) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i6, i6) -> i6
  %1 = llvm.sext %arg6 : i1 to i6
  %2 = llvm.sub %1, %0 : i6
  "llvm.return"(%2) : (i6) -> ()
}
]

Std.Tactic.BVDecide.BVUnOp.rotateRight in Std.Tactic.BVDecide.Bitblast.BVExpr.Basic

def wellformed (fileName : String ) : IO UInt32 := do
    let icom? ← parseComFromFile fileName
    match icom? with
    | none => return 1
    | some (Sigma.mk _Γ ⟨_eff, ⟨_retTy, c⟩⟩) => do
      IO.println s!"{Com.printModule c}"
      return 0

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

def src_is_mask_const_sgt_before := [llvm|
{
^0(%arg47 : i8):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(7 : i8) : i8
  %2 = llvm.xor %arg47, %0 : i8
  %3 = llvm.and %2, %1 : i8
  %4 = llvm.icmp "sgt" %2, %3 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

def ashr_xor_before := [llvm|
{
^0(%arg20 : i8):
  %0 = llvm.mlir.constant(-128 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(-64 : i8) : i8
  %3 = llvm.ashr %0, %arg20 : i8
  %4 = llvm.add %arg20, %1 : i8
  %5 = llvm.ashr %2, %4 : i8
  %6 = llvm.xor %3, %5 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

def n9_after := [llvm|
{
^0(%arg1 : i64):
  %0 = llvm.mlir.constant(62) : i64
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.lshr %arg1, %0 : i64
  %3 = llvm.trunc %2 overflow<nsw,nuw> : i64 to i32
  %4 = llvm.sub %1, %3 overflow<nsw> : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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

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

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

String.intercalate in Init.Data.String.Defs

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

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

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

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

def OrLshrLshr : 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.lshr %x, %z : i64
      %1 = llvm.lshr %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.lshr %0, %z : i64
      llvm.return %1 : i64
  }]

def sdiv_shl_pair1_before := [llvm|
{
^0(%arg43 : i32, %arg44 : i32, %arg45 : i32):
  %0 = llvm.shl %arg43, %arg44 overflow<nsw> : i32
  %1 = llvm.shl %arg43, %arg45 overflow<nsw,nuw> : i32
  %2 = llvm.sdiv %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def add_shl_sext_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 32)] where
  lhs := add_shl_sext_llvm
  rhs := add_shl_sext_riscv

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

def test : DCOp.ValueStream (BitVec 8) × DCOp.ValueStream (BitVec 8) :=
  DCFork.denote (Ctxt.Valuation.ofHVector (.cons x <| .nil))

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

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

def test38_before := [llvm|
{
^0(%arg155 : i32):
  %0 = llvm.mlir.constant(-2 : i32) : i32
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.icmp "eq" %arg155, %0 : i32
  %3 = llvm.zext %2 : i1 to i8
  %4 = llvm.xor %3, %1 : i8
  %5 = llvm.zext %4 : i8 to i64
  "llvm.return"(%5) : (i64) -> ()
}
]

noncomputable def TV_add_zero_lhs : PeepholeRewrite (ModArith q) [.modLike] .modLike :=
{
  lhs := test_add_zero_lhs_LHS,
  rhs := test_add_zero_lhs_RHS,
  correct := by admit /- proof elided -/

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

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

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

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

instance : EmptyCollection MedusaSynthGeneralizeConfig where
  emptyCollection := {}

declare_config_elab elabMedusaSynthGeneralizeConfig MedusaSynthGeneralizeConfig

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

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

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

def eq_commuted_before := [llvm|
{
^0(%arg2 : i8, %arg3 : i8):
  %0 = llvm.mlir.constant(43 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.sdiv %0, %arg3 : i8
  %3 = llvm.icmp "eq" %arg2, %1 : i8
  %4 = llvm.icmp "ult" %2, %arg2 : i8
  %5 = llvm.or %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

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

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

@[simp]
def EnvFin.get_castLe {w n n' : Nat} (env : EnvFin w n) (h : n' ≤ n) (i : Fin n') :
  (env.castLe h) i = env ⟨i, by admit /- proof elided -/
  ⟩ := rfl

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

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

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

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

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

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

def DialectMorphism.preserves_regSig (op : d.Op) :
    DialectSignature.regSig (f.mapOp op) = (DialectSignature.regSig op).map f.mapTy :=

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

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

def bool_add_lshr_after := [llvm|
{
^0(%arg14 : i1, %arg15 : i1):
  %0 = llvm.and %arg14, %arg15 : i1
  %1 = llvm.zext %0 : i1 to i2
  "llvm.return"(%1) : (i2) -> ()
}
]

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

def t1_flags_nuw_only_after := [llvm|
{
^0(%arg45 : i8, %arg46 : i8, %arg47 : i8):
  %0 = llvm.add %arg46, %arg47 overflow<nuw> : i8
  %1 = llvm.sub %arg45, %0 overflow<nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

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

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

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

def formatCircuit {α : Type u} (formatVar : α → Format)  (c : Circuit α) : Lean.Format :=
  match c with
  | .tru => "T"
  | .fals => "F"
  | .var b v =>
     let vstr := "v:" ++ formatVar v
     if b then vstr else "!" ++ vstr
  | .and l r => s!"(and {formatCircuit formatVar l} {formatCircuit formatVar r})"
  | .or l r => s!"(or {formatCircuit formatVar l} {formatCircuit formatVar r})"
  | .xor l r => s!"(xor {formatCircuit formatVar l} {formatCircuit formatVar r})"

instance {d : Dialect} [TyDenote d.Ty] [DialectSignature d] [DialectDenote d] :
    Coe d.Op (Scf d).Op where
  coe o := .coe o

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

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

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

def andn_or_cmp_2_logical_before := [llvm|
{
^0(%arg167 : i16, %arg168 : i16, %arg169 : i16):
  %0 = llvm.mlir.constant(42 : i16) : i16
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "sge" %arg167, %arg168 : i16
  %4 = llvm.icmp "slt" %arg167, %arg168 : i16
  %5 = llvm.icmp "ugt" %arg169, %0 : i16
  %6 = "llvm.select"(%5, %1, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %7 = "llvm.select"(%6, %4, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%7) : (i1) -> ()
}
]

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

def alive_Select_1105_tgt  (w : Nat)  :=
[llvm( w )| {
^bb0(%Y : _, %X : _):
  %v1 = llvm.copy %Y
  llvm.return %v1
}]

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

def eq_smin1_after := [llvm|
{
^0(%arg87 : i32, %arg88 : i32):
  %0 = llvm.icmp "sle" %arg87, %arg88 : i32
  "llvm.return"(%0) : (i1) -> ()
}
]

def and_sequence_40_lhs (w : Nat)   :=
[llvm( w )| {
^bb0(%C1 : _, %Z : _):
  %v1 = llvm.and %Z, %C1
  %v2 = llvm.and %v1, %C1
  %v3 = llvm.and %v2, %C1
  %v4 = llvm.and %v3, %C1
  %v5 = llvm.and %v4, %C1
  %v6 = llvm.and %v5, %C1
  %v7 = llvm.and %v6, %C1
  %v8 = llvm.and %v7, %C1
  %v9 = llvm.and %v8, %C1
  %v10 = llvm.and %v9, %C1
  %v11 = llvm.and %v10, %C1
  %v12 = llvm.and %v11, %C1
  %v13 = llvm.and %v12, %C1
  %v14 = llvm.and %v13, %C1
  %v15 = llvm.and %v14, %C1
  %v16 = llvm.and %v15, %C1
  %v17 = llvm.and %v16, %C1
  %v18 = llvm.and %v17, %C1
  %v19 = llvm.and %v18, %C1
  %v20 = llvm.and %v19, %C1
  %v21 = llvm.and %v20, %C1
  %v22 = llvm.and %v21, %C1
  %v23 = llvm.and %v22, %C1
  %v24 = llvm.and %v23, %C1
  %v25 = llvm.and %v24, %C1
  %v26 = llvm.and %v25, %C1
  %v27 = llvm.and %v26, %C1
  %v28 = llvm.and %v27, %C1
  %v29 = llvm.and %v28, %C1
  %v30 = llvm.and %v29, %C1
  %v31 = llvm.and %v30, %C1
  %v32 = llvm.and %v31, %C1
  %v33 = llvm.and %v32, %C1
  %v34 = llvm.and %v33, %C1
  %v35 = llvm.and %v34, %C1
  %v36 = llvm.and %v35, %C1
  %v37 = llvm.and %v36, %C1
  %v38 = llvm.and %v37, %C1
  %v39 = llvm.and %v38, %C1
  %v40 = llvm.and %v39, %C1
  llvm.return %v40
}]

def different_size_zext_zext_ult_before := [llvm|
{
^0(%arg24 : i4, %arg25 : i7):
  %0 = llvm.zext %arg24 : i4 to i25
  %1 = llvm.zext %arg25 : i7 to i25
  %2 = llvm.icmp "ult" %0, %1 : i25
  "llvm.return"(%2) : (i1) -> ()
}
]

def alive_Select_1105_tgt :=
[sllvm| {
^bb0(%Y : i64, %X : i64):
  %v1 = llvm.copy %Y : i64
  llvm.return %v1 : i64
}]

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

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

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

def and_two_ranges_to_mask_and_range_no_add_on_one_range_after := [llvm|
{
^0(%arg249 : i16):
  %0 = llvm.mlir.constant(-20 : i16) : i16
  %1 = llvm.mlir.constant(11 : i16) : i16
  %2 = llvm.and %arg249, %0 : i16
  %3 = llvm.icmp "ugt" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

def slt_after := [llvm|
{
^0(%arg3 : i64):
  %0 = llvm.mlir.constant(32) : i64
  %1 = llvm.mlir.constant(31 : i32) : i32
  %2 = llvm.lshr %arg3, %0 : i64
  %3 = llvm.trunc %2 overflow<nuw> : i64 to i32
  %4 = llvm.trunc %arg3 : i64 to i32
  %5 = llvm.ashr %4, %1 : i32
  %6 = llvm.icmp "slt" %5, %3 : i32
  "llvm.return"(%6) : (i1) -> ()
}
]

def Tensor1D : Dialect where
  Op := Op
  Ty := Ty

abbrev mfixed : Nat := 3 

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

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 function : Parser :=
  leading_parser argumentList >> arrow >> termParser

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

def fold_add_udiv_urem_or_disjoint_before := [llvm|
{
^0(%arg5 : i32):
  %0 = llvm.mlir.constant(10 : i32) : i32
  %1 = llvm.mlir.constant(4 : i32) : i32
  %2 = llvm.udiv %arg5, %0 : i32
  %3 = llvm.shl %2, %1 : i32
  %4 = llvm.urem %arg5, %0 : i32
  %5 = llvm.or disjoint %3, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

def test (w : ℕ) :
    Com InstCombine.LLVM [LLVM.Ty.bitvec w] .pure (LLVM.Ty.bitvec w) :=
  .var (const  w 0  ) <|
  .var (not    w 0  ) <|
  .var (neg    w 0  ) <|
  .var (and    w 0 0) <|
  .var (or     w 0 0) <|
  .var (xor    w 0 0) <|
  .var (shl    w 0 0) <|
  .var (lshr   w 0 0) <|
  .var (ashr   w 0 0) <|
  .var (sub    w 0 0) <|
  .var (add    w 0 0) <|
  .var (mul    w 0 0) <|
  .var (sdiv   w 0 0) <|
  .var (udiv   w 0 0) <|
  .var (srem   w 0 0) <|
  .var (urem   w 0 0) <|
  .var (icmp   w .eq 0 0) <|
  .var (select w 0 1 1) <|
  .ret ⟨0, rfl⟩

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

def sext_diff_i1_xor_sub_1_before := [llvm|
{
^0(%arg12 : i64, %arg13 : i1, %arg14 : i1):
  %0 = llvm.sext %arg13 : i1 to i64
  %1 = llvm.sext %arg14 : i1 to i64
  %2 = llvm.xor %0, %arg12 : i64
  %3 = llvm.sub %0, %1 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

inductive AffineMap
  | mk: AffineTuple -> AffineTuple -> AffineMap
  deriving DecidableEq, Repr

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

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

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

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

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

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

def t0_after := [llvm|
{
^0(%arg43 : i32, %arg44 : i32):
  %0 = llvm.mlir.constant(30 : i32) : i32
  %1 = llvm.lshr %arg43, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

instance : Inhabited (Ty q n) := ⟨Ty.index⟩

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

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

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

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

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

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

def eq_irregular_bit_widths_after := [llvm|
{
^0(%arg114 : i31, %arg115 : i31):
  %0 = llvm.mlir.constant(7 : i31) : i31
  %1 = llvm.lshr %arg114, %0 : i31
  %2 = llvm.trunc %1 : i31 to i11
  %3 = llvm.lshr %arg115, %0 : i31
  %4 = llvm.trunc %3 : i31 to i11
  %5 = llvm.icmp "eq" %2, %4 : i11
  "llvm.return"(%5) : (i1) -> ()
}
]

def or_and_not_not_wrong_a_after := [llvm|
{
^0(%arg382 : i32, %arg383 : i32, %arg384 : i32, %arg385 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.or %arg383, %arg385 : i32
  %2 = llvm.xor %1, %0 : i32
  %3 = llvm.or %arg382, %arg384 : i32
  %4 = llvm.xor %3, %0 : i32
  %5 = llvm.and %arg383, %4 : i32
  %6 = llvm.or %5, %2 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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 xor_common_op_commute3_after := [llvm|
{
^0(%arg202 : i8, %arg203 : i8):
  %0 = llvm.mlir.constant(5 : i8) : i8
  %1 = llvm.xor %arg202, %0 : i8
  %2 = llvm.mul %arg203, %arg203 : i8
  %3 = llvm.or %1, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

def bitwise_or_bitwise_or_icmps_comm2_before := [llvm|
{
^0(%arg190 : i8, %arg191 : i8, %arg192 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(0 : i8) : i8
  %3 = llvm.icmp "eq" %arg191, %0 : i8
  %4 = llvm.and %arg190, %1 : i8
  %5 = llvm.shl %1, %arg192 : i8
  %6 = llvm.and %arg190, %5 : i8
  %7 = llvm.icmp "eq" %4, %2 : i8
  %8 = llvm.icmp "eq" %6, %2 : i8
  %9 = llvm.or %7, %3 : i1
  %10 = llvm.or %9, %8 : i1
  "llvm.return"(%10) : (i1) -> ()
}
]

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

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

def foo1_or_signbit_lshr_without_shifting_signbit_after := [llvm|
{
^0(%arg112 : i32, %arg113 : i32, %arg114 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg113 overflow<nuw> : i32
  %3 = llvm.and %2, %arg112 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.shl %arg112, %arg114 : i32
  %6 = llvm.icmp "slt" %5, %1 : i32
  %7 = llvm.and %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

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

def pr89516_after := [llvm|
{
^0(%arg0 : i8, %arg1 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.icmp "slt" %arg1, %0 : i8
  %3 = llvm.shl %1, %arg0 overflow<nuw> : i8
  %4 = llvm.srem %1, %3 : i8
  %5 = "llvm.select"(%2, %3, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %6 = llvm.add %4, %5 overflow<nuw> : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

def lowmask_sub_zext_commute_before := [llvm|
{
^0(%arg223 : i5, %arg224 : i17):
  %0 = llvm.mlir.constant(31 : i17) : i17
  %1 = llvm.zext %arg223 : i5 to i17
  %2 = llvm.sub %arg224, %1 : i17
  %3 = llvm.and %2, %0 : i17
  "llvm.return"(%3) : (i17) -> ()
}
]

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

def xor_2_after := [llvm|
{
^0(%arg133 : i8, %arg134 : i1, %arg135 : i8, %arg136 : i8):
  %0 = llvm.mlir.constant(-124 : i8) : i8
  %1 = llvm.xor %arg136, %0 : i8
  %2 = "llvm.select"(%arg134, %arg135, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %3 = llvm.xor %arg133, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

def reduce_xor_common_op_commute1_after := [llvm|
{
^0(%arg7 : i4, %arg8 : i4, %arg9 : i4):
  %0 = llvm.xor %arg8, %arg9 : i4
  %1 = llvm.or %0, %arg7 : i4
  "llvm.return"(%1) : (i4) -> ()
}
]

def shl_lshr_eq_amt_multi_use_after := [llvm|
{
^0(%arg7 : i44):
  %0 = llvm.mlir.constant(33 : i44) : i44
  %1 = llvm.mlir.constant(2047 : i44) : i44
  %2 = llvm.shl %arg7, %0 : i44
  %3 = llvm.and %arg7, %1 : i44
  %4 = llvm.or disjoint %2, %3 : i44
  "llvm.return"(%4) : (i44) -> ()
}
]

def lshr_and_before := [llvm|
{
^0(%arg18 : i8):
  %0 = llvm.mlir.constant(48 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.mlir.constant(64 : i8) : i8
  %3 = llvm.lshr %0, %arg18 : i8
  %4 = llvm.add %arg18, %1 : i8
  %5 = llvm.lshr %2, %4 : i8
  %6 = llvm.and %3, %5 : i8
  "llvm.return"(%6) : (i8) -> ()
}
]

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

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

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

def test_xor_ne_after := [llvm|
{
^0(%arg64 : i8, %arg65 : i8, %arg66 : i8):
  %0 = llvm.xor %arg65, %arg64 : i8
  %1 = llvm.icmp "ne" %arg66, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

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

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

def xor_or_xor_common_op_commute7_after := [llvm|
{
^0(%arg62 : i32, %arg63 : i32, %arg64 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg62, %0 : i32
  %2 = llvm.and %arg63, %1 : i32
  %3 = llvm.xor %2, %arg64 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def set_bits_before := [llvm|
{
^0(%arg26 : i8, %arg27 : i1):
  %0 = llvm.mlir.constant(-6 : i8) : i8
  %1 = llvm.mlir.constant(5 : i8) : i8
  %2 = llvm.and %arg26, %0 : i8
  %3 = llvm.or %arg26, %1 : i8
  %4 = "llvm.select"(%arg27, %3, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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

def RawCNFA.transBV' (m : RawCNFA A) (res : BitVec m.stateMax) (s : m.states) (a : A) : BitVec m.stateMax :=
  let ts := m.tr s a
  ts.fold (init := res) fun res s => res ||| 1#m.stateMax <<< s

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

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

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 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 or_nontrivial_mask2_before := [llvm|
{
^0(%arg11 : i16):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.mlir.constant(-4096 : i16) : i16
  %2 = llvm.mlir.constant(20480 : i16) : i16
  %3 = llvm.trunc %arg11 : i16 to i8
  %4 = llvm.icmp "ne" %3, %0 : i8
  %5 = llvm.and %arg11, %1 : i16
  %6 = llvm.icmp "ne" %5, %2 : i16
  %7 = llvm.or %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

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

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

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

def xvar := @MultiWidth.Term.var (wcard := 1) (bcard := 0) (ncard := 0) (icard := 0) (pcard := 0) (tcard := 1) 
  (tctx := tctx) (v := ⟨0, by admit /- proof elided -/
  ⟩)

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

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

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

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

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

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

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

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

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

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

def args : BasicBlock Op T → List VarName
  | ⟨_, args, _⟩ => args

def select_icmp_ne_0_and_32_xor_4096_after := [llvm|
{
^0(%arg199 : i32, %arg200 : i32):
  %0 = llvm.mlir.constant(7 : i32) : i32
  %1 = llvm.mlir.constant(4096 : i32) : i32
  %2 = llvm.shl %arg199, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.xor %3, %arg200 : i32
  %5 = llvm.xor %4, %1 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def reduce_xor_common_op_commute0_before := [llvm|
{
^0(%arg10 : i4, %arg11 : i4, %arg12 : i4):
  %0 = llvm.xor %arg10, %arg11 : i4
  %1 = llvm.xor %0, %arg12 : i4
  %2 = llvm.or %1, %arg10 : i4
  "llvm.return"(%2) : (i4) -> ()
}
]

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

def test11_after := [llvm|
{
^0(%arg84 : i32, %arg85 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.zext %arg84 : i32 to i64
  %2 = llvm.and %arg85, %0 : i32
  %3 = llvm.zext nneg %2 : i32 to i64
  %4 = llvm.shl %1, %3 overflow<nsw,nuw> : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

def bools2_logical_commute1_after := [llvm|
{
^0(%arg52 : i1, %arg53 : i1, %arg54 : i1):
  %0 = "llvm.select"(%arg54, %arg52, %arg53) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def drop_nuw_trunc_before := [llvm|
{
^0(%arg11 : i16, %arg12 : i16):
  %0 = llvm.mlir.constant(255 : i16) : i16
  %1 = llvm.and %arg11, %0 : i16
  %2 = llvm.and %1, %arg12 : i16
  %3 = llvm.trunc %2 overflow<nuw> : i16 to i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def src_srem_shl_demand_max_signbit_before := [llvm|
{
^0(%arg24 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(30 : i32) : i32
  %2 = llvm.mlir.constant(-2147483648 : i32) : i32
  %3 = llvm.srem %arg24, %0 : i32
  %4 = llvm.shl %3, %1 : i32
  %5 = llvm.and %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

def udiv_illegal_type_after := [llvm|
{
^0(%arg23 : i9, %arg24 : i9):
  %0 = llvm.udiv %arg23, %arg24 : i9
  %1 = llvm.zext %0 : i9 to i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def passriscv64 (fileName : String) : IO UInt32 := do
    let icom? ← Com.parseFromFile LLVMPlusRiscV fileName
    match icom? with
    | none => return 1
    | some (Sigma.mk _Γ ⟨eff, ⟨retTy, c⟩⟩) =>
      match eff with
      | EffectKind.pure =>
        match retTy with
        | [Ty.llvm (.bitvec _w)]  =>
           
          let lowered := selectionPipeFuelWithCSE 150 c true

          IO.println <| lowered.printModule
          return 0
        | _ =>
        IO.println s!" debug: WRONG RETURN TYPE : expected Ty.llvm (Ty.bitvec 64) "
        return 1
      | _ =>
      IO.println s!" debug: WRONG EFFECT KIND : expected pure program "
      return 1

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

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

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

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

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

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

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

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

def GLobalISelO0PreLegalizerCombiner :
    List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) :=
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  not_cmp_fold)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  double_icmp_zero_combine)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
   mul_by_neg_one)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
    sub_to_add)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  mul_to_shl)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  udiv_pow2)

def mul64_low_before := [llvm|
{
^0(%arg20 : i64, %arg21 : i64):
  %0 = llvm.mlir.constant(4294967295) : i64
  %1 = llvm.mlir.constant(32) : i64
  %2 = llvm.and %arg20, %0 : i64
  %3 = llvm.lshr %arg20, %1 : i64
  %4 = llvm.and %arg21, %0 : i64
  %5 = llvm.lshr %arg21, %1 : i64
  %6 = llvm.mul %5, %2 : i64
  %7 = llvm.mul %4, %3 : i64
  %8 = llvm.mul %4, %2 : i64
  %9 = llvm.add %6, %7 : i64
  %10 = llvm.shl %9, %1 : i64
  %11 = llvm.add %10, %8 : i64
  "llvm.return"(%11) : (i64) -> ()
}
]

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

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

def Expr.mk {Γ} {ty}
    (varName : VarName)
    (op : Op) (ty_eq : ty = (signature op).returnType)
    (args : VarList Γ (signature op).arguments)
    (regions : RegionList Op (signature op).regions) :
    Expr Op Γ ty :=
  ⟨⟨varName, op, args.val, regions.val⟩, by admit /- proof elided -/
  ⟩

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

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

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

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

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

def 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 and_not_or_commute8_after := [llvm|
{
^0(%arg457 : i32, %arg458 : i32, %arg459 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg457 : i32
  %3 = llvm.sdiv %0, %arg458 : i32
  %4 = llvm.xor %3, %arg459 : i32
  %5 = llvm.and %4, %2 : i32
  %6 = llvm.xor %5, %1 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def listAllTests : IO Unit := do
  IO.println s!"{tests.map (fun t => t.name.toString)}"

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

def t4_commutative_before := [llvm|
{
^0(%arg34 : i8, %arg35 : i8):
  %0 = llvm.add %arg34, %arg35 : i8
  %1 = llvm.icmp "ule" %arg35, %0 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

Std.HashMap.union in Std.Data.HashMap.Basic

def Deleted.append {Γ : Ctxt Ty} {vs : DeleteRange Γ}
    (DEL : Deleted Γ vs Γ') (ωs : List Ty) :
    Deleted (⟨ωs⟩ ++ Γ) vs.appendInl (⟨ωs⟩ ++ Γ') :=

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

def n11_before := [llvm|
{
^0(%arg5 : i32, %arg6 : i16):
  %0 = llvm.mlir.constant(30 : i16) : i16
  %1 = llvm.mlir.constant(-31 : i16) : i16
  %2 = llvm.sub %0, %arg6 : i16
  %3 = llvm.zext %2 : i16 to i32
  %4 = llvm.shl %arg5, %3 : i32
  %5 = llvm.trunc %4 : i32 to i16
  %6 = llvm.add %arg6, %1 : i16
  %7 = llvm.shl %5, %6 : i16
  "llvm.return"(%7) : (i16) -> ()
}
]

def test18_before := [llvm|
{
^0(%arg6 : i128):
  %0 = llvm.mlir.constant(2 : i128) : i128
  %1 = llvm.shl %arg6, %0 : i128
  %2 = llvm.shl %arg6, %0 : i128
  %3 = llvm.sub %1, %2 : i128
  "llvm.return"(%3) : (i128) -> ()
}
]

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

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

def ex2' : Com ∅ .nat :=
  Com.var (cst 1) <|
  Com.var (add ⟨0, by admit /- proof elided -/
  ⟩ ⟨0, by admit /- proof elided -/
  ⟩  ) <|
  Com.var (add ⟨1, by admit /- proof elided -/
  ⟩ ⟨0, by admit /- proof elided -/
  ⟩  ) <|
  Com.var (add ⟨1, by admit /- proof elided -/
  ⟩ ⟨1, by admit /- proof elided -/
  ⟩  ) <|
  Com.var (add ⟨1, by admit /- proof elided -/
  ⟩ ⟨1, by admit /- proof elided -/
  ⟩  ) <|
  Com.ret ⟨0, by admit /- proof elided -/
  ⟩

Array.back? in Init.Data.Array.Basic

Union in Init.Core
</all_available_defs>

<all_available_lemmas>
Option.map_map in Init.Data.Option.Lemmas

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 val_lt (v : Γ.Var t) : v.val < Γ.length

@[simp, grind=] theorem length_ofList : (ofList ts).length = ts.length

@[simp, grind=] theorem getElem?_ofList (i : Nat) : (ofList ts)[i]? = ts[i]?

@[simp] theorem appendCases_appendInl (v : Γ.Var t) :
    appendCases (motive := motive) left right v.appendInl = (left v)

theorem lshr_mul_negative_nonuw_proof : lshr_mul_negative_nonuw_before ⊑ lshr_mul_negative_nonuw_after

theorem or_consts_logical_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and (const? 32 4) e) (const? 32 0))
      (icmp IntPred.ne (LLVM.and (const? 32 8) e) (const? 32 0)) (const? 1 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 12)) (const? 32 12)

theorem t4_ugt_slt_128_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬ofBool (143#32 <ᵤ x + 16#32) = 1#1 →
    ofBool (127#32 <ₛ x) = 1#1 ∨ ofBool (x <ₛ BitVec.ofInt 32 (-16)) = 1#1 → False

theorem test19_proof : test19_before ⊑ test19_after

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

theorem sub_ashr_or_i8_proof : sub_ashr_or_i8_before ⊑ sub_ashr_or_i8_after

theorem icmp_ult_x_y_proof : icmp_ult_x_y_before ⊑ icmp_ult_x_y_after

theorem test_sge_xor_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 ^^^ -1#32 ≤ₛ x_1 ^^^ -1#32 ^^^ x) = ofBool (x ^^^ x_1 ≤ₛ x_1)

theorem uge_to_slt_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (15#8 ≤ᵤ x ^^^ 127#8) = ofBool (x <ₛ 113#8)

theorem mul_constant_partial_nuw_eq_proof : mul_constant_partial_nuw_eq_before ⊑ mul_constant_partial_nuw_eq_after

theorem scf.for.peel_begin (n : Nat) (f : Nat → β → β) (seed : β) :
  scf.for.loop f (n + 1) n (f 0 seed) = scf.for.loop f (n + 1) (n + 1) seed

@[simp] theorem foldl_cons :
    foldl f b (cons x xs) = foldl f (f _ b x) xs

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

theorem ashr_ugt_2_proof : ashr_ugt_2_before ⊑ ashr_ugt_2_after

theorem sgt_swap_and_min_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.eq e_1 (const? 8 (-128))) (icmp IntPred.slt e e_1) (const? 1 0) ⊑ const? 1 0

theorem test3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), ¬x = 0 → ofBool (x_1 / x != 0#32) = ofBool (x ≤ᵤ x_1)

theorem test15i_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 2#32 != 0#32) = 1#1 → ¬ofBool (x &&& 2#32 == 0#32) = 1#1 → 1089#32 = 577#32

theorem e_907 :
    11 *  ~~~(z &&&  ~~~z) + 1 * (z ||| t) - 5 *  ~~~t + 2 *  ~~~z - 8 *  ~~~(z ||| t) - 7 * (z &&&  ~~~t) = 14 *  ~~~(z |||  ~~~t) + 12 * (z &&& t)

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

theorem test13_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  x_1 + 1#32 + ((x ||| BitVec.ofInt 32 (-1431655767)) ^^^ 1431655766#32) = x_1 - (x &&& 1431655766#32)

theorem test67_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ofBool (x &&& 4#16 != 0#16) = 1#1 → ofBool (x &&& 4#16 == 0#16) = 1#1 → 40#32 = 42#32

theorem not_cond_proof : not_cond_before ⊑ not_cond_after

theorem lor_land_left1_proof : lor_land_left1_before ⊑ lor_land_left1_after

theorem test6_proof : test6_before ⊑ test6_after

theorem e_1506 :
    7 *  ~~~(a ^^^ b) + 1 *  ~~~a - 1 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 7 *  ~~~(a ||| (b ||| c)) - 6 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 13 * ( ~~~a &&& ( ~~~b &&& c)) - 5 * ( ~~~a &&& (b &&& c)) - 12 * (a &&& (b &&& c)) =  - 5 * (c ^^^ (a &&&  ~~~b)) + 5 *  ~~~( ~~~a ||| (b ||| c))

theorem t2_ult_sgt_128_thm.extracted_1._5 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 + 16#32 <ᵤ 144#32) = 1#1 →
    ¬ofBool (127#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ BitVec.ofInt 32 (-16)) = 1#1 → x_1 = x

theorem xor_or_xor_common_op_commute5_proof : xor_or_xor_common_op_commute5_before ⊑ xor_or_xor_common_op_commute5_after

theorem alive_constant_fold_10: forall (w : Nat), TSSA.eval
  (Op := Op) (e := e)
  (i := TSSAIndex.STMT (UserType.base (BaseType.bitvec w)))
  [dsl_bb|
  ^bb
  %v0 := unit: ;
  %v1 := op:const (Bitvec.ofInt w (0)) %v0
  dsl_ret %v1
  ]  ⊑
  TSSA.eval
  (Op := Op) (e := e)
  (i := TSSAIndex.STMT (UserType.base (BaseType.bitvec w)))
  [dsl_bb|
  ^bb
  %v000 := unit: ;
  %v001 := op:const (Bitvec.ofInt w (0)) %v000;
  %v100 := pair:%v001 %v001;
  %v101 := op:add w %v100;
  %v110 := pair:%v101 %v001;
  %v111 := op:add w %v110;
  %v120 := pair:%v111 %v001;
  %v121 := op:add w %v120;
  %v130 := pair:%v121 %v001;
  %v131 := op:add w %v130;
  %v140 := pair:%v131 %v001;
  %v141 := op:add w %v140;
  %v150 := pair:%v141 %v001;
  %v151 := op:add w %v150;
  %v160 := pair:%v151 %v001;
  %v161 := op:add w %v160;
  %v170 := pair:%v161 %v001;
  %v171 := op:add w %v170;
  %v180 := pair:%v171 %v001;
  %v181 := op:add w %v180;
  %v190 := pair:%v181 %v001;
  %v191 := op:add w %v190
  dsl_ret %v191
  ]

theorem masked_and_notallzeroes_logical_proof : masked_and_notallzeroes_logical_before ⊑ masked_and_notallzeroes_logical_after

theorem cmpeq_xor_cst1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 ^^^ 10#32 == x) = ofBool (x_1 ^^^ x == 10#32)

theorem ashrslt_01_07_proof : ashrslt_01_07_before ⊑ ashrslt_01_07_after

theorem e_2173 :
    2 * (e |||  ~~~f) + 3 * (f &&& (d ^^^ e)) + 1 *  ~~~f - 1 * (f ^^^ (d ||| e)) + 5 *  ~~~( ~~~d ||| (e &&& f)) + 7 * (d ||| (e ||| f)) + 2 * (e ^^^ f) + 1 * ((e &&& f) ||| (d &&& (e ||| f))) + 5 * (e ^^^ (d |||  ~~~f)) + 2 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 7 * ((d ^^^ e) ||| (d ^^^ f)) + 1 * (e ^^^ (d ||| ( ~~~e &&& f))) + 1 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) + 11 * (f ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 3 * (f |||  ~~~(d ||| e)) - 1 * ( ~~~e ||| (d ^^^ f)) + 11 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 11 * ((d &&& e) |||  ~~~(e ^^^ f)) + 2 * (d ||| f) - 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) + 5 * (e |||  ~~~(d ||| f)) - 6 * (e ^^^  ~~~(d &&& (e ||| f))) + 4 *  ~~~(d &&& ( ~~~e &&& f)) + 5 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 6 * (f ^^^  ~~~(d |||  ~~~e)) + 7 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) - 11 *  ~~~(d |||  ~~~e) + 4 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 5 * (d ^^^ (e ^^^ f)) - 5 * (f ^^^ (d ||| ( ~~~e ||| f))) + 2 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 2 * ( ~~~f ||| (d ^^^ e)) + 1 * (f ^^^  ~~~(d &&& (e ||| f))) - 1 * (e &&&  ~~~(d &&& f)) + 3 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) - 3 * (f ^^^ (d ||| ( ~~~e &&& f))) - 2 * (e ^^^ ( ~~~d ||| (e &&& f))) - 3 *  ~~~(d &&&  ~~~d) - 6 * (e ^^^ (d &&& f)) - 1 * (f ^^^ ( ~~~d &&& (e ||| f))) - 2 * (f &&&  ~~~(d &&& e)) - 5 * (f &&& (d ||| e)) - 18 *  ~~~(d ||| (e ||| f)) - 7 *  ~~~(d ||| ( ~~~e ||| f)) - 28 *  ~~~( ~~~d ||| (e ||| f)) - 26 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 13 * ( ~~~d &&& ( ~~~e &&& f)) - 34 * (d &&& ( ~~~e &&& f)) + 11 * (d &&& (e &&& f)) =  - 4 * (e ^^^  ~~~(d &&&  ~~~f)) + 11 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f)))

theorem eq_umin1_proof : eq_umin1_before ⊑ eq_umin1_after

theorem uadd_sat_flipped_wrong_bounds4_thm (e : IntW 32) :
  select (icmp IntPred.uge e (const? 32 (-8))) (const? 32 (-1)) (add e (const? 32 9)) ⊑
    select (icmp IntPred.ugt e (const? 32 (-9))) (const? 32 (-1)) (add e (const? 32 9))

theorem ashrslt_03_11_proof : ashrslt_03_11_before ⊑ ashrslt_03_11_after

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

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

theorem e_2258 :
     - 2 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 2 * (d |||  ~~~e) - 1 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) - 6 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 7 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 2 *  ~~~(d ^^^ ( ~~~e &&& f)) + 5 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) - 1 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 2 *  ~~~(d &&& (e &&& f)) + 1 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 11 * (f ^^^ ( ~~~d ||| (e ||| f))) - 1 * (f &&& (d |||  ~~~e)) + 11 * (e |||  ~~~(d |||  ~~~f)) + 3 * (f ^^^ (d ||| ( ~~~e ||| f))) - 5 * (e ^^^ ( ~~~d ||| (e ^^^ f))) - 1 * (f ^^^  ~~~(d &&& e)) - 7 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 1 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 11 * (d ||| (e &&& f)) + 3 * ((d &&& e) ||| (e ^^^ f)) + 3 * (f ^^^ (d &&& (e ||| f))) - 6 * (e &&&  ~~~(d &&&  ~~~f)) + 3 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 2 * (e ^^^ ( ~~~d ||| (e ||| f))) - 1 * (e ^^^ (d &&& ( ~~~e ||| f))) - 3 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) - 2 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 6 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) + 1 * (d &&& f) - 2 * (f ||| (d &&& e)) - 1 * (e ^^^ (d |||  ~~~f)) - 7 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 11 * (f ^^^  ~~~(d ||| e)) - 7 *  ~~~(d ^^^ ( ~~~e ||| f)) - 2 * ((d &&& e) |||  ~~~(e ||| f)) - 1 * ( ~~~d &&& (e ^^^ f)) + 11 * (e ^^^ (d ||| (e ^^^ f))) + 7 * (d ||| (e ||| f)) + 2 * ( ~~~e &&&  ~~~(d ^^^ f)) + 11 *  ~~~(e &&&  ~~~f) - 1 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) + 5 * (e ^^^  ~~~(d &&& (e &&& f))) - 1 * (d ||| ( ~~~e ||| f)) + 3 * ((d &&& f) ||| (e &&&  ~~~f)) + 1 * (f ||| (d ^^^ e)) + 4 * ( ~~~d ||| (e ^^^ f)) - 3 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 5 * (f ^^^ (d ||| e)) + 2 * ((d &&& e) |||  ~~~(e ^^^ f)) + 1 *  ~~~(d |||  ~~~e) - 11 *  ~~~(d ||| (e ||| f)) + 9 *  ~~~(d ||| ( ~~~e ||| f)) - 29 *  ~~~( ~~~d ||| (e ||| f)) - 22 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 45 * ( ~~~d &&& ( ~~~e &&& f)) - 32 * ( ~~~d &&& (e &&& f)) - 35 * (d &&& ( ~~~e &&& f)) - 32 * (d &&& (e &&& f)) = 11 * (e ||| (d &&&  ~~~f)) - 5 * (e ^^^ ( ~~~d &&& (e ^^^ f)))

theorem no_shift_xor_multiuse_or_thm (e e_1 : IntW 32) :
  mul (select (icmp IntPred.ne (const? 32 0) (LLVM.and e_1 (const? 32 4096))) e (LLVM.or e (const? 32 4096)))
      (LLVM.or e (const? 32 4096)) ⊑
    mul (LLVM.or e (LLVM.xor (LLVM.and e_1 (const? 32 4096)) (const? 32 4096))) (LLVM.or e (const? 32 4096))

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

theorem e_805 :
    11 * t + 5 *  ~~~z - 5 *  ~~~(z ||| t) - 21 *  ~~~(z |||  ~~~t) - 5 * (z &&&  ~~~t) =  - 5 * (z ^^^ t) + 11 * (z &&& t)

theorem lshrult_03_08_thm (e : IntW 4) : icmp IntPred.ult (lshr e (const? 4 3)) (const? 4 (-8)) ⊑ const? 1 1

theorem icmp_slt_0_and_icmp_sge_neg1_i64_thm (e : IntW 64) :
  LLVM.and (lshr e (const? 64 63)) (zext 64 (icmp IntPred.sge e (const? 64 (-1)))) ⊑
    zext 64 (icmp IntPred.eq e (const? 64 (-1)))

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

theorem drop_nuw_trunc_proof : drop_nuw_trunc_before ⊑ drop_nuw_trunc_after

theorem test16_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬1#32 ≥ ↑32 →
    ¬(1#32 ≥ ↑32 ∨ True ∧ (BitVec.ofInt 32 (-2)).usubOverflow (x >>> 1#32) = true) →
      4294967294#64 - zeroExtend 64 (x >>> 1#32) = zeroExtend 64 (BitVec.ofInt 32 (-2) - x >>> 1#32)

theorem slt_zero_ne_ne_0_proof : slt_zero_ne_ne_0_before ⊑ slt_zero_ne_ne_0_after

theorem shift_no_xor_multiuse_cmp_thm.extracted_1._8 : ∀ (x x_1 x_2 x_3 : BitVec 32),
  ¬ofBool (x_3 &&& 1#32 == 0#32) = 1#1 →
    ¬(True ∧ ((x_3 &&& 1#32) <<< 1#32).sshiftRight' 1#32 ≠ x_3 &&& 1#32 ∨
          True ∧ (x_3 &&& 1#32) <<< 1#32 >>> 1#32 ≠ x_3 &&& 1#32 ∨ 1#32 ≥ ↑32) →
      (x_2 ||| 2#32) * x = (x_2 ||| (x_3 &&& 1#32) <<< 1#32) * x

theorem or_trunc_lshr_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬1#8 ≥ ↑8 → 1#6 ≥ ↑6 ∨ True ∧ (truncate 6 x >>> 1#6 &&& BitVec.ofInt 6 (-32) != 0) = true → False

theorem icmp_eq_or_z_or_pow2orz_fail_nonzero_const_proof : icmp_eq_or_z_or_pow2orz_fail_nonzero_const_before ⊑ icmp_eq_or_z_or_pow2orz_fail_nonzero_const_after

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

theorem e_2289 :
     - 7 *  ~~~(d ^^^ (e ||| f)) + 2 * (f ||| (d &&&  ~~~e)) + 2 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 1 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 1 * (e ^^^ (d &&&  ~~~f)) + 3 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) - 2 *  ~~~( ~~~d ||| ( ~~~e &&& f)) + 2 *  ~~~(d ^^^ ( ~~~e &&& f)) - 5 * (f ^^^ ( ~~~d ||| (e &&& f))) + 2 * (e &&& f) - 7 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) - 3 * (f ^^^ (d ||| ( ~~~e ||| f))) - 7 * ( ~~~d ||| ( ~~~e ||| f)) + 11 * ((d ^^^ e) ||| (d ^^^ f)) + 2 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 2 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) + 1 *  ~~~(d ||| f) + 2 * (d ^^^ ( ~~~e &&& f)) + 4 * ( ~~~f ||| (d ^^^ e)) - 11 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 * (e &&& (d |||  ~~~f)) + 2 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 1 *  ~~~(d ^^^ ( ~~~e ||| f)) + 5 * ( ~~~d ||| (e &&& f)) + 1 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) + 7 *  ~~~( ~~~d &&& (e ^^^ f)) + 11 * (f ^^^ (d &&& e)) - 3 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 7 * ((d &&& e) |||  ~~~(e ||| f)) - 1 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 7 * (f |||  ~~~(d ||| e)) + 1 * (d ||| ( ~~~e ||| f)) - 1 * (e ^^^ (d &&& (e ||| f))) - 7 * (e ^^^ ( ~~~d &&& (e ||| f))) - 3 *  ~~~(d ^^^ (e ^^^ f)) - 1 * (e &&&  ~~~(d &&&  ~~~f)) + 11 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 3 *  ~~~(d ||| (e ^^^ f)) + 1 * (f ^^^  ~~~(d &&& (e &&& f))) + 1 * ((d |||  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * (e ^^^ (d ||| ( ~~~e &&& f))) + 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 6 * ( ~~~f &&& (d ^^^ e)) - 2 * (e ^^^ ( ~~~d ||| (e &&& f))) - 11 * (e ||| (d &&& f)) - 2 *  ~~~( ~~~d &&& (e ||| f)) - 2 * (e ^^^ (d ||| (e &&& f))) - 3 *  ~~~(d ^^^ f) - 2 * ((d &&& f) |||  ~~~(e ||| f)) - 2 *  ~~~(d &&& (e ||| f)) - 6 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 11 * (d &&& ( ~~~e ||| f)) - 1 * (e &&&  ~~~(d &&& f)) + 3 *  ~~~(d ||| (e ||| f)) + 8 *  ~~~(d ||| ( ~~~e ||| f)) + 8 *  ~~~( ~~~d ||| (e ||| f)) + 8 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 14 * ( ~~~d &&& ( ~~~e &&& f)) - 36 * ( ~~~d &&& (e &&& f)) + 9 * (d &&& ( ~~~e &&& f)) + 38 * (d &&& (e &&& f)) =  - 7 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) + 5 * e

theorem decideIfZeroAux_wf {α : Type _} [Fintype α] [DecidableEq α]
    {c c' : Circuit α} (h : ¬c' ≤ c) : card_compl (c' ||| c) < card_compl c

theorem lshr_by_const_cmp_sge_value_proof : lshr_by_const_cmp_sge_value_before ⊑ lshr_by_const_cmp_sge_value_after

theorem icmp_eq_sext_eq_allones_proof : icmp_eq_sext_eq_allones_before ⊑ icmp_eq_sext_eq_allones_after

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

theorem xor_or_xor_proof : xor_or_xor_before ⊑ xor_or_xor_after

theorem or_test2_proof : or_test2_before ⊑ or_test2_after

theorem pr89516_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 <ₛ 0#8) = 1#1 →
    ¬(True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨
          x ≥ ↑8 ∨
            (1#8 <<< x == 0 || 8 != 1 && 1#8 == intMin 8 && 1#8 <<< x == -1) = true ∨
              True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8 ∨ True ∧ ((1#8).srem (1#8 <<< x)).uaddOverflow (1#8 <<< x) = true) →
      ¬(True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨
            x ≥ ↑8 ∨ (1#8 <<< x == 0 || 8 != 1 && 1#8 == intMin 8 && 1#8 <<< x == -1) = true) →
        ¬(True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8) →
          True ∧ ((1#8).srem (1#8 <<< x)).uaddOverflow (1#8 <<< x) = true → False

lemma CNFA.ofFSM_bv_language :
    (CNFA.ofFSM (FSM.ofTerm t)).bv_recognizes t.language

theorem e_894 :
    3 *  ~~~t - 6 *  ~~~(z &&&  ~~~z) + 10 *  ~~~(z ||| t) + 6 *  ~~~(z |||  ~~~t) + 10 * (z &&&  ~~~t) + 13 * (z &&& t) = 7 * (z |||  ~~~t)

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

theorem lshrugt_02_13_proof : lshrugt_02_13_before ⊑ lshrugt_02_13_after

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

theorem t0_proof : t0_before ⊑ t0_after

theorem pr51551_proof : pr51551_before ⊑ pr51551_after

theorem nonexact_lshr_eq_proof : nonexact_lshr_eq_before ⊑ nonexact_lshr_eq_after

theorem samesign_commute1_proof : samesign_commute1_before ⊑ samesign_commute1_after

private theorem decide_and_decide_eq_decide {P Q : Prop}
  [Decidable P] [Decidable Q] :
  (decide P && decide Q) = decide (P ∧ Q)

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

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

theorem Factor.denoteFin_eq_denote {f : Factor} {xs : List (BitVec w)} {xsFin : EnvFin w f.numVars}
    (h : ∀ (i : Fin f.numVars), xs[i]?.getD 0#w = xsFin i) :
    f.denoteFin xsFin = f.denote xs

theorem ashrslt_02_04_proof : ashrslt_02_04_before ⊑ ashrslt_02_04_after

theorem fold_icmp_shl_nuw_c2_precondition3_thm (e : IntW 32) :
  icmp IntPred.ult (shl (const? 32 1) e { «nsw» := false, «nuw» := true }) (const? 32 1) ⊑ const? 1 0

theorem t2_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬63#64 ≥ ↑64 →
    63#64 ≥ ↑64 ∨
        True ∧ signExtend 64 (truncate 32 (x >>> 63#64)) ≠ x >>> 63#64 ∨
          True ∧ zeroExtend 64 (truncate 32 (x >>> 63#64)) ≠ x >>> 63#64 →
      False

theorem ashr_lshr_shift_amt_mismatch_proof : ashr_lshr_shift_amt_mismatch_before ⊑ ashr_lshr_shift_amt_mismatch_after

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

theorem lshrult_03_10_exact_proof : lshrult_03_10_exact_before ⊑ lshrult_03_10_exact_after

theorem mul_splat_fold_too_narrow_thm.extracted_1._1 : ∀ (x : BitVec 2),
  ¬(True ∧ x.umulOverflow (BitVec.ofInt 2 (-2)) = true ∨ 1#2 ≥ ↑2) → (x * BitVec.ofInt 2 (-2)) >>> 1#2 = x

theorem trunc_nsw_xor_proof : trunc_nsw_xor_before ⊑ trunc_nsw_xor_after

theorem sel_false_val_is_a_masked_shl_of_true_val2_proof : sel_false_val_is_a_masked_shl_of_true_val2_before ⊑ sel_false_val_is_a_masked_shl_of_true_val2_after

theorem test1_proof : test1_before ⊑ test1_after

theorem test8_thm (e : IntW 999) : LLVM.and e (const? 999 0) ⊑ const? 999 0

theorem xor_logic_and_or1_proof : xor_logic_and_or1_before ⊑ xor_logic_and_or1_after

theorem zext_nneg_flag_drop_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ¬(True ∧ (x_1 &&& 127#8).msb = true) →
    zeroExtend 16 (x_1 &&& 127#8) ||

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

theorem zext_sext_add_icmp_eq_minus1_proof : zext_sext_add_icmp_eq_minus1_before ⊑ zext_sext_add_icmp_eq_minus1_after

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

theorem bitwise_and_logical_and_masked_icmp_allones_poison2_thm.extracted_1._3 : ∀ (x : BitVec 32) (x_1 : BitVec 1)
  (x_2 : BitVec 32),
  ¬ofBool (x_2 &&& 8#32 == 8#32) = 1#1 →
    ofBool (x_2 &&& 8#32 != 0#32) = 1#1 → 0#1 &&& ofBool (x_2 &&& x == x) = x_1 &&& ofBool (x_2 &&& x == x)

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

theorem test_sub_4_Y_ne_4_proof : test_sub_4_Y_ne_4_before ⊑ test_sub_4_Y_ne_4_after

theorem or_consts_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (4#32 &&& x != 0#32) &&& ofBool (8#32 &&& x != 0#32) = ofBool (x &&& 12#32 == 12#32)

theorem smear_set_bit_thm (e : IntW 32) :
  sext 32 (ashr (trunc 8 e) (const? 8 7)) ⊑ ashr (shl e (const? 32 24)) (const? 32 31)

@[simp] theorem scanAnd_zero (s : BitStream) : scanAnd s 0 = s 0

theorem t5_ugt_slt_0_thm.extracted_1._7 : ∀ (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 alive_AndOrXor_2595  (w : Nat)   : alive_AndOrXor_2595_src w  ⊑ alive_AndOrXor_2595_tgt w

theorem p0_proof : p0_before ⊑ p0_after

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

theorem e_81 :
    1 * y - 7 *  ~~~(x &&& y) + 7 *  ~~~x + 7 * (x &&&  ~~~y) - 1 * (x &&& y) = 1 *  ~~~(x |||  ~~~y)

theorem src3_proof : src3_before ⊑ src3_after

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

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

theorem lshrult_01_13_exact_proof : lshrult_01_13_exact_before ⊑ lshrult_01_13_exact_after

theorem lshr_shl_demand4_proof : lshr_shl_demand4_before ⊑ lshr_shl_demand4_after

theorem slt_smin3_thm (e e_1 : IntW 32) :
  icmp IntPred.sgt (add e_1 (const? 32 3))
      (select (icmp IntPred.slt (add e_1 (const? 32 3)) e) (add e_1 (const? 32 3)) e) ⊑
    icmp IntPred.slt e (add e_1 (const? 32 3))

lemma evalFinStream_evalFin {t : Term} {k : Nat} (hlt : k < w) (vars : Fin t.arity → BitVec w) :
    EqualUpTo w (t.evalFin (fun ar => BitStream.ofBitVecSext (vars ar))) (BitStream.ofBitVecSext $ t.evalFinBV vars)

@[simp]
theorem R.trimTensor_append_zero_eq (tensor : List Int) :
    trimTensor (tensor ++ [0]) = trimTensor tensor

theorem samesign_commute2_proof : samesign_commute2_before ⊑ samesign_commute2_after

theorem andn_or_cmp_4_logical_thm.extracted_1._7 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 == x_1) = 1#1 → ¬ofBool (x_2 != x_1) = 1#1 → True → ofBool (x_2 != x_1) = 0#1

theorem sgt_smax2_proof : sgt_smax2_before ⊑ sgt_smax2_after

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

@[simp]
lemma reduce_spec (M : NFA α σ) : M.reduce.accepts = M.accepts

theorem or_signbit_select_ashr_proof : or_signbit_select_ashr_before ⊑ or_signbit_select_ashr_after

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

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

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

theorem ashr_mul_times_3_div_2_exact_2_proof : ashr_mul_times_3_div_2_exact_2_before ⊑ ashr_mul_times_3_div_2_exact_2_after

theorem PR1817_2_logical_proof : PR1817_2_logical_before ⊑ PR1817_2_logical_after

theorem PR42691_2_logical_proof : PR42691_2_logical_before ⊑ PR42691_2_logical_after

theorem mul_constant_nuw_eq_proof : mul_constant_nuw_eq_before ⊑ mul_constant_nuw_eq_after

theorem a_or_b_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == 0#32) &&& ofBool (x != 0#32) ||

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

theorem icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail_proof : icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail_before ⊑ icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail_after

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

@[simp] theorem Lets.mk_inner (lets : Lets Op T) : ⟨lets.inner⟩ = lets

theorem PR2844_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x == 0#32) ||

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

theorem lshrugt_02_04_exact_proof : lshrugt_02_04_exact_before ⊑ lshrugt_02_04_exact_after

theorem narrow_zext_or_proof : narrow_zext_or_before ⊑ narrow_zext_or_after

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

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

theorem main9_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 64#32 != 0#32) &&& ofBool (truncate 8 x <ₛ 0#8) = 1#1 →
    ofBool (x &&& 192#32 == 192#32) = 1#1 → 1#32 = 2#32

theorem test2_proof : test2_before ⊑ test2_after

theorem ashrsgt_01_10_proof : ashrsgt_01_10_before ⊑ ashrsgt_01_10_after

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

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

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

theorem lshr_shl_pow2_const_case2_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 4#16 ≥ ↑16) → ofBool (x == 12#16) = 1#1 → 8192#16 >>> x <<< 4#16 &&& 32#16 = 32#16

theorem e_1568 :
    2 * (b ^^^ (a ||| ( ~~~b &&& c))) + 2 * ( ~~~c &&&  ~~~(a ^^^ b)) - 7 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c))) - 1 * (c ^^^  ~~~(a ||| (b &&& c))) - 2 * (b ^^^ (a &&& c)) - 11 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) + 5 * (a &&& c) - 1 * (b &&& (a ||| c)) + 17 *  ~~~(a ||| (b ||| c)) + 9 *  ~~~( ~~~a ||| (b ||| c)) + 1 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 9 * ( ~~~a &&& ( ~~~b &&& c)) + 9 * ( ~~~a &&& (b &&& c)) + 3 * (a &&& ( ~~~b &&& c)) + 8 * (a &&& (b &&& c)) =  - 12 *  ~~~(a ||| ( ~~~b ||| c))

theorem or_xor_common_op_commute6_thm (e e_1 e_2 : IntW 8) :
  LLVM.or (LLVM.xor e_2 e_1) (LLVM.or e_1 e) ⊑ LLVM.or (LLVM.or e_1 e) e_2

theorem main7g_logical_proof : main7g_logical_before ⊑ main7g_logical_after

theorem and_nosignbit_select_ashr_proof : and_nosignbit_select_ashr_before ⊑ and_nosignbit_select_ashr_after

theorem denote_rewritePeephole_go (pr : PeepholeRewrite d Γ t)
    (pos : ℕ) (target : Com d Γ₂ eff t₂) :
    (rewritePeephole_go fuel pr pos target).denote = target.denote

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

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

theorem icmp_slt_0_xor_icmp_sge_neg2_i32_fail_proof : icmp_slt_0_xor_icmp_sge_neg2_i32_fail_before ⊑ icmp_slt_0_xor_icmp_sge_neg2_i32_fail_after

theorem positive_sameconst_proof : positive_sameconst_before ⊑ positive_sameconst_after

theorem ashrsgt_01_15_proof : ashrsgt_01_15_before ⊑ ashrsgt_01_15_after

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

theorem sub_from_constant_of_sub_from_constant_thm.extracted_1._1 : ∀ (x : BitVec 8),
  11#8 - (42#8 - x) = x + BitVec.ofInt 8 (-31)

theorem not_logicalAnd_not_op1_proof : not_logicalAnd_not_op1_before ⊑ not_logicalAnd_not_op1_after

theorem lshrult_03_13_exact_proof : lshrult_03_13_exact_before ⊑ lshrult_03_13_exact_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_1_proof : masked_icmps_mask_notallzeros_bmask_mixed_1_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_1_after

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

theorem or_sext_to_sel_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → signExtend 32 x_1 ||

theorem 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 signed_sign_bit_extract_trunc_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬63#64 ≥ ↑64 → ofBool (truncate 32 (x.sshiftRight' 63#64) != 0#32) = ofBool (x <ₛ 0#64)

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

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

theorem C0zero_thm.extracted_1._6 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 + 10#8 <ᵤ 0#8) = 1#1 → ¬ofBool (x_1 <ₛ BitVec.ofInt 8 (-10)) = 1#1 → x_1 = x

theorem select_replace_nested_no_simplify_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 == 1#32) = 1#1 → x_1 - x_2 + x = x_1 + -1#32 + x

@[grind =, simp]
lemma RawCNFA.addFinal_initials {m : RawCNFA A} : (m.addFinal s).initials = m.initials

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

theorem e_1629 :
     - 3 * (c &&& (a ^^^ b)) + 5 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) + 2 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 3 * ( ~~~a ||| ( ~~~b &&& c)) - 5 * (a ^^^ ( ~~~b &&& c)) + 2 * ((a &&& b) ^^^ (b ||| c)) - 1 * ( ~~~a ||| (b ||| c)) - 1 *  ~~~(b ||| c) - 1 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 1 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 5 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 1 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 1 * ((a |||  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 1 * (a ||| ( ~~~b ||| c)) - 6 *  ~~~(a ||| ( ~~~b ||| c)) + 7 *  ~~~( ~~~a ||| (b ||| c)) + 12 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 7 * ( ~~~a &&& ( ~~~b &&& c)) + 5 * ( ~~~a &&& (b &&& c)) + 13 * (a &&& ( ~~~b &&& c)) + 5 * (a &&& (b &&& c)) =  - 9 *  ~~~(a ||| (b ||| c))

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬x = 0 → ofBool (0#32 <ᵤ 5#32 / x) = ofBool (x <ᵤ 6#32)

theorem src_x_and_nmask_sge_fail_maybe_z_thm (e : IntW 8) (e_1 : IntW 1) (e_2 : IntW 8) :
  icmp IntPred.sge (LLVM.and e_2 (select e_1 (shl (const? 8 (-1)) e) (const? 8 0)))
      (select e_1 (shl (const? 8 (-1)) e) (const? 8 0)) ⊑
    icmp IntPred.sge
      (LLVM.and e_2 (select e_1 (shl (const? 8 (-1)) e { «nsw» := true, «nuw» := false }) (const? 8 0)))
      (select e_1 (shl (const? 8 (-1)) e { «nsw» := true, «nuw» := false }) (const? 8 0))

theorem test26_proof : test26_before ⊑ test26_after

theorem trunc_shl_nsw_31_i32_i64_thm (e : IntW 64) :
  trunc 32 (shl e (const? 64 31) { «nsw» := true, «nuw» := false }) ⊑ shl (trunc 32 e) (const? 32 31)

theorem test18_proof : test18_before ⊑ test18_after

theorem bools_proof : bools_before ⊑ bools_after

theorem wrongimm2_thm (e : IntW 16) :
  icmp IntPred.eq (ashr (trunc 8 e) (const? 8 6)) (trunc 8 (lshr e (const? 16 8))) ⊑
    icmp IntPred.eq (ashr (trunc 8 e) (const? 8 6))
      (trunc 8 (lshr e (const? 16 8)) { «nsw» := false, «nuw» := true })

theorem n8_proof : n8_before ⊑ n8_after

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

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

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

theorem alive_290__292 : alive_290__292_src ⊑ alive_290__292_tgt

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

theorem positive_samevar_shlnuw_ashrexact_proof : positive_samevar_shlnuw_ashrexact_before ⊑ positive_samevar_shlnuw_ashrexact_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 masked_icmps_mask_notallzeros_bmask_mixed_negated_3_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 15#32 == 0#32) = 1#1 → ofBool (x &&& 7#32 != 0#32) = ofBool (x &&& 15#32 != 8#32)

theorem trunc_lshr_exact_mask_proof : trunc_lshr_exact_mask_before ⊑ trunc_lshr_exact_mask_after

theorem add_odd_iff_neq (n m : Nat) :
    (n + m) % 2 = 1 ↔ (n % 2 = 1) ≠ (m % 2 = 1)

theorem or_eq_with_one_bit_diff_constants3_proof : or_eq_with_one_bit_diff_constants3_before ⊑ or_eq_with_one_bit_diff_constants3_after

theorem ne_basic_equal_5_proof : ne_basic_equal_5_before ⊑ ne_basic_equal_5_after

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

theorem e_871 :
    5 *  ~~~(z &&&  ~~~t) - 5 * z - 7 * (z ||| t) + 1 *  ~~~(z ||| t) + 8 *  ~~~(z |||  ~~~t) + 18 * (z &&&  ~~~t) = 6 *  ~~~(z &&& t) - 7 * (z &&& t)

theorem positive_and_odd_ne_proof : positive_and_odd_ne_before ⊑ positive_and_odd_ne_after

theorem e_852 :
     - 6 *  ~~~t + 1 * t - 2 *  ~~~(z &&&  ~~~t) + 9 *  ~~~(z ||| t) + 6 * (z &&&  ~~~t) + 1 * (z &&& t) =  - 2 *  ~~~(z |||  ~~~t) + 1 *  ~~~z

theorem negate_ashr_proof : negate_ashr_before ⊑ negate_ashr_after

theorem neg_not_signbit3_thm (e : IntW 8) :
  sub (const? 32 0) (zext 32 (ashr e (const? 8 7))) ⊑
    sub (const? 32 0) (zext 32 (ashr e (const? 8 7))) { «nsw» := true, «nuw» := false }

theorem test13_proof : test13_before ⊑ test13_after

theorem neg_nsw_slt_0_proof : neg_nsw_slt_0_before ⊑ neg_nsw_slt_0_after

theorem masked_and_notallones_proof : masked_and_notallones_before ⊑ masked_and_notallones_after

theorem icmp_eq_or_z_or_pow2orz_fail_logic_or_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 == 0#8) = 1#1 → ofBool (x_1 == 0#8 - x &&& x) = ofBool (x_1 == x &&& 0#8 - x)

theorem lshrugt_02_01_exact_proof : lshrugt_02_01_exact_before ⊑ lshrugt_02_01_exact_after

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

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

theorem icmp_equality_test_swift_optional_pointers_proof : icmp_equality_test_swift_optional_pointers_before ⊑ icmp_equality_test_swift_optional_pointers_after

theorem zext_sext_eq_known_nonneg_proof : zext_sext_eq_known_nonneg_before ⊑ zext_sext_eq_known_nonneg_after

@[simp]
lemma lift_eval (M : NFA (BitVec n) σ) (f : Fin n → Fin m) :
    (M.lift f).eval w = M.eval (BitVecs'.transport f w)

theorem eq_irregular_bit_widths_thm.extracted_1._1 : ∀ (x x_1 : BitVec 31),
  ¬(13#31 ≥ ↑31 ∨ 13#31 ≥ ↑31 ∨ 7#31 ≥ ↑31 ∨ 7#31 ≥ ↑31) → 7#31 ≥ ↑31 ∨ 7#31 ≥ ↑31 → False

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

theorem ashr_mul_thm (e e_1 : IntW 8) :
  trunc 16 (ashr (mul (sext 20 e_1) (sext 20 e)) (const? 20 8)) ⊑
    ashr (mul (sext 16 e_1) (sext 16 e) { «nsw» := true, «nuw» := false }) (const? 16 8)

@[grind =, simp]
lemma RawCNFA.addFinal_finals {m : RawCNFA A} : (m.addFinal s).finals = m.finals.insert s

theorem c0_thm (e : IntW 8) : icmp IntPred.ule (LLVM.and e (const? 8 3)) e ⊑ const? 1 1

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

theorem test1_thm.extracted_1._1 : ∀ (x : BitVec 33), ¬4096#33 = 0 → x % 4096#33 = x &&& 4095#33

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

theorem sext_zext_nneg_slt_proof : sext_zext_nneg_slt_before ⊑ sext_zext_nneg_slt_after

theorem icmp_slt_sext_ne_allones_nofold_proof : icmp_slt_sext_ne_allones_nofold_before ⊑ icmp_slt_sext_ne_allones_nofold_after

theorem negate_shl_xor_proof : negate_shl_xor_before ⊑ negate_shl_xor_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1b_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 3#32 != 1#32) = 1#1 → 1#1 = ofBool (x &&& 3#32 != 1#32) ||

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

theorem reassoc_add_nuw_proof : reassoc_add_nuw_before ⊑ reassoc_add_nuw_after

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

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

theorem and_xor_or2_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 64),
  ¬(x_2 = 0 ∨ x_1 = 0 ∨ x = 0 ∨ x_2 = 0) →
    ¬(x = 0 ∨ x_2 = 0) → 42#64 / x_2 &&& 42#64 / x_1 ^^^ 42#64 / x ||

@[bv_multi_width_normalize] theorem not_eq_iff_ne {α : Sort u} (x y : α) :
  ¬ (x = y) ↔ x ≠ y

@[aesop 80% unsafe]
theorem Std.HashMap.mem_keys_insert_old [BEq K] [LawfulBEq K] [Hashable K] [LawfulHashable K] (m : Std.HashMap K V) (k k' : K) :
    k ∈ m → k ∈ m.insert k' v

theorem ugt_swap_and_min_commute_logical_proof : ugt_swap_and_min_commute_logical_before ⊑ ugt_swap_and_min_commute_logical_after

theorem masked_or_A_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 14#32 == x) = 1#1 → 1#1 = ofBool (x &&& BitVec.ofInt 32 (-79) == 0#32)

theorem src_is_mask_zext_fail_not_mask_proof : src_is_mask_zext_fail_not_mask_before ⊑ src_is_mask_zext_fail_not_mask_after

theorem test9_thm (e : IntW 16) : trunc 16 (sext 32 e) ⊑ e

theorem select_icmp_eq_and_1_0_or_2_thm.extracted_1._4 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 &&& 1#32 == 0#32) = 1#1 → ¬1#32 ≥ ↑32 → x ||

theorem test1_proof : test1_before ⊑ test1_after

theorem test_sext3_proof : test_sext3_before ⊑ test_sext3_after

theorem ashr_lshr_inv_thm (e e_1 : IntW 32) :
  select (icmp IntPred.slt e_1 (const? 32 1)) (ashr e_1 e { «exact» := true }) (lshr e_1 e) ⊑ ashr e_1 e

theorem ugt_rem_nz_nsw_thm (e : IntW 8) :
  icmp IntPred.ugt (mul e (const? 8 5) { «nsw» := true, «nuw» := true }) (const? 8 21) ⊑
    icmp IntPred.ugt e (const? 8 4)

theorem shl_lshr_pow2_const_case2_proof : shl_lshr_pow2_const_case2_before ⊑ shl_lshr_pow2_const_case2_after

theorem alive_AndOrXor_2475 : alive_AndOrXor_2475_src ⊑ alive_AndOrXor_2475_tgt

theorem p0_proof : p0_before ⊑ p0_after

@[simp]
theorem simplifyNot_eq_complement (c : Circuit α) :
    simplifyNot c = ~~~ c

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

theorem neg_mask_proof : neg_mask_before ⊑ neg_mask_after

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

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 icmp_slt_0_and_icmp_sge_neg1_i64_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬63#64 ≥ ↑64 → x >>> 63#64 &&& zeroExtend 64 (ofBool (-1#64 ≤ₛ x)) = zeroExtend 64 (ofBool (x == -1#64))

theorem AvoidCollision_setWidth_append_append_eq_shiftLeft_setWidth_or {b : BitVec w} {b' : BitVec w'} {b'' : BitVec w''} :
    (b ++ b' ++ b'').setWidth w''' = (b.setWidth w''' <<< (w' + w'')) ||

@[simp]
theorem toConcrete_concrete : toConcrete (.concrete a) = a

theorem fixed (x : BitVec 8) :
    BitVec.sle (1024#32) (x.signExtend 32) = false

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

theorem test2_proof : test2_before ⊑ test2_after

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

theorem e_1970 :
    7 * ( ~~~b &&&  ~~~(a ^^^ c)) + 2 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) - 6 *  ~~~(a &&& (b ^^^ c)) + 1 * (a ||| (b &&& c)) - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 1 * (b ||| (a &&& c)) + 5 * (b ^^^  ~~~(a &&&  ~~~c)) + 1 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 3 * (c ^^^  ~~~(a &&& b)) - 1 * (c ^^^  ~~~(a ||| b)) - 1 * (c &&&  ~~~(a &&&  ~~~b)) + 11 * ( ~~~a &&& ( ~~~b ||| c)) + 2 * (b ||| c) - 2 * (c ||| (a &&& b)) + 2 * ((a &&& b) |||  ~~~(b |||  ~~~c)) + 1 *  ~~~(a ||| c) - 1 * (c ^^^ (a &&&  ~~~b)) - 11 * (a |||  ~~~c) + 5 * (b &&& (a |||  ~~~c)) - 3 * ( ~~~c &&& (a ^^^ b)) - 5 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) - 2 * ((a |||  ~~~b) &&& (b ^^^ c)) + 3 *  ~~~(a &&& (b &&& c)) + 5 * (b ^^^ (a &&& (b ||| c))) - 2 * ( ~~~a ||| (b &&& c)) - 2 * (a ^^^ (b &&& c)) + 11 *  ~~~(a &&& ( ~~~b ||| c)) + 7 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) + 11 * (b ||| (a ^^^ c)) - 2 * (a ^^^ (b ^^^ c)) + 11 * ( ~~~b &&& (a ^^^ c)) + 1 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) - 11 *  ~~~(b |||  ~~~c) + 7 * (c &&& (a ||| b)) - 7 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) + 1 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 2 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) - 1 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) - 7 * (a ^^^ ( ~~~b &&& c)) - 1 * (c &&& (a |||  ~~~b)) - 3 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) - 6 *  ~~~(b &&&  ~~~c) + 4 * ((a |||  ~~~b) &&&  ~~~(b ^^^ c)) + 1 * ((a &&&  ~~~b) ||| (a ^^^ (b ^^^ c))) - 2 * (b ^^^  ~~~( ~~~a &&& (b &&& c))) + 5 * (a ||| b) - 11 * ( ~~~a ||| (b ||| c)) - 1 * (c ^^^  ~~~(a ||| ( ~~~b &&& c))) + 5 * ((a ||| b) &&&  ~~~(b ^^^ c)) + 1 * (b ||| (a &&&  ~~~c)) + 8 *  ~~~(a ||| ( ~~~b ||| c)) + 11 *  ~~~( ~~~a ||| (b ||| c)) - 4 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 1 * ( ~~~a &&& ( ~~~b &&& c)) - 28 * ( ~~~a &&& (b &&& c)) + 9 * (a &&& (b &&& c)) =  - 1 *  ~~~(a ||| (b ||| c)) - 21 * (a &&& ( ~~~b &&& c))

theorem xor_sext_to_sel_proof : xor_sext_to_sel_before ⊑ xor_sext_to_sel_after

theorem icmp_equality_test_commute_icmp2_proof : icmp_equality_test_commute_icmp2_before ⊑ icmp_equality_test_commute_icmp2_after

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

theorem main3e_like_proof : main3e_like_before ⊑ main3e_like_after

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

theorem lshrult_02_05_exact_proof : lshrult_02_05_exact_before ⊑ lshrult_02_05_exact_after

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

theorem mul8_low_proof : mul8_low_before ⊑ mul8_low_after

theorem e_1071 :
     - 11 * (z ||| t) - 2 * z - 5 * (z |||  ~~~t) + 3 *  ~~~(z &&& t) + 2 *  ~~~(z ||| t) + 8 *  ~~~(z |||  ~~~t) + 18 * (z &&& t) =  - 15 * (z &&&  ~~~t)

theorem t0_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(True ∧ x.smod (BitVec.ofInt 8 (-32)) ≠ 0 ∨
        (BitVec.ofInt 8 (-32) == 0 || 8 != 1 && x == intMin 8 && BitVec.ofInt 8 (-32) == -1) = true) →
    ¬(True ∧ x >>> 5#8 <<< 5#8 ≠ x ∨ 5#8 ≥ ↑8 ∨ True ∧ (0#8).ssubOverflow (x.sshiftRight' 5#8) = true) →
      x.sdiv (BitVec.ofInt 8 (-32)) = 0#8 - x.sshiftRight' 5#8

theorem test_simplify_decrement_invalid_ne_proof : test_simplify_decrement_invalid_ne_before ⊑ test_simplify_decrement_invalid_ne_after

theorem ult_toNat (x y : BitVec n) :
    (BitVec.ult (n := n) x y) = decide (x.toNat < y.toNat)

theorem masked_or_allzeroes_logical_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 7)) (const? 32 0)) (const? 1 1)
      (icmp IntPred.eq (LLVM.and e (const? 32 39)) (const? 32 0)) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 7)) (const? 32 0)

@[bv_automata_nnf] theorem ite_false_true {_ : Decidable p} : (ite p False True) = ¬p

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

@[simp]
theorem mem_mkLowerTriangularPairs₂  {n : Nat} {ij :  Nat × Nat} :
  (ij ∈ mkLowerTriangularPairs n) ↔
  (ij.1 < ij.2 ∧ ij.2 ≤ n)

theorem carryWith_eq_carry_of_eq_initCarry (p : FSM arity) (carryState : p.α → Bool) (x : arity → BitStream) (n : Nat)
    (hc : carryState = p.initCarry) :
    p.carryWith carryState x n = p.carry x n

theorem or_and2_commuted_thm.extracted_1._6 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 ||

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

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

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

theorem xor_of_icmps_to_ne_proof : xor_of_icmps_to_ne_before ⊑ xor_of_icmps_to_ne_after

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

theorem scalar_i32_shl_and_negC_ne_proof : scalar_i32_shl_and_negC_ne_before ⊑ scalar_i32_shl_and_negC_ne_after

theorem shl_xor_xor_no_const_proof : shl_xor_xor_no_const_before ⊑ shl_xor_xor_no_const_after

theorem test2_thm (e : IntW 32) :
  add (LLVM.and e (const? 32 7)) (LLVM.and e (const? 32 32)) ⊑ LLVM.and e (const? 32 39)

theorem e_300 :
    1 *  ~~~(x ^^^ y) + 11 *  ~~~y - 1 * (x |||  ~~~y) - 10 *  ~~~(x ||| y) + 1 *  ~~~(x |||  ~~~y) - 15 * (x &&&  ~~~y) - 5 * (x &&& y) =  - 5 *  ~~~(x &&&  ~~~x) + 6 *  ~~~x

theorem carry_congrEnv {p : FSM arity}
    {x y : arity → BitStream} {n : Nat} (h : ∀ a i, i < n → x a i = y a i) :
    p.carry x n = p.carry y n

theorem ashr_lowmask_proof : ashr_lowmask_before ⊑ ashr_lowmask_after

theorem icmp_eq_and_pow2_minus1_shl1_proof : icmp_eq_and_pow2_minus1_shl1_before ⊑ icmp_eq_and_pow2_minus1_shl1_after

theorem positive_sameconst_shlnuwnsw_lshrexact_proof : positive_sameconst_shlnuwnsw_lshrexact_before ⊑ positive_sameconst_shlnuwnsw_lshrexact_after

theorem src_is_mask_lshr_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1) (x_3 : BitVec 8),
  ¬x_2 = 1#1 →
    ¬x ≥ ↑8 → ofBool (x_3 ^^^ 123#8 != 15#8 >>> x &&& (x_3 ^^^ 123#8)) = ofBool (15#8 >>> x <ᵤ x_3 ^^^ 123#8)

theorem lshrugt_03_09_proof : lshrugt_03_09_before ⊑ lshrugt_03_09_after

theorem one_side_fold_slt_thm (e e_1 e_2 : IntW 32) (e_3 : IntW 1) :
  icmp IntPred.slt (select e_3 e_2 e_1) (select e_3 e e_1) ⊑
    select e_3 (icmp IntPred.slt e_2 e) (const? 1 0)

@[simp] lemma tru_and (c : Circuit α) :
  Circuit.tru &&& c = c

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

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

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

theorem shl1_trunc_sgt4_thm (e : IntW 32) :
  icmp IntPred.sgt (trunc 16 (shl (const? 32 1) e)) (const? 16 4) ⊑
    icmp IntPred.sgt (trunc 16 (shl (const? 32 1) e { «nsw» := false, «nuw» := true })) (const? 16 4)

theorem bv_AddSub_1202 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.add (LLVM.xor e (LLVM.const? w (-1))) e_1 ⊑ LLVM.sub (LLVM.sub e_1 (LLVM.const? w 1)) e

theorem sle_or_min_logical_proof : sle_or_min_logical_before ⊑ sle_or_min_logical_after

theorem twoway_clamp_lt_proof : twoway_clamp_lt_before ⊑ twoway_clamp_lt_after

theorem demo2 (x : BitVec 64) : BitVec.zeroExtend 64 (BitVec.truncate 32 x) = x &&& 4294967295#64

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

theorem test_add_nuw__nuw_is_safe_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 2147483647#32 == 2147483647#32) = 1#1 → True ∧ (x &&& 2147483647#32).uaddOverflow 1#32 = true → False

theorem test0_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (-1#32 <ₛ x ^^^ BitVec.ofInt 32 (-2147483648)) = ofBool (x <ₛ 0#32)

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

theorem t0_shl_thm (e : IntW 8) (e_1 : IntW 32) : shl e_1 (sext 32 e) ⊑ shl e_1 (zext 32 e { «nneg» := true })

theorem sext_xor_sub_2_proof : sext_xor_sub_2_before ⊑ sext_xor_sub_2_after

theorem test_negative_nsw_and_unsigned_pred_thm (e : IntW 64) :
  icmp IntPred.ult (sub (const? 64 10) e { «nsw» := true, «nuw» := false }) (const? 64 3) ⊑
    icmp IntPred.ult (add e (const? 64 (-8))) (const? 64 3)

theorem test86_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬4#32 ≥ ↑32 → ¬4#16 ≥ ↑16 → truncate 16 ((signExtend 32 x).sshiftRight' 4#32) = x.sshiftRight' 4#16

theorem pow2_or_zero_is_not_negative_commute_proof : pow2_or_zero_is_not_negative_commute_before ⊑ pow2_or_zero_is_not_negative_commute_after

theorem e_127 :
    11 *  ~~~(x &&& y) - 1 *  ~~~(x &&&  ~~~x) + 5 * (x ||| y) - 10 *  ~~~(x ||| y) - 15 *  ~~~(x |||  ~~~y) - 15 * (x &&&  ~~~y) = 4 * (x &&& y)

theorem lshrult_01_03_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 1)) (const? 4 3) ⊑ icmp IntPred.ult e (const? 4 6)

theorem testi16i8_ne_proof : testi16i8_ne_before ⊑ testi16i8_ne_after

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

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

theorem e_2008 :
     - 11 * (e ^^^ ( ~~~d ||| (e &&& f))) + 1 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) + 4 * (e ^^^  ~~~(d ||| (e ^^^ f))) + 2 *  ~~~(e &&&  ~~~f) + 1 * ( ~~~d &&& (e ||| f)) + 1 * ((d ^^^ e) &&& (d ^^^ f)) - 1 * d - 3 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) + 1 *  ~~~(d &&&  ~~~e) + 2 * (e ^^^ (d &&& (e ||| f))) - 6 * (d |||  ~~~f) + 7 * (d ^^^ e) - 5 * (e ^^^ (d &&& f)) + 3 * (e ||| f) - 11 * (e ^^^  ~~~(d &&& (e &&& f))) - 5 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 2 * (f ^^^  ~~~( ~~~d &&& (e ||| f))) + 1 * ( ~~~f &&&  ~~~(d ^^^ e)) - 2 *  ~~~( ~~~d &&& (e ^^^ f)) - 2 * (f ^^^ (d &&&  ~~~e)) - 11 * ( ~~~(d &&& e) &&& (e ^^^ f)) - 2 * ((d &&& e) ||| (e ^^^ f)) + 1 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 1 *  ~~~e + 1 * (e ||| (d ^^^ f)) + 7 * (e ^^^ ( ~~~d &&& (e ||| f))) + 17 *  ~~~(d ||| (e ||| f)) + 10 *  ~~~(d ||| ( ~~~e ||| f)) + 13 *  ~~~( ~~~d ||| (e ||| f)) + 13 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 9 * ( ~~~d &&& (e &&& f)) + 30 * (d &&& ( ~~~e &&& f)) + 5 * (d &&& (e &&& f)) =  - 2 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 26 * ( ~~~d &&& ( ~~~e &&& f))

theorem sdiv_icmp4_proof : sdiv_icmp4_before ⊑ sdiv_icmp4_after

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

theorem trunc_sel_larger_sext_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → signExtend 64 42#16 = 42#64

theorem test14_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬x = 0 → ofBool (4#32 / x <ᵤ 4#32) = ofBool (1#32 <ᵤ x)

theorem multiuse3_proof : multiuse3_before ⊑ multiuse3_after

theorem lshr_or_or_no_const_proof : lshr_or_or_no_const_before ⊑ lshr_or_or_no_const_after

theorem pr9998_thm (e : IntW 32) :
  icmp IntPred.ugt (sext 64 (ashr (shl e (const? 32 31)) (const? 32 31) { «exact» := true }))
      (const? 64 7297771788697658747) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 1)) (const? 32 0)

theorem fold_xor_zext_icmp_proof : fold_xor_zext_icmp_before ⊑ fold_xor_zext_icmp_after

theorem lshr_shl_pow2_const_xor_thm (e : IntW 16) :
  LLVM.xor (LLVM.and (shl (lshr (const? 16 256) e) (const? 16 2)) (const? 16 8)) (const? 16 8) ⊑
    select (icmp IntPred.eq e (const? 16 7)) (const? 16 0) (const? 16 8)

theorem e_1830 :
    2 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) - 1 *  ~~~(a &&& (b ^^^ c)) - 1 * ((a ||| b) &&&  ~~~(b ^^^ c)) - 11 *  ~~~a - 6 * (c |||  ~~~(a |||  ~~~b)) + 1 * (c ||| (a ^^^ b)) - 2 * ( ~~~c ||| (a ^^^ b)) - 2 * ( ~~~(a ||| b) ||| (b ^^^ c)) + 4 * (b ^^^ ( ~~~a ||| (b ^^^ c))) - 6 * (b |||  ~~~(a ^^^ c)) + 4 * ( ~~~a ||| (b ||| c)) + 7 * (a &&& ( ~~~b ||| c)) - 5 * ((b &&&  ~~~c) ^^^ ( ~~~a ||| (b ^^^ c))) - 5 * (b ^^^  ~~~(a ||| c)) - 1 * (a ^^^ (b &&& c)) - 3 * (a ||| ( ~~~b ||| c)) - 7 * (c ^^^ (a &&& b)) + 2 * (b ^^^ (a ||| (b ||| c))) + 4 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 3 * (c ^^^  ~~~(a &&& (b &&& c))) - 7 *  ~~~( ~~~a ||| (b &&& c)) + 1 * ( ~~~c &&& (a ^^^ b)) - 2 * ((a &&& b) |||  ~~~(b ||| c)) - 1 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 1 * ((a &&& b) |||  ~~~(b ^^^ c)) - 2 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) - 3 * (c &&& (a ^^^ b)) - 1 * (b ^^^ (a &&& c)) + 2 * (b &&&  ~~~(a &&& c)) - 1 * (b &&&  ~~~(a ^^^ c)) - 5 *  ~~~( ~~~a &&& (b ^^^ c)) - 5 * ((a |||  ~~~b) &&& (b ^^^ c)) + 1 * ((a ^^^ b) ||| (a ^^^ c)) + 2 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 3 * (b ||| (a &&&  ~~~c)) + 31 *  ~~~(a ||| (b ||| c)) + 13 *  ~~~(a ||| ( ~~~b ||| c)) + 1 *  ~~~( ~~~a ||| (b ||| c)) + 26 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 20 * ( ~~~a &&& ( ~~~b &&& c)) + 41 * ( ~~~a &&& (b &&& c)) + 28 * (a &&& ( ~~~b &&& c)) + 10 * (a &&& (b &&& c)) =  - 2 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c)))

theorem e_744 :
    1 * (x ^^^ y) - 11 *  ~~~(x &&&  ~~~x) + 11 * x + 3 *  ~~~(x &&& y) - 3 *  ~~~(x &&&  ~~~y) - 1 *  ~~~y + 1 * y + 14 *  ~~~(x ||| y) + 15 *  ~~~(x |||  ~~~y) - 3 * (x &&&  ~~~y) - 2 * (x &&& y) =  - 4 *  ~~~(x ^^^ y) + 6 *  ~~~x

theorem lsb_mask_sign_zext_proof : lsb_mask_sign_zext_before ⊑ lsb_mask_sign_zext_after

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

theorem alive_AddSub_1619  (w : Nat)   : alive_AddSub_1619_src w  ⊑ alive_AddSub_1619_tgt w

theorem bv_AndOrXor_698 :
    ∀ (e e_1 e_2 : LLVM.IntW w),
      LLVM.and (LLVM.icmp LLVM.IntPred.eq (LLVM.and e e_1) (LLVM.const? w 0))
          (LLVM.icmp LLVM.IntPred.eq (LLVM.and e e_2) (LLVM.const? w 0)) ⊑
        LLVM.icmp LLVM.IntPred.eq (LLVM.and e (LLVM.or e_1 e_2)) (LLVM.const? w 0)

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬32#128 ≥ ↑128 → 32#64 ≥ ↑64 ∨ True ∧ zeroExtend 64 (truncate 32 (x >>> 32#64)) ≠ x >>> 32#64 → False

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

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

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

theorem e_1662 :
    5 * ((a &&&  ~~~b) ||| (b ^^^ c)) - 1 * ( ~~~c ||| (a ^^^ b)) - 1 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) + 2 * ((a &&& b) |||  ~~~(b |||  ~~~c)) - 6 *  ~~~( ~~~a ||| (b ^^^ c)) + 5 *  ~~~( ~~~a &&& (b &&& c)) + 11 * (b &&&  ~~~(a ^^^ c)) + 11 *  ~~~(a |||  ~~~c) + 4 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 7 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) - 2 * ((a &&& b) ^^^ (b |||  ~~~c)) - 3 * ((a &&& b) ^^^ (b ||| c)) + 3 * (b ^^^ ( ~~~a ||| (b &&& c))) + 7 * (a &&& ( ~~~b ||| c)) - 3 * (c &&& (a |||  ~~~b)) - 18 *  ~~~(a ||| (b ||| c)) - 19 *  ~~~(a ||| ( ~~~b ||| c)) - 22 *  ~~~( ~~~a ||| (b ||| c)) - 19 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 30 * ( ~~~a &&& ( ~~~b &&& c)) - 6 * ( ~~~a &&& (b &&& c)) - 15 * (a &&& ( ~~~b &&& c)) - 19 * (a &&& (b &&& c)) =  - 2 *  ~~~( ~~~a &&& (b ||| c))

theorem shl_xor_proof : shl_xor_before ⊑ shl_xor_after

@[simp]
theorem snd_nextBit_fsmCarry'' {state : Unit → Bool} {env : Bool → Bool} :
    ((fsmCarry'' initCarry).nextBit state env).2 =
      (state ())

theorem ult_umin2_proof : ult_umin2_before ⊑ ult_umin2_after

theorem fold_add_udiv_urem_without_noundef_thm.extracted_1._2 : ∀ (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) →
      (x / 10#32) <<< 4#32 + x % 10#32 = (x / 10#32) <<< 4#32 ||

theorem ashr_eq_msb_low_second_zero_proof : ashr_eq_msb_low_second_zero_before ⊑ ashr_eq_msb_low_second_zero_after

theorem ashr_16_add_zext_basic_proof : ashr_16_add_zext_basic_before ⊑ ashr_16_add_zext_basic_after

theorem substitute_constant_or_ne_uge_commute_logical_proof : substitute_constant_or_ne_uge_commute_logical_before ⊑ substitute_constant_or_ne_uge_commute_logical_after

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

@[simp]
theorem Env.length_ofEnvFin (envFin : EnvFin w n) :
  List.length (Env.ofEnvFin envFin) = n

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

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

theorem foo1_and_signbit_lshr_proof : foo1_and_signbit_lshr_before ⊑ foo1_and_signbit_lshr_after

theorem scalar_i8_shl_ult_const_3_proof : scalar_i8_shl_ult_const_3_before ⊑ scalar_i8_shl_ult_const_3_after

theorem t10_almost_highest_bit_proof : t10_almost_highest_bit_before ⊑ t10_almost_highest_bit_after

theorem trunc_shl_lshr_var_thm.extracted_1._2 : ∀ (x x_1 : BitVec 64),
  ¬(x ≥ ↑64 ∨ 2#64 ≥ ↑64) →
    ¬(x ≥ ↑64 ∨ 2#32 ≥ ↑32) → truncate 32 (x_1 >>> x <<< 2#64) = truncate 32 (x_1 >>> x) <<< 2#32

theorem test16_thm.extracted_1._1 : ∀ (x : BitVec 16), 12#16 ≥ ↑16 ∨ 15#16 ≥ ↑16 → False

theorem select_bittest_to_sub_proof : select_bittest_to_sub_before ⊑ select_bittest_to_sub_after

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

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

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

theorem ashrslt_01_06_exact_proof : ashrslt_01_06_exact_before ⊑ ashrslt_01_06_exact_after

theorem foo1_and_signbit_lshr_proof : foo1_and_signbit_lshr_before ⊑ foo1_and_signbit_lshr_after

theorem negate_lowbitmask_proof : negate_lowbitmask_before ⊑ negate_lowbitmask_after

theorem lshrult_01_15_exact_proof : lshrult_01_15_exact_before ⊑ lshrult_01_15_exact_after

theorem logic_or_logic_and_8_proof : logic_or_logic_and_8_before ⊑ logic_or_logic_and_8_after

theorem shl_mask_wrong_shl_const_proof : shl_mask_wrong_shl_const_before ⊑ shl_mask_wrong_shl_const_after

theorem icmp_ugt_32_thm (e : IntW 64) :
  icmp IntPred.ugt (shl e (const? 64 32) { «nsw» := false, «nuw» := true }) (const? 64 4294967295) ⊑
    icmp IntPred.ne e (const? 64 0)

theorem positive_samevar_proof : positive_samevar_before ⊑ positive_samevar_after

theorem test32_proof : test32_before ⊑ test32_after

theorem ashrsgt_03_14_exact_proof : ashrsgt_03_14_exact_before ⊑ ashrsgt_03_14_exact_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1b_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1b_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1b_logical_after

theorem test13_thm (e : IntW 32) : LLVM.srem e e ⊑ const? 32 0

theorem positive_with_extra_and_logical_proof : positive_with_extra_and_logical_before ⊑ positive_with_extra_and_logical_after

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

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

theorem and_not_or_or_not_or_xor_commute5_proof : and_not_or_or_not_or_xor_commute5_before ⊑ and_not_or_or_not_or_xor_commute5_after

theorem src_is_mask_and_proof : src_is_mask_and_before ⊑ src_is_mask_and_after

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

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

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

theorem icmp_ugt_16_thm (e : IntW 64) :
  icmp IntPred.ugt (shl e (const? 64 16) { «nsw» := false, «nuw» := true }) (const? 64 1048575) ⊑
    icmp IntPred.ugt e (const? 64 15)

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

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

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

theorem or_and1_proof : or_and1_before ⊑ or_and1_after

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

theorem neg_mask_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 32),
  ¬(True ∧ x_1.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 ∧ x_1.ssubOverflow (signExtend 32 x) = true → 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 shl_lshr_eq_amt_multi_use_proof : shl_lshr_eq_amt_multi_use_before ⊑ shl_lshr_eq_amt_multi_use_after

theorem negative_not_less_than_proof : negative_not_less_than_before ⊑ negative_not_less_than_after

theorem neg_nsw_sgt_1_proof : neg_nsw_sgt_1_before ⊑ neg_nsw_sgt_1_after

theorem zext_nneg_signbit_extract_proof : zext_nneg_signbit_extract_before ⊑ zext_nneg_signbit_extract_after

theorem icmp_eq_and_pow2_shl_pow2_negative1_proof : icmp_eq_and_pow2_shl_pow2_negative1_before ⊑ icmp_eq_and_pow2_shl_pow2_negative1_after

theorem udiv_i32_thm (e e_1 : IntW 8) : LLVM.udiv (zext 32 e_1) (zext 32 e) ⊑ zext 32 (LLVM.udiv e_1 e)

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

theorem e_2043 :
     - 2 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) + 5 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 5 * ( ~~~f |||  ~~~(d ^^^ e)) + 1 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 1 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) + 1 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 1 * ( ~~~d ||| (e ^^^ f)) - 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 3 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) - 1 * (e ^^^  ~~~(d |||  ~~~f)) - 2 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) + 1 * (e ||| (d &&& f)) - 2 *  ~~~(d ^^^ f) + 2 * (f |||  ~~~(d ^^^ e)) - 7 * (e ||| (d &&&  ~~~f)) - 2 * (e ^^^ (d |||  ~~~f)) - 5 * (e |||  ~~~(d ||| f)) + 2 *  ~~~(d &&& (e ^^^ f)) - 2 * (e ||| f) + 11 * ( ~~~f &&&  ~~~(d ^^^ e)) + 3 *  ~~~(d &&& (e ||| f)) - 1 * (e ^^^ (d ||| (e ^^^ f))) + 5 * (d ||| e) - 2 * ( ~~~(d &&& e) &&& (e ^^^ f)) + 1 * (f ||| (d ^^^ e)) - 1 * d + 2 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 11 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) + 11 * ( ~~~e &&& (d ^^^ f)) - 10 *  ~~~(d ||| (e ||| f)) + 1 *  ~~~(d ||| ( ~~~e ||| f)) - 13 *  ~~~( ~~~d ||| (e ||| f)) - 1 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 9 * ( ~~~d &&& (e &&& f)) + 2 * (d &&& ( ~~~e &&& f)) + 17 * (d &&& (e &&& f)) = 23 * ( ~~~d &&& ( ~~~e &&& f))

theorem shl_mul_mask_wrong_mul_const_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬8#32 ≥ ↑32 →
    True ∧ (x &&& 255#32).smulOverflow 65535#32 = true ∨
        True ∧ (x &&& 255#32).umulOverflow 65535#32 = true ∨
          True ∧ ((x &&& 255#32) <<< 8#32).sshiftRight' 8#32 ≠ x &&& 255#32 ∨
            True ∧ (x &&& 255#32) <<< 8#32 >>> 8#32 ≠ x &&& 255#32 ∨ 8#32 ≥ ↑32 →
      False

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

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

theorem splat_mul_unknown_lz_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬95#128 ≥ ↑128 → ofBool ((zeroExtend 128 x * 18446744078004518913#128) >>> 95#128 == 0#128) = ofBool (-1#32 <ₛ x)

theorem ashr_ult_4_thm (e : IntW 4) :
  icmp IntPred.ult (ashr e (const? 4 1)) (const? 4 4) ⊑ icmp IntPred.sgt e (const? 4 (-1))

theorem bitwise_and_logical_and_masked_icmp_allones_proof : bitwise_and_logical_and_masked_icmp_allones_before ⊑ bitwise_and_logical_and_masked_icmp_allones_after

theorem and_or_not_not_commute1_proof : and_or_not_not_commute1_before ⊑ and_or_not_not_commute1_after

@[simp] theorem op_changeVars : (e.changeVars f).op = e.op

theorem udiv_exact_ne_30_no_of_thm (e e_1 : IntW 8) :
  icmp IntPred.ne (LLVM.udiv e_1 (LLVM.and e (const? 8 7)) { «exact» := true }) (const? 8 30) ⊑
    icmp IntPred.ne (mul (LLVM.and e (const? 8 7)) (const? 8 30) { «nsw» := false, «nuw» := true }) e_1

theorem icmp_equality_test_constant_samesign_proof : icmp_equality_test_constant_samesign_before ⊑ icmp_equality_test_constant_samesign_after

theorem mul_add_to_mul_7_thm (e : IntW 16) :
  add e (mul e (const? 16 32767) { «nsw» := true, «nuw» := false }) { «nsw» := true, «nuw» := false } ⊑
    shl e (const? 16 15)

theorem fold_sext_to_and_wrong9_proof : fold_sext_to_and_wrong9_before ⊑ fold_sext_to_and_wrong9_after

theorem test27_proof : test27_before ⊑ test27_after

theorem sle_swap_and_min_proof : sle_swap_and_min_before ⊑ sle_swap_and_min_after

theorem ashrsgt_01_13_proof : ashrsgt_01_13_before ⊑ ashrsgt_01_13_after

theorem e_1965 :
    1 * (b ^^^  ~~~(a ||| (b &&& c))) - 6 * (b ^^^  ~~~(a ||| c)) - 6 * (c |||  ~~~(a ||| b)) + 7 * ( ~~~b &&& (a ^^^ c)) + 2 * (c &&& (a ^^^ b)) - 1 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 1 * ( ~~~a ||| (b ||| c)) + 5 * (a |||  ~~~c) + 7 * ( ~~~(a |||  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 7 * ((b &&&  ~~~c) ^^^ (a ||| (b ^^^ c))) - 11 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) + 1 *  ~~~(a ^^^ ( ~~~b &&& c)) + 7 *  ~~~(a ||| c) + 2 * (b &&& c) - 5 * (c ^^^ (a ||| b)) - 1 * (b ^^^  ~~~(a &&& c)) - 1 *  ~~~( ~~~a &&& (b &&& c)) - 1 * ( ~~~(a ||| b) ||| (a ^^^ (b ^^^ c))) - 7 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) - 5 * ( ~~~c &&& (a ^^^ b)) - 6 * (c |||  ~~~(a |||  ~~~b)) - 2 * (c ||| (a &&&  ~~~b)) + 7 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) + 2 * ( ~~~c ||| (a ^^^ b)) + 3 * (c ^^^ (a &&& (b ||| c))) + 3 * (a ^^^ c) - 1 * (c ^^^ ( ~~~a ||| (b ||| c))) - 3 * (a ^^^ b) + 1 * ( ~~~b |||  ~~~(a ^^^ c)) + 1 * ((a &&& b) |||  ~~~(b ^^^ c)) - 6 *  ~~~( ~~~a &&& (b ^^^ c)) + 1 * (b ^^^ ( ~~~a ||| (b &&& c))) - 6 * ((a &&& b) |||  ~~~(b ||| c)) - 7 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 2 * ((a &&& b) ||| (b ^^^ c)) - 1 * (a ||| (b ^^^ c)) + 2 *  ~~~(a &&& c) + 2 * ((a &&& b) ^^^ (b ||| c)) + 2 * ( ~~~(a &&& b) &&& (b ^^^ c)) - 11 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) - 1 * (c ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 5 * (b ^^^  ~~~(a &&& (b &&& c))) + 7 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) - 5 * (b ^^^ (a &&&  ~~~c)) + 4 * (c ^^^  ~~~(a ||| (b &&& c))) - 3 * ( ~~~(a &&&  ~~~b) &&&  ~~~(b ^^^ c)) + 3 * (c &&&  ~~~(a &&&  ~~~b)) + 9 *  ~~~(a ||| (b ||| c)) + 11 *  ~~~(a ||| ( ~~~b ||| c)) + 13 *  ~~~( ~~~a ||| (b ||| c)) - 1 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 3 * ( ~~~a &&& ( ~~~b &&& c)) + 8 * ( ~~~a &&& (b &&& c)) + 7 * (a &&& ( ~~~b &&& c)) + 34 * (a &&& (b &&& c)) = 11 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) - 4 * (b &&& (a |||  ~~~c))

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

theorem ashrslt_01_14_proof : ashrslt_01_14_before ⊑ ashrslt_01_14_after

@[simp]
theorem eval_fsmMsb_eq {wcard bcard tcard : Nat}
    {wenv : WidthExpr.Env wcard}
    {fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream}
    {tctx : Term.Ctx wcard tcard}
    (tenv : Term.Ctx.Env tctx wenv)
    (benv : Term.BoolEnv bcard)
    (nenv : Term.NatEnv ncard)
    (ienv : Term.IntEnv icard)
    (w : WidthExpr wcard)
    (x : Term bcard ncard icard pcard tctx (.bv w))
    (xfsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm x))
    (hxfsm : HTermFSMToBitStream xfsm)
    (wfsm : NatFSM wcard tcard bcard ncard icard pcard (.ofDep w))
    (hwfsm : HNatFSMToBitstream wfsm)
    (htenv : HTermEnv fsmEnv tenv benv) :
    (fsmMsb xfsm.toFsmZext wfsm.toFsm).eval fsmEnv = (fun i =>
      BitStream.ofBitVecZext (x.toBV benv nenv ienv penv tenv) (min i (w.toNat wenv - 1)))

theorem bools_logical_thm.extracted_1._14 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 ^^^ 1#1 = 1#1 → ¬x_2 = 1#1 → x_1 = 1#1 → 1#1 = x_1

theorem lshrugt_01_13_exact_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 1) { «exact» := true }) (const? 4 (-3)) ⊑ const? 1 0

theorem ashrsgt_03_06_exact_proof : ashrsgt_03_06_exact_before ⊑ ashrsgt_03_06_exact_after

theorem ashrsgt_03_02_exact_proof : ashrsgt_03_02_exact_before ⊑ ashrsgt_03_02_exact_after

theorem negate_lshr_thm (e e_1 : IntW 8) : sub e_1 (lshr e (const? 8 7)) ⊑ add (ashr e (const? 8 7)) e_1

theorem test_sdiv_canonicalize_op0_proof : test_sdiv_canonicalize_op0_before ⊑ test_sdiv_canonicalize_op0_after

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

theorem test43_proof : test43_before ⊑ test43_after

theorem trunc_signed_nsw_zext_proof : trunc_signed_nsw_zext_before ⊑ trunc_signed_nsw_zext_after

theorem e_1140 :
    5 * (z ||| t) - 2 *  ~~~(z &&&  ~~~z) + 2 * (z |||  ~~~t) - 11 *  ~~~(z ^^^ t) + 4 * (z ^^^ t) - 7 * z - 7 *  ~~~(z |||  ~~~t) - 2 * (z &&&  ~~~t) =  - 13 * (z &&& t) - 11 *  ~~~(z ||| t)

theorem not_and_and_or_not_or_or_commute2_thm.extracted_1._1 : ∀ (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 → False

theorem src_x_and_nmask_ult_thm.extracted_1._4 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 : BitVec 8),
  ¬x_1 = 1#1 → ofBool (x_2 &&& 0#8 <ᵤ 0#8) = 0#1

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

theorem ne_umax4_proof : ne_umax4_before ⊑ ne_umax4_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_4_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_4_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_4_after

theorem ashr_xor_proof : ashr_xor_before ⊑ ashr_xor_after

theorem add_umax_simplify2_proof : add_umax_simplify2_before ⊑ add_umax_simplify2_after

theorem main7b_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ofBool (x_2 == x_1 &&& x_2) &&& ofBool (x * 42#32 == x_1 &&& x * 42#32) = 1#1 →
    0#32 = zeroExtend 32 (ofBool (x_1 &&& (x_2 ||| x * 42#32) != x_2 ||| x * 42#32))

theorem sle_and_min_commute_logical_proof : sle_and_min_commute_logical_before ⊑ sle_and_min_commute_logical_after

theorem test1_proof : test1_before ⊑ test1_after

theorem test3_proof : test3_before ⊑ test3_after

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

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

theorem test8_proof : test8_before ⊑ test8_after

theorem lshrult_02_14_exact_proof : lshrult_02_14_exact_before ⊑ lshrult_02_14_exact_after

@[simp] lemma eval_simplify :
    p.simplify.eval = p.eval

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

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

theorem test13_thm (e e_1 : IntW 32) :
  trunc 64 (ashr (sext 128 e_1) (LLVM.and (zext 128 e) (const? 128 31))) ⊑
    ashr (sext 64 e_1) (zext 64 (LLVM.and e (const? 32 31)) { «nneg» := true })

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

theorem ashrsgt_01_08_exact_proof : ashrsgt_01_08_exact_before ⊑ ashrsgt_01_08_exact_after

theorem shl_and_thm (e e_1 : IntW 8) :
  shl (LLVM.and (shl e_1 (const? 8 3)) e) (const? 8 2) ⊑ LLVM.and (shl e_1 (const? 8 5)) (shl e (const? 8 2))

theorem icmp_mul_nsw_sle_proof : icmp_mul_nsw_sle_before ⊑ icmp_mul_nsw_sle_after

theorem xor_signbit_lshr_proof : xor_signbit_lshr_before ⊑ xor_signbit_lshr_after

theorem test5_thm.extracted_1._2 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ¬(zeroExtend 32 x ≥ ↑32 ∨ 32#32 <<< zeroExtend 32 x = 0) →
    ¬(True ∧ x.msb = true ∨ True ∧ 32#32 <<< zeroExtend 32 x >>> zeroExtend 32 x ≠ 32#32 ∨ zeroExtend 32 x ≥ ↑32) →
      x_1 % 32#32 <<< zeroExtend 32 x = x_1 &&& 32#32 <<< zeroExtend 32 x + -1#32

theorem lshrult_03_15_proof : lshrult_03_15_before ⊑ lshrult_03_15_after

theorem e_639 :
     - 11 * (x ||| y) + 1 * (x ^^^ y) + 5 *  ~~~(x &&&  ~~~x) - 3 * (x |||  ~~~y) - 5 * x + 1 * y - 5 *  ~~~(x &&& y) + 2 *  ~~~(x ||| y) + 9 *  ~~~(x |||  ~~~y) + 18 * (x &&&  ~~~y) =  - 1 *  ~~~(x ^^^ y) - 12 * (x &&& y)

theorem select_or_disjoint_or_proof : select_or_disjoint_or_before ⊑ select_or_disjoint_or_after

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

theorem sdiv_mul_shl_nsw_exact_commute1_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 5),
  ¬(True ∧ x_2.smulOverflow x_1 = true ∨
        True ∧ (x_1 <<< x).sshiftRight' x ≠ x_1 ∨
          x ≥ ↑5 ∨
            True ∧ (x_2 * x_1).smod (x_1 <<< x) ≠ 0 ∨
              (x_1 <<< x == 0 || 5 != 1 && x_2 * x_1 == intMin 5 && x_1 <<< x == -1) = true) →
    True ∧ 1#5 <<< x >>> x ≠ 1#5 ∨
        x ≥ ↑5 ∨
          True ∧ x_2.smod (1#5 <<< x) ≠ 0 ∨ (1#5 <<< x == 0 || 5 != 1 && x_2 == intMin 5 && 1#5 <<< x == -1) = true →
      False

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

@[simp]
lemma CNFA.autUnsignedCmp_states cmp : s ∈ (autUnsignedCmp cmp).m.states ↔  s < 3

theorem t1_lshr_proof : t1_lshr_before ⊑ t1_lshr_after

theorem e_31 :
    1 * (x ||| y) + 3 * y - 4 *  ~~~(x |||  ~~~y) + 6 * (x &&&  ~~~y) + 3 * (x &&& y) = 7 * x

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

theorem factorize3_thm (e e_1 e_2 : IntW 32) :
  LLVM.and (LLVM.or e_2 (LLVM.or e_1 e)) (LLVM.or e_2 e) ⊑ LLVM.or e_2 e

theorem test9_proof : test9_before ⊑ test9_after

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

theorem lshrugt_01_08_proof : lshrugt_01_08_before ⊑ lshrugt_01_08_after

theorem t10_c1_c2_proof : t10_c1_c2_before ⊑ t10_c1_c2_after

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

theorem udiv_icmp2_proof : udiv_icmp2_before ⊑ udiv_icmp2_after

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

lemma inter_eq (M N : NFA' n) : M.inter N = NFA'.product And M N

theorem exact_ashr_eq_exactdiv_proof : exact_ashr_eq_exactdiv_before ⊑ exact_ashr_eq_exactdiv_after

lemma product.f_spec {m₁ m₂ : CNFA n} {s₁ : m₁.m.states} {s₂ : m₂.m.states} :
    ∀ a s₁' s₂',
      (a, (s₁', s₂')) ∈ f m₁ m₂ (s₁, s₂) ↔ s₁'.val ∈ m₁.m.tr s₁ a ∧ s₂'.val ∈ m₂.m.tr s₂ a

theorem udiv_mul_shl_nuw_exact_commute1_proof : udiv_mul_shl_nuw_exact_commute1_before ⊑ udiv_mul_shl_nuw_exact_commute1_after

theorem t2_proof : t2_before ⊑ t2_after

theorem test23_thm.extracted_1._1 : ∀ (x : BitVec 8), ((x ||| BitVec.ofInt 8 (-2)) ^^^ 13#8 ||| 1#8) ^^^ 12#8 = -1#8

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

theorem t1_ult_slt_0_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x <ᵤ 65536#32) = 1#1 → ofBool (65535#32 <ₛ x) = 1#1 ∨ ofBool (x <ₛ 0#32) = 1#1 → False

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_logical_after

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

theorem bitwise_or_logical_or_icmps_comm3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x ≥ ↑8 →
    ofBool (x_1 &&& 1#8 == 0#8) = 1#1 →
      True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8 ∨ True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8 → False

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

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 n2_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(BitVec.ofInt 8 (-128) == 0 || 8 != 1 && x == intMin 8 && BitVec.ofInt 8 (-128) == -1) = true →
    x.sdiv (BitVec.ofInt 8 (-128)) = zeroExtend 8 (ofBool (x == BitVec.ofInt 8 (-128)))

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

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

theorem bools2_logical_commute1_thm.extracted_1._14 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 = 1#1 → ¬x_1 ^^^ 1#1 = 1#1 → ¬x_1 = 1#1 → 0#1 = x

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

theorem lshrugt_01_04_proof : lshrugt_01_04_before ⊑ lshrugt_01_04_after

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

theorem add_nsw_const_const_sub_nsw_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x.saddOverflow 1#8 = true ∨ True ∧ (BitVec.ofInt 8 (-127)).ssubOverflow (x + 1#8) = true) →
    True ∧ (BitVec.ofInt 8 (-128)).ssubOverflow x = true → False

theorem slt_0_thm (e : IntW 32) :
  icmp IntPred.slt (trunc 8 e) (const? 8 0) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 128)) (const? 32 0)

theorem test_shl_nuw_nsw__nuw_is_safe_proof : test_shl_nuw_nsw__nuw_is_safe_before ⊑ test_shl_nuw_nsw__nuw_is_safe_after

theorem test16_proof : test16_before ⊑ test16_after

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

theorem and_and_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 2#32 == 0#32) = 1#1 → x &&& 1#32 = zeroExtend 32 (ofBool (x &&& 3#32 != 0#32))

theorem e_1527 :
    1 * (c ^^^  ~~~(a &&&  ~~~b)) - 7 * (b ^^^  ~~~(a &&& c)) + 4 * ((a ||| b) &&&  ~~~(b ^^^ c)) - 2 * (c &&& (a |||  ~~~b)) + 3 *  ~~~(a ||| (b ||| c)) - 4 *  ~~~(a ||| ( ~~~b ||| c)) + 3 *  ~~~( ~~~a ||| (b ||| c)) - 3 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 9 * ( ~~~a &&& ( ~~~b &&& c)) - 4 * ( ~~~a &&& (b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) =  - 3 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) - 2 * (a &&& b)

theorem ule_swap_or_min_logical_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x ≤ᵤ x_1) = 1#1 → ofBool (x == 0#8) = ofBool (x ≤ᵤ x_1)

theorem icmp_eq_sext_eq_allones_proof : icmp_eq_sext_eq_allones_before ⊑ icmp_eq_sext_eq_allones_after

theorem trunc_shl_nsw_nuw_31_i32_i64_thm (e : IntW 64) :
  trunc 32 (shl e (const? 64 31) { «nsw» := true, «nuw» := true }) ⊑ shl (trunc 32 e) (const? 32 31)

theorem eq_smin2_thm (e e_1 : IntW 32) :
  icmp IntPred.eq (select (icmp IntPred.slt e_1 e) e_1 e) e ⊑ icmp IntPred.sle e e_1

theorem f_var0_proof : f_var0_before ⊑ f_var0_after

@[simp]
theorem Eqn.denoteFin_cons {w : Nat} (t : Term) (eqn : Eqn)
    (envFin : EnvFin w (max t.numVars  eqn.numVars)) :
  Eqn.denoteFin (t :: eqn) envFin =
  t.denoteFin (envFin.castLe (by omega)) +
  Eqn.denoteFin eqn (envFin.castLe (by omega))

theorem urem_common_divisor_defined_cond_thm.extracted_1._1 : ∀ (x x_1 : BitVec 5) (x_2 : BitVec 1),
  ¬(x_2 = 1#1 ∨ x_1 = 0) → x_2 = 1#1 → x_1 = 0 → False

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

theorem or_xor_xor_normal_binops_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  x_2 ^^^ x_1 ^^^ (x_2 ^^^ x_1) &&& (x ^^^ x_1) ||

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

theorem main6b_logical_proof : main6b_logical_before ⊑ main6b_logical_after

theorem negate_lshr_thm (e e_1 : IntW 8) : sub e_1 (lshr e (const? 8 7)) ⊑ add (ashr e (const? 8 7)) e_1

theorem rewriteDidSomething : runRewriteOnLhs ≠ lhs

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

theorem slt_swap_or_not_max_proof : slt_swap_or_not_max_before ⊑ slt_swap_or_not_max_after

theorem test8_thm.extracted_1._1 : ∀ (x : BitVec 8), x &&& 3#8 &&& 4#8 = 0#8

theorem PR75692_1_thm (e : IntW 32) :
  LLVM.or (LLVM.xor e (const? 32 4)) (LLVM.xor e (const? 32 (-5))) ⊑ const? 32 (-1)

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

@[bv_multi_width_normalize]
theorem BitVec.twoPow_eq_minusOne_zext_plus_one : BitVec.twoPow w i = (-(1#i)).zeroExtend w + 1

theorem ashrslt_03_13_exact_proof : ashrslt_03_13_exact_before ⊑ ashrslt_03_13_exact_after

theorem e_1547 :
    1 * ( ~~~a ||| (b &&& c)) - 11 * ( ~~~b &&& (a ^^^ c)) + 1 * (b ^^^  ~~~(a &&& c)) + 4 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) + 1 *  ~~~(b |||  ~~~c) + 11 * (c ^^^ (a ||| (b &&& c))) - 7 * (a ^^^ (b &&& c)) - 2 *  ~~~(a ||| (b ||| c)) + 2 *  ~~~( ~~~a ||| (b ||| c)) - 8 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 7 * ( ~~~a &&& ( ~~~b &&& c)) + 2 * ( ~~~a &&& (b &&& c)) - 6 * (a &&& (b &&& c)) =  - 6 * (a &&& ( ~~~b &&& c)) + 1 *  ~~~(a ||| ( ~~~b ||| c))

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

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

theorem main5f_like_thm (e e_1 e_2 : IntW 32) :
  select (LLVM.or (icmp IntPred.ne (LLVM.and e_2 e_1) e_2) (icmp IntPred.ne (LLVM.and e_2 e) e_2))
      (const? 32 0) (const? 32 1) ⊑
    zext 32 (icmp IntPred.eq (LLVM.and e_2 (LLVM.and e_1 e)) e_2)

theorem PR2844_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x == 0#32) = 1#1 →
    ¬True → 0#32 = zeroExtend 32 (ofBool (x != 0#32) &&& ofBool (BitVec.ofInt 32 (-638208502) <ₛ x))

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

theorem ashr_ne_exact_proof : ashr_ne_exact_before ⊑ ashr_ne_exact_after

theorem e_1619 :
     - 11 * (c &&& (a |||  ~~~b)) - 7 *  ~~~(a &&&  ~~~b) + 2 * ( ~~~(a &&&  ~~~b) &&&  ~~~(a ^^^ (b ^^^ c))) + 11 * (b ^^^ ( ~~~a ||| (b ^^^ c))) + 11 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) - 2 * (a ||| b) - 1 * (c &&&  ~~~(a &&& b)) + 1 *  ~~~b - 11 *  ~~~(a &&& c) - 7 *  ~~~(a ^^^ (b &&& c)) + 1 * ((a &&& b) ||| (b ^^^ c)) - 3 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 4 *  ~~~(a ||| (b ||| c)) + 30 *  ~~~(a ||| ( ~~~b ||| c)) + 13 *  ~~~( ~~~a ||| (b ||| c)) + 17 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 12 * ( ~~~a &&& ( ~~~b &&& c)) + 18 * ( ~~~a &&& (b &&& c)) + 1 * (a &&& ( ~~~b &&& c)) + 7 * (a &&& (b &&& c)) =  - 1 * (c ||| (a &&& b)) + 1 * (a |||  ~~~c)

theorem OrZextOr_thm (e : IntW 3) :
  LLVM.or (zext 5 (LLVM.or e (const? 3 3))) (const? 5 8) ⊑ LLVM.or (zext 5 e) (const? 5 11)

theorem tryFactorization_add_mul_nuw_proof : tryFactorization_add_mul_nuw_before ⊑ tryFactorization_add_mul_nuw_after

theorem sub_to_and_and_commuted_proof : sub_to_and_and_commuted_before ⊑ sub_to_and_and_commuted_after

theorem and_nosignbit_select_shl_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → ¬8#32 ≥ ↑32 → (x &&& 2147418112#32) <<< 8#32 = x <<< 8#32 &&& BitVec.ofInt 32 (-16777216)

@[simp] theorem dropUntilHom_toCons {v : Var Γ t} :
  dropUntilHom (v := v.toCons (t' := t')) = (dropUntilHom (v:=v)).consRight

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

theorem exactly_one_set_signbit_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬7#8 ≥ ↑8 → ofBool (x_1 >>> 7#8 == zeroExtend 8 (ofBool (-1#8 <ₛ x))) = ofBool (x_1 ^^^ x <ₛ 0#8)

theorem ashrsgt_03_08_proof : ashrsgt_03_08_before ⊑ ashrsgt_03_08_after

theorem negate_add_with_single_negatible_operand_depth2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  0#8 - (x_1 + 21#8) * x = (BitVec.ofInt 8 (-21) - x_1) * x

theorem one_side_fold_eq_thm.extracted_1._8 : ∀ (x x_1 x_2 : BitVec 32) (x_3 : BitVec 1),
  x_3 = 1#1 → x_3 ^^^ 1#1 = 1#1 → ofBool (x_2 == x) = 1#1

theorem test22_proof : test22_before ⊑ test22_after

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

theorem testi16i8_proof : testi16i8_before ⊑ testi16i8_after

theorem sgt_x_impliesF_eq_smin_todo_proof : sgt_x_impliesF_eq_smin_todo_before ⊑ sgt_x_impliesF_eq_smin_todo_after

theorem main7a_logical_thm (e e_1 e_2 : IntW 32) :
  select (select (icmp IntPred.eq (LLVM.and e_2 e_1) e_2) (icmp IntPred.eq (LLVM.and e e_1) e) (const? 1 0))
      (const? 32 0) (const? 32 1) ⊑
    zext 32
      (select (icmp IntPred.ne (LLVM.and e_2 e_1) e_2) (const? 1 1)
        (icmp IntPred.ne (LLVM.and e e_1) e))

theorem sextbool_add_commute_proof : sextbool_add_commute_before ⊑ sextbool_add_commute_after

theorem ashr_mul_sign_bits_proof : ashr_mul_sign_bits_before ⊑ ashr_mul_sign_bits_after

theorem and_not_or_or_not_or_xor_commute1_proof : and_not_or_or_not_or_xor_commute1_before ⊑ and_not_or_or_not_or_xor_commute1_after

theorem urem_illegal_type_thm (e e_1 : IntW 9) : urem (zext 32 e_1) (zext 32 e) ⊑ zext 32 (urem e_1 e)

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

theorem test_thm (e : IntW 32) :
  icmp IntPred.ne (lshr (shl e (const? 32 12)) (const? 32 12)) (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 1048575)) (const? 32 0)

theorem ashr_not_proof : ashr_not_before ⊑ ashr_not_after

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

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

theorem test_mul__nuw_is_safe_proof : test_mul__nuw_is_safe_before ⊑ test_mul__nuw_is_safe_after

theorem zext_nneg_signbit_extract_proof : zext_nneg_signbit_extract_before ⊑ zext_nneg_signbit_extract_after

theorem test_ashr__exact_is_unsafe_proof : test_ashr__exact_is_unsafe_before ⊑ test_ashr__exact_is_unsafe_after

theorem test19_proof : test19_before ⊑ test19_after

theorem or_ranges_overlap_thm (e : IntW 8) :
  LLVM.or (LLVM.and (icmp IntPred.uge e (const? 8 5)) (icmp IntPred.ule e (const? 8 10)))
      (LLVM.and (icmp IntPred.uge e (const? 8 10)) (icmp IntPred.ule e (const? 8 20))) ⊑
    icmp IntPred.ult (add e (const? 8 (-5))) (const? 8 16)

theorem positive_biggerashr_shlnsw_ashrexact_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(True ∧ x >>> 6#8 <<< 6#8 ≠ x ∨
        6#8 ≥ ↑8 ∨ True ∧ (x.sshiftRight' 6#8 <<< 3#8).sshiftRight' 3#8 ≠ x.sshiftRight' 6#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 a_false_implies_b_true_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1) (x_2 : BitVec 8),
  ¬ofBool (10#8 <ᵤ x_2) = 1#1 → ¬ofBool (x_2 <ᵤ 20#8) = 1#1 → x = x_1

theorem lshrult_01_05_proof : lshrult_01_05_before ⊑ lshrult_01_05_after

theorem test21_proof : test21_before ⊑ test21_after

theorem n5_thm.extracted_1._1 : ∀ (x : BitVec 8), x - (x &&& 42#8) = x &&& BitVec.ofInt 8 (-43)

theorem bv_AndOrXor_2263 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.or e_1 (LLVM.xor e_1 e) ⊑ LLVM.or e_1 e

theorem add_nsw_mul_nsw_proof : add_nsw_mul_nsw_before ⊑ add_nsw_mul_nsw_after

theorem icmp_eq_sext_eq_zero_thm (e : IntW 32) :
  icmp IntPred.eq (sext 32 (icmp IntPred.eq e (const? 32 0))) e ⊑ const? 1 0

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

theorem trunc_ashr_trunc_proof : trunc_ashr_trunc_before ⊑ trunc_ashr_trunc_after

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

theorem MatchVar.isMonotone_unifyVars  : IsMonotone (unifyVars w v)

theorem value_ne_poison (a : α) :
    @Ne (no_index _) (value a) poison

theorem test6_proof : test6_before ⊑ test6_after

theorem test15_proof : test15_before ⊑ test15_after

theorem icmp_shl_ule_2_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬1#8 ≥ ↑8 → ofBool (42#8 + x ≤ᵤ (42#8 + x) <<< 1#8) = ofBool (-1#8 <ₛ x + 42#8)

theorem t1_single_bit_proof : t1_single_bit_before ⊑ t1_single_bit_after

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

theorem or_ranges_overlap_proof : or_ranges_overlap_before ⊑ or_ranges_overlap_after

theorem ugt_or_not_min_commute_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 != 0#8) ||

theorem e_2475 :
     - 2 * ( ~~~e &&& (d ^^^ f)) - 3 * (f ^^^ (d |||  ~~~e)) - 6 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 6 * (e &&&  ~~~(d &&& f)) + 3 *  ~~~( ~~~d &&& (e ||| f)) - 11 * (e ^^^  ~~~(d &&&  ~~~f)) + 11 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 6 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 4 * (f |||  ~~~(d ^^^ e)) - 5 * (f &&&  ~~~(d &&&  ~~~e)) + 4 *  ~~~(d ^^^ ( ~~~e &&& f)) - 2 * (e &&&  ~~~(d ^^^ f)) - 1 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 1 * (f ||| (d &&&  ~~~e)) - 1 * (e ^^^ ( ~~~d ||| (e ||| f))) + 11 * ((e &&& f) ||| (d &&& (e ||| f))) + 1 *  ~~~(e &&&  ~~~f) + 5 *  ~~~(e ||| f) - 1 * (f ^^^ (d ||| (e ||| f))) - 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 3 * (f ^^^  ~~~(d &&& (e ||| f))) + 1 * ( ~~~(d &&& e) &&& (e ^^^ f)) - 11 * (d &&& (e ^^^ f)) + 2 * (f ^^^  ~~~(d &&& ( ~~~e ||| f))) + 2 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 2 * (f ^^^ (d ||| ( ~~~e &&& f))) - 2 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 5 * (d &&&  ~~~f) - 1 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 1 *  ~~~( ~~~d &&& ( ~~~e ||| f)) - 3 *  ~~~(d ||| (e &&& f)) + 4 *  ~~~(d ^^^ (e &&& f)) + 2 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 7 * (e &&& f) - 7 *  ~~~(d ^^^ e) + 1 * (e ^^^ ( ~~~d &&& (e ^^^ f))) + 1 *  ~~~(d &&& e) - 1 *  ~~~(d &&& (e ^^^ f)) + 3 * (f ^^^ (d ||| e)) - 5 * (f ^^^  ~~~(d &&& (e &&& f))) + 1 * (e ^^^  ~~~(d |||  ~~~f)) - 7 * ( ~~~d &&& (e ^^^ f)) + 11 * (f ^^^ (d ||| ( ~~~e ||| f))) - 2 * ( ~~~d ||| (e &&& f)) - 11 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 7 * (e |||  ~~~(d ||| f)) - 1 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 7 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * (f ^^^ ( ~~~d ||| (e &&& f))) - 5 *  ~~~e + 2 * ( ~~~d &&& ( ~~~e ||| f)) + 2 * (e ^^^ ( ~~~d &&& (e ||| f))) + 11 * (f ^^^ (d &&& (e ||| f))) + 1 *  ~~~(d &&& ( ~~~e ||| f)) + 7 * (e |||  ~~~(d |||  ~~~f)) + 5 * ((d ||| e) &&&  ~~~(e ^^^ f)) - 5 * (e |||  ~~~(d ^^^ f)) + 5 *  ~~~(d ||| f) - 2 * (f ^^^  ~~~(d &&&  ~~~e)) - 1 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 1 * f - 3 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) - 3 * (e ^^^ (d &&& (e ^^^ f))) - 7 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(e ^^^ f)) - 1 *  ~~~( ~~~d ||| (e &&& f)) + 2 *  ~~~(d &&&  ~~~d) - 1 * (e ^^^ (d ||| ( ~~~e ||| f))) + 1 * ((d ^^^ e) ||| (d ^^^ f)) + 1 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 1 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 6 * (e ||| (d &&& f)) - 6 * (d ^^^ ( ~~~e &&& f)) - 7 *  ~~~(d ||| (e ||| f)) + 3 *  ~~~(d ||| ( ~~~e ||| f)) + 27 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 47 * ( ~~~d &&& ( ~~~e &&& f)) - 25 * ( ~~~d &&& (e &&& f)) + 39 * (d &&& ( ~~~e &&& f)) + 17 * (d &&& (e &&& f)) =  - 23 *  ~~~( ~~~d ||| (e ||| f)) + 7 * (d |||  ~~~f)

theorem test17_thm (e : IntW 106) :
  icmp IntPred.eq (lshr e (const? 106 3)) (const? 106 1234) ⊑
    icmp IntPred.eq (LLVM.and e (const? 106 (-8))) (const? 106 9872)

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

theorem rem_euclid_non_const_pow2_thm.extracted_1._4 : ∀ (x x_1 : BitVec 8),
  ¬(x ≥ ↑8 ∨ (1#8 <<< x == 0 || 8 != 1 && x_1 == intMin 8 && 1#8 <<< x == -1) = true) →
    ¬ofBool (x_1.srem (1#8 <<< x) <ₛ 0#8) = 1#1 →
      ¬(True ∧ ((-1#8) <<< x).sshiftRight' x ≠ -1#8 ∨ x ≥ ↑8) →
        x_1.srem (1#8 <<< x) = x_1 &&& ((-1#8) <<< x ^^^ -1#8)

theorem zext_nneg_sext_sle_op0_narrow_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ¬(True ∧ x_1.msb = true) → ofBool (zeroExtend 32 x_1 ≤ₛ signExtend 32 x) = ofBool (signExtend 16 x_1 ≤ₛ x)

theorem negative_and_odd_proof : negative_and_odd_before ⊑ negative_and_odd_after

theorem t2_ult_sgt_128_thm.extracted_1._6 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 + 16#32 <ᵤ 144#32) = 1#1 →
    ¬ofBool (127#32 <ₛ x_1) = 1#1 → ¬ofBool (x_1 <ₛ BitVec.ofInt 32 (-16)) = 1#1 → x = x_1

theorem p0_proof : p0_before ⊑ p0_after

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

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

theorem mul_of_bool_no_lz_other_op_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  ¬(True ∧ (x_1 &&& 1#32).smulOverflow (signExtend 32 x) = true ∨
        True ∧ (x_1 &&& 1#32).umulOverflow (signExtend 32 x) = true) →
    ofBool (127#32 <ₛ (x_1 &&& 1#32) * signExtend 32 x) = 0#1

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

theorem not_zext_thm (e : IntW 1) : select e (const? 999 0) (const? 999 1) ⊑ zext 999 (LLVM.xor e (const? 1 1))

theorem e_1934 :
    4 * ( ~~~(a &&&  ~~~b) &&& (b ^^^ c)) + 11 * (a ^^^ (b &&& c)) - 6 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 11 * (c &&& (a ||| b)) - 5 * (c ^^^ ( ~~~a ||| (b ||| c))) - 7 * (b &&& (a |||  ~~~c)) + 1 * (c ||| (a ^^^ b)) + 1 * b + 7 * (c ||| (a &&&  ~~~b)) - 2 * c - 1 * (c ^^^ (a &&& ( ~~~b ||| c))) - 1 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) - 2 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) - 6 *  ~~~( ~~~a &&& (b ^^^ c)) + 1 * (c |||  ~~~(a |||  ~~~b)) - 1 *  ~~~a - 11 *  ~~~(a &&& c) + 5 *  ~~~(a ||| (b &&& c)) - 6 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 2 *  ~~~(b |||  ~~~c) + 1 * (a ||| c) - 7 * (a |||  ~~~c) + 2 * ((a &&& c) ^^^ (a ^^^ (b &&& c))) - 11 * (c ^^^ (a ||| ( ~~~b &&& c))) + 2 * (c ^^^  ~~~(a &&& b)) - 3 * (b ^^^ (a &&& c)) - 2 *  ~~~( ~~~a ||| (b ^^^ c)) - 11 *  ~~~(a ||| (b ^^^ c)) + 2 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) - 1 * ( ~~~a ||| (b ||| c)) - 11 * ( ~~~c |||  ~~~(a ^^^ b)) + 4 * (b ^^^ (a ||| (b ||| c))) + 3 * (c &&& (a |||  ~~~b)) - 1 * (c ^^^  ~~~(a ||| b)) + 2 * ((a &&& b) |||  ~~~(b ||| c)) + 4 * (c ^^^  ~~~(a &&& ( ~~~b &&& c))) - 1 * ((a &&& c) ||| (b &&&  ~~~c)) - 2 * ((a ^^^ b) &&&  ~~~(a ^^^ c)) - 11 * (b ||| (a &&& c)) + 1 * (c |||  ~~~(a ||| b)) + 2 * ( ~~~a ||| ( ~~~b &&& c)) - 6 * (b ^^^ (a &&& ( ~~~b ||| c))) + 4 * (b ^^^  ~~~(a ||| (b ^^^ c))) - 1 * (c ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 43 *  ~~~(a ||| (b ||| c)) + 52 *  ~~~(a ||| ( ~~~b ||| c)) + 29 *  ~~~( ~~~a ||| (b ||| c)) + 55 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 1 * ( ~~~a &&& ( ~~~b &&& c)) + 39 * ( ~~~a &&& (b &&& c)) - 2 * (a &&& ( ~~~b &&& c)) + 23 * (a &&& (b &&& c)) = 2 * (b ^^^ (a |||  ~~~c))

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

theorem test37_proof : test37_before ⊑ test37_after

theorem two_signed_truncation_checks_proof : two_signed_truncation_checks_before ⊑ two_signed_truncation_checks_after

theorem test_sle_xor_thm (e e_1 : IntW 32) :
  icmp IntPred.sle (LLVM.xor (LLVM.xor e_1 (const? 32 (-1))) e) (LLVM.xor e_1 (const? 32 (-1))) ⊑
    icmp IntPred.sge (LLVM.xor e e_1) e_1

theorem zext_mul_thm.extracted_1._1 : ∀ (x : BitVec 8),
  zeroExtend 16 x * 3#16 &&& zeroExtend 16 x = zeroExtend 16 (x * 3#8 &&& x)

theorem neg_test_icmp_non_equality_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741823#32 <ₛ 0#32) = 1#1 → ¬2#32 ≥ ↑32 → 0#32 = x <<< 2#32

theorem t5_c2_proof : t5_c2_before ⊑ t5_c2_after

theorem samesign_inverted_commute3_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 ||| x <ₛ 0#32) &&& ofBool (-1#32 <ₛ x &&& x_1) = ofBool (x_1 ^^^ x <ₛ 0#32)

theorem test18a_proof : test18a_before ⊑ test18a_after

theorem fast_div_201_thm (e : IntW 8) :
  lshr
      (add (trunc 8 (lshr (mul (zext 16 e) (const? 16 71)) (const? 16 8)))
        (lshr (sub e (trunc 8 (lshr (mul (zext 16 e) (const? 16 71)) (const? 16 8)))) (const? 8 1)))
      (const? 8 7) ⊑
    lshr
      (add
        (lshr
          (sub e
            (trunc 8 (lshr (mul (zext 16 e) (const? 16 71) { «nsw» := true, «nuw» := true }) (const? 16 8))
              { «nsw» := true, «nuw» := true }))
          (const? 8 1))
        (trunc 8 (lshr (mul (zext 16 e) (const? 16 71) { «nsw» := true, «nuw» := true }) (const? 16 8))
          { «nsw» := true, «nuw» := true })
        { «nsw» := false, «nuw» := true })
      (const? 8 7)

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

theorem test10_thm (e : IntW 1) : icmp IntPred.ugt e (const? 1 1) ⊑ const? 1 0

theorem select_mul_icmp_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.eq e_2 (const? 32 1)) (mul e_2 e_1) e ⊑
    select (icmp IntPred.eq e_2 (const? 32 1)) e_1 e

theorem sge_or_not_max_commute_proof : sge_or_not_max_commute_before ⊑ sge_or_not_max_commute_after

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

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

theorem ashrsgt_02_11_proof : ashrsgt_02_11_before ⊑ ashrsgt_02_11_after

theorem uge_umin4_thm (e e_1 : IntW 32) :
  icmp IntPred.ule (add e_1 (const? 32 3))
      (select (icmp IntPred.ult e (add e_1 (const? 32 3))) e (add e_1 (const? 32 3))) ⊑
    icmp IntPred.uge e (add e_1 (const? 32 3))

theorem e_1246 :
    4 *  ~~~t + 4 *  ~~~(z &&&  ~~~t) - 1 * z + 1 * (z ^^^ t) + 1 *  ~~~z + 4 *  ~~~(z &&& t) - 13 *  ~~~(z ||| t) - 9 * (z &&&  ~~~t) - 4 * (z &&& t) =  - 1 * (z ||| t) + 11 *  ~~~(z |||  ~~~t)

theorem e_191 :
     - 11 *  ~~~(x ^^^ y) + 11 * y + 5 * (x ||| y) + 4 *  ~~~(x ||| y) - 12 * (x &&&  ~~~y) - 5 * (x &&& y) =  - 7 *  ~~~(x &&& y) + 23 *  ~~~(x |||  ~~~y)

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

theorem lshr_exact_proof : lshr_exact_before ⊑ lshr_exact_after

theorem e_87 :
    2 * (x |||  ~~~y) + 5 *  ~~~(x &&&  ~~~y) - 7 *  ~~~(x ||| y) - 2 * (x &&&  ~~~y) - 14 * (x &&& y) = 12 *  ~~~(x |||  ~~~y) - 7 * y

theorem add_nsw_const_const_sub_nsw_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(True ∧ x.saddOverflow 1#8 = true ∨ True ∧ (BitVec.ofInt 8 (-127)).ssubOverflow (x + 1#8) = true) →
    ¬(True ∧ (BitVec.ofInt 8 (-128)).ssubOverflow x = true) →
      BitVec.ofInt 8 (-127) - (x + 1#8) = BitVec.ofInt 8 (-128) - x

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 55), ¬1#55 ≥ ↑55 → x <<< 1#55 * 3#55 = x * 6#55

theorem lshrugt_01_06_exact_proof : lshrugt_01_06_exact_before ⊑ lshrugt_01_06_exact_after

theorem test9_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), x_1 &&& x ^^^ (x_1 ^^^ x) = x_1 ||

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

theorem pv_proof : pv_before ⊑ pv_after

theorem bitwise_or_logical_or_icmps_comm1_proof : bitwise_or_logical_or_icmps_comm1_before ⊑ bitwise_or_logical_or_icmps_comm1_after

theorem different_size_sext_sext_eq_proof : different_size_sext_sext_eq_before ⊑ different_size_sext_sext_eq_after

theorem ne_smax3_thm (e e_1 : IntW 32) :
  icmp IntPred.ne (add e_1 (const? 32 3))
      (select (icmp IntPred.sgt (add e_1 (const? 32 3)) e) (add e_1 (const? 32 3)) e) ⊑
    icmp IntPred.slt (add e_1 (const? 32 3)) e

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

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

theorem sgt_smax3_proof : sgt_smax3_before ⊑ sgt_smax3_after

theorem test84_proof : test84_before ⊑ test84_after

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

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

theorem or_shl_thm.extracted_1._1 : ∀ (x x_1 x_2 x_3 : BitVec 8), ¬(x_2 ≥ ↑8 ∨ x_2 ≥ ↑8) → x_2 ≥ ↑8 → False

theorem canonicalize_logic_first_xor_0_nsw_proof : canonicalize_logic_first_xor_0_nsw_before ⊑ canonicalize_logic_first_xor_0_nsw_after

theorem pr40493_thm (e : IntW 32) :
  icmp IntPred.eq (LLVM.and (mul e (const? 32 12)) (const? 32 4)) (const? 32 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 1)) (const? 32 0)

theorem lshr_and_sub_proof : lshr_and_sub_before ⊑ lshr_and_sub_after

theorem icmp_ne_and_pow2_lshr_pow2_case2_proof : icmp_ne_and_pow2_lshr_pow2_case2_before ⊑ icmp_ne_and_pow2_lshr_pow2_case2_after

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

theorem e_1681 :
    1 * ( ~~~b &&& (a ^^^ c)) + 2 * ((a |||  ~~~b) &&& (b ^^^ c)) - 6 * (b |||  ~~~(a ^^^ c)) - 2 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 1 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) - 2 *  ~~~(b &&&  ~~~c) - 1 *  ~~~(a ^^^ (b ||| c)) + 1 * b + 1 * (c ^^^ (a &&& ( ~~~b ||| c))) + 2 * (b ^^^ ( ~~~a &&& (b ||| c))) - 1 * (c ^^^ (a &&&  ~~~b)) + 4 * (b ^^^ (a ||| c)) + 1 * (a ||| (b &&& c)) - 1 * (c ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 2 * (b ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 2 * (b &&&  ~~~c) - 1 * (b ^^^ (a &&& (b ^^^ c))) - 1 * (c |||  ~~~(a ||| b)) + 2 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) + 13 *  ~~~(a ||| (b ||| c)) + 3 *  ~~~(a ||| ( ~~~b ||| c)) + 4 *  ~~~( ~~~a ||| (b ||| c)) + 3 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 4 * ( ~~~a &&& ( ~~~b &&& c)) + 17 * ( ~~~a &&& (b &&& c)) + 9 * (a &&& ( ~~~b &&& c)) + 10 * (a &&& (b &&& c)) = 3 *  ~~~(a &&& c) + 1 * ((a &&& b) ^^^ (b |||  ~~~c))

theorem ule_swap_and_min_proof : ule_swap_and_min_before ⊑ ule_swap_and_min_after

theorem foo1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), x_1 - x = x ^^^ x_1

theorem src_is_mask_zext_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 16),
  ¬x ≥ ↑8 →
    ofBool ((x_1 ^^^ 123#16) &&& zeroExtend 16 ((-1#8) >>> x) == x_1 ^^^ 123#16) =
      ofBool (x_1 ^^^ 123#16 ≤ᵤ zeroExtend 16 ((-1#8) >>> x))

theorem and_or1_wrong_operand_proof : and_or1_wrong_operand_before ⊑ and_or1_wrong_operand_after

theorem lshrugt_03_12_proof : lshrugt_03_12_before ⊑ lshrugt_03_12_after

theorem test_ult_xor_proof : test_ult_xor_before ⊑ test_ult_xor_after

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

theorem select_constants_and_icmp_ne0_common_bit_thm.extracted_1._2 : ∀ (x x_1 : BitVec 1),
  x_1 = 1#1 → ¬x = 1#1 → ofBool (2#8 &&& 3#8 != 0#8) = 1#1

theorem test_nuw_dropped_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741823#32 == 0#32) = 1#1 → 2#32 ≥ ↑32 → False

theorem logical_or_logical_or_icmps_comm1_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 8),
  ¬x_1 ≥ ↑8 →
    ofBool (x_2 &&& 1#8 <<< x_1 == 0#8) = 1#1 ∨ ofBool (x == 42#8) = 1#1 →
      ¬(True ∧ 1#8 <<< x_1 >>> x_1 ≠ 1#8 ∨ x_1 ≥ ↑8) →
        ¬ofBool (x_2 &&& 1#8 <<< x_1 == 0#8) = 1#1 → ¬ofBool (x == 42#8) = 1#1 → 1#1 = ofBool (x_2 &&& 1#8 == 0#8)

theorem test56_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬5#32 ≥ ↑32 → 5#32 ≥ ↑32 ∨ True ∧ (signExtend 32 x >>> 5#32).msb = true → False

theorem test14_thm (e e_1 : IntW 32) :
  add (add e_1 (const? 32 1) { «nsw» := true, «nuw» := false })
      (LLVM.xor (LLVM.or e (const? 32 (-1431655767))) (const? 32 1431655766)) { «nsw» := true, «nuw» := false } ⊑
    sub e_1 (LLVM.and e (const? 32 1431655766))

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

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

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

theorem bitwise_and_logical_and_masked_icmp_allzeros_poison1_thm.extracted_1._3 : ∀ (x : BitVec 1)
  (x_1 x_2 : BitVec 32),
  ofBool (x_2 &&& x_1 == 0#32) = 1#1 →
    ofBool (x_2 &&& (x_1 ||| 7#32) == 0#32) = 1#1 → x &&& ofBool (x_2 &&& 7#32 == 0#32) = x

theorem AvoidCollision_toInt_setWidth (x : BitVec w) :
    (x.setWidth v).toInt = Int.bmod x.toNat (2^v)

@[simp]
lemma dec_snoc_in_langRel {n} {R : BVNRel n} {w : BitVecs' n} {a : BitVec n} :
    dec (w ++ [a]) ∈ langRel R ↔
      R (List.Vector.ofFn fun k => .cons (a.getLsbD k) ((dec w).bvs.get k))

theorem alive_AddSub_1043 : alive_AddSub_1043_src  ⊑ alive_AddSub_1043_tgt

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

theorem e_1563 :
    2 * ( ~~~b |||  ~~~(a ^^^ c)) - 1 * (c &&& (a ^^^ b)) - 3 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 1 * (a ||| (b ||| c)) + 4 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) - 6 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) + 1 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 5 *  ~~~(a ||| (b ||| c)) - 2 *  ~~~(a ||| ( ~~~b ||| c)) + 9 *  ~~~( ~~~a ||| (b ||| c)) + 1 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 2 * ( ~~~a &&& ( ~~~b &&& c)) + 6 * ( ~~~a &&& (b &&& c)) + 3 * (a &&& ( ~~~b &&& c)) + 8 * (a &&& (b &&& c)) = 1 * (a |||  ~~~b)

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

theorem t0_exact_proof : t0_exact_before ⊑ t0_exact_after

theorem t4_ugt_slt_65536_proof : t4_ugt_slt_65536_before ⊑ t4_ugt_slt_65536_after

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

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

theorem PR24763_proof : PR24763_before ⊑ PR24763_after

theorem test_or_eq_a_b_commuted_thm (e e_1 : IntW 8) (e_2 : IntW 1) :
  select (LLVM.or e_2 (icmp IntPred.eq e_1 e)) e e_1 ⊑ select e_2 e e_1

theorem main7b_logical_thm (e e_1 e_2 : IntW 32) :
  select (select (icmp IntPred.eq e_2 (LLVM.and e_1 e_2)) (icmp IntPred.eq e (LLVM.and e_1 e)) (const? 1 0))
      (const? 32 0) (const? 32 1) ⊑
    zext 32
      (select (icmp IntPred.ne e_2 (LLVM.and e_1 e_2)) (const? 1 1)
        (icmp IntPred.ne e (LLVM.and e_1 e)))

theorem eq_umin3_thm (e e_1 : IntW 32) :
  icmp IntPred.eq (add e_1 (const? 32 3))
      (select (icmp IntPred.ult (add e_1 (const? 32 3)) e) (add e_1 (const? 32 3)) e) ⊑
    icmp IntPred.ule (add e_1 (const? 32 3)) e

theorem negative_and_odd_proof : negative_and_odd_before ⊑ negative_and_odd_after

theorem lshrult_03_13_exact_proof : lshrult_03_13_exact_before ⊑ lshrult_03_13_exact_after

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

theorem prove_exact_with_high_mask_limit_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(BitVec.ofInt 8 (-32) == 0 || 8 != 1 && x &&& BitVec.ofInt 8 (-32) == intMin 8 && BitVec.ofInt 8 (-32) == -1) =
        true →
    ¬(5#8 ≥ ↑8 ∨ True ∧ (0#8).ssubOverflow (x.sshiftRight' 5#8) = true) →
      (x &&& BitVec.ofInt 8 (-32)).sdiv (BitVec.ofInt 8 (-32)) = 0#8 - x.sshiftRight' 5#8

protected theorem carry'_eq_carry (x y : BitStream) (c : Bool)
    (x' y' : BitVec w)
    (hx : ∀ i, i < n → x'.getLsbD i = x i)
    (hy : ∀ i,  i < n → y'.getLsbD i = y i) :
    carry' c x y n = (BitVec.carry n x' y' c)

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

theorem test_ult_proof : test_ult_before ⊑ test_ult_after

theorem test_thm.extracted_1._4 : ∀ (x : BitVec 1) (x_1 : BitVec 64),
  ¬x = 1#1 →
    ¬(4#64 ≥ ↑64 ∨
          3#64 ≥ ↑64 ∨
            True ∧ (x_1 >>> 4#64).saddOverflow (x_1 >>> 3#64) = true ∨
              True ∧ (x_1 >>> 4#64).uaddOverflow (x_1 >>> 3#64) = true) →
      ¬(8#64 = 0 ∨ 0#64 = 0) → x_1 / 8#64 + x_1 / 0#64 = x_1 >>> 4#64 + x_1 >>> 3#64

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

theorem positive_biggerashr_shlnsw_proof : positive_biggerashr_shlnsw_before ⊑ positive_biggerashr_shlnsw_after

theorem shl_add_nuw_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(x ≥ ↑32 ∨ True ∧ (1#32 <<< x).uaddOverflow (-1#32) = true) → 1#32 <<< x + -1#32 = -1#32

theorem mul9_low_proof : mul9_low_before ⊑ mul9_low_after

theorem shift_xor_multiuse_cmp_and_proof : shift_xor_multiuse_cmp_and_before ⊑ shift_xor_multiuse_cmp_and_after

theorem sdiv6_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.smod 3#32 ≠ 0 ∨ (3#32 == 0 || 32 != 1 && x == intMin 32 && 3#32 == -1) = true) →
    x.sdiv 3#32 * BitVec.ofInt 32 (-3) = 0#32 - x

theorem alive_AndOrXor_2123___A__B__A__B___A__B : alive_AndOrXor_2123___A__B__A__B___A__B_src ⊑ alive_AndOrXor_2123___A__B__A__B___A__B_tgt

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

@[grind =, simp]
lemma addTrans_tr_neq (m : RawCNFA A) [LawfulBEq A] {a : A} {s₁ s₁' s₂ : State} (hneq : s₁ ≠ s₁') :
    (m.addTrans a s₁ s₂).tr s₁' a = m.tr s₁' a

theorem main7g_logical_proof : main7g_logical_before ⊑ main7g_logical_after

theorem or_disjoint_with_xor_proof : or_disjoint_with_xor_before ⊑ or_disjoint_with_xor_after

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 shl_nsw_ule_Csle0_fail_missing_flag_thm (e e_1 : IntW 8) :
  icmp IntPred.ule (shl e_1 e { «nsw» := true, «nuw» := false }) (const? 8 (-19)) ⊑
    icmp IntPred.ult (shl e_1 e { «nsw» := true, «nuw» := false }) (const? 8 (-18))

theorem test16_proof : test16_before ⊑ test16_after

theorem trunc_equality_nuw_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  ¬(True ∧ zeroExtend 16 (truncate 8 x_1) ≠ x_1 ∨ True ∧ zeroExtend 16 (truncate 8 x) ≠ x) →
    ofBool (truncate 8 x_1 == truncate 8 x) = ofBool (x_1 == x)

theorem zext_sext_add_icmp_sgt_minus1_proof : zext_sext_add_icmp_sgt_minus1_before ⊑ zext_sext_add_icmp_sgt_minus1_after

theorem test13_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬zeroExtend 128 x &&& 31#128 ≥ ↑128 → True ∧ (x &&& 31#32).msb = true ∨ zeroExtend 64 (x &&& 31#32) ≥ ↑64 → False

theorem main4c_logical_proof : main4c_logical_before ⊑ main4c_logical_after

theorem e_921 :
    2 *  ~~~(z &&& t) + 5 * z - 7 *  ~~~(z ||| t) - 12 *  ~~~(z |||  ~~~t) - 12 * (z &&&  ~~~t) - 15 * (z &&& t) =  - 5 * (z ||| t) - 5 *  ~~~(z &&&  ~~~t)

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

theorem test_add_nsw__all_are_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 1073741823#32 == 3#32) = 1#1 →
    ¬(True ∧ (x &&& 1073741823#32).saddOverflow 1#32 = true ∨ True ∧ (x &&& 1073741823#32).uaddOverflow 1#32 = true) →
      4#32 = (x &&& 1073741823#32) + 1#32

theorem ugt_swap_and_not_min_logical_proof : ugt_swap_and_not_min_logical_before ⊑ ugt_swap_and_not_min_logical_after

theorem or_and_not_not_commute5_proof : or_and_not_not_commute5_before ⊑ or_and_not_not_commute5_after

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

theorem e_1169 :
    1 *  ~~~(z &&&  ~~~z) - 1 *  ~~~(z &&&  ~~~t) - 7 *  ~~~z + 1 * t - 2 *  ~~~(z ||| t) + 6 *  ~~~(z |||  ~~~t) - 8 * (z &&&  ~~~t) - 10 * (z &&& t) =  - 2 *  ~~~(z ^^^ t) - 7 * (z |||  ~~~t)

@[simp]
theorem eval_ofNat (n : Nat) (i : Nat) {env : Fin 0 → BitStream} :
    (ofNat n).eval env i = n.testBit i

theorem t0_commutative_thm.extracted_1._15 : ∀ (x x_1 x_2 x_3 : BitVec 8),
  ofBool (x_3 == x_2) = 1#1 → ¬ofBool (x_3 != x_2) = 1#1 → True → 0#1 = 1#1 → x_1 = x

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

theorem select_icmp_ne_0_and_4096_or_32_thm (e e_1 : IntW 32) :
  select (icmp IntPred.ne (const? 32 0) (LLVM.and e_1 (const? 32 4096))) e (LLVM.or e (const? 32 32)) ⊑
    LLVM.or e (LLVM.xor (LLVM.and (lshr e_1 (const? 32 7)) (const? 32 32)) (const? 32 32))

theorem scalar_i32_shl_and_negC_eq_nonzero_proof : scalar_i32_shl_and_negC_eq_nonzero_before ⊑ scalar_i32_shl_and_negC_eq_nonzero_after

theorem bools_multi_uses1_logical_thm.extracted_1._17 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 ^^^ 1#1 = 1#1 → ¬x_2 = 1#1 → 0#1 = 1#1 → 1#1 ^^^ 0#1 = x_1 ^^^ 0#1

theorem lshrugt_03_01_exact_proof : lshrugt_03_01_exact_before ⊑ lshrugt_03_01_exact_after

theorem select_icmp_ne_0_and_1073741824_xor_8_proof : select_icmp_ne_0_and_1073741824_xor_8_before ⊑ select_icmp_ne_0_and_1073741824_xor_8_after

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

theorem not_and_and_or_not_or_or_proof : not_and_and_or_not_or_or_before ⊑ not_and_and_or_not_or_or_after

theorem t5_ugt_slt_0_proof : t5_ugt_slt_0_before ⊑ t5_ugt_slt_0_after

theorem ult_and_max_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), ofBool (x_1 <ᵤ x) &&& ofBool (x_1 == -1#8) = 0#1
</all_available_lemmas>

<local_ctx>
import LeanMLIR.ErasedContext

import LeanMLIR.HVector

import LeanMLIR.EffectKind

import LeanMLIR.Framework.Dialect

import Mathlib.Data.Finset.Union

open Ctxt (Var VarSet Valuation Hom)

open TyDenote (toType)

abbrev RegionSignature Ty := List (Ctxt Ty × List Ty)

structure Signature (Ty : Type) where
  mkEffectful ::
  sig         : List Ty
  regSig      : RegionSignature Ty
  returnTypes : List Ty
  effectKind  : EffectKind := .pure

abbrev Signature.mk (sig : List Ty) (regSig : RegionSignature Ty) (returnTypes : List Ty) : Signature Ty :=
 { sig, regSig, returnTypes }

class DialectSignature (d : Dialect) where
  signature : d.Op → Signature d.Ty

namespace DialectSignature

variable {d} [s : DialectSignature d]

def sig          := Signature.sig ∘ s.signature

def regSig       := Signature.regSig ∘ s.signature

def returnTypes  := Signature.returnTypes ∘ s.signature

def effectKind   := Signature.effectKind ∘ s.signature

end DialectSignature

class DialectDenote (d : Dialect) [TyDenote d.Ty] [DialectSignature d] where
  denote : (op : d.Op) → HVector toType (DialectSignature.sig op) →
    (HVector (fun t : Ctxt d.Ty × List d.Ty =>
      t.1.Valuation
      → EffectKind.impure.toMonad d.m (HVector toType t.2))
            (DialectSignature.regSig op)) →
    ((DialectSignature.effectKind op).toMonad d.m
      (HVector toType <| DialectSignature.returnTypes op))

section DataStructures

variable (d : Dialect) [DialectSignature d]

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

inductive Com : Ctxt d.Ty → EffectKind → List d.Ty → Type where
  | rets {Γ} {tys} {eff : EffectKind} (vs : HVector Γ.Var tys) : Com Γ eff tys
  | var (e : Expr Γ eff ty) (body : Com (ty ++ Γ) eff β) : Com Γ eff β

end

abbrev Expr.outContext (_ : Expr d Γ eff ts) : Ctxt d.Ty :=
  ts ++ Γ

abbrev Regions (regSig : RegionSignature d.Ty) : Type :=
  HVector (fun t => Com d t.1 .impure t.2) regSig

inductive Lets (Γ_in : Ctxt d.Ty) (eff : EffectKind) :
    (Γ_out : Ctxt d.Ty) → Type where
  | nil : Lets Γ_in eff Γ_in
  | var (body : Lets Γ_in eff Γ_out) (e : Expr d Γ_out eff t) : Lets Γ_in eff e.outContext

variable {d} [DialectSignature d]

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

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

protected instance Com.decidableEq [DecidableEq d.Op] [DecidableEq d.Ty]
    {Γ : Ctxt d.Ty} {eff : EffectKind} {tys : List d.Ty} : DecidableEq (Com d Γ eff tys)
  | .rets v₁, .rets v₂ => decidable_of_iff (v₁ = v₂) (by admit /- proof elided -/
  )
  | .var (ty := ty₁) e₁ body₁, .var (ty := ty₂) e₂ body₂ =>
    if hα : ty₁ = ty₂
    then by
      subst hα
      letI := Expr.decidableEq e₁ e₂
      letI := Com.decidableEq body₁ body₂
      exact decidable_of_iff (e₁ = e₂ ∧ body₁ = body₂) (by admit /- proof elided -/
      )
    else isFalse (by admit /- proof elided -/
    )
  | .rets _, .var _ _ => isFalse (fun h => Com.noConfusion h)
  | .var _ _, .rets _ => isFalse (fun h => Com.noConfusion h)

end -- decEq

end DataStructures

variable {d : Dialect} [DialectSignature d]

section Rec

variable {eff t} {motive : ∀ {Γ}, Com d Γ eff t → Sort u}
          (rets : ∀ {Γ : Ctxt _} , (v : HVector Γ.Var t) → motive (Com.rets v))
          (var : ∀ {Γ} {u},
            (e : Expr d Γ eff u) → (body : Com d e.outContext eff t) →
              motive body → motive (Com.var e body))

def Com.rec' {Γ} (com : Com d Γ eff t) : motive com :=
   
  Com.rec
    (motive_1 := fun _ _ _ _ => PUnit)
    (motive_2 := fun _ eff' t' c =>
      (h₁ : eff = eff') → (h₂ : t = t') → motive (h₁ ▸ h₂ ▸ c))
    (motive_3 := fun _ _ => PUnit)
    (fun _ _ _ _ _ _ => ⟨⟩) 
    (fun v h₁ h₂ => 
      cast (by admit /- proof elided -/
      ) <| rets (h₂ ▸ v))
    (fun e' body' _ r' h₁ h₂ => 
      let e := h₁ ▸ e'
      let body : Com _ _ eff t := cast (by admit /- proof elided -/
      ) body'
      let r : motive body := cast (by admit /- proof elided -/
      ) (r' h₁ h₂)
      cast (by admit /- proof elided -/
      ) <| var e body r)
    ⟨⟩
    (fun _ _ _ _ => ⟨⟩)
    com
    rfl
    rfl

variable {rets} {var} {Γ : Ctxt _}

end Rec

def Expr.args {Γ ts} (e : Expr d Γ eff ts) :
    HVector (Var Γ) (DialectSignature.sig e.op) :=
  Expr.casesOn e (fun _ _ _ args _ => args)

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

section Lemmas

namespace Com

end Com

end Lemmas

def Com.outContext {Γ} : Com d Γ eff ts → Ctxt d.Ty :=
  Com.rec' (motive := fun _ => Ctxt d.Ty)
    (@fun Γ _ => Γ) 
    (fun _ _ r => r) 

abbrev Expr.contextHom (e : Expr d Γ eff ts) : Γ.Hom e.outContext :=
  Hom.id.appendCodomain

section Lemmas

end Lemmas

variable [TyDenote d.Ty] [DialectDenote d] [DecidableEq d.Ty] [Monad d.m] [LawfulMonad d.m]

end

section Unfoldings

open EffectKind (liftEffect)

end Unfoldings

section Lemmas

end Lemmas

def Expr.changeVars (varsMap : Γ.Hom Γ') {ty} (e : Expr d Γ eff ty) :
    Expr d Γ' eff ty :=
  ⟨e.op, e.ty_eq, e.eff_le, e.args.map varsMap, e.regArgs⟩

section Lemmas

variable {Γ Γ' : Ctxt d.Ty} {t} (f : Γ.Hom Γ') (e : Expr d Γ eff t) (V : Γ'.Valuation)

end Lemmas

structure FlatCom (d : Dialect) [DialectSignature d]  (Γ_in : Ctxt d.Ty) (eff : EffectKind)
    (Γ_out : Ctxt d.Ty) (ts : List d.Ty) where
  lets : Lets d Γ_in eff Γ_out
  rets : HVector Γ_out.Var ts

section Lemmas

end Lemmas

section toPureLemmas

variable {Γ eff ty} {e : Expr d Γ eff ty} (h : e.HasPureOp)

end toPureLemmas

section DenoteInsert

end DenoteInsert

def Lets.getPureExprAux {Γ₁ Γ₂ : Ctxt d.Ty} {t} : Lets d Γ₁ eff Γ₂ → (v : Var Γ₂ t) →
    Option (Σ ts, (Var ⟨ts⟩ t) × Expr d (Γ₂.dropUntil v) .pure ts)
  | .nil, _ => none
  | .var (Γ_out := Γ_out) (t := t) lets e, v => by admit /- proof elided -/
    | right v =>
        apply cast ?_ <| Lets.getPureExprAux lets v
        simp
    | left v =>
        have h : (Ctxt.dropUntil t v) ++ Γ_out = e.outContext.dropUntil v.appendInl := by admit /- proof elided -/

def Lets.getPureExpr {Γ₁ Γ₂ : Ctxt d.Ty} (lets : Lets d Γ₁ eff Γ₂) {t : d.Ty} (v : Var Γ₂ t) :
    Option (Σ ts, (Var ⟨ts⟩ t) × Expr d Γ₂ .pure ts) :=
  (getPureExprAux lets v).map fun ⟨_, v, e⟩ =>
    ⟨_, v, e.changeVars Ctxt.dropUntilHom⟩
</local_ctx>

<target_theorem>
@[simp] theorem Lets.getPureExpr_var_appendInl (lets : Lets d Γ_in eff Γ_out)
    (e : Expr d Γ_out eff ty) (v : Var ⟨ty⟩ u) :
    getPureExpr (lets.var e) v.appendInl
    = e.toPure?.map (fun e => ⟨_, v, e.changeVars <| e.contextHom⟩) :=
</target_theorem>

