Repository: bytecodealliance/wasmtime
Pull request #8410 (2024-04-19 04:04:54)

Fix use-after-free in externref example
This fixes a typo in the `externref.c` example where a deallocated `wasmtime_val_t` was used by accident. Additionally this introduces scoping to prevent this from arising again.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index ea48ab4d5..37c6ede4d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -849,7 +849,7 @@ dependencies = [
  "serde_derive",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmtime-types",
  "wat",
 ]
@@ -2756,7 +2756,7 @@ dependencies = [
  "cargo_metadata",
  "heck",
  "wasmtime",
- "wit-component 0.204.0",
+ "wit-component 0.205.0",
 ]
 
 [[package]]
@@ -3092,7 +3092,7 @@ name = "verify-component-adapter"
 version = "21.0.0"
 dependencies = [
  "anyhow",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wat",
 ]
 
@@ -3184,7 +3184,7 @@ dependencies = [
  "byte-array-literals",
  "object 0.33.0",
  "wasi",
- "wasm-encoder 0.204.0",
+ "wasm-encoder 0.205.0",
  "wit-bindgen",
 ]
 
@@ -3253,9 +3253,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "500cbde9b4d8dfc0335ec729d226dbf083e51e47501ac71e6addaed10ccb0a51"
+checksum = "90e95b3563d164f33c1cfb0a7efbd5940c37710019be10cd09f800fdec8b0e5c"
 dependencies = [
  "leb128",
 ]
@@ -3278,9 +3278,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-metadata"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f33b61754be27af5abf0fda890badb7c3265f7b634077157b4214704303ebbcc"
+checksum = "e9855ad6dd4d099fa8505f01fb0b84c7e3efd5f555207329e3ad938d5f394fe7"
 dependencies = [
  "anyhow",
  "indexmap 2.0.0",
@@ -3288,36 +3288,36 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "spdx",
- "wasm-encoder 0.204.0",
- "wasmparser 0.204.0",
+ "wasm-encoder 0.205.0",
+ "wasmparser 0.205.0",
 ]
 
 [[package]]
 name = "wasm-mutate"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34d24ec979ae72a27f3770a7db426e7f2d459e67ecf26983ca727675e4956037"
+checksum = "d92842509e0cc163a0f8f4a54e38ec180e18594b9ed3999d0a05108e70d25cb3"
 dependencies = [
  "egg",
  "log",
  "rand",
  "thiserror",
- "wasm-encoder 0.204.0",
- "wasmparser 0.204.0",
+ "wasm-encoder 0.205.0",
+ "wasmparser 0.205.0",
 ]
 
 [[package]]
 name = "wasm-smith"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1fe1d435b8a14ebf05c2669cf76d1ca1cef6b632320c8e0b0e703ff0259a328"
+checksum = "1218f393276f7a13f6c54467434633144b46c33ecbc3cbafdc938033f0315d1a"
 dependencies = [
  "anyhow",
  "arbitrary",
  "flagset",
  "indexmap 2.0.0",
  "leb128",
- "wasm-encoder 0.204.0",
+ "wasm-encoder 0.205.0",
 ]
 
 [[package]]
