Repository: bytecodealliance/wasmtime
Pull request #6113 (2023-03-28 20:17:17)

x64: Deduplicate fcmp emission logic
The `select`-of-`fcmp` lowering duplicated a good deal of `FloatCC`
lowering logic that was already done by `emit_fcmp`, so this commit
refactors these lowering rules to instead delegate to `emit_fcmp` and
then handle that result.

I also split up the commits here where the first one is slightly unidiomatic in a few places but doesn't affect any of the test outputs. The next two commits swap the order of a few operands and shows the test updates necessary to get there.


Patch:
diff --git a/CODEOWNERS b/CODEOWNERS
index 0ce6d46c7..61d8a372d 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -19,24 +19,24 @@
 # work on this project. We gratefully welcome reviews from other contributors,
 # but we don't believe it's fair to ask volunteers to respond quickly.
 
-# TODO: use GitHub teams instead of individual usernames
-
-# If none of the later patterns match, assign to anyone:
-* @alexcrichton @cfallin @elliottt @fitzgen @jameysharp @pchickey
+# If none of the later patterns match, assign to anyone. This team is the
+# parent of all the other teams and automatically includes everyone on those
+# teams.
+* @bytecodealliance/wasmtime-default-reviewers
 
 # Some parts of the project require more specialized knowledge. In those areas
 # we designate smaller groups who are more likely to be aware of who's working
 # in specific areas.
 
 # Wasmtime
-/crates/   @alexcrichton @fitzgen @jameysharp @pchickey
-/examples/ @alexcrichton @fitzgen @jameysharp @pchickey
-/src/      @alexcrichton @fitzgen @jameysharp @pchickey
-/tests/    @alexcrichton @fitzgen @jameysharp @pchickey
+/crates/   @bytecodealliance/wasmtime-core-reviewers
+/examples/ @bytecodealliance/wasmtime-core-reviewers
+/src/      @bytecodealliance/wasmtime-core-reviewers
+/tests/    @bytecodealliance/wasmtime-core-reviewers
 
 # Cranelift/Winch compilers
-/cranelift/ @cfallin @elliottt @fitzgen @jameysharp
-/winch/     @cfallin @elliottt @fitzgen @jameysharp
+/cranelift/ @bytecodealliance/wasmtime-compiler-reviewers
+/winch/     @bytecodealliance/wasmtime-compiler-reviewers
 
 # Fuzz testing
-/fuzz/ @alexcrichton @elliottt @fitzgen @jameysharp
+/fuzz/ @bytecodealliance/wasmtime-fuzz-reviewers
diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs
index f9dd071dc..723cffb10 100644
--- a/cranelift/codegen/src/isa/x64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/x64/inst/mod.rs
@@ -1589,20 +1589,19 @@ impl PrettyPrint for Inst {
                 let alternative = pretty_print_reg(alternative.to_reg(), size, allocs);
                 let dst = pretty_print_reg(dst.to_reg().to_reg(), size, allocs);
                 let consequent = consequent.pretty_print(size, allocs);
+                let suffix = match *ty {
+                    types::F64 => "sd",
+                    types::F32 => "ss",
+                    types::F32X4 => "aps",
+                    types::F64X2 => "apd",
+                    _ => "dqa",
+                };
                 format!(
-                    "mov {}, {}; j{} $next; mov{} {}, {}; $next: ",
+                    "mov{suffix} {alternative}, {dst}; \
+                    j{} $next; \
+                    mov{suffix} {consequent}, {dst}; \
+                    $next:",
                     cc.invert().to_string(),
-                    match *ty {
-                        types::F64 => "sd",
-                        types::F32 => "ss",
-                        types::F32X4 => "aps",
-                        types::F64X2 => "apd",
-                        _ => "dqa",
-                    },
-                    consequent,
-                    dst,
-                    alternative,
-                    dst,
                 )
             }
 
diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle
index ee7ca827b..3e50417d0 100644
--- a/cranelift/codegen/src/isa/x64/lower.isle
+++ b/cranelift/codegen/src/isa/x64/lower.isle
@@ -1570,90 +1570,25 @@
 
 ;;;; Rules for `select` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;; CLIF `select` instructions receive a testable argument (i.e. boolean or
-;; integer) that determines which of the other two arguments is selected as
-;; output. Since Cranelift booleans are typically generated by a comparison, the
-;; lowerings in this section "look upwards in the tree" to emit the proper
-;; sequence of "selection" instructions.
+;; When a `select` has an `fcmp` as a condition then rely on `emit_fcmp` to
+;; figure out how to perform the comparison.
 ;;
