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
Sigma in Init.Core
Sigma.mk in Init.Core
Subtype 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 appendInr (v : Var Δ t) : (Γ ++ Δ).Var t :=
  ⟨v.val + Γ.length, by admit /- proof elided -/
  ⟩

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

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

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

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

@[simp]
def ofNat_eq_concrete (x : Nat) :
    (OfNat.ofNat x) = (ConcreteOrMVar.concrete x : ConcreteOrMVar Nat φ) := rfl

def HVector.replicateToList {α : Type} {f : α → Type} {a : α} :
    {n : Nat} → HVector f (List.replicate n a) → List (f a)
  | 0, _ => []
  | n + 1, HVector.cons x xs => x :: replicateToList xs


example (op : Comb.Op) : DialectSignature.effectKind (d := HSxComb) (.comb op) = .pure := rfl



example (op : Comb.Op) : DialectSignature.regSig (d := HSxComb) (.comb op) = [] := rfl

def add_select_not_sext_after := [llvm|
{
^0(%arg26 : i1):
  %0 = llvm.mlir.constant(64) : i64
  %1 = llvm.mlir.constant(0) : i64
  %2 = "llvm.select"(%arg26, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%2) : (i64) -> ()
}
]

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

def foo1_or_signbit_lshr_without_shifting_signbit_both_sides_after := [llvm|
{
^0(%arg100 : i32, %arg101 : i32, %arg102 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.shl %arg100, %arg101 : i32
  %2 = llvm.shl %arg100, %arg102 : i32
  %3 = llvm.and %1, %2 : i32
  %4 = llvm.icmp "slt" %3, %0 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

def ashr_ult_noexact_before := [llvm|
{
^0(%arg159 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(10 : i8) : i8
  %2 = llvm.ashr %arg159, %0 : i8
  %3 = llvm.icmp "ult" %2, %1 : i8
  "llvm.return"(%3) : (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 test15_after := [llvm|
{
^0(%arg284 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  "llvm.return"(%0) : (i8) -> ()
}
]

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

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

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

@[tactic fpGeneralize]
def evalFpGeneralize : Tactic
  | `(tactic| fp_generalize $cfg) => do
      withMainContext do
        let cfg ← elabMedusaSynthGeneralizeConfig cfg
        generalizeTactic (H := fpHydrableParseAndGeneralize) cfg (← getMainTarget)
  | _ => Lean.Elab.throwUnsupportedSyntax

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

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

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

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

def 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 icmp_ule_riscv_eq_icmp_ule_llvm_64 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] :=
  {lhs:= icmp_ule_llvm_64, rhs:= icmp_ule_riscv_64}

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

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

def t3_after := [llvm|
{
^0(%arg23 : i8, %arg24 : i2):
  %0 = llvm.sext %arg24 : i2 to i8
  %1 = llvm.add %arg23, %0 : i8
  %2 = llvm.xor %1, %0 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

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

def mkTermExpr (wcard tcard bcard ncard icard pcard : Nat) (tctx : Expr)
    (t : MultiWidth.Nondep.Term) : SolverM Expr := do
  match t with
  | .bvOfBool b =>
    let bExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx b
    let out := mkAppN (mkConst ``MultiWidth.Term.bvOfBool [])
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx, bExpr]
    debugCheck out
    return out
  | .ofNat w n =>
    let wExpr ← mkWidthExpr wcard w
    let out := mkAppN (mkConst ``MultiWidth.Term.ofNat [])
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx, wExpr, mkNatLit n]
    debugCheck out
    return out
  | .var v _wexpr =>
    let out := mkAppN (mkConst ``MultiWidth.Term.var [])
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx, ← mkFinLit tcard v]
    debugCheck out
    return out
  | .add _w a b =>
     let out ← mkAppM ``MultiWidth.Term.add
        #[← mkTermExpr wcard tcard bcard ncard icard pcard tctx a,
        ← mkTermExpr wcard tcard bcard ncard icard pcard tctx b]
     debugCheck out
     return out
  | .zext a v =>
    let vExpr ← mkWidthExpr wcard v
    let out ← mkAppM ``MultiWidth.Term.zext
      #[← mkTermExpr wcard tcard bcard ncard icard pcard tctx a, vExpr]
    debugCheck out
    return out
  | .setWidth a v =>
    let vExpr ← mkWidthExpr wcard v
    let out ← mkAppM ``MultiWidth.Term.setWidth
      #[← mkTermExpr wcard tcard bcard ncard icard pcard tctx a, vExpr]
    debugCheck out
    return out
  | .sext a v =>
    let vExpr ← mkWidthExpr wcard v
    let out ← mkAppM ``MultiWidth.Term.sext
      #[← mkTermExpr wcard tcard bcard ncard icard pcard tctx a, vExpr]
    debugCheck out
    return out
  | .band w a b =>
      let wExpr ← mkWidthExpr wcard w
      let aExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx a
      let bExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx b
      let out := mkAppN (mkConst ``MultiWidth.Term.band)
        #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
          wExpr, aExpr, bExpr]
      debugCheck out
      return out
  | .bor w a b =>
    let wExpr ← mkWidthExpr wcard w
    let aExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx a
    let bExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx b
    let out := mkAppN (mkConst ``MultiWidth.Term.bor)
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
        wExpr, aExpr, bExpr]
    debugCheck out
    return out
  | .bxor w a b =>
    let wExpr ← mkWidthExpr wcard w
    let aExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx a
    let bExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx b
    let out := mkAppN (mkConst ``MultiWidth.Term.bxor)
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
        wExpr, aExpr, bExpr]
    debugCheck out
    return out
  | .bnot w a =>
    let wExpr ← mkWidthExpr wcard w
    let aExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx a
    let out := mkAppN (mkConst ``MultiWidth.Term.bnot)
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
        wExpr, aExpr]
    debugCheck out
    return out
  | .boolVar v =>
    let out := mkAppN (mkConst ``MultiWidth.Term.boolVar [])
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
        ← mkFinLit bcard v]
    debugCheck out
    return out
  | .boolConst b =>
    let out := mkAppN (mkConst ``MultiWidth.Term.boolConst [])
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
        mkBoolLit b]
    debugCheck out
    return out
  | .shiftl w a n =>
    let wExpr ← mkWidthExpr wcard w
    let aExpr ← mkTermExpr wcard tcard bcard ncard icard pcard tctx a
    let nExpr := mkNatLit n
    let out := mkAppN (mkConst ``MultiWidth.Term.shiftl)
      #[mkNatLit wcard, mkNatLit tcard, mkNatLit bcard, mkNatLit ncard, mkNatLit icard, mkNatLit pcard, tctx,
        wExpr, aExpr, nExpr]
    debugCheck out
    return out
  | _ => throwError m!"mkTermExpr: unsupported term: {repr t}"

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

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

def test39_before := [llvm|
{
^0(%arg237 : i32):
  %0 = llvm.mlir.constant(7) : i64
  %1 = llvm.mlir.constant(240) : i64
  %2 = llvm.zext %arg237 : i32 to i64
  %3 = llvm.or %2, %0 : i64
  %4 = llvm.and %3, %1 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def test13_before := [llvm|
{
^0(%arg178 : i32, %arg179 : i32):
  %0 = llvm.xor %arg179, %arg178 : i32
  %1 = llvm.or %arg179, %arg178 : i32
  %2 = llvm.xor %1, %0 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

IO.FS.withTempFile in Init.System.IO

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 factorize5_after := [llvm|
{
^0(%arg1 : i32, %arg2 : i32):
  %0 = llvm.mul %arg2, %arg1 : i32
  "llvm.return"(%0) : (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 test9_after := [llvm|
{
^0(%arg298 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.icmp "slt" %arg298, %0 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

def 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 positive_biggershl_shlnuw_before := [llvm|
{
^0(%arg54 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(6 : i8) : i8
  %2 = llvm.ashr %arg54, %0 : i8
  %3 = llvm.shl %2, %1 overflow<nuw> : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def isPoison : PoisonOr α → Bool
  | poison => true
  | value _ => false

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

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

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

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

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

Functor.map in Init.Prelude

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

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

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

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

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

def or_and_not_constant_commute1_after := [llvm|
{
^0(%arg110 : i32, %arg111 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.and %arg110, %0 : i32
  %2 = llvm.or %1, %arg111 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

def mul_select_sext_after := [llvm|
{
^0(%arg17 : i1):
  %0 = llvm.mlir.constant(-64) : i64
  %1 = llvm.mlir.constant(0) : i64
  %2 = "llvm.select"(%arg17, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%2) : (i64) -> ()
}
]

instance : Monad (MetaLLVM φ).m :=

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

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

def select_mul_icmp_bad_after := [llvm|
{
^0(%arg158 : i32, %arg159 : i32, %arg160 : i32, %arg161 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.icmp "eq" %arg158, %0 : i32
  %2 = llvm.mul %arg160, %0 : i32
  %3 = "llvm.select"(%1, %2, %arg159) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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 invert_signbit_splat_mask_before := [llvm|
{
^0(%arg93 : i8, %arg94 : i16):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.ashr %arg93, %0 : i8
  %3 = llvm.xor %2, %1 : i8
  %4 = llvm.sext %3 : i8 to i16
  %5 = llvm.and %4, %arg94 : i16
  "llvm.return"(%5) : (i16) -> ()
}
]

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

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

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

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

def add64_accept_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := add64_accept_llvm
  rhs := add64_accept_riscv

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

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

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

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

RV64.srli in RISCV.Instructions

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

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

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

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

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

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

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

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

def t5_before := [llvm|
{
^0(%arg230 : i1, %arg231 : i1, %arg232 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(32 : i32) : i32
  %2 = llvm.mlir.constant(64 : i32) : i32
  %3 = llvm.shl %0, %arg232 : i32
  %4 = "llvm.select"(%arg230, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %5 = "llvm.select"(%arg231, %4, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %6 = llvm.udiv %arg232, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

def test_sub_nsw__all_are_safe_after := [llvm|
{
^0(%arg29 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.mlir.constant(-254 : i32) : i32
  %2 = llvm.and %arg29, %0 : i32
  %3 = llvm.sub %1, %2 overflow<nsw,nuw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

modifyGetThe in Init.Prelude

def xor_or_before := [llvm|
{
^0(%arg159 : i8):
  %0 = llvm.mlir.constant(32 : i8) : i8
  %1 = llvm.mlir.constant(7 : i8) : i8
  %2 = llvm.xor %arg159, %0 : i8
  %3 = llvm.or %2, %1 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def negative4_before := [llvm|
{
^0(%arg6 : i32, %arg7 : i32):
  %0 = llvm.mlir.constant(2147483647 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg7, %0 : i32
  %3 = llvm.icmp "ne" %arg6, %2 : i32
  %4 = llvm.icmp "sge" %arg6, %1 : i32
  %5 = llvm.and %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def shl_sub_i64_after := [llvm|
{
^0(%arg15 : i64):
  %0 = llvm.mlir.constant(-9223372036854775808) : i64
  %1 = llvm.lshr exact %0, %arg15 : i64
  "llvm.return"(%1) : (i64) -> ()
}
]

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

def List.Vector.transport (v : Vector α m) (f : Fin n → Fin m) : Vector α n :=
  Vector.ofFn fun i => v.get (f i)

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

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

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

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

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

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

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

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

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

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 and_zext_demanded_before := [llvm|
{
^0(%arg255 : i16, %arg256 : i32):
  %0 = llvm.mlir.constant(8 : i16) : i16
  %1 = llvm.mlir.constant(255 : i32) : i32
  %2 = llvm.lshr %arg255, %0 : i16
  %3 = llvm.zext %2 : i16 to i32
  %4 = llvm.or %arg256, %1 : i32
  %5 = llvm.and %4, %3 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

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

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

Lean.Core.getMessageLog in Lean.CoreM

@[simp_denote]
def zext_riscv_1_to_16 := [LV| {
  ^entry (%arg: i1):
    %0 = "builtin.unrealized_conversion_cast"(%arg) : (i1) -> !i64
    %1 = andi %0, 1 : !i64
    %res = "builtin.unrealized_conversion_cast"(%1) : (!i64) -> (i16)
    llvm.return %res : i16
  }]

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

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

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

def EnvFin.castLe {w n n' : Nat} (env : EnvFin w n) (h : n' ≤ n) : EnvFin w n' :=
  fun i' => env ⟨i', by admit /- proof elided -/
  ⟩

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

reprStr in Init.Data.Repr

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

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

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

Language.instMembershipList in Mathlib.Computability.Language

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 n2_before := [llvm|
{
^0(%arg10 : i16):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : i32) : i32
  %2 = llvm.zext %arg10 : i16 to i32
  %3 = llvm.shl %2, %0 : i32
  %4 = llvm.and %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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 llvm_sext_lower_riscv_i1_to_32 : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 1)] :=
  {lhs:= sext_llvm_i1_to_32, rhs:= sext_riscv_i1_to_32}

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

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 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 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 src_srem_shl_demand_max_mask_hit_demand_before := [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 : i32
  %5 = llvm.and %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def a_false_implies_b_true_before := [llvm|
{
^0(%arg15 : i8, %arg16 : i1, %arg17 : i1):
  %0 = llvm.mlir.constant(10 : i8) : i8
  %1 = llvm.mlir.constant(20 : i8) : i8
  %2 = llvm.mlir.constant(true) : i1
  %3 = llvm.icmp "ugt" %arg15, %0 : i8
  %4 = llvm.icmp "ult" %arg15, %1 : i8
  %5 = "llvm.select"(%4, %arg16, %arg17) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %6 = "llvm.select"(%3, %2, %5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%6) : (i1) -> ()
}
]

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

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

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

    |

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

def uge_or_max_commute_before := [llvm|
{
^0(%arg170 : i8, %arg171 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.icmp "uge" %arg170, %arg171 : i8
  %2 = llvm.icmp "eq" %arg170, %0 : i8
  %3 = llvm.or %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def and_not_or_or_not_or_xor_commute4_after := [llvm|
{
^0(%arg313 : i32, %arg314 : i32, %arg315 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg313 : i32
  %3 = llvm.or %arg314, %arg315 : i32
  %4 = llvm.xor %arg314, %arg315 : i32
  %5 = llvm.or %2, %4 : i32
  %6 = llvm.and %3, %5 : i32
  %7 = llvm.xor %6, %1 : i32
  "llvm.return"(%7) : (i32) -> ()
}
]

def bools2_logical_commute1_and1_and2_after := [llvm|
{
^0(%arg43 : i1, %arg44 : i1, %arg45 : i1):
  %0 = "llvm.select"(%arg45, %arg43, %arg44) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def select_add_before := [llvm|
{
^0(%arg15 : i1, %arg16 : i64, %arg17 : i64):
  %0 = llvm.add %arg16, %arg17 : i64
  %1 = "llvm.select"(%arg15, %0, %arg16) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%1) : (i64) -> ()
}
]

def is_rem4_neg_i16_after := [llvm|
{
^0(%arg54 : i16):
  %0 = llvm.mlir.constant(-32765 : i16) : i16
  %1 = llvm.mlir.constant(-32768 : i16) : i16
  %2 = llvm.and %arg54, %0 : i16
  %3 = llvm.icmp "ugt" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

def and_logic_and_logic_or_2_before := [llvm|
{
^0(%arg135 : i1, %arg136 : i1, %arg137 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.and %arg135, %arg136 : i1
  %3 = "llvm.select"(%arg137, %arg135, %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 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 test_ashr__exact_is_unsafe_after := [llvm|
{
^0(%arg48 : i32, %arg49 : i64):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.mlir.constant(-536870897 : i32) : i32
  %2 = llvm.ashr %arg48, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.zext nneg %3 : i32 to i64
  %5 = llvm.ashr %arg49, %4 : i64
  "llvm.return"(%5) : (i64) -> ()
}
]

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

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

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

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

def 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 positive_biggerashr_shlnuwnsw_ashrexact_after := [llvm|
{
^0(%arg25 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.ashr exact %arg25, %0 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

def test6_before := [llvm|
{
^0(%arg51 : i1023):
  %0 = llvm.mlir.constant(64 : i1023) : i1023
  %1 = llvm.mlir.constant(0 : i1023) : i1023
  %2 = llvm.and %arg51, %0 : i1023
  %3 = llvm.icmp "ne" %2, %1 : i1023
  %4 = "llvm.select"(%3, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1023, i1023) -> i1023
  "llvm.return"(%4) : (i1023) -> ()
}
]

def llvm_const_lower_riscv_li15 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM15, rhs:= liRiscv15,
   correct := by admit /- proof elided -/

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 test2_before := [llvm|
{
^0(%arg208 : i1):
  %0 = llvm.xor %arg208, %arg208 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

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

instance : TyDenote ExplicitISL.Ty where
  toType := fun
    | .isl ty => ⟦ty⟧
    | .regFile => RegFile

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

def mkWidthEnvEmpty : SolverM Expr := do
  let out := (mkConst ``MultiWidth.WidthExpr.Env.empty)
  debugCheck out
  return out

def or_eq_with_diff_one_logical_before := [llvm|
{
^0(%arg353 : i8):
  %0 = llvm.mlir.constant(13 : i8) : i8
  %1 = llvm.mlir.constant(14 : i8) : i8
  %2 = llvm.mlir.constant(true) : i1
  %3 = llvm.icmp "eq" %arg353, %0 : i8
  %4 = llvm.icmp "eq" %arg353, %1 : i8
  %5 = "llvm.select"(%3, %2, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (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 test22_logical_before := [llvm|
{
^0(%arg5 : i32, %arg6 : i32):
  %0 = llvm.mlir.constant(100663295 : i32) : i32
  %1 = llvm.mlir.constant(268435456 : i32) : i32
  %2 = llvm.mlir.constant(7 : i32) : i32
  %3 = llvm.mlir.constant(-1 : i32) : i32
  %4 = llvm.mlir.constant(true) : i1
  %5 = llvm.and %arg5, %0 : i32
  %6 = llvm.icmp "ult" %5, %1 : i32
  %7 = llvm.and %arg6, %2 : i32
  %8 = llvm.icmp "sgt" %7, %3 : i32
  %9 = "llvm.select"(%6, %4, %8) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%9) : (i1) -> ()
}
]

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

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

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

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

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

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

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

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

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

def shift_trunc_wrong_shift_after := [llvm|
{
^0(%arg1 : i32):
  %0 = llvm.mlir.constant(1073741824 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.and %arg1, %0 : i32
  %3 = llvm.icmp "ne" %2, %1 : i32
  "llvm.return"(%3) : (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 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 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 not_or_or_not_before := [llvm|
{
^0(%arg552 : i32, %arg553 : i32, %arg554 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg552 : i32
  %3 = llvm.xor %arg553, %1 : i32
  %4 = llvm.xor %arg554, %1 : i32
  %5 = llvm.or %2, %3 : i32
  %6 = llvm.or %5, %4 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

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

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

def multiuse_lshr_lshr_after := [llvm|
{
^0(%arg39 : i9):
  %0 = llvm.mlir.constant(2 : i9) : i9
  %1 = llvm.mlir.constant(5 : i9) : i9
  %2 = llvm.lshr %arg39, %0 : i9
  %3 = llvm.lshr %arg39, %1 : i9
  %4 = llvm.mul %2, %3 : i9
  "llvm.return"(%4) : (i9) -> ()
}
]

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

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

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

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

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

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

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

def add_shl_same_amount_before := [llvm|
{
^0(%arg59 : i6, %arg60 : i6, %arg61 : i6):
  %0 = llvm.shl %arg59, %arg61 : i6
  %1 = llvm.shl %arg60, %arg61 : i6
  %2 = llvm.add %0, %1 : i6
  "llvm.return"(%2) : (i6) -> ()
}
]

def test2_before := [llvm|
{
^0(%arg196 : i8):
  %0 = llvm.zext %arg196 : i8 to i16
  %1 = llvm.zext %0 : i16 to i32
  %2 = llvm.zext %1 : i32 to i64
  "llvm.return"(%2) : (i64) -> ()
}
]

def or_shl_after := [llvm|
{
^0(%arg640 : i8, %arg641 : i8, %arg642 : i8, %arg643 : i8):
  %0 = llvm.or %arg640, %arg641 : i8
  %1 = llvm.shl %0, %arg643 : i8
  %2 = llvm.or %1, %arg642 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

def hasAttr (attr : String) : Bool :=
  (op.getAttr? attr).isSome

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 and_logic_and_logic_or_6_after := [llvm|
{
^0(%arg123 : i1, %arg124 : i1, %arg125 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = "llvm.select"(%arg125, %0, %arg124) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %2 = llvm.and %arg123, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def lshr_and_sub_after := [llvm|
{
^0(%arg53 : i8, %arg54 : 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 %arg53, %0 : i8
  %4 = llvm.lshr %arg54, %1 : i8
  %5 = llvm.and %4, %2 : i8
  %6 = llvm.sub %3, %5 overflow<nsw> : i8
  %7 = llvm.shl %6, %1 : i8
  "llvm.return"(%7) : (i8) -> ()
}
]

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

def zext_nneg_sext_ugt_after := [llvm|
{
^0(%arg58 : i8, %arg59 : i8):
  %0 = llvm.icmp "ugt" %arg58, %arg59 : i8
  "llvm.return"(%0) : (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 or_xor_tree_1001_after := [llvm|
{
^0(%arg18 : i32, %arg19 : i32, %arg20 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mul %arg18, %0 : i32
  %2 = llvm.mul %arg19, %0 : i32
  %3 = llvm.mul %arg20, %0 : i32
  %4 = llvm.xor %2, %1 : i32
  %5 = llvm.or %4, %3 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

Lean.mkAtom in Init.Prelude

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

RV64.remu in RISCV.Instructions

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

def one_inst_concrete_com_proof :
    one_inst_concrete_com ⊑ one_inst_concrete_com :=

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

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

Lean.Name.mkSimple in Init.Prelude

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

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

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

def narrow_sext_and_before := [llvm|
{
^0(%arg56 : i16, %arg57 : i32):
  %0 = llvm.sext %arg56 : i16 to i32
  %1 = llvm.and %0, %arg57 : i32
  %2 = llvm.trunc %1 : i32 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

class HRefinement (α β : Type) where
   
  IsRefinedBy : α → β → Prop

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

AList.insert in Mathlib.Data.List.AList

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

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

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

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

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

def not_ashr_not_before := [llvm|
{
^0(%arg139 : i32, %arg140 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg139, %0 : i32
  %2 = llvm.ashr %1, %arg140 : i32
  %3 = llvm.xor %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def different_size_zext_zext_sgt_before := [llvm|
{
^0(%arg16 : i7, %arg17 : i4):
  %0 = llvm.zext %arg16 : i7 to i25
  %1 = llvm.zext %arg17 : i4 to i25
  %2 = llvm.icmp "sgt" %0, %1 : i25
  "llvm.return"(%2) : (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 Com.toLets (com : Com d Γ eff t) : Lets d Γ eff com.outContext :=
  Lets.nil.addComToEnd com

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 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 test11_before := [llvm|
{
^0(%arg48 : i32, %arg49 : i32):
  %0 = llvm.mlir.constant(-1431655766 : i32) : i32
  %1 = llvm.mlir.constant(1431655765 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.or %arg48, %0 : i32
  %4 = llvm.xor %3, %1 : i32
  %5 = llvm.add %arg49, %2 : i32
  %6 = llvm.add %5, %4 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

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

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

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

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

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

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

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

Valuation in Mathlib.RingTheory.Valuation.Basic

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

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

def absdiff1_before := [llvm|
{
^0(%arg2 : i64, %arg3 : i64):
  %0 = llvm.icmp "ult" %arg2, %arg3 : i64
  %1 = llvm.sext %0 : i1 to i64
  %2 = llvm.sub %arg2, %arg3 : i64
  %3 = llvm.xor %2, %1 : i64
  %4 = llvm.sub %3, %1 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def splat_mul_known_lz_before := [llvm|
{
^0(%arg72 : i32):
  %0 = llvm.mlir.constant(18446744078004518913 : i128) : i128
  %1 = llvm.mlir.constant(96 : i128) : i128
  %2 = llvm.mlir.constant(0 : i128) : i128
  %3 = llvm.zext %arg72 : i32 to i128
  %4 = llvm.mul %3, %0 : i128
  %5 = llvm.lshr %4, %1 : i128
  %6 = llvm.icmp "eq" %5, %2 : i128
  "llvm.return"(%6) : (i1) -> ()
}
]

def ashrsgt_03_06_exact_after := [llvm|
{
^0(%arg63 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (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 select_icmp_eq_0_and_1_xor_1_after := [llvm|
{
^0(%arg213 : i64, %arg214 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.trunc %arg213 : i64 to i32
  %2 = llvm.and %1, %0 : i32
  %3 = llvm.xor %arg214, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

def ashrsgt_02_05_after := [llvm|
{
^0(%arg296 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (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 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 sub_shl_same_amount_before := [llvm|
{
^0(%arg29 : i6, %arg30 : i6, %arg31 : i6):
  %0 = llvm.shl %arg29, %arg31 : i6
  %1 = llvm.shl %arg30, %arg31 : i6
  %2 = llvm.sub %0, %1 : i6
  "llvm.return"(%2) : (i6) -> ()
}
]

abbrev BitVecs' (n : Nat) := List (BitVec n)

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

def product (accept? : Prop → Prop → Prop) (M : NFA α σ) (N : NFA α ς) : NFA α (σ × ς) where
  step := fun (q₁, q₂) a => { (q₁', q₂') | (q₁' ∈ M.step q₁ a) ∧ (q₂' ∈ N.step q₂ a) }
  start := { (q₁, q₂) | (q₁ ∈ M.start) ∧ (q₂ ∈ N.start) }
  accept := { (q₁, q₂) | accept? (q₁ ∈ M.accept) (q₂ ∈ N.accept) }

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

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

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

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

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

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

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

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

def ult_swap_and_not_max_logical_before := [llvm|
{
^0(%arg100 : i8, %arg101 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.icmp "ugt" %arg101, %arg100 : i8
  %3 = llvm.icmp "ne" %arg100, %0 : i8
  %4 = "llvm.select"(%2, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (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 p0_before := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.shl %0, %arg29 : i8
  %2 = llvm.xor %1, %0 : i8
  %3 = llvm.icmp "ult" %2, %arg28 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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 join (x y : TokenStream) : TokenStream  :=
  syncMap₂ (xs := x) (ys := y) (f := sendReadySignal)

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

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

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

def main15_before := [llvm|
{
^0(%arg14 : 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 %arg14 : i32 to i16
  %5 = llvm.icmp "sge" %4, %0 : i16
  %6 = llvm.trunc %arg14 : i32 to i8
  %7 = llvm.icmp "sge" %6, %1 : i8
  %8 = llvm.or %5, %7 : i1
  %9 = "llvm.select"(%8, %2, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%9) : (i32) -> ()
}
]

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

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

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

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

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

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

@[simp_llvm]
def icmp' {w : Nat} (c : IntPred) (x y : BitVec w) : Bool :=
  match c with
    | .eq => (x == y)
    | .ne => (x != y)
    | .sgt => (x >ₛ y)
    | .sge => (x ≥ₛ y)
    | .slt => (x <ₛ y)
    | .sle => (x ≤ₛ y)
    | .ugt => (x >ᵤ y)
    | .uge => (x ≥ᵤ y)
    | .ult => (x <ᵤ y)
    | .ule => (x ≤ᵤ y)

def lshr_add_or_fail_after := [llvm|
{
^0(%arg92 : i8, %arg93 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(123 : i8) : i8
  %2 = llvm.lshr %arg92, %0 : i8
  %3 = llvm.lshr %arg93, %0 : i8
  %4 = llvm.add %3, %1 overflow<nuw> : i8
  %5 = llvm.or %2, %4 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

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

def 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 test15_before := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(8) : i64
  %2 = llvm.ashr %arg6, %0 : i32
  %3 = llvm.sext %2 : i32 to i64
  %4 = llvm.sub %1, %3 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

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

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

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

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

def andcond.100.inv.inner.cond.in.outer.cond_before := [llvm|
{
^0(%arg55 : i1, %arg56 : i1, %arg57 : i8, %arg58 : i8, %arg59 : i8):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.xor %arg55, %0 : i1
  %3 = "llvm.select"(%2, %arg56, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = "llvm.select"(%arg55, %arg57, %arg58) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %5 = "llvm.select"(%3, %arg59, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%5) : (i8) -> ()
}
]

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 sle_swap_or_min_after := [llvm|
{
^0(%arg150 : i8, %arg151 : i8):
  %0 = llvm.icmp "sge" %arg151, %arg150 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

instance : DialectPrint TestDialect where
  printOpName
    | .noop   => "noop"
    | .unPair => "unpair"
    | .mkPair => "pair"
  printAttributes _ := ""
  printTy
    | .int => "!int"
    | .int2 => "!int2"
  dialectName := "test"
  printReturn _ := "return"
  printFunc _ := "^entry"

Lean.SyntaxNodeKinds in Init.Prelude

elab "llvmTests!" : term <= ty => do
  mkElab llvmExtension ty

@[simp_denote]
def ori_riscv_i32 :=
  [LV| {
    ^entry (%arg: i32):
    %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64)
    %0 = ori %a, 5 : !i64
    %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32)
    llvm.return %1 : 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 n7_before := [llvm|
{
^0(%arg3 : i8, %arg4 : i8, %arg5 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.and %arg3, %0 : i8
  %2 = llvm.icmp "ne" %1, %0 : i8
  %3 = "llvm.select"(%2, %arg4, %arg5) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%3) : (i8) -> ()
}
]

def ex1_pre_cse : Com Ex ∅ .pure [.nat] :=
  Com.var (cst 1) <|
  Com.var (cst 1) <|
  Com.var (add ⟨0, rfl⟩ ⟨1, rfl⟩) <|
  Com.ret ⟨0, rfl⟩

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

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 State.cseArgList
 [TyDenote d.Ty] [DialectSignature d] [DialectDenote d]
  {Γstart Γ : Ctxt d.Ty} {lets : Lets d Γstart .pure Γ} (s : State d lets)
  {ts : List d.Ty}
  (as : HVector (Ctxt.Var Γ) <| ts) :
  { as' : HVector (Ctxt.Var Γ) <| ts // ∀ (V : Γstart.Valuation),
    as.map (lets.denote V).eval = as'.map (lets.denote V).eval  } :=
  match as with
  | .nil => ⟨.nil, by admit /- proof elided -/
    ⟩
  | .cons a as =>
    let ⟨a', ha'⟩ :=  s.var2var a
    let ⟨as', has'⟩ := s.cseArgList as
    ⟨.cons a' as', by admit /- proof elided -/
    ⟩

def bools2_logical_commute1_and2_after := [llvm|
{
^0(%arg46 : i1, %arg47 : i1, %arg48 : i1):
  %0 = "llvm.select"(%arg48, %arg46, %arg47) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def or_simplify_ugt_fail_before := [llvm|
{
^0(%arg7 : i8, %arg8 : i8):
  %0 = llvm.mlir.constant(-2 : i8) : i8
  %1 = llvm.mlir.constant(1 : i8) : i8
  %2 = llvm.and %arg7, %0 : i8
  %3 = llvm.or %arg8, %1 : i8
  %4 = llvm.or %2, %3 : i8
  %5 = llvm.icmp "ugt" %4, %3 : i8
  "llvm.return"(%5) : (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 canonicalize_logic_first_or0_before := [llvm|
{
^0(%arg40 : i32):
  %0 = llvm.mlir.constant(112 : i32) : i32
  %1 = llvm.mlir.constant(15 : i32) : i32
  %2 = llvm.add %arg40, %0 : i32
  %3 = llvm.or %2, %1 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

inductive Bracket
| Square 
| Round 
| Curly 
| Angle 
deriving Inhabited, DecidableEq

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

Lean.Meta.State in Lean.Meta.Basic

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

CoeDep in Init.Coe

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

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

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

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

def sext_zext_ne_known_nonneg_before := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.sext %arg10 : i8 to i32
  %2 = llvm.udiv %arg11, %0 : i8
  %3 = llvm.zext %2 : i8 to i32
  %4 = llvm.icmp "ne" %1, %3 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

def and_not_or_commute5_after := [llvm|
{
^0(%arg466 : i32, %arg467 : i32, %arg468 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.sdiv %0, %arg466 : i32
  %3 = llvm.sdiv %0, %arg468 : i32
  %4 = llvm.xor %arg467, %3 : i32
  %5 = llvm.and %4, %2 : i32
  %6 = llvm.xor %5, %1 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

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

def xor_with_or_disjoint_ab_before := [llvm|
{
^0(%arg26 : i32, %arg27 : i32):
  %0 = llvm.or disjoint %arg26, %arg27 : i32
  %1 = llvm.xor %arg26, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def aVal : DCOp.ValueStream (BitVec 32) := ofList [some 1#32, none, some 2#32, some 5#32, none]

def t15_and_with_const1_after := [llvm|
{
^0(%arg3 : i32, %arg4 : i32, %arg5 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg4 overflow<nuw> : i32
  %3 = llvm.and %arg3, %2 : i32
  %4 = llvm.icmp "eq" %3, %1 : i32
  "llvm.return"(%4) : (i1) -> ()
}
]

def PR21222_after := [llvm|
{
^0(%arg131 : i32):
  %0 = llvm.mlir.constant(6 : i32) : i32
  %1 = llvm.icmp "eq" %arg131, %0 : i32
  "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 shl_add_nsw_before := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(-32 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.or %arg10, %0 : i8
  %3 = llvm.and %arg11, %1 : i8
  %4 = llvm.shl %2, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

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

def defaultParsedExprState : ParsedInputState := { maxFreeVarId := 0, maxWidthId := 1, widthIdToVariable := {},
                                                                 widthValToVar := {}
                                                                 , numSymVars := 0, originalWidth := 32
                                                                , inputVarIdToVariable := {}, symVarToVal := {}
                                                                , symVarIdToVariable := {}, displayNameToVariable := {}, valToSymVar:= {}}

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

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

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

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

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

def test40_before := [llvm|
{
^0(%arg216 : i1):
  %0 = llvm.mlir.constant(1000 : i32) : i32
  %1 = llvm.mlir.constant(10 : i32) : i32
  %2 = llvm.mlir.constant(123 : i32) : i32
  %3 = "llvm.select"(%arg216, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.and %3, %2 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

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 test7_after := [llvm|
{
^0(%arg0 : i47):
  %0 = llvm.mlir.constant(-70368744177664 : i47) : i47
  %1 = llvm.mlir.constant(70368040490200 : i47) : i47
  %2 = llvm.and %arg0, %0 : i47
  %3 = llvm.or disjoint %2, %1 : i47
  "llvm.return"(%3) : (i47) -> ()
}
]

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

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

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

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

def 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 sext_sext_slt_after := [llvm|
{
^0(%arg74 : i8, %arg75 : i8):
  %0 = llvm.icmp "slt" %arg74, %arg75 : i8
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def worklistRun'_spec :
    (worklistRun' A S final inits hinits f |>.Sim $ nfa inits final f) :=

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 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 urem_i1_is_zero_before := [llvm|
{
^0(%arg0 : i1, %arg1 : i1):
  %0 = llvm.urem %arg0, %arg1 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

def ashr_can_be_lshr_after := [llvm|
{
^0(%arg1 : i32):
  %0 = llvm.mlir.constant(16 : i32) : i32
  %1 = llvm.lshr exact %arg1, %0 : i32
  %2 = llvm.trunc %1 overflow<nuw> : i32 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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

def liRiscv11 := [LV| {
  ^entry ():
    %0 = "li"() {imm = 11 : !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) -> ()
}
]

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

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

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

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

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

unsafe def elabIntoCore {α : Type} (expectedType : Expr) (stx : Lean.Syntax) : CoreM α :=
  elabIntoMeta (α := α) expectedType stx |>.run'

def test_sub__all_are_safe_after := [llvm|
{
^0(%arg28 : i32):
  %0 = llvm.mlir.constant(255 : i32) : i32
  %1 = llvm.mlir.constant(-254 : i32) : i32
  %2 = llvm.and %arg28, %0 : i32
  %3 = llvm.sub %1, %2 overflow<nsw,nuw> : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def 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 test6_logical_after := [llvm|
{
^0(%arg301 : i1):
  "llvm.return"(%arg301) : (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 llvm_const_lower_riscv_li_49 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_49, rhs:= liRiscv_49,
   correct := by admit /- proof elided -/

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

def add_const_add_const_before := [llvm|
{
^0(%arg71 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.add %arg71, %0 : i32
  %3 = llvm.add %2, %1 : i32
  "llvm.return"(%3) : (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 lshrugt_03_07_exact_after := [llvm|
{
^0(%arg182 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def test_nuw_and_unsigned_pred_after := [llvm|
{
^0(%arg57 : i64):
  %0 = llvm.mlir.constant(7) : i64
  %1 = llvm.icmp "ugt" %arg57, %0 : i64
  "llvm.return"(%1) : (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 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 lshrult_03_02_exact_after := [llvm|
{
^0(%arg115 : i4):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def test_add_sub_const_lhs_RHS := [mod_arith q, hq| {
  ^bb0(%x : !R):
    %res0 = mod_arith.constant 4 : !R
    %res1 = mod_arith.sub %res0, %x : !R
    return %res1 : !R
}]

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

def 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_samevar_shlnuwnsw_lshrexact_before := [llvm|
{
^0(%arg27 : i8, %arg28 : i8):
  %0 = llvm.lshr exact %arg27, %arg28 : i8
  %1 = llvm.shl %0, %arg28 overflow<nsw,nuw> : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

def srl_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where
  lhs := srl_llvm_i32
  rhs := srl_riscv_i32

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

def bool_add_ashr_after := [llvm|
{
^0(%arg10 : i1, %arg11 : i1):
  %0 = llvm.mlir.constant(1 : i2) : i2
  %1 = llvm.zext %arg10 : i1 to i2
  %2 = llvm.zext %arg11 : i1 to i2
  %3 = llvm.add %1, %2 overflow<nuw> : i2
  %4 = llvm.ashr %3, %0 : i2
  "llvm.return"(%4) : (i2) -> ()
}
]

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 test19_before := [llvm|
{
^0(%arg192 : i32, %arg193 : i32):
  %0 = llvm.xor %arg192, %arg193 : i32
  %1 = llvm.xor %0, %arg192 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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 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 t4_ugt_slt_65536_before := [llvm|
{
^0(%arg54 : i32, %arg55 : i32, %arg56 : i32):
  %0 = llvm.mlir.constant(65536 : i32) : i32
  %1 = llvm.mlir.constant(65535 : i32) : i32
  %2 = llvm.icmp "slt" %arg54, %0 : i32
  %3 = "llvm.select"(%2, %arg55, %arg56) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.icmp "ugt" %arg54, %1 : i32
  %5 = "llvm.select"(%4, %3, %arg54) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

def alive_AddSub_1152_src   :=
[llvm()| {
^bb0(%y : i1, %x : i1):
  %v1 = llvm.add %x, %y : i1
  llvm.return %v1 : i1
}]

Quotient.mk in Init.Core

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

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

def ripple_nsw1_before := [llvm|
{
^0(%arg23 : i16, %arg24 : i16):
  %0 = llvm.mlir.constant(1 : i16) : i16
  %1 = llvm.mlir.constant(-16385 : i16) : i16
  %2 = llvm.and %arg24, %0 : i16
  %3 = llvm.and %arg23, %1 : i16
  %4 = llvm.add %2, %3 : i16
  "llvm.return"(%4) : (i16) -> ()
}
]

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

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

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

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

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

def 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 test51_after := [llvm|
{
^0(%arg133 : i64, %arg134 : i1):
  %0 = llvm.mlir.constant(-2 : i32) : i32
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.trunc %arg133 : i64 to i32
  %3 = llvm.and %2, %0 : i32
  %4 = llvm.xor %arg134, %1 : i1
  %5 = llvm.zext %4 : i1 to i32
  %6 = llvm.or disjoint %3, %5 : i32
  %7 = llvm.sext %6 : i32 to i64
  "llvm.return"(%7) : (i64) -> ()
}
]

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

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

def p0_after := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.lshr %arg28, %arg29 : i8
  %2 = llvm.icmp "eq" %1, %0 : i8
  "llvm.return"(%2) : (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) -> ()
}
]

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

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

instance : ToExpr (Var Γ ty) where
  toTypeExpr := mkApp3 (mkConst ``Var) (toTypeExpr Ty) (toExpr Γ) (toExpr ty)
  toExpr := fun ⟨i, _hi⟩ =>
    let Ty := toTypeExpr Ty
    let Γ := toExpr Γ
    let ty := toExpr ty
    let i := toExpr i
     
    mkVar Ty Γ ty i

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

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

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

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

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

class TransformReturn (d : Dialect) (φ : outParam Nat) [DialectSignature d] [TransformTy d φ] where
  mkReturn : (Γ : Ctxt d.Ty) → (opStx : AST.Op φ) → ReaderM d (Σ eff ty, Com d Γ eff ty)

def Expr.substitute (σ : Substitution) : Expr Op T → Expr Op T
  | ⟨varName, op, args, regions⟩ =>
      let σ' := σ.removeMappingFor varName
      ⟨varName, op, σ'.apply <$> args, subRegions σ' regions⟩
  
  
  where subRegions (σ' : Substitution) : List (Region Op T) → List (Region Op T)
    | []    => []
    | r::rs => r.substitute σ' :: subRegions σ' rs

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

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

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 mul_add_to_mul_7_after := [llvm|
{
^0(%arg25 : i16):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.shl %arg25, %0 : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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 sltiu_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := sltiu_llvm_i64
  rhs := sltiu_riscv_i64

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

def src_is_notmask_x_xor_neg_x_before := [llvm|
{
^0(%arg69 : i8, %arg70 : i8, %arg71 : i1):
  %0 = llvm.mlir.constant(123 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.mlir.constant(-8 : i8) : i8
  %3 = llvm.xor %arg69, %0 : i8
  %4 = llvm.sub %1, %arg70 : i8
  %5 = llvm.xor %arg70, %4 : i8
  %6 = "llvm.select"(%arg71, %5, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  %7 = llvm.and %3, %6 : i8
  %8 = llvm.icmp "eq" %7, %1 : i8
  "llvm.return"(%8) : (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 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 sub_select_sext_after := [llvm|
{
^0(%arg24 : i1, %arg25 : i64):
  %0 = llvm.mlir.constant(65) : i64
  %1 = "llvm.select"(%arg24, %0, %arg25) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%1) : (i64) -> ()
}
]

def icmp_equality_test_commute_select1_after := [llvm|
{
^0(%arg17 : i64, %arg18 : i64, %arg19 : i64):
  %0 = llvm.icmp "eq" %arg17, %arg18 : i64
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

def n10_wrong_pred2_before := [llvm|
{
^0(%arg22 : i8, %arg23 : i8):
  %0 = llvm.add %arg22, %arg23 : i8
  %1 = llvm.icmp "eq" %0, %arg23 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

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

abbrev Ix := Nat

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

def zext_sext_add_icmp_sgt_minus1_after := [llvm|
{
^0(%arg80 : i1, %arg81 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg81, %0 : i1
  %2 = llvm.or %arg80, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

RV64.binv in RISCV.Instructions

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

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

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

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

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

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

def scalar_i32_lshr_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.lshr %0, %arg5 : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.icmp "eq" %4, %2 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

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

BitVec.signExtend in Init.Data.BitVec.Basic

def select_match : List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) :=
  [⟨[Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64),Ty.llvm (.bitvec 1)],
   [Ty.llvm (.bitvec 64)],(LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND select_riscv_select_llvm_64)⟩,
  ⟨[Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32),Ty.llvm (.bitvec 1)],
   [Ty.llvm (.bitvec 32)],(LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND select_riscv_select_llvm_32)⟩,
   ⟨[Ty.llvm (.bitvec 8), Ty.llvm (.bitvec 8),Ty.llvm (.bitvec 1)],
   [Ty.llvm (.bitvec 8)],(LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND select_riscv_select_llvm_8)⟩]

def shl_lshr_demand1_before := [llvm|
{
^0(%arg20 : i8):
  %0 = llvm.mlir.constant(40 : i8) : i8
  %1 = llvm.mlir.constant(3 : i8) : i8
  %2 = llvm.mlir.constant(-32 : i8) : i8
  %3 = llvm.shl %0, %arg20 : i8
  %4 = llvm.lshr %3, %1 : i8
  %5 = llvm.or %4, %2 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

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

def lshr_and_sub_before := [llvm|
{
^0(%arg53 : i8, %arg54 : 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 %arg53, %0 : i8
  %4 = llvm.lshr %arg54, %1 : i8
  %5 = llvm.and %4, %2 : i8
  %6 = llvm.sub %3, %5 : i8
  %7 = llvm.shl %6, %1 : i8
  "llvm.return"(%7) : (i8) -> ()
}
]

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

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

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

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

Coe.coe in Init.Coe

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

inductive BinaryPredicate
| eq
| neq
| ult
| ule
| slt
| sle
deriving Repr, Lean.ToExpr

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 alive_AndOrXor_2264_tgt :=
[sllvm| {
^bb0(%A : i64, %B : i64):
  %v1 = llvm.mlir.constant -1 : i64
  %v2 = llvm.xor %B, %v1 : i64
  %v3 = llvm.mlir.constant -1 : i64
  %v4 = llvm.xor %A, %v3 : i64
  %v5 = llvm.xor %v4, %B : i64
  %v6 = llvm.or %A, %v2 : i64
  llvm.return %v6 : i64
}]

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

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

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

def Sexpr.ofString (s : String) : Sexpr :=
  Sexpr.atom (format s)

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

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

def icmp_eq_or_z_or_pow2orz_fail_bad_pred2_before := [llvm|
{
^0(%arg6 : i8, %arg7 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.sub %0, %arg7 : i8
  %2 = llvm.and %1, %arg7 : i8
  %3 = llvm.icmp "sle" %arg6, %0 : i8
  %4 = llvm.icmp "sle" %arg6, %2 : i8
  %5 = llvm.or %3, %4 : i1
  "llvm.return"(%5) : (i1) -> ()
}
]

def CNFA.recognizes (m : CNFA n) (L : Language (BitVec n)) :=
  ∃ (M : NFA' n), m.Sim M ∧ M.M.accepts = L

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

def genTable.getGenTable (n : Name) (args : Array Expr) : GenM (Option (Array Bool)) := do
  
  
  if n == ``BitVec then
    if hx : args.size ≠ 1 then
      throwError "BitVec expected 1 argument, got {args.size}"
    else
      
      if let some 1 ← Meta.getNatValue? args[0] then
        return some #[false]
      
      return some #[true]
  
  

  let constInfo ← getConstInfo n
  let ty := constInfo.type
  withTraceNode `WidthGeneralize
    (fun _ => return m!"genTable.getGenTable for {n}") do
      forallTelescope ty fun xs ret => do
        trace[WidthGeneralize] m!"getGenTable for {n} : {xs} → {ret}"
        let mut widths : Std.HashSet Expr := {}
        for x in xs do
          let ty ← inferType x
          
          
          
          
          trace[WidthGeneralize] m!"inspecting arg {x} : {ty}"
          widths ← getBitVecTypeWidths ty widths
        
        
        
        
        widths ← getBitVecTypeWidths ret widths
        trace[WidthGeneralize] m!"found concrete widths: {widths.toArray}"
        let mut out := #[]
        for (x, arg) in xs.zip args do
          
          if let some 1 ← getNatValue? arg then
            trace[WidthGeneralize] m!"arg {arg} is BitVec 1, skipping width generalization"
            out := out.push false
            continue
          let x ← whnf x
          let isWidth := widths.contains x
          trace[WidthGeneralize] m!"inspecting concrete arg {x} isWidth: {isWidth}"
          out := out.push isWidth
        trace[WidthGeneralize] m!"genTable for {n} @ {out}"
        return some out

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

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

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

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

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

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

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

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

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

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 test88_after := [llvm|
{
^0(%arg57 : i16):
  %0 = llvm.mlir.constant(15 : i16) : i16
  %1 = llvm.ashr %arg57, %0 : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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

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

def sgt_x_impliesF_eq_smin_todo_after := [llvm|
{
^0(%arg11 : i8, %arg12 : i8, %arg13 : i8):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.icmp "sle" %arg11, %arg13 : i8
  %2 = llvm.icmp "eq" %arg12, %arg11 : i8
  %3 = "llvm.select"(%1, %2, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

instance : HVector.ToExprPi (Var Γ) where
  toTypeExpr := mkApp2 (mkConst ``Var) (toTypeExpr Ty) (toExpr Γ)

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

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

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

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

def shl_mask_weird_type_before := [llvm|
{
^0(%arg4 : i37):
  %0 = llvm.mlir.constant(255 : i37) : i37
  %1 = llvm.mlir.constant(8 : i37) : i37
  %2 = llvm.and %arg4, %0 : i37
  %3 = llvm.shl %2, %1 : i37
  %4 = llvm.or %2, %3 : i37
  "llvm.return"(%4) : (i37) -> ()
}
]

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

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

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

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

def BitVecs'.transport (f : Fin n → Fin m) (bvs' : BitVecs' m): BitVecs' n :=
  bvs'.map fun bv => bv.transport f

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

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

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

def not_before := [llvm|
{
^0(%arg7 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(-1 : i8) : i8
  %2 = llvm.udiv %arg7, %0 : i8
  %3 = llvm.xor %1, %arg7 : i8
  %4 = llvm.mul %3, %2 : i8
  "llvm.return"(%4) : (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 test0_after := [llvm|
{
^0(%arg3 : i32):
  %0 = llvm.mlir.constant(-1431655766 : i32) : i32
  %1 = llvm.and %arg3, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

def ule_bignum_before := [llvm|
{
^0(%arg145 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.mul %arg145, %0 : i8
  %3 = llvm.icmp "ule" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

def shl_xor_lshr_comm_after := [llvm|
{
^0(%arg97 : i32, %arg98 : i32, %arg99 : i32):
  %0 = llvm.lshr %arg99, %arg98 : i32
  %1 = llvm.xor %0, %arg97 : i32
  "llvm.return"(%1) : (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 slt_smin3_after := [llvm|
{
^0(%arg59 : i32, %arg60 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.add %arg59, %0 : i32
  %2 = llvm.icmp "slt" %arg60, %1 : i32
  "llvm.return"(%2) : (i1) -> ()
}
]

Lean.withImportModules in Lean.Environment

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 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 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 t0_basic_after := [llvm|
{
^0(%arg29 : i8, %arg30 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg30, %0 : i8
  %2 = llvm.icmp "ugt" %arg29, %1 : i8
  "llvm.return"(%2) : (i1) -> ()
}
]

def ugt_zext_before := [llvm|
{
^0(%arg174 : i1, %arg175 : i8):
  %0 = llvm.zext %arg174 : i1 to i8
  %1 = llvm.icmp "ugt" %0, %arg175 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

def test3_before := [llvm|
{
^0(%arg26 : i32, %arg27 : i32):
  %0 = llvm.and %arg26, %arg27 : i32
  %1 = llvm.and %arg27, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def test23_before := [llvm|
{
^0(%arg8 : i44):
  %0 = llvm.mlir.constant(33 : i44) : i44
  %1 = llvm.shl %arg8, %0 : i44
  %2 = llvm.ashr %1, %0 : i44
  %3 = llvm.trunc %2 : i44 to i11
  "llvm.return"(%3) : (i11) -> ()
}
]

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

def or_nosignbit_select_shl_before := [llvm|
{
^0(%arg40 : i32, %arg41 : i1):
  %0 = llvm.mlir.constant(2147418112 : i32) : i32
  %1 = llvm.mlir.constant(8 : i32) : i32
  %2 = llvm.or %arg40, %0 : i32
  %3 = "llvm.select"(%arg41, %2, %arg40) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  %4 = llvm.shl %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

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

def llvm_const_lower_riscv_li13 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM13, rhs:= liRiscv13,
   correct := by admit /- proof elided -/

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

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

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

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

def t0_after := [llvm|
{
^0(%arg30 : i1, %arg31 : i8, %arg32 : i8, %arg33 : i8, %arg34 : i8):
  %0 = llvm.icmp "ne" %arg31, %arg32 : i8
  %1 = llvm.or %0, %arg30 : i1
  %2 = "llvm.select"(%1, %arg34, %arg33) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%2) : (i8) -> ()
}
]

instance : HydrablePackedBitvecToSubstitutionValue GenBVPred GenBVExpr where
  packedBitVecToSubstitutionValue := packedBitVecToSubstitutionValue

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 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 pow2_or_zero_is_negative_commute_before := [llvm|
{
^0(%arg7 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(0 : i8) : i8
  %2 = llvm.mul %0, %arg7 : i8
  %3 = llvm.sub %1, %2 : i8
  %4 = llvm.and %3, %2 : i8
  %5 = llvm.icmp "slt" %4, %1 : i8
  "llvm.return"(%5) : (i1) -> ()
}
]

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

Vector in Init.Data.Vector.Basic

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 mkExprOf (Γ : Ctxt d.Ty) (parsedOp : d.Op)
    (args? : Option (ParsedArgs Γ) := none):
    ReaderM d (Σ eff returnTy, Expr d Γ eff returnTy) := do
  let args ← args?.getDM (op.parseArgs Γ)
  let signature := DialectSignature.signature parsedOp
  let argsVec := args.toHVector
  let eff := signature.effectKind
  let returnTy := signature.returnTypes

  
  if h_noRegions : ¬signature.regSig.isEmpty then
    panic! s!"mkExprOf shouldn't be called with an operation that expects regions!"
  else
    return ⟨eff, returnTy, ⟨
      parsedOp,
      rfl,
      EffectKind.le_refl _,
      ← args.withSignature _,
      have : DialectSignature.regSig parsedOp = [] := by admit /- proof elided -/
    ⟩⟩

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

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

def or_eq_with_one_bit_diff_constants1_before := [llvm|
{
^0(%arg366 : i32):
  %0 = llvm.mlir.constant(50 : i32) : i32
  %1 = llvm.mlir.constant(51 : i32) : i32
  %2 = llvm.icmp "eq" %arg366, %0 : i32
  %3 = llvm.icmp "eq" %arg366, %1 : i32
  %4 = llvm.or %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def icmp_slt_riscv_eq_icmp_slt_llvm_32 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] :=
  {lhs:= icmp_slt_llvm_32, rhs:= icmp_slt_riscv_32}

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

def select_add_after := [llvm|
{
^0(%arg15 : i1, %arg16 : i64, %arg17 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = "llvm.select"(%arg15, %arg17, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  %2 = llvm.add %arg16, %1 : i64
  "llvm.return"(%2) : (i64) -> ()
}
]

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

def EnvFin.ofEnv (env : Env w) (n : Nat) : EnvFin w n :=
  fun i => env.getD i 0#w

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

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

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 positive_biggershl_shlnuw_before := [llvm|
{
^0(%arg54 : i8):
  %0 = llvm.mlir.constant(3 : i8) : i8
  %1 = llvm.mlir.constant(6 : i8) : i8
  %2 = llvm.ashr %arg54, %0 : i8
  %3 = llvm.shl %2, %1 overflow<nuw> : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

def implies (c₁ c₂ : Circuit α) : Circuit α := (~~~ c₁) ||| c₂

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

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

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

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

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 sub_undemanded_low_bits_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(15 : i32) : i32
  %1 = llvm.mlir.constant(1616 : i32) : i32
  %2 = llvm.mlir.constant(4 : i32) : i32
  %3 = llvm.or %arg0, %0 : i32
  %4 = llvm.sub %3, %1 : i32
  %5 = llvm.lshr %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

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

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

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

instance instTransformTy : MLIR.AST.TransformTy DCPlus 0 where
  mkTy := mkTy

def eval (assign : Std.HashMap Nat BVExpr.PackedBitVec) : FpPredicate → Bool
  | bin lhs op rhs =>
    match op with
    | .eq => (lhs.eval assign) = (rhs.eval assign)

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

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

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

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

def orn_and_cmp_2_partial_logical_after := [llvm|
{
^0(%arg6 : i16, %arg7 : i16, %arg8 : i1):
  %0 = llvm.icmp "slt" %arg6, %arg7 : i16
  %1 = llvm.or %arg8, %0 : i1
  "llvm.return"(%1) : (i1) -> ()
}
]

def test_const_shr_exact_and_1_ne_0_after := [llvm|
{
^0(%arg6 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(42 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.shl %0, %arg6 overflow<nuw> : i32
  %4 = llvm.and %3, %1 : i32
  %5 = llvm.icmp "ne" %4, %2 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

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

def test30_before := [llvm|
{
^0(%arg259 : i1):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.zext %arg259 : i1 to i32
  %2 = llvm.and %1, %0 : i32
  "llvm.return"(%2) : (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 test17_before := [llvm|
{
^0(%arg17 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.mlir.constant(2 : i8) : i8
  %2 = llvm.or %arg17, %0 : i8
  %3 = llvm.icmp "eq" %2, %1 : i8
  "llvm.return"(%3) : (i1) -> ()
}
]

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

def shrink_and_before := [llvm|
{
^0(%arg9 : i64):
  %0 = llvm.mlir.constant(42) : i64
  %1 = llvm.and %arg9, %0 : i64
  %2 = llvm.trunc %1 : i64 to i31
  "llvm.return"(%2) : (i31) -> ()
}
]

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

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

def dec_sub_after := [llvm|
{
^0(%arg16 : i8, %arg17 : i8):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.xor %arg17, %0 : i8
  %2 = llvm.add %arg16, %1 : 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
  }]

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

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

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

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

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

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

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

Lean.Import in Lean.Setup
</all_available_defs>

<all_available_lemmas>
Option.map_none in Init.Data.Option.Basic
Option.map_some in Init.Data.Option.Basic
cast_eq_iff_heq in Batteries.Logic
Function.comp_apply in Init.Core
Option.map_eq_map in Init.Data.Option.Lemmas
Option.map_map in Init.Data.Option.Lemmas
heq_eq_eq in Init.SimpLemmas
true_and in Init.SimpLemmas

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 sdiv_x_by_const_cmp_x_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(13#32 == 0 || 32 != 1 && x == intMin 32 && 13#32 == -1) = true → ofBool (x.sdiv 13#32 == x) = ofBool (x == 0#32)

theorem masked_or_allzeroes_proof : masked_or_allzeroes_before ⊑ masked_or_allzeroes_after

theorem test_trunc_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (zeroExtend 32 x).saddOverflow (-1#32) = true ∨ 31#32 ≥ ↑32) →
    truncate 8 ((zeroExtend 32 x + -1#32).sshiftRight' 31#32) ^^^ -1#8 = signExtend 8 (ofBool (x != 0#8))

theorem test_logical_proof : test_logical_before ⊑ test_logical_after

theorem test24_proof : test24_before ⊑ test24_after

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

theorem and_ne_with_one_bit_diff_constants3_logical_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (x != 65#8) = 1#1 → ofBool (x != BitVec.ofInt 8 (-63)) = ofBool (x &&& 127#8 != 65#8)

theorem positive_samevar_shlnuwnsw_lshrexact_proof : positive_samevar_shlnuwnsw_lshrexact_before ⊑ positive_samevar_shlnuwnsw_lshrexact_after

theorem shift_xor_multiuse_cmp_with_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 (-2049)) * x = x_2 * x_1

theorem test92_thm.extracted_1._1 : ∀ (x : BitVec 64), ¬32#96 ≥ ↑96 → 32#64 ≥ ↑64 → False

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

theorem ashrsgt_03_07_exact_proof : ashrsgt_03_07_exact_before ⊑ ashrsgt_03_07_exact_after

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

theorem main5_like_proof : main5_like_before ⊑ main5_like_after

theorem e_2280 :
    3 * (f ^^^  ~~~(d &&&  ~~~e)) + 5 * ( ~~~d &&& (e ||| f)) + 1 * (f ||| (d &&&  ~~~e)) - 6 * (f ^^^ ( ~~~d ||| (e ||| f))) - 2 * (e ^^^ (d ||| (e ||| f))) - 7 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 2 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 3 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) + 1 * (d ||| e) + 1 *  ~~~(d ||| ( ~~~e &&& f)) - 7 * ( ~~~d ||| ( ~~~e &&& f)) - 1 * (e ^^^  ~~~(d ||| f)) + 1 *  ~~~( ~~~d &&& ( ~~~e &&& f)) + 1 * ( ~~~d &&& ( ~~~e ||| f)) + 1 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 1 *  ~~~(e ||| f) + 4 * (f &&& (d |||  ~~~e)) - 6 * ( ~~~f &&&  ~~~(d ^^^ e)) + 1 *  ~~~( ~~~d ||| ( ~~~e &&& f)) + 4 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) - 5 *  ~~~( ~~~d ||| (e ^^^ f)) + 5 * (f ||| (d &&& e)) + 2 * (e ^^^  ~~~(d &&& f)) + 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 7 * (f ^^^ (d &&&  ~~~e)) + 1 * (e ^^^ ( ~~~d ||| (e &&& f))) - 1 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 7 * (f ^^^ (d ||| ( ~~~e ||| f))) + 1 * (e ^^^  ~~~(d &&&  ~~~f)) - 1 * (e &&& (d |||  ~~~f)) - 1 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 2 * (e &&&  ~~~(d ^^^ f)) + 1 * (f &&& (d ^^^ e)) - 5 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * (f ^^^ (d &&& (e ||| f))) - 2 *  ~~~( ~~~d &&& (e ||| f)) + 2 * (d ^^^ ( ~~~e &&& f)) + 5 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) + 7 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 11 * ((d &&& f) ^^^ (d ^^^ (e &&& f))) + 2 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 1 * (f |||  ~~~(d |||  ~~~e)) - 1 * (e ^^^  ~~~(d &&& (e ^^^ f))) - 5 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 2 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 2 *  ~~~(d |||  ~~~f) - 1 * d + 1 * (d ^^^ (e ^^^ f)) + 2 * (e ||| (d &&& f)) - 1 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) - 6 * (e &&&  ~~~(d &&& f)) + 2 * (d ^^^ ( ~~~e ||| f)) + 22 *  ~~~(d ||| (e ||| f)) - 8 *  ~~~(d ||| ( ~~~e ||| f)) - 24 *  ~~~( ~~~d ||| (e ||| f)) - 3 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 27 * ( ~~~d &&& ( ~~~e &&& f)) - 17 * ( ~~~d &&& (e &&& f)) - 2 * (d &&& ( ~~~e &&& f)) - 50 * (d &&& (e &&& f)) =  - 11 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) + 6 * (e ^^^ (d &&&  ~~~f))

theorem scalar_i16_signbit_lshr_and_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  ¬x_1 ≥ ↑16 → True ∧ BitVec.ofInt 16 (-32768) >>> x_1 <<< x_1 ≠ BitVec.ofInt 16 (-32768) ∨ x_1 ≥ ↑16 → False

theorem test_ne_0_and_15_add_3_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (x + 3#8 &&& 15#8 != 0#8) = ofBool (x &&& 15#8 != 13#8)

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

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

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

theorem neg_nsw_slt_0_proof : neg_nsw_slt_0_before ⊑ neg_nsw_slt_0_after

theorem lshrugt_01_04_exact_proof : lshrugt_01_04_exact_before ⊑ lshrugt_01_04_exact_after

theorem test_mul_nsw__all_are_safe_proof : test_mul_nsw__all_are_safe_before ⊑ test_mul_nsw__all_are_safe_after

theorem sub_const_sub_const_thm.extracted_1._1 : ∀ (x : BitVec 32), x - 8#32 - 2#32 = x + BitVec.ofInt 32 (-10)

theorem tryFactorization_add_nuw_mul_nuw_mul_nuw_var_thm (e e_1 e_2 : IntW 32) :
  add (mul e_2 e_1 { «nsw» := false, «nuw» := true }) (mul e_2 e { «nsw» := false, «nuw» := true })
      { «nsw» := false, «nuw» := true } ⊑
    mul e_2 (add e_1 e) { «nsw» := false, «nuw» := true }

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

theorem slt_zero_eq_ne_0_fail2_proof : slt_zero_eq_ne_0_fail2_before ⊑ slt_zero_eq_ne_0_fail2_after

theorem sub_from_constant_of_sub_from_constant_thm (e : IntW 8) : sub (const? 8 11) (sub (const? 8 42) e) ⊑ add e (const? 8 (-31))

theorem test35_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ (0#32 - x &&& 240#32).msb = true) →
    0#64 - zeroExtend 64 x &&& 240#64 = zeroExtend 64 (0#32 - x &&& 240#32)

theorem sub_ashr_or_i64_proof : sub_ashr_or_i64_before ⊑ sub_ashr_or_i64_after

theorem e_1509 :
    4 * (b ^^^  ~~~(a &&& (b ||| c))) + 4 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 2 * ((a &&& b) ^^^ (b |||  ~~~c)) - 2 *  ~~~(a ||| (b ||| c)) + 2 *  ~~~(a ||| ( ~~~b ||| c)) - 6 *  ~~~( ~~~a ||| (b ||| c)) - 8 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 8 * ( ~~~a &&& ( ~~~b &&& c)) - 8 * (a &&& (b &&& c)) = 2 * ( ~~~a &&& (b &&& c))

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

theorem t6_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (0#8).ssubOverflow x = true) → ofBool (0#8 - x <ᵤ x) = ofBool (x <ₛ 0#8)

theorem negate_sdiv_proof : negate_sdiv_before ⊑ negate_sdiv_after

theorem masked_or_allones_proof : masked_or_allones_before ⊑ masked_or_allones_after

theorem test13_thm (e : IntW 32) :
  icmp IntPred.ult (LLVM.udiv (const? 32 4) e) (const? 32 3) ⊑ icmp IntPred.ugt e (const? 32 1)

theorem ult_to_slt_proof : ult_to_slt_before ⊑ ult_to_slt_after

theorem test_logical_or_eq_a_b_proof : test_logical_or_eq_a_b_before ⊑ test_logical_or_eq_a_b_after

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

theorem or_or_and_pat2_proof : or_or_and_pat2_before ⊑ or_or_and_pat2_after

theorem test88_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬18#32 ≥ ↑32 → ¬15#16 ≥ ↑16 → truncate 16 ((signExtend 32 x).sshiftRight' 18#32) = x.sshiftRight' 15#16

theorem e_2022 :
     - 1 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) + 5 * (d &&& f) + 1 * ((e &&& f) ||| (d &&& (e ||| f))) - 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 1 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 7 *  ~~~(d &&& (e &&& f)) + 2 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) + 11 * ((d ^^^ e) ||| (d ^^^ f)) + 2 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) + 1 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 3 *  ~~~(d ^^^ (e &&& f)) - 1 * (f ^^^ ( ~~~d ||| (e &&& f))) + 1 *  ~~~(d &&& ( ~~~e &&& f)) + 2 * (f ^^^ (d ||| ( ~~~e &&& f))) + 4 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 1 * f - 2 *  ~~~( ~~~d ||| (e &&& f)) - 6 * (e ^^^ (d ||| f)) - 7 * ( ~~~f &&& (d ^^^ e)) + 4 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 7 * (e &&&  ~~~f) + 3 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) + 5 *  ~~~( ~~~d &&& (e ||| f)) + 1 * ( ~~~d ||| (e ||| f)) + 11 * (d &&& ( ~~~e ||| f)) + 2 * ( ~~~d &&& (e ||| f)) + 1 * ((d ^^^ e) &&& (d ^^^ f)) - 9 *  ~~~(d ||| (e ||| f)) - 3 *  ~~~(d ||| ( ~~~e ||| f)) - 24 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 9 * ( ~~~d &&& ( ~~~e &&& f)) - 15 * ( ~~~d &&& (e &&& f)) - 29 * (d &&& ( ~~~e &&& f)) - 26 * (d &&& (e &&& f)) = 12 *  ~~~( ~~~d ||| (e ||| f))

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

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

theorem test3_logical_thm (e e_1 : IntW 32) :
  select (icmp IntPred.eq (sub e_1 e { «nsw» := true, «nuw» := false }) (const? 32 0)) (const? 1 1)
      (icmp IntPred.eq (sub e_1 e { «nsw» := true, «nuw» := false }) (const? 32 31)) ⊑
    select (icmp IntPred.eq e_1 e) (const? 1 1)
      (icmp IntPred.eq (sub e_1 e { «nsw» := true, «nuw» := false }) (const? 32 31))

theorem and_sext_sext_thm (e : IntW 8) (e_1 : IntW 4) :
  LLVM.and (sext 16 e_1) (sext 16 e) ⊑ sext 16 (LLVM.and e (sext 8 e_1))

theorem lshrugt_02_01_exact_proof : lshrugt_02_01_exact_before ⊑ lshrugt_02_01_exact_after

theorem bools2_logical_commute0_and1_proof : bools2_logical_commute0_and1_before ⊑ bools2_logical_commute0_and1_after

theorem ne_umin4_proof : ne_umin4_before ⊑ ne_umin4_after

theorem p0_proof : p0_before ⊑ p0_after

theorem ashrsgt_03_11_exact_proof : ashrsgt_03_11_exact_before ⊑ ashrsgt_03_11_exact_after

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

@[simp] theorem Hom.castDomain_apply {h : Δ = Δ'} {f : Γ.Hom Δ} {v : Γ.Var t} :
    f.castCodomain h v = (f v).castCtxt h

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

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 t2_ult_sgt_65536_proof : t2_ult_sgt_65536_before ⊑ t2_ult_sgt_65536_after

theorem and_ugt_to_mask_proof : and_ugt_to_mask_before ⊑ and_ugt_to_mask_after

theorem xor_common_op_commute3_proof : xor_common_op_commute3_before ⊑ xor_common_op_commute3_after

theorem test7_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x <ₛ 1#32) = 1#1 → ofBool (x == 0#32) = 1#1 → ¬0#1 = 1#1 → False

theorem e_2292 :
    2 *  ~~~(d ||| f) - 11 * (e &&& f) + 11 *  ~~~(e &&&  ~~~f) + 7 * (f ^^^ ( ~~~d &&& (e ||| f))) + 4 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 7 * (d ||| ( ~~~e &&& f)) + 1 *  ~~~( ~~~d ||| (e &&& f)) - 2 * (d |||  ~~~e) - 2 * (e ^^^  ~~~(d &&& f)) + 1 *  ~~~(d &&& e) + 2 * ( ~~~(d |||  ~~~e) ||| (d ^^^ (e ^^^ f))) - 6 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 1 * (d &&& e) + 2 * (e &&& (d |||  ~~~f)) + 7 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) + 7 * (f ^^^ (d &&& (e ||| f))) - 3 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 1 * (e ^^^ (d &&& ( ~~~e ||| f))) - 7 * (d ^^^ ( ~~~e &&& f)) - 1 *  ~~~(d ^^^ ( ~~~e ||| f)) - 7 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 5 *  ~~~(d ^^^ ( ~~~e &&& f)) + 2 *  ~~~(d ||| e) + 1 * (f ^^^ (d &&& e)) - 1 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) + 11 * ( ~~~d ||| ( ~~~e ||| f)) + 7 * (e ^^^  ~~~(d |||  ~~~f)) + 2 * ((d &&& f) |||  ~~~(e ||| f)) + 1 * (e &&&  ~~~(d &&&  ~~~f)) + 11 * ( ~~~f |||  ~~~(d ^^^ e)) - 5 *  ~~~(d ||| (e ^^^ f)) - 1 * (d ||| (e &&& f)) + 2 * (e ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 3 * ( ~~~d ||| (e ^^^ f)) + 2 * (e ^^^  ~~~(d ||| (e ^^^ f))) + 2 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 11 * (e ^^^ ( ~~~d ||| (e ||| f))) - 11 * (e ^^^ ( ~~~d &&& (e ^^^ f))) - 2 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) - 5 *  ~~~(e &&& f) + 4 * (d ||| e) - 1 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 3 * ((e &&& f) ||| (d &&& (e ||| f))) + 4 * ( ~~~d &&& (e ^^^ f)) - 11 *  ~~~(d ||| (e &&& f)) - 1 * d - 2 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) + 2 *  ~~~(d &&& f) - 3 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) - 2 * (e |||  ~~~(d ||| f)) + 1 *  ~~~( ~~~d &&& (e ||| f)) + 11 *  ~~~(d &&&  ~~~f) + 2 * (f ^^^ (d ||| (e &&& f))) - 51 *  ~~~(d ||| (e ||| f)) - 43 *  ~~~(d ||| ( ~~~e ||| f)) - 11 *  ~~~( ~~~d ||| (e ||| f)) - 5 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 41 * ( ~~~d &&& ( ~~~e &&& f)) - 32 * ( ~~~d &&& (e &&& f)) - 53 * (d &&& ( ~~~e &&& f)) - 25 * (d &&& (e &&& f)) =  - 7 * (f &&& (d ^^^ e)) + 1 *  ~~~(d &&& (e &&& f))

theorem and_nosignbit_shl_proof : and_nosignbit_shl_before ⊑ and_nosignbit_shl_after

theorem trunc_sel_smaller_zext_thm.extracted_1._2 : ∀ (x : BitVec 64) (x_1 : BitVec 1),
  x_1 = 1#1 → zeroExtend 32 (truncate 16 x) = truncate 32 x &&& 65535#32

theorem sext_zext_apint1_thm.extracted_1._1 : ∀ (x : BitVec 77),
  signExtend 1024 (zeroExtend 533 x) = zeroExtend 1024 x

theorem e_1709 :
     - 2 * (b |||  ~~~(a ^^^ c)) - 7 * (b |||  ~~~(a |||  ~~~c)) - 11 *  ~~~( ~~~a ||| ( ~~~b &&& c)) + 4 * (b ^^^ (a ||| (b &&& c))) + 1 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 1 * ((a &&&  ~~~b) ||| (b ^^^ c)) + 1 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 5 * (c ||| (a &&& b)) + 3 * (a &&& b) + 1 * (c ^^^  ~~~(a &&& ( ~~~b ||| c))) + 1 * ((a ^^^ b) ||| (a ^^^ c)) - 7 * (a |||  ~~~c) + 3 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) + 1 * (a ^^^ ( ~~~b &&& c)) + 11 * (c ^^^ (a &&& b)) + 1 * ( ~~~a ||| (b ||| c)) - 3 * (c ^^^ (a ||| ( ~~~b &&& c))) + 11 * (c ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 2 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) - 2 * (b ^^^  ~~~(a ||| (b &&& c))) + 3 * (b &&& c) - 1 * (b ^^^ ( ~~~a &&& (b ^^^ c))) - 1 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 7 * (b ^^^  ~~~(a &&&  ~~~c)) - 2 *  ~~~(a ||| (b ||| c)) + 9 *  ~~~(a ||| ( ~~~b ||| c)) + 3 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 23 * ( ~~~a &&& ( ~~~b &&& c)) - 25 * (a &&& ( ~~~b &&& c)) + 15 * (a &&& (b &&& c)) = 14 * ( ~~~a &&& (b &&& c)) - 7 * (c &&&  ~~~(a &&&  ~~~b))

theorem mult_same_same'
  (hppot : ppot &&& (ppot - 1) = 0)
  (hqpot : qpot &&& (qpot - 1) = 0)
  (hrpot : rpot &&& (rpot - 1) = 0)
  (hspot : spot &&& (spot - 1) = 0)
  (htpot : tpot &&& (tpot - 1) = 0)
  (hupot : upot &&& (upot - 1) = 0)
  (hpmask : pmask = ppot - 1)
  (hqmask : qmask = qpot - 1)
  (hrmask : rmask = rpot - 1)
  (hsmask : smask = spot - 1)
  (htmask : tmask = tpot - 1)
  (humask : umask = upot - 1)
  (htp : UnaryGt tmask pmask) (ht1 : UnaryGt tmask (1#o)) (hs : UnaryGe smask (unaryAdd pmask qmask)) :
  (bw' rmask 
    (addMax' 
      (bw' smask 
        (mulMax' (bw' pmask a') pmask (bw' qmask b') qmask)) 
      smask 
      (bw' qmask b') 
      qmask)) =
  (bw' rmask 
    (mulMax' 
      (bw' tmask 
        (addMax' (bw' pmask a') pmask (bw' (1#o) (1#o)) (1#o))) 
      tmask 
      (bw' qmask b') 
      qmask))

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

theorem gt_signed_to_small_unsigned_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (17#32 <ᵤ signExtend 32 x) = ofBool (17#8 <ᵤ x)

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

theorem test_zext1_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → 0#32 = zeroExtend 32 0#1

theorem test65_proof : test65_before ⊑ test65_after

theorem e_216 :
     - 7 * (x ||| y) + 1 *  ~~~x + 5 *  ~~~(x ^^^ y) + 5 * (x ^^^ y) - 12 *  ~~~(x ||| y) - 4 * (x &&&  ~~~y) - 3 * (x &&& y) =  - 1 *  ~~~(x &&& y) - 5 * (x |||  ~~~y)

theorem test9_thm (e : IntW 42) : sub e (mul (const? 42 3) e) ⊑ mul e (const? 42 (-2))

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

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

theorem and_not_or_or_not_or_xor_proof : and_not_or_or_not_or_xor_before ⊑ and_not_or_or_not_or_xor_after

theorem eq_basic_proof : eq_basic_before ⊑ eq_basic_after

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

theorem xor_to_xor3_proof : xor_to_xor3_before ⊑ xor_to_xor3_after

theorem neg_sgt_42_thm (e : IntW 32) :
  icmp IntPred.sgt (sub (const? 32 0) e) (const? 32 42) ⊑
    icmp IntPred.slt (add e (const? 32 (-1))) (const? 32 (-43))

theorem or_xor_tree_0001_proof : or_xor_tree_0001_before ⊑ or_xor_tree_0001_after

theorem xor_common_op_commute2_thm (e e_1 : IntW 8) :
  LLVM.or (LLVM.xor e_1 (const? 8 5)) (LLVM.xor (LLVM.xor e_1 (const? 8 5)) e) ⊑
    LLVM.or (LLVM.xor e_1 (const? 8 5)) e

theorem c_0_1_0_proof : c_0_1_0_before ⊑ c_0_1_0_after

theorem icmp_select_var_select_thm.extracted_1._3 : ∀ (x : BitVec 8) (x_1 : BitVec 1),
  x_1 = 1#1 →
    ofBool (x == 0#8) = 1#1 ∧ x_1 = 1#1 → ¬ofBool (x == 0#8) = 1#1 → x_1 ^^^ 1#1 = 1#1 → ofBool (x == x) = 1#1

theorem bools_logical_proof : bools_logical_before ⊑ bools_logical_after

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

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

theorem xor_2_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1) (x_3 : BitVec 8),
  x_2 = 1#1 → x_3 ^^^ (x_1 ^^^ -1#8) ^^^ -1#8 = x_3 ^^^ x_1

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

@[simp]
theorem Eqn.reflect_nil  {w : Nat} (env : Env w) :
    Eqn.reflect [] env = 0

@[simp] theorem borrow_zero (x y : BitStream) : (x.borrow y 0) = (!(x 0) && y 0)

theorem test15b_proof : test15b_before ⊑ test15b_after

theorem e_1431 :
    2 *  ~~~(z ^^^ t) + 4 * z - 3 *  ~~~(z &&& t) + 4 *  ~~~z + 2 * (z ^^^ t) - 6 *  ~~~t + 6 *  ~~~(z ||| t) - 3 *  ~~~(z |||  ~~~t) + 6 * (z &&&  ~~~t) - 3 * (z &&& t) = 3 * (z |||  ~~~t)

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

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

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

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

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

theorem gt_unsigned_to_large_negative_proof : gt_unsigned_to_large_negative_before ⊑ gt_unsigned_to_large_negative_after

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

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

theorem ashr_ugt_4_proof : ashr_ugt_4_before ⊑ ashr_ugt_4_after

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

theorem test8_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬16#32 ≥ ↑32 → 16#32 ≥ ↑32 ∨ True ∧ (x.sshiftRight' 16#32).smulOverflow 32767#32 = true → False

theorem slt_swap_and_max_commute_proof : slt_swap_and_max_commute_before ⊑ slt_swap_and_max_commute_after

@[simp] theorem ofFn_nil : ofFn A [] f = .nil

theorem test_eq_0_and_15_add_1_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (x + 1#8 &&& 15#8 == 0#8) = ofBool (x &&& 15#8 == 15#8)

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

theorem shl_xor_lshr_comm_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_1 <<< x >>> x ≠ x_1 ∨ x ≥ ↑32 ∨ x ≥ ↑32) → ¬x ≥ ↑32 → (x_2 ^^^ x_1 <<< x) >>> x = x_2 >>> x ^^^ x_1

theorem add_mask_sign_i32_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(31#32 ≥ ↑32 ∨ 31#32 ≥ ↑32) →
    ¬ofBool (x <ₛ 0#32) = 1#1 → (x.sshiftRight' 31#32 &&& 8#32) + x.sshiftRight' 31#32 = 0#32

theorem test_shl_nsw__nuw_is_safe_proof : test_shl_nsw__nuw_is_safe_before ⊑ test_shl_nsw__nuw_is_safe_after

theorem and_or3_commuted_thm.extracted_1._8 : ∀ (x x_1 : BitVec 1) (x_2 x_3 : BitVec 32),
  ¬ofBool (x_3 == x_2) &&& x_1 = 1#1 → ¬x_1 = 1#1 → x_1 = 0#1

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

theorem or_sext_to_sel_thm (e : IntW 32) (e_1 : IntW 1) : LLVM.or (sext 32 e_1) e ⊑ select e_1 (const? 32 (-1)) e

theorem trunc_shl_ashr_var_thm.extracted_1._2 : ∀ (x x_1 : BitVec 64),
  ¬(x ≥ ↑64 ∨ 2#64 ≥ ↑64) →
    ¬(x ≥ ↑64 ∨ 2#32 ≥ ↑32) → truncate 32 (x_1.sshiftRight' x <<< 2#64) = truncate 32 (x_1.sshiftRight' x) <<< 2#32

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

theorem e_195 :
     - 1 *  ~~~(x ^^^ y) + 2 * (x ||| y) - 1 *  ~~~(x &&&  ~~~x) + 2 *  ~~~(x &&&  ~~~y) - 13 *  ~~~(x |||  ~~~y) - 13 * (x &&& y) =  - 11 * y + 1 * (x ^^^ y)

@[simp] theorem cons_get_zero {A : α → Type*} {a: α} {as : List α} {e : A a} {vec : HVector A as} :
   (HVector.cons e vec).get (@OfNat.ofNat (Fin (as.length + 1)) 0 Fin.instOfNat) = e

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

theorem shl_sub_no_commute_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(3#8 ≥ ↑8 ∨ 2#8 ≥ ↑8) → ¬(2#8 ≥ ↑8 ∨ 5#8 ≥ ↑8) → (x_1 - x <<< 3#8) <<< 2#8 = x_1 <<< 2#8 - x <<< 5#8

theorem zext_sub_const_thm (e : IntW 1) : sub (const? 64 42) (zext 64 e) ⊑ select e (const? 64 41) (const? 64 42)

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

theorem main6c_proof : main6c_before ⊑ main6c_after

theorem shl_nsw_nuw_add_nuw_thm (e : IntW 32) :
  add (shl (const? 32 1) e { «nsw» := true, «nuw» := true }) (const? 32 (-1)) { «nsw» := false, «nuw» := true } ⊑
    const? 32 (-1)

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

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

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

theorem logical_or_logical_or_icmps_comm1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬x ≥ ↑8 → ofBool (x_1 &&& 1#8 <<< x == 0#8) = 1#1 → True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8 → False

theorem mul_of_bool_commute_proof : mul_of_bool_commute_before ⊑ mul_of_bool_commute_after

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

theorem urem_i1_is_zero_thm (e e_1 : IntW 1) : urem e_1 e ⊑ const? 1 0

theorem ashrsgt_01_11_proof : ashrsgt_01_11_before ⊑ ashrsgt_01_11_after

theorem shift_xor_multiuse_cmp_xor_proof : shift_xor_multiuse_cmp_xor_before ⊑ shift_xor_multiuse_cmp_xor_after

theorem test11_proof : test11_before ⊑ test11_after

theorem no_reassoc_add_none_nuw_proof : no_reassoc_add_none_nuw_before ⊑ no_reassoc_add_none_nuw_after

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

theorem udiv_illegal_type_c_proof : udiv_illegal_type_c_before ⊑ udiv_illegal_type_c_after

theorem sge_or_max_logical_proof : sge_or_max_logical_before ⊑ sge_or_max_logical_after

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

theorem trunc_shl_zext_64_proof : trunc_shl_zext_64_before ⊑ trunc_shl_zext_64_after

theorem fold_select_trunc_nsw_true_thm (e e_1 : IntW 128) :
  select (trunc 1 e_1 { «nsw» := true, «nuw» := false }) e_1 e ⊑
    select (trunc 1 e_1 { «nsw» := true, «nuw» := false }) (const? 128 (-1)) e

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

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

theorem and1_lshr1_is_cmp_eq_0_proof : and1_lshr1_is_cmp_eq_0_before ⊑ and1_lshr1_is_cmp_eq_0_after

theorem ashr_ult_10_proof : ashr_ult_10_before ⊑ ashr_ult_10_after

theorem e_104 :
    5 * y + 2 * (x |||  ~~~y) + 11 *  ~~~x - 13 *  ~~~(x ||| y) - 16 *  ~~~(x |||  ~~~y) - 7 * (x &&& y) = 2 * (x &&&  ~~~y)

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

theorem e_628 :
    5 * (x ^^^ y) + 1 *  ~~~x + 4 *  ~~~(x &&&  ~~~y) - 2 * x + 4 *  ~~~(x &&& y) + 2 *  ~~~(x ^^^ y) + 11 *  ~~~y - 22 *  ~~~(x ||| y) - 14 *  ~~~(x |||  ~~~y) - 18 * (x &&&  ~~~y) = 4 * (x &&& y)

theorem e_1328 :
     - 5 * (z |||  ~~~t) + 11 * t + 2 * (z ^^^ t) - 11 * (z ||| t) + 5 *  ~~~(z &&&  ~~~z) - 2 *  ~~~(z ||| t) - 9 *  ~~~(z |||  ~~~t) + 9 * (z &&&  ~~~t) - 2 * (z &&& t) =  - 2 *  ~~~(z &&&  ~~~t)

theorem differentconsts_thm.extracted_1._6 : ∀ (x : BitVec 32),
  ¬ofBool (x + 16#32 <ᵤ 144#32) = 1#1 →
    ¬ofBool (x <ₛ 128#32) = 1#1 →
      ¬ofBool (127#32 <ₛ x) = 1#1 → ¬ofBool (x <ₛ BitVec.ofInt 32 (-16)) = 1#1 → -1#16 = truncate 16 x

@[simp] theorem Expr.args_toPure     : (e.toPure h).args = e.args

theorem test_invert_demorgan_logical_and_proof : test_invert_demorgan_logical_and_before ⊑ test_invert_demorgan_logical_and_after

@[grind =, simp, aesop 50% unsafe]
lemma newState_eq (m : RawCNFA A) :
    m.newState.1 = m.stateMax

theorem demorgan_and_apint5_proof : demorgan_and_apint5_before ⊑ demorgan_and_apint5_after

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

theorem e_420 :
    3 *  ~~~(x &&&  ~~~x) - 1 *  ~~~y + 1 * (x ||| y) - 6 * x + 7 * (x |||  ~~~y) - 9 *  ~~~(x ||| y) - 4 * (x &&&  ~~~y) - 6 * (x &&& y) = 5 *  ~~~(x |||  ~~~y) - 1 * y

theorem lshrugt_03_06_proof : lshrugt_03_06_before ⊑ lshrugt_03_06_after

theorem zero_mul (a : ZMod q) : 0 * a = 0

theorem e_1971 :
    11 * (b ^^^ ( ~~~a ||| (b ||| c))) + 4 * (c ^^^ ( ~~~a ||| (b &&& c))) - 3 * (c |||  ~~~(a ^^^ b)) + 3 *  ~~~(b ||| c) + 5 * (b |||  ~~~(a ||| c)) - 1 * ((b &&& c) ||| (a &&& (b ||| c))) + 4 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) + 3 *  ~~~(b ^^^ c) + 1 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 4 * (b ^^^ (a |||  ~~~c)) - 5 * ( ~~~(a |||  ~~~b) |||  ~~~(b ^^^ c)) - 6 * (c &&& (a |||  ~~~b)) + 11 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) + 1 *  ~~~(a &&& ( ~~~b ||| c)) - 2 * (c ||| (a &&&  ~~~b)) - 7 * ( ~~~b &&&  ~~~(a ^^^ c)) - 1 * ( ~~~a &&& (b ^^^ c)) + 4 * ( ~~~(a &&&  ~~~b) &&& (a ^^^ (b ^^^ c))) - 2 * (c ^^^ (a ||| ( ~~~b ||| c))) - 2 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) + 2 * (b ^^^ (a ||| (b &&& c))) + 2 * (b &&&  ~~~(a &&& c)) + 11 * (c |||  ~~~(a ||| b)) - 1 * (b ^^^  ~~~(a |||  ~~~c)) + 2 * (c ^^^  ~~~(a |||  ~~~b)) + 5 *  ~~~(a &&& (b ||| c)) + 1 * a + 2 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 1 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) + 2 *  ~~~(a &&& (b ^^^ c)) - 1 * (a &&& (b ||| c)) + 1 * ( ~~~a &&& ( ~~~b ||| c)) + 2 * ( ~~~(a ^^^ b) &&& (a ^^^ c)) - 5 *  ~~~(a ^^^ (b ||| c)) + 3 * (a ||| c) + 1 *  ~~~(a &&&  ~~~c) - 1 * (b ^^^ ( ~~~a ||| (b &&& c))) - 6 * (a &&& c) - 5 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) + 7 * ((a ||| b) &&& (a ^^^ (b ^^^ c))) - 2 *  ~~~(a ^^^ (b &&& c)) - 3 * ( ~~~a ||| (b &&& c)) + 7 * (b ^^^  ~~~(a &&& (b ||| c))) - 11 * ((a &&&  ~~~b) ||| (b ^^^ c)) + 1 * ((b &&& c) ||| ( ~~~a &&& (b ||| c))) + 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * ( ~~~(a |||  ~~~b) ||| (a ^^^ (b ^^^ c))) - 1 * ( ~~~a &&& (b ||| c)) - 34 *  ~~~(a ||| (b ||| c)) - 10 *  ~~~(a ||| ( ~~~b ||| c)) - 27 *  ~~~( ~~~a ||| (b ||| c)) + 1 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 21 * ( ~~~a &&& ( ~~~b &&& c)) - 21 * ( ~~~a &&& (b &&& c)) + 4 * (a &&& ( ~~~b &&& c)) - 14 * (a &&& (b &&& c)) = 11 *  ~~~(a ||| (b &&& c)) + 2 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c)))

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

theorem add_const_const_sub_nsw_thm (e : IntW 8) :
  sub (const? 8 (-127)) (add e (const? 8 1)) { «nsw» := true, «nuw» := false } ⊑ sub (const? 8 (-128)) e

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

theorem test_sub_nuw__nsw_is_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x ||| BitVec.ofInt 32 (-2147483648) == BitVec.ofInt 32 (-2147483647)) = 1#1 →
    ¬(True ∧ (BitVec.ofInt 32 (-2147483648)).ssubOverflow (x ||| BitVec.ofInt 32 (-2147483648)) = true) →
      -1#32 = BitVec.ofInt 32 (-2147483648) - (x ||| BitVec.ofInt 32 (-2147483648))

theorem foo_proof : foo_before ⊑ foo_after

theorem not_proof : not_before ⊑ not_after

theorem decideIfZeros_correct {arity : Type _} [DecidableEq arity]
    (p : FSM arity) : decideIfZeros p = true ↔ ∀ n x, p.simplify.eval x n = false

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

theorem ult_x_impliesT_eq_umax_todo_proof : ult_x_impliesT_eq_umax_todo_before ⊑ ult_x_impliesT_eq_umax_todo_after

theorem e_867 :
    7 * (z |||  ~~~t) - 6 * (z ||| t) - 1 * z - 6 *  ~~~(z &&&  ~~~z) - 1 *  ~~~(z ||| t) + 6 * (z &&&  ~~~t) =  - 6 * (z &&& t) - 12 *  ~~~(z |||  ~~~t)

theorem samesign_inverted_commute3_thm (e e_1 : IntW 32) :
  LLVM.and (icmp IntPred.slt (LLVM.or e_1 e) (const? 32 0))
      (icmp IntPred.sgt (LLVM.and e e_1) (const? 32 (-1))) ⊑
    icmp IntPred.slt (LLVM.xor e_1 e) (const? 32 0)

theorem not_mul_of_bool_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 32),
  True ∧ (x_1 &&& 3#32).smulOverflow (zeroExtend 32 x) = true ∨
      True ∧ (x_1 &&& 3#32).umulOverflow (zeroExtend 32 x) = true →
    False

theorem lshr_x_by_const_cmp_x_thm (e : IntW 32) :
  icmp IntPred.eq (lshr e (const? 32 1)) e ⊑ icmp IntPred.eq e (const? 32 0)

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

theorem no_masks_with_logical_or2_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (select (icmp IntPred.ne e_2 (const? 32 (-1))) (const? 1 1) (icmp IntPred.ne e_1 (const? 32 63)))
      (icmp IntPred.ne e (const? 32 (-1))) ⊑
    select (icmp IntPred.ne (LLVM.and e_2 e) (const? 32 (-1))) (const? 1 1)
      (icmp IntPred.ne e_1 (const? 32 63))

theorem fold_xor_zext_sandwich_thm.extracted_1._1 : ∀ (x : BitVec 1),
  zeroExtend 64 (zeroExtend 32 x ^^^ 1#32) = zeroExtend 64 (x ^^^ 1#1)

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

theorem e_1044 :
     - 1 * (z ^^^ t) + 1 * t + 7 * (z ||| t) - 2 *  ~~~z + 7 *  ~~~(z &&&  ~~~t) - 12 *  ~~~(z |||  ~~~t) - 15 * (z &&& t) = 6 * (z &&&  ~~~t) + 5 *  ~~~(z ||| t)

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

theorem e_331 :
     - 6 *  ~~~x + 2 * (x |||  ~~~y) - 3 * x + 2 * (x ||| y) - 10 *  ~~~(x ||| y) - 10 *  ~~~(x |||  ~~~y) - 4 * (x &&&  ~~~y) - 15 * (x &&& y) =  - 3 *  ~~~(x &&&  ~~~x) - 11 *  ~~~(x &&&  ~~~y)

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

theorem test1_trunc_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(24#32 ≥ ↑32 ∨ 8#32 ≥ ↑32) →
    24#32 ≥ ↑32 ∨
        8#32 ≥ ↑32 ∨
          True ∧ (x >>> 24#32 &&& (x >>> 8#32 &&& 65280#32) != 0) = true ∨
            True ∧
              zeroExtend 32 (truncate 16 (x >>> 24#32 ||| x >>> 8#32 &&& 65280#32)) ≠
                x >>> 24#32 ||

theorem e_2154 :
    1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 5 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 1 * (f &&&  ~~~(d ^^^ e)) - 2 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 7 *  ~~~(d &&& f) + 1 * (e &&& f) + 2 *  ~~~(e ^^^ f) - 1 *  ~~~( ~~~d ||| (e &&& f)) + 5 * (e ^^^ ( ~~~d &&& (e ||| f))) + 5 * ( ~~~d ||| ( ~~~e ||| f)) + 2 * ( ~~~d &&& ( ~~~e ||| f)) - 1 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) + 11 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) + 7 * (f ^^^ ( ~~~d &&& (e ||| f))) - 11 * (f ^^^ (d &&& ( ~~~e ||| f))) + 2 * ( ~~~f &&& (d ^^^ e)) - 3 * (f &&& (d ^^^ e)) + 11 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 3 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 5 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 11 * (d &&& ( ~~~e ||| f)) - 1 * (e |||  ~~~f) + 2 * (d ^^^ (e ^^^ f)) + 1 * (f ^^^ ( ~~~d ||| (e ||| f))) - 5 *  ~~~(d ||| (e ^^^ f)) + 7 * (d ||| (e ||| f)) + 2 *  ~~~(d &&& e) + 1 *  ~~~(e &&& f) - 5 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) - 1 * (e ^^^ ( ~~~d ||| (e &&& f))) - 1 * (f ^^^  ~~~(d &&& (e &&& f))) - 6 *  ~~~( ~~~d &&& (e &&& f)) + 1 * d - 5 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) + 3 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 11 * (f ^^^  ~~~(d &&& (e ||| f))) + 5 *  ~~~e + 11 * (f &&& (d ||| e)) + 3 * (f ^^^ (d ||| (e &&& f))) - 2 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 16 *  ~~~(d ||| (e ||| f)) - 41 *  ~~~(d ||| ( ~~~e ||| f)) - 12 *  ~~~( ~~~d ||| (e ||| f)) + 11 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 16 * ( ~~~d &&& ( ~~~e &&& f)) - 32 * ( ~~~d &&& (e &&& f)) - 18 * (d &&& ( ~~~e &&& f)) - 38 * (d &&& (e &&& f)) = 2 * ((d &&& e) ||| (e ^^^ f)) + 11 *  ~~~( ~~~d &&& (e ||| f))

theorem ne_basic_equal_5_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.ne e_1 (const? 8 5)) (icmp IntPred.ule (add e_1 (const? 8 (-5))) e) ⊑
    icmp IntPred.ult (add e_1 (const? 8 (-6))) e

theorem alive_Select_1105 : alive_Select_1105_src ⊑ alive_Select_1105_tgt

theorem ugt_swap_or_not_min_commute_logical_thm (e e_1 : IntW 823) :
  select (icmp IntPred.ne e_1 (const? 823 0)) (const? 1 1) (icmp IntPred.ult e e_1) ⊑
    icmp IntPred.ne e_1 (const? 823 0)

theorem or_and3_commuted_proof : or_and3_commuted_before ⊑ or_and3_commuted_after

theorem add_select_not_sext_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 1#64 + signExtend 64 (x ^^^ 1#1) = 0#64

theorem select_bittest_to_add_thm.extracted_1._4 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 1#32 == 0#32) = 1#1 →
    ¬(True ∧ (x &&& 1#32).saddOverflow 3#32 = true ∨ True ∧ (x &&& 1#32).uaddOverflow 3#32 = true) →
      4#32 = (x &&& 1#32) + 3#32

theorem R.fromPoly_representatitive'_toFun (a : R q n) :
    (R.fromPoly (q := q) (n := n)).toFun (R.representative' q n a) = ↑a

theorem positive_biggerlshr_shlnsw_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(6#8 ≥ ↑8 ∨ True ∧ (x >>> 6#8 <<< 3#8).sshiftRight' 3#8 ≠ x >>> 6#8 ∨ 3#8 ≥ ↑8) →
    ¬3#8 ≥ ↑8 → x >>> 6#8 <<< 3#8 = x >>> 3#8 &&& 24#8

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

theorem masked_icmps_mask_notallzeros_bmask_mixed_swapped_7_proof : masked_icmps_mask_notallzeros_bmask_mixed_swapped_7_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_swapped_7_after

theorem n2_badmask_proof : n2_badmask_before ⊑ n2_badmask_after

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

theorem ashr_bitwidth_mask_thm (e e_1 : IntW 8) :
  LLVM.and (ashr e_1 (const? 8 7)) e ⊑ select (icmp IntPred.slt e_1 (const? 8 0)) e (const? 8 0)

theorem neg_nsw_sgt_1_proof : neg_nsw_sgt_1_before ⊑ neg_nsw_sgt_1_after

theorem prove_exact_with_high_mask_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(BitVec.ofInt 8 (-4) == 0 || 8 != 1 && x &&& BitVec.ofInt 8 (-32) == intMin 8 && BitVec.ofInt 8 (-4) == -1) = true →
    ¬(2#8 ≥ ↑8 ∨ True ∧ (0#8).ssubOverflow (x.sshiftRight' 2#8 &&& BitVec.ofInt 8 (-8)) = true) →
      (x &&& BitVec.ofInt 8 (-32)).sdiv (BitVec.ofInt 8 (-4)) = 0#8 - (x.sshiftRight' 2#8 &&& BitVec.ofInt 8 (-8))

theorem masked_and_notA_proof : masked_and_notA_before ⊑ masked_and_notA_after

theorem test1_thm.extracted_1._1 : ∀ (x : BitVec 23), x ||

theorem test32_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬2#32 ≥ ↑32 → (x &&& 16#32) >>> 2#32 &&& 1#32 = 0#32

theorem e_1141 :
    4 * t - 1 * z + 5 *  ~~~(z &&&  ~~~z) + 4 * (z |||  ~~~t) + 7 *  ~~~(z &&& t) - 16 *  ~~~(z ||| t) - 16 * (z &&&  ~~~t) - 12 * (z &&& t) =  - 1 * (z ^^^ t) + 17 *  ~~~(z |||  ~~~t)

theorem or_nosignbit_lshr_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬8#32 ≥ ↑32 → (x ||| 2147418112#32) >>> 8#32 = x >>> 8#32 ||

theorem sext_zext_ult_known_nonneg_proof : sext_zext_ult_known_nonneg_before ⊑ sext_zext_ult_known_nonneg_after

theorem Expr.WellTyped.exists_iff {e : UnTyped.Expr Op VarName} {Γ : Context Ty} :
    (∃ ty, Expr.WellTyped Γ e ty) ↔ Expr.WellTyped Γ e (signature e.op).returnType

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

@[simp] theorem toHom_zero {Γ : Ctxt Ty} {h : Valid Γ Γ 0} :
    toHom ⟨0, h⟩ = Hom.id

theorem test10_thm (e : IntW 32) :
  icmp IntPred.ugt (LLVM.udiv (const? 32 4) e) (const? 32 1) ⊑ icmp IntPred.ult e (const? 32 3)

theorem test1_proof : test1_before ⊑ test1_after

theorem positive_sameconst_shlnuw_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(3#8 ≥ ↑8 ∨ True ∧ x >>> 3#8 <<< 3#8 >>> 3#8 ≠ x >>> 3#8 ∨ 3#8 ≥ ↑8) →
    x >>> 3#8 <<< 3#8 = x &&& BitVec.ofInt 8 (-8)

theorem and_lshr_and_proof : and_lshr_and_before ⊑ and_lshr_and_after

theorem test23_thm.extracted_1._1 : ∀ (x : BitVec 32),
  zeroExtend 32 (ofBool (x &&& 1#32 == 0#32)) = x &&& 1#32 ^^^ 1#32

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

theorem shiftl1 {v : Nat} (x : BitVec v) :
    x <<< 5 = x <<< 3 <<< 2

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

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

theorem smear_sign_and_widen_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬24#32 ≥ ↑32 → ¬7#8 ≥ ↑8 → signExtend 32 x >>> 24#32 = zeroExtend 32 (x.sshiftRight' 7#8)

theorem ashrsgt_03_11_exact_proof : ashrsgt_03_11_exact_before ⊑ ashrsgt_03_11_exact_after

theorem icmp_shl_eq_1_thm (e : IntW 8) :
  icmp IntPred.eq (shl e (const? 8 1)) e ⊑ icmp IntPred.eq e (const? 8 0)

theorem e_1803 :
    3 * (b &&& (a |||  ~~~c)) + 7 * (b &&&  ~~~(a &&& c)) + 1 * (a ||| (b ^^^ c)) - 1 * (a &&& ( ~~~b ||| c)) - 1 * (b |||  ~~~(a |||  ~~~c)) + 11 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) - 7 * (c ^^^ (a &&& b)) - 3 * (c ^^^ ( ~~~a &&& (b ||| c))) - 7 *  ~~~(b ||| c) - 7 * (b ^^^  ~~~(a ||| c)) + 7 * ((a &&& b) |||  ~~~(b ||| c)) + 1 * (b &&& (a ^^^ c)) - 7 *  ~~~( ~~~a &&& (b &&& c)) + 1 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) - 6 * (c ^^^ (a &&& ( ~~~b ||| c))) + 4 *  ~~~(a ||| (b &&& c)) - 11 * (b ^^^  ~~~( ~~~a &&& ( ~~~b &&& c))) - 3 *  ~~~( ~~~a &&& ( ~~~b &&& c)) - 11 * (a &&& b) + 7 * (c ^^^ (a ||| (b ||| c))) - 2 * ( ~~~(a ^^^ b) &&&  ~~~(a ^^^ c)) - 11 * (c ||| (a ^^^ b)) + 4 * ( ~~~a ||| (b ^^^ c)) - 1 * ( ~~~b &&& (a ^^^ c)) - 1 * (a ||| c) + 1 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 2 * (c ^^^ (a |||  ~~~b)) + 7 *  ~~~(a ||| b) + 4 * (a ^^^ ( ~~~b ||| c)) + 4 * (a ||| (b &&& c)) - 1 * (b ^^^ (a ||| (b &&& c))) - 1 * (c &&&  ~~~(a &&& b)) - 4 *  ~~~(a ||| (b ||| c)) - 12 *  ~~~(a ||| ( ~~~b ||| c)) + 26 *  ~~~( ~~~a ||| (b ||| c)) - 16 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 3 * ( ~~~a &&& ( ~~~b &&& c)) + 12 * ( ~~~a &&& (b &&& c)) + 34 * (a &&& ( ~~~b &&& c)) + 30 * (a &&& (b &&& c)) =  - 1 * (b ||| c)

theorem ashr_and_thm.extracted_1._1 : ∀ (x : BitVec 8), ¬(x ≥ ↑8 ∨ x + 1#8 ≥ ↑8) → x ≥ ↑8 → False

theorem and_xor_commute2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(x_1 = 0 ∨ x = 0 ∨ x = 0) → x = 0 ∨ x_1 = 0 → False

theorem icmp_mul_nsw_slt_thm (e e_1 : IntW 8) :
  icmp IntPred.slt (mul e_1 (const? 8 7) { «nsw» := true, «nuw» := false })
      (mul e (const? 8 7) { «nsw» := true, «nuw» := false }) ⊑
    icmp IntPred.slt e_1 e

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

theorem test9_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.ne (LLVM.and e (const? 32 1073741824)) (const? 32 0))
      (icmp IntPred.sgt e (const? 32 (-1))) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 (-1073741824))) (const? 32 1073741824)

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

theorem e_443 :
    7 * y - 11 * (x |||  ~~~y) + 2 *  ~~~(x ^^^ y) - 7 *  ~~~y + 2 * (x ||| y) + 11 *  ~~~x + 5 *  ~~~(x ||| y) - 20 *  ~~~(x |||  ~~~y) =  - 16 * (x &&&  ~~~y)

theorem or_xor_common_op_commute7_proof : or_xor_common_op_commute7_before ⊑ or_xor_common_op_commute7_after

theorem foo_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ (x &&& 223#32 ^^^ 29#32).uaddOverflow (BitVec.ofInt 32 (-784568073)) = true ∨
        True ∧
            (((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                      ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                    1#32).sshiftRight'
                1#32 ≠
              (x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^ ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32) ∨
          True ∧
              ((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                      ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                    1#32 >>>
                  1#32 ≠
                (x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^ ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32) ∨
            1#32 ≥ ↑32 ∨
              True ∧
                ((x &&& 223#32 ^^^ 29#32) + BitVec.ofInt 32 (-784568073) -
                        ((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                            ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                          1#32).saddOverflow
                    1533579450#32 =
                  true) →
    ¬(True ∧ (x &&& 223#32 ^^^ 29#32).saddOverflow 1362915575#32 = true ∨
          True ∧ (x &&& 223#32 ^^^ 29#32).uaddOverflow 1362915575#32 = true ∨
            True ∧ ((x &&& 223#32 ^^^ 29#32) <<< 1#32).sshiftRight' 1#32 ≠ x &&& 223#32 ^^^ 29#32 ∨
              True ∧ (x &&& 223#32 ^^^ 29#32) <<< 1#32 >>> 1#32 ≠ x &&& 223#32 ^^^ 29#32 ∨
                1#32 ≥ ↑32 ∨
                  True ∧
                      ((x &&& 223#32 ^^^ 29#32) + 1362915575#32).ssubOverflow
                          ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32) =
                        true ∨
                    True ∧
                        ((x &&& 223#32 ^^^ 29#32) + 1362915575#32).usubOverflow
                            ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32) =
                          true ∨
                      True ∧
                        ((x &&& 223#32 ^^^ 29#32) + 1362915575#32 -
                                ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32)).uaddOverflow
                            1533579450#32 =
                          true) →
      ((x &&& 223#32 ^^^ 29#32) + BitVec.ofInt 32 (-784568073) -
                ((x &&& 223#32 ^^^ 29#32 ||| 1874836915#32) ^^^
                    ((x &&& 223#32 ^^^ 29#32) &&& 221#32 ^^^ 1874836915#32)) <<<
                  1#32 +
              1533579450#32 |||
            BitVec.ofInt 32 (-2147483648)) ^^^
          749011377#32 =
        (x &&& 223#32 ^^^ 29#32) + 1362915575#32 - ((x &&& 223#32 ^^^ 29#32) <<< 1#32 &&& 290#32) + 1533579450#32 ^^^
          749011377#32

theorem lshrugt_02_07_exact_proof : lshrugt_02_07_exact_before ⊑ lshrugt_02_07_exact_after

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

theorem ashrslt_03_11_thm (e : IntW 4) : icmp IntPred.slt (ashr e (const? 4 3)) (const? 4 (-5)) ⊑ const? 1 0

theorem sdiv_mul_shl_nsw_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 5),
  ¬(True ∧ x_2.smulOverflow x_1 = true ∨
        True ∧ (x_2 <<< x).sshiftRight' x ≠ x_2 ∨
          x ≥ ↑5 ∨ (x_2 <<< x == 0 || 5 != 1 && x_2 * x_1 == intMin 5 && x_2 <<< x == -1) = true) →
    ¬(True ∧ 1#5 <<< x >>> x ≠ 1#5 ∨ x ≥ ↑5 ∨ (1#5 <<< x == 0 || 5 != 1 && x_1 == intMin 5 && 1#5 <<< x == -1) = true) →
      (x_2 * x_1).sdiv (x_2 <<< x) = x_1.sdiv (1#5 <<< x)

theorem test5_proof : test5_before ⊑ test5_after

theorem invert_both_cmp_operands_sub_proof : invert_both_cmp_operands_sub_before ⊑ invert_both_cmp_operands_sub_after

theorem sdiv_i1_is_op0_thm (e e_1 : IntW 1) : LLVM.sdiv e_1 e ⊑ e_1

theorem test_proof : test_before ⊑ test_after

theorem test3_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬8#32 = 0 → x % 8#32 = x &&& 7#32

theorem xor_sge_thm (e e_1 : IntW 8) :
  icmp IntPred.sge (mul e_1 e_1) (LLVM.xor (LLVM.or e (const? 8 (-128))) (mul e_1 e_1)) ⊑
    icmp IntPred.slt (LLVM.xor (LLVM.or e (const? 8 (-128))) (mul e_1 e_1)) (mul e_1 e_1)

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

theorem nonexact_ashr_eq_noexactlog_proof : nonexact_ashr_eq_noexactlog_before ⊑ nonexact_ashr_eq_noexactlog_after

theorem ashr_icmp2_proof : ashr_icmp2_before ⊑ ashr_icmp2_after

theorem scalar_i16_signbit_lshr_and_eq_thm (e e_1 : IntW 16) :
  icmp IntPred.eq (LLVM.and (lshr (const? 16 (-32768)) e_1) e) (const? 16 0) ⊑
    icmp IntPred.eq (LLVM.and (lshr (const? 16 (-32768)) e_1 { «exact» := true }) e) (const? 16 0)

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

theorem both_proof : both_before ⊑ both_after

theorem or_xor_tree_1001_proof : or_xor_tree_1001_before ⊑ or_xor_tree_1001_after

theorem fold_add_udiv_urem_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(10#32 = 0 ∨ 4#32 ≥ ↑32 ∨ 10#32 = 0) →
    ¬(10#32 = 0 ∨ True ∧ (x / 10#32).umulOverflow 6#32 = true) →
      (x / 10#32) <<< 4#32 + x % 10#32 = x / 10#32 * 6#32 + x

theorem neg_sgt_42_proof : neg_sgt_42_before ⊑ neg_sgt_42_after

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

theorem icmp_equality_test_commute_select1_thm (e e_1 e_2 : IntW 64) :
  select (icmp IntPred.eq e_2 e_1) (icmp IntPred.eq e e_1)
      (select (icmp IntPred.eq e e_1) (const? 1 0) (icmp IntPred.eq e_2 e)) ⊑
    icmp IntPred.eq e_2 e

@[simp]
theorem neg_accepts (M : NFA α σ) :
    M.neg.accepts = M.acceptsᶜ

theorem p0_proof : p0_before ⊑ p0_after

theorem test3_apint_proof : test3_apint_before ⊑ test3_apint_after

theorem sge_and_max_commute_logical_proof : sge_and_max_commute_logical_before ⊑ sge_and_max_commute_logical_after

theorem test5_proof : test5_before ⊑ test5_after

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

theorem udiv_common_dividend_defined_cond_proof : udiv_common_dividend_defined_cond_before ⊑ udiv_common_dividend_defined_cond_after

theorem test4_thm (e : IntW 1) (e_1 : IntW 32) :
  urem e_1 (select e (const? 32 1) (const? 32 8)) ⊑ LLVM.and e_1 (select e (const? 32 0) (const? 32 7))

theorem demorgan_nor_use2ac_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ¬(((x_1 ^^^ -1#8 ||| x) * 23#8 == 0 ||
            8 != 1 && (x_1 ^^^ -1#8 ||| x) ^^^ -1#8 == intMin 8 && (x_1 ^^^ -1#8 ||| x) * 23#8 == -1) =
          true ∨
        ((x_1 ^^^ -1#8) * 17#8 == 0 ||
            8 != 1 && ((x_1 ^^^ -1#8 ||| x) ^^^ -1#8).sdiv ((x_1 ^^^ -1#8 ||| x) * 23#8) == intMin 8 &&
              (x_1 ^^^ -1#8) * 17#8 == -1) =
          true) →
    ((x ||| x_1 ^^^ -1#8) * 23#8 == 0 ||
            8 != 1 && (x ||| x_1 ^^^ -1#8) ^^^ -1#8 == intMin 8 && (x ||| x_1 ^^^ -1#8) * 23#8 == -1) =
          true ∨
        ((x_1 ^^^ -1#8) * 17#8 == 0 ||
            8 != 1 && ((x ||| x_1 ^^^ -1#8) ^^^ -1#8).sdiv ((x ||| x_1 ^^^ -1#8) * 23#8) == intMin 8 &&
              (x_1 ^^^ -1#8) * 17#8 == -1) =
          true →
      False

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

theorem or_not_and_proof : or_not_and_before ⊑ or_not_and_after

theorem test9_thm.extracted_1._1 : ∀ (x : BitVec 32), truncate 8 (x &&& 42#32) = truncate 8 x &&& 42#8

theorem ashr_xor_proof : ashr_xor_before ⊑ ashr_xor_after

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

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

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

theorem lshrult_03_03_proof : lshrult_03_03_before ⊑ lshrult_03_03_after

theorem udiv_exact_ne_0_proof : udiv_exact_ne_0_before ⊑ udiv_exact_ne_0_after

theorem e_1829 :
    3 * (b &&& (a ||| c)) + 11 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) - 2 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) - 7 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c))) + 1 * (b |||  ~~~c) - 1 * a + 1 * ((a &&& b) ||| (b ^^^ c)) - 3 * ( ~~~b &&&  ~~~(a ^^^ c)) + 11 * ((a &&& b) |||  ~~~(b |||  ~~~c)) - 7 * ((b &&& c) ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 2 * ( ~~~c |||  ~~~(a ^^^ b)) + 1 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) - 2 * (c ^^^ (a ||| (b &&& c))) + 5 * ( ~~~a ||| ( ~~~b &&& c)) - 2 * (b ^^^  ~~~(a &&& (b ||| c))) + 4 * (a ^^^ ( ~~~b &&& c)) + 7 * ( ~~~(a &&& b) &&&  ~~~(a ^^^ (b ^^^ c))) + 1 * ((a &&& b) |||  ~~~(b ^^^ c)) - 2 *  ~~~a - 1 * (a ||| c) + 7 * ( ~~~c &&& (a ^^^ b)) - 1 *  ~~~(a &&& ( ~~~b ||| c)) - 1 * (c &&&  ~~~(a &&& b)) + 2 *  ~~~(a &&&  ~~~a) - 6 * ( ~~~c &&&  ~~~(a ^^^ b)) + 3 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 1 * (a ^^^ (b ||| c)) - 6 * ((b &&& c) ||| (a &&& (b ||| c))) + 11 * (b ^^^  ~~~( ~~~a ||| (b &&& c))) + 2 * ( ~~~b |||  ~~~(a ^^^ c)) + 7 * ((a &&& c) ^^^ (a ^^^ ( ~~~b &&& c))) + 11 * (b ^^^ (a &&& (b ^^^ c))) + 4 * b + 7 * (a ^^^ c) - 1 * (c &&& (a |||  ~~~b)) - 1 *  ~~~(a ||| (b ||| c)) - 44 *  ~~~(a ||| ( ~~~b ||| c)) - 49 *  ~~~( ~~~a ||| (b ||| c)) - 35 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 33 * ( ~~~a &&& ( ~~~b &&& c)) - 45 * ( ~~~a &&& (b &&& c)) - 40 * (a &&& ( ~~~b &&& c)) - 44 * (a &&& (b &&& c)) =  - 7 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c)))

theorem test14_proof : test14_before ⊑ test14_after

theorem e_1178 :
     - 5 * (z ||| t) - 6 * z + 1 * (z |||  ~~~t) - 1 *  ~~~(z &&& t) + 8 *  ~~~(z ||| t) + 12 *  ~~~(z |||  ~~~t) + 13 * (z &&&  ~~~t) + 10 * (z &&& t) = 6 *  ~~~z + 2 *  ~~~t

theorem test7_proof : test7_before ⊑ test7_after

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

theorem ashr_lshr_no_ashr_thm (e e_1 : IntW 32) :
  select (icmp IntPred.sge e_1 (const? 32 0)) (lshr e_1 e) (LLVM.xor e_1 e) ⊑
    select (icmp IntPred.slt e_1 (const? 32 0)) (LLVM.xor e_1 e) (lshr e_1 e)

theorem ashrslt_03_13_proof : ashrslt_03_13_before ⊑ ashrslt_03_13_after

theorem or_not_and_commute3_proof : or_not_and_commute3_before ⊑ or_not_and_commute3_after

theorem test30_thm (e : IntW 1) : LLVM.and (zext 32 e) (const? 32 1) ⊑ zext 32 e

theorem trunc_shl_32_i32_i64_proof : trunc_shl_32_i32_i64_before ⊑ trunc_shl_32_i32_i64_after

theorem ashr_exact_add_negative_shift_negative_proof : ashr_exact_add_negative_shift_negative_before ⊑ ashr_exact_add_negative_shift_negative_after

theorem ofBitVec_add_congr (h1 : ofBitVecSext x ≈ʷ a) (h2 : ofBitVecSext y ≈ʷ b) : ofBitVecSext (x + y) ≈ʷ a + b

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

theorem select_shl_icmp_bad_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.eq e_2 (const? 32 1)) (shl e_1 e_2) e ⊑
    select (icmp IntPred.eq e_2 (const? 32 1)) (shl e_1 (const? 32 1)) e

theorem test10b_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), x_1 ^^^ x ^^^ x &&& x_1 = x_1 ||

theorem exact_lshr_eq_opposite_msb_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ BitVec.ofInt 8 (-128) >>> x <<< x ≠ BitVec.ofInt 8 (-128) ∨ x ≥ ↑8) →
    ofBool (BitVec.ofInt 8 (-128) >>> x == 1#8) = ofBool (x == 7#8)

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

theorem sub_select_sext_op_swapped_non_const_args_thm (e e_1 : IntW 6) (e_2 : IntW 1) :
  sub (sext 6 e_2) (select e_2 e_1 e) ⊑ select e_2 (LLVM.xor e_1 (const? 6 (-1))) (sub (const? 6 0) e)

lemma Fin.natAdd_zero' [h : NeZero m] : Fin.natAdd (m := m) n 0 = n

theorem test_add__nuw_is_safe_proof : test_add__nuw_is_safe_before ⊑ test_add__nuw_is_safe_after

theorem test11_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬zeroExtend 128 x &&& 31#128 ≥ ↑128 →
    ¬(True ∧ (x &&& 31#32).msb = true ∨
          True ∧
              (zeroExtend 64 x_1 <<< zeroExtend 64 (x &&& 31#32)).sshiftRight' (zeroExtend 64 (x &&& 31#32)) ≠
                zeroExtend 64 x_1 ∨
            True ∧
                zeroExtend 64 x_1 <<< zeroExtend 64 (x &&& 31#32) >>> zeroExtend 64 (x &&& 31#32) ≠ zeroExtend 64 x_1 ∨
              zeroExtend 64 (x &&& 31#32) ≥ ↑64) →
      truncate 64 (zeroExtend 128 x_1 <<< (zeroExtend 128 x &&& 31#128)) =
        zeroExtend 64 x_1 <<< zeroExtend 64 (x &&& 31#32)

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

theorem generic (x : BitVec w) (w2 w3 : Nat) (h1 : w  < w2) (h2 : w2 ≤ w3) :
   BitVec.signExtend w3 (BitVec.zeroExtend w2 x) = BitVec.zeroExtend w3 x

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

theorem lshr_or_and_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬(5#8 ≥ ↑8 ∨ 5#8 ≥ ↑8) →
    ¬5#8 ≥ ↑8 → (x_1 >>> 5#8 ||| BitVec.ofInt 8 (-58)) &&& x >>> 5#8 = (x &&& (x_1 ||| BitVec.ofInt 8 (-64))) >>> 5#8

theorem drop_nuw_trunc_proof : drop_nuw_trunc_before ⊑ drop_nuw_trunc_after

theorem PR45977_f2_proof : PR45977_f2_before ⊑ PR45977_f2_after

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

theorem not_logicalOr_not_op1_proof : not_logicalOr_not_op1_before ⊑ not_logicalOr_not_op1_after

theorem test4_proof : test4_before ⊑ test4_after

theorem test7_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬32#128 ≥ ↑128 →
    ¬(32#64 ≥ ↑64 ∨ True ∧ (x >>> 32#64).msb = true) →
      truncate 92 (zeroExtend 128 x >>> 32#128) = zeroExtend 92 (x >>> 32#64)

theorem not_signbit_zext_proof : not_signbit_zext_before ⊑ not_signbit_zext_after

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

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

theorem test6_proof : test6_before ⊑ test6_after

theorem src_srem_shl_demand_eliminate_signbit_proof : src_srem_shl_demand_eliminate_signbit_before ⊑ src_srem_shl_demand_eliminate_signbit_after

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

theorem t3_const_after_fold_lshr_shl_ne_proof : t3_const_after_fold_lshr_shl_ne_before ⊑ t3_const_after_fold_lshr_shl_ne_after

theorem or_xor_tree_0111_proof : or_xor_tree_0111_before ⊑ or_xor_tree_0111_after

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

theorem and1_lshr1_is_cmp_eq_0_proof : and1_lshr1_is_cmp_eq_0_before ⊑ and1_lshr1_is_cmp_eq_0_after

theorem bv_283 :
    ∀ (e e_1 : LLVM.IntW 1), LLVM.mul e_1 e ⊑ LLVM.and e_1 e

theorem uge_swap_or_max_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 ≤ᵤ x) = 1#1 → 1#1 = ofBool (x_1 ≤ᵤ x)

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

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

theorem test12_thm (e e_1 : IntW 32) :
  LLVM.and (icmp IntPred.ult e_1 e) (icmp IntPred.ule e_1 e) ⊑ icmp IntPred.ult e_1 e

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

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

theorem sdiv_icmp2_thm (e : IntW 64) :
  icmp IntPred.eq (LLVM.sdiv e (const? 64 5) { «exact» := true }) (const? 64 1) ⊑
    icmp IntPred.eq e (const? 64 5)

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

theorem ne_irregular_bit_widths_proof : ne_irregular_bit_widths_before ⊑ ne_irregular_bit_widths_after

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

@[simp] theorem Com.denoteLets_castPureToEff {com : Com d Γ .pure ty} :
    denoteLets (com.castPureToEff eff)
    = fun V => pure (com.denoteLets V |>.comap fun _ v => v.castCtxt (by simp))

theorem trunc_ashr_trunc_exact_thm (e : IntW 64) :
  trunc 8 (ashr (trunc 32 e) (const? 32 8) { «exact» := true }) ⊑
    trunc 8 (lshr e (const? 64 8) { «exact» := true })

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

theorem or_xor_tree_1000_proof : or_xor_tree_1000_before ⊑ or_xor_tree_1000_after

theorem PR42691_10_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.ugt e (const? 32 13)) (icmp IntPred.ne e (const? 32 (-1))) ⊑
    icmp IntPred.ult (add e (const? 32 (-14))) (const? 32 (-15))

theorem icmp_equality_test_wrong_and_thm (e e_1 e_2 : IntW 64) :
  select (icmp IntPred.eq e_2 e_1) (icmp IntPred.eq e e_1)
      (select (LLVM.xor (icmp IntPred.eq e e_1) (const? 1 1)) (const? 1 0) (icmp IntPred.eq e_2 e)) ⊑
    select (icmp IntPred.eq e_2 e_1) (icmp IntPred.eq e e_1)
      (select (icmp IntPred.eq e e_1) (icmp IntPred.eq e_2 e) (const? 1 0))

theorem test4_thm.extracted_1._1 : ∀ (x : BitVec 1023), ofBool (x <ₛ 0#1023) = 1#1 → 1022#1023 ≥ ↑1023 → False

theorem test54_proof : test54_before ⊑ test54_after

theorem alive_AndOrXor_1704 : alive_AndOrXor_1704_src ⊑ alive_AndOrXor_1704_tgt

theorem select_ashr_icmp_bad_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (x_1 == 1#32) = 1#1 → ¬x_1 ≥ ↑32 → ¬1#32 ≥ ↑32 → x.sshiftRight' x_1 = x.sshiftRight' 1#32

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

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

theorem and_nosignbit_lshr_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬8#32 ≥ ↑32 → (x &&& 2147418112#32) >>> 8#32 = x >>> 8#32 &&& 8388352#32

theorem lshr_eq_both_equal_proof : lshr_eq_both_equal_before ⊑ lshr_eq_both_equal_after

theorem select_bittest_to_sub_proof : select_bittest_to_sub_before ⊑ select_bittest_to_sub_after

theorem or_ranges_single_elem_right_proof : or_ranges_single_elem_right_before ⊑ or_ranges_single_elem_right_after

theorem canonicalize_logic_first_or0_nsw_proof : canonicalize_logic_first_or0_nsw_before ⊑ canonicalize_logic_first_or0_nsw_after

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

theorem icmp_ne_zext_ne_zero_proof : icmp_ne_zext_ne_zero_before ⊑ icmp_ne_zext_ne_zero_after

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

theorem e_251 :
     - 5 *  ~~~y + 11 *  ~~~x + 3 *  ~~~(x &&&  ~~~x) + 11 *  ~~~(x &&&  ~~~y) - 20 *  ~~~(x ||| y) - 25 *  ~~~(x |||  ~~~y) + 1 * (x &&&  ~~~y) = 15 * (x &&& y) - 1 * x

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

theorem select_icmp_eq_and_1_0_xor_2_proof : select_icmp_eq_and_1_0_xor_2_before ⊑ select_icmp_eq_and_1_0_xor_2_after

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

theorem add_eq (x : BitVec w) : x = x + 0

private theorem BitVec.signExtend_sle_signExtend_of_sle {x y : BitVec w}
    {N : Nat} (hN : w ≤ N)
    (h : x.sle y) : (x.signExtend N).sle (y.signExtend N)

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

theorem pr4917_3_proof : pr4917_3_before ⊑ pr4917_3_after

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

theorem fold_icmp_shl_nuw_c2_non_pow2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ 48#32 <<< x >>> x ≠ 48#32 ∨ x ≥ ↑32) → ofBool (48#32 <<< x <ᵤ 192#32) = ofBool (x <ᵤ 2#32)

theorem ashrsgt_01_13_proof : ashrsgt_01_13_before ⊑ ashrsgt_01_13_after

theorem bools_logical_commute0_and1_and2_proof : bools_logical_commute0_and1_and2_before ⊑ bools_logical_commute0_and1_and2_after

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

theorem eq_umax4_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 + 3#32 <ᵤ x) = 1#1 → ofBool (x_1 + 3#32 == x_1 + 3#32) = ofBool (x ≤ᵤ x_1 + 3#32)

theorem ugt_zext_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 1),
  ofBool (x <ᵤ zeroExtend 8 x_1) = ofBool (x == 0#8) &&& x_1

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

@[simp] theorem mk_none : { toOption := none (α := α) } = PoisonOr.poison

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

theorem test67_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 32),
  ¬(True ∧ ((x_1 &&& (zeroExtend 32 x ^^^ 1#32)) <<< 24#32).sshiftRight' 24#32 ≠ x_1 &&& (zeroExtend 32 x ^^^ 1#32) ∨
        True ∧ (x_1 &&& (zeroExtend 32 x ^^^ 1#32)) <<< 24#32 >>> 24#32 ≠ x_1 &&& (zeroExtend 32 x ^^^ 1#32) ∨
          24#32 ≥ ↑32 ∨
            True ∧
                ((x_1 &&& (zeroExtend 32 x ^^^ 1#32)) <<< 24#32 ^^^ BitVec.ofInt 32 (-16777216)) >>> 24#32 <<< 24#32 ≠
                  (x_1 &&& (zeroExtend 32 x ^^^ 1#32)) <<< 24#32 ^^^ BitVec.ofInt 32 (-16777216) ∨
              24#32 ≥ ↑32) →
    ofBool
        (truncate 8
            (((x_1 &&& (zeroExtend 32 x ^^^ 1#32)) <<< 24#32 ^^^ BitVec.ofInt 32 (-16777216)).sshiftRight' 24#32) ==
          0#8) =
      0#1

theorem e_2263 :
    3 * (e ^^^ (d |||  ~~~f)) - 1 * (e ||| (d &&& f)) + 1 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 5 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 3 *  ~~~(d &&&  ~~~e) + 2 *  ~~~(d ||| (e &&& f)) - 5 * (d ^^^ (e ^^^ f)) + 7 * (e ||| (d ^^^ f)) + 5 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 7 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 1 * (f ^^^ (d &&& (e ||| f))) - 1 * ((e &&& f) ||| (d &&& (e ||| f))) - 11 * (f ^^^ (d ||| (e ||| f))) - 11 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) - 2 * (f ^^^ (d &&& ( ~~~e ||| f))) + 5 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 5 * (e ^^^ (d ||| (e &&& f))) + 1 * (f &&& (d ||| e)) - 6 * (f |||  ~~~(d ||| e)) - 1 * (e |||  ~~~(d |||  ~~~f)) + 2 * (d ||| f) + 2 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) + 7 *  ~~~d + 2 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 11 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) - 2 * ( ~~~e &&& (d ^^^ f)) + 1 *  ~~~(d ^^^ (e ||| f)) - 7 * (f &&& (d ^^^ e)) - 2 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 7 * (f ^^^ (d ||| ( ~~~e ||| f))) + 1 * (f ^^^ (d &&& e)) - 1 *  ~~~( ~~~d &&& ( ~~~e ||| f)) + 1 *  ~~~(d ||| (e ^^^ f)) - 1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 5 * (f ^^^ (d &&&  ~~~e)) + 11 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 5 * (e ^^^ ( ~~~d ||| (e ||| f))) - 7 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) + 1 * (e ^^^ (d &&&  ~~~f)) - 1 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 3 * (e ^^^  ~~~(d ||| ( ~~~e &&& f))) - 3 * (f ^^^  ~~~(d ||| (e &&& f))) - 1 * (d ||| ( ~~~e &&& f)) + 1 * ( ~~~d &&& ( ~~~e ||| f)) - 11 *  ~~~(e &&&  ~~~f) + 1 * d + 1 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) + 5 * (e ^^^ (d &&& (e ^^^ f))) - 7 *  ~~~( ~~~d ||| (e ^^^ f)) + 11 * (e ^^^ (d &&& f)) - 47 *  ~~~(d ||| (e ||| f)) - 21 *  ~~~(d ||| ( ~~~e ||| f)) + 1 *  ~~~( ~~~d ||| (e ||| f)) - 25 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 21 * ( ~~~d &&& ( ~~~e &&& f)) - 50 * ( ~~~d &&& (e &&& f)) - 23 * (d &&& ( ~~~e &&& f)) - 9 * (d &&& (e &&& f)) =  - 1 * (e ^^^  ~~~(d ||| (e ^^^ f))) - 11 * (e ^^^  ~~~( ~~~d &&& (e ||| f)))

theorem positive_biggerLshr_lshrexact_proof : positive_biggerLshr_lshrexact_before ⊑ positive_biggerLshr_lshrexact_after

theorem sext_diff_i1_xor_sub_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  True ∧ (zeroExtend 64 x).saddOverflow (signExtend 64 x_1) = true → False

theorem sge_swap_or_max_commute_proof : sge_swap_or_max_commute_before ⊑ sge_swap_or_max_commute_after

theorem positive_different_trunc_both_proof : positive_different_trunc_both_before ⊑ positive_different_trunc_both_after

theorem select_replace_udiv_non_speculatable_proof : select_replace_udiv_non_speculatable_before ⊑ select_replace_udiv_non_speculatable_after

theorem fold_select_trunc_nsw_true_thm.extracted_1._2 : ∀ (x x_1 : BitVec 128),
  ¬(True ∧ signExtend 128 (truncate 1 x_1) ≠ x_1) → truncate 1 x_1 = 1#1 → x_1 = -1#128

theorem land_land_left1_proof : land_land_left1_before ⊑ land_land_left1_after

theorem src_is_mask_xor_fail_notmask_proof : src_is_mask_xor_fail_notmask_before ⊑ src_is_mask_xor_fail_notmask_after

theorem shl_or_lshr_proof : shl_or_lshr_before ⊑ shl_or_lshr_after

theorem trunc_sel_larger_sext_thm.extracted_1._1 : ∀ (x : BitVec 1), ¬x = 1#1 → signExtend 64 42#16 = 42#64

theorem test3_thm.extracted_1._1 : ∀ (x : BitVec 41), ofBool (x <ₛ 0#41) = 1#1 → 40#41 ≥ ↑41 → False

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

theorem or_and2_commuted_proof : or_and2_commuted_before ⊑ or_and2_commuted_after

theorem e_1424 :
    1 * t + 4 *  ~~~z + 4 *  ~~~t - 1 *  ~~~(z &&&  ~~~z) - 1 *  ~~~(z ^^^ t) - 7 * (z |||  ~~~t) - 1 * (z ^^^ t) - 4 *  ~~~(z |||  ~~~t) + 4 * (z &&&  ~~~t) + 8 * (z &&& t) =  - 1 *  ~~~(z &&& t)

theorem ashr_ult_14_proof : ashr_ult_14_before ⊑ ashr_ult_14_after

theorem a_true_implies_b_true2_thm (e e_1 : IntW 1) (e_2 : IntW 8) :
  LLVM.and (icmp IntPred.ugt e_2 (const? 8 20)) (select (icmp IntPred.ugt e_2 (const? 8 10)) e_1 e) ⊑
    select (icmp IntPred.ugt e_2 (const? 8 20)) e_1 (const? 1 0)

theorem test4_thm.extracted_1._1 : ∀ (x : BitVec 37),
  ofBool (x &&& BitVec.ofInt 37 (-2147483648) != 0#37) = ofBool (2147483647#37 <ᵤ x)

theorem PR60818_eq_commuted_proof : PR60818_eq_commuted_before ⊑ PR60818_eq_commuted_after

theorem shl_add_nuw_proof : shl_add_nuw_before ⊑ shl_add_nuw_after

theorem uge_and_max_commute_proof : uge_and_max_commute_before ⊑ uge_and_max_commute_after

theorem test_thm.extracted_1._4 : ∀ (x : BitVec 1) (x_1 : BitVec 32),
  ¬x = 1#1 → ¬1#32 = 0 → ¬0#32 ≥ ↑32 → x_1 / 1#32 = x_1 >>> 0#32

theorem zext_nneg_sext_ugt_proof : zext_nneg_sext_ugt_before ⊑ zext_nneg_sext_ugt_after

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

theorem main3d_proof : main3d_before ⊑ main3d_after

theorem icmp_ule_proof : icmp_ule_before ⊑ icmp_ule_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_7b_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_7b_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_7b_after

theorem and_ranges_overlap_single_proof : and_ranges_overlap_single_before ⊑ and_ranges_overlap_single_after

@[simp] theorem eval_shiftLeft_of_le {x : BitStream} {k : Nat} (hi : k ≤ i) :
  (shiftLeft x k) i = x (i - k)

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

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

lemma nonempty_eq_false_iff [DecidableEq α] (c : Circuit α) :
    nonempty c = false ↔ ∀ x, ¬ eval c x

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

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

theorem test_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), ofBool (x_1 <ₛ x) ||

theorem test_shl_nuw__nsw_is_safe_proof : test_shl_nuw__nsw_is_safe_before ⊑ test_shl_nuw__nsw_is_safe_after

theorem eval_fsmUnaryIncrK_eq_decide
  (a : NatFSM wcard tcard bcard ncard icard pcard (.ofDep v))
  {wenv : WidthExpr.Env wcard}
  {fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream}
  (henv : HWidthEnv fsmEnv wenv)
  (ha : HNatFSMToBitstream a) :
  ((fsmUnaryIncrK k a.toFsm).eval fsmEnv) = fun i =>
  decide (i < (v.toNat wenv) + k)

theorem e_1080 :
     - 6 * (z |||  ~~~t) - 6 *  ~~~t - 6 * t - 1 *  ~~~(z &&&  ~~~z) - 11 * (z ^^^ t) + 18 *  ~~~(z |||  ~~~t) + 24 * (z &&&  ~~~t) + 13 * (z &&& t) =  - 13 *  ~~~(z ||| t)

theorem zext_ashr_proof : zext_ashr_before ⊑ zext_ashr_after

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

theorem evalWith_succ_eq_evalWith_delta' (p : FSM arity) (carryState : p.α → Bool)
      (x : arity → BitStream) :
  p.evalWith carryState x (n + 1) =
  p.evalWith (p.delta' carryState (fun s => x s 0)) (fun s i => x s (i + 1)) n

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

theorem ult_swap_and_max_commute_logical_proof : ult_swap_and_max_commute_logical_before ⊑ ult_swap_and_max_commute_logical_after

theorem test69_xor_proof : test69_xor_before ⊑ test69_xor_after

@[simp] theorem bvars_var  :
  (var e body : Com d Γ eff t).bvars = e.bvars + body.bvars

@[simp]
theorem eval_implies (c₁ c₂ : Circuit α) (f : _) : (c₁.implies c₂).eval f = (!(c₁.eval f) || (c₂.eval f))

theorem test_sext_zext_proof : test_sext_zext_before ⊑ test_sext_zext_after

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

theorem test36_thm (e : IntW 32) :
  icmp IntPred.eq (trunc 8 (lshr e (const? 32 31))) (const? 8 0) ⊑
    icmp IntPred.sgt e (const? 32 (-1))

theorem t0_const_lshr_shl_ne_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(1#32 ≥ ↑32 ∨ 1#32 ≥ ↑32) →
    ¬2#32 ≥ ↑32 → ofBool (x_1 <<< 1#32 &&& x >>> 1#32 != 0#32) = ofBool (x >>> 2#32 &&& x_1 != 0#32)

theorem e_1072 :
     - 5 *  ~~~z + 2 * t - 2 * (z ||| t) - 2 *  ~~~(z &&&  ~~~z) + 2 * z + 7 *  ~~~(z ||| t) + 7 *  ~~~(z |||  ~~~t) =  - 2 * (z &&&  ~~~t)

theorem pv_proof : pv_before ⊑ pv_after

theorem add_select_not_zext_thm.extracted_1._1 : ∀ (x : BitVec 1),
  x = 1#1 → 64#64 + zeroExtend 64 (x ^^^ 1#1) = 64#64

theorem slt_swap_and_max_commute_logical_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == 127#8) = 1#1 → ofBool (x_1 <ₛ x) = 0#1

theorem test15_proof : test15_before ⊑ test15_after

theorem no_shift_xor_multiuse_cmp_or_thm (e e_1 e_2 e_3 : IntW 32) :
  mul
      (mul
        (select (icmp IntPred.ne (const? 32 0) (LLVM.and e_3 (const? 32 4096))) e_2 (LLVM.or e_2 (const? 32 4096)))
        (select (icmp IntPred.ne (const? 32 0) (LLVM.and e_3 (const? 32 4096))) e_1 e))
      (LLVM.or e_2 (const? 32 4096)) ⊑
    mul
      (mul
        (select (icmp IntPred.eq (LLVM.and e_3 (const? 32 4096)) (const? 32 0)) (LLVM.or e_2 (const? 32 4096)) e_2)
        (select (icmp IntPred.eq (LLVM.and e_3 (const? 32 4096)) (const? 32 0)) e e_1))
      (LLVM.or e_2 (const? 32 4096))

theorem t2_const_lshr_shl_eq_proof : t2_const_lshr_shl_eq_before ⊑ t2_const_lshr_shl_eq_after

theorem main5_like_proof : main5_like_before ⊑ main5_like_after

theorem icmp_ne_zext_ne_zero_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (zeroExtend 32 (ofBool (x != 0#32)) != x) = ofBool (1#32 <ᵤ x)

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 shl1_trunc_sgt0_thm (e : IntW 9) :
  icmp IntPred.sgt (trunc 6 (shl (const? 9 1) e)) (const? 6 0) ⊑
    icmp IntPred.sgt (trunc 6 (shl (const? 9 1) e { «nsw» := false, «nuw» := true })) (const? 6 0)

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

theorem test_add_nuw__all_are_safe_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 1073741823#32 == 3#32) = 1#1 →
    ¬(True ∧ (x &&& 1073741823#32).uaddOverflow 1#32 = true) →
      True ∧ (x &&& 1073741823#32).saddOverflow 1#32 = true ∨ True ∧ (x &&& 1073741823#32).uaddOverflow 1#32 = true →
        False

theorem Tensor1d.map_fusion [Inhabited α] (t: Tensor1d α):
  (t.map (g ∘ f)) = (t.map f).map g

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

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

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

theorem sext_proof : sext_before ⊑ sext_after

theorem n4_thm (e : IntW 16) :
  LLVM.and (shl (zext 32 e) (const? 32 16)) (const? 32 (-1073741824)) ⊑
    LLVM.and (shl (zext 32 e) (const? 32 16) { «nsw» := false, «nuw» := true }) (const? 32 (-1073741824))

theorem lshr_32_add_not_known_32_leading_zeroes_proof : lshr_32_add_not_known_32_leading_zeroes_before ⊑ lshr_32_add_not_known_32_leading_zeroes_after

theorem lshrugt_01_01_thm (e : IntW 4) :
  icmp IntPred.ugt (lshr e (const? 4 1)) (const? 4 1) ⊑ icmp IntPred.ugt e (const? 4 3)

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

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 ofBitVec_add : ofBitVecSext (x + y) ≈ʷ (ofBitVecSext x) + (ofBitVecSext y)

theorem xor_or_xor_common_op_commute5_proof : xor_or_xor_common_op_commute5_before ⊑ xor_or_xor_common_op_commute5_after

theorem n3_constmask_samemask_thm (e e_1 : IntW 32) :
  LLVM.xor (LLVM.and e_1 (const? 32 65280)) (LLVM.and e (const? 32 65280)) ⊑
    LLVM.and (LLVM.xor e_1 e) (const? 32 65280)

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

theorem t1_proof : t1_before ⊑ t1_after

theorem xor_logic_and_logic_or4_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 1),
  x_2 = 1#1 → x_1 = 1#1 → x_1 ^^^ 1#1 = x_2 ^^^ 1#1

theorem t13_x_is_one_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 32),
  ¬(32#32 - x_1 ≥ ↑32 ∨ zeroExtend 64 (x_1 + BitVec.ofInt 32 (-16)) ≥ ↑64) →
    ofBool (1#32 <<< (32#32 - x_1) &&& truncate 32 (x >>> zeroExtend 64 (x_1 + BitVec.ofInt 32 (-16))) != 0#32) =
      ofBool (x &&& 65536#64 != 0#64)

theorem ripple_nsw1_proof : ripple_nsw1_before ⊑ ripple_nsw1_after

theorem PR1817_1_logical_proof : PR1817_1_logical_before ⊑ PR1817_1_logical_after

theorem add_zero :
    (bw p (addMax (bw p a) (bw q (0#1))))  =
    (bw p a)

theorem positive_with_aggressive_icmp_logical_proof : positive_with_aggressive_icmp_logical_before ⊑ positive_with_aggressive_icmp_logical_after

theorem t9_proof : t9_before ⊑ t9_after

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

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

theorem decision_procedure_is_correct {w} (φ : Formula) (env : Nat → BitVec w) :
    formulaIsUniversal φ → φ.sat' env

theorem ashr_sub_nsw_proof : ashr_sub_nsw_before ⊑ ashr_sub_nsw_after

theorem test_add_nsw__all_are_safe_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 1073741823#32 == 3#32) = 1#1 →
    ¬(True ∧ (x &&& 1073741823#32).saddOverflow 1#32 = true) →
      True ∧ (x &&& 1073741823#32).saddOverflow 1#32 = true ∨ True ∧ (x &&& 1073741823#32).uaddOverflow 1#32 = true →
        False

theorem is_rem2_neg_i8_thm (e : IntW 8) :
  icmp IntPred.slt (LLVM.srem e (const? 8 2)) (const? 8 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 8 (-127))) (const? 8 (-127))

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

@[simp] lemma eval_complement : ∀ (c : Circuit α) (f : α → Bool),
    eval (~~~ c) f = !(eval c f)

theorem c0_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x <ₛ x &&& 3#8) = ofBool (x <ₛ 0#8)

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

theorem t15_proof : t15_before ⊑ t15_after

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

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 t10_c1_c2_proof : t10_c1_c2_before ⊑ t10_c1_c2_after

theorem test_add__nuw_is_safe_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 2147483647#32 == 2147483647#32) = 1#1 →
    True ∧ (x &&& 2147483647#32).uaddOverflow 1#32 = true → False

theorem varsFinset_and [DecidableEq α] (c₁ c₂ : Circuit α) :
    (varsFinset (c₁ &&& c₂)) ⊆ (varsFinset c₁ ∪ varsFinset c₂)

theorem ashr_and_or_disjoint_thm (e e_1 : IntW 8) :
  shl (LLVM.or (LLVM.srem e_1 (const? 8 42)) (LLVM.and (ashr e (const? 8 2)) (const? 8 13)) { «disjoint» := true })
      (const? 8 2) ⊑
    LLVM.or (LLVM.and e (const? 8 52)) (shl (LLVM.srem e_1 (const? 8 42)) (const? 8 2)) { «disjoint» := true }

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

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

theorem positive_biggershl_proof : positive_biggershl_before ⊑ positive_biggershl_after

theorem ashr_mul_times_5_div_4_exact_2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.smulOverflow 5#32 = true ∨ True ∧ (x * 5#32) >>> 2#32 <<< 2#32 ≠ x * 5#32 ∨ 2#32 ≥ ↑32) →
    True ∧ x >>> 2#32 <<< 2#32 ≠ x ∨ 2#32 ≥ ↑32 ∨ True ∧ x.saddOverflow (x.sshiftRight' 2#32) = true → False

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

theorem PR1817_1_logical_proof : PR1817_1_logical_before ⊑ PR1817_1_logical_after

theorem test_shl_nuw_nsw__nsw_is_safe_proof : test_shl_nuw_nsw__nsw_is_safe_before ⊑ test_shl_nuw_nsw__nsw_is_safe_after

theorem mullo_thm (e e_1 : IntW 64) :
  LLVM.or
      (shl
        (add
          (LLVM.and
            (add
              (lshr
                (mul (LLVM.and e_1 (const? 64 4294967295)) (LLVM.and e (const? 64 4294967295))
                  { «nsw» := false, «nuw» := true })
                (const? 64 32))
              (mul (LLVM.and e_1 (const? 64 4294967295)) (lshr e (const? 64 32)) { «nsw» := false, «nuw» := true }))
            (const? 64 4294967295))
          (mul (lshr e_1 (const? 64 32)) (LLVM.and e (const? 64 4294967295)) { «nsw» := false, «nuw» := true }))
        (const? 64 32))
      (LLVM.and
        (mul (LLVM.and e_1 (const? 64 4294967295)) (LLVM.and e (const? 64 4294967295))
          { «nsw» := false, «nuw» := true })
        (const? 64 4294967295)) ⊑
    LLVM.or
      (shl
        (add
          (add
            (lshr
              (mul (LLVM.and e_1 (const? 64 4294967295)) (LLVM.and e (const? 64 4294967295))
                { «nsw» := false, «nuw» := true })
              (const? 64 32))
            (mul e_1 (lshr e (const? 64 32))))
          (mul (lshr e_1 (const? 64 32)) e))
        (const? 64 32))
      (LLVM.and
        (mul (LLVM.and e_1 (const? 64 4294967295)) (LLVM.and e (const? 64 4294967295))
          { «nsw» := false, «nuw» := true })
        (const? 64 4294967295))
      { «disjoint» := true }

theorem ashrslt_03_14_proof : ashrslt_03_14_before ⊑ ashrslt_03_14_after

theorem smear_set_bit_different_dest_type_wider_dst_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬7#8 ≥ ↑8 →
    ¬(24#32 ≥ ↑32 ∨ 31#32 ≥ ↑32) →
      signExtend 64 ((truncate 8 x).sshiftRight' 7#8) = signExtend 64 ((x <<< 24#32).sshiftRight' 31#32)

theorem select_non_const_sides_thm.extracted_1._4 : ∀ (x x_1 : BitVec 64) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → x - zeroExtend 64 x_2 = x

theorem or_logic_or_logic_and_5_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1), ¬x_1 ||

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

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

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

theorem PR42691_6_logical_thm (e : IntW 32) :
  select (icmp IntPred.ult e (const? 32 (-2147483647))) (const? 1 1) (icmp IntPred.eq e (const? 32 (-1))) ⊑
    icmp IntPred.ult (add e (const? 32 1)) (const? 32 (-2147483646))

theorem main4f_like_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬ofBool (x_2 &&& x_1 != x_1) ||

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 test_mul_nsw__nuw_is_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 268435457#32 == 268435456#32) = 1#1 →
    ¬(True ∧ (x &&& 268435457#32).umulOverflow 9#32 = true) →
      BitVec.ofInt 32 (-1879048192) = (x &&& 268435457#32) * 9#32

theorem icmp_select_var_both_fold_thm (e e_1 : IntW 8) :
  icmp IntPred.eq (select (icmp IntPred.eq e_1 (const? 8 0)) (LLVM.or e (const? 8 1)) (const? 8 2))
      (LLVM.or e (const? 8 1)) ⊑
    icmp IntPred.eq e_1 (const? 8 0)

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

theorem test1_proof : test1_before ⊑ test1_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_0_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_0_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_0_logical_after

theorem n3_constmask_samemask_proof : n3_constmask_samemask_before ⊑ n3_constmask_samemask_after

theorem select_icmp_eq_and_1_0_lshr_fv_thm.extracted_1._4 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 &&& 1#8 == 0#8) = 1#1 →
    ¬2#8 ≥ ↑8 → ¬(1#8 ≥ ↑8 ∨ x_1 <<< 1#8 &&& 2#8 ≥ ↑8) → x >>> 2#8 = x >>> (x_1 <<< 1#8 &&& 2#8)

theorem test17_thm (e : IntW 1) : sub (const? 32 0) (sext 32 e) ⊑ zext 32 e

theorem t7_thm (e : IntW 8) :
  icmp IntPred.ule (sub (const? 8 0) e { «nsw» := true, «nuw» := false }) e ⊑
    icmp IntPred.slt e (const? 8 1)

theorem xor_of_icmps_neg_to_ne_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ofBool (BitVec.ofInt 64 (-6) <ₛ x) ^^^ ofBool (x <ₛ BitVec.ofInt 64 (-4)) = ofBool (x != BitVec.ofInt 64 (-5))

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

theorem or_xor_tree_0110_proof : or_xor_tree_0110_before ⊑ or_xor_tree_0110_after

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

theorem e_1550 :
    1 * c + 4 * (b ^^^ (a |||  ~~~c)) - 2 * b + 11 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) + 7 * (b ^^^  ~~~(a ||| (b ^^^ c))) + 1 * (b ^^^ (a &&&  ~~~c)) - 22 *  ~~~(a ||| (b ||| c)) + 1 *  ~~~(a ||| ( ~~~b ||| c)) - 9 *  ~~~( ~~~a ||| (b ||| c)) - 9 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 1 * ( ~~~a &&& ( ~~~b &&& c)) - 15 * ( ~~~a &&& (b &&& c)) - 9 * (a &&& ( ~~~b &&& c)) = 7 *  ~~~( ~~~a &&& ( ~~~b ||| c))

theorem icmp_ne_and_pow2_lshr_pow2_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬x ≥ ↑32 → zeroExtend 32 (ofBool (8#32 >>> x &&& 4#32 == 0#32)) = zeroExtend 32 (ofBool (x != 1#32))

theorem e_2405 :
     - 1 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 1 * (e ||| (d &&&  ~~~f)) - 3 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) + 7 * d + 2 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 6 *  ~~~(d ||| e) - 1 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 3 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) + 1 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 1 * (e ^^^ ( ~~~d ||| (e &&& f))) + 4 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 5 * (e ^^^  ~~~(d &&&  ~~~f)) - 11 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) + 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 5 *  ~~~e - 2 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 1 * (e ^^^ (d &&&  ~~~f)) + 7 * (e ^^^  ~~~(d ||| f)) - 2 * (f &&&  ~~~(d &&&  ~~~e)) - 5 * ( ~~~e ||| (d ^^^ f)) + 2 * (f ^^^ (d ||| (e ||| f))) + 5 *  ~~~(e &&& f) - 1 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 1 * (e ^^^ (d ||| f)) + 4 *  ~~~d + 1 *  ~~~(d ||| (e ^^^ f)) - 6 * (e ^^^  ~~~(d &&& (e &&& f))) + 2 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 3 * ((d &&& e) |||  ~~~(e |||  ~~~f)) + 7 * (d ^^^ f) + 2 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) + 1 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 11 * (d ||| ( ~~~e ||| f)) + 5 *  ~~~( ~~~d &&& ( ~~~e ||| f)) - 5 * (f ^^^  ~~~(d &&& (e &&& f))) - 5 * (f ^^^  ~~~(d ||| e)) - 11 * (f ^^^ (d |||  ~~~e)) + 2 * (f ^^^ (d ||| (e &&& f))) + 1 * (d &&& e) - 5 *  ~~~( ~~~d &&& (e ||| f)) - 3 * ((d &&& e) ^^^ (e |||  ~~~f)) + 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 11 * (e ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 2 * ( ~~~f &&& (d ^^^ e)) + 11 * (f ^^^ (d ||| e)) + 1 * (e ^^^ (d ||| (e ^^^ f))) + 2 * ( ~~~d &&& (e ^^^ f)) - 2 * (d ^^^ e) + 7 * ((e &&& f) ||| (d &&& (e ||| f))) - 2 * (e ||| (d &&& f)) + 1 * ((d |||  ~~~e) &&&  ~~~(e ^^^ f)) - 7 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 4 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 1 * (f &&&  ~~~(d &&& e)) + 1 * ((d &&& e) ^^^ (e ||| f)) - 5 * (e &&& f) + 1 * ((d &&& e) |||  ~~~(e ||| f)) - 1 * (f ^^^  ~~~(d &&& e)) - 2 * (f &&& (d |||  ~~~e)) + 1 * ((d ||| e) &&&  ~~~(d ^^^ (e ^^^ f))) + 1 * (e ^^^ ( ~~~d &&& (e ||| f))) + 4 * (e ^^^ ( ~~~d ||| (e ^^^ f))) - 3 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 4 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 7 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 11 * ((d &&& e) ^^^ (d ^^^ (e &&& f))) + 24 *  ~~~(d ||| (e ||| f)) - 28 *  ~~~(d ||| ( ~~~e ||| f)) + 29 *  ~~~( ~~~d ||| (e ||| f)) + 10 * ( ~~~d &&& ( ~~~e &&& f)) + 12 * ( ~~~d &&& (e &&& f)) + 40 * (d &&& ( ~~~e &&& f)) + 17 * (d &&& (e &&& f)) = 1 * ((e &&& f) ^^^  ~~~(d &&& (e ^^^ f))) - 3 * (e ^^^  ~~~( ~~~d &&& (e &&& f)))

theorem e_493 :
    5 * (x ||| y) + 4 *  ~~~y - 7 * (x |||  ~~~y) - 7 *  ~~~x - 5 * (x ^^^ y) - 2 *  ~~~(x &&& y) + 12 *  ~~~(x ||| y) + 9 *  ~~~(x |||  ~~~y) + 2 * (x &&& y) =  - 5 * (x &&&  ~~~y)

theorem p_proof : p_before ⊑ p_after

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

theorem trunc_shl_shl_var_proof : trunc_shl_shl_var_before ⊑ trunc_shl_shl_var_after

theorem shift_no_xor_multiuse_cmp_with_xor_proof : shift_no_xor_multiuse_cmp_with_xor_before ⊑ shift_no_xor_multiuse_cmp_with_xor_after

theorem ashr_ult_exact_proof : ashr_ult_exact_before ⊑ ashr_ult_exact_after

theorem not_or_or_and_no_and_commute2_proof : not_or_or_and_no_and_commute2_before ⊑ not_or_or_and_no_and_commute2_after

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

theorem tryFactorization_add_nuw_mul_nuw_mul_var_proof : tryFactorization_add_nuw_mul_nuw_mul_var_before ⊑ tryFactorization_add_nuw_mul_nuw_mul_var_after

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

theorem icmp_mul_nsw_sgt_proof : icmp_mul_nsw_sgt_before ⊑ icmp_mul_nsw_sgt_after

theorem test3_proof : test3_before ⊑ test3_after

theorem ule_swap_or_min_proof : ule_swap_or_min_before ⊑ ule_swap_or_min_after

theorem test19_proof : test19_before ⊑ test19_after

theorem and_two_ranges_to_mask_and_range_different_sizes_proof : and_two_ranges_to_mask_and_range_different_sizes_before ⊑ and_two_ranges_to_mask_and_range_different_sizes_after

theorem bv0 (a b : BitVec 0) : a = b

theorem or_and_not_not_commute7_proof : or_and_not_not_commute7_before ⊑ or_and_not_not_commute7_after

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

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

theorem ashrsgt_01_02_exact_proof : ashrsgt_01_02_exact_before ⊑ ashrsgt_01_02_exact_after

theorem lshr_2_add_zext_basic_proof : lshr_2_add_zext_basic_before ⊑ lshr_2_add_zext_basic_after

theorem ashr_32_add_zext_basic_proof : ashr_32_add_zext_basic_before ⊑ ashr_32_add_zext_basic_after

theorem test1_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8), truncate 8 (zeroExtend 64 x_1 + zeroExtend 64 x) = x_1 + x

theorem n2_proof : n2_before ⊑ n2_after

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

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

theorem different_size_zext_zext_ugt_proof : different_size_zext_zext_ugt_before ⊑ different_size_zext_zext_ugt_after

theorem test5_proof : test5_before ⊑ test5_after

theorem and_zext_zext_thm.extracted_1._1 : ∀ (x : BitVec 4) (x_1 : BitVec 8),
  True ∧ (x_1 &&& zeroExtend 8 x).msb = true → False

theorem and_zext_eq_zero_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x ≥ ↑32 → zeroExtend 32 (ofBool (x_1 == 0#32)) &&& (x_1 >>> x ^^^ -1#32) = zeroExtend 32 (ofBool (x_1 == 0#32))

theorem test3_thm.extracted_1._1 : ∀ (x : BitVec 32), True ∧ (x &&& 32#32 &&& 8#32 != 0) = true → False

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

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

theorem test_sub__nuw_is_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 2147483647#32 == 1073741824#32) = 1#1 →
    ¬(True ∧ (BitVec.ofInt 32 (-2147483648)).usubOverflow (x &&& 2147483647#32) = true) →
      1073741824#32 = BitVec.ofInt 32 (-2147483648) - (x &&& 2147483647#32)

theorem or_nosignbit_select_shl_proof : or_nosignbit_select_shl_before ⊑ or_nosignbit_select_shl_after

theorem and_add_bool_to_select_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → -1#32 + zeroExtend 32 x_1 &&& x = 0#32

theorem test22_proof : test22_before ⊑ test22_after

theorem test5_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬16#128 ≥ ↑128 → ¬16#32 ≥ ↑32 → truncate 32 (zeroExtend 128 x >>> 16#128) = x >>> 16#32

theorem fold_sext_to_and_wrong9_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (signExtend 32 x &&& 128#32 != 1#32) = 1#1

theorem masked_and_notA_slightly_optimized_thm (e : IntW 32) :
  LLVM.and (icmp IntPred.uge e (const? 32 8)) (icmp IntPred.ne (LLVM.and e (const? 32 39)) e) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 (-40))) (const? 32 0)

theorem add_nuw_nsw_or_and_proof : add_nuw_nsw_or_and_before ⊑ add_nuw_nsw_or_and_after

theorem add_select_not_sext_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 1#64 + signExtend 64 (x ^^^ 1#1) = 0#64

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

theorem t3_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 2),
  signExtend 8 x_1 + x ^^^ signExtend 8 x_1 = x + signExtend 8 x_1 ^^^ signExtend 8 x_1

theorem test1_proof : test1_before ⊑ test1_after

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

theorem ule_umax1_thm (e e_1 : IntW 32) :
  icmp IntPred.ule (select (icmp IntPred.ugt e_1 e) e_1 e) e_1 ⊑ icmp IntPred.ule e e_1

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

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

theorem icmp_x_slt_0_and_icmp_y_sgt_neg1_i32_fail_proof : icmp_x_slt_0_and_icmp_y_sgt_neg1_i32_fail_before ⊑ icmp_x_slt_0_and_icmp_y_sgt_neg1_i32_fail_after

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 select_icmp_sgt_allones_smin_proof : select_icmp_sgt_allones_smin_before ⊑ select_icmp_sgt_allones_smin_after

theorem or_eq_with_diff_one_proof : or_eq_with_diff_one_before ⊑ or_eq_with_diff_one_after

theorem test19_proof : test19_before ⊑ test19_after

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

theorem sel_sext_constants_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → signExtend 16 (-1#8) = -1#16

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

theorem ashrslt_02_10_proof : ashrslt_02_10_before ⊑ ashrslt_02_10_after

theorem trunc_sel_equal_zext_proof : trunc_sel_equal_zext_before ⊑ trunc_sel_equal_zext_after

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

theorem t0_proof : t0_before ⊑ t0_after

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

theorem lshr_shl_pow2_const_case1_thm (e : IntW 16) :
  LLVM.and (shl (lshr (const? 16 256) e) (const? 16 2)) (const? 16 8) ⊑
    select (icmp IntPred.eq e (const? 16 7)) (const? 16 8) (const? 16 0)

theorem p1_ugt_thm (e e_1 : IntW 32) :
  select (icmp IntPred.ugt e_1 (const? 32 65534)) e (const? 32 65535) ⊑
    select (icmp IntPred.ult e_1 (const? 32 65535)) (const? 32 65535) e

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

theorem narrow_source_matching_signbits_proof : narrow_source_matching_signbits_before ⊑ narrow_source_matching_signbits_after

theorem trunc_lshr_exact_mask_thm.extracted_1._1 : ∀ (x : BitVec 8), ¬2#8 ≥ ↑8 → 2#6 ≥ ↑6 → False

theorem test16_proof : test16_before ⊑ test16_after

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

theorem test15_thm.extracted_1._1 : ∀ (x : BitVec 32), 27#32 ≥ ↑32 ∨ 31#32 ≥ ↑32 → False

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

theorem test_sub__nuw_is_safe_proof : test_sub__nuw_is_safe_before ⊑ test_sub__nuw_is_safe_after

theorem test_or3_logical_thm (e e_1 : IntW 32) :
  select (icmp IntPred.sle (LLVM.and e_1 (const? 32 2147483647)) e) (const? 1 1)
      (icmp IntPred.slt e (const? 32 0)) ⊑
    icmp IntPred.uge e (LLVM.and e_1 (const? 32 2147483647))

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

theorem alive_AddSub_1176 : alive_AddSub_1176_src ⊑ alive_AddSub_1176_tgt

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

theorem t15_and_with_const1_proof : t15_and_with_const1_before ⊑ t15_and_with_const1_after

theorem t3_ult_sgt_neg1_thm.extracted_1._9 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (x_1 <ᵤ 65536#32) = 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 multiuse2_proof : multiuse2_before ⊑ multiuse2_after

theorem set_to_set_decomposebittest_thm.extracted_1._4 : ∀ (x : BitVec 8),
  ¬ofBool (x <ₛ 0#8) = 1#1 →
    ¬(True ∧ (x &&& BitVec.ofInt 8 (-128) &&& 3#8 != 0) = true) → 3#8 = x &&& BitVec.ofInt 8 (-128) ||

theorem masked_bit_set_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x_1 ≥ ↑32 → zeroExtend 32 (ofBool (1#32 <<< x_1 &&& x != 0#32)) = x >>> x_1 &&& 1#32

theorem ashr_ugt_exact_proof : ashr_ugt_exact_before ⊑ ashr_ugt_exact_after

theorem scalar_i32_signbit_lshr_and_eq_nonzero_proof : scalar_i32_signbit_lshr_and_eq_nonzero_before ⊑ scalar_i32_signbit_lshr_and_eq_nonzero_after

theorem p3_sgt_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ofBool (65534#32 <ₛ x_1) = 1#1 → ofBool (x_1 <ₛ 65535#32) = 1#1 → x = 65535#32

theorem test14_proof : test14_before ⊑ test14_after

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

theorem t10_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ (x_1 <<< x).sshiftRight' x ≠ x_1 ∨
        x ≥ ↑32 ∨ (x_1 == 0 || 32 != 1 && x_1 <<< x == intMin 32 && x_1 == -1) = true) →
    True ∧ (1#32 <<< x).sshiftRight' x ≠ 1#32 ∨ True ∧ 1#32 <<< x >>> x ≠ 1#32 ∨ x ≥ ↑32 → False

theorem not_not_cmp_thm (e e_1 : IntW 32) :
  icmp IntPred.slt (LLVM.xor e_1 (const? 32 (-1))) (LLVM.xor e (const? 32 (-1))) ⊑
    icmp IntPred.sgt e_1 e

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

theorem lshrult_01_00_exact_proof : lshrult_01_00_exact_before ⊑ lshrult_01_00_exact_after

theorem and_ne_with_diff_one_signed_logical_thm (e : IntW 64) :
  select (icmp IntPred.ne e (const? 64 (-1))) (icmp IntPred.ne e (const? 64 0)) (const? 1 0) ⊑
    icmp IntPred.ult (add e (const? 64 (-1))) (const? 64 (-2))

theorem test_with_neg_even_thm (e : IntW 32) : LLVM.and (shl (const? 32 (-4)) e) (const? 32 1) ⊑ const? 32 0

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

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

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

theorem main7c_logical_thm (e e_1 e_2 : IntW 32) :
  select (select (icmp IntPred.eq e_2 (LLVM.and e_2 e_1)) (icmp IntPred.eq e (LLVM.and e e_1)) (const? 1 0))
      (const? 32 0) (const? 32 1) ⊑
    zext 32
      (select (icmp IntPred.ne e_2 (LLVM.and e_2 e_1)) (const? 1 1)
        (icmp IntPred.ne e (LLVM.and e e_1)))

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

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

theorem logical_and_logical_and_icmps_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 8),
  ¬ofBool (x_2 == 42#8) = 1#1 → ¬x ≥ ↑8 → True ∧ 1#8 <<< x >>> x ≠ 1#8 ∨ x ≥ ↑8 → 0#1 = 1#1 → False

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

theorem slt_negative_multip_rem_zero_proof : slt_negative_multip_rem_zero_before ⊑ slt_negative_multip_rem_zero_after

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

theorem lshr_xor_or_good_mask_proof : lshr_xor_or_good_mask_before ⊑ lshr_xor_or_good_mask_after

@[simp] theorem toHom_comp_toHom (f : Γ.Diff Δ) (g : Δ.Diff Ξ) :
    f.toHom.comp g.toHom = (f + g).toHom

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

theorem scalar_i32_signbit_lshr_and_ne_proof : scalar_i32_signbit_lshr_and_ne_before ⊑ scalar_i32_signbit_lshr_and_ne_after

theorem masked_bit_set_nonzero_cmp_proof : masked_bit_set_nonzero_cmp_before ⊑ masked_bit_set_nonzero_cmp_after

theorem negate_add_with_single_negatible_operand_depth2_thm (e e_1 : IntW 8) :
  sub (const? 8 0) (mul (add e_1 (const? 8 21)) e) ⊑ mul (sub (const? 8 (-21)) e_1) e

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

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

@[simp]
theorem Bool.xor_false_iff_eq : ∀ (a b : Bool), (a ^^ b) = false ↔ a = b

theorem shl_bad_sub_i8_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬4#8 - x ≥ ↑8 → True ∧ 1#8 <<< (4#8 - x) >>> (4#8 - x) ≠ 1#8 ∨ 4#8 - x ≥ ↑8 → False

theorem trunc_ashr_thm (e : IntW 32) :
  trunc 32 (ashr (LLVM.or (zext 36 e) (const? 36 (-2147483648))) (const? 36 8)) ⊑
    LLVM.or (lshr e (const? 32 8)) (const? 32 (-8388608))

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

theorem e_2385 :
    4 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) - 2 * (f ^^^  ~~~(d &&& (e ||| f))) - 2 * (e |||  ~~~(d ||| f)) - 1 *  ~~~( ~~~d ||| ( ~~~e &&& f)) - 1 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 6 * (e ^^^ (d &&& (e ^^^ f))) - 6 * (d ^^^ f) + 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 7 * ( ~~~(d &&&  ~~~e) &&& (d ^^^ (e ^^^ f))) + 5 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 3 * ((d ||| e) &&& (e ^^^ f)) - 11 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 3 * (f ^^^ (d ||| ( ~~~e &&& f))) - 7 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 4 * (f &&& (d ^^^ e)) - 5 * (e ^^^  ~~~(d &&&  ~~~f)) - 2 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 3 * (d &&& f) - 5 * ( ~~~d &&& (e ^^^ f)) + 1 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) + 7 *  ~~~(d &&&  ~~~d) - 7 * ((d &&& e) ^^^ (e |||  ~~~f)) - 6 * (e ^^^ (d ||| (e ^^^ f))) - 3 *  ~~~( ~~~d &&& (e ^^^ f)) + 7 * (e ^^^  ~~~(d &&& (e &&& f))) + 2 *  ~~~e + 4 *  ~~~(d ||| (e &&& f)) + 5 * (e ^^^ ( ~~~d ||| (e &&& f))) - 7 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 2 * ( ~~~d &&& ( ~~~e ||| f)) - 3 * ((d &&&  ~~~e) ||| (d ^^^ (e ^^^ f))) + 1 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 1 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 3 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 2 * (d ||| (e &&& f)) - 2 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) - 11 * (e &&&  ~~~f) + 7 * (e ^^^ f) - 2 * (d ||| e) - 1 * (f ^^^ (d &&&  ~~~e)) + 3 * (e ^^^ ( ~~~d &&& (e ||| f))) - 11 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 4 * (f ^^^ (d ||| (e &&& f))) + 1 * (e ^^^ (d ||| (e ||| f))) + 5 * (e ^^^  ~~~(d |||  ~~~f)) + 1 * (e ||| (d &&&  ~~~f)) + 3 *  ~~~(e ||| f) - 2 * ( ~~~d ||| (e ^^^ f)) + 1 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) + 1 * (d ||| (e ||| f)) - 6 * (d &&& (e ^^^ f)) + 11 *  ~~~(e &&&  ~~~f) + 11 * (e ^^^ ( ~~~d &&& (e ^^^ f))) + 11 * (e &&& (d ||| f)) + 3 *  ~~~(d ^^^ (e ^^^ f)) + 5 *  ~~~(d &&& (e ||| f)) - 5 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 2 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 1 * (e ^^^ (d &&& ( ~~~e ||| f))) + 2 * ((d ^^^ e) |||  ~~~(d ^^^ f)) - 1 * (e ^^^ (d ||| (e &&& f))) - 11 *  ~~~(d ||| (e ||| f)) + 34 *  ~~~(d ||| ( ~~~e ||| f)) + 15 *  ~~~( ~~~d ||| (e ||| f)) + 19 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 26 * ( ~~~d &&& ( ~~~e &&& f)) - 24 * ( ~~~d &&& (e &&& f)) + 21 * (d &&& ( ~~~e &&& f)) - 33 * (d &&& (e &&& f)) = 1 * (e ^^^  ~~~(d &&& ( ~~~e ||| f)))

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

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

@[simp]
theorem BitStream.ofProp_eq (p : Prop) : (BitStream.ofProp p i) = decide p

theorem lshr_pow2_slt_proof : lshr_pow2_slt_before ⊑ lshr_pow2_slt_after

theorem test_zext3_thm.extracted_1._5 : ∀ (x x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬x_1 ^^^ 1#1 = 1#1 → zeroExtend 32 x = zeroExtend 32 0#1

theorem masked_bit_set_proof : masked_bit_set_before ⊑ masked_bit_set_after

theorem trunc_signed_nsw_zext_proof : trunc_signed_nsw_zext_before ⊑ trunc_signed_nsw_zext_after

theorem R.representative_fromPoly_toFun :
    forall a :
      (ZMod q)[X], ((R.fromPoly (n:=n) (q := q)).toFun a).representative = a %ₘ (f q n)

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

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

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

theorem lshrugt_03_06_proof : lshrugt_03_06_before ⊑ lshrugt_03_06_after

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

theorem shl_and_and_proof : shl_and_and_before ⊑ shl_and_and_after

theorem test6_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬3#32 ≥ ↑32 →
    ¬(3#32 ≥ ↑32 ∨
          True ∧ (x >>> 3#32).smulOverflow 3#32 = true ∨
            True ∧ (x >>> 3#32).umulOverflow 3#32 = true ∨ True ∧ (x >>> 3#32 * 3#32).msb = true) →
      signExtend 64 (x >>> 3#32 * 3#32) = zeroExtend 64 (x >>> 3#32 * 3#32)

theorem trunc_lshr_sext_exact_proof : trunc_lshr_sext_exact_before ⊑ trunc_lshr_sext_exact_after

theorem test_or_ne_a_b_thm (e e_1 : IntW 8) (e_2 : IntW 1) :
  select (LLVM.or e_2 (icmp IntPred.ne e_1 e)) e_1 e ⊑ e_1

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

theorem R.fromPoly_rep'_eq_ideal :
    forall a : (ZMod q)[X],
      ∃ i ∈ Ideal.span {f q n}, (R.fromPoly (n:=n) a).representative' = a + i

theorem cmpeq_bitwise_proof : cmpeq_bitwise_before ⊑ cmpeq_bitwise_after

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

theorem main2_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x &&& 1#32 == 0#32) = 1#1 → ¬True → 0#32 = zeroExtend 32 (ofBool (x &&& 3#32 == 3#32))

theorem ugt_swap_and_min_commute_logical_proof : ugt_swap_and_min_commute_logical_before ⊑ ugt_swap_and_min_commute_logical_after

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

theorem ashr_mul_times_3_div_2_proof : ashr_mul_times_3_div_2_before ⊑ ashr_mul_times_3_div_2_after

theorem lowmask_add_zext_proof : lowmask_add_zext_before ⊑ lowmask_add_zext_after

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

theorem lshrult_01_15_exact_proof : lshrult_01_15_exact_before ⊑ lshrult_01_15_exact_after

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

theorem t5_ugt_slt_0_proof : t5_ugt_slt_0_before ⊑ t5_ugt_slt_0_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 t0_commutative_thm.extracted_1._6 : ∀ (x : BitVec 8) (x_1 : BitVec 1) (x_2 x_3 : BitVec 8),
  ¬ofBool (x_3 == x_2) = 1#1 → ¬ofBool (x_3 != x_2) = 1#1 → 0#1 = 1#1 → x_1 = 1#1 → False

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

theorem n10_proof : n10_before ⊑ n10_after

theorem eq_210_proof : eq_210_before ⊑ eq_210_after

theorem shl1_nsw_thm (e e_1 : IntW 8) :
  LLVM.sdiv e_1 (shl (const? 8 1) e { «nsw» := true, «nuw» := false }) { «exact» := true } ⊑
    ashr e_1 e { «exact» := true }

theorem udiv_illegal_type_c_thm.extracted_1._1 : ∀ (x : BitVec 9),
  ¬10#32 = 0 → 10#9 = 0 ∨ True ∧ (x / 10#9).msb = true → False

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

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

theorem ashrsgt_02_01_proof : ashrsgt_02_01_before ⊑ ashrsgt_02_01_after

theorem icmp_power2_and_icmp_shifted_mask_swapped_8_7_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x &&& 7#32 != 7#32) &&& ofBool (x <ᵤ 8#32) = ofBool (x <ᵤ 7#32)

theorem trunc_shl_shl_var_thm (e e_1 : IntW 64) :
  trunc 32 (shl (shl e_1 e) (const? 64 2)) ⊑ shl (trunc 32 (shl e_1 e)) (const? 32 2)

theorem test3_thm (e e_1 : IntW 32) :
  zext 32 (icmp IntPred.eq (lshr e_1 (const? 32 31)) (lshr e (const? 32 31))) ⊑
    zext 32 (icmp IntPred.sgt (LLVM.xor e_1 e) (const? 32 (-1)))

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

theorem wrongimm_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬14#16 ≥ ↑16 →
    14#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 14#16)) ≠ x.sshiftRight' 14#16 → False

theorem test6_proof : test6_before ⊑ test6_after

@[simp]
theorem HPredicateEnv.of_mkFsmEnvOfTenv {wcard tcard bcard ncard icard pcard : Nat}
    {wenv : Fin wcard → Nat}
    {tctx : Term.Ctx wcard tcard}
    (tenv : tctx.Env wenv)
    (benv : Term.BoolEnv bcard)
    (nenv : Term.NatEnv ncard)
    (ienv : Term.IntEnv icard)
    (penv : Predicate.Env pcard) :
    HPredicateEnv (HTermEnv.mkFsmEnvOfTenv tenv benv nenv ienv penv) penv

lemma NFA'.correct2_spec {M : NFA' 2} {ζ : M.sa2} {L : BVRel} :
    M.correct2 ζ L → M.accepts = langRel2 L

theorem test6_thm.extracted_1._2 : ∀ (x : BitVec 64),
  ¬32#128 ≥ ↑128 →
    ¬(32#64 ≥ ↑64 ∨ True ∧ zeroExtend 64 (truncate 32 (x >>> 32#64)) ≠ x >>> 32#64) →
      truncate 32 (zeroExtend 128 x >>> 32#128) = truncate 32 (x >>> 32#64)

theorem multiuse_select_thm (e : IntW 1) :
  mul (select e (const? 64 64) (const? 64 0)) (sub (select e (const? 64 64) (const? 64 0)) (zext 64 e)) ⊑
    select e (const? 64 4032) (const? 64 0)

theorem t2_proof : t2_before ⊑ t2_after

theorem in_constant_mone_vary_invmask_proof : in_constant_mone_vary_invmask_before ⊑ in_constant_mone_vary_invmask_after

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 add_five (x : BitVec w) : (x + x) + (x + x) + x = x + x + x + x + x

theorem Predicate.denote_of_eval {w : Nat} {p : Predicate} {vars : List (BitVec w)}
    (heval : (p.eval (vars.map .ofBitVecSext) w = false)) : p.denote w vars

theorem p0_scalar_urem_by_const_proof : p0_scalar_urem_by_const_before ⊑ p0_scalar_urem_by_const_after

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

theorem e_986 :
    5 *  ~~~z + 4 *  ~~~t - 1 *  ~~~(z &&&  ~~~z) - 9 *  ~~~(z ||| t) - 5 *  ~~~(z |||  ~~~t) - 4 * (z &&&  ~~~t) + 1 * (z &&& t) =  - 1 *  ~~~(z &&& t)

theorem div_bit_set_proof : div_bit_set_before ⊑ div_bit_set_after

theorem ashr_exact_add_negative_shift_negative_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ BitVec.ofInt 32 (-2) >>> (x + -1#32) <<< (x + -1#32) ≠ BitVec.ofInt 32 (-2) ∨ x + -1#32 ≥ ↑32) →
    ¬(True ∧ BitVec.ofInt 32 (-4) >>> x <<< x ≠ BitVec.ofInt 32 (-4) ∨ x ≥ ↑32) →
      (BitVec.ofInt 32 (-2)).sshiftRight' (x + -1#32) = (BitVec.ofInt 32 (-4)).sshiftRight' x

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

theorem ashr_overshift_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(15#32 ≥ ↑32 ∨ 17#32 ≥ ↑32) → ¬31#32 ≥ ↑32 → (x.sshiftRight' 15#32).sshiftRight' 17#32 = x.sshiftRight' 31#32

theorem main1_proof : main1_before ⊑ main1_after

theorem ashr_mul_sign_bits_proof : ashr_mul_sign_bits_before ⊑ ashr_mul_sign_bits_after

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

theorem e_1377 :
     - 3 * (z ||| t) - 1 *  ~~~(z &&&  ~~~z) - 3 *  ~~~z - 1 *  ~~~(z &&& t) - 11 * t + 1 *  ~~~(z &&&  ~~~t) + 3 * (z |||  ~~~t) + 1 *  ~~~(z ||| t) + 18 *  ~~~(z |||  ~~~t) + 1 * (z &&&  ~~~t) =  - 1 * z - 10 * (z &&& t)

theorem and_not_or_or_not_or_xor_commute4_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32),
  ¬((x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true ∨
        (x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true) →
    ¬(x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true →
      (42#32).sdiv x_2 &&& ((x_1 ||| x) ^^^ -1#32) ||

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

theorem and_not_or_or_not_or_xor_commute4_proof : and_not_or_or_not_or_xor_commute4_before ⊑ and_not_or_or_not_or_xor_commute4_after

theorem or_not_xor_common_op_commute7_proof : or_not_xor_common_op_commute7_before ⊑ or_not_xor_common_op_commute7_after

@[simp]
theorem Term.toBV_setWidth {wenv : WidthExpr.Env wcard}
    {tctx : Term.Ctx wcard tcard}
    (benv : Term.BoolEnv bcard)
    (tenv : tctx.Env wenv) (a : Term bcard ncard icard pcard tctx (.bv w)) (v : WidthExpr wcard) :
  Term.toBV benv nenv ienv penv tenv (.setWidth a v) = (a.toBV benv nenv ienv penv tenv).zeroExtend (v.toNat wenv)

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

theorem add_const_const_sub_proof : add_const_const_sub_before ⊑ add_const_const_sub_after

theorem n3_constmask_samemask_proof : n3_constmask_samemask_before ⊑ n3_constmask_samemask_after

theorem n7_thm (e e_1 : IntW 8) :
  sub e_1 (LLVM.and (sub (const? 8 0) e) e_1) ⊑ LLVM.and e_1 (add e (const? 8 (-1)))

theorem t6_ugt_sgt_128_proof : t6_ugt_sgt_128_before ⊑ t6_ugt_sgt_128_after

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

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

theorem lshrult_03_08_exact_thm (e : IntW 4) :
  icmp IntPred.ult (lshr e (const? 4 3) { «exact» := true }) (const? 4 (-8)) ⊑ const? 1 1

theorem select_icmp_x_and_8_ne_0_y_or_8_thm (e : IntW 64) (e_1 : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e_1 (const? 32 8)) (const? 32 0)) (LLVM.or e (const? 64 8)) e ⊑
    LLVM.or e (zext 64 (LLVM.xor (LLVM.and e_1 (const? 32 8)) (const? 32 8)) { «nneg» := true })

theorem main7e_logical_thm.extracted_1._2 : ∀ (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 → 1#32 = zeroExtend 32 1#1

theorem or_and_not_constant_commute0_proof : or_and_not_constant_commute0_before ⊑ or_and_not_constant_commute0_after

theorem and_lshr_and_proof : and_lshr_and_before ⊑ and_lshr_and_after

theorem test_mul__nuw_is_safe_thm.extracted_1._3 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 268435457#32 == 268435456#32) = 1#1 → True ∧ (x &&& 268435457#32).umulOverflow 9#32 = true → False

theorem test_add_nsw__all_are_safe_proof : test_add_nsw__all_are_safe_before ⊑ test_add_nsw__all_are_safe_after

theorem e_1207 :
     - 6 * (z ^^^ t) + 2 *  ~~~z - 11 * z - 11 *  ~~~(z &&& t) + 3 *  ~~~(z &&&  ~~~t) + 6 *  ~~~(z ||| t) + 10 *  ~~~(z |||  ~~~t) + 26 * (z &&&  ~~~t) + 6 * (z &&& t) =  - 2 * (z ||| t)

theorem icmp_sgt11_thm (e : IntW 8) :
  icmp IntPred.sgt (shl e (const? 8 7) { «nsw» := true, «nuw» := false }) (const? 8 (-2)) ⊑
    icmp IntPred.sgt e (const? 8 (-1))

theorem shift_xor_multiuse_cmp_or_proof : shift_xor_multiuse_cmp_or_before ⊑ shift_xor_multiuse_cmp_or_after

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

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

theorem bools_multi_uses2_logical_thm.extracted_1._6 : ∀ (x x_1 : BitVec 1),
  x_1 ^^^ 1#1 = 1#1 → ¬x_1 = 1#1 → ¬x = 1#1 → 0#1 = 1#1 → x + 0#1 = 0#1

theorem or_disjoint_with_xor_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ (x_1 &&& x != 0) = true) → (x_1 ||| x) ^^^ x_1 = x

theorem positive_biggerlshr_shlnuwnsw_proof : positive_biggerlshr_shlnuwnsw_before ⊑ positive_biggerlshr_shlnuwnsw_after

theorem t9_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ (0#8).ssubOverflow x = true) → ofBool (0#8 - x != x) = ofBool (x != 0#8)

theorem test10_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(6#8 ≥ ↑8 ∨ 6#8 ≥ ↑8) →
    ¬(30#32 ≥ ↑32 ∨ True ∧ x <<< 30#32 >>> 30#32 <<< 30#32 ≠ x <<< 30#32 ∨ 30#32 ≥ ↑32) →
      signExtend 32 ((truncate 8 x <<< 6#8).sshiftRight' 6#8) = (x <<< 30#32).sshiftRight' 30#32

theorem zext_sext_eq_known_nonneg_proof : zext_sext_eq_known_nonneg_before ⊑ zext_sext_eq_known_nonneg_after

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

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_2_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_2_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_2_after

theorem select_icmp_eq_pow2_thm (e : IntW 8) :
  select (icmp IntPred.eq (LLVM.and e (const? 8 4)) (const? 8 0)) e (LLVM.xor e (const? 8 4)) ⊑
    LLVM.and e (const? 8 (-5))

theorem urem_i1_is_zero_proof : urem_i1_is_zero_before ⊑ urem_i1_is_zero_after

theorem t4_ugt_slt_65536_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.ugt e_2 (const? 32 65535)) (select (icmp IntPred.slt e_2 (const? 32 65536)) e_1 e)
      e_2 ⊑
    select (icmp IntPred.sgt e_2 (const? 32 65535)) e
      (select (icmp IntPred.slt e_2 (const? 32 0)) e_1 e_2)

theorem shl_xor_lshr_thm.extracted_1._2 : ∀ (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 → (x_2 <<< x_1 ^^^ x) >>> x_1 = x >>> x_1 ^^^ x_2

theorem test6_thm (e : IntW 55) : mul (shl e (const? 55 1)) (const? 55 3) ⊑ mul e (const? 55 6)

theorem scalar_i32_shl_and_negC_slt_proof : scalar_i32_shl_and_negC_slt_before ⊑ scalar_i32_shl_and_negC_slt_after

@[simp]
theorem eval_repeatForever_eq_self (b : Bool) : (FSM.repeatForever b).eval env = fun _ => b

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

theorem shl_bad_sub_i32_thm (e : IntW 32) :
  shl (const? 32 1) (sub (const? 32 32) e) ⊑
    shl (const? 32 1) (sub (const? 32 32) e) { «nsw» := false, «nuw» := true }

theorem 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 t1_proof : t1_before ⊑ t1_after
</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_appendInr (lets : Lets d Γ_in eff Γ_out) (e : Expr d Γ_out _ ty₁)
    (v : Var Γ_out ty₂):
    getPureExpr (lets.var e) v.appendInr
    = (fun ⟨_, w, e'⟩ => ⟨_, w,  e'.changeVars <| e.contextHom⟩) <$> (getPureExpr lets v) :=
</target_theorem>