@@ -3373,9 +3373,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1239d539d9b92489cf729d40df694a62b09f5159f2ab058f4de15d4f820d6585"
+checksum = "1d457bb52804242e09d55a306e53ddbc65d1d29ed83db6a4eea3ed412ee0cfdf"
 dependencies = [
  "bitflags 2.4.1",
  "indexmap 2.0.0",
@@ -3393,12 +3393,12 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce3e6a3111855bf59cb6a16a95e217c59eff1d30d9f09483039b81b0739c3128"
+checksum = "edcd1e00bc348d4b1c0abe913d86f4a89377cbd5c1c704d4eca5cf3492a27da8"
 dependencies = [
  "anyhow",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
 ]
 
 [[package]]
@@ -3430,8 +3430,8 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "wasi-common",
- "wasm-encoder 0.204.0",
- "wasmparser 0.204.0",
+ "wasm-encoder 0.205.0",
+ "wasmparser 0.205.0",
  "wasmtime-cache",
  "wasmtime-component-macro",
  "wasmtime-component-util",
@@ -3571,7 +3571,7 @@ dependencies = [
  "tracing",
  "walkdir",
  "wasi-common",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmtime",
  "wasmtime-cache",
  "wasmtime-cli-flags",
@@ -3585,10 +3585,10 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 204.0.0",
+ "wast 205.0.0",
  "wat",
  "windows-sys 0.52.0",
- "wit-component 0.204.0",
+ "wit-component 0.205.0",
 ]
 
 [[package]]
@@ -3617,7 +3617,7 @@ dependencies = [
  "wasmtime",
  "wasmtime-component-util",
  "wasmtime-wit-bindgen",
- "wit-parser 0.204.0",
+ "wit-parser 0.205.0",
 ]
 
 [[package]]
@@ -3641,7 +3641,7 @@ dependencies = [
  "object 0.33.0",
  "target-lexicon",
  "thiserror",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmtime-environ",
  "wasmtime-versioned-export-macros",
 ]
@@ -3665,8 +3665,8 @@ dependencies = [
  "serde_derive",
  "target-lexicon",
  "thiserror",
- "wasm-encoder 0.204.0",
- "wasmparser 0.204.0",
+ "wasm-encoder 0.205.0",
+ "wasmparser 0.205.0",
  "wasmprinter",
  "wasmtime-component-util",
  "wasmtime-types",
@@ -3681,7 +3681,7 @@ dependencies = [
  "component-fuzz-util",
  "env_logger",
  "libfuzzer-sys",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmprinter",
  "wasmtime-environ",
  "wat",
@@ -3738,7 +3738,7 @@ dependencies = [
  "rand",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmtime",
  "wasmtime-fuzzing",
 ]
@@ -3758,12 +3758,12 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "v8",
- "wasm-encoder 0.204.0",
+ "wasm-encoder 0.205.0",
  "wasm-mutate",
  "wasm-smith",
  "wasm-spec-interpreter",
  "wasmi",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmprinter",
  "wasmtime",
  "wasmtime-wast",
@@ -3810,7 +3810,7 @@ dependencies = [
  "rand",
  "rustix",
  "sptr",
- "wasm-encoder 0.204.0",
+ "wasm-encoder 0.205.0",
  "wasmtime-asm-macros",
  "wasmtime-environ",
  "wasmtime-fiber",
@@ -3833,7 +3833,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "thiserror",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
 ]
 
 [[package]]
@@ -3940,7 +3940,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 204.0.0",
+ "wast 205.0.0",
 ]
 
 [[package]]
@@ -3952,7 +3952,7 @@ dependencies = [
  "gimli",
  "object 0.33.0",
  "target-lexicon",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmtime-cranelift",
  "wasmtime-environ",
  "winch-codegen",
@@ -3965,7 +3965,7 @@ dependencies = [
  "anyhow",
  "heck",
  "indexmap 2.0.0",
- "wit-parser 0.204.0",
+ "wit-parser 0.205.0",
 ]
 
 [[package]]
@@ -3983,24 +3983,24 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "204.0.0"
+version = "205.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0e3de19692b3d4c2fa13775271a751935decf530ae59c408c9f0b510b4ead62"
+checksum = "441a6a195b3b5245e26d450bbcc91366c6b652382a22f63cbe3c73240e13b2bb"
 dependencies = [
  "bumpalo",
  "leb128",
  "memchr",
  "unicode-width",
- "wasm-encoder 0.204.0",
+ "wasm-encoder 0.205.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.204.0"
+version = "1.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4280322d523214024d03bc05e25bdda6088d5229d9515aecd78c5914b1f3e734"
+checksum = "19832624d606e7c6bf3cd4caa73578ecec5eac30c768269256d19c79900beb18"
 dependencies = [
- "wast 204.0.0",
+ "wast 205.0.0",
 ]
 
 [[package]]
@@ -4130,7 +4130,7 @@ dependencies = [
  "regalloc2",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
  "wasmtime-cranelift",
  "wasmtime-environ",
 ]
@@ -4381,9 +4381,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "657fab6fd5f9ad3e1b7fd65a76f06ff25cac7f4fd8f885715bed4147095a6c38"
+checksum = "74841e17b2c2bfbd8ca8c45190ef85dff1c5e8659f0e2d164802ffc87dfb18c3"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -4392,10 +4392,10 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.204.0",
- "wasm-metadata 0.204.0",
- "wasmparser 0.204.0",
- "wit-parser 0.204.0",
+ "wasm-encoder 0.205.0",
+ "wasm-metadata 0.205.0",
+ "wasmparser 0.205.0",
+ "wit-parser 0.205.0",
 ]
 
 [[package]]
@@ -4418,9 +4418,9 @@ dependencies = [
 
 [[package]]
 name = "wit-parser"
-version = "0.204.0"
+version = "0.205.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdc20f9284017574e942347e953e82fb3a0dccdfafa3beea7840b0bcbfa4fe00"
+checksum = "a3db34c7688c161ed7bd1b2f8055dca9fb2c15201db58754e9c48a0805f32e5f"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -4431,7 +4431,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.204.0",
+ "wasmparser 0.205.0",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index ab812cbc6..f137a2e26 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -234,15 +234,15 @@ rustix = "0.38.31"
 wit-bindgen = { version = "0.22.0", default-features = false }
 
 # wasm-tools family:
-wasmparser = "0.204.0"
-wat = "1.204.0"
-wast = "204.0.0"
-wasmprinter = "0.204.0"
-wasm-encoder = "0.204.0"
-wasm-smith = "0.204.0"
-wasm-mutate = "0.204.0"
-wit-parser = "0.204.0"
-wit-component = "0.204.0"
+wasmparser = "0.205.0"
+wat = "1.205.0"
+wast = "205.0.0"
+wasmprinter = "0.205.0"
+wasm-encoder = "0.205.0"
+wasm-smith = "0.205.0"
+wasm-mutate = "0.205.0"
+wit-parser = "0.205.0"
+wit-component = "0.205.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
diff --git a/RELEASES.md b/RELEASES.md
index 84af9edc6..5b232971f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -139,6 +139,22 @@ Unreleased.
 
 --------------------------------------------------------------------------------
 
+## 19.0.2
+
+Released 2024-04-11.
+
+* Fix a panic when compiling invalid components.
+  [#8323](https://github.com/bytecodealliance/wasmtime/issues/8323)
+
+* Fix `bindgen!` with `trappable_error_type` using unversioned/versioned
+  packages.
+  [#8305](https://github.com/bytecodealliance/wasmtime/pull/8305)
+
+* cranelift: Include clobbers and outgoing args in stack limit.
+  [#8301](https://github.com/bytecodealliance/wasmtime/pull/8301)
+
+--------------------------------------------------------------------------------
+
 ## 19.0.1
 
 Released 2024-04-02.
@@ -248,6 +264,24 @@ Released 2024-03-20
 
 --------------------------------------------------------------------------------
 
+## 18.0.4
+
+Released 2024-04-11
+
+### Fixed
+
+* Fix `bindgen!` with `trappable_error_type` using unversioned/versioned
+  packages.
+  [#8305](https://github.com/bytecodealliance/wasmtime/pull/8305)
+
+* cranelift: Include clobbers and outgoing args in stack limit.
+  [#8301](https://github.com/bytecodealliance/wasmtime/pull/8301)
+
+* Fix a panic when compiling invalid components.
+  [#8323](https://github.com/bytecodealliance/wasmtime/issues/8323)
+
+--------------------------------------------------------------------------------
+
 ## 18.0.3
 
 Released 2024-03-12
@@ -333,6 +367,20 @@ Released 2024-02-20
 
 --------------------------------------------------------------------------------
 
+## 17.0.3
+
+Released 2024-04-11
+
+### Fixed
+
+* cranelift: Include clobbers and outgoing args in stack limit.
+  [#8301](https://github.com/bytecodealliance/wasmtime/pull/8301)
+
+* Fix a panic when compiling invalid components.
+  [#8323](https://github.com/bytecodealliance/wasmtime/issues/8323)
+
+--------------------------------------------------------------------------------
+
 ## 17.0.2
 
 Released 2024-02-28
diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs
index ea2672328..0abb95131 100644
--- a/cranelift/codegen/src/isa/x64/abi.rs
+++ b/cranelift/codegen/src/isa/x64/abi.rs
@@ -1046,7 +1046,7 @@ impl X64CallSite {
                     distance: RelocDistance::Far,
                 });
                 ctx.emit(Inst::ReturnCallUnknown {
-                    callee: tmp2.to_writable_reg().into(),
+                    callee: tmp2.to_reg().to_reg(),
                     info,
                 });
             }
diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle
index 84c498808..2020be69e 100644
--- a/cranelift/codegen/src/isa/x64/inst.isle
+++ b/cranelift/codegen/src/isa/x64/inst.isle
@@ -367,6 +367,10 @@
                     (dst WritableGpr)
                     (dst_size OperandSize))
 
+       ;; Float comparisons/tests: cmp (b w l q) (reg addr imm) reg.
+       (XmmCmpRmRVex (op AvxOpcode)
+                     (src1 Xmm)
+                     (src2 XmmMem))
 
        ;; XMM (scalar or vector) binary op that relies on the EVEX
        ;; prefix. Takes two inputs.
@@ -541,7 +545,7 @@
                         (info BoxReturnCallInfo))
 
        ;; Tail call to an indirect destination.
-       (ReturnCallUnknown (callee RegMem)
+       (ReturnCallUnknown (callee Reg)
                           (info BoxReturnCallInfo))
 
        ;; A pseudo-instruction that captures register arguments in vregs.
@@ -1413,6 +1417,9 @@
             Vsqrtsd
             Vroundss
             Vroundsd
+            Vucomiss
+            Vucomisd
+            Vptest
           ))
 
 (type Avx512Opcode
@@ -2817,14 +2824,24 @@
       (ProducesFlags.ProducesFlagsSideEffect
        (MInst.XmmCmpRmR opcode src1 src2)))
 
+;; Helper for creating `MInst.XmmCmpRmRVex` instructions.
+(decl xmm_cmp_rm_r_vex (AvxOpcode Xmm XmmMem) ProducesFlags)
+(rule (xmm_cmp_rm_r_vex opcode src1 src2)
+      (ProducesFlags.ProducesFlagsSideEffect
+       (MInst.XmmCmpRmRVex opcode src1 src2)))
+
 ;; Helper for creating floating-point comparison instructions (`UCOMIS[S|D]`).
-(decl x64_ucomis (Value Value) ProducesFlags)
-(rule (x64_ucomis src1 @ (value_type $F32) src2)
-      ;; N.B.: cmp can be generated more than once, so cannot do a
-      ;; load-op merge. So `put_in_xmm` for src1, not `put_in_xmm_mem`.
-      (xmm_cmp_rm_r (SseOpcode.Ucomiss) (put_in_xmm src1) (put_in_xmm src2)))
-(rule (x64_ucomis src1 @ (value_type $F64) src2)
-      (xmm_cmp_rm_r (SseOpcode.Ucomisd) (put_in_xmm src1) (put_in_xmm src2)))
+(decl x64_ucomis (Type Xmm XmmMem) ProducesFlags)
+(rule (x64_ucomis $F32 src1 src2)
+      (xmm_cmp_rm_r (SseOpcode.Ucomiss) src1 src2))
+(rule (x64_ucomis $F64 src1 src2)
+      (xmm_cmp_rm_r (SseOpcode.Ucomisd) src1 src2))
+(rule 1 (x64_ucomis $F32 src1 src2)
+        (if-let $true (use_avx))
+        (xmm_cmp_rm_r_vex (AvxOpcode.Vucomiss) src1 src2))
+(rule 1 (x64_ucomis $F64 src1 src2)
+        (if-let $true (use_avx))
+        (xmm_cmp_rm_r_vex (AvxOpcode.Vucomisd) src1 src2))
 
 ;; Helper for creating `test` instructions.
 (decl x64_test (OperandSize GprMemImm Gpr) ProducesFlags)
@@ -2835,6 +2852,9 @@
 (decl x64_ptest (Xmm XmmMem) ProducesFlags)
 (rule (x64_ptest src1 src2)
       (xmm_cmp_rm_r (SseOpcode.Ptest) src1 src2))
+(rule 1 (x64_ptest src1 src2)
+        (if-let $true (use_avx))
+        (xmm_cmp_rm_r_vex (AvxOpcode.Vptest) src1 src2))
 
 ;; Helper for creating `cmove` instructions. Note that these instructions do not
 ;; always result in a single emitted x86 instruction; e.g., XmmCmove uses jumps
@@ -4881,46 +4901,46 @@
 ;;  - equal assigns        Z = 1, P = 0, C = 0
 (decl emit_fcmp (FloatCC Value Value) FcmpCondResult)
 
-(rule (emit_fcmp (FloatCC.Equal) a @ (value_type (ty_scalar_float _)) b)
-      (FcmpCondResult.AndCondition (x64_ucomis a b) (CC.NP) (CC.Z)))
+(rule (emit_fcmp (FloatCC.Equal) a @ (value_type (ty_scalar_float ty)) b)
+      (FcmpCondResult.AndCondition (x64_ucomis ty a b) (CC.NP) (CC.Z)))
 
-(rule (emit_fcmp (FloatCC.NotEqual) a @ (value_type (ty_scalar_float _)) b)
-      (FcmpCondResult.OrCondition (x64_ucomis a b) (CC.P) (CC.NZ)))
+(rule (emit_fcmp (FloatCC.NotEqual) a @ (value_type (ty_scalar_float ty)) b)
+      (FcmpCondResult.OrCondition (x64_ucomis ty a b) (CC.P) (CC.NZ)))
 
 ;; Some scalar lowerings correspond to one condition code.
 
 (rule (emit_fcmp (FloatCC.Ordered) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.NP)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.NP)))
 (rule (emit_fcmp (FloatCC.Unordered) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.P)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.P)))
 (rule (emit_fcmp (FloatCC.OrderedNotEqual) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.NZ)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.NZ)))
 (rule (emit_fcmp (FloatCC.UnorderedOrEqual) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.Z)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.Z)))
 (rule (emit_fcmp (FloatCC.GreaterThan) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.NBE)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.NBE)))
 (rule (emit_fcmp (FloatCC.GreaterThanOrEqual) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.NB)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.NB)))
 (rule (emit_fcmp (FloatCC.UnorderedOrLessThan) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.B)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.B)))
 (rule (emit_fcmp (FloatCC.UnorderedOrLessThanOrEqual) a @ (value_type (ty_scalar_float ty)) b)
-      (FcmpCondResult.Condition (x64_ucomis a b) (CC.BE)))
+      (FcmpCondResult.Condition (x64_ucomis ty a b) (CC.BE)))
 
 ;; Other scalar lowerings are made possible by flipping the operands and
 ;; reversing the condition code.
 
 (rule (emit_fcmp (FloatCC.LessThan) a @ (value_type (ty_scalar_float ty)) b)
       ;; Same flags as `GreaterThan`.
-      (FcmpCondResult.Condition (x64_ucomis b a) (CC.NBE)))
+      (FcmpCondResult.Condition (x64_ucomis ty b a) (CC.NBE)))
 (rule (emit_fcmp (FloatCC.LessThanOrEqual) a @ (value_type (ty_scalar_float ty)) b)
       ;; Same flags as `GreaterThanOrEqual`.
-      (FcmpCondResult.Condition (x64_ucomis b a) (CC.NB)))
+      (FcmpCondResult.Condition (x64_ucomis ty b a) (CC.NB)))
 (rule (emit_fcmp (FloatCC.UnorderedOrGreaterThan) a @ (value_type (ty_scalar_float ty)) b)
       ;; Same flags as `UnorderedOrLessThan`.
-      (FcmpCondResult.Condition (x64_ucomis b a) (CC.B)))
+      (FcmpCondResult.Condition (x64_ucomis ty b a) (CC.B)))
 (rule (emit_fcmp (FloatCC.UnorderedOrGreaterThanOrEqual) a @ (value_type (ty_scalar_float ty)) b)
       ;; Same flags as `UnorderedOrLessThanOrEqual`.
-      (FcmpCondResult.Condition (x64_ucomis b a) (CC.BE)))
+      (FcmpCondResult.Condition (x64_ucomis ty b a) (CC.BE)))
 
 ;;;; Type Guards ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