-;; The following rules--for selecting on a floating-point comparison--emit a
-;; `UCOMIS*` instruction and then a conditional move, `cmove`. Note that for
-;; values contained in XMM registers, `cmove` and `cmove_or` may in fact emit a
-;; jump sequence, not `CMOV`. The `cmove` instruction operates on the flags set
-;; by `UCOMIS*`; the key to understanding these is the UCOMIS* documentation
-;; (see Intel's Software Developer's Manual, volume 2, chapter 4):
-;;  - unordered assigns    Z = 1, P = 1, C = 1
-;;  - greater than assigns Z = 0, P = 0, C = 0
-;;  - less than assigns    Z = 0, P = 0, C = 1
-;;  - equal assigns        Z = 1, P = 0, C = 0
-;;
-;; Note that prefixing the flag with `N` means "not," so that `CC.P -> P = 1`
-;; and `CC.NP -> P = 0`. Also, x86 uses mnemonics for certain combinations of
-;; flags; e.g.:
-;;  - `CC.B -> C = 1` (below)
-;;  - `CC.NB -> C = 0` (not below)
-;;  - `CC.BE -> C = 1 OR Z = 1` (below or equal)
-;;  - `CC.NBE -> C = 0 AND Z = 0` (not below or equal)
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.Ordered) a b)) x y)))
-      (with_flags (x64_ucomis b a) (cmove_from_values ty (CC.NP) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.Unordered) a b)) x y)))
-      (with_flags (x64_ucomis b a) (cmove_from_values ty (CC.P) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.GreaterThan) a b)) x y)))
-      (with_flags (x64_ucomis b a) (cmove_from_values ty (CC.NBE) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.GreaterThanOrEqual) a b)) x y)))
-      (with_flags (x64_ucomis b a) (cmove_from_values ty (CC.NB) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.UnorderedOrLessThan) a b)) x y)))
-      (with_flags (x64_ucomis b a) (cmove_from_values ty (CC.B) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.UnorderedOrLessThanOrEqual) a b)) x y)))
-      (with_flags (x64_ucomis b a) (cmove_from_values ty (CC.BE) x y)))
-
-;; Certain FloatCC variants are implemented by flipping the operands of the
-;; comparison (e.g., "greater than" is lowered the same as "less than" but the
-;; comparison is reversed). This allows us to use a single flag for the `cmove`,
-;; which involves fewer instructions than `cmove_or`.
-;;
-;; But why flip at all, you may ask? Can't we just use `CC.B` (i.e., below) for
-;; `FloatCC.LessThan`? Recall that in these floating-point lowerings, values may
-;; be unordered and we must we want to express that `FloatCC.LessThan` is `LT`,
-;; not `LT | UNO`. By flipping the operands AND inverting the comparison (e.g.,
-;; to `CC.NBE`), we also avoid these unordered cases.
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.LessThan) a b)) x y)))
-      (with_flags (x64_ucomis a b) (cmove_from_values ty (CC.NBE) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.LessThanOrEqual) a b)) x y)))
-      (with_flags (x64_ucomis a b) (cmove_from_values ty (CC.NB) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.UnorderedOrGreaterThan) a b)) x y)))
-      (with_flags (x64_ucomis a b) (cmove_from_values ty (CC.B) x y)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.UnorderedOrGreaterThanOrEqual) a b)) x y)))
-      (with_flags (x64_ucomis a b) (cmove_from_values ty (CC.BE) x y)))
-
-;; `FloatCC.Equal` and `FloatCC.NotEqual` can only be implemented with multiple
-;; flag checks. Recall from the flag assignment chart above that equality, e.g.,
-;; will assign `Z = 1`. But so does an unordered comparison: `Z = 1, P = 1, C =
-;; 1`. In order to avoid semantics like `EQ | UNO` for equality, we must ensure
-;; that the values are actually ordered, checking that `P = 0` (note that the
-;; `C` flag is irrelevant here). Since we cannot find a single instruction that
-;; implements a `Z = 1 AND P = 0` check, we invert the flag checks (i.e., `Z = 1
-;; AND P = 0` becomes `Z = 0 OR P = 1`) and also flip the select operands, `x`
-;; and `y`. The same argument applies to `FloatCC.NotEqual`.
-;;
-;; More details about the CLIF semantics for `fcmp` are available at
-;; https://docs.rs/cranelift-codegen/latest/cranelift_codegen/ir/trait.InstBuilder.html#method.fcmp.
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.Equal) a b)) x y)))
-      (with_flags (x64_ucomis a b) (cmove_or_from_values ty (CC.NZ) (CC.P) y x)))
-
-(rule (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.NotEqual) a b)) x y)))
-      (with_flags (x64_ucomis a b) (cmove_or_from_values ty (CC.NZ) (CC.P) x y)))
+;; Note, though, that the `FloatCC.Equal` requires an "and" to happen for two
+;; condition codes which isn't the easiest thing to lower to a `cmove`
+;; instruction. For this reason a `select (fcmp eq ..) ..` is instead
+;; flipped around to be `select (fcmp ne ..) ..` with all operands reversed.
+;; This will produce a `FcmpCondResult.OrCondition` which is easier to codegen
+;; for.
+(rule (lower (has_type ty (select (maybe_uextend (fcmp cc a b)) x y)))
+      (lower_select_fcmp ty (emit_fcmp cc a b) x y))
+(rule 1 (lower (has_type ty (select (maybe_uextend (fcmp (FloatCC.Equal) a b)) x y)))
+        (lower_select_fcmp ty (emit_fcmp (FloatCC.NotEqual) a b) y x))
+
+(decl lower_select_fcmp (Type FcmpCondResult Value Value) InstOutput)
+(rule (lower_select_fcmp ty (FcmpCondResult.Condition flags cc) x y)
+      (with_flags flags (cmove_from_values ty cc x y)))
+(rule (lower_select_fcmp ty (FcmpCondResult.OrCondition flags cc1 cc2) x y)
+      (with_flags flags (cmove_or_from_values ty cc1 cc2 x y)))
 
 ;; We also can lower `select`s that depend on an `icmp` test, but more simply
 ;; than the `fcmp` variants above. In these cases, we lower to a `CMP`
diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle
index 8cab77bd4..db3d8d4b4 100644
--- a/cranelift/codegen/src/opts/algebraic.isle
+++ b/cranelift/codegen/src/opts/algebraic.isle
@@ -479,6 +479,56 @@
              (iconst _ (u64_from_imm64 0))))
       (iconst ty (imm64 1)))
 
+(decl pure decompose_intcc (IntCC) u64)
+(rule (decompose_intcc (IntCC.Equal)) 1)
+(rule (decompose_intcc (IntCC.UnsignedLessThan)) 2)
+(rule (decompose_intcc (IntCC.SignedLessThan)) 2)
+(rule (decompose_intcc (IntCC.UnsignedLessThanOrEqual)) 3)
+(rule (decompose_intcc (IntCC.SignedLessThanOrEqual)) 3)
+(rule (decompose_intcc (IntCC.UnsignedGreaterThan)) 4)
+(rule (decompose_intcc (IntCC.SignedGreaterThan)) 4)
+(rule (decompose_intcc (IntCC.UnsignedGreaterThanOrEqual)) 5)
+(rule (decompose_intcc (IntCC.SignedGreaterThanOrEqual)) 5)
+(rule (decompose_intcc (IntCC.NotEqual)) 6)
+
+(decl compose_icmp (Type u64 bool Value Value) Value)
+(rule (compose_icmp ty 0 _ _ _) (subsume (iconst ty (imm64 0))))
+(rule (compose_icmp ty 1 _ x y) (icmp ty (IntCC.Equal) x y))
+(rule (compose_icmp ty 2 $false x y) (icmp ty (IntCC.UnsignedLessThan) x y))
+(rule (compose_icmp ty 2 $true x y) (icmp ty (IntCC.SignedLessThan) x y))
+(rule (compose_icmp ty 3 $false x y) (icmp ty (IntCC.UnsignedLessThanOrEqual) x y))
+(rule (compose_icmp ty 3 $true x y) (icmp ty (IntCC.SignedLessThanOrEqual) x y))
+(rule (compose_icmp ty 4 $false x y) (icmp ty (IntCC.UnsignedGreaterThan) x y))
+(rule (compose_icmp ty 4 $true x y) (icmp ty (IntCC.SignedGreaterThan) x y))
+(rule (compose_icmp ty 5 $false x y) (icmp ty (IntCC.UnsignedGreaterThanOrEqual) x y))
+(rule (compose_icmp ty 5 $true x y) (icmp ty (IntCC.SignedGreaterThanOrEqual) x y))
+(rule (compose_icmp ty 6 _ x y) (icmp ty (IntCC.NotEqual) x y))
+(rule (compose_icmp ty 7 _ _ _) (subsume (iconst ty (imm64 1))))
+
+(decl pure intcc_class (IntCC) u64)
+(rule (intcc_class (IntCC.UnsignedLessThan)) 1)
+(rule (intcc_class (IntCC.UnsignedLessThanOrEqual)) 1)
+(rule (intcc_class (IntCC.UnsignedGreaterThan)) 1)
+(rule (intcc_class (IntCC.UnsignedGreaterThanOrEqual)) 1)
+(rule (intcc_class (IntCC.SignedLessThan)) 2)
+(rule (intcc_class (IntCC.SignedLessThanOrEqual)) 2)
+(rule (intcc_class (IntCC.SignedGreaterThan)) 2)
+(rule (intcc_class (IntCC.SignedGreaterThanOrEqual)) 2)
+(rule (intcc_class (IntCC.Equal)) 3)
+(rule (intcc_class (IntCC.NotEqual)) 3)
+
+(decl pure partial intcc_comparable (IntCC IntCC) bool)
+(rule (intcc_comparable x y)
+  (if-let (u64_nonzero class) (u64_and (intcc_class x) (intcc_class y)))
+  (u64_eq 2 class))
+
+(rule (simplify (band ty (icmp ty cc1 x y) (icmp ty cc2 x y)))
+  (if-let signed (intcc_comparable cc1 cc2))
+  (compose_icmp ty (u64_and (decompose_intcc cc1) (decompose_intcc cc2)) signed x y))
+
+(rule (simplify (bor ty (icmp ty cc1 x y) (icmp ty cc2 x y)))
+  (if-let signed (intcc_comparable cc1 cc2))
+  (compose_icmp ty (u64_or (decompose_intcc cc1) (decompose_intcc cc2)) signed x y))
 
 ;; Transform select-of-icmp into {u,s}{min,max} instructions where possible.
 (rule (simplify (select ty (sgt _ x y) x y)) (smax ty x y))


