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>
String in Init.Prelude
BEq in Init.Prelude
ite in Init.Prelude
Repr in Init.Data.Repr
List in Init.Prelude
Vector in Init.Data.Vector.Basic
Bool in Init.Prelude
Int in Init.Data.Int.Basic
bool in Init.Control.Basic
Computation in Mathlib.Data.Seq.Computation
DecidableEq in Init.Prelude
Lean.ToExpr in Lean.ToExpr
Option in Init.Prelude
Nat in Init.Prelude
AList in Mathlib.Data.List.AList
StateT in Init.Control.State
Unit in Init.Prelude
AList.insert in Mathlib.Data.List.AList
Valuation.map in Mathlib.RingTheory.Valuation.Basic
Valuation.mk in Mathlib.RingTheory.Valuation.Basic
cast in Init.Prelude
Id in Init.Control.Id
List.map in Init.Prelude
PUnit in Init.Prelude
Pure in Init.Prelude
LawfulMonad in Init.Control.Lawful.Basic
id in Init.Prelude
liftM in Init.Prelude
Fin in Init.Prelude
Inhabited in Init.Prelude
BitVec in Init.Prelude

syntax "neg" : MLIR.Pretty.uniform_op

syntax "llvm.and"     : MLIR.Pretty.uniform_op

syntax "llvm.ashr"    : MLIR.Pretty.exact_op

syntax "llvm.add"     : MLIR.Pretty.overflow_op

syntax "llvm.return"  : MLIR.Pretty.uniform_op

notation:50 x " ≤ₛ " y => BitVec.sle x y

notation:50 x " >ᵤ " y => BitVec.ult y x

notation:50 x " ≥ᵤ " y => BitVec.ule y x

notation:50 x " <ᵤ " y => BitVec.ult x y

notation:50 x " ≥ₛ " y => BitVec.sle y x

notation:50 x " <ₛ " y => BitVec.slt x y

notation:50 x " >ₛ " y => BitVec.slt y x

notation:50 x " ≤ᵤ " y => BitVec.ule x y

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

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

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

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

macro_rules
  | `(mlir_op| $resName:mlir_op_operand = $name:InstCombine.cmp_op_name $x, $y $[: $t]?) => do
    let some opName := extractOpName name.raw
      | Macro.throwUnsupported
    let t ← t.getDM `(mlir_type| _)
    `(mlir_op| $resName:mlir_op_operand = $opName ($x, $y) : ($t, $t) -> (i1) )

macro_rules
  | `(mlir_op| $resName:mlir_op_operand = $name:InstCombine.int_cast_op $x : $t to $t') => do
    let some opName := extractOpName name.raw
      | Macro.throwUnsupported
    `(mlir_op| $resName:mlir_op_operand = $opName ($x) : ($t) -> $t')

macro_rules
  | `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant( $x $[: $inner_type]?)
      $[: $outer_type]? ) => do
       
      let outer_type ← outer_type.getDM `(mlir_type| _)
      let inner_type := inner_type.getD outer_type
      `(mlir_op| $res:mlir_op_operand = "llvm.mlir.constant"()
          {value = $x:neg_num : $inner_type} : () -> ($outer_type) )
  | `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant( ${ $x:term }) $[: $t]?) => do
      let t ← t.getDM `(mlir_type| _)
      let x ← `(MLIR.AST.AttrValue.int $x [mlir_type| $t])
      `(mlir_op| $res:mlir_op_operand = "llvm.mlir.constant"() {value = $$($x) } : () -> ($t) )

macro_rules
  | `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant (true) $[: $t]?) =>
      `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant (1 : i1) : i1)
  | `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant (false) $[: $t]?) =>
      `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant (0 : i1) : i1)
  | `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant $x $[: $t]?) =>
      `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant($x $[: $t]?) $[: $t]?)
  | `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant ${ $x:term } $[: $t]?) =>
      `(mlir_op| $res:mlir_op_operand = llvm.mlir.constant($$($x) $[: $t]?) $[: $t]?)

macro_rules
  | `(mlir_op| $res:mlir_op_operand = llvm.icmp $p $x, $y $[: $t]?) => do
    let t ← t.getDM `(mlir_type| _)
    match p.getString with
      | "eq" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.eq" ($x, $y) : ($t, $t) -> (i1))
      | "ne" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.ne" ($x, $y) : ($t, $t) -> (i1))
      | "slt" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.slt" ($x, $y) : ($t, $t) -> (i1))
      | "sle" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.sle" ($x, $y) : ($t, $t) -> (i1))
      | "sgt" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.sgt" ($x, $y) : ($t, $t) -> (i1))
      | "sge" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.sge" ($x, $y) : ($t, $t) -> (i1))
      | "ult" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.ult" ($x, $y) : ($t, $t) -> (i1))
      | "ule" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.ule" ($x, $y) : ($t, $t) -> (i1))
      | "ugt" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.ugt" ($x, $y) : ($t, $t) -> (i1))
      | "uge" => `(mlir_op| $res:mlir_op_operand = "llvm.icmp.uge" ($x, $y) : ($t, $t) -> (i1))
      | _ => Macro.throwErrorAt p s!"unexpected predicate {p.getString}"

macro_rules
  | `(mlir_op| $res:mlir_op_operand = llvm.select $c, $x, $y $[: $t]?) => do
    let t ← t.getDM `(mlir_type| _)
    `(mlir_op| $res:mlir_op_operand = "llvm.select" ($c, $x, $y) : (i1, $t, $t) -> ($t))

structure Zipper (Γ_in : Ctxt d.Ty) (eff : EffectKind) (tys : List d.Ty) where
   
  {Γ_mid : Ctxt d.Ty}
   
  top : Lets d Γ_in eff Γ_mid
   
  bot : Com d Γ_mid eff tys

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

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

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

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

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

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

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 β

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

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

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

def matchArgRes (lets : Lets d Γ_in eff Γ_out)
    (matchLets : Lets d Δ_in .pure Δ_out)
    (vs : HVector Γ_out.Var ts)
    (ws : HVector Δ_out.Var ts) :
    Option (MatchArgResult lets matchLets vs ws ∅) := do
  (matchArg lets matchLets vs ws ∅).attach.map fun ⟨⟨_, _⟩, h⟩ => .mk h

def matchArg [DecidableEq d.Op]
    (lets : Lets d Γ_in eff Γ_out) (matchLets : Lets d Δ_in .pure Δ_out) :
    {l : List d.Ty} → HVector (Var Γ_out) l → HVector (Var Δ_out) l →
    MatchVar Δ_in Γ_out
  | _, .nil, .nil => return
  | t::l, .cons vₗ vsₗ, .cons vᵣ vsᵣ => do
      matchVar (t := t) lets vₗ matchLets vᵣ
      matchArg lets matchLets vsₗ vsᵣ
  termination_by l => (sizeOf matchLets, l.length + 1)

def matchVar {Γ_in Γ_out Δ_in Δ_out : Ctxt d.Ty} {t : d.Ty} [DecidableEq d.Op]
    (lets : Lets d Γ_in eff Γ_out) (v : Var Γ_out t) :
    (matchLets : Lets d Δ_in .pure Δ_out) →
    (w : Var Δ_out t) →
    MatchVar Δ_in Γ_out
   
  | @Lets.var _ _ _ _ Δ_out ts matchLets matchExpr, w => by admit /- proof elided -/
      | right w =>
        exact matchVar lets v matchLets w
      | left w => exact do
        let ⟨ts', w', ie⟩ ← lets.getPureExpr v
        if hs : ∃ h : ie.op = matchExpr.op, ie.regArgs = (h ▸ matchExpr.regArgs) then
          have hts : Ctxt.ofList ts' = ts := by admit /- proof elided -/

abbrev MatchVar (Δ Γ : Ctxt d.Ty)  := MatchVarM Δ Γ Unit

abbrev MatchVarM (Δ Γ : Ctxt d.Ty) := (StateT (Mapping Δ Γ) Option)

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

def MatchVarM.unifyVars {Δ Γ : Ctxt d.Ty} (v : Δ.Var t) (w : Γ.Var t) : MatchVar Δ Γ :=
  fun ma =>
    match ma.lookup ⟨_, v⟩ with
    | some v =>
      if v = w then
        some ((), ma)
      else
        none
    | none =>
      some ((), AList.insert ⟨_, v⟩ w ma)

@[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 -/

@[match_pattern]
def last (Γ : Ctxt Ty) (t : Ty) : Ctxt.Var (Ctxt.cons t Γ) t :=
  ⟨0, by admit /- proof elided -/
  ⟩

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

def MatchArgResult := { mapOut : Mapping _ _ //
  ∃ (mapIn' mapOut' : Mapping _ _),
    mapIn.entries ⊆ mapIn'.entries
    ∧ mapOut'.entries ⊆ mapOut.entries
    ∧ matchArg lets matchLets vs ws mapIn' = some ((), mapOut') }

def toHom (d : Diff Γ₁ Γ₂) : Hom Γ₁ Γ₂ :=
  fun _ v => ⟨v.val + d.val, d.property v.property⟩

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

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 Expr.pdenoteOp :
    Expr d Γ .pure ty → Γ.Valuation → (HVector toType ty) :=
  Expr.denoteOp

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

def Expr.denoteOp (e : Expr d Γ eff ty) (V : Γ.Valuation) :
    eff.toMonad d.m (HVector toType ty) :=
  EffectKind.liftEffect e.eff_le <| cast (by admit /- proof elided -/
  ) <|
    DialectDenote.denote e.op (e.args.map V) e.regArgs.denote

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

def Lets.denote [DialectSignature d] [DialectDenote d] {Γ₂}
    (lets : Lets d Γ₁ eff Γ₂) (V : Valuation Γ₁) : (eff.toMonad d.m <| Valuation Γ₂) :=
  match lets with
  | .nil          => return V
  | .var lets' e  => lets'.denote V >>= e.denote

def sig          := Signature.sig ∘ s.signature

structure Signature (Ty : Type) where
  mkEffectful ::
  sig         : List Ty
  regSig      : RegionSignature Ty
  returnTypes : List Ty
  effectKind  : EffectKind := .pure

class DialectSignature (d : Dialect) where
  signature : d.Op → Signature d.Ty

def regSig       := Signature.regSig ∘ s.signature

abbrev RegionSignature Ty := List (Ctxt Ty × List Ty)

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 effectKind   := Signature.effectKind ∘ s.signature

def returnTypes  := Signature.returnTypes ∘ s.signature

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

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

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

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

def HVector.denote :
    {l : RegionSignature d.Ty} → (T : HVector (fun t => Com d t.1 .impure t.2) l) →
    HVector (fun t => t.1.Valuation → EffectKind.impure.toMonad d.m (HVector toType t.2)) l
  | _, .nil => HVector.nil
  | _, .cons v vs => HVector.cons (v.denote) (HVector.denote vs)

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

def RegionSignature.map (f : Ty → Ty') : RegionSignature Ty → RegionSignature Ty' :=
  List.map fun ⟨Γ, ty⟩ => (Γ.map f, ty.map f)

def Signature.map (f : Ty → Ty') : Signature Ty → Signature Ty' :=
  fun sig => {
    sig         := sig.sig.map f
    regSig      := sig.regSig.map f
    returnTypes := sig.returnTypes.map f
  }

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

def Expr.denote {ty} (e : Expr d Γ eff ty) (V : Valuation Γ) :
    eff.toMonad d.m (e.outContext.Valuation) :=
  match e with
  | ⟨op, ty_eq, heff, args, regArgs⟩ => do
      let argsDenote := args.map V
      let val ← EffectKind.liftEffect heff <| DialectDenote.denote op argsDenote regArgs.denote
      return (val ++ V).cast (by admit /- proof elided -/
      )

def Expr.op {Γ : Ctxt d.Ty} {eff : EffectKind} {ty} (e : Expr d Γ eff ty) : d.Op :=
  Expr.casesOn e (fun op _ _ _ _ => op)

def Com.outContext {Γ} : Com d Γ eff ts → Ctxt d.Ty :=
  Com.rec' (motive := fun _ => Ctxt d.Ty)
    (@fun Γ _ => Γ) 
    (fun _ _ r => r)

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

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

abbrev Expr.outContext (_ : Expr d Γ eff ts) : Ctxt d.Ty :=
  ts ++ Γ

def liftEffect [Pure m] {e1 e2 : EffectKind} {α : Type}
    (hle : e1 ≤ e2) (v1 : e1.toMonad m α) : e2.toMonad m α :=
  match e1, e2, hle with
    | .pure, .pure, _ | .impure, .impure, _ => v1
    | .pure, .impure, _ => Pure.pure v1

def toMonad (e : EffectKind) (m : Type → Type) : Type → Type :=
  match e with
  | pure => Id
  | impure => m

def Com.denote : Com d Γ eff ty → (Γv : Valuation Γ) →
    eff.toMonad d.m (HVector toType ty)
  | .rets vs, Γv     => pure (vs.map Γv)
  | .var e body, V => e.denote V >>= body.denote

def Com.ty : Com d Γ eff [t] → d.Ty := fun _ => t

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)

abbrev Regions (regSig : RegionSignature d.Ty) : Type :=
  HVector (fun t => Com d t.1 .impure t.2) regSig

def FlatCom.denoteLets (flatCom : FlatCom d Γ eff Γ_out t) (Γv : Γ.Valuation) :
    eff.toMonad d.m <| Γ_out.Valuation :=
  flatCom.lets.denote Γv

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

def Com.denoteLets : (com : Com d Γ eff ty) → (Γv : Valuation Γ) →
    eff.toMonad d.m (com.outContext.Valuation)
  | .rets _, V => pure V
  | .var e body, V =>
      e.denote V >>= body.denoteLets >>= fun V =>
        return V.cast (by admit /- proof elided -/
        )

def cast (h_eq : ty₁ = ty₂) : Γ.Var ty₁ → Γ.Var ty₂
  | ⟨i, h⟩ => ⟨i, h_eq ▸ h⟩

def cast (h₁ : Γ = Γ') (h₂ : Δ = Δ') : Diff Γ Δ → Diff Γ' Δ'
  | ⟨n, h⟩ => ⟨n, by admit /- proof elided -/
  ⟩

def toCom (zip : Zipper d Γ_in eff ty) : Com d Γ_in eff ty :=
  go zip.top zip.bot
  where
    go : {Γ_mid : _} → Lets d Γ_in eff Γ_mid → Com d Γ_mid eff ty → Com d Γ_in eff ty
      | _, .nil, com          => com
      | _, .var body e, com  => go body (.var e com)

def denote (zip : Zipper d Γ_in eff tys) (V_in : Valuation Γ_in) :
    eff.toMonad d.m (HVector toType tys) :=
  (zip.top.denote V_in) >>= zip.bot.denote

def Expr.returnVars (e : Expr d Γ eff tys) : HVector e.outContext.Var tys :=
  .ofFn _ _ <| fun i => (Var.ofFin i).appendInl

def ofFin (i : Fin Γ.length) : Γ.Var (Γ[i]) :=
  ⟨i.val, by admit /- proof elided -/
  ⟩

def Com.returnVars : (com : Com d Γ eff ts) → HVector (Var com.outContext) ts
  | .rets vs => vs
  | .var _ body => body.returnVars

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

def MatchVarResult.isTotal_of
    (map : MatchVarResult lets v matchLets w mapIn)
    (hvars : ∀ t (v : Var Δ_in t), ⟨t, v⟩ ∈ matchLets.vars w) :
    map.val.IsTotal :=

def MatchArgResult.isTotal_of
    (map : MatchArgResult lets matchLets vs ws mapIn)
    (hvars : ∀ t (v : Var Δ_in t), ⟨t, v⟩ ∈ matchLets.varsOfVec ws) :
    map.val.IsTotal :=

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

variable
  {Γ_in Γ_out Δ_in Δ_out : Ctxt d.Ty}
  {lets : Lets d Γ_in eff Γ_out}
  {matchTy}
  {v : Var Γ_out matchTy}
  {matchLets : Lets d Δ_in .pure Δ_out}
  {w : Var Δ_out matchTy}
in

def Valuation.comap {Γi Γo : Ctxt Ty} (Γiv: Γi.Valuation) (hom : Ctxt.Hom Γo Γi) : Γo.Valuation :=
  fun _to vo => Γiv (hom vo)

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)

def MatchVarResult := { mapOut : Mapping _ _ //
  ∃ (mapIn' mapOut' : Mapping _ _),
    mapIn.entries ⊆ mapIn'.entries
    ∧ mapOut'.entries ⊆ mapOut.entries
    ∧ matchVar lets v matchLets w mapIn' = some ((), mapOut') }

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

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

def eqvVarLeft  :
    MatchVarResult lets v (.var matchLets matchExpr) w.appendInr ma
    ≃ MatchVarResult lets v matchLets w ma where
  toFun := fun ⟨x, h⟩ => ⟨x, by admit /- proof elided -/
  ⟩
  invFun := fun ⟨x, h⟩ => ⟨x, by admit /- proof elided -/
  ⟩

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⟩