diff --git a/cranelift/codegen/src/isa/x64/inst/args.rs b/cranelift/codegen/src/isa/x64/inst/args.rs
index 992e322b4..caf21dbbb 100644
--- a/cranelift/codegen/src/isa/x64/inst/args.rs
+++ b/cranelift/codegen/src/isa/x64/inst/args.rs
@@ -1814,7 +1814,10 @@ impl AvxOpcode {
             | AvxOpcode::Vsqrtsd
             | AvxOpcode::Vroundss
             | AvxOpcode::Vroundsd
-            | AvxOpcode::Vunpcklpd => {
+            | AvxOpcode::Vunpcklpd
+            | AvxOpcode::Vptest
+            | AvxOpcode::Vucomiss
+            | AvxOpcode::Vucomisd => {
                 smallvec![InstructionSet::AVX]
             }
 
diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs
index 481362b9e..cd43516a4 100644
--- a/cranelift/codegen/src/isa/x64/inst/emit.rs
+++ b/cranelift/codegen/src/isa/x64/inst/emit.rs
@@ -1647,11 +1647,14 @@ pub(crate) fn emit(
             callee,
             info: call_info,
         } => {
-            let callee = callee.with_allocs(allocs);
+            let callee = allocs.next(*callee);
 
             emit_return_call_common_sequence(allocs, sink, info, state, &call_info);
 
-            Inst::JmpUnknown { target: callee }.emit(&[], sink, info, state);
+            Inst::JmpUnknown {
+                target: RegMem::reg(callee),
+            }
+            .emit(&[], sink, info, state);
             sink.add_call_site(ir::Opcode::ReturnCallIndirect);
         }
 
@@ -2855,6 +2858,32 @@ pub(crate) fn emit(
                 .encode(sink);
         }
 
+        Inst::XmmCmpRmRVex { op, src1, src2 } => {
+            let src1 = allocs.next(src1.to_reg());
+            let src2 = match src2.clone().to_reg_mem().with_allocs(allocs) {
+                RegMem::Reg { reg } => {
+                    RegisterOrAmode::Register(reg.to_real_reg().unwrap().hw_enc().into())
+                }
+                RegMem::Mem { addr } => RegisterOrAmode::Amode(addr.finalize(state, sink)),
+            };
+
+            let (prefix, map, opcode) = match op {
+                AvxOpcode::Vucomiss => (LegacyPrefixes::None, OpcodeMap::_0F, 0x2E),
+                AvxOpcode::Vucomisd => (LegacyPrefixes::_66, OpcodeMap::_0F, 0x2E),
+                AvxOpcode::Vptest => (LegacyPrefixes::_66, OpcodeMap::_0F38, 0x17),
+                _ => unimplemented!("Opcode {:?} not implemented", op),
+            };
+
+            VexInstruction::new()
+                .length(VexVectorLength::V128)
+                .prefix(prefix)
+                .map(map)
+                .opcode(opcode)
+                .rm(src2)
+                .reg(src1.to_real_reg().unwrap().hw_enc())
+                .encode(sink);
+        }
+
         Inst::XmmRmREvex {
             op,
             src1,
diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs
index 55407ee86..37ac3398b 100644
--- a/cranelift/codegen/src/isa/x64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/x64/inst/mod.rs
@@ -191,7 +191,8 @@ impl Inst {
             | Inst::XmmToGprImmVex { op, .. }
             | Inst::XmmToGprVex { op, .. }
             | Inst::GprToXmmVex { op, .. }
-            | Inst::CvtIntToFloatVex { op, .. } => op.available_from(),
+            | Inst::CvtIntToFloatVex { op, .. }
+            | Inst::XmmCmpRmRVex { op, .. } => op.available_from(),
         }
     }
 }
@@ -1351,6 +1352,12 @@ impl PrettyPrint for Inst {
                 format!("{op} {src1}, {src2}, {dst}")
             }
 
+            Inst::XmmCmpRmRVex { op, src1, src2 } => {
+                let src1 = pretty_print_reg(src1.to_reg(), 8, allocs);
+                let src2 = src2.pretty_print(8, allocs);
+                format!("{} {src2}, {src1}", ljustify(op.to_string()))
+            }
+
             Inst::CvtUint64ToFloatSeq {
                 src,
                 dst,
@@ -1690,7 +1697,7 @@ impl PrettyPrint for Inst {
                     new_stack_arg_size,
                     tmp,
                 } = &**info;
-                let callee = callee.pretty_print(8, allocs);
+                let callee = pretty_print_reg(*callee, 8, allocs);
                 let tmp = pretty_print_reg(tmp.to_reg().to_reg(), 8, allocs);
                 let mut s =
                     format!("return_call_unknown {callee} ({new_stack_arg_size}) tmp={tmp}");
@@ -2159,6 +2166,10 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
             collector.reg_use(src1.to_reg());
             src2.get_operands(collector);
         }
+        Inst::XmmCmpRmRVex { src1, src2, .. } => {
+            collector.reg_use(src1.to_reg());
+            src2.get_operands(collector);
+        }
         Inst::Imm { dst, .. } => {
             collector.reg_def(dst.to_writable_reg());
         }
@@ -2336,8 +2347,9 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
             match dest {
                 RegMem::Reg { reg } if info.callee_conv == CallConv::Winch => {
                     // TODO(https://github.com/bytecodealliance/regalloc2/issues/145):
-                    // This shouldn't be a fixed register constraint.
-                    collector.reg_fixed_use(*reg, regs::r15())
+                    // This shouldn't be a fixed register constraint. r10 is caller-saved, so this
+                    // should be safe to use.
+                    collector.reg_fixed_use(*reg, regs::r10())
                 }
                 _ => dest.get_operands(collector),
             }
@@ -2352,7 +2364,7 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
 
         Inst::ReturnCallKnown { callee, info } => {
             let ReturnCallInfo { uses, tmp, .. } = &**info;
-            collector.reg_early_def(tmp.to_writable_reg());
+            collector.reg_fixed_def(tmp.to_writable_reg(), regs::r11());
             // Same as in the `Inst::CallKnown` branch.
             debug_assert_ne!(*callee, ExternalName::LibCall(LibCall::Probestack));
             for u in uses {
@@ -2362,8 +2374,15 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
 
         Inst::ReturnCallUnknown { callee, info } => {
             let ReturnCallInfo { uses, tmp, .. } = &**info;
-            callee.get_operands(collector);
-            collector.reg_early_def(tmp.to_writable_reg());
+
+            // TODO(https://github.com/bytecodealliance/regalloc2/issues/145):
+            // This shouldn't be a fixed register constraint, but it's not clear how to
+            // pick a register that won't be clobbered by the callee-save restore code
+            // emitted with a return_call_indirect. r10 is caller-saved, so this should be
+            // safe to use.
+            collector.reg_fixed_use(*callee, regs::r10());
+
+            collector.reg_fixed_def(tmp.to_writable_reg(), regs::r11());
             for u in uses {
                 collector.reg_fixed_use(u.vreg, u.preg);
             }
diff --git a/cranelift/codegen/src/isa/x64/pcc.rs b/cranelift/codegen/src/isa/x64/pcc.rs
index e28cf05d1..c0c007f01 100644
--- a/cranelift/codegen/src/isa/x64/pcc.rs
+++ b/cranelift/codegen/src/isa/x64/pcc.rs
@@ -813,6 +813,18 @@ pub(crate) fn check(
             ensure_no_fact(vcode, dst.to_reg())
         }
 
+        Inst::XmmCmpRmRVex {
+            ref src1, ref src2, ..
+        } => {
+            match <&RegMem>::from(src2) {
+                RegMem::Mem { ref addr } => {
+                    check_load(ctx, None, addr, vcode, F32, 32)?;
+                }
+                RegMem::Reg { .. } => {}
+            }
+            ensure_no_fact(vcode, src1.to_reg())
+        }
+
         Inst::CallKnown { .. }
         | Inst::ReturnCallKnown { .. }
         | Inst::JmpKnown { .. }
@@ -826,10 +838,9 @@ pub(crate) fn check(
         | Inst::Ud2 { .. } => Ok(()),
         Inst::Rets { .. } => Ok(()),
 
+        Inst::ReturnCallUnknown { .. } => Ok(()),
+
         Inst::CallUnknown { ref dest, .. }
-        | Inst::ReturnCallUnknown {
-            callee: ref dest, ..
-        }
         | Inst::JmpUnknown {
             target: ref dest, ..
         } => match <&RegMem>::from(dest) {
diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs
index 2e32e0e70..502279f24 100644
--- a/cranelift/wasm/src/code_translator.rs
+++ b/cranelift/wasm/src/code_translator.rs
@@ -2543,6 +2543,10 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::StructGet { .. } => {
             unimplemented!("GC operators not yet implemented")
         }
+
+        Operator::GlobalAtomicGet { .. } | Operator::GlobalAtomicSet { .. } => {
+            unimplemented!("shared-everything-threads not yet implemented")
+        }
     };
     Ok(())
 }
diff --git a/examples/externref.c b/examples/externref.c
index d29ea2b97..79fa82841 100644
--- a/examples/externref.c
+++ b/examples/externref.c
@@ -101,76 +101,82 @@ int main() {
   void *data = wasmtime_externref_data(context, externref);
   assert(strcmp((char *)data, "Hello, World!") == 0);
 
-  printf("Touching `externref` table...\n");
-
   wasmtime_extern_t item;
-
-  // Lookup the `table` export.
-  ok = wasmtime_instance_export_get(context, &instance, "table",
-                                    strlen("table"), &item);
-  assert(ok);
-  assert(item.kind == WASMTIME_EXTERN_TABLE);
-
-  // Set `table[3]` to our `externref`.
   wasmtime_val_t externref_val;
   externref_val.kind = WASMTIME_EXTERNREF;
   externref_val.of.externref = externref;
-  error = wasmtime_table_set(context, &item.of.table, 3, &externref_val);
-  if (error != NULL)
-    exit_with_error("failed to set table", error, NULL);
 
-  // `table[3]` should now be our `externref`.
-  wasmtime_val_t elem;
-  ok = wasmtime_table_get(context, &item.of.table, 3, &elem);
-  assert(ok);
-  assert(elem.kind == WASMTIME_EXTERNREF);
-  assert(strcmp((char *)wasmtime_externref_data(context, elem.of.externref),
-                "Hello, World!") == 0);
-  wasmtime_val_delete(context, &elem);
+  // Lookup the `table` export.
+  printf("Touching `externref` table...\n");
+  {
+    ok = wasmtime_instance_export_get(context, &instance, "table",
+                                      strlen("table"), &item);
+    assert(ok);
+    assert(item.kind == WASMTIME_EXTERN_TABLE);
+
+    // Set `table[3]` to our `externref`.
+    error = wasmtime_table_set(context, &item.of.table, 3, &externref_val);
+    if (error != NULL)
+      exit_with_error("failed to set table", error, NULL);
+
+    // `table[3]` should now be our `externref`.
+    wasmtime_val_t elem;
+    ok = wasmtime_table_get(context, &item.of.table, 3, &elem);
+    assert(ok);
+    assert(elem.kind == WASMTIME_EXTERNREF);
+    assert(strcmp((char *)wasmtime_externref_data(context, elem.of.externref),
+                  "Hello, World!") == 0);
+    wasmtime_val_delete(context, &elem);
+  }
 
   printf("Touching `externref` global...\n");
 
   // Lookup the `global` export.
-  ok = wasmtime_instance_export_get(context, &instance, "global",
-                                    strlen("global"), &item);
-  assert(ok);
-  assert(item.kind == WASMTIME_EXTERN_GLOBAL);
-
-  // Set the global to our `externref`.
-  error = wasmtime_global_set(context, &item.of.global, &externref_val);
-  if (error != NULL)
-    exit_with_error("failed to set global", error, NULL);
-
-  // Get the global, and it should return our `externref` again.
-  wasmtime_val_t global_val;
-  wasmtime_global_get(context, &item.of.global, &global_val);
-  assert(global_val.kind == WASMTIME_EXTERNREF);
-  assert(strcmp((char *)wasmtime_externref_data(context, elem.of.externref),
-                "Hello, World!") == 0);
-  wasmtime_val_delete(context, &global_val);
+  {
+    ok = wasmtime_instance_export_get(context, &instance, "global",
+                                      strlen("global"), &item);
+    assert(ok);
+    assert(item.kind == WASMTIME_EXTERN_GLOBAL);
+
+    // Set the global to our `externref`.
+    error = wasmtime_global_set(context, &item.of.global, &externref_val);
+    if (error != NULL)
+      exit_with_error("failed to set global", error, NULL);
+
+    // Get the global, and it should return our `externref` again.
+    wasmtime_val_t global_val;
+    wasmtime_global_get(context, &item.of.global, &global_val);
+    assert(global_val.kind == WASMTIME_EXTERNREF);
+    assert(strcmp((char *)wasmtime_externref_data(context,
+                                                  global_val.of.externref),
+                  "Hello, World!") == 0);
+    wasmtime_val_delete(context, &global_val);
+  }
 
   printf("Calling `externref` func...\n");
 
   // Lookup the `func` export.
-  ok = wasmtime_instance_export_get(context, &instance, "func", strlen("func"),
-                                    &item);
-  assert(ok);
-  assert(item.kind == WASMTIME_EXTERN_FUNC);
-
-  // And call it!
-  wasmtime_val_t results[1];
-  error = wasmtime_func_call(context, &item.of.func, &externref_val, 1, results,
-                             1, &trap);
-  if (error != NULL || trap != NULL)
-    exit_with_error("failed to call function", error, trap);
-
-  // `func` returns the same reference we gave it, so `results[0]` should be our
-  // `externref`.
-  assert(results[0].kind == WASMTIME_EXTERNREF);
-  assert(
-      strcmp((char *)wasmtime_externref_data(context, results[0].of.externref),
-             "Hello, World!") == 0);
-  wasmtime_val_delete(context, &results[0]);
+  {
+    ok = wasmtime_instance_export_get(context, &instance, "func",
+                                      strlen("func"), &item);
+    assert(ok);
+    assert(item.kind == WASMTIME_EXTERN_FUNC);
+
+    // And call it!
+    wasmtime_val_t results[1];
+    error = wasmtime_func_call(context, &item.of.func, &externref_val, 1,
+                               results, 1, &trap);
+    if (error != NULL || trap != NULL)
+      exit_with_error("failed to call function", error, trap);
+
+    // `func` returns the same reference we gave it, so `results[0]` should be
+    // our `externref`.
+    assert(results[0].kind == WASMTIME_EXTERNREF);
+    assert(strcmp((char *)wasmtime_externref_data(context,
+                                                  results[0].of.externref),
+                  "Hello, World!") == 0);
+    wasmtime_val_delete(context, &results[0]);
+  }
   wasmtime_val_delete(context, &externref_val);
 
   // We can GC any now-unused references to our externref that the store is
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 263bfd6e6..61311c79f 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -1190,6 +1190,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-encoder]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-metadata]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1214,6 +1220,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-metadata]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-mutate]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1238,6 +1250,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-mutate]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-smith]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1262,6 +1280,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-smith]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmparser]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1286,6 +1310,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasmparser]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmprinter]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1310,6 +1340,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasmprinter]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmtime]]
 version = "18.0.2"
 when = "2024-02-28"