Test patch:
diff --git a/cranelift/filetests/filetests/egraph/icmp.clif b/cranelift/filetests/filetests/egraph/icmp.clif
new file mode 100644
index 000000000..0f10e4062
--- /dev/null
+++ b/cranelift/filetests/filetests/egraph/icmp.clif
@@ -0,0 +1,3010 @@
+test optimize precise-output
+set opt_level=speed
+set use_egraphs=true
+target x86_64
+
+;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;; !!! GENERATED BY 'make-icmp-tests.sh' DO NOT EDIT !!!
+;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;; run with the 'CRANELIFT_TEST_BLESS=1' env var set to update this file
+
+function %icmp_and_eq_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp eq v0, v1
+;     return v2
+; }
+
+function %icmp_and_eq_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_eq_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_eq_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_eq_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_eq_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_eq_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_eq_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_eq_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_eq_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_eq_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ne_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ne v0, v1
+;     return v2
+; }
+
+function %icmp_and_ne_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ult v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ult v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ugt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ugt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp slt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp slt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sgt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ne_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ne_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sgt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ult_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ult_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ult v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ult_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     return v2
+; }
+
+function %icmp_and_ult_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ult v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ult_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ult_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ult_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ult_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ult_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ult_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ult_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ule_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ule_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ult v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ule_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ult v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ule_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     return v2
+; }
+
+function %icmp_and_ule_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ule_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ule_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ule_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ule_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ule_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ule_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ugt_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ugt_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ugt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ugt_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ugt_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_ugt_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     return v2
+; }
+
+function %icmp_and_ugt_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ugt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_ugt_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ugt_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ugt_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_ugt_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_ugt_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_uge_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_uge_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ugt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_uge_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_uge_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_uge_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ugt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_uge_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     return v2
+; }
+
+function %icmp_and_uge_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_uge_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_uge_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_uge_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_uge_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_slt_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_slt_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp slt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_slt_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_slt_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_slt_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_slt_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_slt_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     return v2
+; }
+
+function %icmp_and_slt_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp slt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_slt_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_slt_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_slt_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_sle_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sle_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp slt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sle_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sle_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sle_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sle_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sle_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp slt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sle_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     return v2
+; }
+
+function %icmp_and_sle_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_sle_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sle_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sgt_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_sgt_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sgt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sgt_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sgt_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sgt_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sgt_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sgt_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_sgt_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_sgt_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     return v2
+; }
+
+function %icmp_and_sgt_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sgt_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sgt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sge_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp eq v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sge_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ne v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sgt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sge_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ult v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sge_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ule v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sge_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sge_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp uge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = band v2, v3
+;     return v4
+; }
+
+function %icmp_and_sge_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp slt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 0
+;     return v5  ; v5 = 0
+; }
+
+function %icmp_and_sge_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp sle v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp eq v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sge_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sgt v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_and_sge_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp sge v0, v1
+    v4 = band v2, v3
+    return v4
+}
+
+; function %icmp_and_sge_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     return v2
+; }
+
+function %icmp_or_eq_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp eq v0, v1
+;     return v2
+; }
+
+function %icmp_or_eq_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_eq_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ule v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ule v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp uge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp uge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sle v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sle v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_eq_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp eq v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_eq_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ne_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ne_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ne v0, v1
+;     return v2
+; }
+
+function %icmp_or_ne_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ne_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ne_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ne_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ne_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ne_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ne_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ne_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ne v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ne_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ult_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ule v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ult_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ult_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     return v2
+; }
+
+function %icmp_or_ult_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ule v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ult_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ult_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ult_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ult_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ult_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ult_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ult v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ult_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ult v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ule_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ule v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ule_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ule_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ule v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ule_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     return v2
+; }
+
+function %icmp_or_ule_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ule_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ule_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ule_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ule_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ule_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ule v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ule_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ule v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ugt_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp uge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ugt_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ugt_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ugt_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_ugt_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     return v2
+; }
+
+function %icmp_or_ugt_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp uge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_ugt_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ugt_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ugt_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_ugt_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ugt v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_ugt_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp ugt v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_uge_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp uge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_uge_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_uge_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_uge_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_uge_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp uge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_uge_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     return v2
+; }
+
+function %icmp_or_uge_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp slt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_uge_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp sle v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_uge_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp sgt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_uge_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp uge v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_uge_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp uge v0, v1
+;     v3 = icmp sge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_slt_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sle v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_slt_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_slt_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_slt_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_slt_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_slt_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_slt_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp slt v0, v1
+;     return v2
+; }
+
+function %icmp_or_slt_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sle v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_slt_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_slt_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp slt v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_slt_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sle_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sle v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sle_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sle_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sle_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sle_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sle_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sle_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sle v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sle_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sle v0, v1
+;     return v2
+; }
+
+function %icmp_or_sle_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sle_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sle v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sle_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sgt_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sgt_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sgt_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sgt_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sgt_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sgt_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sgt_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp ne v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sgt_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sgt_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sgt v0, v1
+;     return v2
+; }
+
+function %icmp_or_sgt_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sgt v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sgt_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sge_eq(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp eq v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_eq(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sge_ne(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ne v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_ne(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sge_ult(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ult v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_ult(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp ult v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sge_ule(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ule v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_ule(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp ule v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sge_ugt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp ugt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_ugt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp ugt v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sge_uge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp uge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_uge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     v3 = icmp uge v0, v1
+;     v4 = bor v2, v3
+;     return v4
+; }
+
+function %icmp_or_sge_slt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp slt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_slt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sge_sle(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp sle v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_sle(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = iconst.i8 1
+;     return v5  ; v5 = 1
+; }
+
+function %icmp_or_sge_sgt(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp sgt v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_sgt(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v5 = icmp sge v0, v1
+;     v6 -> v5
+;     return v5
+; }
+
+function %icmp_or_sge_sge(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp sge v0, v1
+    v3 = icmp sge v0, v1
+    v4 = bor v2, v3
+    return v4
+}
+
+; function %icmp_or_sge_sge(i32, i32) -> i8 fast {
+; block0(v0: i32, v1: i32):
+;     v2 = icmp sge v0, v1
+;     return v2
+; }
+
diff --git a/cranelift/filetests/filetests/egraph/make-icmp-tests.sh b/cranelift/filetests/filetests/egraph/make-icmp-tests.sh
new file mode 100755
index 000000000..79b021781
--- /dev/null
+++ b/cranelift/filetests/filetests/egraph/make-icmp-tests.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+set -e
+cd $(dirname "$0")
+out=icmp.clif
+CCS="eq ne ult ule ugt uge slt sle sgt sge"
+
+function main {
+    cat << EOF > $out
+test optimize precise-output
+set opt_level=speed
+set use_egraphs=true
+target x86_64
+
+;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;; !!! GENERATED BY 'make-icmp-tests.sh' DO NOT EDIT !!!
+;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+;; run with the 'CRANELIFT_TEST_BLESS=1' env var set to update this file
+
+EOF
+    for op in "and" "or"; do
+        for cc1 in $CCS; do
+            for cc2 in $CCS; do
+                cat << EOF >> $out
+function %icmp_${op}_${cc1}_${cc2}(i32, i32) -> i8 {
+block0(v0: i32, v1: i32):
+    v2 = icmp ${cc1} v0, v1
+    v3 = icmp ${cc2} v0, v1
+    v4 = b${op} v2, v3
+    return v4
+}
+EOF
+            done
+        done
+    done
+}
+
+main
diff --git a/cranelift/filetests/filetests/isa/x64/cmp-mem-bug.clif b/cranelift/filetests/filetests/isa/x64/cmp-mem-bug.clif
index 459302beb..a7996bdab 100644
--- a/cranelift/filetests/filetests/isa/x64/cmp-mem-bug.clif
+++ b/cranelift/filetests/filetests/isa/x64/cmp-mem-bug.clif
@@ -60,10 +60,10 @@ block0(v0: f64, v1: i64):
 ;   setz    %al
 ;   andl    %edi, %eax, %edi
 ;   movzbq  %dil, %rax
-;   ucomisd %xmm0, %xmm9
+;   ucomisd %xmm9, %xmm0
 ;   movdqa  %xmm0, %xmm2
-;   mov z, sd; j%xmm2 $next; mov%xmm0 %xmm0, %xmm0; $next: 
-;   mov np, sd; j%xmm2 $next; mov%xmm0 %xmm0, %xmm0; $next: 
+;   movsd %xmm0, %xmm0; jnp $next; movsd %xmm2, %xmm0; $next:
+;   movsd %xmm0, %xmm0; jz $next; movsd %xmm2, %xmm0; $next:
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -79,11 +79,11 @@ block0(v0: f64, v1: i64):
 ;   sete %al
 ;   andl %eax, %edi
 ;   movzbq %dil, %rax
-;   ucomisd %xmm0, %xmm9
+;   ucomisd %xmm9, %xmm0
 ;   movdqa %xmm0, %xmm2
-;   je 0x2f
+;   jnp 0x2f
 ;   movsd %xmm2, %xmm0
-;   jnp 0x39
+;   je 0x39
 ;   movsd %xmm2, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
diff --git a/cranelift/filetests/filetests/isa/x64/select-i128.clif b/cranelift/filetests/filetests/isa/x64/select-i128.clif
index 89576c873..035322813 100644
--- a/cranelift/filetests/filetests/isa/x64/select-i128.clif
+++ b/cranelift/filetests/filetests/isa/x64/select-i128.clif
@@ -52,11 +52,11 @@ block0(v0: f32, v1: i128, v2: i128):
 ; block0:
 ;   ucomiss %xmm0, %xmm0
 ;   movq    %rdi, %rax
-;   cmovnzq %rdx, %rax, %rax
 ;   cmovpq  %rdx, %rax, %rax
+;   cmovnzq %rdx, %rax, %rax
 ;   movq    %rsi, %rdx
-;   cmovnzq %rcx, %rdx, %rdx
 ;   cmovpq  %rcx, %rdx, %rdx
+;   cmovnzq %rcx, %rdx, %rdx
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -68,11 +68,11 @@ block0(v0: f32, v1: i128, v2: i128):
 ; block1: ; offset 0x4
 ;   ucomiss %xmm0, %xmm0
 ;   movq %rdi, %rax
-;   cmovneq %rdx, %rax
 ;   cmovpq %rdx, %rax
+;   cmovneq %rdx, %rax
 ;   movq %rsi, %rdx
-;   cmovneq %rcx, %rdx
 ;   cmovpq %rcx, %rdx
+;   cmovneq %rcx, %rdx
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
diff --git a/cranelift/filetests/filetests/isa/x64/select-issue-3744.clif b/cranelift/filetests/filetests/isa/x64/select-issue-3744.clif
index 2e50d6c0a..eff72d2b3 100644
--- a/cranelift/filetests/filetests/isa/x64/select-issue-3744.clif
+++ b/cranelift/filetests/filetests/isa/x64/select-issue-3744.clif
@@ -1,4 +1,4 @@
-test compile
+test compile precise-output
 target x86_64
 
 ; Check that no intervening moves are inserted when lowering `select` (see
@@ -9,8 +9,35 @@ block0(v0: f32, v1: f32):
     v3 = iconst.i32 1
     v4 = iconst.i32 0
     v5 = select v2, v3, v4
-    ; check: ucomiss
-    ; nextln: cmovnzl
-    ; nextln: cmovpl
     return v5
 }
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movl    $1, %eax
+;   ucomiss %xmm1, %xmm0
+;   cmovpl  const(0), %eax, %eax
+;   cmovnzl const(0), %eax, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+; 
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movl $1, %eax
+;   ucomiss %xmm1, %xmm0
+;   cmovpl 0xd(%rip), %eax
+;   cmovnel 6(%rip), %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+
diff --git a/cranelift/filetests/filetests/isa/x64/select.clif b/cranelift/filetests/filetests/isa/x64/select.clif
index 674a01e5f..0b7445ace 100644
--- a/cranelift/filetests/filetests/isa/x64/select.clif
+++ b/cranelift/filetests/filetests/isa/x64/select.clif
@@ -44,10 +44,10 @@ block0(v0: f32, v1: f32, v2: i64, v3: i64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   ucomiss %xmm0, %xmm1
+;   ucomiss %xmm1, %xmm0
 ;   movq    %rdi, %rax
-;   cmovnzq %rsi, %rax, %rax
 ;   cmovpq  %rsi, %rax, %rax
+;   cmovnzq %rsi, %rax, %rax
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -57,10 +57,10 @@ block0(v0: f32, v1: f32, v2: i64, v3: i64):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   ucomiss %xmm0, %xmm1
+;   ucomiss %xmm1, %xmm0
 ;   movq %rdi, %rax
-;   cmovneq %rsi, %rax
 ;   cmovpq %rsi, %rax
+;   cmovneq %rsi, %rax
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
diff --git a/cranelift/filetests/src/subtest.rs b/cranelift/filetests/src/subtest.rs
index b34292917..5b4776700 100644
--- a/cranelift/filetests/src/subtest.rs
+++ b/cranelift/filetests/src/subtest.rs
@@ -2,13 +2,16 @@
 
 use crate::runone::FileUpdate;
 use anyhow::Context as _;
+use anyhow::{bail, Result};
 use cranelift_codegen::ir::Function;
 use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::settings::{Flags, FlagsOrIsa};
 use cranelift_reader::{Comment, Details, TestFile};
 use filecheck::{Checker, CheckerBuilder, NO_VARIABLES};
 use log::info;
+use similar::TextDiff;
 use std::borrow::Cow;
+use std::env;
 
 /// Context for running a test on a single function.
 pub struct Context<'a> {
@@ -149,3 +152,74 @@ pub fn build_filechecker(context: &Context) -> anyhow::Result<Checker> {
     }
     Ok(builder.finish())
 }
+
+pub fn check_precise_output(actual: &[&str], context: &Context) -> Result<()> {
+    // Use the comments after the function to build the test expectation.
+    let expected = context
+        .details
+        .comments
+        .iter()
+        .filter(|c| !c.text.starts_with(";;"))
+        .map(|c| c.text.strip_prefix("; ").unwrap_or(c.text))
+        .collect::<Vec<_>>();
+
+    // If the expectation matches what we got, then there's nothing to do.
+    if actual == expected {
+        return Ok(());
+    }
+
+    // If we're supposed to automatically update the test, then do so here.
+    if env::var("CRANELIFT_TEST_BLESS").unwrap_or(String::new()) == "1" {
+        return update_test(&actual, context);
+    }
+
+    // Otherwise this test has failed, and we can print out as such.
+    bail!(
+        "compilation of function on line {} does not match\n\
+         the text expectation\n\
+         \n\
+         {}\n\
+         \n\
+         This test assertion can be automatically updated by setting the\n\
+         CRANELIFT_TEST_BLESS=1 environment variable when running this test.
+         ",
+        context.details.location.line_number,
+        TextDiff::from_slices(&expected, &actual)
+            .unified_diff()
+            .header("expected", "actual")
+    )
+}
+
+fn update_test(output: &[&str], context: &Context) -> Result<()> {
+    context
+        .file_update
+        .update_at(&context.details.location, |new_test, old_test| {
+            // blank newline after the function
+            new_test.push_str("\n");
+
+            // Splice in the test output
+            for output in output {
+                new_test.push_str("; ");
+                new_test.push_str(output);
+                new_test.push_str("\n");
+            }
+
+            // blank newline after test assertion
+            new_test.push_str("\n");
+
+            // Drop all remaining commented lines (presumably the old test expectation),
+            // but after we hit a real line then we push all remaining lines.
+            let mut in_next_function = false;
+            for line in old_test {
+                if !in_next_function
+                    && (line.trim().is_empty()
+                        || (line.starts_with(";") && !line.starts_with(";;")))
+                {
+                    continue;
+                }
+                in_next_function = true;
+                new_test.push_str(line);
+                new_test.push_str("\n");
+            }
+        })
+}
diff --git a/cranelift/filetests/src/test_compile.rs b/cranelift/filetests/src/test_compile.rs
index 94c975c14..934219086 100644
--- a/cranelift/filetests/src/test_compile.rs
+++ b/cranelift/filetests/src/test_compile.rs
@@ -2,17 +2,12 @@
 //!
 //! The `compile` test command runs each function through the full code generator pipeline
 
-use crate::subtest::{run_filecheck, Context, SubTest};
-use anyhow::{bail, Result};
+use crate::subtest::{check_precise_output, run_filecheck, Context, SubTest};
+use anyhow::Result;
 use cranelift_codegen::ir;
-use cranelift_codegen::ir::function::FunctionParameters;
-use cranelift_codegen::isa;
-use cranelift_codegen::CompiledCode;
 use cranelift_reader::{TestCommand, TestOption};
 use log::info;
-use similar::TextDiff;
 use std::borrow::Cow;
-use std::env;
 
 struct TestCompile {
     /// Flag indicating that the text expectation, comments after the function,
@@ -67,97 +62,20 @@ impl SubTest for TestCompile {
         info!("Generated {} bytes of code:\n{}", total_size, vcode);
 
         if self.precise_output {
-            check_precise_output(isa, &params, &compiled_code, context)
+            let cs = isa
+                .to_capstone()
+                .map_err(|e| anyhow::format_err!("{}", e))?;
+            let dis = compiled_code.disassemble(Some(&params), &cs)?;
+
+            let actual = Vec::from_iter(
+                std::iter::once("VCode:")
+                    .chain(compiled_code.vcode.as_ref().unwrap().lines())
+                    .chain(["", "Disassembled:"])
+                    .chain(dis.lines()),
+            );
+            check_precise_output(&actual, context)
         } else {
             run_filecheck(&vcode, context)
         }
     }
 }
-
-fn check_precise_output(
-    isa: &dyn isa::TargetIsa,
-    params: &FunctionParameters,
-    compiled_code: &CompiledCode,
-    context: &Context,
-) -> Result<()> {
-    let cs = isa
-        .to_capstone()
-        .map_err(|e| anyhow::format_err!("{}", e))?;
-    let dis = compiled_code.disassemble(Some(params), &cs)?;
-
-    let actual = Vec::from_iter(
-        std::iter::once("VCode:")
-            .chain(compiled_code.vcode.as_ref().unwrap().lines())
-            .chain(["", "Disassembled:"])
-            .chain(dis.lines()),
-    );
-
-    // Use the comments after the function to build the test expectation.
-    let expected = context
-        .details
-        .comments
-        .iter()
-        .filter(|c| !c.text.starts_with(";;"))
-        .map(|c| c.text.strip_prefix("; ").unwrap_or(c.text))
-        .collect::<Vec<_>>();
-
-    // If the expectation matches what we got, then there's nothing to do.
-    if actual == expected {
-        return Ok(());
-    }
-
-    // If we're supposed to automatically update the test, then do so here.
-    if env::var("CRANELIFT_TEST_BLESS").unwrap_or(String::new()) == "1" {
-        return update_test(&actual, context);
-    }
-
-    // Otherwise this test has failed, and we can print out as such.
-    bail!(
-        "compilation of function on line {} does not match\n\
-         the text expectation\n\
-         \n\
-         {}\n\
-         \n\
-         This test assertion can be automatically updated by setting the\n\
-         CRANELIFT_TEST_BLESS=1 environment variable when running this test.
-         ",
-        context.details.location.line_number,
-        TextDiff::from_slices(&expected, &actual)
-            .unified_diff()
-            .header("expected", "actual")
-    )
-}
-
-fn update_test(output: &[&str], context: &Context) -> Result<()> {
-    context
-        .file_update
-        .update_at(&context.details.location, |new_test, old_test| {
-            // blank newline after the function
-            new_test.push_str("\n");
-
-            // Splice in the test output
-            for output in output {
-                new_test.push_str("; ");
-                new_test.push_str(output);
-                new_test.push_str("\n");
-            }
-
-            // blank newline after test assertion
-            new_test.push_str("\n");
-
-            // Drop all remaining commented lines (presumably the old test expectation),
-            // but after we hit a real line then we push all remaining lines.
-            let mut in_next_function = false;
-            for line in old_test {
-                if !in_next_function
-                    && (line.trim().is_empty()
-                        || (line.starts_with(";") && !line.starts_with(";;")))
-                {
-                    continue;
-                }
-                in_next_function = true;
-                new_test.push_str(line);
-                new_test.push_str("\n");
-            }
-        })
-}
diff --git a/cranelift/filetests/src/test_optimize.rs b/cranelift/filetests/src/test_optimize.rs
index dfab6a1c4..fd76a8fe0 100644
--- a/cranelift/filetests/src/test_optimize.rs
+++ b/cranelift/filetests/src/test_optimize.rs
@@ -7,17 +7,32 @@
 //! Some legalization may be ISA-specific, so this requires an ISA
 //! (for now).
 
-use crate::subtest::{run_filecheck, Context, SubTest};
+use crate::subtest::{check_precise_output, run_filecheck, Context, SubTest};
 use anyhow::Result;
 use cranelift_codegen::ir;
-use cranelift_reader::TestCommand;
+use cranelift_reader::{TestCommand, TestOption};
 use std::borrow::Cow;
 
-struct TestOptimize;
+struct TestOptimize {
+    /// Flag indicating that the text expectation, comments after the function,
+    /// must be a precise 100% match on the compiled output of the function.
+    /// This test assertion is also automatically-update-able to allow tweaking
+    /// the code generator and easily updating all affected tests.
+    precise_output: bool,
+}
 
 pub fn subtest(parsed: &TestCommand) -> Result<Box<dyn SubTest>> {
     assert_eq!(parsed.command, "optimize");
-    Ok(Box::new(TestOptimize))
+    let mut test = TestOptimize {
+        precise_output: false,
+    };
+    for option in parsed.options.iter() {
+        match option {
+            TestOption::Flag("precise-output") => test.precise_output = true,
+            _ => anyhow::bail!("unknown option on {}", parsed),
+        }
+    }
+    Ok(Box::new(test))
 }
 
 impl SubTest for TestOptimize {
@@ -42,6 +57,12 @@ impl SubTest for TestOptimize {
             .map_err(|e| crate::pretty_anyhow_error(&comp_ctx.func, e))?;
 
         let clif = format!("{:?}", comp_ctx.func);
-        run_filecheck(&clif, context)
+
+        if self.precise_output {
+            let actual: Vec<_> = clif.lines().collect();
+            check_precise_output(&actual, context)
+        } else {
+            run_filecheck(&clif, context)
+        }
     }
 }