def Com.changeVars : Com d Γ eff ty →
    (varsMap : Γ.Hom Γ') →
    Com d Γ' eff ty
  |  .rets e => fun varsMap => .rets (e.map varsMap)
  |  .var e body => fun varsMap => .var (e.changeVars varsMap)
      (body.changeVars (fun _ v => varsMap.append v))

def Hom.append {ζ : Ctxt Ty} (f : Γ.Hom Δ) : Hom (ζ ++ Γ) (ζ ++ Δ) :=
  fun _ => Var.appendCases
    (fun v => v.appendInl)
    (fun v => (f v).appendInr)

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

def insertPureCom (zip : Zipper d Γ_in eff ty)
    (vs : HVector zip.Γ_mid.Var newTy)
    (newCom : Com d zip.Γ_mid .pure newTy) : Zipper d Γ_in eff ty :=
  zip.insertCom vs (newCom.castPureToEff eff)

def insertCom (zip : Zipper d Γ_in eff ty)
    (vs : HVector zip.Γ_mid.Var newTy) (newCom : Com d zip.Γ_mid eff newTy) :
    Zipper d Γ_in eff ty :=
  let top := zip.top.addComToEnd newCom
  
  let bot := zip.bot.changeVars <| newCom.outContextHom.with vs newCom.returnVars
  
  
  { top, bot }

def Hom.with [DecidableEq Ty] {Γ₁ Γ₂ : Ctxt Ty} (f : Γ₁.Hom Γ₂) {ts}
    (v₁ : HVector Γ₁.Var ts) (v₂ : HVector Γ₂.Var ts) : Γ₁.Hom Γ₂ :=
  fun _ w =>
    match v₁.idxOf? w with
    | none => f w
    | some ⟨i, h⟩ => (v₂.get i).cast h

def Com.outContextHom (com : Com d Γ eff t) : Γ.Hom com.outContext :=
  com.outContextDiff.toHom

def Com.outContextDiff (com : Com d Γ eff ts) : Γ.Diff com.outContext :=
  ⟨com.bvars, by admit /- proof elided -/
      ⟩

@[simp, grind=] def Expr.bvars (e : Expr d Γ eff Δ) : Nat :=
  (DialectSignature.returnTypes e.op).length

def Com.bvars : Com d Γ eff t → Nat :=
  Com.rec'
           (fun _ => 0)
      (fun e _body bodySize => e.bvars + bodySize)

def castCtxt (h_eq : Γ = Δ) : Γ.Var ty → Δ.Var ty
  | ⟨i, h⟩ => ⟨i, h_eq ▸ h⟩

def Com.castPureToEff (eff : EffectKind) : Com d Γ .pure t → Com d Γ eff t :=
  changeEffect (EffectKind.pure_le eff)

def Com.changeEffect {eff₁ eff₂ : EffectKind} (h : eff₁ ≤ eff₂) :
    Com d Γ eff₁ t → Com d Γ eff₂ t := fun com =>
  Com.rec' (motive := @fun Γ _ => eff₁ ≤ eff₂ → Com d Γ eff₂ t)
            (fun v _h               => rets v)
      (fun e _body castBody h => var (e.changeEffect h) (castBody h))
    com h

def Expr.changeEffect {eff₁ eff₂ : EffectKind} (h : eff₁ ≤ eff₂) :
    Expr d Γ eff₁ t → Expr d Γ eff₂ t
  | Expr.mk op ty_eq eff_le args regArgs =>
    have heff : DialectSignature.effectKind op ≤ eff₂ := by admit /- proof elided -/

def com := mkCom (d := InstCombine.MetaLLVM 0) bb0 |>.toOption |>.get (by admit /- proof elided -/
)

def bb0 : Region 0 := [mlir_region|
{
  ^bb0(%arg0: i32):
    %0 = llvm.mlir.constant(8) : i32
    %1 = llvm.mlir.constant(31) : i32
    %2 = llvm.ashr %arg0, %1 : i32
    %3 = llvm.and %2, %0 : i32
    %4 = llvm.add %3, %2 : i32
    llvm.return %4 : i32
  }]

structure Region where
  (name: String)
  (args: List <| TypedSSAVal φ)
  (ops: List Op)

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

@[deprecated "Use `LLVM.Ty` instead" (since:="2025-04-30")] abbrev Ty := LLVM.Ty

@[deprecated "Use `LLVM.Op` instead" (since:="2025-04-30")] abbrev Op := LLVM.Op

inductive MOp (φ : Nat) : Type
  | unary   (w : Width φ) (op : MOp.UnaryOp φ) :  MOp φ
  | binary  (w : Width φ) (op : MOp.BinaryOp) :  MOp φ
  | select  (w : Width φ) : MOp φ
  | icmp    (c : IntPred) (w : Width φ) : MOp φ
   
  | const (w : Width φ) (val : ℤ) : MOp φ
deriving Repr, DecidableEq, Inhabited, Lean.ToExpr

@[match_pattern] abbrev binary (w : Nat) (op : MOp.BinaryOp) : LLVM.Op :=
  MOp.binary (.concrete w) op

inductive MOp.BinaryOp : Type
  | and
  | or   (disjoint : DisjointFlag := {disjoint := false} )
  | xor
  | shl  (nswnuw : NoWrapFlags := {nsw := false, nuw := false} )
  | lshr (exact : ExactFlag := {exact := false} )
  | ashr (exact : ExactFlag := {exact := false} )
  | urem
  | srem
  | add  (nswnuw : NoWrapFlags := {nsw := false, nuw := false} )
  | mul  (nswnuw : NoWrapFlags := {nsw := false, nuw := false} )
  | sub  (nswnuw : NoWrapFlags := {nsw := false, nuw := false} )
  | sdiv (exact : ExactFlag := {exact := false} )
  | udiv (exact : ExactFlag := {exact := false} )
deriving DecidableEq, Inhabited, Lean.ToExpr

def LLVM : Dialect where
  Op := MOp 0
  Ty := MTy 0

inductive MTy (φ : Nat)
  | bitvec (w : Width φ) : MTy φ
  deriving DecidableEq, Inhabited, Lean.ToExpr

abbrev Width φ := ConcreteOrMVar Nat φ

inductive ConcreteOrMVar (α : Type u) (φ : Nat)
  | concrete (a : α)
  | mvar (i : Fin φ)
  deriving DecidableEq, Repr, Inhabited, Lean.ToExpr

@[match_pattern] abbrev const (w : Nat) (val : ℤ) : LLVM.Op        := MOp.const (.concrete w) val

inductive MOp.UnaryOp (φ : Nat) : Type
  | neg
  | not
  | copy
  | freeze
  | trunc (w' : Width φ) (noWrapFlags : NoWrapFlags := {nsw := false, nuw := false} )
  | zext  (w' : Width φ) (nneg : NonNegFlag := {nneg := false} )
  | sext  (w' : Width φ)
deriving Repr, DecidableEq, Inhabited, Lean.ToExpr

@[simp_llvm_option]
def select {w : Nat} (c? : IntW 1) (x? y? : IntW w ) : IntW w := do
  let c ← c?
  if c = 1#1 then x? else y?

def IntW w := PoisonOr <| BitVec w

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

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

@[simp_llvm]
def icmp? {w : Nat} (c : IntPred) (x y : BitVec w) : IntW 1 :=
  .value ↑(icmp' c x y)

inductive IntPred where
  | eq
  | ne
  | ugt
  | uge
  | ult
  | ule
  | sgt
  | sge
  | slt
  | sle
deriving Inhabited, DecidableEq, Repr, Lean.ToExpr

@[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 mkCom [TransformTy d φ] [TransformExpr d φ] [TransformReturn d φ]
  (reg : MLIR.AST.Region φ) :
  ExceptM d (Σ (Γ : Ctxt d.Ty) (eff : EffectKind) (ty : _), Com d Γ eff ty) :=
  match reg.ops with
  | [] => throw <| .generic "Ill-formed region (empty)"
  | coms => BuilderM.runWithEmptyMapping <| do
    let Γ ← declareBindings ∅ reg.args
    let com ← mkComHelper Γ coms
    return ⟨Γ, com⟩

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

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

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

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

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

@[tactic bvAutomataGen]
def evalBvAutomataCircuit : Tactic := fun
| `(tactic| bv_automata_gen $[$cfg]?) => do
  let cfg ← elabBvAutomataCircuitConfig (mkOptionalNode cfg)
  let g ← getMainGoal
  g.withContext do
    let gs ← reflectUniversalWidthBVs g cfg
    replaceMainGoal gs
    match gs  with
    | [] => return ()
    | [g] => do
      trace[Bits.Frontend] m!"goal being decided via boolean reflection: {indentD g}"
      evalDecideCore `bv_automata_circuit (cfg := { native := true : Parser.Tactic.DecideConfig })
    | _gs => throwError m!"expected single goal after reflecting, found multiple goals. quitting"
| _ => throwUnsupportedSyntax

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

def narrow_zext_add_after := [llvm|
{
^0(%arg42 : i16, %arg43 : i32):
  %0 = llvm.trunc %arg43 : i32 to i16
  %1 = llvm.add %arg42, %0 : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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

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

def bool_eq0_before := [llvm|
{
^0(%arg33 : i64):
  %0 = llvm.mlir.constant(0) : i64
  %1 = llvm.mlir.constant(1) : i64
  %2 = llvm.mlir.constant(false) : i1
  %3 = llvm.icmp "sgt" %arg33, %0 : i64
  %4 = llvm.icmp "eq" %arg33, %1 : i64
  %5 = llvm.icmp "eq" %4, %2 : i1
  %6 = llvm.and %3, %5 : i1
  "llvm.return"(%6) : (i1) -> ()
}
]

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

def toCons (d : Diff Γ₁ Γ₂) : Diff Γ₁ (Γ₂.cons t) :=
  ⟨d.val + 1, by admit /- proof elided -/
  ⟩

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

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

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

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

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

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

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

RV64.sltu in RISCV.Instructions

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

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

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

def RawCNFA.transSet (m : RawCNFA A) (ss : Std.HashSet State) (a : A) : Std.HashSet State :=
  ss.fold (init := ∅) fun ss' s =>
    ss'.insertMany $ m.trans.getD (s, a) ∅

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

def or_basic_before := [llvm|
{
^0(%arg15 : i16):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.mlir.constant(-256 : i16) : i16
  %2 = llvm.mlir.constant(17664 : i16) : i16
  %3 = llvm.trunc %arg15 : i16 to i8
  %4 = llvm.icmp "ne" %3, %0 : i8
  %5 = llvm.and %arg15, %1 : i16
  %6 = llvm.icmp "ne" %5, %2 : i16
  %7 = llvm.or %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def test_add_zero_lhs_LHS := [mod_arith q, hq| {
  ^bb0(%x : !R):
    %zero = mod_arith.constant 0 : !R
    %add = mod_arith.add %zero, %x : !R
    return %add : !R
}]

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

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

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

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

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

instance : Coe String (AttrValue φ) where
  coe (s: String) := AttrValue.str s

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

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

def test_before := [llvm|
{
^0(%arg0 : i64):
  %0 = llvm.trunc %arg0 : i64 to i32
  %1 = llvm.zext %0 : i32 to i64
  "llvm.return"(%1) : (i64) -> ()
}
]

def icmp_ne_and_pow2_lshr_pow2_before := [llvm|
{
^0(%arg41 : i32):
  %0 = llvm.mlir.constant(8 : i32) : i32
  %1 = llvm.mlir.constant(4 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.lshr %0, %arg41 : 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) -> ()
}
]

@[inline]
def RawCNFA.addSink (m : RawCNFA A) : RawCNFA A := m.createSink.2

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 ugt_or_not_min_before := [llvm|
{
^0(%arg14 : i8, %arg15 : i8):
  %0 = llvm.mlir.constant(0 : i8) : i8
  %1 = llvm.icmp "ugt" %arg14, %arg15 : i8
  %2 = llvm.icmp "ne" %arg14, %0 : i8
  %3 = llvm.or %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

Prod.mk in Init.Prelude

def llvm_or_lower_riscv_disjoint_64 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := or_llvm_disjoint_64
  rhs := or_riscv_64

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

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

def BoolBinaryRelationKind.toSmtLib : BoolBinaryRelationKind → SexprPBV.BoolBinaryRelationKind
| .eq => .eq

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

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

def uadd_sat_flipped_wrong_bounds_after := [llvm|
{
^0(%arg96 : i32):
  %0 = llvm.mlir.constant(-13 : i32) : i32
  %1 = llvm.mlir.constant(9 : i32) : i32
  %2 = llvm.mlir.constant(-1 : i32) : i32
  %3 = llvm.icmp "ugt" %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 test_shl_nuw_nsw__nuw_is_safe_before := [llvm|
{
^0(%arg82 : i32, %arg83 : i64):
  %0 = llvm.mlir.constant(1073741822 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(0 : i32) : i32
  %3 = llvm.and %arg82, %0 : i32
  %4 = llvm.shl %3, %1 overflow<nsw,nuw> : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.icmp "eq" %3, %2 : i32
  %7 = llvm.ashr %arg83, %5 : i64
  %8 = "llvm.select"(%6, %arg83, %7) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  "llvm.return"(%8) : (i64) -> ()
}
]

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

@[simp]
def enc_transport_idx {bvs : BitVecs n} (f : Fin m → Fin n) (i : Fin bvs.w) :
    (enc (bvs.transport f))[i] = (enc bvs)[i].transport f :=

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

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

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

def scalar_i16_shl_ult_const_before := [llvm|
{
^0(%arg16 : i16):
  %0 = llvm.mlir.constant(8 : i16) : i16
  %1 = llvm.mlir.constant(1024 : i16) : i16
  %2 = llvm.shl %arg16, %0 : i16
  %3 = llvm.icmp "ult" %2, %1 : i16
  "llvm.return"(%3) : (i1) -> ()
}
]

def t0_scalar_after := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.xor %arg10, %arg11 : i8
  %2 = llvm.xor %1, %0 : i8
  "llvm.return"(%2) : (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) -> ()
}
]

RV64.sh3adduw in RISCV.Instructions

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

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

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

def test_uge_xor_after := [llvm|
{
^0(%arg30 : i32, %arg31 : i32):
  %0 = llvm.xor %arg31, %arg30 : i32
  %1 = llvm.icmp "ule" %0, %arg30 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

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

def llvm_const_lower_riscv_li_47 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_47, rhs:= liRiscv_47,
   correct := by admit /- proof elided -/

def sext_sext_add_mismatched_types_before := [llvm|
{
^0(%arg39 : i16, %arg40 : i32):
  %0 = llvm.mlir.constant(7 : i16) : i16
  %1 = llvm.mlir.constant(9 : i32) : i32
  %2 = llvm.ashr %arg39, %0 : i16
  %3 = llvm.ashr %arg40, %1 : i32
  %4 = llvm.sext %2 : i16 to i64
  %5 = llvm.sext %3 : i32 to i64
  %6 = llvm.add %4, %5 : i64
  "llvm.return"(%6) : (i64) -> ()
}
]

def passriscv64_optimized_const (fileName : String) : IO UInt32 := do
    let icom? ← Com.parseFromFile LLVMPlusRiscV fileName
    match icom? with
    | none => return 1
    | some (Sigma.mk _Γ ⟨eff, ⟨retTy, c⟩⟩) =>
      match eff with
      | EffectKind.pure =>
        match retTy with
        | [Ty.llvm (.bitvec _w)]  =>
           
          let lowered := selectionPipeFuelWithCSEWithOptConst 150 c true
          IO.println <| lowered.printModule
          return 0
        | _ =>
        IO.println s!" debug: WRONG RETURN TYPE : expected Ty.llvm (Ty.bitvec 64) "
        return 1
      | _ =>
      IO.println s!" debug: WRONG EFFECT KIND : expected pure program "
      return 1

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

def select_exact_lshr_icmp_const_before := [llvm|
{
^0(%arg146 : 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" %arg146, %0 : i32
  %4 = llvm.lshr exact %arg146, %1 : i32
  %5 = "llvm.select"(%3, %4, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def test83_after := [llvm|
{
^0(%arg62 : i16, %arg63 : i64):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.sext %arg62 : i16 to i32
  %2 = llvm.trunc %arg63 : i64 to i32
  %3 = llvm.add %2, %0 : i32
  %4 = llvm.shl %1, %3 : i32
  %5 = llvm.zext %4 : i32 to i64
  "llvm.return"(%5) : (i64) -> ()
}
]

def add_sub_reg_frags : List (Σ Γ, RISCVPeepholeRewrite Γ) :=
  [⟨_, add_sub_reg_frags_left⟩,
  ⟨_, add_sub_reg_frags_right⟩]

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

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

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

def IntToString (i: Int): String := i.repr

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

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

def toConcrete : ConcreteOrMVar α 0 → α
  | .concrete a => a

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

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

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

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

def AttrDict.find_str {φ} (attrs : AttrDict φ) (name : String) : Option String :=
  match attrs.find name with
  | .some (AttrValue.str s) =>  .some s
  | _ => .none

def test15_after := [llvm|
{
^0(%arg44 : i8, %arg45 : i8):
  %0 = llvm.mlir.constant(33 : i8) : i8
  %1 = llvm.xor %arg45, %arg44 : i8
  %2 = llvm.xor %arg44, %arg45 : i8
  %3 = llvm.xor %2, %0 : i8
  %4 = llvm.and %1, %3 : i8
  %5 = llvm.mul %4, %3 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

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

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 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 scalar0_before := [llvm|
{
^0(%arg32 : i4, %arg33 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.xor %arg32, %arg33 : i4
  %2 = llvm.and %1, %0 : i4
  %3 = llvm.xor %2, %arg33 : i4
  "llvm.return"(%3) : (i4) -> ()
}
]

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

def slt_zero_ult_i1_after := [llvm|
{
^0(%arg10 : i32, %arg11 : i1):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "slt" %arg10, %0 : i32
  %3 = llvm.xor %arg11, %1 : i1
  %4 = llvm.and %2, %3 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def revertNonDepPropHyps (g : MVarId) : MetaM MVarId := do
  g.withContext do
    let (_, g) ← g.revert (← g.getNondepPropHyps)
    return g

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

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

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

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

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

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

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

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

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

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

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

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

def bools_multi_uses2_logical_before := [llvm|
{
^0(%arg36 : i1, %arg37 : i1, %arg38 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.xor %arg38, %0 : i1
  %3 = "llvm.select"(%2, %arg36, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = "llvm.select"(%arg38, %arg37, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %5 = "llvm.select"(%3, %0, %4) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %6 = llvm.add %3, %4 : i1
  %7 = "llvm.select"(%5, %6, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def mul_of_udiv_fail_bad_remainder_after := [llvm|
{
^0(%arg2 : i8):
  %0 = llvm.mlir.constant(11 : i8) : i8
  %1 = llvm.mlir.constant(6 : i8) : i8
  %2 = llvm.udiv exact %arg2, %0 : i8
  %3 = llvm.mul %2, %1 overflow<nuw> : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def not_mul_of_bool_commute_after := [llvm|
{
^0(%arg87 : i32, %arg88 : i32):
  %0 = llvm.mlir.constant(30 : i32) : i32
  %1 = llvm.mlir.constant(255 : i32) : i32
  %2 = llvm.lshr %arg87, %0 : i32
  %3 = llvm.and %arg88, %1 : i32
  %4 = llvm.mul %3, %2 overflow<nsw,nuw> : i32
  %5 = llvm.icmp "ugt" %4, %1 : i32
  "llvm.return"(%5) : (i1) -> ()
}
]

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

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

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

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

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

private def oprgn0 : Op φ := [mlir_op|
 "func"() ({ ^entry: %x = "foo.add"() : () -> (i64) } ) : () -> ()
]

def lshr_exact_add_negative_shift_positive_after := [llvm|
{
^0(%arg56 : i32):
  %0 = llvm.mlir.constant(4 : i32) : i32
  %1 = llvm.lshr exact %0, %arg56 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

def or_basic_before := [llvm|
{
^0(%arg15 : i16):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.mlir.constant(-256 : i16) : i16
  %2 = llvm.mlir.constant(17664 : i16) : i16
  %3 = llvm.trunc %arg15 : i16 to i8
  %4 = llvm.icmp "ne" %3, %0 : i8
  %5 = llvm.and %arg15, %1 : i16
  %6 = llvm.icmp "ne" %5, %2 : i16
  %7 = llvm.or %4, %6 : i1
  "llvm.return"(%7) : (i1) -> ()
}
]

def t0_before := [llvm|
{
^0(%arg42 : i32, %arg43 : i32, %arg44 : i32, %arg45 : i32):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.icmp "eq" %arg42, %arg43 : i32
  %2 = llvm.icmp "eq" %arg44, %arg45 : i32
  %3 = llvm.or %2, %1 : i1
  %4 = llvm.xor %3, %0 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

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

def lowmask_or_zext_commute_after := [llvm|
{
^0(%arg217 : i16, %arg218 : i24):
  %0 = llvm.trunc %arg218 : i24 to i16
  %1 = llvm.or %arg217, %0 : i16
  %2 = llvm.zext %1 : i16 to i24
  "llvm.return"(%2) : (i24) -> ()
}
]

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

def rewriteAt
    (lhs rhs : Com d Γ₁ .pure ts₁)
    (hlhs : ∀ t (v : Var Γ₁ t), ⟨t, v⟩ ∈ lhs.vars)
    (pos : ℕ) (target : Com d Γ₂ eff t₂) :
    Option (Com d Γ₂ eff t₂) := do
  let splitRes ← splitProgramAt pos target
  if h : ts₁ = splitRes.midTypes then
    let m ← matchArgRes splitRes.top lhs.toLets splitRes.midRet (h ▸ lhs.returnVars)
    let m := m.toHom <| by
      subst h; exact hlhs
    let rhs := rhs.changeVars m
    let zip := splitRes.insertPureCom splitRes.midRet (cast (by admit /- proof elided -/
    ) rhs)
    return zip.toCom
  else none

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

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

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

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

def binop_same_val : List (Σ Γ, RISCVPeepholeRewrite  Γ) :=
    [⟨_, binop_same_val_and⟩,
    ⟨_, binop_same_val_or⟩]

def main1_logical_after := [llvm|
{
^0(%arg158 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(2 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.and %arg158, %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 missed_const_prop_2002h12h05_before := [llvm|
{
^0(%arg0 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(1 : i32) : i32
  %2 = llvm.sub %0, %arg0 : i32
  %3 = llvm.sub %0, %1 : i32
  %4 = llvm.add %3, %1 : i32
  %5 = llvm.add %arg0, %4 : i32
  %6 = llvm.add %2, %5 : i32
  "llvm.return"(%6) : (i32) -> ()
}
]

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

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

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

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

def test4_before := [llvm|
{
^0(%arg57 : i32):
  %0 = llvm.add %arg57, %arg57 overflow<nuw> : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

def or_xor_common_op_commute6_after := [llvm|
{
^0(%arg117 : i8, %arg118 : i8, %arg119 : i8):
  %0 = llvm.or %arg117, %arg118 : i8
  %1 = llvm.or %0, %arg119 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def Tensor2D : Dialect where
  Op := Op
  Ty := Ty

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

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

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

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

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

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

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

def test1_after := [llvm|
{
^0(%arg60 : i64, %arg61 : i32):
  %0 = llvm.mlir.constant(123) : i64
  %1 = llvm.and %arg60, %0 : i64
  "llvm.return"(%1) : (i64) -> ()
}
]

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

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

structure NonNegFlag where
  nneg : Bool := false
  deriving Repr, DecidableEq, Lean.ToExpr

def sub_select_sext_before := [llvm|
{
^0(%arg24 : i1, %arg25 : i64):
  %0 = llvm.mlir.constant(64) : i64
  %1 = "llvm.select"(%arg24, %0, %arg25) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i64, i64) -> i64
  %2 = llvm.sext %arg24 : i1 to i64
  %3 = llvm.sub %1, %2 : i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

def test7_before := [llvm|
{
^0(%arg30 : i32):
  %0 = llvm.mlir.constant(511 : i32) : i32
  %1 = llvm.mlir.constant(20000 : i32) : i32
  %2 = llvm.and %arg30, %0 : i32
  %3 = llvm.sub %1, %2 : i32
  %4 = llvm.sext %3 : i32 to i64
  "llvm.return"(%4) : (i64) -> ()
}
]

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

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

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

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

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

inductive GenBVPred where
   
  | bin (lhs : GenBVExpr w) (op : BVBinPred) (rhs : GenBVExpr w)
   
  | getLsbD (expr : GenBVExpr w) (idx : Nat)
deriving Hashable, BEq, DecidableEq

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

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

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

noncomputable def HTermEnv.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) :
    StateSpace wcard tcard bcard ncard icard pcard → BitStream := fun
    | .widthVar v =>
        BitStream.ofNatUnary (wenv v)
    | .termVar v =>
      BitStream.ofBitVecZext (tenv v)
    | .predVar v => BitStream.ofProp (penv v)
    | .boolVar v => BitStream.ofBool (benv v) 

@[simp_llvm_option]
def lshr {w : Nat} (x y : IntW w) (flag : ExactFlag := {exact := false}) : IntW w := do
  let x' ← x
  let y' ← y
  if flag.exact ∧(x' >>> y') <<< y' ≠ x' then
    .poison
  else
    lshr? x' y'

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

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

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

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

instance : Inhabited (TyDenote.toType (t : Ty)) where
  default := by admit /- proof elided -/

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

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

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

def urem_c_i32_before := [llvm|
{
^0(%arg5 : i8):
  %0 = llvm.mlir.constant(10 : i32) : i32
  %1 = llvm.zext %arg5 : i8 to i32
  %2 = llvm.urem %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

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

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

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

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

Fin.mk in Init.Prelude

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

def test13_after := [llvm|
{
^0(%arg68 : i32, %arg69 : i32):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.sext %arg68 : i32 to i64
  %2 = llvm.and %arg69, %0 : i32
  %3 = llvm.zext nneg %2 : i32 to i64
  %4 = llvm.ashr %1, %3 : i64
  "llvm.return"(%4) : (i64) -> ()
}
]

def llvm_zext_lower_riscv_8_to_32 : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 8)] :=
  {lhs:= zext_llvm_8_to_32, rhs:= zext_riscv_8_to_32}

def udiv_i32_before := [llvm|
{
^0(%arg29 : i8, %arg30 : i8):
  %0 = llvm.zext %arg29 : i8 to i32
  %1 = llvm.zext %arg30 : i8 to i32
  %2 = llvm.udiv %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def or_and3_commuted_after := [llvm|
{
^0(%arg100 : i1, %arg101 : i1, %arg102 : i32, %arg103 : i32):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = llvm.icmp "ne" %arg102, %arg103 : i32
  %3 = "llvm.select"(%2, %arg101, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = "llvm.select"(%arg100, %1, %3) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

def icmp_sgt_riscv_eq_icmp_slt_llvm_32 : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] :=
  {lhs:= icmp_sgt_llvm_32, rhs:= icmp_sgt_riscv_32}

def three_inst_concrete_stmt (e : LLVM.IntW 1) :
    (LLVM.not (LLVM.not (LLVM.not e)))
      ⊑ (LLVM.not (LLVM.not (LLVM.not e))) :=

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

def src_x_and_nmask_ne_after := [llvm|
{
^0(%arg27 : i8, %arg28 : i8, %arg29 : i1):
  %0 = llvm.mlir.constant(-1 : i8) : i8
  %1 = llvm.mlir.constant(false) : i1
  %2 = llvm.shl %0, %arg28 overflow<nsw> : i8
  %3 = llvm.icmp "ugt" %2, %arg27 : i8
  %4 = "llvm.select"(%arg29, %3, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

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

def par_after := [llvm|
{
^0(%arg81 : i32, %arg82 : i32, %arg83 : i32, %arg84 : i32):
  %0 = llvm.icmp "slt" %arg81, %arg82 : i32
  %1 = "llvm.select"(%0, %arg83, %arg84) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

def test_sge_xor_after := [llvm|
{
^0(%arg38 : i32, %arg39 : i32):
  %0 = llvm.xor %arg39, %arg38 : i32
  %1 = llvm.icmp "sle" %0, %arg38 : i32
  "llvm.return"(%1) : (i1) -> ()
}
]

NFA.evalFrom in Mathlib.Computability.NFA

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

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

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

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

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

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

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

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

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

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

def NFA.sa (_ : NFA α σ) := σ → Language α

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

def test5_after := [llvm|
{
^0(%arg2 : i7):
  %0 = llvm.mlir.constant(-24 : i7) : i7
  %1 = llvm.and %arg2, %0 : i7
  "llvm.return"(%1) : (i7) -> ()
}
]

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

def zext_nneg_flag_drop_before := [llvm|
{
^0(%arg7 : i8, %arg8 : i16):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.mlir.constant(128 : i16) : i16
  %2 = llvm.and %arg7, %0 : i8
  %3 = llvm.zext nneg %2 : i8 to i16
  %4 = llvm.or %3, %arg8 : i16
  %5 = llvm.or %4, %1 : i16
  "llvm.return"(%5) : (i16) -> ()
}
]

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

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

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

def dec_inj {n : Nat} : Function.Injective (dec (n := n)) :=

@[simp]
def _root_.Set.lift (f : Fin n → Fin m) (bvs : Set (BitVecs n)) : Set (BitVecs m) :=
  BitVecs.transport f ⁻¹' bvs

def xor_of_icmps_to_ne_commute_before := [llvm|
{
^0(%arg28 : i64):
  %0 = llvm.mlir.constant(4) : i64
  %1 = llvm.mlir.constant(6) : i64
  %2 = llvm.icmp "sgt" %arg28, %0 : i64
  %3 = llvm.icmp "slt" %arg28, %1 : i64
  %4 = llvm.xor %3, %2 : i1
  "llvm.return"(%4) : (i1) -> ()
}
]

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

def src3_before := [llvm|
{
^0(%arg8 : i32, %arg9 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.and %arg9, %arg8 : i32
  %2 = llvm.xor %arg8, %0 : i32
  %3 = llvm.xor %arg9, %0 : i32
  %4 = llvm.and %2, %3 : i32
  %5 = llvm.add %1, %4 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

def test12_after := [llvm|
{
^0(%arg29 : i47):
  %0 = llvm.mlir.constant(-256 : i47) : i47
  %1 = llvm.and %arg29, %0 : i47
  "llvm.return"(%1) : (i47) -> ()
}
]

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

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

instance : Sub BitStream := ⟨sub⟩

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

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

def or_not_and_after := [llvm|
{
^0(%arg537 : i32, %arg538 : i32, %arg539 : i32):
  %0 = llvm.mlir.constant(-1 : i32) : i32
  %1 = llvm.xor %arg538, %arg539 : i32
  %2 = llvm.xor %arg537, %0 : i32
  %3 = llvm.and %1, %2 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

def test4_before := [llvm|
{
^0(%arg57 : i32):
  %0 = llvm.add %arg57, %arg57 overflow<nuw> : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

def composeQuinaryAux' (p : FSM (Fin 5)) (q₀ q₁ q₂ q₃ q₄: FSM α) : FSM α :=
  p.compose (α)
    (λ _ => α)
    (λ _ i => i)
    (λ v =>
      v.cases q₀ fun v =>
        v.cases q₁ fun v =>
          v.cases q₂ fun v =>
            v.cases q₃ fun v =>
              v.cases q₄ fun v => v.elim0)

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

def t1_before := [llvm|
{
^0(%arg11 : i8):
  %0 = llvm.mlir.constant(24 : i32) : i32
  %1 = llvm.mlir.constant(-2147483648 : i32) : i32
  %2 = llvm.zext %arg11 : i8 to i32
  %3 = llvm.shl %2, %0 : i32
  %4 = llvm.and %3, %1 : i32
  "llvm.return"(%4) : (i32) -> ()
}
]

def test42_after := [llvm|
{
^0(%arg208 : i32, %arg209 : i32, %arg210 : i32):
  %0 = llvm.mul %arg209, %arg210 : i32
  %1 = llvm.and %0, %arg208 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

class HydrableGetGenPredSize (genPred : Type) where
  getGenPredSize : genPred → Nat

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

def or_or_and_pat7_after := [llvm|
{
^0(%arg50 : i8, %arg51 : i8, %arg52 : i8, %arg53 : i8):
  %0 = llvm.or %arg53, %arg50 : i8
  %1 = llvm.and %arg51, %0 : i8
  %2 = llvm.or %1, %arg52 : i8
  "llvm.return"(%2) : (i8) -> ()
}
]

abbrev Simple : Dialect where
  Op := Op
  Ty := Ty

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

def sge_or_max_commute_before := [llvm|
{
^0(%arg186 : i8, %arg187 : i8):
  %0 = llvm.mlir.constant(127 : i8) : i8
  %1 = llvm.icmp "sge" %arg186, %arg187 : i8
  %2 = llvm.icmp "eq" %arg186, %0 : i8
  %3 = llvm.or %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

def shl_or_after := [llvm|
{
^0(%arg25 : i8):
  %0 = llvm.mlir.constant(22 : i8) : i8
  %1 = llvm.shl %0, %arg25 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

def mul_constant_eq_before := [llvm|
{
^0(%arg140 : i32, %arg141 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mul %arg140, %0 : i32
  %2 = llvm.mul %arg141, %0 : i32
  %3 = llvm.icmp "eq" %1, %2 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def sdiv_one_allOnes {w : Nat} (h : 1 < w) :
    BitVec.sdiv (1#w) (BitVec.allOnes w) = BitVec.allOnes w :=

def lowmask_sub_zext_commute_after := [llvm|
{
^0(%arg223 : i5, %arg224 : i17):
  %0 = llvm.trunc %arg224 : i17 to i5
  %1 = llvm.sub %0, %arg223 : i5
  %2 = llvm.zext %1 : i5 to i17
  "llvm.return"(%2) : (i17) -> ()
}
]

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

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

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

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

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

def or_or_xor_commute2_before := [llvm|
{
^0(%arg100 : i4, %arg101 : i4, %arg102 : i4):
  %0 = llvm.or %arg102, %arg100 : i4
  %1 = llvm.or %arg101, %arg102 : i4
  %2 = llvm.xor %0, %1 : i4
  "llvm.return"(%2) : (i4) -> ()
}
]

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

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

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

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

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

def udiv_common_dividend_defined_cond_after := [llvm|
{
^0(%arg17 : i1, %arg18 : i5, %arg19 : i5, %arg20 : i5):
  %0 = "llvm.select"(%arg17, %arg20, %arg19) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i5, i5) -> i5
  %1 = llvm.udiv %arg18, %0 : i5
  "llvm.return"(%1) : (i5) -> ()
}
]

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

def different_size_sext_sext_sgt_before := [llvm|
{
^0(%arg14 : i7, %arg15 : i4):
  %0 = llvm.sext %arg14 : i7 to i25
  %1 = llvm.sext %arg15 : i4 to i25
  %2 = llvm.icmp "sgt" %0, %1 : i25
  "llvm.return"(%2) : (i1) -> ()
}
]

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

    |

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

def test3_before := [llvm|
{
^0(%arg0 : i599, %arg1 : i1):
  %0 = llvm.mlir.constant(70368744177664 : i599) : i599
  %1 = llvm.mlir.constant(4096 : i599) : i599
  %2 = "llvm.select"(%arg1, %0, %1) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i599, i599) -> i599
  %3 = llvm.udiv %arg0, %2 : i599
  "llvm.return"(%3) : (i599) -> ()
}
]

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

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 not_xor_to_or_not3_before := [llvm|
{
^0(%arg33 : i3, %arg34 : i3, %arg35 : i3):
  %0 = llvm.mlir.constant(-1 : i3) : i3
  %1 = llvm.or %arg35, %arg34 : i3
  %2 = llvm.and %arg35, %arg33 : i3
  %3 = llvm.xor %2, %1 : i3
  %4 = llvm.xor %3, %0 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

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

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

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

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

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

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

def lshr {w : Nat} (x y : IntW w) (flag : ExactFlag := {exact := false}) : IntW w := do
  let x' ← x
  let y' ← y
  if flag.exact ∧(x' >>> y') <<< y' ≠ x' then
    .poison
  else
    lshr? x' y'

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

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

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

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

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

def sub_from_constant_of_add_with_constant_after := [llvm|
{
^0(%arg153 : i8):
  %0 = llvm.mlir.constant(-31 : i8) : i8
  %1 = llvm.sub %0, %arg153 : i8
  "llvm.return"(%1) : (i8) -> ()
}
]

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

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

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

instance : BEq FpExprWrapper where
  beq := fun a b =>
    if h : a.width = b.width then
      a.bvExpr = h ▸ b.bvExpr
    else
      false

def icmp_ne_mul_nsw_nonequal_before := [llvm|
{
^0(%arg28 : i8, %arg29 : i8):
  %0 = llvm.mlir.constant(1 : i8) : i8
  %1 = llvm.add %arg28, %0 : i8
  %2 = llvm.mul %arg28, %arg29 overflow<nsw> : i8
  %3 = llvm.mul %1, %arg29 overflow<nsw> : i8
  %4 = llvm.icmp "ne" %2, %3 : i8
  "llvm.return"(%4) : (i1) -> ()
}
]

def shl_or_lshr_comm_before := [llvm|
{
^0(%arg106 : i32, %arg107 : i32, %arg108 : i32):
  %0 = llvm.shl %arg106, %arg107 overflow<nuw> : i32
  %1 = llvm.or %arg108, %0 : i32
  %2 = llvm.lshr %1, %arg107 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

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

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

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

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

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

def llvm_rem_lower_riscv_8 : LLVMPeepholeRewriteRefine 8 [Ty.llvm (.bitvec 8), Ty.llvm (.bitvec 8)] where
  lhs := rem_llvm_8
  rhs := rem_riscv_8
  correct := by admit /- proof elided -/

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

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

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

def pruneConstantExprsSynthesisResults(exprSynthesisResults : ExpressionSynthesisResult)
                            : GeneralizerStateM ParsedFpExpr FpPredicate ExpressionSynthesisResult := do
      withTraceNode `Generalize (fun _ => return "Pruned expressions synthesis results") do
          let state ← get
          let mut tempResults : Std.HashMap Nat (List (FpExprWrapper)) := Std.HashMap.emptyWithCapacity

          for (var, expressions) in exprSynthesisResults.toList do
              let width := state.parsedLogicalExpr.state.symVarIdToVariable[var]!.width
              let mut bvExprs : List (FpExpr width) := []

              for expr in expressions do
                let h : width = expr.width := sorry
                bvExprs := h ▸ expr.bvExpr :: bvExprs

              let mut prunedExprs ← pruneEquivalentFpExprs bvExprs.reverse 
              tempResults := tempResults.insert var (prunedExprs.map (λ expr => wrap expr))

          pure tempResults

def t6_shl_before := [llvm|
{
^0(%arg31 : i32, %arg32 : i32):
  %0 = llvm.mlir.constant(32 : i32) : i32
  %1 = llvm.mlir.constant(-2 : i32) : i32
  %2 = llvm.sub %0, %arg32 : i32
  %3 = llvm.shl %arg31, %2 overflow<nuw> : i32
  %4 = llvm.add %arg32, %1 : i32
  %5 = llvm.shl %3, %4 overflow<nsw> : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

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

def alive_AddSub_1043_tgt  (w : Nat)  :=
[llvm( w )| {
^bb0(%C1 : _, %Z : _, %RHS : _):
  %v1 = llvm.not %C1
  %v2 = llvm.or %Z, %v1
  %v3 = llvm.and %Z, %C1
  %v4 = llvm.xor %v3, %C1
  %v5 = llvm.mlir.constant 1
  %v6 = llvm.add %v4, %v5
  %v7 = llvm.sub %RHS, %v2
  llvm.return %v7
}]

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

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

def test4_apint_before := [llvm|
{
^0(%arg42 : i61):
  %0 = llvm.mlir.constant(-1 : i61) : i61
  %1 = llvm.mlir.constant(5 : i61) : i61
  %2 = llvm.xor %arg42, %0 : i61
  %3 = llvm.and %2, %1 : i61
  %4 = llvm.xor %3, %0 : i61
  "llvm.return"(%3) : (i61) -> ()
}
]

inductive AffineTuple
  | mk: List AffineExpr -> AffineTuple
  deriving DecidableEq, Repr

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

def widget_after := [llvm|
{
^0(%arg0 : i32, %arg1 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.mlir.constant(20 : i32) : i32
  %2 = llvm.icmp "ne" %arg0, %0 : i32
  %3 = llvm.zext %2 : i1 to i32
  %4 = llvm.shl %1, %3 overflow<nsw,nuw> : i32
  %5 = llvm.zext %2 : i1 to i32
  %6 = llvm.or disjoint %4, %5 : i32
  %7 = llvm.zext %2 : i1 to i32
  %8 = llvm.shl %6, %7 overflow<nsw,nuw> : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

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 test21_before := [llvm|
{
^0(%arg0 : i256, %arg1 : i256):
  %0 = llvm.sub %arg0, %arg1 : i256
  %1 = llvm.icmp "ne" %0, %arg0 : i256
  "llvm.return"(%1) : (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 not_xor_to_or_not1_after := [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 %1, %0 : i3
  %4 = llvm.or %2, %3 : i3
  "llvm.return"(%4) : (i3) -> ()
}
]

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

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

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

def xor_to_xor3_after := [llvm|
{
^0(%arg81 : i32, %arg82 : i32):
  %0 = llvm.xor %arg81, %arg82 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

RV64.xori in RISCV.Instructions

def udiv_shl_pair1_before := [llvm|
{
^0(%arg30 : i32, %arg31 : i32, %arg32 : i32):
  %0 = llvm.shl %arg30, %arg31 overflow<nuw> : i32
  %1 = llvm.shl %arg30, %arg32 overflow<nuw> : i32
  %2 = llvm.udiv %0, %1 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

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

Lean.Meta.mkDecideProof in Lean.Meta.AppBuilder

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

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

def or_and_shift_shift_and_after := [llvm|
{
^0(%arg12 : i32):
  %0 = llvm.mlir.constant(3 : i32) : i32
  %1 = llvm.mlir.constant(56 : i32) : i32
  %2 = llvm.mlir.constant(2 : i32) : i32
  %3 = llvm.mlir.constant(28 : i32) : i32
  %4 = llvm.shl %arg12, %0 : i32
  %5 = llvm.and %4, %1 : i32
  %6 = llvm.shl %arg12, %2 : i32
  %7 = llvm.and %6, %3 : i32
  %8 = llvm.or %5, %7 : i32
  "llvm.return"(%8) : (i32) -> ()
}
]

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

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

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

def test_before := [llvm|
{
^0(%arg0 : i1, %arg1 : i1):
  %0 = llvm.add %arg0, %arg1 : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

def foo1_and_signbit_lshr_without_shifting_signbit_after := [llvm|
{
^0(%arg118 : i32, %arg119 : i32, %arg120 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.mlir.constant(-1 : i32) : i32
  %3 = llvm.shl %0, %arg119 overflow<nuw> : i32
  %4 = llvm.and %3, %arg118 : i32
  %5 = llvm.icmp "eq" %4, %1 : i32
  %6 = llvm.shl %arg118, %arg120 : i32
  %7 = llvm.icmp "sgt" %6, %2 : i32
  %8 = llvm.or %5, %7 : i1
  "llvm.return"(%8) : (i1) -> ()
}
]

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

def test9_after := [llvm|
{
^0(%arg52 : i16):
  %0 = llvm.mlir.constant(-32767 : i16) : i16
  %1 = llvm.mul %arg52, %0 : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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

Array.emptyWithCapacity in Init.Prelude

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

def lshr_add_and_shl_before := [llvm|
{
^0(%arg17 : i32, %arg18 : i32):
  %0 = llvm.mlir.constant(5 : i32) : i32
  %1 = llvm.mlir.constant(127 : i32) : i32
  %2 = llvm.lshr %arg17, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.add %arg18, %3 : i32
  %5 = llvm.shl %4, %0 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

def sdiv400_yes_after := [llvm|
{
^0(%arg3 : i32):
  %0 = llvm.mlir.constant(400 : i32) : i32
  %1 = llvm.udiv %arg3, %0 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

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

RV64.srl in RISCV.Instructions

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

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

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

def mul_splat_fold_too_narrow_after := [llvm|
{
^0(%arg77 : i2):
  "llvm.return"(%arg77) : (i2) -> ()
}
]

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

def narrow_zext_and_after := [llvm|
{
^0(%arg54 : i16, %arg55 : i32):
  %0 = llvm.trunc %arg55 : i32 to i16
  %1 = llvm.and %arg54, %0 : i16
  "llvm.return"(%1) : (i16) -> ()
}
]

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

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

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

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

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

def srem? {w : Nat} (x y : BitVec w) : IntW w :=
  if y == 0 || (w != 1 && x == (BitVec.intMin w) && y == -1) then
    .poison
  else
    .value <| BitVec.srem x y

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

def add_shl_moreOneUse_sh4add_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where
  lhs := add_shl_moreOneUse_sh4add_llvm
  rhs :=add_shl_moreOneUse_sh4add_riscv

def slt_zero_ult_i1_fail2_after := [llvm|
{
^0(%arg6 : i32, %arg7 : i1):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.zext %arg7 : i1 to i32
  %2 = llvm.ashr %arg6, %0 : i32
  %3 = llvm.icmp "ugt" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

def lshr_exact_add_nuw_after := [llvm|
{
^0(%arg63 : i32):
  %0 = llvm.mlir.constant(2 : i32) : i32
  %1 = llvm.lshr exact %0, %arg63 : i32
  "llvm.return"(%1) : (i32) -> ()
}
]

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

def select_lshr_icmp_before := [llvm|
{
^0(%arg199 : i32, %arg200 : i32, %arg201 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.icmp "eq" %arg199, %0 : i32
  %2 = llvm.lshr %arg201, %arg199 : i32
  %3 = "llvm.select"(%1, %2, %arg200) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> 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_02_09_exact_after := [llvm|
{
^0(%arg196 : i4):
  %0 = llvm.mlir.constant(false) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

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

abbrev Ix := Nat

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 sub_ashr_and_i32_after := [llvm|
{
^0(%arg27 : i32, %arg28 : i32):
  %0 = llvm.mlir.constant(0 : i32) : i32
  %1 = llvm.icmp "slt" %arg28, %arg27 : i32
  %2 = "llvm.select"(%1, %arg27, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i32, i32) -> i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

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

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

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

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

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

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

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

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

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

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

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

def pr33078_4_after := [llvm|
{
^0(%arg2 : i3):
  %0 = llvm.mlir.constant(13 : i16) : i16
  %1 = llvm.sext %arg2 : i3 to i16
  %2 = llvm.lshr %1, %0 : i16
  %3 = llvm.trunc %2 overflow<nsw,nuw> : i16 to i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

def double_icmp_zero_combine : List (Σ Γ, LLVMPeepholeRewriteRefine 1 Γ) :=
  [⟨_, double_icmp_zero_and_combine⟩,
  ⟨_, double_icmp_zero_or_combine⟩]

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

def masked_bit_set_before := [llvm|
{
^0(%arg83 : i32, %arg84 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg84 : i32
  %3 = llvm.and %2, %arg83 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.zext %4 : i1 to i32
  "llvm.return"(%5) : (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 ashrsgt_01_01_before := [llvm|
{
^0(%arg316 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.ashr %arg316, %0 : i4
  %2 = llvm.icmp "sgt" %1, %0 : i4
  "llvm.return"(%2) : (i1) -> ()
}
]

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

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

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

def substBvEqualitiesTac : TacticM Unit := do
  liftMetaTactic1 substBvEqualities

def rawspeed_signbit_before := [llvm|
{
^0(%arg0 : i64, %arg1 : i32):
  %0 = llvm.mlir.constant(64 : i32) : i32
  %1 = llvm.mlir.constant(-1 : i32) : i32
  %2 = llvm.mlir.constant(1 : i32) : i32
  %3 = llvm.mlir.constant(0 : i32) : i32
  %4 = llvm.sub %0, %arg1 overflow<nsw> : i32
  %5 = llvm.zext %4 : i32 to i64
  %6 = llvm.lshr %arg0, %5 : i64
  %7 = llvm.trunc %6 : i64 to i32
  %8 = llvm.add %arg1, %1 overflow<nsw> : i32
  %9 = llvm.shl %2, %8 : i32
  %10 = llvm.and %9, %7 : i32
  %11 = llvm.icmp "eq" %10, %3 : i32
  "llvm.return"(%11) : (i1) -> ()
}
]

def shl_lshr_pow2_const_negative_overflow1_after := [llvm|
{
^0(%arg70 : i16):
  %0 = llvm.mlir.constant(0 : i16) : i16
  "llvm.return"(%0) : (i16) -> ()
}
]

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

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

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

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

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

instance : Lean.ToExpr RegIndex := inherit

def or_zext_zext_after := [llvm|
{
^0(%arg56 : i8, %arg57 : i4):
  %0 = llvm.zext %arg57 : i4 to i8
  %1 = llvm.or %arg56, %0 : i8
  %2 = llvm.zext %1 : i8 to i16
  "llvm.return"(%2) : (i16) -> ()
}
]

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

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

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

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

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

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

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

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

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

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

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

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

RV64.divu in RISCV.Instructions

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

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

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

def and_or_hoist_mask_after := [llvm|
{
^0(%arg91 : i8, %arg92 : i8):
  %0 = llvm.mlir.constant(6 : i8) : i8
  %1 = llvm.mlir.constant(3 : i8) : i8
  %2 = llvm.lshr %arg91, %0 : i8
  %3 = llvm.and %arg92, %1 : i8
  %4 = llvm.or %2, %3 : i8
  "llvm.return"(%4) : (i8) -> ()
}
]

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

inductive Vars (σ : Type) (ι : Type) (n : Nat)
| state (s : Inputs σ (n + 1))
| inputs (is : Inputs ι n)
| outputs (os : Fin n) 
deriving DecidableEq, Hashable

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

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

@[simp]
def enc_transport :
     enc (bvs.transport f) = (enc bvs).transport f :=

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

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

def ashrslt_01_00_before := [llvm|
{
^0(%arg269 : i4):
  %0 = llvm.mlir.constant(1 : i4) : i4
  %1 = llvm.mlir.constant(0 : i4) : i4
  %2 = llvm.ashr %arg269, %0 : i4
  %3 = llvm.icmp "slt" %2, %1 : i4
  "llvm.return"(%3) : (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 splat_mul_known_lz_after := [llvm|
{
^0(%arg72 : i32):
  %0 = llvm.mlir.constant(true) : i1
  "llvm.return"(%0) : (i1) -> ()
}
]

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

def zext_sext_add_icmp_eq_minus1_after := [llvm|
{
^0(%arg84 : i1, %arg85 : i1):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.xor %arg84, %0 : i1
  %2 = llvm.and %arg85, %1 : i1
  "llvm.return"(%2) : (i1) -> ()
}
]

def test6_after := [llvm|
{
^0(%arg51 : i1023):
  %0 = llvm.mlir.constant(64 : i1023) : i1023
  %1 = llvm.and %arg51, %0 : i1023
  "llvm.return"(%1) : (i1023) -> ()
}
]

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

def lshr_add_before := [llvm|
{
^0(%arg81 : i8, %arg82 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.mlir.constant(5 : i8) : i8
  %2 = llvm.srem %arg81, %0 : i8
  %3 = llvm.lshr %arg82, %1 : i8
  %4 = llvm.add %3, %2 : i8
  %5 = llvm.shl %4, %1 : i8
  "llvm.return"(%5) : (i8) -> ()
}
]

def llvm_const_lower_riscv_li_36 : LLVMPeepholeRewriteRefine 64 [] :=
  {lhs := constLLVM_36, rhs:= liRiscv_36,
   correct := by admit /- proof elided -/

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

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

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

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

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

def sext_non_bool_xor_sub_1_before := [llvm|
{
^0(%arg18 : i64, %arg19 : i8):
  %0 = llvm.sext %arg19 : i8 to i64
  %1 = llvm.xor %0, %arg18 : i64
  %2 = llvm.sub %1, %0 : i64
  "llvm.return"(%2) : (i64) -> ()
}
]

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

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

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

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

instance : AST.TransformTy (LLVM) 0 := { mkTy }

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

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

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

def PR23309v2_before := [llvm|
{
^0(%arg51 : i32, %arg52 : i32):
  %0 = llvm.mlir.constant(-4 : i32) : i32
  %1 = llvm.add %arg51, %0 : i32
  %2 = llvm.add %1, %arg52 overflow<nuw> : i32
  %3 = llvm.trunc %2 : i32 to i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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 XorShlShl : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where
  lhs := [LV| {
    ^entry (%x: i64, %y: i64, %z: i64):
      %0 = llvm.shl %x, %z : i64
      %1 = llvm.shl %y, %z : i64
      %2 = llvm.xor %0, %1 : i64
      llvm.return %2 : i64
  }]
  rhs := [LV| {
    ^entry (%x: i64, %y: i64, %z: i64):
      %0 = llvm.xor %x, %y : i64
      %1 = llvm.shl %0, %z : i64
      llvm.return %1 : i64
  }]

def or_or_and_complex_after := [llvm|
{
^0(%arg82 : i64):
  %0 = llvm.mlir.constant(8) : i64
  %1 = llvm.mlir.constant(71777214294589695) : i64
  %2 = llvm.mlir.constant(-71777214294589696) : i64
  %3 = llvm.lshr %arg82, %0 : i64
  %4 = llvm.shl %arg82, %0 : i64
  %5 = llvm.and %3, %1 : i64
  %6 = llvm.and %4, %2 : i64
  %7 = llvm.or disjoint %5, %6 : i64
  "llvm.return"(%7) : (i64) -> ()
}
]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def test5_before := [llvm|
{
^0(%arg4 : i111):
  %0 = llvm.mlir.constant(1 : i111) : i111
  %1 = llvm.mlir.constant(110 : i111) : i111
  %2 = llvm.shl %0, %1 : i111
  %3 = llvm.xor %arg4, %2 : i111
  %4 = llvm.add %3, %2 : i111
  "llvm.return"(%4) : (i111) -> ()
}
]

abbrev State := Nat

def shl_nsw_nuw_after := [llvm|
{
^0(%arg4 : i1, %arg5 : i8):
  %0 = llvm.mlir.constant(7 : i8) : i8
  %1 = llvm.mlir.constant(56 : i8) : i8
  %2 = llvm.shl %0, %arg5 overflow<nsw,nuw> : i8
  %3 = "llvm.select"(%arg4, %1, %2) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i8, i8) -> i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

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

def div_bit_set_before := [llvm|
{
^0(%arg61 : i32, %arg62 : i32):
  %0 = llvm.mlir.constant(1 : i32) : i32
  %1 = llvm.mlir.constant(0 : i32) : i32
  %2 = llvm.shl %0, %arg62 : i32
  %3 = llvm.sdiv %2, %arg61 : i32
  %4 = llvm.icmp "ne" %3, %1 : i32
  %5 = llvm.zext %4 : i1 to i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

RV64.sh2add in RISCV.Instructions

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

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

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

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

instance : HydrableInitializeGeneralizerState ParsedFpExpr FpPredicate FpExpr where
  initializeGeneralizerState := initialGeneralizerState

def alive_AddSub_1539_src :=
[sllvm| {
^bb0(%a : i64, %x : i64):
  %v1 = llvm.mlir.constant 0 : i64
  %v2 = llvm.sub %v1, %a : i64
  %v3 = llvm.sub %x, %v2 : i64
  llvm.return %v3 : i64
}]

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

def andcond.001.inv.outer.cond_before := [llvm|
{
^0(%arg75 : i1, %arg76 : i1, %arg77 : i1, %arg78 : i1, %arg79 : i1):
  %0 = llvm.mlir.constant(false) : i1
  %1 = llvm.mlir.constant(true) : i1
  %2 = "llvm.select"(%arg75, %arg76, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %3 = "llvm.select"(%arg75, %arg77, %arg78) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  %4 = llvm.xor %2, %1 : i1
  %5 = "llvm.select"(%4, %3, %0) <{"fastmathFlags" = #llvm.fastmath<none>}> : (i1, i1, i1) -> i1
  "llvm.return"(%5) : (i1) -> ()
}
]

instance : ToString DCOp.TokenStream where
  toString s := toString (Stream.toList 100 s)

@[simp]
abbrev envOfList {w} (a : List (BitVec w)) : Nat → BitVec w := fun n => a.getD n 0

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

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

def match_signed_after := [llvm|
{
^0(%arg15 : i64):
  %0 = llvm.mlir.constant(172224) : i64
  %1 = llvm.srem %arg15, %0 : i64
  "llvm.return"(%1) : (i64) -> ()
}
]

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

def andn_or_cmp_4_after := [llvm|
{
^0(%arg161 : i32, %arg162 : i32, %arg163 : i32):
  %0 = llvm.mlir.constant(42 : i32) : i32
  %1 = llvm.icmp "ne" %arg161, %arg162 : i32
  %2 = llvm.icmp "ugt" %arg163, %0 : i32
  %3 = llvm.and %2, %1 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

def test47_after := [llvm|
{
^0(%arg139 : i8):
  %0 = llvm.mlir.constant(42 : i8) : i8
  %1 = llvm.or %arg139, %0 : i8
  %2 = llvm.sext %1 : i8 to i32
  %3 = llvm.zext %2 : i32 to i64
  "llvm.return"(%3) : (i64) -> ()
}
]

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

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

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 Expr.WellTyped (Γ : Context Ty) : UnTyped.Expr Op VarName → Ty → Prop
  | ⟨_, op, args, regions⟩, ty =>
    let ⟨argTys, rgnTys, retTy⟩ := signature op
    args.length = argTys.length
      ∧ (∀ x ∈ args.zip argTys, Γ.hasType x.fst x.snd)
    ∧ RegionList.WellTyped regions rgnTys
    ∧ ty = retTy

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

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

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

def varsFinset [DecidableEq α] (c : Circuit α) : Finset α :=
  ⟨c.vars, nodup_vars c⟩

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

@[simp_denote]
def trunc_llvm_32_to_16 := [LV| {
  ^entry (%lhs: i32):
    %0 = llvm.trunc %lhs : i32 to i16
    llvm.return %0 : i16
  }]

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

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

Lean.Expr.app in Lean.Expr

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

def sub_shl_same_amount_partial_nuw2_after := [llvm|
{
^0(%arg2 : i6, %arg3 : i6, %arg4 : i6):
  %0 = llvm.sub %arg2, %arg3 : i6
  %1 = llvm.shl %0, %arg4 : i6
  "llvm.return"(%1) : (i6) -> ()
}
]

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

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

instance {α β : Type} [Fintype α] [Fintype β] (b : Bool) :
    Fintype (cond b α β) :=

def and_zext_demanded_after := [llvm|
{
^0(%arg255 : i16, %arg256 : i32):
  %0 = llvm.mlir.constant(8 : i16) : i16
  %1 = llvm.lshr %arg255, %0 : i16
  %2 = llvm.zext nneg %1 : i16 to i32
  "llvm.return"(%2) : (i32) -> ()
}
]

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

MonadLiftT in Init.Prelude

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 n7_wrong_pred2_before := [llvm|
{
^0(%arg10 : i8, %arg11 : i8):
  %0 = llvm.sub %arg10, %arg11 : i8
  %1 = llvm.icmp "eq" %0, %arg10 : i8
  "llvm.return"(%1) : (i1) -> ()
}
]

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

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

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

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

def and_to_xor2_after := [llvm|
{
^0(%arg117 : i32, %arg118 : i32):
  %0 = llvm.xor %arg117, %arg118 : i32
  "llvm.return"(%0) : (i32) -> ()
}
]

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

instance : DialectToExpr Comb where
  toExprM := .const ``Id [0]
  toExprDialect := .const ``Comb []

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

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

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

@[inline]
def CNFA.autMsbSet : CNFA 1 :=
  ⟨RawCNFA.autMsbSet, RawCNFA.autMsbSet_wf⟩

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

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

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

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

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

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

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

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

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

def GLobalISelPostLegalizerCombiner :
    List (Σ Γ, Σ ty, PeepholeRewrite LLVMPlusRiscV Γ ty) :=
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  redundant_binop_in_equality)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  PostLegalizerCombiner_LLVMIR_64)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  PostLegalizerCombiner_LLVMIR_32)
  ++
  (List.map (fun ⟨_,y⟩ => mkRewrite (LLVMToRiscvPeepholeRewriteRefine.toPeepholeUNSOUND y))
  canonicalize_icmp)
  ++
  List.map (fun ⟨_,y⟩ => mkRewrite (RISCVPeepholeRewriteToRiscvPeephole y))
  PostLegalizerCombiner_RISCV

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

def resTypes : List (MLIRType φ) :=
  op.res.map Prod.snd

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

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

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

BitVec.sge in Leanwuzla.Aux

def n2_after := [llvm|
{
^0(%arg19 : i1, %arg20 : i8, %arg21 : i8, %arg22 : i8, %arg23 : i8):
  %0 = llvm.mlir.constant(true) : i1
  %1 = llvm.icmp "eq" %arg20, %arg21 : i8
  %2 = llvm.xor %arg19, %0 : i1
  %3 = llvm.and %1, %2 : i1
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

Lean.Parser.mkNodeToken in Lean.Parser.Basic

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

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

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

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

def test6_before := [llvm|
{
^0(%arg3 : i65):
  %0 = llvm.mlir.constant(1 : i65) : i65
  %1 = llvm.mlir.constant(64 : i65) : i65
  %2 = llvm.shl %0, %1 : i65
  %3 = llvm.xor %arg3, %2 : i65
  %4 = llvm.add %3, %2 : i65
  "llvm.return"(%4) : (i65) -> ()
}
]

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

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

def slt_zero_ult_i1_fail2_after := [llvm|
{
^0(%arg6 : i32, %arg7 : i1):
  %0 = llvm.mlir.constant(31 : i32) : i32
  %1 = llvm.zext %arg7 : i1 to i32
  %2 = llvm.ashr %arg6, %0 : i32
  %3 = llvm.icmp "ugt" %2, %1 : i32
  "llvm.return"(%3) : (i1) -> ()
}
]

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

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

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

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

def test10_after := [llvm|
{
^0(%arg187 : i16):
  "llvm.return"(%arg187) : (i16) -> ()
}
]

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

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

def or_lshr_before := [llvm|
{
^0(%arg628 : i8, %arg629 : i8, %arg630 : i8, %arg631 : i8):
  %0 = llvm.lshr %arg628, %arg631 : i8
  %1 = llvm.lshr %arg629, %arg631 : i8
  %2 = llvm.or %0, %arg630 : i8
  %3 = llvm.or %1, %2 : i8
  "llvm.return"(%3) : (i8) -> ()
}
]

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

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

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

def alive_Select_1105_src  (w : Nat)   :=
[llvm( w )| {
^bb0(%Y : _, %X : _):
  %v1 = llvm.mlir.constant 0 :  i1
  %v2 = llvm.select %v1,%X, %Y
  llvm.return %v2
}]

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

def sext_multiuse_after := [llvm|
{
^0(%arg5 : i4):
  %0 = llvm.mlir.constant(-8 : i4) : i4
  %1 = llvm.xor %arg5, %0 : i4
  %2 = llvm.zext %1 : i4 to i7
  %3 = llvm.sext %arg5 : i4 to i7
  %4 = llvm.sdiv %2, %3 : i7
  %5 = llvm.trunc %4 : i7 to i4
  %6 = llvm.sdiv %5, %1 : i4
  "llvm.return"(%6) : (i4) -> ()
}
]

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

def add_mask_ashr28_non_pow2_i32_after := [llvm|
{
^0(%arg1 : i32):
  %0 = llvm.mlir.constant(28 : i32) : i32
  %1 = llvm.mlir.constant(9 : i32) : i32
  %2 = llvm.ashr %arg1, %0 : i32
  %3 = llvm.and %2, %1 : i32
  %4 = llvm.add %3, %2 overflow<nsw> : i32
  "llvm.return"(%4) : (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 slli_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where
  lhs := slli_llvm_i32
  rhs := slli_riscv_i32

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

def shl_sub_lshr_before := [llvm|
{
^0(%arg139 : i32, %arg140 : i32, %arg141 : i32):
  %0 = llvm.shl %arg139, %arg140 overflow<nuw> : i32
  %1 = llvm.sub %0, %arg141 overflow<nsw,nuw> : i32
  %2 = llvm.lshr exact %1, %arg140 : i32
  "llvm.return"(%2) : (i32) -> ()
}
]

def and_orn_xor_after := [llvm|
{
^0(%arg80 : i4, %arg81 : i4):
  %0 = llvm.mlir.constant(-1 : i4) : i4
  %1 = llvm.xor %arg80, %0 : i4
  %2 = llvm.and %arg81, %1 : i4
  "llvm.return"(%2) : (i4) -> ()
}
]

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

def sext_shl_mask_after := [llvm|
{
^0(%arg7 : i16, %arg8 : i32):
  %0 = llvm.mlir.constant(65535 : i32) : i32
  %1 = llvm.zext %arg7 : i16 to i32
  %2 = llvm.shl %1, %arg8 : i32
  %3 = llvm.and %2, %0 : i32
  "llvm.return"(%3) : (i32) -> ()
}
]

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

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

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

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 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 sextinreg_before := [llvm|
{
^0(%arg14 : i32):
  %0 = llvm.mlir.constant(65535 : i32) : i32
  %1 = llvm.mlir.constant(-32768 : i32) : i32
  %2 = llvm.mlir.constant(32768 : i32) : i32
  %3 = llvm.and %arg14, %0 : i32
  %4 = llvm.xor %3, %1 : i32
  %5 = llvm.add %4, %2 : i32
  "llvm.return"(%5) : (i32) -> ()
}
]

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

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

def packSelect := [DC_com| {
  ^entry(%0: !ValueStream_Int, %1: !ValueStream_Int, %2: !ValueStream_Int, %3: !ValueStream_Bool):
    %unpack0 = "DC.unpack" (%0) : (!ValueStream_Int) -> (!ValueTokenStream_Int)
    %unpack1 = "DC.unpack" (%1) : (!ValueStream_Int) -> (!ValueTokenStream_Int)
    %unpack2 = "DC.unpack" (%2) : (!ValueStream_Int) -> (!ValueTokenStream_Int)
    %unpack01 = "DC.fstVal" (%unpack0) : (!ValueTokenStream_Int) -> (!ValueStream_Int)
    %unpack02 = "DC.sndVal" (%unpack0) : (!ValueTokenStream_Int) -> (!TokenStream)
    %unpack11 = "DC.fstVal" (%unpack1) : (!ValueTokenStream_Int) -> (!ValueStream_Int)
    %unpack12 = "DC.sndVal" (%unpack1) : (!ValueTokenStream_Int) -> (!TokenStream)
    %unpack21 = "DC.fstVal" (%unpack2) : (!ValueTokenStream_Int) -> (!ValueStream_Int)
    %unpack22 = "DC.sndVal" (%unpack2) : (!ValueTokenStream_Int) -> (!TokenStream)
    
    
    
    %pack1 = "DC.pack" (%3, %unpack02) : (!ValueStream_Bool, !TokenStream) -> (!ValueStream_Bool)
    %select = "DC.select" (%unpack22, %unpack12, %pack1) : (!TokenStream, !TokenStream, !ValueStream_Bool) -> (!TokenStream)
    %pack2 = "DC.pack" (%unpack21, %select) : (!ValueStream_Int, !TokenStream) -> (!ValueStream_Int)
    "return" (%pack2) : (!ValueStream_Int) -> ()
  }]

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

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

@[simp_denote]
def srl_riscv_i32 :=
  [LV| {
    ^entry (%arg0: i32, %arg1: i32):
    %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64)
    %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64)
    %0 = srlw %a, %b : !i64
    %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32)
    llvm.return %1 : i32
  }]

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

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

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

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

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

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

def NFA'.sa2 (M : NFA' 2) := M.σ → BVRel

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

<all_available_lemmas>
Option.mem_def in Init.Data.Option.Instances
Option.bind_eq_bind in Init.Data.Option.Lemmas
Option.bind_eq_some_iff in Init.Data.Option.Lemmas
Option.dite_none_right_eq_some in Init.Data.Option.Lemmas
Option.pure_def in Init.Data.Option.Lemmas
cast_eq in Init.Core

theorem Com.denoteLets_eq {com : Com d Γ eff t} : com.denoteLets = com.toLets.denote

@[simp] theorem Lets.denote_var {lets : Lets d Γ_in eff Γ_out} {e : Expr d Γ_out eff t} :
    (lets.var e).denote = fun V_in => lets.denote V_in >>= e.denote

@[simp] theorem denote_toCom [LawfulMonad d.m] (zip : Zipper d Γ_in eff ty) :
    zip.toCom.denote = zip.denote

@[simp] theorem Com.denoteLets_returnVars (c : Com d Γ .pure tys) (V : Valuation Γ) :
    c.returnVars.map (c.denoteLets V) = c.denote V

theorem Id.bind_eq' (x : Id α) (f : α → id β) : x >>= f = f x

theorem Id.pure_eq' (a : α) : (pure a : Id α) = a

theorem denote_matchLets_of
    (map : MatchArgResult lets matchLets vs ws mapIn)
    (hvars : ∀ t (v : Var Δ_in t), ⟨t, v⟩ ∈ matchLets.varsOfVec ws)
    (V : lets.ValidDenotation) :
    ws.map (matchLets.denote (V.val.comap <| map.toHom h)) = vs.map V.val

theorem denote_matchArg
    {vs ws : HVector (Var _) ts}
    (mapOut : MatchArgResult lets matchLets vs ws mapIn)
    (V : lets.ValidDenotation) :
    HVector.map (matchLets.denote (mapOut.val.mapValuation V.val)) ws = HVector.map (V.val) vs

theorem HVector.map_eq_map_of_matchArg
    {lets : Lets d Γ_in eff Γ_out}
    {matchLets : Lets d Δ_in .pure Δ_out}
    {ma : Mapping Δ_in Γ_out}
    {l : List d.Ty} {args₁ : HVector _ l} {args₂ : HVector _ l}
    (mapOut : MatchArgResult lets matchLets args₁ args₂ ma)
    (f₁ f₂ : (t : d.Ty) → Var _ t → ⟦t⟧)
    (hf : ∀ {t v₁ v₂},
      (mapOut' : MatchVarResult lets v₁ matchLets v₂ ma)
      → mapOut'.val = mapOut.val
      → f₂ t v₂ = f₁ t v₁) :
    HVector.map f₂ args₂ = HVector.map f₁ args₁

theorem denote_matchVar
    {v w : Var _ t}
    (mapOut : MatchVarResult lets v matchLets w mapIn)
    (V : lets.ValidDenotation) :
    (matchLets.denote (mapOut.val.mapValuation V.val) w)
    = V.val v

theorem getPureExpr_eq_some
    (mapOut : MatchVarResult lets v (.var matchLets matchExpr) w.appendInl mapIn) :
    ∃ args, lets.getPureExpr v = some ⟨te, w, ⟨
        matchExpr.op,
        matchExpr.ty_eq,
        matchExpr.eff_le,
        args,
        matchExpr.regArgs
      ⟩⟩

theorem matchVar_appendInl {w : Var ⟨te⟩ t} :
    matchVar lets v (.var matchLets matchExpr) w.appendInl ma = some ma' →
    ∃ args,
      lets.getPureExpr v
        = some ⟨_, w, matchExpr.op, matchExpr.ty_eq, matchExpr.eff_le, args, matchExpr.regArgs⟩
      ∧ matchArg lets matchLets args matchExpr.args ma = some ma'

@[simp]
theorem MatchVar.liftM_bind_eq_some_iff (x? : Option α)
    (f : α → MatchVarM Δ Γ β) :
    ((liftM x? >>= f) mapIn = some mapOut)
    ↔ ( ∃ h : x?.isSome,
        f (x?.get h) mapIn = some mapOut )

@[simp] theorem Com.denote_changeVars
    (varsMap : Γ.Hom Γ') (c : Com d Γ eff ty) :
    (c.changeVars varsMap).denote =
    fun V => c.denote (V.comap varsMap)

theorem denote_insertPureCom_eq_of [LawfulMonad d.m]
    {zip : Zipper d Γ_in eff tys} {vs}
    {newCom : Com d zip.Γ_mid .pure newTys} {V_in : Valuation Γ_in}
    (h : ∀ V : zip.top.ValidDenotation,
        newCom.denote V.val = vs.map V.val) :
    (zip.insertPureCom vs newCom).denote V_in = zip.denote V_in

theorem denote_insertPureCom {zip : Zipper d Γ_in eff t₁} [LawfulMonad d.m]
    {newCom : Com d zip.Γ_mid .pure newTys} {vs : HVector zip.Γ_mid.Var newTys} :
    (zip.insertPureCom vs newCom).denote = (fun (V_in : Valuation Γ_in) => do
      let V_mid ← zip.top.denote V_in
      zip.bot.denote
        ((Com.denoteLets newCom V_mid).comap <| newCom.outContextHom.with vs newCom.returnVars)
      )

theorem denote_insertCom {zip : Zipper d Γ_in eff t₁} [LawfulMonad d.m]
    {newCom : Com d zip.Γ_mid eff newTys} {vs : HVector zip.Γ_mid.Var newTys} :
    (zip.insertCom vs newCom).denote = (fun (V_in : Valuation Γ_in) => do
      let V_mid ← zip.top.denote V_in
      let V_newMid ← newCom.denoteLets V_mid
      zip.bot.denote
        (V_newMid.comap <| newCom.outContextHom.with vs newCom.returnVars)
      )

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

theorem ashrsgt_03_14_proof : ashrsgt_03_14_before ⊑ ashrsgt_03_14_after

theorem negative_trunc_not_arg_logical_proof : negative_trunc_not_arg_logical_before ⊑ negative_trunc_not_arg_logical_after

@[bv_mba_preprocess]
theorem BitVec.neg_sub {x y : BitVec w} : - (x - y) = (-x) + y

theorem addhshlhsdivhnegative0_proof : addhshlhsdivhnegative0_before ⊑ addhshlhsdivhnegative0_after

theorem bools_multi_uses2_logical_thm.extracted_1._36 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 ^^^ 1#1 = 1#1 → ¬x_2 = 1#1 → 0#1 = 1#1 → ¬x_1 = 1#1 → ¬True → 0#1 + 0#1 = 0#1

theorem test1_proof : test1_before ⊑ test1_after

theorem test20_proof : test20_before ⊑ test20_after

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

theorem e_573 :
    4 *  ~~~(x ^^^ y) + 2 * (x |||  ~~~y) - 2 *  ~~~(x &&&  ~~~y) + 4 * (x ||| y) - 11 *  ~~~(x &&& y) + 18 *  ~~~(x ||| y) + 25 *  ~~~(x |||  ~~~y) + 16 * (x &&&  ~~~y) + 8 * (x &&& y) = 11 *  ~~~(x &&&  ~~~x) + 5 * y

theorem select_constants_and_icmp_eq0_proof : select_constants_and_icmp_eq0_before ⊑ select_constants_and_icmp_eq0_after

theorem or_signbit_select_ashr_proof : or_signbit_select_ashr_before ⊑ or_signbit_select_ashr_after

theorem lshr_mul_times_3_div_2_exact_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬(True ∧ x.smulOverflow 3#32 = true ∨ True ∧ (x * 3#32) >>> 1#32 <<< 1#32 ≠ x * 3#32 ∨ 1#32 ≥ ↑32) →
    True ∧ x >>> 1#32 <<< 1#32 ≠ x ∨ 1#32 ≥ ↑32 ∨ True ∧ x.saddOverflow (x >>> 1#32) = true → False

theorem sgt_and_not_min_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x <ₛ x_1) &&& ofBool (x_1 != BitVec.ofInt 8 (-128)) = ofBool (x <ₛ x_1)

theorem addhshlhsdivhnegative0_thm (e : IntW 8) :
  add (shl (LLVM.sdiv e (const? 8 4)) (const? 8 2)) e ⊑
    add (shl (LLVM.sdiv e (const? 8 4)) (const? 8 2) { «nsw» := true, «nuw» := false }) e

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)

theorem masked_icmps_bmask_notmixed_and_proof : masked_icmps_bmask_notmixed_and_before ⊑ masked_icmps_bmask_notmixed_and_after

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

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

theorem ashr_eq_both_equal_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬x ≥ ↑8 → ofBool ((BitVec.ofInt 8 (-128)).sshiftRight' x == BitVec.ofInt 8 (-128)) = ofBool (x == 0#8)

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 ashrsgt_01_03_exact_proof : ashrsgt_01_03_exact_before ⊑ ashrsgt_01_03_exact_after

theorem test22_thm (e : IntW 32) : shl (sext 32 (trunc 8 e)) (const? 32 24) ⊑ shl e (const? 32 24)

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

theorem add_mask_sign_i32_thm (e : IntW 32) :
  add (LLVM.and (ashr e (const? 32 31)) (const? 32 8)) (ashr e (const? 32 31)) ⊑
    select (icmp IntPred.slt e (const? 32 0)) (const? 32 7) (const? 32 0)

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

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

theorem sub_select_not_sext_proof : sub_select_not_sext_before ⊑ sub_select_not_sext_after

theorem not_signbit_zext_thm (e : IntW 16) :
  zext 32 (lshr (LLVM.xor e (const? 16 (-1))) (const? 16 15)) ⊑
    zext 32 (icmp IntPred.sgt e (const? 16 (-1)))

theorem ashr_lshr2_proof : ashr_lshr2_before ⊑ ashr_lshr2_after

theorem xor_logic_and_or2_thm.extracted_1._3 : ∀ (x x_1 x_2 : BitVec 1),
  ¬x_2 = 1#1 → x_1 = 1#1 → 0#1 ^^^ (x_1 ||| x) = x_2 ^^^ 1#1

theorem lshr_shl_pow2_const_case2_thm (e : IntW 16) :
  LLVM.and (shl (lshr (const? 16 8192) e) (const? 16 4)) (const? 16 32) ⊑
    select (icmp IntPred.eq e (const? 16 12)) (const? 16 32) (const? 16 0)

theorem eval_fsmTermUle_eq_decide_le {wcard tcard : Nat}
    (tctx : Term.Ctx wcard tcard)
    {wenv : WidthExpr.Env wcard}
    (tenv : tctx.Env wenv)
    (benv : Term.BoolEnv bcard)
    (nenv : Term.NatEnv ncard)
    (ienv : Term.IntEnv icard)
    (w : WidthExpr wcard)
    (a : Term bcard ncard icard pcard tctx (.bv w))
    (b : Term bcard ncard icard pcard tctx (.bv w))
    (afsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm a))
    (hafsm : HTermFSMToBitStream afsm)
    (bfsm : TermFSM wcard tcard bcard ncard icard pcard (.ofDepTerm b))
    (hbfsm : HTermFSMToBitStream bfsm)
    (fsmEnv : StateSpace wcard tcard bcard ncard icard pcard → BitStream)
    (henv : HTermEnv fsmEnv tenv benv)
    :
    ((fsmTermUle
      afsm
      bfsm)).eval fsmEnv i =
       decide (((a.toBV benv nenv ienv penv tenv).setWidth i) ≤ ((b.toBV benv nenv ienv penv tenv).setWidth i))

theorem main15_proof : main15_before ⊑ main15_after

theorem udiv_illegal_type_proof : udiv_illegal_type_before ⊑ udiv_illegal_type_after

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

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

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

theorem pr51551_thm (e e_1 : IntW 32) :
  icmp IntPred.eq
      (LLVM.and (mul (LLVM.or (LLVM.and e_1 (const? 32 (-7))) (const? 32 1)) e { «nsw» := true, «nuw» := false })
        (const? 32 3))
      (const? 32 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 3)) (const? 32 0)

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 one_side_fold_sgt_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → ¬x_1 ^^^ 1#1 = 1#1 → ofBool (x <ₛ x) = 0#1

theorem lshr_mul_times_5_div_4_exact_2_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬(True ∧ x.umulOverflow 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.uaddOverflow (x >>> 2#32) = true) →
      (x * 5#32) >>> 2#32 = x + x >>> 2#32

theorem e_1683 :
    1 *  ~~~(a ||| c) + 1 * (c |||  ~~~(a |||  ~~~b)) + 4 *  ~~~(a &&& b) - 1 * ((b &&& c) ^^^  ~~~(a &&& (b ^^^ c))) - 2 * ((a &&&  ~~~b) ||| (b ^^^ c)) - 1 *  ~~~(a &&& ( ~~~b &&& c)) + 11 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c))) + 4 * (b ^^^  ~~~( ~~~a &&& (b ||| c))) + 11 * (a ||| (b ^^^ c)) + 1 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) - 5 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) + 1 * (b ^^^ (a &&&  ~~~c)) + 7 * (c ^^^ ( ~~~a ||| (b &&& c))) - 3 * ( ~~~c |||  ~~~(a ^^^ b)) + 7 * (c ^^^  ~~~(a ||| b)) + 5 * (a ||| (b &&& c)) + 5 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c))) - 2 * (c |||  ~~~(a ||| b)) - 1 * ((a &&& b) ^^^ (a ^^^ (b &&& c))) - 16 *  ~~~(a ||| (b ||| c)) - 21 *  ~~~(a ||| ( ~~~b ||| c)) - 33 *  ~~~( ~~~a ||| (b ||| c)) - 21 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 18 * ( ~~~a &&& ( ~~~b &&& c)) - 13 * ( ~~~a &&& (b &&& c)) - 35 * (a &&& ( ~~~b &&& c)) - 18 * (a &&& (b &&& c)) = 6 * ( ~~~(a |||  ~~~b) |||  ~~~(a ^^^ (b ^^^ c)))

theorem t1_flags_nuw_only_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8),
  ¬(True ∧ x_2.usubOverflow x_1 = true ∨ True ∧ (x_2 - x_1).usubOverflow x = true) →
    True ∧ x_1.uaddOverflow x = true ∨ True ∧ x_2.usubOverflow (x_1 + x) = true → False

theorem alive_AndOrXor_2417  (w : Nat)   : alive_AndOrXor_2417_src w  ⊑ alive_AndOrXor_2417_tgt w

theorem shl_trunc_bigger_lshr_proof : shl_trunc_bigger_lshr_before ⊑ shl_trunc_bigger_lshr_after

theorem trunc_lshr_sext_wide_input_exact_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(True ∧ signExtend 32 x >>> 9#32 <<< 9#32 ≠ signExtend 32 x ∨ 9#32 ≥ ↑32) →
    True ∧ x >>> 9#16 <<< 9#16 ≠ x ∨
        9#16 ≥ ↑16 ∨ True ∧ signExtend 16 (truncate 8 (x.sshiftRight' 9#16)) ≠ x.sshiftRight' 9#16 →
      False

theorem test2_thm (e : IntW 15) : LLVM.and e (const? 15 (-1)) ⊑ e

theorem lshrult_03_03_exact_proof : lshrult_03_03_exact_before ⊑ lshrult_03_03_exact_after

theorem shl_ashr_pow2_const_case1_proof : shl_ashr_pow2_const_case1_before ⊑ shl_ashr_pow2_const_case1_after

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

theorem negate_ashr_proof : negate_ashr_before ⊑ negate_ashr_after

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

theorem ashr_sub_nsw_proof : ashr_sub_nsw_before ⊑ ashr_sub_nsw_after

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

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

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

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

theorem src_is_notmask_x_xor_neg_x_inv_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → ofBool (BitVec.ofInt 8 (-8) &&& (x ^^^ 123#8) == 0#8) = ofBool (x ^^^ 123#8 ≤ᵤ 7#8)

@[simp]
theorem Term.toBV_bnot {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)) :
  Term.toBV benv nenv ienv penv tenv (.bnot a) = ~~~ (a.toBV benv nenv ienv penv tenv)

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

@[simp]
theorem flipAccept_eval {M : NFA α σ} : M.flipAccept.eval w = M.eval w

@[simp] theorem Expr.changeVars_id (e : Expr d Γ eff t) :
    e.changeVars .id = e

theorem or_comm (x y : BitStream) : x ||

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

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

theorem shl_nuw_add_proof : shl_nuw_add_before ⊑ shl_nuw_add_after

theorem test_shl__nsw_is_safe_proof : test_shl__nsw_is_safe_before ⊑ test_shl__nsw_is_safe_after

theorem test2_thm (e : IntW 1005) : LLVM.xor e (const? 1005 0) ⊑ e

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

theorem test19_thm.extracted_1._1 : ∀ (x : BitVec 10),
  ¬(2#3 ≥ ↑3 ∨ 2#3 ≥ ↑3) → True ∧ (0#3).ssubOverflow (truncate 3 x &&& 1#3) = true → False

theorem modulo2_proof : modulo2_before ⊑ modulo2_after

theorem pr40493_neg1_proof : pr40493_neg1_before ⊑ pr40493_neg1_after

theorem bv_152 :
    ∀ (e : LLVM.IntW w), LLVM.mul e (LLVM.const? w (-1)) ⊑ LLVM.sub (LLVM.const? w 0) e

@[simp] theorem nxor_eq : (x.nxor y) i = (x i == y i)

theorem src_is_mask_zext_thm.extracted_1._1 : ∀ (x : BitVec 8) (x_1 : BitVec 16),
  ¬x ≥ ↑8 →
    ofBool ((x_1 ^^^ 123#16) &&& zeroExtend 16 ((-1#8) >>> x) == x_1 ^^^ 123#16) =
      ofBool (x_1 ^^^ 123#16 ≤ᵤ zeroExtend 16 ((-1#8) >>> x))

theorem lshrugt_02_07_exact_proof : lshrugt_02_07_exact_before ⊑ lshrugt_02_07_exact_after

@[simp] lemma eval_single [DecidableEq α] {s : List α} (x : ∀ a ∈ s, Bool) (g : α → Bool):
  eval (single x) g ↔ (∀ a (ha : a ∈ s), g a = x a (by simpa))

theorem t_0_1_proof : t_0_1_before ⊑ t_0_1_after

theorem signbit_splat_mask_proof : signbit_splat_mask_before ⊑ signbit_splat_mask_after

theorem test24_logical_proof : test24_logical_before ⊑ test24_logical_after

theorem e_2441 :
    2 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) + 11 * (f &&& (d ||| e)) + 4 * (e ^^^ (d &&& (e ^^^ f))) - 11 * (f ||| (d ^^^ e)) - 7 * ( ~~~(d |||  ~~~e) |||  ~~~(e ^^^ f)) - 2 * (f ^^^ (d |||  ~~~e)) - 6 * (e ||| f) - 5 * (e ^^^ (d &&& (e ||| f))) + 7 * (e &&&  ~~~(d ^^^ f)) - 7 * (e ^^^  ~~~(d ||| (e &&& f))) + 2 *  ~~~(d ||| f) - 1 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 2 * (f &&&  ~~~(d &&& e)) - 1 * (d |||  ~~~f) + 1 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) + 3 * (e &&& (d ^^^ f)) - 2 * (f ||| (d &&&  ~~~e)) - 2 * ((d &&& f) ^^^ (e ||| f)) - 1 * (f ^^^ (d ||| ( ~~~e ||| f))) - 11 * (f &&&  ~~~(d &&&  ~~~e)) + 2 * (f ^^^ (d &&&  ~~~e)) - 2 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 1 * (d ^^^ e) - 1 * ( ~~~d &&& (e ||| f)) + 1 * (e ^^^  ~~~(d &&& (e ||| f))) + 4 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) + 1 * (d &&&  ~~~e) + 1 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 7 * (e ^^^ (d &&&  ~~~f)) - 2 * (d &&&  ~~~f) - 1 * ((d &&& e) ||| (d ^^^ (e ^^^ f))) - 11 *  ~~~(d &&&  ~~~d) - 5 * (e ^^^ ( ~~~d ||| (e &&& f))) - 11 * ( ~~~e &&& (d ^^^ f)) - 2 * (e ||| (d &&&  ~~~f)) + 7 * (e ^^^ (d &&& ( ~~~e ||| f))) + 1 * e + 1 * ( ~~~f &&&  ~~~(d ^^^ e)) + 1 * (f ^^^  ~~~(d &&& ( ~~~e &&& f))) - 3 * ((e &&&  ~~~f) ^^^ ( ~~~d ||| (e ^^^ f))) + 1 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 1 * (e ||| (d ^^^ f)) + 2 * ( ~~~e |||  ~~~(d ^^^ f)) + 1 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) + 1 *  ~~~(d &&&  ~~~f) + 1 * (f ^^^  ~~~(d &&& e)) - 2 * ( ~~~f &&& (d ^^^ e)) - 1 *  ~~~(d &&& f) - 2 * (d &&& f) - 11 * (e ^^^  ~~~(d &&& (e ^^^ f))) - 6 * ( ~~~e ||| (d ^^^ f)) + 11 * (e ^^^  ~~~( ~~~d &&& (e &&& f))) + 5 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) - 2 *  ~~~(e |||  ~~~f) + 4 * ((d ^^^ e) ||| (d ^^^ f)) - 3 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * (e &&& (d ||| f)) + 4 *  ~~~(d ||| (e ^^^ f)) + 11 * (e |||  ~~~f) - 1 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 4 * (f |||  ~~~(d |||  ~~~e)) + 1 *  ~~~(d ^^^ ( ~~~e &&& f)) - 5 * (f ^^^  ~~~(d |||  ~~~e)) - 3 * (e ^^^ f) - 1 * (d ||| f) - 11 * (e &&& f) + 2 * f - 1 * ( ~~~d ||| (e &&& f)) + 12 *  ~~~(d ||| (e ||| f)) - 1 *  ~~~(d ||| ( ~~~e ||| f)) + 15 *  ~~~( ~~~d ||| (e ||| f)) + 35 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 66 * ( ~~~d &&& ( ~~~e &&& f)) + 6 * ( ~~~d &&& (e &&& f)) + 10 * (d &&& ( ~~~e &&& f)) + 17 * (d &&& (e &&& f)) = 1 *  ~~~e

theorem xor_to_xor2_thm (e e_1 : IntW 32) : LLVM.xor (LLVM.and e_1 e) (LLVM.or e e_1) ⊑ LLVM.xor e_1 e

theorem logical_and_bitwise_and_icmps_comm1_proof : logical_and_bitwise_and_icmps_comm1_before ⊑ logical_and_bitwise_and_icmps_comm1_after

theorem samesign_inverted_commute1_proof : samesign_inverted_commute1_before ⊑ samesign_inverted_commute1_after

theorem eq_smax3_proof : eq_smax3_before ⊑ eq_smax3_after

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

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

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

theorem select_icmp_ne_not_pow2_thm (e : IntW 8) :
  select (icmp IntPred.ne (LLVM.and e (const? 8 5)) (const? 8 0)) (LLVM.xor e (const? 8 5)) e ⊑
    select (icmp IntPred.eq (LLVM.and e (const? 8 5)) (const? 8 0)) e (LLVM.xor e (const? 8 5))

@[simp_denote, simp]
theorem toOption_getSome : (PoisonOr.value x).toOption.getD y = x

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

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

theorem foo1_and_signbit_lshr_without_shifting_signbit_logical_proof : foo1_and_signbit_lshr_without_shifting_signbit_logical_before ⊑ foo1_and_signbit_lshr_without_shifting_signbit_logical_after

theorem icmp_equality_test_commute_icmp1_proof : icmp_equality_test_commute_icmp1_before ⊑ icmp_equality_test_commute_icmp1_after

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

theorem test_sub_nuw__none_are_safe_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x == 1#32) = 1#1 → 2147483647#32 = BitVec.ofInt 32 (-2147483648) - x

theorem PR2539_B_proof : PR2539_B_before ⊑ PR2539_B_after

theorem add_nsw_thm (e : IntW 8) (e_1 : IntW 1) :
  add (select e_1 e (const? 8 7)) (const? 8 64) { «nsw» := true, «nuw» := false } ⊑
    select e_1 (add e (const? 8 64) { «nsw» := true, «nuw» := false }) (const? 8 71)

theorem masked_or_allzeroes_proof : masked_or_allzeroes_before ⊑ masked_or_allzeroes_after

theorem test1_thm (e : IntW 33) : LLVM.udiv e (const? 33 4096) ⊑ lshr e (const? 33 12)

theorem no_shift_no_xor_multiuse_xor_proof : no_shift_no_xor_multiuse_xor_before ⊑ no_shift_no_xor_multiuse_xor_after

theorem and_two_ranges_to_mask_and_range_thm (e : IntW 8) :
  LLVM.and (icmp IntPred.ugt (add e (const? 8 (-97))) (const? 8 25))
      (icmp IntPred.ugt (add e (const? 8 (-65))) (const? 8 25)) ⊑
    icmp IntPred.ult (add (LLVM.and e (const? 8 (-33))) (const? 8 (-91))) (const? 8 (-26))

theorem shl_add_and_proof : shl_add_and_before ⊑ shl_add_and_after

theorem test13_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬zeroExtend 128 x &&& 31#128 ≥ ↑128 → True ∧ (x &&& 31#32).msb = true ∨ zeroExtend 64 (x &&& 31#32) ≥ ↑64 → False

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

theorem zext_mul_proof : zext_mul_before ⊑ zext_mul_after

@[simp]
lemma product_stepSet {M : NFA α σ} {N : NFA α ς} :
    (M.product accept? N).stepSet (S1 ×ˢ S2) a = ((M.stepSet S1 a) ×ˢ (N.stepSet S2 a))

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

theorem test_logical_thm.extracted_1._1 : ∀ (x : BitVec 32), ¬ofBool (13#32 <ᵤ x) = 1#1 → 0#1 = ofBool (x == 15#32)

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

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

theorem or2 {v w k l : Nat} (a : BitVec k) : v < w ∨ w < v ∨ 
  (a.setWidth v).setWidth l = (a.setWidth w).setWidth l

@[simp] theorem HVector.vars_cons {t  : d.Ty} {l : List d.Ty}
    (v : Var Γ t) (T : HVector (Var Γ) l) :
    (HVector.cons v T).vars = insert ⟨_, v⟩ T.vars

theorem e_1467 :
    1 * (z |||  ~~~t) - 2 *  ~~~(z ^^^ t) + 11 *  ~~~(z &&& t) + 1 * (z ^^^ t) + 3 *  ~~~t - 5 * t - 5 *  ~~~(z &&&  ~~~t) - 10 *  ~~~(z ||| t) - 4 *  ~~~(z |||  ~~~t) - 18 * (z &&&  ~~~t) + 9 * (z &&& t) =  - 2 *  ~~~(z &&&  ~~~z)

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

theorem n0_proof : n0_before ⊑ n0_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_7_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_7_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_7_logical_after

theorem icmp_eq_and_pow2_lshr_pow2_proof : icmp_eq_and_pow2_lshr_pow2_before ⊑ icmp_eq_and_pow2_lshr_pow2_after

theorem t10_shift_by_one_proof : t10_shift_by_one_before ⊑ t10_shift_by_one_after

theorem logic_and_logic_or_2_proof : logic_and_logic_or_2_before ⊑ logic_and_logic_or_2_after

theorem test_zext2_proof : test_zext2_before ⊑ test_zext2_after

theorem lshrult_02_06_exact_proof : lshrult_02_06_exact_before ⊑ lshrult_02_06_exact_after

theorem signbit_splat_mask_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ¬7#8 ≥ ↑8 → ofBool (x_1 <ₛ 0#8) = 1#1 → signExtend 16 (x_1.sshiftRight' 7#8) &&& x = x

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

theorem ne_210_thm (e e_1 : IntW 32) :
  LLVM.or (icmp IntPred.ne (trunc 8 (lshr e_1 (const? 32 16))) (trunc 8 (lshr e (const? 32 16))))
      (LLVM.or (icmp IntPred.ne (trunc 8 e_1) (trunc 8 e))
        (icmp IntPred.ne (trunc 8 (lshr e_1 (const? 32 8))) (trunc 8 (lshr e (const? 32 8))))) ⊑
    icmp IntPred.ne (trunc 24 e_1) (trunc 24 e)

theorem and2 : ∀ (w : Nat) (x : BitVec w), -1#w &&& x = x

theorem add_eq_xor_add_mul_and' (x y : BitVec w) :
    x + y = (x ^^^ y) + (x &&& y) + (x &&& y)

theorem test_sdiv_canonicalize_op0_thm (e e_1 : IntW 32) :
  LLVM.sdiv (sub (const? 32 0) e_1 { «nsw» := true, «nuw» := false }) e ⊑
    sub (const? 32 0) (LLVM.sdiv e_1 e) { «nsw» := true, «nuw» := false }

theorem test10_proof : test10_before ⊑ test10_after

theorem nonexact_lshr_eq_noexactdiv_proof : nonexact_lshr_eq_noexactdiv_before ⊑ nonexact_lshr_eq_noexactdiv_after

theorem sub_select_zext_op_swapped_non_const_args_thm (e e_1 : IntW 6) (e_2 : IntW 1) :
  sub (zext 6 e_2) (select e_2 e_1 e) ⊑ select e_2 (sub (const? 6 1) e_1) (sub (const? 6 0) e)

theorem scalar_i16_lshr_and_signbit_eq_proof : scalar_i16_lshr_and_signbit_eq_before ⊑ scalar_i16_lshr_and_signbit_eq_after

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

theorem positive_sameconst_shlnuwnsw_proof : positive_sameconst_shlnuwnsw_before ⊑ positive_sameconst_shlnuwnsw_after

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

theorem shift_xor_multiuse_and_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬ofBool (0#32 != x_1 &&& 4096#32) = 1#1 →
    ¬ofBool (x_1 &&& 4096#32 == 0#32) = 1#1 →
      (x &&& BitVec.ofInt 32 (-2049)) * (x &&& BitVec.ofInt 32 (-2049)) = x * (x &&& BitVec.ofInt 32 (-2049))

theorem test15j_proof : test15j_before ⊑ test15j_after

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

theorem src_is_mask_xor_thm (e e_1 : IntW 8) :
  icmp IntPred.ne (LLVM.and (LLVM.xor e_1 (const? 8 123)) (LLVM.xor e (add e (const? 8 (-1)))))
      (LLVM.xor e_1 (const? 8 123)) ⊑
    icmp IntPred.ugt (LLVM.xor e_1 (const? 8 123)) (LLVM.xor e (add e (const? 8 (-1))))

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

theorem lshr_lshr_pow2_const_negative_nopow2_1_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 6#16 ≥ ↑16) → x ≥ ↑16 → False

theorem lshrugt_01_00_proof : lshrugt_01_00_before ⊑ lshrugt_01_00_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 exact_lshr_eq_noexactdiv_proof : exact_lshr_eq_noexactdiv_before ⊑ exact_lshr_eq_noexactdiv_after

theorem test47_thm.extracted_1._1 : ∀ (x : BitVec 8),
  zeroExtend 64 (signExtend 32 x ||| 42#32) = zeroExtend 64 (signExtend 32 (x ||| 42#8))

theorem icmp_select_var_pred_ult_thm (e e_1 e_2 : IntW 8) :
  icmp IntPred.ult (select (icmp IntPred.eq e_2 (const? 8 0)) e_1 e)
      (add e_1 (const? 8 2) { «nsw» := false, «nuw» := true }) ⊑
    select (icmp IntPred.eq e_2 (const? 8 0)) (const? 1 1)
      (icmp IntPred.ult e (add e_1 (const? 8 2) { «nsw» := false, «nuw» := true }))

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

theorem ashrslt_02_09_proof : ashrslt_02_09_before ⊑ ashrslt_02_09_after

theorem substitute_constant_and_eq_ugt_swap_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ugt e_1 e) (icmp IntPred.eq e (const? 8 42)) (const? 1 0) ⊑
    LLVM.and (icmp IntPred.eq e (const? 8 42)) (icmp IntPred.ugt e_1 (const? 8 42))

theorem t4_proof : t4_before ⊑ t4_after

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

theorem positive_biggerashr_thm.extracted_1._1 : ∀ (x : BitVec 8), ¬(6#8 ≥ ↑8 ∨ 3#8 ≥ ↑8) → 3#8 ≥ ↑8 → False

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 positive_biggerashr_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(6#8 ≥ ↑8 ∨ 3#8 ≥ ↑8) → ¬3#8 ≥ ↑8 → x.sshiftRight' 6#8 <<< 3#8 = x.sshiftRight' 3#8 &&& BitVec.ofInt 8 (-8)

@[simp]
lemma autMsb_states : s ∈ CNFA.autMsbSet.m.states ↔ s < 2

theorem or_and_not_not_commute1_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 bv_AndOrXor_1280_ABA___AB :
    ∀ (e e_1 : LLVM.IntW w), LLVM.and (LLVM.or (LLVM.xor e (LLVM.const? w (-1))) e_1) e ⊑ LLVM.and e e_1

theorem test1_proof : test1_before ⊑ test1_after

theorem test5_thm (e : IntW 8) (e_1 : IntW 32) :
  urem e_1 (shl (const? 32 32) (zext 32 e)) ⊑
    LLVM.and e_1
      (add (shl (const? 32 32) (zext 32 e { «nneg» := true }) { «nsw» := false, «nuw» := true })
        (const? 32 (-1)))

theorem n9_wrong_x2_proof : n9_wrong_x2_before ⊑ n9_wrong_x2_after

theorem or_ranges_adjacent_proof : or_ranges_adjacent_before ⊑ or_ranges_adjacent_after

theorem same_signbit_wrong_type_proof : same_signbit_wrong_type_before ⊑ same_signbit_wrong_type_after

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

theorem e_2377 :
     - 1 * (f ^^^  ~~~(d |||  ~~~e)) + 1 * (f ^^^  ~~~(d ||| (e &&& f))) - 1 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 7 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 1 * (e ^^^  ~~~(d |||  ~~~f)) - 1 *  ~~~( ~~~d &&& (e ||| f)) + 3 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) + 5 * ( ~~~(d &&& e) &&& (d ^^^ (e ^^^ f))) - 3 * (e &&&  ~~~(d &&& f)) - 1 * (e ||| (d &&& f)) - 5 * (d &&&  ~~~e) + 4 * (d |||  ~~~f) + 1 *  ~~~( ~~~d &&& ( ~~~e &&& f)) - 7 * (e ^^^  ~~~(d &&& f)) - 1 *  ~~~(d ^^^ f) + 11 * ( ~~~e |||  ~~~(d ^^^ f)) - 2 * ( ~~~d ||| (e ||| f)) - 1 * (e ^^^ (d ||| (e ||| f))) - 1 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) - 11 * ( ~~~(d ^^^ e) &&&  ~~~(d ^^^ f)) + 5 * (e &&& f) + 1 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) - 2 *  ~~~d + 2 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 * ((d |||  ~~~e) &&& (e ^^^ f)) + 2 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 1 * (f ^^^ (d |||  ~~~e)) - 3 * ((e &&& f) ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 5 * ((d ||| e) &&&  ~~~(e ^^^ f)) + 3 *  ~~~(d &&&  ~~~e) + 5 * ( ~~~d &&& (e ^^^ f)) + 4 * (d ^^^ (e &&& f)) + 7 * ((d &&& f) ^^^ (d ^^^ ( ~~~e &&& f))) - 2 * (e |||  ~~~f) + 1 * ((d &&&  ~~~e) ||| (e ^^^ f)) - 1 *  ~~~(e ^^^ f) - 2 * (e ^^^ (d &&& (e ^^^ f))) - 5 * (f &&&  ~~~(d &&&  ~~~e)) - 1 * ((d &&& e) ^^^ (e |||  ~~~f)) + 2 * ((d &&& e) ^^^  ~~~(d ^^^ (e &&& f))) + 4 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 5 * (f ^^^ (d ||| ( ~~~e ||| f))) - 6 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 7 * ( ~~~(d &&& e) &&&  ~~~(d ^^^ (e ^^^ f))) - 11 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 11 * (f ||| (d &&&  ~~~e)) - 3 * (e &&& (d ||| f)) + 2 * (e |||  ~~~(d ^^^ f)) + 11 * ( ~~~(d ^^^ e) |||  ~~~(d ^^^ f)) + 2 * (d &&& ( ~~~e ||| f)) - 1 * (f ||| (d ^^^ e)) + 11 * (f ^^^ (d ||| ( ~~~e &&& f))) - 5 * (e ^^^  ~~~(d &&& (e &&& f))) - 2 * (f ^^^ (d &&& ( ~~~e ||| f))) - 1 * (d &&& (e ||| f)) - 1 * (f &&& (d ||| e)) - 2 *  ~~~(d ^^^ e) + 11 *  ~~~( ~~~d ||| (e &&& f)) + 2 * (f ^^^ ( ~~~d ||| ( ~~~e ||| f))) + 1 *  ~~~( ~~~d ||| ( ~~~e &&& f)) - 11 *  ~~~(d &&& ( ~~~e ||| f)) + 1 * (f |||  ~~~(d |||  ~~~e)) + 29 *  ~~~(d ||| (e ||| f)) + 8 *  ~~~(d ||| ( ~~~e ||| f)) - 35 *  ~~~( ~~~d ||| (e ||| f)) - 29 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 20 * ( ~~~d &&& ( ~~~e &&& f)) + 20 * ( ~~~d &&& (e &&& f)) + 2 * (d &&& ( ~~~e &&& f)) + 21 * (d &&& (e &&& f)) = 11 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f)))

theorem lshr_shl_pow2_const_xor_thm.extracted_1._2 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 2#16 ≥ ↑16) → ¬ofBool (x == 7#16) = 1#1 → 256#16 >>> x <<< 2#16 &&& 8#16 ^^^ 8#16 = 8#16

theorem lshrugt_01_15_proof : lshrugt_01_15_before ⊑ lshrugt_01_15_after

@[simp]
theorem mkCarryAssignCircuitNAux_eval_eq {arity : Type _}
    [DecidableEq arity]
    [Fintype arity]
    [Hashable arity]
    (p : FSM arity) (s : p.α) (n : Nat)
    {env : Vars p.α arity (n + 1) → Bool} :
    ((mkCarryAssignCircuitNAux p s n).eval env) = ((p.nextStateCirc s).eval
      (fun x => match x with | .inl x => env (Vars.stateN x n) | .inr x => env (Vars.inputN x n)))

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

theorem sge_swap_or_max_thm (e e_1 : IntW 8) :
  LLVM.or (icmp IntPred.sle e_1 e) (icmp IntPred.eq e (const? 8 127)) ⊑ icmp IntPred.sle e_1 e

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 pow2_or_zero_is_not_negative_commute_proof : pow2_or_zero_is_not_negative_commute_before ⊑ pow2_or_zero_is_not_negative_commute_after

theorem bools_multi_uses1_logical_proof : bools_multi_uses1_logical_before ⊑ bools_multi_uses1_logical_after

@[simp] theorem pure_le (e : EffectKind) : pure ≤ e

theorem not_signbit_trunc_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬15#16 ≥ ↑16 → truncate 8 ((x ^^^ -1#16) >>> 15#16) = zeroExtend 8 (ofBool (-1#16 <ₛ x))

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 test14_thm.extracted_1._1 : ∀ (x : BitVec 16),
  4#16 ≥ ↑16 ∨ True ∧ (x >>> 4#16 &&& 1#16).saddOverflow (-1#16) = true → False

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

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_1_thm (e : IntW 32) :
  LLVM.or (icmp IntPred.ne (LLVM.and e (const? 32 7)) (const? 32 1))
      (icmp IntPred.eq (LLVM.and e (const? 32 12)) (const? 32 0)) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 15)) (const? 32 9)

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

theorem test19_thm.extracted_1._1 : ∀ (x x_1 : BitVec 1),
  ofBool (zeroExtend 32 x_1 == zeroExtend 32 x) = x_1 ^^^ x ^^^ 1#1

theorem logical_or_bitwise_or_icmps_comm1_proof : logical_or_bitwise_or_icmps_comm1_before ⊑ logical_or_bitwise_or_icmps_comm1_after

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

theorem t1_ult_slt_0_proof : t1_ult_slt_0_before ⊑ t1_ult_slt_0_after

theorem p_commutative4_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (LLVM.and (LLVM.xor e_2 (const? 32 (-1))) e_1) (LLVM.and e_2 e) ⊑
    LLVM.or (LLVM.and e_1 (LLVM.xor e_2 (const? 32 (-1)))) (LLVM.and e_2 e) { «disjoint» := true }

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

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

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 same_source_not_matching_signbits_thm (e : IntW 32) :
  sext 32 (trunc 8 (shl (const? 32 (-1)) (LLVM.and e (const? 32 8)) { «nsw» := true, «nuw» := false })) ⊑
    ashr (shl (const? 32 (-16777216)) (LLVM.and e (const? 32 8))) (const? 32 24) { «exact» := true }

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

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

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

theorem e_592 :
     - 1 * (x |||  ~~~y) + 1 * (x ||| y) - 5 *  ~~~(x &&& y) + 1 *  ~~~(x &&&  ~~~y) + 2 *  ~~~y + 7 * (x ^^^ y) + 14 *  ~~~(x ||| y) + 7 *  ~~~(x |||  ~~~y) + 8 * (x &&&  ~~~y) + 11 * (x &&& y) = 1 * x + 11 *  ~~~(x &&&  ~~~x)

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

theorem e_1325 :
    11 *  ~~~z + 1 * (z |||  ~~~t) + 2 * (z ^^^ t) - 11 *  ~~~t + 1 *  ~~~(z ^^^ t) + 2 * (z ||| t) - 4 *  ~~~(z ||| t) - 17 *  ~~~(z |||  ~~~t) + 6 * (z &&&  ~~~t) =  - 2 *  ~~~(z &&&  ~~~t) + 6 * (z &&& t)

theorem neg_not_signbit2_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬6#8 ≥ ↑8 →
    6#8 ≥ ↑8 ∨ True ∧ (x >>> 6#8).msb = true ∨ True ∧ (0#32).ssubOverflow (zeroExtend 32 (x >>> 6#8)) = true → False

theorem slt_or_not_max_commute_logical_thm (e e_1 : IntW 8) :
  select (icmp IntPred.ne e_1 (const? 8 127)) (const? 1 1) (icmp IntPred.slt e_1 e) ⊑
    icmp IntPred.ne e_1 (const? 8 127)

theorem p_constmask_proof : p_constmask_before ⊑ p_constmask_after

theorem t0_commutative_thm.extracted_1._18 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1) (x_3 x_4 : BitVec 8),
  ofBool (x_4 == x_3) = 1#1 → ofBool (x_4 != x_3) = 1#1 → ¬True → x_2 = 1#1 → x_1 = x

theorem test19_thm (e : IntW 37) :
  icmp IntPred.eq (ashr e (const? 37 2)) (const? 37 0) ⊑ icmp IntPred.ult e (const? 37 4)

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

theorem e_1867 :
    3 *  ~~~( ~~~a &&& (b &&& c)) - 2 * (b &&& (a ||| c)) + 7 * ((a ^^^ b) |||  ~~~(a ^^^ c)) + 4 *  ~~~( ~~~a &&& (b ||| c)) + 4 *  ~~~(a ||| (b &&& c)) - 5 * ( ~~~a &&& (b ^^^ c)) + 7 * ((a &&& b) ^^^ (b ||| c)) + 1 * ( ~~~(a |||  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 1 * (a ^^^ (b ||| c)) + 2 * ((a &&& c) ^^^  ~~~(a ^^^ (b &&& c))) + 3 * (c ^^^ (a ||| ( ~~~b ||| c))) + 2 * (b ^^^ ( ~~~a &&& (b ^^^ c))) + 11 * (c ^^^  ~~~(a &&& (b ||| c))) - 2 * (a &&& ( ~~~b ||| c)) + 2 * ( ~~~(a ||| b) |||  ~~~(b ^^^ c)) - 1 * ((a ||| b) &&&  ~~~(b ^^^ c)) - 1 * (c |||  ~~~(a ||| b)) + 3 * (b &&&  ~~~c) + 11 *  ~~~(a ||| b) - 3 * (b &&& c) - 3 * ( ~~~a ||| ( ~~~b &&& c)) - 5 * (b ^^^  ~~~(a &&&  ~~~c)) - 3 *  ~~~(a ^^^ (b &&& c)) + 4 * (b ^^^ (a ||| ( ~~~b &&& c))) + 2 * (b ^^^ (a &&& c)) + 4 * (c ^^^  ~~~(a |||  ~~~b)) + 7 * b - 2 * (b ^^^  ~~~(a ||| ( ~~~b &&& c))) - 1 * ( ~~~c &&&  ~~~(a ^^^ b)) + 1 * ((a ^^^ b) &&&  ~~~(a ^^^ c)) + 3 * (c ^^^  ~~~( ~~~a &&& (b &&& c))) + 1 * ( ~~~c |||  ~~~(a ^^^ b)) + 2 * (b ^^^  ~~~(a &&& (b ||| c))) + 1 *  ~~~(a &&& (b &&& c)) + 5 * ((a |||  ~~~b) &&& (b ^^^ c)) - 1 * ((a &&& c) ||| (b &&&  ~~~c)) - 1 * (b ^^^ (a ||| c)) + 11 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) - 44 *  ~~~(a ||| (b ||| c)) - 46 *  ~~~(a ||| ( ~~~b ||| c)) - 51 *  ~~~( ~~~a ||| (b ||| c)) - 25 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 44 * ( ~~~a &&& ( ~~~b &&& c)) - 24 * ( ~~~a &&& (b &&& c)) - 38 * (a &&& ( ~~~b &&& c)) - 43 * (a &&& (b &&& c)) =  - 5 * (b ^^^  ~~~(a &&& c)) + 1 *  ~~~(a &&&  ~~~a)

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

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)

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 icmp_eq_zext_ne_non_boolean_proof : icmp_eq_zext_ne_non_boolean_before ⊑ icmp_eq_zext_ne_non_boolean_after

theorem udiv_common_divisor_thm (e e_1 e_2 : IntW 5) (e_3 : IntW 1) :
  select e_3 (LLVM.udiv e_2 e_1) (LLVM.udiv e e_1) ⊑ LLVM.udiv (select e_3 e_2 e) e_1

theorem sge_and_max_logical_proof : sge_and_max_logical_before ⊑ sge_and_max_logical_after

theorem shl_and_add_proof : shl_and_add_before ⊑ shl_and_add_after

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

theorem test22_proof : test22_before ⊑ test22_after

theorem n2_badmask_proof : n2_badmask_before ⊑ n2_badmask_after

theorem lshr_sext_i1_to_i16_thm.extracted_1._2 : ∀ (x : BitVec 1),
  ¬4#16 ≥ ↑16 → ¬x = 1#1 → signExtend 16 x >>> 4#16 = 0#16

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

theorem Factor.denoteFin_eq_toNat_reflectFin (f : Factor) (xs : EnvFin w f.numVars) :
  f.denoteFin xs = (f.reflectFin xs).toNat

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

theorem sge_and_max_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.sge e_1 e) (icmp IntPred.eq e_1 (const? 8 127)) ⊑
    icmp IntPred.eq e_1 (const? 8 127)

theorem ashrsgt_02_00_proof : ashrsgt_02_00_before ⊑ ashrsgt_02_00_after

theorem logic_and_logic_or_2_proof : logic_and_logic_or_2_before ⊑ logic_and_logic_or_2_after

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

theorem ashrslt_02_09_exact_proof : ashrslt_02_09_exact_before ⊑ ashrslt_02_09_exact_after

theorem tryFactorization_xor_ashr_ashr_proof : tryFactorization_xor_ashr_ashr_before ⊑ tryFactorization_xor_ashr_ashr_after

theorem alive_AndOrXor_2265 : alive_AndOrXor_2265_src ⊑ alive_AndOrXor_2265_tgt

@[simp]
theorem Term.toBV_binRel {wenv : WidthExpr.Env wcard}
    {tctx : Term.Ctx wcard tcard}
    (benv : Term.BoolEnv bcard)
    (tenv : tctx.Env wenv)
    (k : BinaryRelationKind)
    (w : WidthExpr wcard)
    (a b : Term bcard ncard icard pcard tctx (.bv w)) :
  Term.toBV benv nenv ienv penv tenv (.binRel k w a b) =
    match k with

theorem shl_or_with_or_disjoint_instead_of_add_proof : shl_or_with_or_disjoint_instead_of_add_before ⊑ shl_or_with_or_disjoint_instead_of_add_after

@[simp] theorem xor_eq : (x ^^^ y) i = (xor (x i) (y i))

theorem neg_of_add_with_constant_proof : neg_of_add_with_constant_before ⊑ neg_of_add_with_constant_after

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 drop_nsw_trunc_thm.extracted_1._1 : ∀ (x x_1 : BitVec 16),
  ¬(True ∧ signExtend 16 (truncate 8 (x_1 &&& 255#16 &&& x)) ≠ x_1 &&& 255#16 &&& x) →
    truncate 8 (x_1 &&& 255#16 &&& x) = truncate 8 (x_1 &&& x)

theorem udiv_icmp2_proof : udiv_icmp2_before ⊑ udiv_icmp2_after

theorem ashrslt_03_12_proof : ashrslt_03_12_before ⊑ ashrslt_03_12_after

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

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

theorem t0_thm (e e_1 : IntW 8) :
  sub (LLVM.and (sub (const? 8 0) e_1) e) e ⊑ sub (const? 8 0) (LLVM.and e (add e_1 (const? 8 (-1))))

theorem mul_add_to_mul_2_proof : mul_add_to_mul_2_before ⊑ mul_add_to_mul_2_after

theorem mul_select_sext_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → 1#64 * signExtend 64 x = 0#64

theorem exact_lshr_ne_proof : exact_lshr_ne_before ⊑ exact_lshr_ne_after

theorem ashr_eq_exact_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬(True ∧ x >>> 3#8 <<< 3#8 ≠ x ∨ 3#8 ≥ ↑8) → ofBool (x.sshiftRight' 3#8 == 10#8) = ofBool (x == 80#8)

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

@[simp_sllvm]
theorem GlobalState.isRefinedBy_iff (s t : GlobalState) :
    s ⊑ t ↔ s.alloc ⊑ t.alloc ∧ s.mem ⊑ t.mem

theorem set_bits_proof : set_bits_before ⊑ set_bits_after

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

theorem test15e_proof : test15e_before ⊑ test15e_after

theorem sext_true_val_must_be_all_ones_proof : sext_true_val_must_be_all_ones_before ⊑ sext_true_val_must_be_all_ones_after

@[simp, grind=] theorem val_consLeft : mapOut.consLeft.val = mapOut.val

theorem band_lor_left2_proof : band_lor_left2_before ⊑ band_lor_left2_after

theorem positive_sameconst_shlnuw_proof : positive_sameconst_shlnuw_before ⊑ positive_sameconst_shlnuw_after

theorem e_141 :
     - 6 * (x ^^^ y) + 2 *  ~~~x + 5 *  ~~~(x &&& y) + 4 *  ~~~(x ||| y) + 1 * (x &&&  ~~~y) + 11 * (x &&& y) =  - 10 *  ~~~(x |||  ~~~y) + 11 *  ~~~(x &&&  ~~~y)

theorem test_and_ne_a_b_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8) (x_2 : BitVec 1),
  x_2 &&& ofBool (x_1 != x) = 1#1 → ¬x_2 = 1#1 → x_1 = x

theorem lshrult_01_00_proof : lshrult_01_00_before ⊑ lshrult_01_00_after

theorem e_2291 :
     - 6 *  ~~~(e ||| f) + 1 * (e ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 1 * e + 7 * (f ^^^  ~~~(d &&&  ~~~e)) - 2 * (e ||| (d &&& f)) + 5 * ( ~~~(d ||| e) ||| (e ^^^ f)) - 1 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) - 1 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 1 * (e ^^^ (d &&& (e ^^^ f))) - 2 * (e ^^^  ~~~(d &&& f)) - 7 *  ~~~(d &&& ( ~~~e &&& f)) + 2 *  ~~~d - 1 * (e &&& f) + 3 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) - 2 * ( ~~~(d ||| e) |||  ~~~(d ^^^ (e ^^^ f))) - 11 * (e ^^^ (d &&& ( ~~~e ||| f))) - 2 * (e ^^^  ~~~(d ||| (e &&& f))) - 1 * (f ^^^ (d &&&  ~~~e)) + 11 * ((d &&& e) ||| (e ^^^ f)) + 2 * (f ^^^ ( ~~~d &&& (e ||| f))) + 11 * (d ^^^ (e ||| f)) + 11 * (e ^^^ ( ~~~d ||| (e &&& f))) + 1 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 2 *  ~~~(d &&& (e ||| f)) + 1 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) + 5 * (f |||  ~~~(d ^^^ e)) + 1 * (f ^^^  ~~~(d &&& e)) + 1 * ((d &&& e) ^^^  ~~~(d ^^^ ( ~~~e ||| f))) + 1 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 6 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 11 *  ~~~(d &&& ( ~~~e ||| f)) + 3 * ((d &&& e) |||  ~~~(e |||  ~~~f)) - 7 *  ~~~( ~~~d ||| (e &&& f)) - 3 *  ~~~(d ^^^ e) - 1 * f + 4 * ((d &&& f) ||| (e &&&  ~~~f)) - 5 * ((d ^^^ e) ||| (d ^^^ f)) + 5 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) - 2 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 1 * ( ~~~d ||| ( ~~~e &&& f)) - 2 * (f ^^^  ~~~( ~~~d ||| ( ~~~e &&& f))) - 11 * (e ^^^ (d &&& f)) - 11 * (e ^^^  ~~~(d &&& (e &&& f))) - 6 * (f ||| (d &&&  ~~~e)) - 1 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) + 1 * (e ^^^  ~~~( ~~~d ||| (e ^^^ f))) - 1 *  ~~~(d &&& f) + 2 * ( ~~~(d ||| e) |||  ~~~(e ^^^ f)) + 5 *  ~~~(d ^^^ f) + 5 * (f ^^^ (d &&& e)) - 1 * (e ^^^ f) - 2 * (e ||| f) - 1 *  ~~~(d &&&  ~~~e) - 2 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 13 *  ~~~(d ||| (e ||| f)) - 16 *  ~~~(d ||| ( ~~~e ||| f)) + 49 *  ~~~( ~~~d ||| (e ||| f)) - 7 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 17 * ( ~~~d &&& ( ~~~e &&& f)) + 30 * ( ~~~d &&& (e &&& f)) + 12 * (d &&& ( ~~~e &&& f)) =  - 12 * (d &&& (e &&& f))

theorem or_nosignbit_lshr_thm (e : IntW 32) :
  lshr (LLVM.or e (const? 32 2147418112)) (const? 32 8) ⊑ LLVM.or (lshr e (const? 32 8)) (const? 32 8388352)

theorem eq1 : ∀ (w : Nat) (a : BitVec w), a = a

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

theorem xor_signbit_select_ashr_proof : xor_signbit_select_ashr_before ⊑ xor_signbit_select_ashr_after

theorem e_1995 :
     - 1 *  ~~~(a &&& (b ||| c)) + 1 * (b ^^^  ~~~(a &&&  ~~~c)) - 2 *  ~~~b + 1 *  ~~~( ~~~a ||| (b ^^^ c)) - 6 * (a &&& (b ||| c)) + 4 * (a ^^^ (b ||| c)) - 1 * (c ^^^  ~~~(a &&& b)) - 6 * (b ^^^ (a &&& (b ||| c))) + 1 *  ~~~(a ||| (b &&& c)) + 11 * ( ~~~b &&&  ~~~(a ^^^ c)) - 11 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) + 7 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 2 *  ~~~(a &&&  ~~~a) - 11 * (b ^^^ ( ~~~a ||| ( ~~~b &&& c))) + 11 * (b ^^^ (a &&&  ~~~c)) + 7 * (c ^^^  ~~~(a ||| (b &&& c))) - 1 * ((b &&&  ~~~c) |||  ~~~( ~~~a ||| ( ~~~b &&& c))) + 11 * (b &&&  ~~~c) + 1 * ((a &&& b) |||  ~~~(b ||| c)) - 1 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 2 *  ~~~(b |||  ~~~c) + 1 * (b ^^^  ~~~(a ||| (b ^^^ c))) - 2 * ( ~~~(a &&& b) &&& (a ^^^ (b ^^^ c))) - 2 * (a ||| b) + 1 *  ~~~(a ^^^ b) - 2 * (b ^^^  ~~~( ~~~a &&& (b ^^^ c))) - 3 * (b ^^^  ~~~(a &&& (b ^^^ c))) + 1 * ( ~~~a ||| ( ~~~b &&& c)) - 2 * ((a &&& c) ^^^ (a ^^^ (b &&& c))) - 7 * (c &&& (a ^^^ b)) + 2 * (a ||| ( ~~~b &&& c)) - 5 *  ~~~a + 2 * ( ~~~b ||| (a ^^^ c)) + 5 * (a &&& b) + 2 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 7 * ( ~~~a &&& (b ||| c)) + 3 * ((a &&& b) ^^^ (a ^^^ ( ~~~b ||| c))) + 5 * (b ^^^  ~~~(a &&& ( ~~~b ||| c))) + 1 * (a ^^^ c) - 1 * (b |||  ~~~(a ||| c)) - 2 * ((a &&&  ~~~b) |||  ~~~(b ^^^ c)) + 1 * (c ^^^  ~~~(a &&&  ~~~b)) + 2 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 1 * (b ||| (a &&&  ~~~c)) + 3 * (c ^^^  ~~~( ~~~a ||| (b &&& c))) - 7 * (c ^^^  ~~~(a &&& (b ||| c))) + 4 * ((a &&&  ~~~b) ||| (b ^^^ c)) - 2 * (b |||  ~~~(a ^^^ c)) - 6 * (a &&& ( ~~~b ||| c)) - 1 * (b ^^^ (a &&& (b ^^^ c))) - 2 *  ~~~(a ^^^ ( ~~~b ||| c)) + 6 *  ~~~(a ||| (b ||| c)) - 13 *  ~~~(a ||| ( ~~~b ||| c)) - 5 *  ~~~( ~~~a ||| (b ||| c)) - 11 *  ~~~( ~~~a ||| ( ~~~b ||| c)) - 15 * ( ~~~a &&& ( ~~~b &&& c)) - 16 * ( ~~~a &&& (b &&& c)) + 30 * (a &&& ( ~~~b &&& c)) + 18 * (a &&& (b &&& c)) =  - 1 * (b ^^^ ( ~~~a ||| ( ~~~b ||| c)))

theorem ashr_eq_exact_proof : ashr_eq_exact_before ⊑ ashr_eq_exact_after

theorem land_land_right1_proof : land_land_right1_before ⊑ land_land_right1_after

theorem test16_proof : test16_before ⊑ test16_after

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 not_or_or_and_no_and_commute1_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  (x_2 ^^^ -1#32 ||| x_1 ||| x) &&& (x_2 &&& x_1 ^^^ -1#32) = x &&& (x_1 ^^^ -1#32) ||

theorem zext_ashr_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬2#16 ≥ ↑16 → 2#8 ≥ ↑8 ∨ True ∧ (x >>> 2#8 &&& x).msb = true → False

theorem fold_xor_zext_icmp_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 64),
  zeroExtend 8 (ofBool (x_1 <ₛ x_2)) ^^^ zeroExtend 8 (ofBool (x_2 <ₛ x)) =
    zeroExtend 8 (ofBool (x_1 <ₛ x_2) ^^^ ofBool (x_2 <ₛ x))

theorem t14_and_with_const0_proof : t14_and_with_const0_before ⊑ t14_and_with_const0_after

theorem no_shift_xor_multiuse_xor_proof : no_shift_xor_multiuse_xor_before ⊑ no_shift_xor_multiuse_xor_after

theorem not_or_or_and_not_and_and_commute1_proof : not_or_or_and_not_and_and_commute1_before ⊑ not_or_or_and_not_and_and_commute1_after

theorem lshr_and_or_disjoint_thm.extracted_1._2 : ∀ (x x_1 : BitVec 8),
  ¬((42#8 == 0 || 8 != 1 && x_1 == intMin 8 && 42#8 == -1) = true ∨
        2#8 ≥ ↑8 ∨ True ∧ (x_1.srem 42#8 &&& (x >>> 2#8 &&& 13#8) != 0) = true ∨ 2#8 ≥ ↑8) →
    ¬((42#8 == 0 || 8 != 1 && x_1 == intMin 8 && 42#8 == -1) = true ∨
          2#8 ≥ ↑8 ∨ True ∧ (x &&& 52#8 &&& x_1.srem 42#8 <<< 2#8 != 0) = true) →
      (x_1.srem 42#8 ||| x >>> 2#8 &&& 13#8) <<< 2#8 = x &&& 52#8 ||

theorem test1_thm (e : IntW 16) :
  trunc 16 (LLVM.or (lshr (zext 32 e) (const? 32 8)) (mul (zext 32 e) (const? 32 5))) ⊑
    LLVM.or (lshr e (const? 16 8)) (mul e (const? 16 5))

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 reduce_xor_common_op_commute1_proof : reduce_xor_common_op_commute1_before ⊑ reduce_xor_common_op_commute1_after

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

theorem sle_smin4_proof : sle_smin4_before ⊑ sle_smin4_after

theorem t1_flags_nuw_nsw_second_thm (e e_1 e_2 : IntW 8) :
  sub (sub e_2 e_1) e { «nsw» := true, «nuw» := true } ⊑ sub e_2 (add e_1 e)

theorem t0_commutative_thm.extracted_1._7 : ∀ (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 → True → 0#1 = 1#1 → False

theorem shl_and_proof : shl_and_before ⊑ shl_and_after

theorem test53_proof : test53_before ⊑ test53_after

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

theorem ult_or_not_max_commute_proof : ult_or_not_max_commute_before ⊑ ult_or_not_max_commute_after

theorem shl_lshr_pow2_const_negative_overflow1_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 6#16 ≥ ↑16) → 4096#16 <<< x >>> 6#16 &&& 8#16 = 0#16

@[simp] theorem dropUntil_last   : dropUntil (cons ty Γ) (Var.last Γ ty) = Γ

theorem and_sext_to_sel_proof : and_sext_to_sel_before ⊑ and_sext_to_sel_after

theorem select_icmp_sgt_allones_smin_flipped_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (-1#8 <ₛ x) = 1#1 → x ^^^ BitVec.ofInt 8 (-128) = x ||

theorem oppositesign_proof : oppositesign_before ⊑ oppositesign_after

theorem and_xor_common_op_commute1_thm.extracted_1._2 : ∀ (x x_1 : BitVec 32),
  ¬(x_1 = 0 ∨ x = 0 ∨ x_1 = 0) →
    ¬(x_1 = 0 ∨ x = 0) → 42#32 / x_1 &&& (43#32 / x ^^^ 42#32 / x_1) = 42#32 / x_1 &&& (43#32 / x ^^^ -1#32)

theorem test_sub_nsw__all_are_safe_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 255)) (const? 32 6)) (const? 32 (-260))
      (sub (const? 32 (-254)) (LLVM.and e (const? 32 255)) { «nsw» := true, «nuw» := false }) ⊑
    sub (const? 32 (-254)) (LLVM.and e (const? 32 255)) { «nsw» := true, «nuw» := true }

theorem lshrult_02_06_proof : lshrult_02_06_before ⊑ lshrult_02_06_after

theorem and_ne_with_one_bit_diff_constants3_logical_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬ofBool (x != 65#8) = 1#1 → 0#1 = ofBool (x &&& 127#8 != 65#8)

theorem sgt_swap_and_not_min_proof : sgt_swap_and_not_min_before ⊑ sgt_swap_and_not_min_after

theorem mul16_low_miss_shift_amount_thm (e e_1 : IntW 16) :
  add
      (shl
        (add (mul (lshr e_1 (const? 16 8)) (LLVM.and e (const? 16 127)))
          (mul (LLVM.and e_1 (const? 16 127)) (lshr e (const? 16 8))))
        (const? 16 8))
      (mul (LLVM.and e_1 (const? 16 127)) (LLVM.and e (const? 16 127))) ⊑
    add
      (shl
        (add (mul (lshr e_1 (const? 16 8)) (LLVM.and e (const? 16 127)) { «nsw» := true, «nuw» := true })
          (mul (LLVM.and e_1 (const? 16 127)) (lshr e (const? 16 8)) { «nsw» := true, «nuw» := true })
          { «nsw» := false, «nuw» := true })
        (const? 16 8))
      (mul (LLVM.and e_1 (const? 16 127)) (LLVM.and e (const? 16 127)) { «nsw» := true, «nuw» := true })

theorem lshr_exact_add_nuw_proof : lshr_exact_add_nuw_before ⊑ lshr_exact_add_nuw_after

theorem p2_scalar_shifted_urem_by_const_proof : p2_scalar_shifted_urem_by_const_before ⊑ p2_scalar_shifted_urem_by_const_after

theorem and_ashr_not_commuted_thm (e e_1 e_2 : IntW 8) :
  LLVM.and (LLVM.xor (ashr e_2 e_1) (const? 8 (-1))) (ashr e e_1) ⊑
    ashr (LLVM.and e (LLVM.xor e_2 (const? 8 (-1)))) e_1

theorem e_868 :
     - 6 *  ~~~t - 2 * (z ||| t) + 4 *  ~~~(z &&&  ~~~t) + 2 *  ~~~(z ||| t) - 2 *  ~~~(z |||  ~~~t) - 2 * (z &&& t) =  - 8 * (z &&&  ~~~t)

theorem ule_umax3_proof : ule_umax3_before ⊑ ule_umax3_after

theorem mul_eleven' (x : BitVec w) : 11 * x =
  (x + x + x + x + x +
   x + x + x + x + x +
   x)

theorem test11d_proof : test11d_before ⊑ test11d_after

theorem scalar_i32_lshr_and_negC_eq_X_is_constant2_proof : scalar_i32_lshr_and_negC_eq_X_is_constant2_before ⊑ scalar_i32_lshr_and_negC_eq_X_is_constant2_after

@[simp]
lemma dec_snoc_in_langRel {n} {R : BVNRel n} {w : BitVecs' n} {a : BitVec n} :
    dec (w ++ [a]) ∈ langRel R ↔
      R (List.Vector.ofFn fun k => .cons (a.getLsbD k) ((dec w).bvs.get k))

theorem test_negative_combined_sub_signed_overflow_thm (e : IntW 8) :
  icmp IntPred.slt (sub (const? 8 127) e { «nsw» := true, «nuw» := false }) (const? 8 (-1)) ⊑ const? 1 0

theorem test_sext4_thm.extracted_1._2 : ∀ (x : BitVec 1), ¬x = 1#1 → ¬x ^^^ 1#1 = 1#1 → False

theorem add_comm (a b : R q) : a + b = b + a

theorem add_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_1 - x_3

theorem select_add_icmp_bad_proof : select_add_icmp_bad_before ⊑ select_add_icmp_bad_after

theorem and_zext_eq_even_commuted_thm.extracted_1._1 : ∀ (x : BitVec 32),
  zeroExtend 32 (ofBool (x == 2#32)) &&& x = 0#32

theorem select_icmp_and_8_eq_0_xor_8_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 8)) (const? 32 0)) (LLVM.xor e (const? 32 8)) e ⊑
    LLVM.or e (const? 32 8)

theorem icmp_equality_test_constant_samesign_thm.extracted_1._1 : ∀ (x x_1 : BitVec 42),
  ofBool (x_1 == BitVec.ofInt 42 (-42)) = 1#1 → ofBool (x == BitVec.ofInt 42 (-42)) = ofBool (x_1 == x)

theorem negate_sdiv_proof : negate_sdiv_before ⊑ negate_sdiv_after

theorem or_eq_with_diff_one_signed_logical_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x == 0#32) = 1#1 → 1#1 = ofBool (x + 1#32 <ᵤ 2#32)

@[simp]
theorem ctxt_cons {Γ : DerivedCtxt Δ} :
    (Γ.cons ty).ctxt = Γ.ctxt.cons ty

@[simp, grind=] theorem castCtxt_castCtxt (h₁ : Γ = Δ) (h₂ : Δ = Ξ) :
    (v.castCtxt h₁).castCtxt h₂ = v.castCtxt (by simp [*])

theorem lshrugt_02_14_exact_proof : lshrugt_02_14_exact_before ⊑ lshrugt_02_14_exact_after

theorem shl_xor_proof : shl_xor_before ⊑ shl_xor_after

theorem ult_swap_or_not_max_commute_logical_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != -1#8) = 1#1 → ofBool (x_1 <ᵤ x) = ofBool (x_1 != -1#8)

theorem trunc_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 32), ofBool (x_2 <ᵤ x_1) = 1#1 → truncate 16 42#32 = 42#16

theorem foo3_proof : foo3_before ⊑ foo3_after

theorem ashr_icmp1_thm.extracted_1._1 : ∀ (x : BitVec 64),
  ¬(True ∧ x >>> 2#64 <<< 2#64 ≠ x ∨ 2#64 ≥ ↑64) → ofBool (x.sshiftRight' 2#64 == 0#64) = ofBool (x == 0#64)

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 or_and_not_not_commute6_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (LLVM.and (LLVM.sdiv (const? 32 42) e_2) (LLVM.xor (LLVM.or e_1 e) (const? 32 (-1))))
      (LLVM.xor (LLVM.or (LLVM.sdiv (const? 32 42) e_2) e) (const? 32 (-1))) ⊑
    LLVM.xor (LLVM.or (LLVM.and e_1 (LLVM.sdiv (const? 32 42) e_2)) e) (const? 32 (-1))

theorem test55_proof : test55_before ⊑ test55_after

theorem icmp_eq_x_invertable_y_todo_proof : icmp_eq_x_invertable_y_todo_before ⊑ icmp_eq_x_invertable_y_todo_after

theorem nonexact_lshr_ne_thm (e : IntW 8) :
  icmp IntPred.ne (lshr (const? 8 4) e) (const? 8 1) ⊑ icmp IntPred.ne e (const? 8 2)

theorem e_1972 :
    1 * (b |||  ~~~c) + 2 * ((a &&&  ~~~b) |||  ~~~(a ^^^ (b ^^^ c))) - 7 * ((a |||  ~~~b) &&& (a ^^^ (b ^^^ c))) + 2 * (a &&& c) - 2 * (c ^^^  ~~~( ~~~a &&& ( ~~~b ||| c))) - 1 * ((a ^^^ b) ||| (a ^^^ c)) + 4 * ((b &&&  ~~~c) |||  ~~~(a ||| ( ~~~b &&& c))) + 1 * (c ^^^ (a |||  ~~~b)) - 3 * (a ||| b) + 4 * (b ^^^  ~~~(a &&& c)) - 2 * (c ^^^ (a ||| (b ||| c))) - 11 * (c ||| (a ^^^ b)) + 7 * (b ^^^  ~~~( ~~~a ||| ( ~~~b &&& c))) + 2 * (c ^^^ ( ~~~a &&& ( ~~~b ||| c))) - 1 * (c ^^^  ~~~(a ||| (b &&& c))) - 11 *  ~~~(a &&&  ~~~b) - 1 * ((a &&& b) ^^^  ~~~(a ^^^ (b &&& c))) + 7 * (c ^^^ (a ||| ( ~~~b &&& c))) - 6 *  ~~~(a &&& c) + 1 * (c ^^^ (a &&& (b ||| c))) + 2 *  ~~~(a &&& ( ~~~b ||| c)) - 1 * ((a &&& b) |||  ~~~(a ^^^ (b ^^^ c))) - 7 * (c ^^^ ( ~~~a &&& (b ||| c))) - 11 * (a |||  ~~~c) + 5 * (c ^^^  ~~~( ~~~a &&& (b ||| c))) - 1 *  ~~~(a ||| (b ^^^ c)) + 5 *  ~~~(a |||  ~~~c) - 6 * (a ||| (b ^^^ c)) + 1 * ( ~~~(a ^^^ b) |||  ~~~(a ^^^ c)) - 7 *  ~~~(a &&&  ~~~c) + 3 *  ~~~(a ||| (b &&& c)) + 2 * ( ~~~c ||| (a ^^^ b)) - 1 * (b ^^^  ~~~(a &&& ( ~~~b &&& c))) + 1 * (c |||  ~~~(a ^^^ b)) - 1 * ((a ||| b) &&&  ~~~(a ^^^ (b ^^^ c))) - 6 * (a ||| ( ~~~b &&& c)) - 1 * (a &&&  ~~~c) + 4 *  ~~~(a ||| ( ~~~b &&& c)) - 11 * ((a &&& c) ^^^ (b ||| c)) - 5 * (b ^^^ ( ~~~a ||| (b &&& c))) + 1 * ((a |||  ~~~b) &&& (b ^^^ c)) + 1 * (a &&& ( ~~~b ||| c)) + 7 * (c ^^^  ~~~(a |||  ~~~b)) - 5 * (a ^^^ c) + 3 *  ~~~(a ^^^ c) + 3 * ( ~~~b ||| (a ^^^ c)) + 3 * (c &&&  ~~~(a ^^^ b)) + 1 *  ~~~(b ||| c) + 1 * ( ~~~(a |||  ~~~b) ||| (b ^^^ c)) + 6 *  ~~~(a ||| (b ||| c)) + 45 *  ~~~(a ||| ( ~~~b ||| c)) + 28 *  ~~~( ~~~a ||| (b ||| c)) + 41 *  ~~~( ~~~a ||| ( ~~~b ||| c)) + 43 * ( ~~~a &&& ( ~~~b &&& c)) + 29 * (a &&& ( ~~~b &&& c)) + 46 * (a &&& (b &&& c)) =  - 15 * ( ~~~a &&& (b &&& c))

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

@[simp] theorem toBitVec_one : BitStream.toBitVec w BitStream.one = 1#w

theorem rem_euclid_pow2_true_arm_folded_proof : rem_euclid_pow2_true_arm_folded_before ⊑ rem_euclid_pow2_true_arm_folded_after

theorem c_thm :
  LLVM.sdiv (sub (const? 32 0) (const? 32 (-2147483648))) (const? 32 (-3)) ⊑ const? 32 715827882

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

theorem absdiff2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 64),
  ofBool (x_1 <ᵤ x) = 1#1 →
    (x_1 - x ^^^ signExtend 64 (ofBool (x_1 <ᵤ x))) - signExtend 64 (ofBool (x_1 <ᵤ x)) = 0#64 - (x_1 - x)

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 c0_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x &&& 3#8 ≤ₛ x) = ofBool (-1#8 <ₛ x)

theorem ashrslt_01_03_exact_proof : ashrslt_01_03_exact_before ⊑ ashrslt_01_03_exact_after

theorem test15e_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and e (const? 32 128)) (const? 32 0)) (const? 32 256) (const? 32 0) ⊑
    LLVM.and (shl e (const? 32 1)) (const? 32 256)

theorem e_375 :
    3 * y - 7 *  ~~~y + 2 * (x ^^^ y) - 11 *  ~~~x + 3 * x + 7 *  ~~~(x ||| y) - 5 *  ~~~(x |||  ~~~y) - 17 * (x &&& y) =  - 2 * (x &&&  ~~~y) - 11 *  ~~~(x &&&  ~~~y)

theorem select_xor_icmp_meta_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32), ofBool (x_1 == 0#32) = 1#1 → x_1 ^^^ x = x

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

theorem t2_const_lshr_shl_eq_thm (e e_1 : IntW 32) :
  icmp IntPred.eq (LLVM.and (shl e_1 (const? 32 1)) (lshr e (const? 32 1))) (const? 32 0) ⊑
    icmp IntPred.eq (LLVM.and (lshr e (const? 32 2)) e_1) (const? 32 0)

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

theorem e_1447 :
     - 11 * z - 2 *  ~~~(z &&&  ~~~t) - 3 * (z ||| t) - 5 *  ~~~(z ^^^ t) + 1 * (z ^^^ t) + 4 *  ~~~z + 13 *  ~~~(z ||| t) - 1 *  ~~~(z |||  ~~~t) + 23 * (z &&&  ~~~t) + 21 * (z &&& t) = 11 *  ~~~t - 1 *  ~~~(z &&& t)

theorem AvoidCollision_signExtend_or {x y : BitVec w} :
    (x ||| y).signExtend v = (x.signExtend v) ||

theorem lshrult_01_09_proof : lshrult_01_09_before ⊑ lshrult_01_09_after

theorem or_not_and_proof : or_not_and_before ⊑ or_not_and_after

theorem negative3_logical_thm (e e_1 e_2 : IntW 32) :
  select (icmp IntPred.slt e_2 (LLVM.and e_1 (const? 32 2147483647))) (icmp IntPred.sge e (const? 32 0))
      (const? 1 0) ⊑
    select (icmp IntPred.slt e_2 (LLVM.and e_1 (const? 32 2147483647))) (icmp IntPred.sgt e (const? 32 (-1)))
      (const? 1 0)

theorem or_ashr_not_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 8), ¬(x_1 ≥ ↑8 ∨ x_1 ≥ ↑8) → x_1 ≥ ↑8 → False

theorem e_2227 :
     - 3 * (e ^^^  ~~~(d ||| (e &&& f))) - 6 *  ~~~(e ^^^ f) - 3 * ((d &&&  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 2 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 2 *  ~~~(d ^^^ (e ||| f)) - 2 * (e ^^^  ~~~(d ||| (e ^^^ f))) - 3 * (f ^^^  ~~~( ~~~d ||| (e &&& f))) + 11 * ( ~~~d ||| ( ~~~e ||| f)) - 6 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 1 * (f ||| (d &&& e)) - 2 * ((d &&& e) ^^^ (e ||| f)) - 1 *  ~~~(d &&& f) - 2 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) - 1 * (f ^^^ (d ||| ( ~~~e ||| f))) - 3 * ((d ||| e) &&& (e ^^^ f)) - 7 * (f ^^^ (d &&& (e ||| f))) - 1 *  ~~~( ~~~d ||| (e &&& f)) - 2 * (e ^^^ (d ||| ( ~~~e ||| f))) + 2 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) + 2 * ((d &&& e) |||  ~~~(e |||  ~~~f)) - 1 * (e ^^^ (d &&& (e ||| f))) + 11 *  ~~~(e &&&  ~~~f) - 1 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 1 * (d &&& f) - 5 * ((d ^^^ e) |||  ~~~(d ^^^ f)) + 1 *  ~~~(d ^^^ (e ^^^ f)) + 3 *  ~~~(d &&& e) - 1 * (f ^^^ ( ~~~d ||| (e ||| f))) + 5 * (d ||| (e ||| f)) + 7 * ((e &&& f) ||| ( ~~~d &&& (e ||| f))) - 1 * ( ~~~(d &&&  ~~~e) &&& (e ^^^ f)) + 7 * ( ~~~d ||| ( ~~~e &&& f)) + 7 * ((d &&&  ~~~e) ||| (e ^^^ f)) - 1 * ((d &&& e) ^^^ (e |||  ~~~f)) - 6 *  ~~~(d ^^^ ( ~~~e &&& f)) + 2 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 1 * ( ~~~e &&& (d ^^^ f)) - 5 * ((d &&& f) ^^^  ~~~(e &&&  ~~~f)) - 2 * (f ^^^ (d ||| (e ||| f))) - 5 * (d ^^^ (e ^^^ f)) + 7 * ((d &&& f) ^^^  ~~~(d ^^^ ( ~~~e &&& f))) + 11 * (e ||| (d &&&  ~~~f)) - 5 * f + 3 * (d ||| ( ~~~e &&& f)) + 2 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) + 1 * ( ~~~(d |||  ~~~e) |||  ~~~(d ^^^ (e ^^^ f))) - 1 * (f |||  ~~~(d ^^^ e)) - 1 *  ~~~(d ||| (e ||| f)) - 27 *  ~~~(d ||| ( ~~~e ||| f)) - 20 *  ~~~( ~~~d ||| (e ||| f)) - 14 * ( ~~~d &&& ( ~~~e &&& f)) - 16 * ( ~~~d &&& (e &&& f)) - 17 * (d &&& ( ~~~e &&& f)) - 27 * (d &&& (e &&& f)) =  - 2 * (f ^^^  ~~~(d &&& e)) + 1 *  ~~~( ~~~d ||| ( ~~~e ||| f))

@[simp, grind =] theorem val_toHom_apply (d : Diff Γ Δ) (v : Γ.Var t) :
    (d.toHom v).val = v.val + d.val

theorem test_add_nsw__nuw_is_safe_proof : test_add_nsw__nuw_is_safe_before ⊑ test_add_nsw__nuw_is_safe_after

theorem andn_or_cmp_2_proof : andn_or_cmp_2_before ⊑ andn_or_cmp_2_after

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

theorem t0_proof : t0_before ⊑ t0_after

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

theorem test11_proof : test11_before ⊑ test11_after

theorem ashrsgt_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.sshiftRight' 2#4) = 1#1

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

theorem e_731 :
    5 *  ~~~y - 1 * x - 1 * (x ^^^ y) - 5 *  ~~~(x &&&  ~~~x) - 7 *  ~~~x + 5 * (x |||  ~~~y) + 7 * (x ||| y) + 1 *  ~~~(x &&&  ~~~y) - 6 * y + 1 *  ~~~(x ||| y) + 11 *  ~~~(x |||  ~~~y) = 1 * (x &&& y) + 10 * (x &&&  ~~~y)

theorem or_and1_commuted_proof : or_and1_commuted_before ⊑ or_and1_commuted_after

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 select_icmp_ne_0_and_1073741824_xor_8_thm (e : IntW 8) (e_1 : IntW 32) :
  select (icmp IntPred.ne (const? 32 0) (LLVM.and e_1 (const? 32 1073741824))) e (LLVM.xor e (const? 8 8)) ⊑
    select (icmp IntPred.eq (LLVM.and e_1 (const? 32 1073741824)) (const? 32 0)) (LLVM.xor e (const? 8 8))
      e

theorem test21_thm (e : IntW 8) : LLVM.and (ashr e (const? 8 7)) (const? 8 1) ⊑ lshr e (const? 8 7)

theorem test5_proof : test5_before ⊑ test5_after

theorem clear_to_clear_decomposebittest_thm.extracted_1._3 : ∀ (x : BitVec 8),
  ¬ofBool (-1#8 <ₛ x) = 1#1 → True ∧ (x &&& BitVec.ofInt 8 (-128) &&& 3#8 != 0) = true → False

theorem shl_lshr_demand1_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(x ≥ ↑8 ∨ 3#8 ≥ ↑8) → ¬x ≥ ↑8 → 40#8 <<< x >>> 3#8 ||

theorem masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_6_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_6_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_6_logical_after

theorem main3f_like_logical_thm (e e_1 e_2 : IntW 32) :
  select
      (select (icmp IntPred.ne (LLVM.and e_2 e_1) (const? 32 0)) (const? 1 1)
        (icmp IntPred.ne (LLVM.and e_2 e) (const? 32 0)))
      (const? 32 0) (const? 32 1) ⊑
    zext 32
      (select (icmp IntPred.eq (LLVM.and e_2 e_1) (const? 32 0))
        (icmp IntPred.eq (LLVM.and e_2 e) (const? 32 0)) (const? 1 0))

@[simp] lemma eval_simplify :
    p.simplify.eval = p.eval

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

@[simp]
lemma in_enc : x ∈ enc '' S ↔ dec x ∈ S

theorem xor_notand_to_or_not1_proof : xor_notand_to_or_not1_before ⊑ xor_notand_to_or_not1_after

theorem not_or_or_not_commute1_proof : not_or_or_not_commute1_before ⊑ not_or_or_not_commute1_after

theorem e_266 :
     - 7 *  ~~~(x ^^^ y) - 7 *  ~~~y - 7 * x + 3 *  ~~~(x &&&  ~~~y) - 3 *  ~~~(x |||  ~~~y) + 14 * (x &&&  ~~~y) + 11 * (x &&& y) =  - 11 *  ~~~(x ||| y)

theorem test_shl_nsw__nsw_is_safe_thm (e : IntW 32) :
  mul
      (mul
        (select (icmp IntPred.eq (LLVM.or e (const? 32 (-83886080))) (const? 32 (-83886079)))
          (const? 32 (-335544316))
          (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false }))
        (LLVM.or e (const? 32 (-83886080))))
      (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false }) ⊑
    mul
      (mul (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false })
        (LLVM.or e (const? 32 (-83886080))))
      (shl (LLVM.or e (const? 32 (-83886080))) (const? 32 2) { «nsw» := true, «nuw» := false })

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

theorem add_nsw_proof : add_nsw_before ⊑ add_nsw_after

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 test5_thm.extracted_1._1 : ∀ (x : BitVec 1), zeroExtend 32 (zeroExtend 8 x) = zeroExtend 32 x

theorem main6c_proof : main6c_before ⊑ main6c_after

theorem test_with_neg_even_thm (e : IntW 32) : LLVM.and (shl (const? 32 (-4)) e) (const? 32 1) ⊑ const? 32 0

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

theorem icmp_slt_sext_ne_zero_nofold_thm (e : IntW 32) :
  icmp IntPred.slt (sext 32 (icmp IntPred.ne e (const? 32 0))) e ⊑
    icmp IntPred.sgt e (sext 32 (icmp IntPred.ne e (const? 32 0)))

theorem icmp_eq_and_pow2_lshr_pow2_case2_thm (e : IntW 32) :
  zext 32 (icmp IntPred.eq (LLVM.and (lshr (const? 32 4) e) (const? 32 8)) (const? 32 0)) ⊑ const? 32 1

theorem e_424 :
    11 *  ~~~(x &&&  ~~~x) - 1 *  ~~~(x &&& y) - 11 * (x ||| y) + 5 * y - 7 * x - 10 *  ~~~(x ||| y) - 4 *  ~~~(x |||  ~~~y) + 8 * (x &&&  ~~~y) =  - 2 * (x &&& y)

theorem a_true_implies_b_true2_proof : a_true_implies_b_true2_before ⊑ a_true_implies_b_true2_after

theorem or_simplify_uge_thm (e e_1 : IntW 8) :
  icmp IntPred.uge (LLVM.and e_1 (const? 8 127))
      (LLVM.or (LLVM.or e (const? 8 (-127))) (LLVM.and e_1 (const? 8 127))) ⊑
    const? 1 0

theorem ashrslt_03_13_proof : ashrslt_03_13_before ⊑ ashrslt_03_13_after

theorem not_cmp_constant_proof : not_cmp_constant_before ⊑ not_cmp_constant_after

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

theorem t5_ugt_slt_0_proof : t5_ugt_slt_0_before ⊑ t5_ugt_slt_0_after

theorem neg_test_icmp_non_equality_proof : neg_test_icmp_non_equality_before ⊑ neg_test_icmp_non_equality_after

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

@[simp, simp_denote, simp_sllvm] theorem bitvec_isRefinedBy_bitvec :
    @Ty.IsRefinedBy (bitvec w) (bitvec v) x y ↔ @IsRefinedBy (LLVM.IntW w) (LLVM.IntW v) _ x y

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

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

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

theorem lshrugt_02_03_exact_proof : lshrugt_02_03_exact_before ⊑ lshrugt_02_03_exact_after

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

theorem and_or1_proof : and_or1_before ⊑ and_or1_after

theorem positive_biggerlshr_shlnuw_proof : positive_biggerlshr_shlnuw_before ⊑ positive_biggerlshr_shlnuw_after

theorem shrink_and_proof : shrink_and_before ⊑ shrink_and_after

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

theorem main7a_logical_proof : main7a_logical_before ⊑ main7a_logical_after

theorem hoist_ashr_ahead_of_sext_1_proof : hoist_ashr_ahead_of_sext_1_before ⊑ hoist_ashr_ahead_of_sext_1_after

theorem AvoidCollision_getElem?_setWidth (m : Nat) (x : BitVec n) (i : Nat) :
    (x.setWidth m)[i]? = if i < m then some (x.getLsbD i) else none

theorem scalar_i16_lshr_and_negC_eq_thm (e e_1 : IntW 16) :
  icmp IntPred.eq (LLVM.and (lshr e_1 e) (const? 16 (-128))) (const? 16 0) ⊑
    icmp IntPred.ult (lshr e_1 e) (const? 16 128)

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

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

private theorem BitVec.lt_eq_decide_ult {x y : BitVec w} : (x < y) = decide (x.ult y)

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

theorem lshr_pow2_ult_smin_thm (e : IntW 8) :
  icmp IntPred.ult (lshr (const? 8 (-128)) e) (const? 8 (-128)) ⊑ icmp IntPred.ne e (const? 8 0)

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

theorem tryFactorization_add_mul_nuw_mul_var_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ x_2.umulOverflow x_1 = true ∨ True ∧ x_2.umulOverflow x = true) → x_2 * x_1 + x_2 * x = x_2 * (x_1 + x)

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 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 shl_xor_xor_good_mask_proof : shl_xor_xor_good_mask_before ⊑ shl_xor_xor_good_mask_after

theorem udiv_illegal_type_c_thm.extracted_1._2 : ∀ (x : BitVec 9),
  ¬10#32 = 0 → ¬(10#9 = 0 ∨ True ∧ (x / 10#9).msb = true) → zeroExtend 32 x / 10#32 = zeroExtend 32 (x / 10#9)

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

theorem negative5_proof : negative5_before ⊑ negative5_after

theorem select_ashr_thm.extracted_1._2 : ∀ (x : BitVec 128) (x_1 : BitVec 1),
  ¬x_1 = 1#1 → ¬0#128 ≥ ↑128 → x = x.sshiftRight' 0#128

theorem lshrugt_01_11_proof : lshrugt_01_11_before ⊑ lshrugt_01_11_after

theorem sle_and_min_commute_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x_1 == BitVec.ofInt 8 (-128)) &&& ofBool (x_1 ≤ₛ x) = ofBool (x_1 == BitVec.ofInt 8 (-128))

theorem test13_thm (e : IntW 18) :
  shl (ashr (mul e (const? 18 3)) (const? 18 8)) (const? 18 9) ⊑
    LLVM.and (mul e (const? 18 6)) (const? 18 (-512))

theorem test_mul_nuw_nsw__nsw_is_safe_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x ||| BitVec.ofInt 32 (-83886080) == BitVec.ofInt 32 (-83886079)) = 1#1 →
    ¬(True ∧ (x ||| BitVec.ofInt 32 (-83886080)).smulOverflow 9#32 = true) →
      BitVec.ofInt 32 (-754974711) = (x ||| BitVec.ofInt 32 (-83886080)) * 9#32

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

theorem 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 test6_proof : test6_before ⊑ test6_after

theorem ashr_lshr_exact_lshr_only_proof : ashr_lshr_exact_lshr_only_before ⊑ ashr_lshr_exact_lshr_only_after

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

theorem t0_commutative_thm (e e_1 : IntW 8) (e_2 : IntW 1) (e_3 e_4 : IntW 8) :
  select (select (icmp IntPred.eq e_4 e_3) (const? 1 1) (LLVM.xor e_2 (const? 1 1))) e_1 e ⊑
    select (select (icmp IntPred.ne e_4 e_3) e_2 (const? 1 0)) e e_1

theorem flip_masked_bit_thm.extracted_1._1 : ∀ (x : BitVec 8), x + 16#8 &&& 16#8 = x &&& 16#8 ^^^ 16#8

theorem bools_multi_uses1_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 ^^^ x = x ^^^ x

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

theorem AvoidCollision_two_pow_le_toInt_mul_toInt_iff {x y : BitVec w} :
    2 ^ (w - 1) ≤ x.toInt * y.toInt ↔
      (signExtend (w * 2) (intMax w)).slt (signExtend (w * 2) x * signExtend (w * 2) y)

theorem bools_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 1), x_2 = 1#1 → (x_2 ^^^ 1#1) &&& x_1 ||

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

theorem foo1_and_signbit_lshr_without_shifting_signbit_logical_proof : foo1_and_signbit_lshr_without_shifting_signbit_logical_before ⊑ foo1_and_signbit_lshr_without_shifting_signbit_logical_after

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

theorem sub_2_proof : sub_2_before ⊑ sub_2_after

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

theorem and_sel_op0_thm.extracted_1._1 : ∀ (x : BitVec 1), x = 1#1 → 25#32 &&& 1#32 = zeroExtend 32 x

@[simp]
private theorem min_eq_of_not_le' {a b : Nat} (hab : ¬ a ≤ b) : min b a = b

theorem test11e_proof : test11e_before ⊑ test11e_after

theorem demorganize_constant2_proof : demorganize_constant2_before ⊑ demorganize_constant2_after

@[simp_denote] theorem Expr.denote_unfold' {ty} (e : Expr d Γ eff ty) :
    e.denote V = do
      let x ← e.denoteOp V
      return x ++ V

theorem mul_of_pow2s_thm (e e_1 : IntW 32) :
  LLVM.or (mul (LLVM.and e_1 (const? 32 8)) (LLVM.and e (const? 32 16))) (const? 32 128) ⊑ const? 32 128

theorem neg_eq_not_add_one (x : BitVec w) :
    -x = ~~~ x + 1#w

theorem lshrugt_03_14_proof : lshrugt_03_14_before ⊑ lshrugt_03_14_after

@[simp]
lemma Fin.castSucc_neq_last (x : Fin n) : x.castSucc ≠ Fin.last n

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

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

theorem ult_swap_and_max_thm (e e_1 : IntW 8) :
  LLVM.and (icmp IntPred.ugt e_1 e) (icmp IntPred.eq e (const? 8 (-1))) ⊑ const? 1 0

lemma helper2 : (k = 1) → (x ::ᵥ y ::ᵥ vs).get k = y

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

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

theorem sub_shl_same_amount_nuw_proof : sub_shl_same_amount_nuw_before ⊑ sub_shl_same_amount_nuw_after

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

theorem e_2320 :
    4 *  ~~~(d ^^^ (e ||| f)) + 3 * (e ||| (d &&& f)) - 3 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 7 * (f ||| (d &&& e)) + 11 * (d ^^^ (e &&& f)) + 1 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) - 5 *  ~~~(d &&&  ~~~e) - 11 * (e ^^^  ~~~( ~~~d &&& (e ^^^ f))) + 7 * (e ^^^ (d ||| f)) - 11 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) + 7 * (d ^^^ (e ^^^ f)) - 1 * ((d &&& f) ^^^ (e ||| f)) - 1 * (f ^^^  ~~~(d ||| (e &&& f))) - 6 * (d ||| e) + 5 *  ~~~(d &&& ( ~~~e &&& f)) - 1 * (f ^^^ ( ~~~d ||| (e ||| f))) + 2 * ( ~~~(d |||  ~~~e) ||| (e ^^^ f)) - 2 *  ~~~(d ||| ( ~~~e &&& f)) + 3 *  ~~~( ~~~d &&& ( ~~~e &&& f)) + 1 * (e |||  ~~~(d ^^^ f)) + 11 * ( ~~~d ||| ( ~~~e ||| f)) + 7 * (f ^^^ (d &&& e)) + 11 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) + 5 *  ~~~(d |||  ~~~e) + 1 * (f |||  ~~~(d ^^^ e)) + 2 *  ~~~(d |||  ~~~f) - 1 * (f ^^^ ( ~~~d &&& (e ||| f))) + 5 * (e ^^^ (d &&& ( ~~~e ||| f))) - 1 * (e ^^^ ( ~~~d &&& (e ||| f))) - 6 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 1 * (e ^^^  ~~~( ~~~d ||| (e &&& f))) - 2 * (d &&& ( ~~~e ||| f)) + 4 * ((d &&& f) |||  ~~~(e ||| f)) - 5 * ( ~~~e &&&  ~~~(d ^^^ f)) - 2 * (e |||  ~~~(d ||| f)) - 3 * ((d &&& f) ^^^  ~~~(d ^^^ (e &&& f))) + 4 * ( ~~~d &&& ( ~~~e ||| f)) - 2 * (e ^^^  ~~~(d &&& f)) + 5 * ((d &&& e) |||  ~~~(d ^^^ (e ^^^ f))) - 2 * d + 2 * (e ^^^ ( ~~~d ||| (e ^^^ f))) + 4 * ((d &&& e) |||  ~~~(e |||  ~~~f)) - 7 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 11 * (f ^^^ ( ~~~d ||| (e &&& f))) + 11 *  ~~~(e ^^^ f) - 5 * (d ^^^ e) - 1 * (d ||| (e &&& f)) - 11 * (d ^^^ ( ~~~e ||| f)) + 4 *  ~~~d + 4 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 6 *  ~~~(d ^^^ e) + 1 * (f ||| (d ^^^ e)) + 3 * e - 1 *  ~~~(e |||  ~~~f) + 2 * (f ^^^ (d ||| (e &&& f))) + 1 * ( ~~~e &&& (d ^^^ f)) - 14 *  ~~~(d ||| (e ||| f)) - 8 *  ~~~(d ||| ( ~~~e ||| f)) - 32 *  ~~~( ~~~d ||| (e ||| f)) - 9 *  ~~~( ~~~d ||| ( ~~~e ||| f)) - 11 * ( ~~~d &&& ( ~~~e &&& f)) - 57 * ( ~~~d &&& (e &&& f)) - 33 * (d &&& ( ~~~e &&& f)) - 16 * (d &&& (e &&& f)) =  - 1 * (d |||  ~~~f)

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

theorem 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 positive_biggerashr_proof : positive_biggerashr_before ⊑ positive_biggerashr_after

theorem trunc_shl_zext_64_proof : trunc_shl_zext_64_before ⊑ trunc_shl_zext_64_after

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

theorem icmp_eq_zext_ne_zero_proof : icmp_eq_zext_ne_zero_before ⊑ icmp_eq_zext_ne_zero_after

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

theorem ult_rem_nz_nsw_proof : ult_rem_nz_nsw_before ⊑ ult_rem_nz_nsw_after

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

theorem select_icmp_ne_0_and_8_and_not_1073741824_thm.extracted_1._2 : ∀ (x : BitVec 32) (x_1 : BitVec 8),
  ¬ofBool (0#8 != x_1 &&& 8#8) = 1#1 → ¬ofBool (x_1 &&& 8#8 == 0#8) = 1#1 → x &&& BitVec.ofInt 32 (-1073741825) = x

@[simp]
theorem scanAnd_idem (s : BitStream) : s.scanAnd.scanAnd = s.scanAnd

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

theorem test28_thm (e : IntW 32) :
  icmp IntPred.eq (LLVM.srem e (const? 32 (-2147483648))) (const? 32 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 2147483647)) (const? 32 0)

theorem t2_proof : t2_before ⊑ t2_after

theorem and_signbit_shl_thm (e : IntW 32) :
  shl (LLVM.and e (const? 32 (-65536))) (const? 32 8) ⊑ LLVM.and (shl e (const? 32 8)) (const? 32 (-16777216))

theorem pv_proof : pv_before ⊑ pv_after

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

theorem ne_irregular_bit_widths_thm.extracted_1._2 : ∀ (x x_1 : BitVec 31),
  ¬(13#31 ≥ ↑31 ∨ 13#31 ≥ ↑31 ∨ 7#31 ≥ ↑31 ∨ 7#31 ≥ ↑31) →
    ¬(7#31 ≥ ↑31 ∨ 7#31 ≥ ↑31) →
      ofBool (truncate 5 (x_1 >>> 13#31) != truncate 5 (x >>> 13#31)) ||

theorem zext_masked_bit_zero_to_smaller_bitwidth_thm (e e_1 : IntW 32) :
  zext 16 (icmp IntPred.eq (LLVM.and (shl (const? 32 1) e_1) e) (const? 32 0)) ⊑
    LLVM.and (trunc 16 (lshr (LLVM.xor e (const? 32 (-1))) e_1)) (const? 16 1)

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

theorem t2_commutative_proof : t2_commutative_before ⊑ t2_commutative_after

theorem substitute_constant_and_eq_ugt_swap_thm.extracted_1._1 : ∀ (x x_1 : BitVec 8),
  ofBool (x <ᵤ x_1) &&& ofBool (x == 42#8) = ofBool (x == 42#8) &&& ofBool (42#8 <ᵤ x_1)

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

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

theorem corec_eq_corec {a : α} {b : β} {f g}
    (R : α → β → Prop)
    (thing : R a b)
    (h : ∀ a b, R a b →
          let x := f a
          let y := g b
          R x.fst y.fst ∧ x.snd = y.snd) :
    corec f a = corec g b

theorem test6_proof : test6_before ⊑ test6_after

theorem test9_proof : test9_before ⊑ test9_after

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

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

theorem test_thm (e : IntW 32) :
  icmp IntPred.ne (lshr (shl e (const? 32 12)) (const? 32 12)) (const? 32 0) ⊑
    icmp IntPred.ne (LLVM.and e (const? 32 1048575)) (const? 32 0)

theorem ashr_exact_add_negative_shift_negative_thm.extracted_1._1 : ∀ (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 → False

theorem ashr_sgt_overflow_proof : ashr_sgt_overflow_before ⊑ ashr_sgt_overflow_after

theorem xor_sext_to_sel_thm (e : IntW 32) (e_1 : IntW 1) : LLVM.xor (sext 32 e_1) e ⊑ LLVM.xor e (sext 32 e_1)

theorem positive_biggerlshr_shlnuw_proof : positive_biggerlshr_shlnuw_before ⊑ positive_biggerlshr_shlnuw_after

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

theorem shl_fold_or_disjoint_cnt_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(True ∧ (x &&& 3#8 != 0) = true ∨ x ||| 3#8 ≥ ↑8) → ¬x ≥ ↑8 → 2#8 <<< (x ||| 3#8) = 16#8 <<< x

theorem set_shl_mask_proof : set_shl_mask_before ⊑ set_shl_mask_after

theorem badimm1_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(7#8 ≥ ↑8 ∨ 9#16 ≥ ↑16) →
    ofBool ((truncate 8 x).sshiftRight' 7#8 == truncate 8 (x >>> 9#16)) = 1#1 →
      7#8 ≥ ↑8 ∨
          9#16 ≥ ↑16 ∨
            True ∧ signExtend 16 (truncate 8 (x >>> 9#16)) ≠ x >>> 9#16 ∨
              True ∧ zeroExtend 16 (truncate 8 (x >>> 9#16)) ≠ x >>> 9#16 →
        False

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

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

theorem xor_nosignbit_lshr_proof : xor_nosignbit_lshr_before ⊑ xor_nosignbit_lshr_after

theorem scalar_i32_shl_and_negC_eq_nonzero_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬x ≥ ↑32 → ofBool (x_1 <<< x &&& BitVec.ofInt 32 (-8) == 1#32) = 0#1

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

theorem is_rem4_neg_i16_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(4#16 == 0 || 16 != 1 && x == intMin 16 && 4#16 == -1) = true →
    ofBool (x.srem 4#16 <ₛ 0#16) = ofBool (BitVec.ofInt 16 (-32768) <ᵤ x &&& BitVec.ofInt 16 (-32765))

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

theorem scalar_i64_lshr_and_negC_eq_thm.extracted_1._1 : ∀ (x x_1 : BitVec 64),
  ¬x ≥ ↑64 → ofBool (x_1 >>> x &&& BitVec.ofInt 64 (-8589934592) == 0#64) = ofBool (x_1 >>> x <ᵤ 8589934592#64)

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

theorem sext_shl_trunc_smaller_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 16),
  ¬x ≥ ↑32 → truncate 5 (signExtend 32 x_1 <<< x) = truncate 5 (zeroExtend 32 x_1 <<< x)

theorem PR2844_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ofBool (x == 0#32) = 1#1 →
    ¬True → 0#32 = zeroExtend 32 (ofBool (x != 0#32) &&& ofBool (BitVec.ofInt 32 (-638208502) <ₛ x))

theorem ule_or_not_min_logical_proof : ule_or_not_min_logical_before ⊑ ule_or_not_min_logical_after

theorem e_1383 :
    11 * (z |||  ~~~t) + 3 * (z ||| t) + 3 *  ~~~(z &&&  ~~~t) + 4 * z - 6 *  ~~~t + 1 * t + 14 *  ~~~(z ||| t) + 15 *  ~~~(z |||  ~~~t) - 1 * (z &&&  ~~~t) - 22 * (z &&& t) = 11 *  ~~~z + 11 *  ~~~(z &&& t)

theorem ashr_lshr_cst_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ofBool (x <ₛ 1#32) = 1#1 → ¬(True ∧ x >>> 8#32 <<< 8#32 ≠ x ∨ 8#32 ≥ ↑32) → 8#32 ≥ ↑32 → False

theorem bools_logical_commute0_and2_proof : bools_logical_commute0_and2_before ⊑ bools_logical_commute0_and2_after

theorem sdiv_shl_pair3_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬(True ∧ (x_2 <<< x_1).sshiftRight' x_1 ≠ x_2 ∨
        x_1 ≥ ↑32 ∨
          True ∧ (x_2 <<< x).sshiftRight' x ≠ x_2 ∨
            x ≥ ↑32 ∨ (x_2 <<< x == 0 || 32 != 1 && x_2 <<< x_1 == intMin 32 && x_2 <<< x == -1) = true) →
    True ∧ 1#32 <<< x_1 >>> x_1 ≠ 1#32 ∨ x_1 ≥ ↑32 ∨ x ≥ ↑32 → False

theorem e_1418 :
     - 7 * z - 11 * (z ||| t) - 6 * (z ^^^ t) + 3 *  ~~~t + 1 * (z |||  ~~~t) - 2 * t - 3 *  ~~~(z ||| t) + 20 *  ~~~(z |||  ~~~t) + 21 * (z &&&  ~~~t) + 19 * (z &&& t) = 1 *  ~~~(z &&& t)

theorem e_7 :
    11 *  ~~~(x &&&  ~~~y) - 11 * x + 11 * (x &&&  ~~~y) + 11 * (x &&& y) = 11 *  ~~~(x ||| y) + 11 * y

theorem ult_umin2_proof : ult_umin2_before ⊑ ult_umin2_after

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

theorem sext_sext_sge_op0_narrow_proof : sext_sext_sge_op0_narrow_before ⊑ sext_sext_sge_op0_narrow_after

theorem neg_or_lshr_i32_commute_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬((x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨
        (x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true ∨ 31#32 ≥ ↑32) →
    ¬(x == 0 || 32 != 1 && 42#32 == intMin 32 && x == -1) = true →
      ((42#32).sdiv x ||| 0#32 - (42#32).sdiv x) >>> 31#32 = zeroExtend 32 (ofBool ((42#32).sdiv x != 0#32))

theorem scalar_i32_signbit_shl_and_slt_proof : scalar_i32_signbit_shl_and_slt_before ⊑ scalar_i32_signbit_shl_and_slt_after

theorem ashrsgt_01_13_exact_proof : ashrsgt_01_13_exact_before ⊑ ashrsgt_01_13_exact_after

theorem logical_and_logical_and_icmps_comm1_proof : logical_and_logical_and_icmps_comm1_before ⊑ logical_and_logical_and_icmps_comm1_after

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

theorem test10_logical_thm.extracted_1._2 : ∀ (x : BitVec 32),
  ¬ofBool (x &&& 2#32 == 0#32) = 1#1 → 0#1 = ofBool (x <ᵤ 2#32)

theorem prove_exact_with_high_mask_limit_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬(8#8 == 0 || 8 != 1 && x &&& BitVec.ofInt 8 (-8) == intMin 8 && 8#8 == -1) = true →
    ¬3#8 ≥ ↑8 → (x &&& BitVec.ofInt 8 (-8)).sdiv 8#8 = x.sshiftRight' 3#8

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

theorem icmp_slt_0_or_icmp_add_1_sge_100_i32_fail_proof : icmp_slt_0_or_icmp_add_1_sge_100_i32_fail_before ⊑ icmp_slt_0_or_icmp_add_1_sge_100_i32_fail_after

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

theorem lor_band_right2_proof : lor_band_right2_before ⊑ lor_band_right2_after

theorem shl_lshr_pow2_const_negative_overflow2_thm.extracted_1._1 : ∀ (x : BitVec 16),
  ¬(x ≥ ↑16 ∨ 6#16 ≥ ↑16) → 8#16 <<< x >>> 6#16 &&& BitVec.ofInt 16 (-32768) = 0#16

theorem test_invalid_simplify_other_proof : test_invalid_simplify_other_before ⊑ test_invalid_simplify_other_after

theorem sub_zext_trunc_lshr_thm (e : IntW 64) :
  sub (const? 32 10) (zext 32 (trunc 1 (lshr e (const? 64 15)))) ⊑
    add (ashr (shl (trunc 32 e) (const? 32 16)) (const? 32 31)) (const? 32 10)
      { «nsw» := true, «nuw» := false }

theorem select_2_thm.extracted_1._13 : ∀ (x x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  ¬x_3 = 1#1 → x ^^^ 45#8 ^^^ -1#8 = x ^^^ BitVec.ofInt 8 (-46)

theorem test11_proof : test11_before ⊑ test11_after

theorem test15e_proof : test15e_before ⊑ test15e_after

@[simp]
theorem eval_repeatN_zero (b : Bool) (env : Unit → BitStream) :
  (repeatN b 0).eval env = (env ())

@[bv_automata_nnf]
theorem ult_iff_ule_eq_false {a b : BitVec w} : a.ule b = false ↔ b.ult a

theorem t0_basic_proof : t0_basic_before ⊑ t0_basic_after

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

theorem xor_icmp_invalid_range_proof : xor_icmp_invalid_range_before ⊑ xor_icmp_invalid_range_after

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

theorem shl_add_proof : shl_add_before ⊑ shl_add_after

theorem scalar_i16_shl_and_signbit_eq_proof : scalar_i16_shl_and_signbit_eq_before ⊑ scalar_i16_shl_and_signbit_eq_after

theorem eval_mkPostcondSafety_eq_false_iff
    {circs : KInductionCircuits fsm n}
    (hCircs : circs.IsLawful)
    (env : Vars fsm.α arity (n + 1) → Bool) :
    ((mkPostcondSafety circs).eval env = false) ↔
    ((∀ (s : fsm.α), fsm.initCarry s = env ((Vars.state0 s))) →
    (∀ (i : Nat) (hi : i < n + 1), env (Vars.outputs ⟨i, by omega⟩) = false))

theorem add_and_or_commutative_proof : add_and_or_commutative_before ⊑ add_and_or_commutative_after

theorem mul_mask_pow2_sgt0_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ofBool (0#8 <ₛ x * 44#8 &&& 4#8) = ofBool (x &&& 1#8 != 0#8)

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

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

theorem or_nosignbit_select_ashr_proof : or_nosignbit_select_ashr_before ⊑ or_nosignbit_select_ashr_after

theorem shl_add_add_proof : shl_add_add_before ⊑ shl_add_add_after

theorem shl_add_proof : shl_add_before ⊑ shl_add_after

theorem List.attachWith_nodup (l : List α) (hnd : l.Nodup) P H : (l.attachWith P H).Nodup

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

theorem positive_different_trunc_both_logical_proof : positive_different_trunc_both_logical_before ⊑ positive_different_trunc_both_logical_after

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

theorem xor_i8_to_i64_shl_save_and_ne_thm.extracted_1._1 : ∀ (x : BitVec 64) (x_1 : BitVec 8),
  ofBool (x_1 &&& 1#8 != 0#8) = 1#1 → 63#64 ≥ ↑64 → False

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

theorem lshr_16_add_zext_basic_thm (e e_1 : IntW 16) :
  lshr (add (zext 32 e_1) (zext 32 e)) (const? 32 16) ⊑
    zext 32 (icmp IntPred.ugt e (LLVM.xor e_1 (const? 16 (-1))))

theorem bv_AndOrXor_2475 :
    ∀ (e e_1 : LLVM.IntW w), LLVM.xor (LLVM.sub e_1 e) (LLVM.const? w (-1)) ⊑ LLVM.add e (LLVM.sub (LLVM.const? w (-1)) e_1)

theorem xor_logic_and_logic_or1_proof : xor_logic_and_logic_or1_before ⊑ xor_logic_and_logic_or1_after

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

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

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

theorem ripple_nsw6_thm (e e_1 : IntW 16) :
  add (LLVM.or e_1 (const? 16 (-10923))) (LLVM.or e (const? 16 (-21845))) ⊑
    add (LLVM.or e_1 (const? 16 (-10923))) (LLVM.or e (const? 16 (-21845))) { «nsw» := true, «nuw» := false }

theorem scalar_i8_signbit_lshr_and_eq_proof : scalar_i8_signbit_lshr_and_eq_before ⊑ scalar_i8_signbit_lshr_and_eq_after

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

theorem PR38139_thm (e : IntW 8) :
  icmp IntPred.ne (LLVM.or e (const? 8 (-64))) e ⊑ icmp IntPred.ult e (const? 8 (-64))

theorem test_shl_nuw_nsw__nuw_is_safe_proof : test_shl_nuw_nsw__nuw_is_safe_before ⊑ test_shl_nuw_nsw__nuw_is_safe_after

theorem or_xor_tree_1100_thm (e e_1 e_2 : IntW 32) :
  LLVM.or (LLVM.xor (mul e_2 (const? 32 42)) (LLVM.xor (mul e_1 (const? 32 42)) (mul e (const? 32 42))))
      (LLVM.xor (mul e_2 (const? 32 42)) (mul e_1 (const? 32 42))) ⊑
    LLVM.or (LLVM.xor (mul e_2 (const? 32 42)) (mul e_1 (const? 32 42))) (mul e (const? 32 42))

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

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

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

theorem test15h_thm (e : IntW 32) :
  select (icmp IntPred.ne (LLVM.and e (const? 32 8)) (const? 32 0)) (const? 32 (-9)) (const? 32 (-1)) ⊑
    LLVM.xor (LLVM.and e (const? 32 8)) (const? 32 (-1))

theorem urem_c_i32_thm.extracted_1._1 : ∀ (x : BitVec 8),
  ¬zeroExtend 32 x = 0 → x = 0 ∨ True ∧ (10#8 % x).msb = true → False

theorem ashr_proof : ashr_before ⊑ ashr_after

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

theorem sgt_smax2_proof : sgt_smax2_before ⊑ sgt_smax2_after

theorem e_555 :
    11 * (x |||  ~~~y) - 1 *  ~~~x + 4 *  ~~~(x &&&  ~~~y) + 7 *  ~~~(x ^^^ y) + 7 * (x ^^^ y) - 14 *  ~~~(x ||| y) - 3 *  ~~~(x |||  ~~~y) - 11 * (x &&&  ~~~y) - 15 * (x &&& y) = 7 *  ~~~(x &&&  ~~~x)

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

theorem ashrslt_02_07_proof : ashrslt_02_07_before ⊑ ashrslt_02_07_after

theorem t5_proof : t5_before ⊑ t5_after

theorem test_shl_nuw_nsw__none_are_safe_thm (e : IntW 64) (e_1 : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e_1 (const? 32 (-2))) (const? 32 0)) e
      (ashr e (zext 64 (shl (LLVM.and e_1 (const? 32 (-2))) (const? 32 2) { «nsw» := true, «nuw» := true }))) ⊑
    ashr e (zext 64 (LLVM.and (shl e_1 (const? 32 2)) (const? 32 (-8))) { «nneg» := true })

theorem sub_zero (a : ZMod q) : a - 0 = a

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 zext_sext_add_icmp_ult_minus1_thm (e e_1 : IntW 1) :
  icmp IntPred.ult (add (zext 8 e_1) (sext 8 e)) (const? 8 (-1)) ⊑ LLVM.or e_1 (LLVM.xor e (const? 1 1))

theorem pr51551_neg2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬(True ∧ (x_1 &&& BitVec.ofInt 32 (-7)).smulOverflow x = true) →
    truncate 1 x_1 ^^^ 1#1 = 1#1 → ofBool ((x_1 &&& BitVec.ofInt 32 (-7)) * x &&& 7#32 == 0#32) = 1#1

theorem decideIfZerosAuxM_Id_eq_decideIfZerosAux {arity : Type _}
    (p : FSM arity) [DecidableEq arity] [Fintype arity] (c : Circuit p.α) :
    decideIfZerosAuxM (m := Id) (decLe := fun c c' =>
      let b := c ≤ c'
      ⟨b, by simp [b]⟩
    ) p c = decideIfZerosAux p c

theorem sext_shl_mask_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 16),
  ¬x ≥ ↑32 → signExtend 32 x_1 <<< x &&& 65535#32 = zeroExtend 32 x_1 <<< x &&& 65535#32

theorem ult_x_impliesT_eq_umax_todo_thm (e e_1 e_2 : IntW 8) :
  icmp IntPred.ne (select (icmp IntPred.ugt e_2 e_1) (const? 8 (-1)) e) e_1 ⊑
    select (icmp IntPred.ugt e_2 e_1) (const? 1 1) (icmp IntPred.ne e e_1)

theorem masked_icmps_mask_notallzeros_bmask_mixed_swapped_2_logical_proof : masked_icmps_mask_notallzeros_bmask_mixed_swapped_2_logical_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_swapped_2_logical_after

theorem ashr_mul_proof : ashr_mul_before ⊑ ashr_mul_after

theorem e_2323 :
     - 5 * (e ^^^ ( ~~~d ||| (e ||| f))) - 11 * (f ^^^  ~~~(d ||| ( ~~~e &&& f))) - 11 * (f &&&  ~~~(d &&&  ~~~e)) + 5 * ((e &&&  ~~~f) |||  ~~~(d ||| ( ~~~e &&& f))) + 1 * (f ^^^ ( ~~~d ||| ( ~~~e &&& f))) - 3 * ( ~~~(d ^^^ e) ||| (d ^^^ f)) - 7 * (f ^^^ (d ||| ( ~~~e ||| f))) + 5 * ( ~~~d &&& (e ||| f)) + 2 * ((e &&&  ~~~f) |||  ~~~( ~~~d ||| ( ~~~e &&& f))) + 3 * (e ^^^ ( ~~~d ||| ( ~~~e ||| f))) - 7 * (e ^^^ (d &&& (e ^^^ f))) - 2 * (e ^^^  ~~~( ~~~d &&& (e ||| f))) + 5 * ( ~~~e |||  ~~~(d ^^^ f)) + 1 * ( ~~~e &&&  ~~~(d ^^^ f)) + 5 * (d ^^^ e) + 1 *  ~~~(d &&&  ~~~f) + 2 * (f ^^^  ~~~( ~~~d &&& ( ~~~e ||| f))) + 5 * ( ~~~(d ||| e) ||| (e ^^^ f)) + 3 * (e |||  ~~~(d ^^^ f)) + 2 * ((d ^^^ e) &&& (d ^^^ f)) - 2 * ( ~~~(d &&& e) &&&  ~~~(e ^^^ f)) + 11 * (f &&&  ~~~(d ^^^ e)) + 2 * (e ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 7 * (f ^^^ (d |||  ~~~e)) - 5 * ( ~~~e ||| (d ^^^ f)) + 7 * (e ^^^ (d &&&  ~~~f)) - 1 *  ~~~(e |||  ~~~f) - 2 * (e ^^^  ~~~(d &&& ( ~~~e &&& f))) - 7 * ((d &&&  ~~~e) |||  ~~~(e ^^^ f)) - 3 * (f ^^^ ( ~~~d &&& ( ~~~e ||| f))) + 11 * (e ^^^ (d ||| ( ~~~e ||| f))) + 5 * (e ^^^  ~~~( ~~~d &&& ( ~~~e &&& f))) - 6 * (e ^^^  ~~~(d &&& (e ||| f))) - 5 * (f ^^^ (d &&& ( ~~~e ||| f))) - 1 *  ~~~(e &&& f) + 1 *  ~~~(d ^^^ (e ||| f)) + 4 * (f |||  ~~~(d ^^^ e)) + 11 * (f ^^^ (d &&& (e ||| f))) - 5 *  ~~~( ~~~d ||| ( ~~~e &&& f)) - 1 * (e ^^^ ( ~~~d ||| (e &&& f))) + 11 * (e ^^^ (d &&& ( ~~~e ||| f))) - 2 * (f &&& (d ^^^ e)) - 1 * ( ~~~(d &&&  ~~~e) &&&  ~~~(d ^^^ (e ^^^ f))) - 2 * ( ~~~(d ||| e) ||| (d ^^^ (e ^^^ f))) - 1 * (e ^^^  ~~~(d &&& ( ~~~e ||| f))) + 1 * f - 6 * ( ~~~d ||| ( ~~~e ||| f)) + 2 * ( ~~~(d ^^^ e) &&& (d ^^^ f)) - 11 * ((d &&&  ~~~e) ||| (e ^^^ f)) + 1 * ( ~~~f &&& (d ^^^ e)) + 7 * ((e &&&  ~~~f) ^^^ (d ||| (e ^^^ f))) + 2 * ((d |||  ~~~e) &&& (d ^^^ (e ^^^ f))) - 1 * (f &&&  ~~~(d &&& e)) + 1 * (e ||| (d &&&  ~~~f)) - 3 * ((d &&& e) ^^^ (d ^^^ ( ~~~e ||| f))) - 7 * (d &&& e) + 15 *  ~~~(d ||| (e ||| f)) - 26 *  ~~~(d ||| ( ~~~e ||| f)) - 7 *  ~~~( ~~~d ||| (e ||| f)) - 12 *  ~~~( ~~~d ||| ( ~~~e ||| f)) + 4 * ( ~~~d &&& ( ~~~e &&& f)) - 10 * ( ~~~d &&& (e &&& f)) - 1 * (d &&& ( ~~~e &&& f)) + 25 * (d &&& (e &&& f)) = 1 *  ~~~(d ^^^ (e &&& f))

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

theorem select_icmp_sgt_allones_smin_thm.extracted_1._2 : ∀ (x : BitVec 8),
  ¬ofBool (-1#8 <ₛ x) = 1#1 → x ^^^ BitVec.ofInt 8 (-128) = x &&& 127#8

theorem main6b_logical_proof : main6b_logical_before ⊑ main6b_logical_after

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

theorem and_signbit_select_shl_proof : and_signbit_select_shl_before ⊑ and_signbit_select_shl_after

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

theorem scalar_i32_lshr_and_negC_eq_X_is_constant2_proof : scalar_i32_lshr_and_negC_eq_X_is_constant2_before ⊑ scalar_i32_lshr_and_negC_eq_X_is_constant2_after

theorem shl_and_thm (e e_1 : IntW 8) :
  shl (LLVM.and (shl e_1 (const? 8 3)) e) (const? 8 2) ⊑ LLVM.and (shl e_1 (const? 8 5)) (shl e (const? 8 2))

theorem ashrslt_03_05_proof : ashrslt_03_05_before ⊑ ashrslt_03_05_after

theorem e_96 :
    4 *  ~~~y + 7 *  ~~~x - 7 * (x ||| y) - 2 * (x ^^^ y) - 5 *  ~~~(x |||  ~~~y) - 2 * (x &&&  ~~~y) =  - 7 *  ~~~(x &&&  ~~~x) + 18 *  ~~~(x ||| y)

theorem mul_of_pow2_commute_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (1020#32 <ᵤ (x_1 &&& 255#32) * (x &&& 4#32)) = 0#1

theorem ne_shift_in_zeros_proof : ne_shift_in_zeros_before ⊑ ne_shift_in_zeros_after

theorem test5_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬30000#32 = 0 → 30000#32 = 0 ∨ True ∧ (x % 30000#32).msb = true → False

theorem lshrult_03_06_proof : lshrult_03_06_before ⊑ lshrult_03_06_after

theorem shift_xor_multiuse_xor_proof : shift_xor_multiuse_xor_before ⊑ shift_xor_multiuse_xor_after

theorem or_or_xor_commute2_proof : or_or_xor_commute2_before ⊑ or_or_xor_commute2_after

theorem t0_thm (e : IntW 16) (e_1 : IntW 32) :
  shl (trunc 16 (shl e_1 (zext 32 (sub (const? 16 32) e)))) (add e (const? 16 (-24))) ⊑
    shl (trunc 16 e_1) (const? 16 8)

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

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

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

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

theorem test_thm.extracted_1._1 : zeroExtend 32 (ofBool (1#32 == 2#32)) = 0#32

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

theorem in_constant_mone_vary_thm.extracted_1._1 : ∀ (x : BitVec 4), (x ^^^ -1#4) &&& 1#4 ^^^ x = x ||

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

theorem t0_basic_proof : t0_basic_before ⊑ t0_basic_after

theorem ashr_mul_proof : ashr_mul_before ⊑ ashr_mul_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 main2_logical_thm (e : IntW 32) :
  select
      (select (icmp IntPred.eq (LLVM.and e (const? 32 1)) (const? 32 0)) (const? 1 1)
        (icmp IntPred.eq (LLVM.and e (const? 32 2)) (const? 32 0)))
      (const? 32 0) (const? 32 1) ⊑
    zext 32 (icmp IntPred.eq (LLVM.and e (const? 32 3)) (const? 32 3))

theorem bitwise_or_logical_or_icmps_comm3_thm.extracted_1._6 : ∀ (x x_1 x_2 : BitVec 8),
  ¬x_1 ≥ ↑8 →
    ofBool (x_2 &&& 1#8 == 0#8) = 1#1 →
      ¬(True ∧ 1#8 <<< x_1 >>> x_1 ≠ 1#8 ∨ x_1 ≥ ↑8 ∨ True ∧ 1#8 <<< x_1 >>> x_1 ≠ 1#8 ∨ x_1 ≥ ↑8) →
        ¬ofBool (x_2 &&& (1#8 <<< x_1 ||| 1#8) != 1#8 <<< x_1 ||| 1#8) = 1#1 →
          ofBool (x_2 &&& 1#8 <<< x_1 == 0#8) ||

theorem ashr_sle_noexact_proof : ashr_sle_noexact_before ⊑ ashr_sle_noexact_after

theorem lshrugt_01_08_exact_proof : lshrugt_01_08_exact_before ⊑ lshrugt_01_08_exact_after

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

theorem udiv_x_by_const_cmp_x_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬123#32 = 0 → ofBool (x / 123#32 <ₛ x) = ofBool (0#32 <ₛ x)

theorem lshr_16_add_known_16_leading_zeroes_thm (e e_1 : IntW 32) :
  lshr (add (LLVM.and e_1 (const? 32 65535)) (LLVM.and e (const? 32 65535))) (const? 32 16) ⊑
    lshr (add (LLVM.and e_1 (const? 32 65535)) (LLVM.and e (const? 32 65535)) { «nsw» := true, «nuw» := true })
      (const? 32 16)

theorem xor_icmp_to_icmp_add_proof : xor_icmp_to_icmp_add_before ⊑ xor_icmp_to_icmp_add_after

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

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

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 test1_proof : test1_before ⊑ test1_after

theorem main15_proof : main15_before ⊑ main15_after

theorem n10_thm (e : IntW 64) :
  sub (const? 32 1) (trunc 32 (lshr e (const? 64 63))) ⊑
    add (trunc 32 (ashr e (const? 64 63)) { «nsw» := true, «nuw» := false }) (const? 32 1)
      { «nsw» := true, «nuw» := false }

theorem select_ashr_thm.extracted_1._3 : ∀ (x x_1 : BitVec 128) (x_2 : BitVec 1), ¬x_2 = 1#1 → 0#128 ≥ ↑128 → False

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

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

theorem select_1_thm.extracted_1._2 : ∀ (x : BitVec 1) (x_1 x_2 : BitVec 8) (x_3 : BitVec 1),
  x_3 = 1#1 → x_2 ^^^ (x_1 ^^^ 45#8) ^^^ -1#8 = x_1 ^^^ x_2 ^^^ BitVec.ofInt 8 (-46)

theorem pr64558_thm (e e_1 : IntW 1) : select (LLVM.and (LLVM.xor e_1 (const? 1 1)) e) e e_1 ⊑ LLVM.or e_1 e

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

theorem shl_sub_i32_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬31#32 - x ≥ ↑32 →
    True ∧ BitVec.ofInt 32 (-2147483648) >>> x <<< x ≠ BitVec.ofInt 32 (-2147483648) ∨ x ≥ ↑32 → False

theorem reassoc_x2_add_nuw_thm (e e_1 : IntW 32) :
  add (add e_1 (const? 32 4) { «nsw» := false, «nuw» := true }) (add e (const? 32 8) { «nsw» := false, «nuw» := true })
      { «nsw» := false, «nuw» := true } ⊑
    add (add e_1 e { «nsw» := false, «nuw» := true }) (const? 32 12) { «nsw» := false, «nuw» := true }

theorem ashrslt_01_01_exact_proof : ashrslt_01_01_exact_before ⊑ ashrslt_01_01_exact_after

theorem trunc_shl_nuw_31_i32_i64_proof : trunc_shl_nuw_31_i32_i64_before ⊑ trunc_shl_nuw_31_i32_i64_after

theorem masked_icmps_mask_notallzeros_bmask_mixed_swapped_1_logical_thm (e : IntW 32) :
  select (icmp IntPred.eq (LLVM.and e (const? 32 7)) (const? 32 1))
      (icmp IntPred.ne (LLVM.and e (const? 32 12)) (const? 32 0)) (const? 1 0) ⊑
    icmp IntPred.eq (LLVM.and e (const? 32 15)) (const? 32 9)

theorem test15 (x y : BitVec w) : (x - y) = (( x &&& (~~~ y)) - ((~~~ x) &&&  y))

theorem e_75 :
    1 *  ~~~(x &&&  ~~~y) + 1 * x - 12 *  ~~~(x ||| y) - 1 *  ~~~(x |||  ~~~y) - 2 * (x &&& y) =  - 11 *  ~~~y + 12 * (x &&&  ~~~y)

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

theorem testi8i8_proof : testi8i8_before ⊑ testi8i8_after

theorem ult_swap_or_not_max_proof : ult_swap_or_not_max_before ⊑ ult_swap_or_not_max_after

theorem test_sub__all_are_safe_proof : test_sub__all_are_safe_before ⊑ test_sub__all_are_safe_after

theorem test56_proof : test56_before ⊑ test56_after

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

@[simp] theorem cons_append : (x ::ₕ xs) ++ ys = (x ::ₕ (xs ++ ys))

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 sub_to_xor_and_commuted_thm (e e_1 : IntW 32) : sub (LLVM.or e_1 e) (LLVM.and e e_1) ⊑ LLVM.xor e e_1

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

theorem test4_thm.extracted_1._1 : ∀ (x : BitVec 8), ofBool (x ≤ₛ 126#8) = ofBool (x != 127#8)

theorem ult_and_max_proof : ult_and_max_before ⊑ ult_and_max_after

theorem or_and_xor_not_constant_commute1_thm (e e_1 : IntW 9) :
  LLVM.or (LLVM.and (LLVM.xor e_1 e) (const? 9 42)) (LLVM.and e_1 (const? 9 (-43))) ⊑
    LLVM.xor (LLVM.and e (const? 9 42)) e_1

theorem t1_flags_proof : t1_flags_before ⊑ t1_flags_after

theorem main7b_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 masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_proof : masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_before ⊑ masked_icmps_mask_notallzeros_bmask_mixed_negated_swapped_7b_after

theorem t3_exact_proof : t3_exact_before ⊑ t3_exact_after

theorem add_undemanded_low_bits_thm.extracted_1._1 : ∀ (x : BitVec 32),
  ¬4#32 ≥ ↑32 → ((x ||| 15#32) + 1616#32) >>> 4#32 = (x + 1616#32) >>> 4#32

theorem and_xor_commute4_thm (e e_1 : IntW 32) :
  LLVM.xor (LLVM.udiv (const? 32 42) e_1) (LLVM.and (LLVM.udiv (const? 32 42) e) (LLVM.udiv (const? 32 42) e_1)) ⊑
    LLVM.and (LLVM.udiv (const? 32 42) e_1) (LLVM.xor (LLVM.udiv (const? 32 42) e) (const? 32 (-1)))

theorem lshr_lshr_proof : lshr_lshr_before ⊑ lshr_lshr_after

theorem icmp_select_var_select_thm.extracted_1._4 : ∀ (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 → False

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

theorem a_false_implies_b_true2_comm_proof : a_false_implies_b_true2_comm_before ⊑ a_false_implies_b_true2_comm_after

theorem band_land_right2_proof : band_land_right2_before ⊑ band_land_right2_after

theorem test_mul_nsw__none_are_safe_proof : test_mul_nsw__none_are_safe_before ⊑ test_mul_nsw__none_are_safe_after

theorem n5_thm.extracted_1._2 : ∀ (x x_1 x_2 : BitVec 8), ofBool (x_2 &&& 1#8 == 2#8) = 1#1 → x_1 = x

theorem test_and2_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ofBool (-1#32 <ₛ x_1) &&& ofBool (x_1 ≤ₛ x &&& 2147483647#32) = ofBool (x_1 ≤ᵤ x &&& 2147483647#32)

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

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 e_333 :
    4 *  ~~~y + 4 *  ~~~(x ^^^ y) - 1 *  ~~~(x &&&  ~~~y) + 2 * y - 18 *  ~~~(x ||| y) - 1 *  ~~~(x |||  ~~~y) - 17 * (x &&&  ~~~y) - 18 * (x &&& y) =  - 11 * (x |||  ~~~y) - 2 * x

theorem sext_zext_nneg_uge_op0_wide_thm (e : IntW 8) (e_1 : IntW 16) :
  icmp IntPred.uge (sext 32 e_1) (zext 32 e { «nneg» := true }) ⊑ icmp IntPred.uge e_1 (sext 16 e)

theorem main4c_proof : main4c_before ⊑ main4c_after

theorem or_not_and_commute2_thm.extracted_1._1 : ∀ (x x_1 x_2 : BitVec 32),
  ¬((x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true ∨
        (x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true) →
    (x_2 == 0 || 32 != 1 && 42#32 == intMin 32 && x_2 == -1) = true → False

theorem test9_thm (e : IntW 32) : trunc 8 (LLVM.and e (const? 32 42)) ⊑ LLVM.and (trunc 8 e) (const? 8 42)

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

theorem e_418 :
     - 6 *  ~~~y - 7 *  ~~~x + 1 *  ~~~(x ^^^ y) - 1 *  ~~~(x &&& y) + 13 *  ~~~(x ||| y) + 10 *  ~~~(x |||  ~~~y) + 9 * (x &&&  ~~~y) + 1 * (x &&& y) = 2 * (x ||| y)

theorem lshr_2_add_zext_basic_proof : lshr_2_add_zext_basic_before ⊑ lshr_2_add_zext_basic_after

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 logical_or_not_proof : logical_or_not_before ⊑ logical_or_not_after

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

theorem sext_zext_uge_known_nonneg_op0_wide_proof : sext_zext_uge_known_nonneg_op0_wide_before ⊑ sext_zext_uge_known_nonneg_op0_wide_after

theorem sge_smin4_proof : sge_smin4_before ⊑ sge_smin4_after

theorem ashrslt_03_11_proof : ashrslt_03_11_before ⊑ ashrslt_03_11_after

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

@[simp]
lemma proj_stepSet (M : NFA (BitVec m) σ) (f : Fin n → Fin m) :
    (M.proj f).stepSet S a =
      ⋃ a' ∈ BitVec.transport f ⁻¹' {a}, M.stepSet S a'

@[simp] theorem Expr.changeVars_changeVars (e : Expr d Γ eff ty) (f : Γ.Hom Δ) (g : Δ.Hom Ξ) :
    (e.changeVars f).changeVars g = e.changeVars (f.comp g)

theorem n15_variable_shamts_proof : n15_variable_shamts_before ⊑ n15_variable_shamts_after

theorem lshr_add_proof : lshr_add_before ⊑ lshr_add_after

theorem icmp_sle4_proof : icmp_sle4_before ⊑ icmp_sle4_after

theorem sext_sext_slt_proof : sext_sext_slt_before ⊑ sext_sext_slt_after

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

theorem addsub_combine_constants_thm (e e_1 : IntW 7) :
  add (add e_1 (const? 7 42)) (sub (const? 7 10) e) { «nsw» := true, «nuw» := false } ⊑
    add (sub e_1 e) (const? 7 52)

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

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

theorem negate_sdiv_proof : negate_sdiv_before ⊑ negate_sdiv_after

theorem neg_sgt_0_proof : neg_sgt_0_before ⊑ neg_sgt_0_after

theorem test2_thm.extracted_1._2 : ∀ (x : BitVec 49),
  ¬(17#49 ≥ ↑49 ∨ 4096#49 <<< 17#49 = 0) → ¬29#49 ≥ ↑49 → x / 4096#49 <<< 17#49 = x >>> 29#49

theorem lshr_31_i32_add_zext_basic_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32),
  ¬31#64 ≥ ↑64 →
    True ∧ (zeroExtend 64 x_1).saddOverflow (zeroExtend 64 x) = true ∨
        True ∧ (zeroExtend 64 x_1).uaddOverflow (zeroExtend 64 x) = true ∨ 31#64 ≥ ↑64 →
      False

theorem icmp_eq_select_thm.extracted_1._1 : ∀ (x x_1 : BitVec 32) (x_2 : BitVec 1),
  ¬x_2 = 1#1 → ofBool (x == x_1) = ofBool (x_1 == x)

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

theorem ult_x_impliesT_eq_umax_todo_proof : ult_x_impliesT_eq_umax_todo_before ⊑ ult_x_impliesT_eq_umax_todo_after

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

theorem test6_thm.extracted_1._1 : ∀ (x : BitVec 55), ¬1#55 ≥ ↑55 → x <<< 1#55 * 3#55 = x * 6#55

theorem scalar_i32_shl_and_negC_slt_proof : scalar_i32_shl_and_negC_slt_before ⊑ scalar_i32_shl_and_negC_slt_after

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

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

@[symm] theorem Bisim.symm {a b : Stream α} : a ~ b → b ~ a

theorem or_logic_or_logic_and_4_proof : or_logic_or_logic_and_4_before ⊑ or_logic_or_logic_and_4_after

theorem t2_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8) (x_2 : BitVec 1),
  signExtend 8 x_2 + x_1 ^^^ signExtend 8 x = x_1 + signExtend 8 x_2 ^^^ signExtend 8 x

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

theorem test6_proof : test6_before ⊑ test6_after

theorem test_eq_0_and_15_add_3_proof : test_eq_0_and_15_add_3_before ⊑ test_eq_0_and_15_add_3_after

theorem and_nosignbit_select_ashr_thm.extracted_1._1 : ∀ (x : BitVec 32) (x_1 : BitVec 1),
  x_1 = 1#1 → ¬8#32 ≥ ↑32 → (x &&& 2147418112#32).sshiftRight' 8#32 = x.sshiftRight' 8#32 &&& 8388352#32

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

theorem t0_proof : t0_before ⊑ t0_after

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

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

theorem test_lshr_exact__exact_is_unsafe_proof : test_lshr_exact__exact_is_unsafe_before ⊑ test_lshr_exact__exact_is_unsafe_after

theorem test85_proof : test85_before ⊑ test85_after

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

theorem t5_thm.extracted_1._6 : ∀ (x x_1 : BitVec 1) (x_2 : BitVec 32),
  x_1 = 1#1 → ¬x = 1#1 → ¬64#32 = 0 → 6#32 ≥ ↑32 → False

theorem sgt_or_not_min_commute_logical_thm.extracted_1._3 : ∀ (x x_1 : BitVec 8),
  ¬ofBool (x_1 != BitVec.ofInt 8 (-128)) = 1#1 → ofBool (x <ₛ x_1) = ofBool (x_1 != BitVec.ofInt 8 (-128))

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 t0_sub_from_trueval_thm.extracted_1._1 : ∀ (x : BitVec 1) (x_1 : BitVec 8), x = 1#1 → x_1 - x_1 = 0#8

theorem ashr_ugt_2_proof : ashr_ugt_2_before ⊑ ashr_ugt_2_after

theorem test1_proof : test1_before ⊑ test1_after

@[simp, simp_denote] theorem effToMonadRefinement_impure (x : impure.toMonad m α) (y : impure.toMonad n β) :
    x ⊑ y ↔ (@id (m α) x) ⊑ (@id (n β) y)

theorem not_invert_signbit_splat_mask1_thm.extracted_1._1 : ∀ (x : BitVec 16) (x_1 : BitVec 8),
  ¬7#8 ≥ ↑8 →
    zeroExtend 16 (x_1.sshiftRight' 7#8 ^^^ -1#8) &&& x = x &&& zeroExtend 16 (signExtend 8 (ofBool (-1#8 <ₛ x_1)))

theorem positive_biggerLshr_shlnuw_lshrexact_thm (e : IntW 32) :
  lshr (shl e (const? 32 5) { «nsw» := false, «nuw» := true }) (const? 32 10) { «exact» := true } ⊑
    lshr e (const? 32 5) { «exact» := true }

theorem src_is_notmask_lshr_shl_fail_mismatch_shifts_proof : src_is_notmask_lshr_shl_fail_mismatch_shifts_before ⊑ src_is_notmask_lshr_shl_fail_mismatch_shifts_after

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

theorem and_ne_with_one_bit_diff_constants2_logical_proof : and_ne_with_one_bit_diff_constants2_logical_before ⊑ and_ne_with_one_bit_diff_constants2_logical_after

theorem test2_proof : test2_before ⊑ test2_after

theorem icmp_eq_x_invertable_y2_proof : icmp_eq_x_invertable_y2_before ⊑ icmp_eq_x_invertable_y2_after
</all_available_lemmas>

<local_ctx>
import LeanMLIR.Framework

import LeanMLIR.Framework.Zipper

import LeanMLIR.Transforms.Rewrite.Match

open Ctxt (Var VarSet Valuation)

variable {d} [DialectSignature d] [TyDenote d.Ty] [DialectDenote d] [Monad d.m]

variable [DecidableEq d.Ty] [DecidableEq d.Op]

variable [∀ (t : d.Ty), Inhabited (toType t)]

section SplitProgram

variable (d Γ eff t) in

structure SplitProgramResult extends Zipper d Γ eff t where
  {midTypes : List d.Ty}
  midRet : HVector toZipper.Γ_mid.Var midTypes

def splitProgramAtAux : (pos : ℕ) → (lets : Lets d Γ₁ eff Γ₂) →
    (prog : Com d Γ₂ eff t) →
    Option (SplitProgramResult d Γ₁ eff t)
  | 0, lets, .var e body => some {
      top := lets.var e
      bot := body
      midRet := e.returnVars
    }
  | _, _, .rets _ => none
  | n+1, lets, .var e body =>
    splitProgramAtAux n (lets.var e) body

def splitProgramAt (pos : ℕ) (prog : Com d Γ eff t) :
    Option (SplitProgramResult d Γ eff t) :=
  splitProgramAtAux pos .nil prog

end SplitProgram

def rewriteAt
    (lhs rhs : Com d Γ₁ .pure ts₁)
    (hlhs : ∀ t (v : Var Γ₁ t), ⟨t, v⟩ ∈ lhs.vars)
    (pos : ℕ) (target : Com d Γ₂ eff t₂) :
    Option (Com d Γ₂ eff t₂) := do
  let splitRes ← splitProgramAt pos target
  if h : ts₁ = splitRes.midTypes then
    let m ← matchArgRes splitRes.top lhs.toLets splitRes.midRet (h ▸ lhs.returnVars)
    let m := m.toHom <| by
      subst h; exact hlhs
    let rhs := rhs.changeVars m
    let zip := splitRes.insertPureCom splitRes.midRet (cast (by admit /- proof elided -/
    ) rhs)
    return zip.toCom
  else none
</local_ctx>

<target_theorem>
theorem denote_rewriteAt [LawfulMonad d.m]
    {lhs rhs : Com d Γ₁ .pure t₁}
    (hl : lhs.denote = rhs.denote)
    {hlhs : ∀ t (v : Var Γ₁ t), ⟨t, v⟩ ∈ lhs.vars}
    {pos : ℕ} {target : Com d Γ₂ eff t₂}
    {rew : Com d Γ₂ eff t₂}
    (hrew : rew ∈ rewriteAt lhs rhs hlhs pos target) :
    rew.denote = target.denote :=
</target_theorem>