@@ -1622,6 +1658,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wast]]
+version = "205.0.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wat]]
 version = "1.201.0"
 when = "2024-02-27"
@@ -1646,6 +1688,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wat]]
+version = "1.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wiggle]]
 version = "18.0.2"
 when = "2024-02-28"
@@ -1940,6 +1988,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wit-component]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wit-parser]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1964,6 +2018,12 @@ when = "2024-04-16"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wit-parser]]
+version = "0.205.0"
+when = "2024-04-18"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.witx]]
 version = "0.9.1"
 when = "2021-06-22"


Test patch:
diff --git a/cranelift/filetests/filetests/isa/x64/branches.clif b/cranelift/filetests/filetests/isa/x64/branches.clif
index 57ab4de3f..fbbd876b8 100644
--- a/cranelift/filetests/filetests/isa/x64/branches.clif
+++ b/cranelift/filetests/filetests/isa/x64/branches.clif
@@ -630,15 +630,13 @@ block202:
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   movl    $1112539136, %eax
-;   movd    %eax, %xmm4
-;   ucomiss %xmm4, %xmm0
+;   ucomiss const(1), %xmm0
 ;   jp      label2
 ;   jnz     label2; j label1
 ; block1:
 ;   jmp     label5
 ; block2:
-;   ucomiss %xmm4, %xmm0
+;   ucomiss const(0), %xmm0
 ;   jnp     label4; j label3
 ; block3:
 ;   jmp     label5
@@ -654,20 +652,36 @@ block202:
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movl $0x42500000, %eax
-;   movd %eax, %xmm4
-;   ucomiss %xmm4, %xmm0
-;   jp 0x1c
-;   je 0x27
-; block2: ; offset 0x1c
-;   ucomiss %xmm4, %xmm0
-;   jp 0x27
-; block3: ; offset 0x25
+;   ucomiss 0x25(%rip), %xmm0
+;   jp 0x17
+;   je 0x26
+; block2: ; offset 0x17
+;   ucomiss 0x22(%rip), %xmm0
+;   jp 0x26
+; block3: ; offset 0x24
 ;   ud2 ; trap: heap_oob
-; block4: ; offset 0x27
+; block4: ; offset 0x26
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %dl, 0x42(%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   pushq %rax
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
+;   addb %al, (%rax)
 
 function %br_i8_icmp(i32, i32) -> i32 {
 block0(v0: i32, v1: i32):
diff --git a/cranelift/filetests/filetests/isa/x64/f64-branches-avx.clif b/cranelift/filetests/filetests/isa/x64/f64-branches-avx.clif
new file mode 100644
index 000000000..f40100bbf
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/f64-branches-avx.clif
@@ -0,0 +1,105 @@
+test compile precise-output
+target x86_64 has_avx
+
+function %f3(f32, f32) -> i32 {
+block0(v0: f32, v1: f32):
+  v2 = fcmp eq v0, v1
+  brif v2, block1, block2
+
+block1:
+  v3 = iconst.i32 1
+  return v3
+
+block2:
+  v4 = iconst.i32 2
+  return v4
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   vucomiss %xmm1, %xmm0
+;   jp      label1
+;   jnz     label1; j label2
+; block1:
+;   movl    $2, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+; block2:
+;   movl    $1, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   vucomiss %xmm1, %xmm0
+;   jp 0x14
+;   je 0x1e
+; block2: ; offset 0x14
+;   movl $2, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+; block3: ; offset 0x1e
+;   movl $1, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %f3(f64, f64) -> i32 {
+block0(v0: f64, v1: f64):
+  v2 = fcmp eq v0, v1
+  brif v2, block1, block2
+
+block1:
+  v3 = iconst.i32 1
+  return v3
+
+block2:
+  v4 = iconst.i32 2
+  return v4
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   vucomisd %xmm1, %xmm0
+;   jp      label1
+;   jnz     label1; j label2
+; block1:
+;   movl    $2, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+; block2:
+;   movl    $1, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   vucomisd %xmm1, %xmm0
+;   jp 0x14
+;   je 0x1e
+; block2: ; offset 0x14
+;   movl $2, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+; block3: ; offset 0x1e
+;   movl $1, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
diff --git a/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif b/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif
index ba16a98c9..22ba0bb94 100644
--- a/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif
+++ b/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif
@@ -42,18 +42,18 @@ block0(v0: i64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_i64+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %rdi=%rdi
+;   load_ext_name %callee_i64+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movabsq $0, %rcx ; reloc_external Abs8 %callee_i64 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_i64 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test colocated tail calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -70,18 +70,18 @@ block0(v0: i64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_i64+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %rdi=%rdi
+;   load_ext_name %callee_i64+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   leaq (%rip), %rcx ; reloc_external CallPCRel4 %callee_i64 -4
+;   leaq (%rip), %r10 ; reloc_external CallPCRel4 %callee_i64 -4
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test passing `f64`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -139,18 +139,18 @@ block0(v0: f64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_f64+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %xmm0=%xmm0
+;   load_ext_name %callee_f64+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %xmm0=%xmm0
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movabsq $0, %rcx ; reloc_external Abs8 %callee_f64 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_f64 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test passing `i8`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -195,18 +195,18 @@ block0(v0: i8):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_i8+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %rdi=%rdi
+;   load_ext_name %callee_i8+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movabsq $0, %rcx ; reloc_external Abs8 %callee_i8 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_i8 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test passing many arguments on stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -335,7 +335,7 @@ block0:
 ;   movq    rsp(72 + virtual offset), %r8
 ;   movq    rsp(64 + virtual offset), %r9
 ;   movq    rsp(0 + virtual offset), %r10
-;   return_call_unknown %r10 (160) tmp=%rax %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
+;   return_call_unknown %r10 (160) tmp=%r11 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
diff --git a/cranelift/filetests/filetests/isa/x64/return-call.clif b/cranelift/filetests/filetests/isa/x64/return-call.clif
index 8ffb1c2fd..113d495bc 100644
--- a/cranelift/filetests/filetests/isa/x64/return-call.clif
+++ b/cranelift/filetests/filetests/isa/x64/return-call.clif
@@ -40,18 +40,18 @@ block0(v0: i64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_i64+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %rdi=%rdi
+;   load_ext_name %callee_i64+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movabsq $0, %rcx ; reloc_external Abs8 %callee_i64 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_i64 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test colocated tail calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -66,7 +66,7 @@ block0(v0: i64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   return_call_known TestCase(%callee_i64) (0) tmp=%rax %rdi=%rdi
+;   return_call_known TestCase(%callee_i64) (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -131,18 +131,18 @@ block0(v0: f64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_f64+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %xmm0=%xmm0
+;   load_ext_name %callee_f64+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %xmm0=%xmm0
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movabsq $0, %rcx ; reloc_external Abs8 %callee_f64 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_f64 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test passing `i8`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -185,18 +185,18 @@ block0(v0: i8):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   load_ext_name %callee_i8+0, %rcx
-;   return_call_unknown %rcx (0) tmp=%rdx %rdi=%rdi
+;   load_ext_name %callee_i8+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movabsq $0, %rcx ; reloc_external Abs8 %callee_i8 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_i8 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rcx
+;   jmpq *%r10
 
 ;;;; Test passing fewer arguments on the stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -243,7 +243,7 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v
 ;   movq    rbp(stack args max - 24), %r9
 ;   movq    rbp(stack args max - 16), %rax
 ;   movl    %eax, rbp(stack args max - 16)
-;   return_call_known TestCase(%one_stack_arg) (16) tmp=%r10 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
+;   return_call_known TestCase(%one_stack_arg) (16) tmp=%r11 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -260,8 +260,8 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v
 ;   movl %eax, 0x20(%rbp)
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   movq (%rsp), %r10
-;   movq %r10, 0x10(%rsp)
+;   movq (%rsp), %r11
+;   movq %r11, 0x10(%rsp)
 ;   addq $0x10, %rsp
 ;   jmp 0x35 ; reloc_external CallPCRel4 %one_stack_arg -4
 
@@ -279,7 +279,7 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v
 ;   movq    rbp(stack args max - 32), %r10
 ;   movq    rbp(stack args max - 24), %rsi
 ;   movq    rbp(stack args max - 16), %rdi
-;   return_call_known TestCase(%callee_i8) (0) tmp=%rdx %rdi=%rdi
+;   return_call_known TestCase(%callee_i8) (0) tmp=%r11 %rdi=%rdi
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -291,8 +291,8 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v
 ;   movq 0x20(%rbp), %rdi
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   movq (%rsp), %rdx
-;   movq %rdx, 0x20(%rsp)
+;   movq (%rsp), %r11
+;   movq %r11, 0x20(%rsp)
 ;   addq $0x20, %rsp
 ;   jmp 0x26 ; reloc_external CallPCRel4 %callee_i8 -4
 
@@ -325,7 +325,7 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32):
 ;   movl    %esi, rbp(stack args max - 16)
 ;   movq    %rsi, %rdi
 ;   movq    %r10, %rsi
-;   return_call_known TestCase(%call_one_stack_arg) (32) tmp=%r10 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
+;   return_call_known TestCase(%call_one_stack_arg) (32) tmp=%r11 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -531,14 +531,14 @@ block0:
 ;   movq    %rsi, rbp(stack args max - 16)
 ;   movq    rsp(0 + virtual offset), %rsi
 ;   movq    %rsi, rbp(stack args max - 8)
-;   load_ext_name %tail_callee_stack_args+0, %rax
+;   load_ext_name %tail_callee_stack_args+0, %r10
 ;   movq    rsp(72 + virtual offset), %rcx
 ;   movq    rsp(80 + virtual offset), %rdx
 ;   movq    rsp(88 + virtual offset), %rsi
 ;   movq    rsp(96 + virtual offset), %rdi
 ;   movq    rsp(64 + virtual offset), %r8
 ;   movq    rsp(56 + virtual offset), %r9
-;   return_call_unknown %rax (160) tmp=%r10 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
+;   return_call_unknown %r10 (160) tmp=%r11 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -623,7 +623,7 @@ block0:
 ;   movq %rsi, 0xa0(%rbp)
 ;   movq (%rsp), %rsi
 ;   movq %rsi, 0xa8(%rbp)
-;   movabsq $0, %rax ; reloc_external Abs8 %tail_callee_stack_args 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %tail_callee_stack_args 0
 ;   movq 0x48(%rsp), %rcx
 ;   movq 0x50(%rsp), %rdx
 ;   movq 0x58(%rsp), %rsi
@@ -638,5 +638,5 @@ block0:
 ;   addq $0xa0, %rsp
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   jmpq *%rax
+;   jmpq *%r10
 
diff --git a/cranelift/filetests/filetests/isa/x64/simd-logical-compile-avx.clif b/cranelift/filetests/filetests/isa/x64/simd-logical-compile-avx.clif
new file mode 100644
index 000000000..f30b20acc
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/simd-logical-compile-avx.clif
@@ -0,0 +1,62 @@
+test compile precise-output
+target x86_64 sse42 has_avx
+
+function %vany_true_i32x4(i32x4) -> i8 {
+block0(v0: i32x4):
+    v1 = vany_true v0
+    return v1
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   vptest  %xmm0, %xmm0
+;   setnz   %al
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   vptest %xmm0, %xmm0
+;   setne %al
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %vall_true_i64x2(i64x2) -> i8 {
+block0(v0: i64x2):
+    v1 = vall_true v0
+    return v1
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   uninit  %xmm2
+;   vpxor   %xmm2, %xmm2, %xmm4
+;   vpcmpeqq %xmm0, %xmm4, %xmm6
+;   vptest  %xmm6, %xmm6
+;   setz    %al
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   vpxor %xmm2, %xmm2, %xmm4
+;   vpcmpeqq %xmm4, %xmm0, %xmm6
+;   vptest %xmm6, %xmm6
+;   sete %al
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
diff --git a/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif b/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif
index 93ccab77f..7a2243a0f 100644
--- a/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif
+++ b/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif
@@ -895,7 +895,6 @@ block0:
 ;   popq %rbp
 ;   retq
 
-
 ;; Test that tail calls that shrink the argument area don't clobber the location
 ;; of an indirect jump
 
@@ -916,8 +915,8 @@ block0(v0: f64, v1: f64, v2: i8, v3: i32, v4: i128, v5: i32, v6: i128, v7: i32,
 ;   movq    rbp(stack args max - 24), %rax
 ;   movq    rbp(stack args max - 16), %rdx
 ;   movq    rbp(stack args max - 8), %r9
-;   load_ext_name %callee_simple+0, %rsi
-;   return_call_unknown %rsi (0) tmp=%rdi
+;   load_ext_name %callee_simple+0, %r10
+;   return_call_unknown %r10 (0) tmp=%r11
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -928,11 +927,11 @@ block0(v0: f64, v1: f64, v2: i8, v3: i32, v4: i128, v5: i32, v6: i128, v7: i32,
 ;   movq 0x18(%rbp), %rax
 ;   movq 0x20(%rbp), %rdx
 ;   movq 0x28(%rbp), %r9
-;   movabsq $0, %rsi ; reloc_external Abs8 %callee_simple 0
+;   movabsq $0, %r10 ; reloc_external Abs8 %callee_simple 0
 ;   movq %rbp, %rsp
 ;   popq %rbp
-;   movq (%rsp), %rdi
-;   movq %rdi, 0x20(%rsp)
+;   movq (%rsp), %r11
+;   movq %r11, 0x20(%rsp)
 ;   addq $0x20, %rsp
-;   jmpq *%rsi
+;   jmpq *%r10
 
diff --git a/cranelift/filetests/filetests/isa/x64/very-carefully-sink-loads-in-float-compares.clif b/cranelift/filetests/filetests/isa/x64/very-carefully-sink-loads-in-float-compares.clif
new file mode 100644
index 000000000..01c9d4db2
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/very-carefully-sink-loads-in-float-compares.clif
@@ -0,0 +1,499 @@
+test compile precise-output
+target x86_64
+
+;; This test ensures that Cranelift does not attempt to too eagerly sink loads
+;; into float comparison operations. When a single `fcmp` is used multiple times
+;; it'll regenerate `ucomiss` instructions, for example, but if this duplication
+;; happens then it shouldn't have a load sunk into it because that would load
+;; at two different points in the program, possibly seeing two different
+;; results.
+;;
+;; Exactly how this guarantee is provided has changed a bit over time with
+;; Cranelift. Originally in #3934 this was done explicitly in ISLE by avoiding
+;; the use of `put_in_xmm_mem`. Later in #4061 that ended up removing the need
+;; for the safeguards in #3934. Today there are no guards in ISLE for this any
+;; more and this test is intended to serve as a reference-test for notifying
+;; reviewers if anything changes.
+
+function %select_cond_rhs(f32, i64, i32, i32) -> i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v0, v4
+  v6 = select v5, v2, v3
+  return v6
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   ucomiss 0(%rdi), %xmm0
+;   cmovpl  %edx, %esi, %esi
+;   movq    %rsi, %rax
+;   cmovnzl %edx, %eax, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   ucomiss (%rdi), %xmm0
+;   cmovpl %edx, %esi
+;   movq %rsi, %rax
+;   cmovnel %edx, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+
+function %select_cond_lhs(f32, i64, i32, i32) -> i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v4, v0
+  v6 = select v5, v2, v3
+  return v6
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm7
+;   ucomiss %xmm0, %xmm7
+;   cmovpl  %edx, %esi, %esi
+;   movq    %rsi, %rax
+;   cmovnzl %edx, %eax, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm7
+;   ucomiss %xmm0, %xmm7
+;   cmovpl %edx, %esi
+;   movq %rsi, %rax
+;   cmovnel %edx, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %select_cond_used_twice_rhs(f32, i64, i32, i32) -> i32, i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  ;; this load should NOT sink into either `select` below
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v0, v4
+  v6 = select v5, v2, v3
+  v7 = select v5, v3, v2
+  return v6, v7
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm1
+;   ucomiss %xmm1, %xmm0
+;   movq    %rsi, %rax
+;   cmovpl  %edx, %eax, %eax
+;   cmovnzl %edx, %eax, %eax
+;   ucomiss %xmm1, %xmm0
+;   cmovpl  %esi, %edx, %edx
+;   cmovnzl %esi, %edx, %edx
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm1
+;   ucomiss %xmm1, %xmm0
+;   movq %rsi, %rax
+;   cmovpl %edx, %eax
+;   cmovnel %edx, %eax
+;   ucomiss %xmm1, %xmm0
+;   cmovpl %esi, %edx
+;   cmovnel %esi, %edx
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+
+function %select_cond_used_twice_lhs(f32, i64, i32, i32) -> i32, i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  ;; this load should NOT sink into either `select` below
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v4, v0
+  v6 = select v5, v2, v3
+  v7 = select v5, v3, v2
+  return v6, v7
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm1
+;   ucomiss %xmm0, %xmm1
+;   movq    %rsi, %rax
+;   cmovpl  %edx, %eax, %eax
+;   cmovnzl %edx, %eax, %eax
+;   ucomiss %xmm0, %xmm1
+;   cmovpl  %esi, %edx, %edx
+;   cmovnzl %esi, %edx, %edx
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm1
+;   ucomiss %xmm0, %xmm1
+;   movq %rsi, %rax
+;   cmovpl %edx, %eax
+;   cmovnel %edx, %eax
+;   ucomiss %xmm0, %xmm1
+;   cmovpl %esi, %edx
+;   cmovnel %esi, %edx
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %brif_cond_rhs(f32, i64, i32, i32) -> i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v0, v4
+  brif v5, block1(v2), block1(v3)
+block1(v8: i32):
+  return v8
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm1
+;   ucomiss %xmm1, %xmm0
+;   jp      label2
+;   jnz     label2; j label1
+; block1:
+;   movq    %rsi, %rax
+;   jmp     label3
+; block2:
+;   movq    %rdx, %rax
+;   jmp     label3
+; block3:
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm1
+;   ucomiss %xmm1, %xmm0
+;   jp 0x1f
+;   jne 0x1f
+; block2: ; offset 0x17
+;   movq %rsi, %rax
+;   jmp 0x22
+; block3: ; offset 0x1f
+;   movq %rdx, %rax
+; block4: ; offset 0x22
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %brif_cond_lhs(f32, i64, i32, i32) -> i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v4, v0
+  brif v5, block1(v2), block1(v3)
+block1(v8: i32):
+  return v8
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm1
+;   ucomiss %xmm0, %xmm1
+;   jp      label2
+;   jnz     label2; j label1
+; block1:
+;   movq    %rsi, %rax
+;   jmp     label3
+; block2:
+;   movq    %rdx, %rax
+;   jmp     label3
+; block3:
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm1
+;   ucomiss %xmm0, %xmm1
+;   jp 0x1f
+;   jne 0x1f
+; block2: ; offset 0x17
+;   movq %rsi, %rax
+;   jmp 0x22
+; block3: ; offset 0x1f
+;   movq %rdx, %rax
+; block4: ; offset 0x22
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %brif_cond_used_twice_rhs(f32, i64, i32, i32) -> i32, i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v0, v4
+  brif v5, block1(v2), block1(v3)
+block1(v6: i32):
+  brif v5, block2(v3), block2(v2)
+block2(v7: i32):
+  return v6, v7
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm3
+;   ucomiss %xmm3, %xmm0
+;   jp      label2
+;   jnz     label2; j label1
+; block1:
+;   movq    %rsi, %rax
+;   jmp     label3
+; block2:
+;   movq    %rdx, %rax
+;   jmp     label3
+; block3:
+;   ucomiss %xmm3, %xmm0
+;   jp      label5
+;   jnz     label5; j label4
+; block4:
+;   jmp     label6
+; block5:
+;   movq    %rsi, %rdx
+;   jmp     label6
+; block6:
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm3
+;   ucomiss %xmm3, %xmm0
+;   jp 0x1f
+;   jne 0x1f
+; block2: ; offset 0x17
+;   movq %rsi, %rax
+;   jmp 0x22
+; block3: ; offset 0x1f
+;   movq %rdx, %rax
+; block4: ; offset 0x22
+;   ucomiss %xmm3, %xmm0
+;   jp 0x31
+;   je 0x34
+; block5: ; offset 0x31
+;   movq %rsi, %rdx
+; block6: ; offset 0x34
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %brif_cond_used_twice_lhs(f32, i64, i32, i32) -> i32, i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v4, v0
+  brif v5, block1(v2), block1(v3)
+block1(v6: i32):
+  brif v5, block2(v3), block2(v2)
+block2(v7: i32):
+  return v6, v7
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm3
+;   ucomiss %xmm0, %xmm3
+;   jp      label2
+;   jnz     label2; j label1
+; block1:
+;   movq    %rsi, %rax
+;   jmp     label3
+; block2:
+;   movq    %rdx, %rax
+;   jmp     label3
+; block3:
+;   ucomiss %xmm0, %xmm3
+;   jp      label5
+;   jnz     label5; j label4
+; block4:
+;   jmp     label6
+; block5:
+;   movq    %rsi, %rdx
+;   jmp     label6
+; block6:
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm3
+;   ucomiss %xmm0, %xmm3
+;   jp 0x1f
+;   jne 0x1f
+; block2: ; offset 0x17
+;   movq %rsi, %rax
+;   jmp 0x22
+; block3: ; offset 0x1f
+;   movq %rdx, %rax
+; block4: ; offset 0x22
+;   ucomiss %xmm0, %xmm3
+;   jp 0x31
+;   je 0x34
+; block5: ; offset 0x31
+;   movq %rsi, %rdx
+; block6: ; offset 0x34
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %mix_select_and_brif_rhs(f32, i64, i32, i32) -> i32, i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v0, v4
+  v6 = select v5, v2, v3
+  brif v5, block1(v3), block1(v2)
+block1(v7: i32):
+  return v6, v7
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm2
+;   ucomiss %xmm2, %xmm0
+;   movq    %rsi, %rax
+;   cmovpl  %edx, %eax, %eax
+;   cmovnzl %edx, %eax, %eax
+;   ucomiss %xmm2, %xmm0
+;   jp      label2
+;   jnz     label2; j label1
+; block1:
+;   jmp     label3
+; block2:
+;   movq    %rsi, %rdx
+;   jmp     label3
+; block3:
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm2
+;   ucomiss %xmm2, %xmm0
+;   movq %rsi, %rax
+;   cmovpl %edx, %eax
+;   cmovnel %edx, %eax
+;   ucomiss %xmm2, %xmm0
+;   jp 0x23
+;   je 0x26
+; block2: ; offset 0x23
+;   movq %rsi, %rdx
+; block3: ; offset 0x26
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
+function %mix_select_and_brif_lhs(f32, i64, i32, i32) -> i32, i32 {
+block0(v0: f32, v1: i64, v2: i32, v3: i32):
+  v4 = load.f32 notrap aligned v1
+  v5 = fcmp eq v4, v0
+  v6 = select v5, v2, v3
+  brif v5, block1(v3), block1(v2)
+block1(v7: i32):
+  return v6, v7
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movss   0(%rdi), %xmm2
+;   ucomiss %xmm0, %xmm2
+;   movq    %rsi, %rax
+;   cmovpl  %edx, %eax, %eax
+;   cmovnzl %edx, %eax, %eax
+;   ucomiss %xmm0, %xmm2
+;   jp      label2
+;   jnz     label2; j label1
+; block1:
+;   jmp     label3
+; block2:
+;   movq    %rsi, %rdx
+;   jmp     label3
+; block3:
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movss (%rdi), %xmm2
+;   ucomiss %xmm0, %xmm2
+;   movq %rsi, %rax
+;   cmovpl %edx, %eax
+;   cmovnel %edx, %eax
+;   ucomiss %xmm0, %xmm2
+;   jp 0x23
+;   je 0x26
+; block2: ; offset 0x23
+;   movq %rsi, %rdx
+; block3: ; offset 0x26
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
diff --git a/cranelift/filetests/filetests/isa/x64/winch.clif b/cranelift/filetests/filetests/isa/x64/winch.clif
index 808b73d57..8832531b7 100644
--- a/cranelift/filetests/filetests/isa/x64/winch.clif
+++ b/cranelift/filetests/filetests/isa/x64/winch.clif
@@ -38,8 +38,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   subq    %rsp, $16, %rsp
 ; block0:
 ;   movq    %rdi, rsp(0 + virtual offset)
-;   load_ext_name %g+0, %r15
-;   call    *%r15
+;   load_ext_name %g+0, %r10
+;   call    *%r10
 ;   movq    rsp(0 + virtual offset), %rax
 ;   addq    %rsp, $16, %rsp
 ;   movq    %rbp, %rsp
@@ -53,8 +53,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   subq $0x10, %rsp
 ; block1: ; offset 0x8
 ;   movq %rdi, (%rsp)
-;   movabsq $0, %r15 ; reloc_external Abs8 %g 0
-;   callq *%r15
+;   movabsq $0, %r10 ; reloc_external Abs8 %g 0
+;   callq *%r10
 ;   movq (%rsp), %rax
 ;   addq $0x10, %rsp
 ;   movq %rbp, %rsp
@@ -81,8 +81,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   movq    %r15, 48(%rsp)
 ; block0:
 ;   movq    %rdi, rsp(0 + virtual offset)
-;   load_ext_name %g+0, %r15
-;   call    *%r15
+;   load_ext_name %g+0, %r10
+;   call    *%r10
 ;   movq    rsp(0 + virtual offset), %rax
 ;   movq    16(%rsp), %rbx
 ;   movq    24(%rsp), %r12
@@ -106,8 +106,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   movq %r15, 0x30(%rsp)
 ; block1: ; offset 0x21
 ;   movq %rdi, (%rsp)
-;   movabsq $0, %r15 ; reloc_external Abs8 %g 0
-;   callq *%r15
+;   movabsq $0, %r10 ; reloc_external Abs8 %g 0
+;   callq *%r10
 ;   movq (%rsp), %rax
 ;   movq 0x10(%rsp), %rbx
 ;   movq 0x18(%rsp), %r12
@@ -135,8 +135,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   movq    %rdi, %rax
 ;   movq    %r9, %rdi
 ;   movq    %rax, %r9
-;   load_ext_name %g+0, %r15
-;   call    *%r15
+;   load_ext_name %g+0, %r10
+;   call    *%r10
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -149,8 +149,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   movq %rdi, %rax
 ;   movq %r9, %rdi
 ;   movq %rax, %r9
-;   movabsq $0, %r15 ; reloc_external Abs8 %g 0
-;   callq *%r15
+;   movabsq $0, %r10 ; reloc_external Abs8 %g 0
+;   callq *%r10
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -177,8 +177,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   movq    %rdi, %rax
 ;   movq    %r9, %rdi
 ;   movq    %rax, %r9
-;   load_ext_name %g+0, %r15
-;   call    *%r15
+;   load_ext_name %g+0, %r10
+;   call    *%r10
 ;   movq    0(%rsp), %rbx
 ;   movq    8(%rsp), %r12
 ;   movq    16(%rsp), %r13
@@ -203,8 +203,8 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64):
 ;   movq %rdi, %rax
 ;   movq %r9, %rdi
 ;   movq %rax, %r9
-;   movabsq $0, %r15 ; reloc_external Abs8 %g 0
-;   callq *%r15
+;   movabsq $0, %r10 ; reloc_external Abs8 %g 0
+;   callq *%r10
 ;   movq (%rsp), %rbx
 ;   movq 8(%rsp), %r12
 ;   movq 0x10(%rsp), %r13
@@ -236,12 +236,12 @@ block0:
 ;   movq    %r14, 40(%rsp)
 ;   movq    %r15, 48(%rsp)
 ; block0:
-;   load_ext_name userextname0+0, %r15
-;   movq    %r15, rsp(0 + virtual offset)
-;   movq    rsp(0 + virtual offset), %r15
-;   call    *%r15
-;   movq    rsp(0 + virtual offset), %r15
-;   call    *%r15
+;   load_ext_name userextname0+0, %r10
+;   movq    %r10, rsp(0 + virtual offset)
+;   movq    rsp(0 + virtual offset), %r10
+;   call    *%r10
+;   movq    rsp(0 + virtual offset), %r10
+;   call    *%r10
 ;   movq    16(%rsp), %rbx
 ;   movq    24(%rsp), %r12
 ;   movq    32(%rsp), %r13
@@ -263,12 +263,12 @@ block0:
 ;   movq %r14, 0x28(%rsp)
 ;   movq %r15, 0x30(%rsp)
 ; block1: ; offset 0x21
-;   movabsq $0, %r15 ; reloc_external Abs8 u2:0 0
-;   movq %r15, (%rsp)
-;   movq (%rsp), %r15
-;   callq *%r15
-;   movq (%rsp), %r15
-;   callq *%r15
+;   movabsq $0, %r10 ; reloc_external Abs8 u2:0 0
+;   movq %r10, (%rsp)
+;   movq (%rsp), %r10
+;   callq *%r10
+;   movq (%rsp), %r10
+;   callq *%r10
 ;   movq 0x10(%rsp), %rbx
 ;   movq 0x18(%rsp), %r12
 ;   movq 0x20(%rsp), %r13
@@ -301,8 +301,8 @@ block0(v0:i64):
 ;   movq    %r15, 48(%rsp)
 ; block0:
 ;   lea     0(%rsp), %rdi
-;   load_ext_name %g+0, %r15
-;   call    *%r15
+;   load_ext_name %g+0, %r10
+;   call    *%r10
 ;   movq    4(%rsp), %rax
 ;   movq    0(%rsp), %r11
 ;   andl    %eax, %r11d, %eax
@@ -328,8 +328,8 @@ block0(v0:i64):
 ;   movq %r15, 0x30(%rsp)
 ; block1: ; offset 0x21
 ;   leaq (%rsp), %rdi
-;   movabsq $0, %r15 ; reloc_external Abs8 %g 0
-;   callq *%r15
+;   movabsq $0, %r10 ; reloc_external Abs8 %g 0
+;   callq *%r10
 ;   movq 4(%rsp), %rax
 ;   movq (%rsp), %r11
 ;   andl %r11d, %eax