Repository: bytecodealliance/wasmtime
Pull request #6915 (2023-08-26 16:55:02)

riscv64: Refactor constant emission
👋 Hey,

This PR fixes the RISC-V issues that #6850 exposed. It does a bit of a refactor in our constant emission infrastructure, and also moves some of it into ISLE. 

The issues that that PR exposed are that we sometimes would match or not match a particular constant generation strategy based on the upper bits that shouldn't really matter. The main fix is to sign extend constants before trying to match them. 

Moving the constant emission into ISLE also means that we have a bunch of neutral regalloc changes. There are a few cases where we have actual changes in the instructions emitted.
  
This PR contains a lot of stuff, and I would recommend reviewing it commit by commit.

github-actions[bot]: #### Subscribe to Label Action

cc @cfallin, @fitzgen

<details>
This issue or pull request has been labeled: "cranelift", "cranelift:area:machinst", "cranelift:area:riscv64", "isle"

Thus the following users have been cc'd because of the following labels:

* cfallin: isle
* fitzgen: isle

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

[Learn more.](https://github.com/bytecodealliance/subscribe-to-label-action)
</details>

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index dbd23f150..6c59eeef0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -121,7 +121,7 @@ checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -459,7 +459,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -510,7 +510,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -599,6 +599,7 @@ dependencies = [
  "log",
  "regalloc2",
  "serde",
+ "serde_derive",
  "sha2",
  "similar",
  "smallvec",
@@ -629,6 +630,7 @@ name = "cranelift-entity"
 version = "0.100.0"
 dependencies = [
  "serde",
+ "serde_derive",
 ]
 
 [[package]]
@@ -652,11 +654,12 @@ dependencies = [
  "log",
  "num_cpus",
  "serde",
+ "serde_derive",
  "similar",
  "target-lexicon",
  "thiserror",
  "toml",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wat",
 ]
 
@@ -737,6 +740,7 @@ dependencies = [
  "cranelift-control",
  "hashbrown 0.14.0",
  "serde",
+ "serde_derive",
 ]
 
 [[package]]
@@ -831,9 +835,10 @@ dependencies = [
  "itertools",
  "log",
  "serde",
+ "serde_derive",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmtime-types",
  "wat",
 ]
@@ -960,7 +965,7 @@ checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2407,22 +2412,22 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.171"
+version = "1.0.188"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
+checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.171"
+version = "1.0.188"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
+checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2590,9 +2595,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.25"
+version = "2.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2691,7 +2696,7 @@ dependencies = [
  "wasmtime",
  "wasmtime-wasi",
  "wasmtime-wasi-http",
- "wit-component 0.13.2",
+ "wit-component 0.14.0",
 ]
 
 [[package]]
@@ -2711,7 +2716,7 @@ checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2774,7 +2779,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2831,7 +2836,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2967,7 +2972,7 @@ name = "verify-component-adapter"
 version = "13.0.0"
 dependencies = [
  "anyhow",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wat",
 ]
 
@@ -3069,7 +3074,7 @@ dependencies = [
  "byte-array-literals",
  "object",
  "wasi",
- "wasm-encoder 0.31.1",
+ "wasm-encoder 0.32.0",
  "wit-bindgen",
 ]
 
@@ -3128,7 +3133,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
  "wasm-bindgen-shared",
 ]
 
@@ -3150,7 +3155,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -3172,9 +3177,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.31.1"
+version = "0.32.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16"
+checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7"
 dependencies = [
  "leb128",
 ]
@@ -3196,45 +3201,45 @@ dependencies = [
 
 [[package]]
 name = "wasm-metadata"
-version = "0.10.2"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ac8d3bcbbb5081489f35966b86d127596e9cdacfb3824b79f43344662226178"
+checksum = "08dc59d1fa569150851542143ca79438ca56845ccb31696c70225c638e063471"
 dependencies = [
  "anyhow",
  "indexmap 2.0.0",
  "serde",
  "serde_json",
  "spdx",
- "wasm-encoder 0.31.1",
- "wasmparser 0.111.0",
+ "wasm-encoder 0.32.0",
+ "wasmparser 0.112.0",
 ]
 
 [[package]]
 name = "wasm-mutate"
-version = "0.2.31"
+version = "0.2.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25ff8dc1c451e485af2fdd3997acb95dde3a99ecb584cc0c23c25d0f857a64b1"
+checksum = "1a893c0b2bad91ea78171dbff7fe6d764f8b1c9e20617061d284cfbdf902e329"
 dependencies = [
  "egg",
  "log",
  "rand",
  "thiserror",
- "wasm-encoder 0.31.1",
- "wasmparser 0.111.0",
+ "wasm-encoder 0.32.0",
+ "wasmparser 0.112.0",
 ]
 
 [[package]]
 name = "wasm-smith"
-version = "0.12.14"
+version = "0.12.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07a8af736893cab6d785987ffb6abec45d30b19e64eb7ea022425120354e557e"
+checksum = "ad8e84473dc3e1ca4759114ba8f3beaf3b7272d67868e351ba5d3fc006139f93"
 dependencies = [
  "arbitrary",
  "flagset",
  "indexmap 2.0.0",
  "leb128",
- "wasm-encoder 0.31.1",
- "wasmparser 0.111.0",
+ "wasm-encoder 0.32.0",
+ "wasmparser 0.112.0",
 ]
 
 [[package]]
@@ -3287,9 +3292,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.111.0"
+version = "0.112.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad71036aada3f6b09251546e97e4f4f176dd6b41cf6fa55e7e0f65e86aec319a"
+checksum = "e986b010f47fcce49cf8ea5d5f9e5d2737832f12b53ae8ae785bbe895d0877bf"
 dependencies = [
  "indexmap 2.0.0",
  "semver",
@@ -3306,12 +3311,12 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.2.63"
+version = "0.2.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eeb8cc41d341939dce08ee902b50e36cd35add940f6044c94b144e8f73fe07a6"
+checksum = "34ddf5892036cd4b780d505eff1194a0cbc10ed896097656fdcea3744b5e7c2f"
 dependencies = [
  "anyhow",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
 ]
 
 [[package]]
@@ -3334,12 +3339,13 @@ dependencies = [
  "psm",
  "rayon",
  "serde",
+ "serde_derive",
  "serde_json",
  "target-lexicon",
  "tempfile",
  "wasi-cap-std-sync",
- "wasm-encoder 0.31.1",
- "wasmparser 0.111.0",
+ "wasm-encoder 0.32.0",
+ "wasmparser 0.112.0",
  "wasmtime-cache",
  "wasmtime-component-macro",
  "wasmtime-component-util",
@@ -3416,6 +3422,7 @@ dependencies = [
  "pretty_env_logger 0.5.0",
  "rustix 0.38.8",
  "serde",
+ "serde_derive",
  "sha2",
  "tempfile",
  "toml",
@@ -3446,14 +3453,15 @@ dependencies = [
  "rayon",
  "rustix 0.38.8",
  "serde",
+ "serde_derive",
  "serde_json",
  "target-lexicon",
  "tempfile",
  "test-programs",
  "tokio",
  "walkdir",
- "wasm-encoder 0.31.1",
- "wasmparser 0.111.0",
+ "wasm-encoder 0.32.0",
+ "wasmparser 0.112.0",
  "wasmtime",
  "wasmtime-cache",
  "wasmtime-cli-flags",
@@ -3467,7 +3475,7 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 63.0.0",
+ "wast 64.0.0",
  "wat",
  "windows-sys",
 ]
@@ -3492,12 +3500,12 @@ dependencies = [
  "component-macro-test-helpers",
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
  "tracing",
  "wasmtime",
  "wasmtime-component-util",
  "wasmtime-wit-bindgen",
- "wit-parser 0.10.0",
+ "wit-parser 0.11.0",
 ]
 
 [[package]]
@@ -3521,7 +3529,7 @@ dependencies = [
  "object",
  "target-lexicon",
  "thiserror",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
  "wasmtime-versioned-export-macros",
@@ -3555,10 +3563,11 @@ dependencies = [
  "log",
  "object",
  "serde",
+ "serde_derive",
  "target-lexicon",
  "thiserror",
- "wasm-encoder 0.31.1",
- "wasmparser 0.111.0",
+ "wasm-encoder 0.32.0",
+ "wasmparser 0.112.0",
  "wasmprinter",
  "wasmtime-component-util",
  "wasmtime-types",
@@ -3573,7 +3582,7 @@ dependencies = [
  "component-fuzz-util",
  "env_logger 0.10.0",
  "libfuzzer-sys",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmprinter",
  "wasmtime-environ",
  "wat",
@@ -3586,6 +3595,7 @@ dependencies = [
  "anyhow",
  "capstone",
  "serde",
+ "serde_derive",
  "serde_json",
  "target-lexicon",
  "wasmprinter",
@@ -3628,7 +3638,7 @@ dependencies = [
  "rand",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmtime",
  "wasmtime-fuzzing",
 ]
@@ -3648,12 +3658,12 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "v8",
- "wasm-encoder 0.31.1",
+ "wasm-encoder 0.32.0",
  "wasm-mutate",
  "wasm-smith",
  "wasm-spec-interpreter",
  "wasmi",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmprinter",
  "wasmtime",
  "wasmtime-wast",
@@ -3676,6 +3686,7 @@ dependencies = [
  "rustc-demangle",
  "rustix 0.38.8",
  "serde",
+ "serde_derive",
  "target-lexicon",
  "wasmtime-environ",
  "wasmtime-jit-debug",
@@ -3722,7 +3733,7 @@ dependencies = [
  "rand",
  "rustix 0.38.8",
  "sptr",
- "wasm-encoder 0.31.1",
+ "wasm-encoder 0.32.0",
  "wasmtime-asm-macros",
  "wasmtime-environ",
  "wasmtime-fiber",
@@ -3738,8 +3749,9 @@ version = "13.0.0"
 dependencies = [
  "cranelift-entity",
  "serde",
+ "serde_derive",
  "thiserror",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
 ]
 
 [[package]]
@@ -3748,7 +3760,7 @@ version = "13.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -3837,7 +3849,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 63.0.0",
+ "wast 64.0.0",
 ]
 
 [[package]]
@@ -3849,7 +3861,7 @@ dependencies = [
  "gimli",
  "object",
  "target-lexicon",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
  "winch-codegen",
@@ -3862,7 +3874,7 @@ dependencies = [
  "anyhow",
  "heck",
  "indexmap 2.0.0",
- "wit-parser 0.10.0",
+ "wit-parser 0.11.0",
 ]
 
 [[package]]
@@ -3880,23 +3892,23 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "63.0.0"
+version = "64.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2560471f60a48b77fccefaf40796fda61c97ce1e790b59dfcec9dc3995c9f63a"
+checksum = "a259b226fd6910225aa7baeba82f9d9933b6d00f2ce1b49b80fa4214328237cc"
 dependencies = [
  "leb128",
  "memchr",
  "unicode-width",
- "wasm-encoder 0.31.1",
+ "wasm-encoder 0.32.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.0.70"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bdc306c2c4c2f2bf2ba69e083731d0d2a77437fc6a350a19db139636e7e416c"
+checksum = "53253d920ab413fca1c7dc2161d601c79b4fdf631d0ba51dd4343bf9b556c3f6"
 dependencies = [
- "wast 63.0.0",
+ "wast 64.0.0",
 ]
 
 [[package]]
@@ -3952,7 +3964,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "shellexpand",
- "syn 2.0.25",
+ "syn 2.0.29",
  "witx",
 ]
 
@@ -3962,7 +3974,7 @@ version = "13.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
  "wiggle",
  "wiggle-generate",
 ]
@@ -4021,7 +4033,7 @@ dependencies = [
  "regalloc2",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmtime-environ",
 ]
 
@@ -4033,6 +4045,7 @@ dependencies = [
  "capstone",
  "cranelift-codegen",
  "serde",
+ "serde_derive",
  "similar",
  "target-lexicon",
  "toml",
@@ -4049,7 +4062,7 @@ dependencies = [
  "glob",
  "proc-macro2",
  "quote",
- "syn 2.0.25",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4065,7 +4078,7 @@ dependencies = [
  "similar",
  "target-lexicon",
  "toml",
- "wasmparser 0.111.0",
+ "wasmparser 0.112.0",
  "wasmtime-environ",
  "wat",
  "winch-codegen",
@@ -4201,7 +4214,7 @@ checksum = "0a2abe5c7c4c08468d01590aa96c8a684dd94fb9241a248af88eef7edac61e43"
 dependencies = [
  "anyhow",
  "proc-macro2",
- "syn 2.0.25",
+ "syn 2.0.29",
  "wit-bindgen-core",
  "wit-bindgen-rust",
  "wit-bindgen-rust-lib",
@@ -4226,18 +4239,20 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.13.2"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a9eb6179c5a26adc38fa5a22e263e7a3812c6777ca2e75d1717fd3789f82b64"
+checksum = "66d9f2d16dd55d1a372dcfd4b7a466ea876682a5a3cb97e71ec9eef04affa876"
 dependencies = [
  "anyhow",
  "bitflags 2.3.3",
  "indexmap 2.0.0",
  "log",
- "wasm-encoder 0.31.1",
- "wasm-metadata 0.10.2",
- "wasmparser 0.111.0",
- "wit-parser 0.10.0",
+ "serde",
+ "serde_json",
+ "wasm-encoder 0.32.0",
+ "wasm-metadata 0.10.3",
+ "wasmparser 0.112.0",
+ "wit-parser 0.11.0",
 ]
 
 [[package]]
@@ -4258,9 +4273,9 @@ dependencies = [
 
 [[package]]
 name = "wit-parser"
-version = "0.10.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8d6926af931f285e206ea71f9b67681f00a65d79097f81da7f9f285de006ba2"
+checksum = "61e8b849bea13cc2315426b16efe6eb6813466d78f5fde69b0bb150c9c40e0dc"
 dependencies = [
  "anyhow",
  "id-arena",
diff --git a/Cargo.toml b/Cargo.toml
index d0838f2e7..1a3620d8f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,6 +42,7 @@ once_cell = { workspace = true }
 listenfd = "1.0.0"
 wat = { workspace = true }
 serde = { workspace = true }
+serde_derive = { workspace = true }
 serde_json = { workspace = true }
 wasmparser = { workspace = true }
 wasm-encoder = { workspace = true }
@@ -205,15 +206,15 @@ is-terminal = "0.4.0"
 wit-bindgen = { version = "0.9.0", default-features = false }
 
 # wasm-tools family:
-wasmparser = "0.111.0"
-wat = "1.0.70"
-wast = "63.0.0"
-wasmprinter = "0.2.63"
-wasm-encoder = "0.31.1"
-wasm-smith = "0.12.14"
-wasm-mutate = "0.2.31"
-wit-parser = "0.10.0"
-wit-component = "0.13.2"
+wasmparser = "0.112.0"
+wat = "1.0.71"
+wast = "64.0.0"
+wasmprinter = "0.2.64"
+wasm-encoder = "0.32.0"
+wasm-smith = "0.12.15"
+wasm-mutate = "0.2.32"
+wit-parser = "0.11.0"
+wit-component = "0.14.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
@@ -235,7 +236,9 @@ async-trait = "0.1.71"
 heck = "0.4"
 similar = "2.1.0"
 toml = "0.5.9"
-serde = "1.0.94"
+# serde and serde_derive must have the same version
+serde = "1.0.188"
+serde_derive = "1.0.188"
 serde_json = "1.0.80"
 glob = "0.3.0"
 libfuzzer-sys = "0.4.0"
diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml
index 15d2a1c6c..195c91628 100644
--- a/cranelift/codegen/Cargo.toml
+++ b/cranelift/codegen/Cargo.toml
@@ -23,7 +23,8 @@ cranelift-control = { workspace = true }
 hashbrown = { workspace = true, features = ["raw"] }
 target-lexicon = { workspace = true }
 log = { workspace = true }
-serde = { version = "1.0.94", features = ["derive"], optional = true }
+serde = { version = "1.0.188", optional = true }
+serde_derive = { version = "1.0.188", optional = true }
 bincode = { version = "1.2.1", optional = true }
 gimli = { workspace = true, features = ["write"], optional = true }
 smallvec = { workspace = true }
@@ -87,6 +88,7 @@ all-arch = [
 # For dependent crates that want to serialize some parts of cranelift
 enable-serde = [
     "serde",
+    "serde_derive",
     "cranelift-entity/enable-serde",
     "regalloc2/enable-serde",
     "smallvec/serde"
diff --git a/cranelift/codegen/meta/src/gen_inst.rs b/cranelift/codegen/meta/src/gen_inst.rs
index 329bff65f..2a6e2030e 100644
--- a/cranelift/codegen/meta/src/gen_inst.rs
+++ b/cranelift/codegen/meta/src/gen_inst.rs
@@ -502,7 +502,7 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
     fmt.line(
         r#"#[cfg_attr(
             feature = "enable-serde",
-            derive(serde::Serialize, serde::Deserialize)
+            derive(serde_derive::Serialize, serde_derive::Deserialize)
         )]"#,
     );
 
diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs
index 2b1f57e0f..9f00b9379 100644
--- a/cranelift/codegen/src/binemit/mod.rs
+++ b/cranelift/codegen/src/binemit/mod.rs
@@ -8,7 +8,7 @@ mod stack_map;
 pub use self::stack_map::StackMap;
 use core::fmt;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Offset in bytes from the beginning of the function.
 ///
diff --git a/cranelift/codegen/src/binemit/stack_map.rs b/cranelift/codegen/src/binemit/stack_map.rs
index b1388e18f..037611e6e 100644
--- a/cranelift/codegen/src/binemit/stack_map.rs
+++ b/cranelift/codegen/src/binemit/stack_map.rs
@@ -67,7 +67,10 @@ const NUM_BITS: usize = core::mem::size_of::<Num>() * 8;
 /// live GC references in these slots. We record the `IncomingArg`s in the
 /// callee's stack map.
 #[derive(Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Deserialize, serde::Serialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Deserialize, serde_derive::Serialize)
+)]
 pub struct StackMap {
     bitmap: Vec<BitSet<Num>>,
     mapped_words: u32,
diff --git a/cranelift/codegen/src/bitset.rs b/cranelift/codegen/src/bitset.rs
index d39661ec2..855d585d7 100644
--- a/cranelift/codegen/src/bitset.rs
+++ b/cranelift/codegen/src/bitset.rs
@@ -12,7 +12,10 @@ use core::ops::{Add, BitOr, Shl, Sub};
 
 /// A small bitset built on a single primitive integer type
 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct BitSet<T>(pub T);
 
 impl<T> BitSet<T>
diff --git a/cranelift/codegen/src/incremental_cache.rs b/cranelift/codegen/src/incremental_cache.rs
index 8c7638e25..6290e55f8 100644
--- a/cranelift/codegen/src/incremental_cache.rs
+++ b/cranelift/codegen/src/incremental_cache.rs
@@ -118,7 +118,7 @@ impl std::fmt::Display for CacheKeyHash {
     }
 }
 
-#[derive(serde::Serialize, serde::Deserialize)]
+#[derive(serde_derive::Serialize, serde_derive::Deserialize)]
 struct CachedFunc {
     // Note: The version marker must be first to ensure deserialization stops in case of a version
     // mismatch before attempting to deserialize the actual compiled code.
@@ -139,7 +139,7 @@ struct CacheKey<'a> {
     parameters: CompileParameters,
 }
 
-#[derive(Clone, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
+#[derive(Clone, PartialEq, Hash, serde_derive::Serialize, serde_derive::Deserialize)]
 struct CompileParameters {
     isa: String,
     triple: String,
diff --git a/cranelift/codegen/src/ir/atomic_rmw_op.rs b/cranelift/codegen/src/ir/atomic_rmw_op.rs
index 9d84c7d0b..0317fc00d 100644
--- a/cranelift/codegen/src/ir/atomic_rmw_op.rs
+++ b/cranelift/codegen/src/ir/atomic_rmw_op.rs
@@ -2,7 +2,7 @@
 use core::fmt::{self, Display, Formatter};
 use core::str::FromStr;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
diff --git a/cranelift/codegen/src/ir/condcodes.rs b/cranelift/codegen/src/ir/condcodes.rs
index ba66dfbc3..e791649bb 100644
--- a/cranelift/codegen/src/ir/condcodes.rs
+++ b/cranelift/codegen/src/ir/condcodes.rs
@@ -8,7 +8,7 @@ use core::fmt::{self, Display, Formatter};
 use core::str::FromStr;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Common traits of condition codes.
 pub trait CondCode: Copy {
diff --git a/cranelift/codegen/src/ir/constant.rs b/cranelift/codegen/src/ir/constant.rs
index 1c540c0c3..637784a27 100644
--- a/cranelift/codegen/src/ir/constant.rs
+++ b/cranelift/codegen/src/ir/constant.rs
@@ -19,7 +19,7 @@ use core::str::{from_utf8, FromStr};
 use cranelift_entity::EntityRef;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// This type describes the actual constant data. Note that the bytes stored in this structure are
 /// expected to be in little-endian order; this is due to ease-of-use when interacting with
diff --git a/cranelift/codegen/src/ir/dfg.rs b/cranelift/codegen/src/ir/dfg.rs
index 064179369..76b1b08cb 100644
--- a/cranelift/codegen/src/ir/dfg.rs
+++ b/cranelift/codegen/src/ir/dfg.rs
@@ -20,7 +20,7 @@ use core::u16;
 
 use alloc::collections::BTreeMap;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use smallvec::SmallVec;
 
 /// Storage for instructions within the DFG.
diff --git a/cranelift/codegen/src/ir/dynamic_type.rs b/cranelift/codegen/src/ir/dynamic_type.rs
index f1ae30982..ef802f90e 100644
--- a/cranelift/codegen/src/ir/dynamic_type.rs
+++ b/cranelift/codegen/src/ir/dynamic_type.rs
@@ -7,7 +7,7 @@ use crate::ir::PrimaryMap;
 use crate::ir::Type;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A dynamic type object which has a base vector type and a scaling factor.
 #[derive(Clone, PartialEq, Hash)]
diff --git a/cranelift/codegen/src/ir/entities.rs b/cranelift/codegen/src/ir/entities.rs
index 3917ff658..f33e198c0 100644
--- a/cranelift/codegen/src/ir/entities.rs
+++ b/cranelift/codegen/src/ir/entities.rs
@@ -23,7 +23,7 @@ use crate::entity::entity_impl;
 use core::fmt;
 use core::u32;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// An opaque reference to a [basic block](https://en.wikipedia.org/wiki/Basic_block) in a
 /// [`Function`](super::function::Function).
diff --git a/cranelift/codegen/src/ir/extfunc.rs b/cranelift/codegen/src/ir/extfunc.rs
index 2df0f890f..cafdb11dc 100644
--- a/cranelift/codegen/src/ir/extfunc.rs
+++ b/cranelift/codegen/src/ir/extfunc.rs
@@ -11,7 +11,7 @@ use alloc::vec::Vec;
 use core::fmt;
 use core::str::FromStr;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 use super::function::FunctionParameters;
 
diff --git a/cranelift/codegen/src/ir/extname.rs b/cranelift/codegen/src/ir/extname.rs
index f6aac3b97..b06eb843f 100644
--- a/cranelift/codegen/src/ir/extname.rs
+++ b/cranelift/codegen/src/ir/extname.rs
@@ -11,7 +11,7 @@ use core::str::FromStr;
 
 use cranelift_entity::EntityRef as _;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 use super::entities::UserExternalNameRef;
 use super::function::FunctionParameters;
diff --git a/cranelift/codegen/src/ir/function.rs b/cranelift/codegen/src/ir/function.rs
index 7572b3f37..f5b85c50a 100644
--- a/cranelift/codegen/src/ir/function.rs
+++ b/cranelift/codegen/src/ir/function.rs
@@ -64,7 +64,10 @@ impl<'de> Deserialize<'de> for VersionMarker {
 /// Function parameters used when creating this function, and that will become applied after
 /// compilation to materialize the final `CompiledCode`.
 #[derive(Clone, PartialEq)]
-#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct FunctionParameters {
     /// The first `SourceLoc` appearing in the function, serving as a base for every relative
     /// source loc in the function.
@@ -146,7 +149,10 @@ impl FunctionParameters {
 /// Additionally, these fields can be the same for two functions that would be compiled the same
 /// way, and finalized by applying `FunctionParameters` onto their `CompiledCodeStencil`.
 #[derive(Clone, PartialEq, Hash)]
-#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct FunctionStencil {
     /// A version marker used to ensure that serialized clif ir is never deserialized with a
     /// different version of Cranelift.
diff --git a/cranelift/codegen/src/ir/globalvalue.rs b/cranelift/codegen/src/ir/globalvalue.rs
index 0faef1120..530875641 100644
--- a/cranelift/codegen/src/ir/globalvalue.rs
+++ b/cranelift/codegen/src/ir/globalvalue.rs
@@ -6,7 +6,7 @@ use crate::isa::TargetIsa;
 use core::fmt;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Information about a global value declaration.
 #[derive(Clone, PartialEq, Hash)]
diff --git a/cranelift/codegen/src/ir/immediates.rs b/cranelift/codegen/src/ir/immediates.rs
index 3b3f70323..9900cb806 100644
--- a/cranelift/codegen/src/ir/immediates.rs
+++ b/cranelift/codegen/src/ir/immediates.rs
@@ -12,7 +12,7 @@ use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Sub};
 use core::str::FromStr;
 use core::{i32, u32};
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Convert a type into a vector of bytes; all implementors in this file must use little-endian
 /// orderings of bytes to match WebAssembly's little-endianness.
diff --git a/cranelift/codegen/src/ir/instructions.rs b/cranelift/codegen/src/ir/instructions.rs
index e90488d22..35607e73e 100644
--- a/cranelift/codegen/src/ir/instructions.rs
+++ b/cranelift/codegen/src/ir/instructions.rs
@@ -12,7 +12,7 @@ use core::ops::{Deref, DerefMut};
 use core::str::FromStr;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 use crate::bitset::BitSet;
 use crate::entity;
diff --git a/cranelift/codegen/src/ir/jumptable.rs b/cranelift/codegen/src/ir/jumptable.rs
index 0f02e3c12..dce347048 100644
--- a/cranelift/codegen/src/ir/jumptable.rs
+++ b/cranelift/codegen/src/ir/jumptable.rs
@@ -10,7 +10,7 @@ use core::fmt::{self, Display, Formatter};
 use core::slice::{Iter, IterMut};
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Contents of a jump table.
 ///
diff --git a/cranelift/codegen/src/ir/known_symbol.rs b/cranelift/codegen/src/ir/known_symbol.rs
index 0dd5274d7..c3d17501a 100644
--- a/cranelift/codegen/src/ir/known_symbol.rs
+++ b/cranelift/codegen/src/ir/known_symbol.rs
@@ -1,7 +1,7 @@
 use core::fmt;
 use core::str::FromStr;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A well-known symbol.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
diff --git a/cranelift/codegen/src/ir/libcall.rs b/cranelift/codegen/src/ir/libcall.rs
index 77a680c93..1e05adcc5 100644
--- a/cranelift/codegen/src/ir/libcall.rs
+++ b/cranelift/codegen/src/ir/libcall.rs
@@ -7,7 +7,7 @@ use crate::{
 use core::fmt;
 use core::str::FromStr;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// The name of a runtime library routine.
 ///
diff --git a/cranelift/codegen/src/ir/memflags.rs b/cranelift/codegen/src/ir/memflags.rs
index 0c073f49b..87165ba69 100644
--- a/cranelift/codegen/src/ir/memflags.rs
+++ b/cranelift/codegen/src/ir/memflags.rs
@@ -3,7 +3,7 @@
 use core::fmt;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 enum FlagBit {
     Notrap,
diff --git a/cranelift/codegen/src/ir/mod.rs b/cranelift/codegen/src/ir/mod.rs
index 91607cf9b..986f80037 100644
--- a/cranelift/codegen/src/ir/mod.rs
+++ b/cranelift/codegen/src/ir/mod.rs
@@ -26,7 +26,7 @@ mod trapcode;
 pub mod types;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 pub use crate::ir::atomic_rmw_op::AtomicRmwOp;
 pub use crate::ir::builder::{
diff --git a/cranelift/codegen/src/ir/sourceloc.rs b/cranelift/codegen/src/ir/sourceloc.rs
index 53331ee8c..6704574d0 100644
--- a/cranelift/codegen/src/ir/sourceloc.rs
+++ b/cranelift/codegen/src/ir/sourceloc.rs
@@ -5,7 +5,7 @@
 
 use core::fmt;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A source location.
 ///
diff --git a/cranelift/codegen/src/ir/stackslot.rs b/cranelift/codegen/src/ir/stackslot.rs
index aa77a7ac7..dfe0109e9 100644
--- a/cranelift/codegen/src/ir/stackslot.rs
+++ b/cranelift/codegen/src/ir/stackslot.rs
@@ -17,7 +17,7 @@ use crate::ir::{DynamicTypeData, GlobalValueData};
 use crate::ir::types::*;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// The size of an object on the stack, or the size of a stack frame.
 ///
diff --git a/cranelift/codegen/src/ir/table.rs b/cranelift/codegen/src/ir/table.rs
index 6acfb14fa..6c6b32a14 100644
--- a/cranelift/codegen/src/ir/table.rs
+++ b/cranelift/codegen/src/ir/table.rs
@@ -5,7 +5,7 @@ use crate::ir::{GlobalValue, Type};
 use core::fmt;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Information about a table declaration.
 #[derive(Clone, PartialEq, Hash)]
diff --git a/cranelift/codegen/src/ir/trapcode.rs b/cranelift/codegen/src/ir/trapcode.rs
index 411f2f2ba..339c331ea 100644
--- a/cranelift/codegen/src/ir/trapcode.rs
+++ b/cranelift/codegen/src/ir/trapcode.rs
@@ -3,7 +3,7 @@
 use core::fmt::{self, Display, Formatter};
 use core::str::FromStr;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A trap code describing the reason for a trap.
 ///
diff --git a/cranelift/codegen/src/ir/types.rs b/cranelift/codegen/src/ir/types.rs
index 5fa6403b5..b1a58c5a2 100644
--- a/cranelift/codegen/src/ir/types.rs
+++ b/cranelift/codegen/src/ir/types.rs
@@ -4,7 +4,7 @@ use core::default::Default;
 use core::fmt::{self, Debug, Display, Formatter};
 use cranelift_codegen_shared::constants;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use target_lexicon::{PointerWidth, Triple};
 
 /// The type of an SSA value.
diff --git a/cranelift/codegen/src/isa/call_conv.rs b/cranelift/codegen/src/isa/call_conv.rs
index eeaf9699c..fea9ff0a4 100644
--- a/cranelift/codegen/src/isa/call_conv.rs
+++ b/cranelift/codegen/src/isa/call_conv.rs
@@ -4,7 +4,7 @@ use core::str;
 use target_lexicon::{CallingConvention, Triple};
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Calling convention identifiers.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/cranelift/codegen/src/isa/riscv64/abi.rs b/cranelift/codegen/src/isa/riscv64/abi.rs
index 8a8c807c1..3009a1e6d 100644
--- a/cranelift/codegen/src/isa/riscv64/abi.rs
+++ b/cranelift/codegen/src/isa/riscv64/abi.rs
@@ -285,7 +285,6 @@ impl ABIMachineSpec for Riscv64MachineDeps {
             insts.extend(Inst::load_constant_u32(
                 writable_spilltmp_reg2(),
                 imm as u64,
-                &mut |_| writable_spilltmp_reg2(),
             ));
             insts.push(Inst::AluRRR {
                 alu_op: AluOPRRR::Add,
@@ -391,11 +390,7 @@ impl ABIMachineSpec for Riscv64MachineDeps {
     }
 
     fn gen_probestack(insts: &mut SmallInstVec<Self::I>, frame_size: u32) {
-        insts.extend(Inst::load_constant_u32(
-            writable_a0(),
-            frame_size as u64,
-            &mut |_| writable_a0(),
-        ));
+        insts.extend(Inst::load_constant_u32(writable_a0(), frame_size as u64));
         insts.push(Inst::Call {
             info: Box::new(CallInfo {
                 dest: ExternalName::LibCall(LibCall::Probestack),
@@ -578,7 +573,7 @@ impl ABIMachineSpec for Riscv64MachineDeps {
         let arg1 = Writable::from_reg(x_reg(11));
         let arg2 = Writable::from_reg(x_reg(12));
         let tmp = alloc_tmp(Self::word_type());
-        insts.extend(Inst::load_constant_u64(tmp, size as u64, &mut alloc_tmp).into_iter());
+        insts.extend(Inst::load_constant_u64(tmp, size as u64).into_iter());
         insts.push(Inst::Call {
             info: Box::new(CallInfo {
                 dest: ExternalName::LibCall(LibCall::Memcpy),
diff --git a/cranelift/codegen/src/isa/riscv64/inst.isle b/cranelift/codegen/src/isa/riscv64/inst.isle
index d2f3933f3..496e9ee10 100644
--- a/cranelift/codegen/src/isa/riscv64/inst.isle
+++ b/cranelift/codegen/src/isa/riscv64/inst.isle
@@ -1517,16 +1517,51 @@
 (decl pure shift_mask (Type) u64)
 (rule (shift_mask ty) (u64_sub (ty_bits (lane_type ty)) 1))
 
-;; for load immediate
+;; Helper for generating a i64 from a pair of Imm20 and Imm12 constants
+(decl i64_generate_imm (Imm20 Imm12) i64)
+(extern extractor i64_generate_imm i64_generate_imm)
+
+
+;; Immediate Loading rules
+;; TODO: Loading the zero reg directly causes a bunch of regalloc errors, we should look into it.
+;; TODO: We can load constants like 0x3ff0000000000000 by loading the bits then doing a shift left.
 (decl imm (Type u64) Reg)
-(extern constructor imm imm)
+
+;; Refs get loaded as integers.
+(rule 4 (imm $R32 c) (imm $I32 c))
+(rule 4 (imm $R64 c) (imm $I64 c))
+
+;; Floats get loaded as integers and then moved into an F register.
+(rule 4 (imm $F32 c) (gen_bitcast (imm $I32 c) $I32 $F32))
+(rule 4 (imm $F64 c) (gen_bitcast (imm $I64 c) $I64 $F64))
+
+;; Try to match just an imm12
+(rule 3 (imm (ty_int ty) c)
+  (if-let (i64_generate_imm (imm20_is_zero) imm12) (i64_sextend_u64 ty c))
+  (rv_addi (zero_reg) imm12))
+
+;; We can also try to load using a single LUI.
+;; LUI takes a 20 bit immediate, places it on bits 13 to 32 of the register.
+;; In RV64 this value is then sign extended to 64bits.
+(rule 2 (imm (ty_int ty) c)
+  (if-let (i64_generate_imm imm20 (imm12_is_zero)) (i64_sextend_u64 ty c))
+  (rv_lui imm20))
+
+;; We can combo addi + lui to represent all 32-bit immediates
+;; And some 64-bit immediates as well.
+(rule 1 (imm (ty_int ty) c)
+  (if-let (i64_generate_imm imm20 imm12) (i64_sextend_u64 ty c))
+  (rv_addi (rv_lui imm20) imm12))
+
+;; Otherwise we fall back to loading the immediate from memory
+;; TODO: This doesen't yet emit the constant into the memory pool, but it would
+;; be pretty neat if it did.
+(rule 0 (imm (ty_int ty) c) (emit_load_const_64 c))
 
 ;; Imm12 Rules
 
 (decl pure imm12_zero () Imm12)
-(rule
-  (imm12_zero)
-  (imm12_const 0))
+(rule (imm12_zero) (imm12_const 0))
 
 (decl pure imm12_const (i32) Imm12)
 (extern constructor imm12_const imm12_const)
@@ -1549,39 +1584,48 @@
 (decl imm12_and (Imm12 u64) Imm12)
 (extern constructor imm12_and imm12_and)
 
-;; Helper for get negative of Imm12
-(decl neg_imm12 (Imm12) Imm12)
-(extern constructor neg_imm12 neg_imm12)
-
 ;; Imm12 Extractors
 
 ;; Helper to go directly from a `Value`, when it's an `iconst`, to an `Imm12`.
 (decl imm12_from_value (Imm12) Value)
-(extractor
-  (imm12_from_value n)
-  (def_inst (iconst (u64_from_imm64 (imm12_from_u64 n)))))
+(extractor (imm12_from_value n) (i64_from_iconst (imm12_from_i64 n)))
 
 (decl imm12_from_u64 (Imm12) u64)
 (extern extractor imm12_from_u64 imm12_from_u64)
 
+(decl imm12_from_i64 (Imm12) i64)
+(extern extractor imm12_from_i64 imm12_from_i64)
+
 (decl pure partial u64_to_imm12 (u64) Imm12)
 (rule (u64_to_imm12 (imm12_from_u64 n)) n)
 
+(decl pure imm12_is_zero () Imm12)
+(extern extractor imm12_is_zero imm12_is_zero)
+
+;; Imm20
+
+;; Extractor that matches if a Imm20 is zero
+(decl pure imm20_is_zero () Imm20)
+(extern extractor imm20_is_zero imm20_is_zero)
+
 
 ;; Imm5 Extractors
 
 (decl imm5_from_u64 (Imm5) u64)
 (extern extractor imm5_from_u64 imm5_from_u64)
 
+(decl imm5_from_i64 (Imm5) i64)
+(extern extractor imm5_from_i64 imm5_from_i64)
+
 ;; Construct a Imm5 from an i8
-(decl pure partial imm5_from_i8 (i8) Imm5)
-(extern constructor imm5_from_i8 imm5_from_i8)
+(decl pure partial i8_to_imm5 (i8) Imm5)
+(extern constructor i8_to_imm5 i8_to_imm5)
 
 ;; Extractor that matches a `Value` equivalent to a replicated Imm5 on all lanes.
 ;; TODO(#6527): Try matching vconst here as well
 (decl replicated_imm5 (Imm5) Value)
 (extractor (replicated_imm5 n)
-  (def_inst (splat (iconst (u64_from_imm64 (imm5_from_u64 n))))))
+  (def_inst (splat (i64_from_iconst (imm5_from_i64 n)))))
 
 ;; UImm5 Helpers
 
@@ -1670,6 +1714,24 @@
             (_ Unit (emit (MInst.AluRRImm12 op dst src (imm12_zero)))))
         dst))
 
+;; Helper for emitting the `LoadConst64` instruction.
+(decl emit_load_const_64 (u64) XReg)
+(rule (emit_load_const_64 imm)
+      (let ((dst WritableXReg (temp_writable_xreg))
+            (_ Unit (emit (MInst.LoadConst64 dst imm))))
+        dst))
+
+;; Helper for emitting the `Lui` instruction.
+;; TODO: This should be something like `emit_u_type`. And should share the
+;; `MInst` with `auipc` since these instructions share the U-Type format.
+(decl rv_lui (Imm20) XReg)
+(rule (rv_lui imm)
+      (let ((dst WritableXReg (temp_writable_xreg))
+            (_ Unit (emit (MInst.Lui dst imm))))
+        dst))
+
+
+
 (decl select_addi (Type) AluOPRRI)
 (rule 1 (select_addi (fits_in_32 ty)) (AluOPRRI.Addiw))
 (rule (select_addi (fits_in_64 ty)) (AluOPRRI.Addi))
@@ -1989,7 +2051,7 @@
 (rule 3 (extend val (ExtendOp.Zero) (fits_in_64 from_ty) $I128)
   (let ((val XReg (value_regs_get val 0))
         (low XReg (zext val from_ty $I64))
-        (high XReg (load_u64_constant 0)))
+        (high XReg (imm $I64 0)))
     (value_regs low high)))
 
 ;; Catch all rule for ignoring extensions of the same type.
@@ -2127,7 +2189,7 @@
 (rule (gen_bseti val bit)
   (if-let $false (has_zbs))
   (if-let $false (u64_le bit 12))
-  (let ((const XReg (load_u64_constant (u64_shl 1 bit))))
+  (let ((const XReg (imm $I64 (u64_shl 1 bit))))
     (rv_or val const)))
 
 (rule (gen_bseti val bit)
@@ -2169,7 +2231,7 @@
       (high XReg (lower_popcnt (value_regs_get a 1) $I64))
       ;; add toghter.
       (result XReg (rv_add low high)))
-    (value_regs result (load_u64_constant 0))))
+    (value_regs result (imm $I64 0))))
 
 (decl lower_i128_rotl (ValueRegs ValueRegs) ValueRegs)
 (rule
@@ -2190,7 +2252,7 @@
       (high_part3 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) high_part2))
       (high XReg (rv_or high_part1 high_part3))
       ;;
-      (const64 XReg (load_u64_constant 64))
+      (const64 XReg (imm $I64 64))
       (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
     ;; right now we only rotate less than 64 bits.
     ;; if shamt is greater than or equal 64 , we should switch low and high.
@@ -2220,7 +2282,7 @@
       (high XReg (rv_or high_part1 high_part3))
 
       ;;
-      (const64 XReg (load_u64_constant 64))
+      (const64 XReg (imm $I64 64))
       (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
     ;; right now we only rotate less than 64 bits.
     ;; if shamt is greater than or equal 64 , we should switch low and high.
@@ -2402,10 +2464,6 @@
 (decl gen_select_reg (IntCC XReg XReg Reg Reg) Reg)
 (extern constructor gen_select_reg gen_select_reg)
 
-;; load a constant into reg.
-(decl load_u64_constant (u64) Reg)
-(extern constructor load_u64_constant load_u64_constant)
-
 ;;; clone WritableReg
 ;;; if not rust compiler will complain about use moved value.
 (decl vec_writable_clone (VecWritableReg) VecWritableReg)
@@ -2733,8 +2791,8 @@
 (rule
   (gen_div_overflow rs1 rs2 ty)
   (let
-    ((r_const_neg_1 XReg (load_imm12 -1))
-      (r_const_min XReg (rv_slli (load_imm12 1) (imm12_const 63)))
+    ((r_const_neg_1 XReg (imm $I64 (i64_as_u64 -1)))
+      (r_const_min XReg (rv_slli (imm $I64 1) (imm12_const 63)))
       (tmp_rs1 XReg (shift_int_to_most_significant rs1 ty))
       (t1 XReg (gen_icmp (IntCC.Equal) r_const_neg_1 rs2 ty))
       (t2 XReg (gen_icmp (IntCC.Equal) r_const_min tmp_rs1 ty))
diff --git a/cranelift/codegen/src/isa/riscv64/inst/emit.rs b/cranelift/codegen/src/isa/riscv64/inst/emit.rs
index e15d64131..82f7ee79d 100644
--- a/cranelift/codegen/src/isa/riscv64/inst/emit.rs
+++ b/cranelift/codegen/src/isa/riscv64/inst/emit.rs
@@ -177,18 +177,6 @@ impl MachInstEmitState<Inst> for EmitState {
 }
 
 impl Inst {
-    /// construct a "imm - rs".
-    pub(crate) fn construct_imm_sub_rs(rd: Writable<Reg>, imm: u64, rs: Reg) -> SmallInstVec<Inst> {
-        let mut insts = Inst::load_constant_u64(rd, imm, &mut |_| rd);
-        insts.push(Inst::AluRRR {
-            alu_op: AluOPRRR::Sub,
-            rd,
-            rs1: rd.to_reg(),
-            rs2: rs,
-        });
-        insts
-    }
-
     /// Load int mask.
     /// If ty is int then 0xff in rd.
     pub(crate) fn load_int_mask(rd: Writable<Reg>, ty: Type) -> SmallInstVec<Inst> {
@@ -676,7 +664,7 @@ impl MachInstEmit for Inst {
 
                 let base = from.get_base_register();
                 let offset = from.get_offset_with_state(state);
-                let offset_imm12 = Imm12::maybe_from_u64(offset as u64);
+                let offset_imm12 = Imm12::maybe_from_i64(offset);
 
                 let (addr, imm12) = match (base, offset_imm12) {
                     // If the offset fits into an imm12 we can directly encode it.
@@ -703,7 +691,7 @@ impl MachInstEmit for Inst {
 
                 let base = to.get_base_register();
                 let offset = to.get_offset_with_state(state);
-                let offset_imm12 = Imm12::maybe_from_u64(offset as u64);
+                let offset_imm12 = Imm12::maybe_from_i64(offset);
 
                 let (addr, imm12) = match (base, offset_imm12) {
                     // If the offset fits into an imm12 we can directly encode it.
@@ -785,7 +773,7 @@ impl MachInstEmit for Inst {
                     .for_each(|i| i.emit(&[], sink, emit_info, state));
             }
             &Inst::AdjustSp { amount } => {
-                if let Some(imm) = Imm12::maybe_from_u64(amount as u64) {
+                if let Some(imm) = Imm12::maybe_from_i64(amount) {
                     Inst::AluRRImm12 {
                         alu_op: AluOPRRI::Addi,
                         rd: writable_stack_reg(),
@@ -795,7 +783,7 @@ impl MachInstEmit for Inst {
                     .emit(&[], sink, emit_info, state);
                 } else {
                     let tmp = writable_spilltmp_reg();
-                    let mut insts = Inst::load_constant_u64(tmp, amount as u64, &mut |_| tmp);
+                    let mut insts = Inst::load_constant_u64(tmp, amount as u64);
                     insts.push(Inst::AluRRR {
                         alu_op: AluOPRRR::Add,
                         rd: writable_stack_reg(),
@@ -1119,7 +1107,7 @@ impl MachInstEmit for Inst {
                 // Check if the index passed in is larger than the number of jumptable
                 // entries that we have. If it is, we fallthrough to a jump into the
                 // default block.
-                Inst::load_constant_u32(tmp2, targets.len() as u64, &mut |_| tmp2)
+                Inst::load_constant_u32(tmp2, targets.len() as u64)
                     .iter()
                     .for_each(|i| i.emit(&[], sink, emit_info, state));
                 Inst::CondBr {
@@ -1264,7 +1252,7 @@ impl MachInstEmit for Inst {
 
                 let base = mem.get_base_register();
                 let offset = mem.get_offset_with_state(state);
-                let offset_imm12 = Imm12::maybe_from_u64(offset as u64);
+                let offset_imm12 = Imm12::maybe_from_i64(offset);
 
                 match (mem, base, offset_imm12) {
                     (_, Some(rs), Some(imm12)) => {
@@ -1914,7 +1902,6 @@ impl MachInstEmit for Inst {
                             // I8
                             (u8::MAX >> 1) as u64
                         },
-                        &mut |_| writable_spilltmp_reg2(),
                     )
                     .into_iter()
                     .for_each(|x| x.emit(&[], sink, emit_info, state));
@@ -2791,14 +2778,10 @@ impl MachInstEmit for Inst {
                 tmp: guard_size_tmp,
             } => {
                 let step = writable_spilltmp_reg();
-                Inst::load_constant_u64(
-                    step,
-                    (guard_size as u64) * (probe_count as u64),
-                    &mut |_| step,
-                )
-                .iter()
-                .for_each(|i| i.emit(&[], sink, emit_info, state));
-                Inst::load_constant_u64(guard_size_tmp, guard_size as u64, &mut |_| guard_size_tmp)
+                Inst::load_constant_u64(step, (guard_size as u64) * (probe_count as u64))
+                    .iter()
+                    .for_each(|i| i.emit(&[], sink, emit_info, state));
+                Inst::load_constant_u64(guard_size_tmp, guard_size as u64)
                     .iter()
                     .for_each(|i| i.emit(&[], sink, emit_info, state));
 
@@ -3205,7 +3188,7 @@ fn emit_return_call_common_sequence(
         alu_op: AluOPRRI::Addi,
         rd: regs::writable_stack_reg(),
         rs: regs::fp_reg(),
-        imm12: Imm12::maybe_from_u64(fp_to_callee_sp as u64).unwrap(),
+        imm12: Imm12::maybe_from_i64(fp_to_callee_sp).unwrap(),
     }
     .emit(&[], sink, emit_info, state);
 
diff --git a/cranelift/codegen/src/isa/riscv64/inst/imms.rs b/cranelift/codegen/src/isa/riscv64/inst/imms.rs
index 2f9b544b1..93c2d9640 100644
--- a/cranelift/codegen/src/isa/riscv64/inst/imms.rs
+++ b/cranelift/codegen/src/isa/riscv64/inst/imms.rs
@@ -13,22 +13,19 @@ pub struct Imm12 {
 impl Imm12 {
     pub(crate) const FALSE: Self = Self { bits: 0 };
     pub(crate) const TRUE: Self = Self { bits: 1 };
+
     pub fn maybe_from_u64(val: u64) -> Option<Imm12> {
-        let sign_bit = 1 << 11;
-        if val == 0 {
-            Some(Imm12 { bits: 0 })
-        } else if (val & sign_bit) != 0 && (val >> 12) == 0xffff_ffff_ffff_f {
-            Some(Imm12 {
-                bits: (val & 0xffff) as i16,
-            })
-        } else if (val & sign_bit) == 0 && (val >> 12) == 0 {
-            Some(Imm12 {
-                bits: (val & 0xffff) as i16,
-            })
+        Self::maybe_from_i64(val as i64)
+    }
+
+    pub fn maybe_from_i64(val: i64) -> Option<Imm12> {
+        if val >= -2048 && val <= 2047 {
+            Some(Imm12 { bits: val as i16 })
         } else {
             None
         }
     }
+
     #[inline]
     pub fn from_bits(bits: i16) -> Self {
         Self { bits: bits & 0xfff }
@@ -81,6 +78,7 @@ impl Imm20 {
             bits: bits & 0xf_ffff,
         }
     }
+
     #[inline]
     pub fn as_u32(&self) -> u32 {
         (self.bits as u32) & 0xf_ffff
@@ -178,14 +176,10 @@ impl Inst {
     ///
     /// `value` must be between `imm_min()` and `imm_max()`, or else
     /// this helper returns `None`.
-    pub(crate) fn generate_imm<R>(
-        value: u64,
-        mut handle_imm: impl FnMut(Option<Imm20>, Option<Imm12>) -> R,
-    ) -> Option<R> {
+    pub(crate) fn generate_imm(value: u64) -> Option<(Imm20, Imm12)> {
         if let Some(imm12) = Imm12::maybe_from_u64(value) {
             // can be load using single imm12.
-            let r = handle_imm(None, Some(imm12));
-            return Some(r);
+            return Some((Imm20::from_bits(0), imm12));
         }
         let value = value as i64;
         if !(value >= Self::imm_min() && value <= Self::imm_max()) {
@@ -217,17 +211,9 @@ impl Inst {
         };
         assert!(imm20 >= -(0x7_ffff + 1) && imm20 <= 0x7_ffff);
         assert!(imm20 != 0 || imm12 != 0);
-        Some(handle_imm(
-            if imm20 != 0 {
-                Some(Imm20::from_bits(imm20 as i32))
-            } else {
-                None
-            },
-            if imm12 != 0 {
-                Some(Imm12::from_bits(imm12 as i16))
-            } else {
-                None
-            },
+        Some((
+            Imm20::from_bits(imm20 as i32),
+            Imm12::from_bits(imm12 as i16),
         ))
     }
 }
diff --git a/cranelift/codegen/src/isa/riscv64/inst/mod.rs b/cranelift/codegen/src/isa/riscv64/inst/mod.rs
index 0939f61f3..d63227854 100644
--- a/cranelift/codegen/src/isa/riscv64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/riscv64/inst/mod.rs
@@ -195,23 +195,23 @@ impl Inst {
     }
 
     /// Immediates can be loaded using lui and addi instructions.
-    fn load_const_imm<F: FnMut(Type) -> Writable<Reg>>(
-        rd: Writable<Reg>,
-        value: u64,
-        alloc_tmp: &mut F,
-    ) -> Option<SmallInstVec<Inst>> {
-        Inst::generate_imm(value, |imm20, imm12| {
+    fn load_const_imm(rd: Writable<Reg>, value: u64) -> Option<SmallInstVec<Inst>> {
+        Inst::generate_imm(value).map(|(imm20, imm12)| {
             let mut insts = SmallVec::new();
 
-            let rs = if let Some(imm) = imm20 {
-                let rd = if imm12.is_some() { alloc_tmp(I64) } else { rd };
-                insts.push(Inst::Lui { rd, imm });
+            let imm20_is_zero = imm20.as_u32() == 0;
+            let imm12_is_zero = imm12.as_i16() == 0;
+
+            let rs = if !imm20_is_zero {
+                insts.push(Inst::Lui { rd, imm: imm20 });
                 rd.to_reg()
             } else {
                 zero_reg()
             };
 
-            if let Some(imm12) = imm12 {
+            // We also need to emit the addi if the value is 0, otherwise we just
+            // won't produce any instructions.
+            if !imm12_is_zero || (imm20_is_zero && imm12_is_zero) {
                 insts.push(Inst::AluRRImm12 {
                     alu_op: AluOPRRI::Addi,
                     rd,
@@ -224,12 +224,8 @@ impl Inst {
         })
     }
 
-    pub(crate) fn load_constant_u32<F: FnMut(Type) -> Writable<Reg>>(
-        rd: Writable<Reg>,
-        value: u64,
-        alloc_tmp: &mut F,
-    ) -> SmallInstVec<Inst> {
-        let insts = Inst::load_const_imm(rd, value, alloc_tmp);
+    pub(crate) fn load_constant_u32(rd: Writable<Reg>, value: u64) -> SmallInstVec<Inst> {
+        let insts = Inst::load_const_imm(rd, value);
         insts.unwrap_or_else(|| {
             smallvec![Inst::LoadConst32 {
                 rd,
@@ -238,12 +234,8 @@ impl Inst {
         })
     }
 
-    pub fn load_constant_u64<F: FnMut(Type) -> Writable<Reg>>(
-        rd: Writable<Reg>,
-        value: u64,
-        alloc_tmp: &mut F,
-    ) -> SmallInstVec<Inst> {
-        let insts = Inst::load_const_imm(rd, value, alloc_tmp);
+    pub fn load_constant_u64(rd: Writable<Reg>, value: u64) -> SmallInstVec<Inst> {
+        let insts = Inst::load_const_imm(rd, value);
         insts.unwrap_or_else(|| smallvec![Inst::LoadConst64 { rd, imm: value }])
     }
 
@@ -252,19 +244,20 @@ impl Inst {
         tmp: Writable<Reg>,
         offset: i64,
     ) -> [Inst; 2] {
-        Inst::generate_imm(offset as u64, |imm20, imm12| {
-            let a = Inst::Auipc {
-                rd: tmp,
-                imm: imm20.unwrap_or_default(),
-            };
-            let b = Inst::Jalr {
-                rd: link.unwrap_or(writable_zero_reg()),
-                base: tmp.to_reg(),
-                offset: imm12.unwrap_or_default(),
-            };
-            [a, b]
-        })
-        .expect("code range is too big.")
+        Inst::generate_imm(offset as u64)
+            .map(|(imm20, imm12)| {
+                let a = Inst::Auipc {
+                    rd: tmp,
+                    imm: imm20,
+                };
+                let b = Inst::Jalr {
+                    rd: link.unwrap_or(writable_zero_reg()),
+                    base: tmp.to_reg(),
+                    offset: imm12,
+                };
+                [a, b]
+            })
+            .expect("code range is too big.")
     }
 
     /// Create instructions that load a 32-bit floating-point constant.
@@ -275,11 +268,7 @@ impl Inst {
     ) -> SmallVec<[Inst; 4]> {
         let mut insts = SmallVec::new();
         let tmp = alloc_tmp(I64);
-        insts.extend(Self::load_constant_u32(
-            tmp,
-            const_data as u64,
-            &mut alloc_tmp,
-        ));
+        insts.extend(Self::load_constant_u32(tmp, const_data as u64));
         insts.push(Inst::FpuRR {
             frm: None,
             alu_op: FpuOPRR::move_x_to_f_op(F32),
@@ -297,7 +286,7 @@ impl Inst {
     ) -> SmallVec<[Inst; 4]> {
         let mut insts = SmallInstVec::new();
         let tmp = alloc_tmp(I64);
-        insts.extend(Self::load_constant_u64(tmp, const_data, &mut alloc_tmp));
+        insts.extend(Self::load_constant_u64(tmp, const_data));
         insts.push(Inst::FpuRR {
             frm: None,
             alu_op: FpuOPRR::move_x_to_f_op(F64),
@@ -2071,22 +2060,21 @@ impl LabelUse {
             }
             LabelUse::PCRel32 => {
                 let insn2 = u32::from_le_bytes([buffer[4], buffer[5], buffer[6], buffer[7]]);
-                Inst::generate_imm(offset as u64, |imm20, imm12| {
-                    let imm20 = imm20.unwrap_or_default();
-                    let imm12 = imm12.unwrap_or_default();
-                    // Encode the OR-ed-in value with zero_reg(). The
-                    // register parameter must be in the original
-                    // encoded instruction and or'ing in zeroes does not
-                    // change it.
-                    buffer[0..4].clone_from_slice(&u32::to_le_bytes(
-                        insn | enc_auipc(writable_zero_reg(), imm20),
-                    ));
-                    buffer[4..8].clone_from_slice(&u32::to_le_bytes(
-                        insn2 | enc_jalr(writable_zero_reg(), zero_reg(), imm12),
-                    ));
-                })
-                // expect make sure we handled.
-                .expect("we have check the range before,this is a compiler error.");
+                Inst::generate_imm(offset as u64)
+                    .map(|(imm20, imm12)| {
+                        // Encode the OR-ed-in value with zero_reg(). The
+                        // register parameter must be in the original
+                        // encoded instruction and or'ing in zeroes does not
+                        // change it.
+                        buffer[0..4].clone_from_slice(&u32::to_le_bytes(
+                            insn | enc_auipc(writable_zero_reg(), imm20),
+                        ));
+                        buffer[4..8].clone_from_slice(&u32::to_le_bytes(
+                            insn2 | enc_jalr(writable_zero_reg(), zero_reg(), imm12),
+                        ));
+                    })
+                    // expect make sure we handled.
+                    .expect("we have check the range before,this is a compiler error.");
             }
 
             LabelUse::B12 => {
diff --git a/cranelift/codegen/src/isa/riscv64/inst_vector.isle b/cranelift/codegen/src/isa/riscv64/inst_vector.isle
index cadf4911f..dc0618aec 100644
--- a/cranelift/codegen/src/isa/riscv64/inst_vector.isle
+++ b/cranelift/codegen/src/isa/riscv64/inst_vector.isle
@@ -807,7 +807,7 @@
 ;; This is just a mnemonic for `vxor.vi vd, vs, -1`
 (decl rv_vnot_v (VReg VecOpMasking VState) VReg)
 (rule (rv_vnot_v vs2 mask vstate)
-  (if-let neg1 (imm5_from_i8 -1))
+  (if-let neg1 (i8_to_imm5 -1))
   (rv_vxor_vi vs2 neg1 mask vstate))
 
 ;; Helper for emitting the `vmax.vv` instruction.
@@ -1505,8 +1505,8 @@
 ;; lanes are set to all zeros.
 (decl gen_expand_mask (Type VReg) VReg)
 (rule (gen_expand_mask ty mask)
-  (if-let zero (imm5_from_i8 0))
-  (if-let neg1 (imm5_from_i8 -1))
+  (if-let zero (i8_to_imm5 0))
+  (if-let neg1 (i8_to_imm5 -1))
   (rv_vmerge_vim (rv_vmv_vi zero ty) neg1 mask ty))
 
 
diff --git a/cranelift/codegen/src/isa/riscv64/lower.isle b/cranelift/codegen/src/isa/riscv64/lower.isle
index d7cff6273..66aa3abd5 100644
--- a/cranelift/codegen/src/isa/riscv64/lower.isle
+++ b/cranelift/codegen/src/isa/riscv64/lower.isle
@@ -156,7 +156,7 @@
   (if-let $true (ty_equal (lane_type in_ty) sext_ty))
   (rv_vwadd_vx x y (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
 
-(rule 14 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (sextend x @ (value_type sext_ty)))
+(rule 15 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (sextend x @ (value_type sext_ty)))
                                                             (swiden_low y @ (value_type in_ty)))))
   (if-let $true (ty_equal (lane_type in_ty) sext_ty))
   (rv_vwadd_vx y x (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
@@ -179,7 +179,7 @@
   (if-let $true (ty_equal (lane_type in_ty) sext_ty))
   (rv_vwadd_vx (gen_slidedown_half in_ty x) y (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
 
-(rule 14 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (sextend x @ (value_type sext_ty)))
+(rule 15 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (sextend x @ (value_type sext_ty)))
                                                             (swiden_high y @ (value_type in_ty)))))
   (if-let $true (ty_equal (lane_type in_ty) sext_ty))
   (rv_vwadd_vx (gen_slidedown_half in_ty y) x (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
@@ -201,7 +201,7 @@
   (if-let $true (ty_equal (lane_type in_ty) uext_ty))
   (rv_vwaddu_vx x y (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
 
-(rule 14 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (uextend x @ (value_type uext_ty)))
+(rule 15 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (uextend x @ (value_type uext_ty)))
                                                             (uwiden_low y @ (value_type in_ty)))))
   (if-let $true (ty_equal (lane_type in_ty) uext_ty))
   (rv_vwaddu_vx y x (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
@@ -224,7 +224,7 @@
   (if-let $true (ty_equal (lane_type in_ty) uext_ty))
   (rv_vwaddu_vx (gen_slidedown_half in_ty x) y (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
 
-(rule 14 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (uextend y @ (value_type uext_ty)))
+(rule 15 (lower (has_type (ty_vec_fits_in_register _) (iadd (splat (uextend y @ (value_type uext_ty)))
                                                             (uwiden_high x @ (value_type in_ty)))))
   (if-let $true (ty_equal (lane_type in_ty) uext_ty))
   (rv_vwaddu_vx (gen_slidedown_half in_ty x) y (unmasked) (vstate_mf2 (ty_half_lanes in_ty))))
@@ -888,7 +888,7 @@
         (high_part3 XReg (rv_sll (value_regs_get x 1) shamt))
         (high XReg (rv_or high_part2 high_part3))
         ;;
-        (const64 XReg (load_u64_constant 64))
+        (const64 XReg (imm $I64 64))
         (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
     (value_regs
       (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 (zero_reg) low)
@@ -940,7 +940,7 @@
         (low_part3 XReg (rv_srl (value_regs_get x 0) shamt))
         (low XReg (rv_or low_part2 low_part3))
         ;;
-        (const64 XReg (load_u64_constant 64))
+        (const64 XReg (imm $I64 64))
         ;;
         (high XReg (rv_srl (value_regs_get x 1) shamt))
         (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
@@ -994,14 +994,14 @@
         (low_part3 XReg (rv_srl (value_regs_get x 0) shamt))
         (low XReg (rv_or low_part2 low_part3))
         ;;
-        (const64 XReg (load_u64_constant 64))
+        (const64 XReg (imm $I64 64))
         ;;
         (high XReg (rv_sra (value_regs_get x 1) shamt))
         ;;
-        (const_neg_1 XReg (load_imm12 -1))
+        (const_neg_1 XReg (imm $I64 (i64_as_u64 -1)))
         ;;
         (high_replacement XReg (gen_select_reg (IntCC.SignedLessThan) (value_regs_get x 1) (zero_reg) const_neg_1 (zero_reg)))
-        (const64 XReg (load_u64_constant 64))
+        (const64 XReg (imm $I64 64))
         (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
     (value_regs
       (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high low)
@@ -1773,7 +1773,7 @@
 ;; If we are inserting from an Imm5 const we can use the immediate
 ;; variant of vmerge.
 (rule 2 (lower (insertlane vec @ (value_type (ty_vec_fits_in_register ty))
-                           (iconst (u64_from_imm64 (imm5_from_u64 imm)))
+                           (i64_from_iconst (imm5_from_i64 imm))
                            (u8_from_uimm8 lane)))
   (let ((mask VReg (gen_vec_mask (u64_shl 1 lane))))
     (rv_vmerge_vim vec imm mask ty)))
@@ -1854,7 +1854,7 @@
 ;; The reduce operation leaves the result in the lowest lane, we then move it
 ;; into the destination X register.
 (rule (lower (vall_true x @ (value_type (ty_vec_fits_in_register ty))))
-  (if-let one (imm5_from_i8 1))
+  (if-let one (i8_to_imm5 1))
   ;; We don't need to broadcast the immediate into all lanes, only into lane 0.
   ;; I did it this way since it uses one less instruction than with a vmv.s.x.
   (let ((fixed VReg (rv_vmv_vi one ty))
@@ -1912,7 +1912,7 @@
 ;; vrgather will insert a 0 for lanes that are out of bounds, so we can let it load
 ;; negative and out of bounds indexes.
 (rule (lower (has_type (ty_vec_fits_in_register ty @ $I8X16) (shuffle x y (vconst_from_immediate mask))))
-  (if-let neg16 (imm5_from_i8 -16))
+  (if-let neg16 (i8_to_imm5 -16))
   (let ((x_mask VReg (gen_constant ty mask))
         (x_lanes VReg (rv_vrgather_vv x x_mask (unmasked) ty))
         (y_mask VReg (rv_vadd_vi x_mask neg16 (unmasked) ty))
diff --git a/cranelift/codegen/src/isa/riscv64/lower/isle.rs b/cranelift/codegen/src/isa/riscv64/lower/isle.rs
index e29168398..eb3090400 100644
--- a/cranelift/codegen/src/isa/riscv64/lower/isle.rs
+++ b/cranelift/codegen/src/isa/riscv64/lower/isle.rs
@@ -14,7 +14,7 @@ use crate::isa::riscv64::lower::args::{
 };
 use crate::isa::riscv64::Riscv64Backend;
 use crate::machinst::Reg;
-use crate::machinst::{isle::*, MachInst, SmallInstVec};
+use crate::machinst::{isle::*, MachInst};
 use crate::machinst::{VCodeConstant, VCodeConstantData};
 use crate::{
     ir::{
@@ -60,13 +60,6 @@ impl<'a, 'b> RV64IsleContext<'a, 'b, MInst, Riscv64Backend> {
             min_vec_reg_size: backend.isa_flags.min_vec_reg_size(),
         }
     }
-
-    #[inline]
-    fn emit_list(&mut self, list: &SmallInstVec<MInst>) {
-        for i in list {
-            self.lower_ctx.emit(i.clone());
-        }
-    }
 }
 
 impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend> {
@@ -287,17 +280,10 @@ impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend>
         }
     }
 
-    fn imm(&mut self, ty: Type, val: u64) -> Reg {
-        let tmp = self.temp_writable_reg(ty);
-        let alloc_tmp = &mut |ty| self.temp_writable_reg(ty);
-        let insts = match ty {
-            F32 => MInst::load_fp_constant32(tmp, val as u32, alloc_tmp),
-            F64 => MInst::load_fp_constant64(tmp, val, alloc_tmp),
-            _ => MInst::load_constant_u64(tmp, val, alloc_tmp),
-        };
-        self.emit_list(&insts);
-        tmp.to_reg()
+    fn i64_generate_imm(&mut self, imm: i64) -> Option<(Imm20, Imm12)> {
+        MInst::generate_imm(imm as u64)
     }
+
     #[inline]
     fn emit(&mut self, arg0: &MInst) -> Unit {
         self.lower_ctx.emit(arg0.clone());
@@ -306,12 +292,38 @@ impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend>
     fn imm12_from_u64(&mut self, arg0: u64) -> Option<Imm12> {
         Imm12::maybe_from_u64(arg0)
     }
+    #[inline]
+    fn imm12_from_i64(&mut self, arg0: i64) -> Option<Imm12> {
+        Imm12::maybe_from_i64(arg0)
+    }
+    #[inline]
+    fn imm12_is_zero(&mut self, imm: Imm12) -> Option<()> {
+        if imm.as_u32() == 0 {
+            Some(())
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn imm20_is_zero(&mut self, imm: Imm20) -> Option<()> {
+        if imm.as_u32() == 0 {
+            Some(())
+        } else {
+            None
+        }
+    }
+
     #[inline]
     fn imm5_from_u64(&mut self, arg0: u64) -> Option<Imm5> {
         Imm5::maybe_from_i8(i8::try_from(arg0 as i64).ok()?)
     }
     #[inline]
-    fn imm5_from_i8(&mut self, arg0: i8) -> Option<Imm5> {
+    fn imm5_from_i64(&mut self, arg0: i64) -> Option<Imm5> {
+        Imm5::maybe_from_i8(i8::try_from(arg0).ok()?)
+    }
+    #[inline]
+    fn i8_to_imm5(&mut self, arg0: i8) -> Option<Imm5> {
         Imm5::maybe_from_i8(arg0)
     }
     #[inline]
@@ -331,10 +343,6 @@ impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend>
         writable_zero_reg()
     }
     #[inline]
-    fn neg_imm12(&mut self, arg0: Imm12) -> Imm12 {
-        -arg0
-    }
-    #[inline]
     fn zero_reg(&mut self) -> Reg {
         zero_reg()
     }
@@ -344,7 +352,7 @@ impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend>
     }
     #[inline]
     fn imm_from_neg_bits(&mut self, val: i64) -> Imm12 {
-        Imm12::maybe_from_u64(val as u64).unwrap()
+        Imm12::maybe_from_i64(val).unwrap()
     }
 
     fn gen_default_frm(&mut self) -> OptionFloatRoundingMode {
@@ -364,26 +372,20 @@ impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend>
         });
         rd.to_reg()
     }
-    fn load_u64_constant(&mut self, val: u64) -> Reg {
-        let rd = self.temp_writable_reg(I64);
-        MInst::load_constant_u64(rd, val, &mut |ty| self.temp_writable_reg(ty))
-            .iter()
-            .for_each(|i| self.emit(i));
-        rd.to_reg()
-    }
+
     fn u8_as_i32(&mut self, x: u8) -> i32 {
         x as i32
     }
 
     fn imm12_const(&mut self, val: i32) -> Imm12 {
-        if let Some(res) = Imm12::maybe_from_u64(val as u64) {
+        if let Some(res) = Imm12::maybe_from_i64(val as i64) {
             res
         } else {
             panic!("Unable to make an Imm12 value from {}", val)
         }
     }
     fn imm12_const_add(&mut self, val: i32, add: i32) -> Imm12 {
-        Imm12::maybe_from_u64((val + add) as u64).unwrap()
+        Imm12::maybe_from_i64((val + add) as i64).unwrap()
     }
 
     //
diff --git a/cranelift/codegen/src/isa/unwind.rs b/cranelift/codegen/src/isa/unwind.rs
index bf4561e84..b5269b323 100644
--- a/cranelift/codegen/src/isa/unwind.rs
+++ b/cranelift/codegen/src/isa/unwind.rs
@@ -3,7 +3,7 @@
 use crate::machinst::RealReg;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 #[cfg(feature = "unwind")]
 pub mod systemv;
diff --git a/cranelift/codegen/src/isa/unwind/systemv.rs b/cranelift/codegen/src/isa/unwind/systemv.rs
index e2c2a381a..1e5ae9372 100644
--- a/cranelift/codegen/src/isa/unwind/systemv.rs
+++ b/cranelift/codegen/src/isa/unwind/systemv.rs
@@ -8,7 +8,7 @@ use alloc::vec::Vec;
 use gimli::write::{Address, FrameDescriptionEntry};
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 type Register = u16;
 
diff --git a/cranelift/codegen/src/isa/unwind/winx64.rs b/cranelift/codegen/src/isa/unwind/winx64.rs
index 349b94cfe..de87251f7 100644
--- a/cranelift/codegen/src/isa/unwind/winx64.rs
+++ b/cranelift/codegen/src/isa/unwind/winx64.rs
@@ -4,7 +4,7 @@ use crate::result::{CodegenError, CodegenResult};
 use alloc::vec::Vec;
 use log::warn;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 use crate::binemit::CodeOffset;
 use crate::isa::unwind::UnwindInst;
diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle
index cc5e91460..e6a7fc384 100644
--- a/cranelift/codegen/src/isa/x64/inst.isle
+++ b/cranelift/codegen/src/isa/x64/inst.isle
@@ -3327,12 +3327,6 @@
       (if-let $true (use_avx))
       (xmm_rmir_vex (AvxOpcode.Vdivpd) src1 src2))
 
-;; Helper for creating `blendvp{d,s}` and `pblendvb` instructions.
-(decl x64_blend (Type Xmm XmmMem Xmm) Xmm)
-(rule 1 (x64_blend $F32X4 mask src1 src2) (x64_blendvps src2 src1 mask))
-(rule 1 (x64_blend $F64X2 mask src1 src2) (x64_blendvpd src2 src1 mask))
-(rule 0 (x64_blend (multi_lane _ _) mask src1 src2) (x64_pblendvb src2 src1 mask))
-
 ;; Helper for creating `blendvpd` instructions.
 (decl x64_blendvpd (Xmm XmmMem Xmm) Xmm)
 (rule 0 (x64_blendvpd src1 src2 mask)
diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle
index ee33d5681..bf391a50e 100644
--- a/cranelift/codegen/src/isa/x64/lower.isle
+++ b/cranelift/codegen/src/isa/x64/lower.isle
@@ -300,7 +300,8 @@
 
 ;; `i128`.
 
-(rule 7 (lower (has_type $I128 (band x y)))
+(decl and_i128 (ValueRegs ValueRegs) ValueRegs)
+(rule (and_i128 x y)
       (let ((x_regs ValueRegs x)
             (x_lo Gpr (value_regs_get_gpr x_regs 0))
             (x_hi Gpr (value_regs_get_gpr x_regs 1))
@@ -310,6 +311,9 @@
         (value_gprs (x64_and $I64 x_lo y_lo)
                     (x64_and $I64 x_hi y_hi))))
 
+(rule 7 (lower (has_type $I128 (band x y)))
+      (and_i128 x y))
+
 ;; Specialized lowerings for `(band x (bnot y))` which is additionally produced
 ;; by Cranelift's `band_not` instruction that is legalized into the simpler
 ;; forms early on.
@@ -1370,10 +1374,7 @@
                                     if_false)))
       (if-let $true (use_sse41))
       (if (all_ones_or_all_zeros condition))
-      (x64_blend ty
-                 condition
-                 if_true
-                 if_false))
+      (x64_pblendvb if_false if_true condition))
 
 (decl pure partial all_ones_or_all_zeros (Value) bool)
 (rule (all_ones_or_all_zeros (and (icmp _ _ _) (value_type (multi_lane _ _)))) $true)
@@ -1398,6 +1399,24 @@
 (rule 3 (lower (has_type $F64X2 (bitselect (bitcast _ (fcmp (FloatCC.LessThan) y x)) x y)))
         (x64_maxpd x y))
 
+;; Scalar rules
+
+(rule 3 (lower (has_type $I128 (bitselect c t f)))
+      (let ((a ValueRegs (and_i128 c t))
+            (b ValueRegs (and_i128 (i128_not c) f)))
+        (or_i128 a b)))
+
+(rule 4 (lower (has_type (ty_int_ref_scalar_64 ty) (bitselect c t f)))
+      (let ((a Gpr (x64_and ty c t))
+            (b Gpr (x64_and ty (x64_not ty c) f)))
+        (x64_or ty a b)))
+
+(rule 5 (lower (has_type (ty_scalar_float ty) (bitselect c t f)))
+      (let ((a Xmm (sse_and ty c t))
+            (c_neg Xmm (x64_xor_vector ty c (vector_all_ones)))
+            (b Xmm (sse_and ty c_neg f)))
+        (sse_or ty a b)))
+
 ;;;; Rules for `x86_blendv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (rule (lower (has_type $I8X16
diff --git a/cranelift/codegen/src/isle_prelude.rs b/cranelift/codegen/src/isle_prelude.rs
index b537d9e10..1454838e5 100644
--- a/cranelift/codegen/src/isle_prelude.rs
+++ b/cranelift/codegen/src/isle_prelude.rs
@@ -169,6 +169,12 @@ macro_rules! isle_common_prelude_methods {
             x & 1 == 1
         }
 
+        #[inline]
+        fn i64_sextend_u64(&mut self, ty: Type, x: u64) -> i64 {
+            let shift_amt = std::cmp::max(0, 64 - ty.bits());
+            ((x as i64) << shift_amt) >> shift_amt
+        }
+
         #[inline]
         fn i64_sextend_imm64(&mut self, ty: Type, mut x: Imm64) -> i64 {
             x.sign_extend_from_width(ty.bits());
diff --git a/cranelift/codegen/src/machinst/buffer.rs b/cranelift/codegen/src/machinst/buffer.rs
index e5de3b40e..068d01945 100644
--- a/cranelift/codegen/src/machinst/buffer.rs
+++ b/cranelift/codegen/src/machinst/buffer.rs
@@ -335,7 +335,10 @@ impl MachBufferFinalized<Stencil> {
 /// A `MachBuffer` once emission is completed: holds generated code and records,
 /// without fixups. This allows the type to be independent of the backend.
 #[derive(PartialEq, Debug, Clone)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct MachBufferFinalized<T: CompilePhase> {
     /// The buffer contents, as raw bytes.
     pub(crate) data: SmallVec<[u8; 1024]>,
@@ -1713,7 +1716,10 @@ impl<I: VCodeInst> Ord for MachLabelFixup<I> {
 
 /// A relocation resulting from a compilation.
 #[derive(Clone, Debug, PartialEq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct MachReloc {
     /// The offset at which the relocation applies, *relative to the
     /// containing section*.
@@ -1728,7 +1734,10 @@ pub struct MachReloc {
 
 /// A trap record resulting from a compilation.
 #[derive(Clone, Debug, PartialEq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct MachTrap {
     /// The offset at which the trap instruction occurs, *relative to the
     /// containing section*.
@@ -1739,7 +1748,10 @@ pub struct MachTrap {
 
 /// A call site record resulting from a compilation.
 #[derive(Clone, Debug, PartialEq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct MachCallSite {
     /// The offset of the call's return address, *relative to the containing section*.
     pub ret_addr: CodeOffset,
@@ -1749,7 +1761,10 @@ pub struct MachCallSite {
 
 /// A source-location mapping resulting from a compilation.
 #[derive(PartialEq, Debug, Clone)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct MachSrcLoc<T: CompilePhase> {
     /// The start of the region of code corresponding to a source location.
     /// This is relative to the start of the function, not to the start of the
@@ -1775,7 +1790,10 @@ impl MachSrcLoc<Stencil> {
 
 /// Record of stack map metadata: stack offsets containing references.
 #[derive(Clone, Debug, PartialEq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct MachStackMap {
     /// The code offset at which this stack map applies.
     pub offset: CodeOffset,
diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs
index 04793db4d..e06cb94e3 100644
--- a/cranelift/codegen/src/machinst/isle.rs
+++ b/cranelift/codegen/src/machinst/isle.rs
@@ -209,6 +209,15 @@ macro_rules! isle_lower_prelude_methods {
             self.lower_ctx.dfg().value_def(val).inst()
         }
 
+        #[inline]
+        fn i64_from_iconst(&mut self, val: Value) -> Option<i64> {
+            let inst = self.def_inst(val)?;
+            let constant = self.lower_ctx.get_constant(inst)? as i64;
+            let ty = self.lower_ctx.output_ty(inst, 0);
+            let shift_amt = std::cmp::max(0, 64 - self.ty_bits(ty));
+            Some((constant << shift_amt) >> shift_amt)
+        }
+
         fn zero_value(&mut self, value: Value) -> Option<Value> {
             let insn = self.def_inst(value);
             if insn.is_some() {
diff --git a/cranelift/codegen/src/machinst/mod.rs b/cranelift/codegen/src/machinst/mod.rs
index 5bff57178..b39a4c859 100644
--- a/cranelift/codegen/src/machinst/mod.rs
+++ b/cranelift/codegen/src/machinst/mod.rs
@@ -61,7 +61,7 @@ use smallvec::{smallvec, SmallVec};
 use std::string::String;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 #[macro_use]
 pub mod isle;
diff --git a/cranelift/codegen/src/machinst/reg.rs b/cranelift/codegen/src/machinst/reg.rs
index 11192685c..4fd9b1e17 100644
--- a/cranelift/codegen/src/machinst/reg.rs
+++ b/cranelift/codegen/src/machinst/reg.rs
@@ -9,7 +9,7 @@ use regalloc2::{
 };
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// The first 192 vregs (64 int, 64 float, 64 vec) are "pinned" to
 /// physical registers: this means that they are always constrained to
diff --git a/cranelift/codegen/src/opts/extends.isle b/cranelift/codegen/src/opts/extends.isle
index 3850dece6..a1a4dfda0 100644
--- a/cranelift/codegen/src/opts/extends.isle
+++ b/cranelift/codegen/src/opts/extends.isle
@@ -32,10 +32,3 @@
 ;; actually doing the extend in the first place.
 (rule (simplify (ireduce ty (sextend _ x @ (value_type ty)))) x)
 (rule (simplify (ireduce ty (uextend _ x @ (value_type ty)))) x)
-
-;; {u,s}widen_{low,high}+splat is the same as splat+{u,s}extend
-(rule (simplify (swiden_high wide (splat _ x))) (splat wide (sextend (lane_type wide) x)))
-(rule (simplify (swiden_low wide (splat _ x))) (splat wide (sextend (lane_type wide) x)))
-
-(rule (simplify (uwiden_high wide (splat _ x))) (splat wide (uextend (lane_type wide) x)))
-(rule (simplify (uwiden_low wide (splat _ x))) (splat wide (uextend (lane_type wide) x)))
diff --git a/cranelift/codegen/src/opts/vector.isle b/cranelift/codegen/src/opts/vector.isle
index 8c98ce155..fd47fe69c 100644
--- a/cranelift/codegen/src/opts/vector.isle
+++ b/cranelift/codegen/src/opts/vector.isle
@@ -8,16 +8,23 @@
 (rule (simplify (fcvt_from_sint float_vector_ty (splat _ x)))
       (splat float_vector_ty (fcvt_from_sint (lane_type float_vector_ty) x)))
 
+;; Scalar bitwise ops are usually not implemented in the backends for floats, so
+;; disable this transform.
+
 (rule (simplify (band ty (splat ty x) (splat ty y)))
+      (if (ty_vector_not_float ty))
       (splat ty (band (lane_type ty) x y)))
 
 (rule (simplify (bor ty (splat ty x) (splat ty y)))
+      (if (ty_vector_not_float ty))
       (splat ty (bor (lane_type ty) x y)))
 
 (rule (simplify (bxor ty (splat ty x) (splat ty y)))
+      (if (ty_vector_not_float ty))
       (splat ty (bxor (lane_type ty) x y)))
 
 (rule (simplify (bnot ty (splat ty x)))
+      (if (ty_vector_not_float ty))
       (splat ty (bnot (lane_type ty) x)))
 
 (rule (simplify (iadd ty (splat ty x) (splat ty y)))
@@ -71,4 +78,11 @@
       (splat ty (ushr (lane_type ty) x y)))
 
 (rule (simplify (sshr ty (splat ty x) y))
-      (splat ty (sshr (lane_type ty) x y)))
\ No newline at end of file
+      (splat ty (sshr (lane_type ty) x y)))
+
+;; {u,s}widen_{low,high}+splat is the same as splat+{u,s}extend
+(rule (simplify (swiden_high wide (splat _ x))) (splat wide (sextend (lane_type wide) x)))
+(rule (simplify (swiden_low wide (splat _ x))) (splat wide (sextend (lane_type wide) x)))
+
+(rule (simplify (uwiden_high wide (splat _ x))) (splat wide (uextend (lane_type wide) x)))
+(rule (simplify (uwiden_low wide (splat _ x))) (splat wide (uextend (lane_type wide) x)))
diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle
index dd3c186a6..d83d4b518 100644
--- a/cranelift/codegen/src/prelude.isle
+++ b/cranelift/codegen/src/prelude.isle
@@ -184,6 +184,10 @@
 (decl pure u64_lt (u64 u64) bool)
 (extern constructor u64_lt u64_lt)
 
+;; Sign extends a u64 from ty bits up to 64bits
+(decl pure i64_sextend_u64 (Type u64) i64)
+(extern constructor i64_sextend_u64 i64_sextend_u64)
+
 (decl pure i64_sextend_imm64 (Type Imm64) i64)
 (extern constructor i64_sextend_imm64 i64_sextend_imm64)
 
diff --git a/cranelift/codegen/src/prelude_lower.isle b/cranelift/codegen/src/prelude_lower.isle
index 82737edf6..133f98b01 100644
--- a/cranelift/codegen/src/prelude_lower.isle
+++ b/cranelift/codegen/src/prelude_lower.isle
@@ -253,6 +253,11 @@
 (extractor (u64_from_iconst x)
            (def_inst (iconst (u64_from_imm64 x))))
 
+;; Extract a constant `i64` from a value defined by an `iconst`.
+;; The value is sign extended to 64 bits.
+(decl i64_from_iconst (i64) Value)
+(extern extractor i64_from_iconst i64_from_iconst)
+
 ;; Match any zero value for iconst, fconst32, fconst64, vconst and splat.
 (decl pure partial zero_value (Value) Value)
 (extern constructor zero_value zero_value)
diff --git a/cranelift/codegen/src/value_label.rs b/cranelift/codegen/src/value_label.rs
index 5a33dc57e..fa45bbb8d 100644
--- a/cranelift/codegen/src/value_label.rs
+++ b/cranelift/codegen/src/value_label.rs
@@ -4,7 +4,7 @@ use crate::HashMap;
 use alloc::vec::Vec;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Value location range.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
diff --git a/cranelift/entity/Cargo.toml b/cranelift/entity/Cargo.toml
index d0da5df18..4cbf9a882 100644
--- a/cranelift/entity/Cargo.toml
+++ b/cranelift/entity/Cargo.toml
@@ -12,7 +12,8 @@ keywords = ["entity", "set", "map"]
 edition.workspace = true
 
 [dependencies]
-serde = { version = "1.0.94", features = ["derive"], optional = true }
+serde = { version = "1.0.188", optional = true }
+serde_derive = { version = "1.0.188", optional = true }
 
 [features]
-enable-serde = ["serde"]
+enable-serde = ["serde", "serde_derive"]
diff --git a/cranelift/entity/src/list.rs b/cranelift/entity/src/list.rs
index 80d0acef8..922389f0c 100644
--- a/cranelift/entity/src/list.rs
+++ b/cranelift/entity/src/list.rs
@@ -6,7 +6,7 @@ use core::marker::PhantomData;
 use core::mem;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A small list of entity references allocated from a pool.
 ///
diff --git a/cranelift/entity/src/packed_option.rs b/cranelift/entity/src/packed_option.rs
index 7f48b0196..bc5cb3812 100644
--- a/cranelift/entity/src/packed_option.rs
+++ b/cranelift/entity/src/packed_option.rs
@@ -11,7 +11,7 @@ use core::fmt;
 use core::mem;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Types that have a reserved value which can't be created any other way.
 pub trait ReservedValue {
diff --git a/cranelift/entity/src/primary.rs b/cranelift/entity/src/primary.rs
index 55b923a0e..573f53546 100644
--- a/cranelift/entity/src/primary.rs
+++ b/cranelift/entity/src/primary.rs
@@ -10,7 +10,7 @@ use core::marker::PhantomData;
 use core::ops::{Index, IndexMut};
 use core::slice;
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A primary mapping `K -> V` allocating dense entity references.
 ///
diff --git a/cranelift/entity/src/sparse.rs b/cranelift/entity/src/sparse.rs
index a7cad3151..96d8c7b02 100644
--- a/cranelift/entity/src/sparse.rs
+++ b/cranelift/entity/src/sparse.rs
@@ -15,7 +15,7 @@ use core::slice;
 use core::u32;
 
 #[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Trait for extracting keys from values stored in a `SparseMap`.
 ///
diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs
index 8fdb2694d..15e784433 100644
--- a/cranelift/fuzzgen/src/function_generator.rs
+++ b/cranelift/fuzzgen/src/function_generator.rs
@@ -519,37 +519,12 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -
                     Opcode::Smin | Opcode::Umin | Opcode::Smax | Opcode::Umax,
                     &[I128, I128]
                 ),
-                // https://github.com/bytecodealliance/wasmtime/issues/4870
-                (Opcode::Bnot, &[F32 | F64]),
-                (
-                    Opcode::Band
-                        | Opcode::Bor
-                        | Opcode::Bxor
-                        | Opcode::BandNot
-                        | Opcode::BorNot
-                        | Opcode::BxorNot,
-                    &([F32, F32] | [F64, F64])
-                ),
-                // https://github.com/bytecodealliance/wasmtime/issues/5041
-                (
-                    Opcode::BandNot | Opcode::BorNot | Opcode::BxorNot,
-                    &([I8, I8] | [I16, I16] | [I32, I32] | [I64, I64] | [I128, I128])
-                ),
                 // https://github.com/bytecodealliance/wasmtime/issues/5107
                 (Opcode::Cls, &[I8], &[I8]),
                 (Opcode::Cls, &[I16], &[I16]),
                 (Opcode::Cls, &[I32], &[I32]),
                 (Opcode::Cls, &[I64], &[I64]),
                 (Opcode::Cls, &[I128], &[I128]),
-                // https://github.com/bytecodealliance/wasmtime/issues/5197
-                (
-                    Opcode::Bitselect,
-                    &([I8, I8, I8]
-                        | [I16, I16, I16]
-                        | [I32, I32, I32]
-                        | [I64, I64, I64]
-                        | [I128, I128, I128])
-                ),
                 // https://github.com/bytecodealliance/wasmtime/issues/4897
                 // https://github.com/bytecodealliance/wasmtime/issues/4899
                 (
@@ -761,6 +736,9 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -
                 // https://github.com/bytecodealliance/wasmtime/issues/6104
                 (Opcode::Bitcast, &[I128], &[_]),
                 (Opcode::Bitcast, &[_], &[I128]),
+                // TODO
+                (Opcode::SelectSpectreGuard, &[_, _, _], &[F32]),
+                (Opcode::SelectSpectreGuard, &[_, _, _], &[F64]),
             )
         }
 
@@ -918,86 +896,6 @@ static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = Lazy::new(|| {
                 (Opcode::ScalarToVector),
                 (Opcode::X86Pmaddubsw),
                 (Opcode::X86Cvtt2dq),
-                (Opcode::Select, &[I8, F32, F32], &[F32]),
-                (Opcode::Select, &[I16, F32, F32], &[F32]),
-                (Opcode::Select, &[I32, F32, F32], &[F32]),
-                (Opcode::Select, &[I64, F32, F32], &[F32]),
-                (Opcode::Select, &[I128, F32, F32], &[F32]),
-                (Opcode::Select, &[I8, F64, F64], &[F64]),
-                (Opcode::Select, &[I16, F64, F64], &[F64]),
-                (Opcode::Select, &[I32, F64, F64], &[F64]),
-                (Opcode::Select, &[I64, F64, F64], &[F64]),
-                (Opcode::Select, &[I128, F64, F64], &[F64]),
-                (Opcode::Select, &[I8, I8X16, I8X16], &[I8X16]),
-                (Opcode::Select, &[I16, I8X16, I8X16], &[I8X16]),
-                (Opcode::Select, &[I32, I8X16, I8X16], &[I8X16]),
-                (Opcode::Select, &[I64, I8X16, I8X16], &[I8X16]),
-                (Opcode::Select, &[I128, I8X16, I8X16], &[I8X16]),
-                (Opcode::Select, &[I8, I16X8, I16X8], &[I16X8]),
-                (Opcode::Select, &[I16, I16X8, I16X8], &[I16X8]),
-                (Opcode::Select, &[I32, I16X8, I16X8], &[I16X8]),
-                (Opcode::Select, &[I64, I16X8, I16X8], &[I16X8]),
-                (Opcode::Select, &[I128, I16X8, I16X8], &[I16X8]),
-                (Opcode::Select, &[I8, I32X4, I32X4], &[I32X4]),
-                (Opcode::Select, &[I16, I32X4, I32X4], &[I32X4]),
-                (Opcode::Select, &[I32, I32X4, I32X4], &[I32X4]),
-                (Opcode::Select, &[I64, I32X4, I32X4], &[I32X4]),
-                (Opcode::Select, &[I128, I32X4, I32X4], &[I32X4]),
-                (Opcode::Select, &[I8, I64X2, I64X2], &[I64X2]),
-                (Opcode::Select, &[I16, I64X2, I64X2], &[I64X2]),
-                (Opcode::Select, &[I32, I64X2, I64X2], &[I64X2]),
-                (Opcode::Select, &[I64, I64X2, I64X2], &[I64X2]),
-                (Opcode::Select, &[I128, I64X2, I64X2], &[I64X2]),
-                (Opcode::Select, &[I8, F32X4, F32X4], &[F32X4]),
-                (Opcode::Select, &[I16, F32X4, F32X4], &[F32X4]),
-                (Opcode::Select, &[I32, F32X4, F32X4], &[F32X4]),
-                (Opcode::Select, &[I64, F32X4, F32X4], &[F32X4]),
-                (Opcode::Select, &[I128, F32X4, F32X4], &[F32X4]),
-                (Opcode::Select, &[I8, F64X2, F64X2], &[F64X2]),
-                (Opcode::Select, &[I16, F64X2, F64X2], &[F64X2]),
-                (Opcode::Select, &[I32, F64X2, F64X2], &[F64X2]),
-                (Opcode::Select, &[I64, F64X2, F64X2], &[F64X2]),
-                (Opcode::Select, &[I128, F64X2, F64X2], &[F64X2]),
-                (Opcode::SelectSpectreGuard, &[I8, F32, F32], &[F32]),
-                (Opcode::SelectSpectreGuard, &[I16, F32, F32], &[F32]),
-                (Opcode::SelectSpectreGuard, &[I32, F32, F32], &[F32]),
-                (Opcode::SelectSpectreGuard, &[I64, F32, F32], &[F32]),
-                (Opcode::SelectSpectreGuard, &[I128, F32, F32], &[F32]),
-                (Opcode::SelectSpectreGuard, &[I8, F64, F64], &[F64]),
-                (Opcode::SelectSpectreGuard, &[I16, F64, F64], &[F64]),
-                (Opcode::SelectSpectreGuard, &[I32, F64, F64], &[F64]),
-                (Opcode::SelectSpectreGuard, &[I64, F64, F64], &[F64]),
-                (Opcode::SelectSpectreGuard, &[I128, F64, F64], &[F64]),
-                (Opcode::SelectSpectreGuard, &[I8, I8X16, I8X16], &[I8X16]),
-                (Opcode::SelectSpectreGuard, &[I16, I8X16, I8X16], &[I8X16]),
-                (Opcode::SelectSpectreGuard, &[I32, I8X16, I8X16], &[I8X16]),
-                (Opcode::SelectSpectreGuard, &[I64, I8X16, I8X16], &[I8X16]),
-                (Opcode::SelectSpectreGuard, &[I128, I8X16, I8X16], &[I8X16]),
-                (Opcode::SelectSpectreGuard, &[I8, I16X8, I16X8], &[I16X8]),
-                (Opcode::SelectSpectreGuard, &[I16, I16X8, I16X8], &[I16X8]),
-                (Opcode::SelectSpectreGuard, &[I32, I16X8, I16X8], &[I16X8]),
-                (Opcode::SelectSpectreGuard, &[I64, I16X8, I16X8], &[I16X8]),
-                (Opcode::SelectSpectreGuard, &[I128, I16X8, I16X8], &[I16X8]),
-                (Opcode::SelectSpectreGuard, &[I8, I32X4, I32X4], &[I32X4]),
-                (Opcode::SelectSpectreGuard, &[I16, I32X4, I32X4], &[I32X4]),
-                (Opcode::SelectSpectreGuard, &[I32, I32X4, I32X4], &[I32X4]),
-                (Opcode::SelectSpectreGuard, &[I64, I32X4, I32X4], &[I32X4]),
-                (Opcode::SelectSpectreGuard, &[I128, I32X4, I32X4], &[I32X4]),
-                (Opcode::SelectSpectreGuard, &[I8, I64X2, I64X2], &[I64X2]),
-                (Opcode::SelectSpectreGuard, &[I16, I64X2, I64X2], &[I64X2]),
-                (Opcode::SelectSpectreGuard, &[I32, I64X2, I64X2], &[I64X2]),
-                (Opcode::SelectSpectreGuard, &[I64, I64X2, I64X2], &[I64X2]),
-                (Opcode::SelectSpectreGuard, &[I128, I64X2, I64X2], &[I64X2]),
-                (Opcode::SelectSpectreGuard, &[I8, F32X4, F32X4], &[F32X4]),
-                (Opcode::SelectSpectreGuard, &[I16, F32X4, F32X4], &[F32X4]),
-                (Opcode::SelectSpectreGuard, &[I32, F32X4, F32X4], &[F32X4]),
-                (Opcode::SelectSpectreGuard, &[I64, F32X4, F32X4], &[F32X4]),
-                (Opcode::SelectSpectreGuard, &[I128, F32X4, F32X4], &[F32X4]),
-                (Opcode::SelectSpectreGuard, &[I8, F64X2, F64X2], &[F64X2]),
-                (Opcode::SelectSpectreGuard, &[I16, F64X2, F64X2], &[F64X2]),
-                (Opcode::SelectSpectreGuard, &[I32, F64X2, F64X2], &[F64X2]),
-                (Opcode::SelectSpectreGuard, &[I64, F64X2, F64X2], &[F64X2]),
-                (Opcode::SelectSpectreGuard, &[I128, F64X2, F64X2], &[F64X2]),
                 (Opcode::Bitselect, &[F32, F32, F32], &[F32]),
                 (Opcode::Bitselect, &[F64, F64, F64], &[F64]),
                 (Opcode::Bitselect, &[F32X4, F32X4, F32X4], &[F32X4]),
diff --git a/cranelift/module/Cargo.toml b/cranelift/module/Cargo.toml
index e83a04224..5737f6d51 100644
--- a/cranelift/module/Cargo.toml
+++ b/cranelift/module/Cargo.toml
@@ -15,7 +15,8 @@ cranelift-codegen = { workspace = true }
 cranelift-control = { workspace = true }
 hashbrown = { workspace = true, optional = true }
 anyhow = { workspace = true }
-serde = { version = "1.0.94", features = ["derive"], optional = true }
+serde = { version = "1.0.188", optional = true }
+serde_derive = { version = "1.0.188", optional = true }
 
 [features]
 default = ["std"]
@@ -23,4 +24,4 @@ std = ["cranelift-codegen/std"]
 core = ["hashbrown", "cranelift-codegen/core"]
 
 # For dependent crates that want to serialize some parts of cranelift
-enable-serde = ["serde", "cranelift-codegen/enable-serde"]
+enable-serde = ["serde", "serde_derive", "cranelift-codegen/enable-serde"]
diff --git a/cranelift/module/src/data_context.rs b/cranelift/module/src/data_context.rs
index 3e1e30a11..2b262eca3 100644
--- a/cranelift/module/src/data_context.rs
+++ b/cranelift/module/src/data_context.rs
@@ -13,7 +13,10 @@ use crate::ModuleExtName;
 
 /// This specifies how data is to be initialized.
 #[derive(Clone, PartialEq, Eq, Debug)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub enum Init {
     /// This indicates that no initialization has been specified yet.
     Uninitialized,
@@ -42,7 +45,10 @@ impl Init {
 
 /// A description of a data object.
 #[derive(Clone, Debug)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct DataDescription {
     /// How the data should be initialized.
     pub init: Init,
diff --git a/cranelift/module/src/module.rs b/cranelift/module/src/module.rs
index 1b524cad8..917b8ca68 100644
--- a/cranelift/module/src/module.rs
+++ b/cranelift/module/src/module.rs
@@ -55,7 +55,10 @@ impl ModuleReloc {
 
 /// A function identifier for use in the `Module` interface.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct FuncId(u32);
 entity_impl!(FuncId, "funcid");
 
@@ -83,7 +86,10 @@ impl FuncId {
 
 /// A data object identifier for use in the `Module` interface.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct DataId(u32);
 entity_impl!(DataId, "dataid");
 
@@ -111,7 +117,10 @@ impl DataId {
 
 /// Linkage refers to where an entity is defined and who can see it.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub enum Linkage {
     /// Defined outside of a module.
     Import,
@@ -170,7 +179,10 @@ impl Linkage {
 
 /// A declared name may refer to either a function or data declaration
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub enum FuncOrDataId {
     /// When it's a FuncId
     Func(FuncId),
@@ -190,7 +202,10 @@ impl From<FuncOrDataId> for ModuleExtName {
 
 /// Information about a function which can be called.
 #[derive(Debug)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct FunctionDeclaration {
     #[allow(missing_docs)]
     pub name: Option<String>,
@@ -348,7 +363,10 @@ pub type ModuleResult<T> = Result<T, ModuleError>;
 
 /// Information about a data object which can be accessed.
 #[derive(Debug)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct DataDeclaration {
     #[allow(missing_docs)]
     pub name: Option<String>,
@@ -386,7 +404,10 @@ impl DataDeclaration {
 
 /// A translated `ExternalName` into something global we can handle.
 #[derive(Clone, Debug)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub enum ModuleExtName {
     /// User defined function, converted from `ExternalName::User`.
     User {
diff --git a/cranelift/wasm/Cargo.toml b/cranelift/wasm/Cargo.toml
index d7eb9f42d..56d5c4188 100644
--- a/cranelift/wasm/Cargo.toml
+++ b/cranelift/wasm/Cargo.toml
@@ -20,7 +20,8 @@ wasmtime-types = { workspace = true }
 hashbrown = { workspace = true, optional = true }
 itertools = "0.10.0"
 log = { workspace = true }
-serde = { version = "1.0.94", features = ["derive"], optional = true }
+serde = { version = "1.0.188", optional = true }
+serde_derive = { version = "1.0.188", optional = true }
 smallvec = { workspace = true }
 
 [dev-dependencies]
@@ -31,4 +32,4 @@ target-lexicon = { workspace = true }
 default = ["std"]
 std = ["cranelift-codegen/std", "cranelift-frontend/std"]
 core = ["hashbrown", "cranelift-codegen/core", "cranelift-frontend/core"]
-enable-serde = ["serde"]
+enable-serde = ["serde", "serde_derive"]
diff --git a/cranelift/wasm/src/heap.rs b/cranelift/wasm/src/heap.rs
index 2b2a9fb99..e71fae8e3 100644
--- a/cranelift/wasm/src/heap.rs
+++ b/cranelift/wasm/src/heap.rs
@@ -7,7 +7,10 @@ use cranelift_entity::entity_impl;
 ///
 /// While the order is stable, it is arbitrary.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct Heap(u32);
 entity_impl!(Heap, "heap");
 
@@ -59,7 +62,10 @@ entity_impl!(Heap, "heap");
 /// when the heap is resized. The bound of a dynamic heap is stored in a global
 /// value.
 #[derive(Clone, PartialEq, Hash)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub struct HeapData {
     /// The address of the start of the heap's storage.
     pub base: GlobalValue,
@@ -80,7 +86,10 @@ pub struct HeapData {
 
 /// Style of heap including style-specific information.
 #[derive(Clone, PartialEq, Hash)]
-#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(
+    feature = "enable-serde",
+    derive(serde_derive::Serialize, serde_derive::Deserialize)
+)]
 pub enum HeapStyle {
     /// A dynamic heap can be relocated to a different base address when it is
     /// grown.
diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs
index b0abcbf32..e38b13277 100644
--- a/cranelift/wasm/src/sections_translator.rs
+++ b/cranelift/wasm/src/sections_translator.rs
@@ -21,8 +21,7 @@ use wasmparser::{
     self, Data, DataKind, DataSectionReader, Element, ElementItems, ElementKind,
     ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader,
     GlobalSectionReader, ImportSectionReader, MemorySectionReader, MemoryType, NameSectionReader,
-    Naming, Operator, StructuralType, TableSectionReader, TagSectionReader, TagType, TypeRef,
-    TypeSectionReader,
+    Naming, Operator, TableSectionReader, TagSectionReader, TagType, TypeRef, TypeSectionReader,
 };
 
 fn memory(ty: MemoryType) -> Memory {
@@ -50,20 +49,9 @@ pub fn parse_type_section<'a>(
     let count = types.count();
     environ.reserve_types(count)?;
 
-    for entry in types {
-        let entry = entry?;
-        if entry.is_final || entry.supertype_idx.is_some() {
-            unimplemented!("gc proposal");
-        }
-        match entry.structural_type {
-            StructuralType::Func(wasm_func_ty) => {
-                let ty = environ.convert_func_type(&wasm_func_ty);
-                environ.declare_type_func(ty)?;
-            }
-            StructuralType::Array(_) | StructuralType::Struct(_) => {
-                unimplemented!("gc proposal");
-            }
-        }
+    for ty in types.into_iter_err_on_gc_types() {
+        let ty = environ.convert_func_type(&ty?);
+        environ.declare_type_func(ty)?;
     }
     Ok(())
 }
diff --git a/cranelift/wasm/src/translation_utils.rs b/cranelift/wasm/src/translation_utils.rs
index 7d2208881..8a6ceb2c7 100644
--- a/cranelift/wasm/src/translation_utils.rs
+++ b/cranelift/wasm/src/translation_utils.rs
@@ -4,8 +4,6 @@ use crate::WasmResult;
 use core::u32;
 use cranelift_codegen::ir;
 use cranelift_frontend::FunctionBuilder;
-#[cfg(feature = "enable-serde")]
-use serde::{Deserialize, Serialize};
 use wasmparser::{FuncValidator, WasmFuncType, WasmModuleResources};
 
 /// Get the parameter and result types for the given Wasm blocktype.
diff --git a/crates/cache/Cargo.toml b/crates/cache/Cargo.toml
index 28943c078..0b72cd6b8 100644
--- a/crates/cache/Cargo.toml
+++ b/crates/cache/Cargo.toml
@@ -14,7 +14,8 @@ base64 = "0.21.0"
 bincode = "1.1.4"
 directories-next = "2.0"
 log = { workspace = true }
-serde = { version = "1.0.94", features = ["derive"] }
+serde = "1.0.188"
+serde_derive = "1.0.188"
 sha2 = "0.10.2"
 toml = "0.5.5"
 zstd = { version = "0.11.1", default-features = false }
diff --git a/crates/cache/src/config.rs b/crates/cache/src/config.rs
index 5f028293a..d7b8f3d4f 100644
--- a/crates/cache/src/config.rs
+++ b/crates/cache/src/config.rs
@@ -17,14 +17,14 @@ use std::time::Duration;
 
 // wrapped, so we have named section in config,
 // also, for possible future compatibility
-#[derive(Deserialize, Debug)]
+#[derive(serde_derive::Deserialize, Debug)]
 #[serde(deny_unknown_fields)]
 struct Config {
     cache: CacheConfig,
 }
 
 /// Global configuration for how the cache is managed
-#[derive(Deserialize, Debug, Clone)]
+#[derive(serde_derive::Deserialize, Debug, Clone)]
 #[serde(deny_unknown_fields)]
 pub struct CacheConfig {
     enabled: bool,
@@ -137,7 +137,7 @@ pub fn create_new_config<P: AsRef<Path> + Debug>(config_file: Option<P>) -> Resu
 enabled = true
 ";
 
-    fs::write(&config_file, &content).with_context(|| {
+    fs::write(&config_file, content).with_context(|| {
         format!(
             "Failed to flush config to the disk, path: {}",
             config_file.display(),
diff --git a/crates/cache/src/worker.rs b/crates/cache/src/worker.rs
index 47b252095..7f9aaa572 100644
--- a/crates/cache/src/worker.rs
+++ b/crates/cache/src/worker.rs
@@ -7,7 +7,7 @@
 
 use super::{fs_write_atomic, CacheConfig};
 use log::{debug, info, trace, warn};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::cmp;
 use std::collections::HashMap;
 use std::ffi::OsStr;
diff --git a/crates/component-macro/src/component.rs b/crates/component-macro/src/component.rs
index 0d63ec874..0f49ef07a 100644
--- a/crates/component-macro/src/component.rs
+++ b/crates/component-macro/src/component.rs
@@ -18,7 +18,6 @@ mod kw {
 pub enum VariantStyle {
     Variant,
     Enum,
-    Union,
 }
 
 impl fmt::Display for VariantStyle {
@@ -26,7 +25,6 @@ impl fmt::Display for VariantStyle {
         f.write_str(match self {
             Self::Variant => "variant",
             Self::Enum => "enum",
-            Self::Union => "union",
         })
     }
 }
@@ -70,9 +68,6 @@ impl Parse for Style {
         } else if lookahead.peek(Token![enum]) {
             input.parse::<Token![enum]>()?;
             Ok(Style::Variant(VariantStyle::Enum))
-        } else if lookahead.peek(Token![union]) {
-            input.parse::<Token![union]>()?;
-            Ok(Style::Variant(VariantStyle::Union))
         } else if input.peek(kw::flags) {
             Err(input.error(
                 "`flags` not allowed here; \
@@ -238,7 +233,6 @@ fn expand_variant(
                                     match style {
                                         VariantStyle::Variant => "at most one unnamed field each",
                                         VariantStyle::Enum => "no fields",
-                                        VariantStyle::Union => "exactly one unnamed field each",
                                     }
                                 ),
                             ))
@@ -443,7 +437,6 @@ impl Expander for LiftExpander {
         let interface_type_variant = match style {
             VariantStyle::Variant => quote!(Variant),
             VariantStyle::Enum => quote!(Enum),
-            VariantStyle::Union => quote!(Union),
         };
 
         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
@@ -456,7 +449,6 @@ impl Expander for LiftExpander {
                     VariantStyle::Variant => {
                         quote!(ty.cases[#index].ty.unwrap_or_else(#internal::bad_type_info))
                     }
-                    VariantStyle::Union => quote!(ty.types[#index]),
                     VariantStyle::Enum => unreachable!(),
                 };
                 lifts.extend(
@@ -618,7 +610,6 @@ impl Expander for LowerExpander {
         let interface_type_variant = match style {
             VariantStyle::Variant => quote!(Variant),
             VariantStyle::Enum => quote!(Enum),
-            VariantStyle::Union => quote!(Union),
         };
 
         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
@@ -637,7 +628,6 @@ impl Expander for LowerExpander {
                     VariantStyle::Variant => {
                         quote!(ty.cases[#index].ty.unwrap_or_else(#internal::bad_type_info))
                     }
-                    VariantStyle::Union => quote!(ty.types[#index]),
                     VariantStyle::Enum => unreachable!(),
                 };
                 pattern = quote!(Self::#ident(value));
@@ -768,13 +758,6 @@ impl Expander for ComponentTypeExpander {
         for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() {
             let rename = find_rename(attrs)?;
 
-            if let (Some(_), VariantStyle::Union) = (&rename, style) {
-                return Err(Error::new(
-                    ident.span(),
-                    "renaming `union` cases is not permitted; only the type is used",
-                ));
-            }
-
             let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span()));
 
             if let Some(ty) = ty {
@@ -784,9 +767,6 @@ impl Expander for ComponentTypeExpander {
                     VariantStyle::Variant => {
                         quote!((#name, Some(<#ty as wasmtime::component::ComponentType>::typecheck)),)
                     }
-                    VariantStyle::Union => {
-                        quote!(<#ty as wasmtime::component::ComponentType>::typecheck,)
-                    }
                     VariantStyle::Enum => {
                         return Err(Error::new(
                             ident.span(),
@@ -810,9 +790,6 @@ impl Expander for ComponentTypeExpander {
                     VariantStyle::Variant => {
                         quote!((#name, None),)
                     }
-                    VariantStyle::Union => {
-                        quote!(<() as wasmtime::component::ComponentType>::typecheck,)
-                    }
                     VariantStyle::Enum => quote!(#name,),
                 });
                 lower_payload_case_declarations.extend(quote!(#ident: [wasmtime::ValRaw; 0],));
@@ -821,7 +798,6 @@ impl Expander for ComponentTypeExpander {
 
         let typecheck = match style {
             VariantStyle::Variant => quote!(typecheck_variant),
-            VariantStyle::Union => quote!(typecheck_union),
             VariantStyle::Enum => quote!(typecheck_enum),
         };
 
diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml
index ed0499b30..1fd84a613 100644
--- a/crates/environ/Cargo.toml
+++ b/crates/environ/Cargo.toml
@@ -17,7 +17,8 @@ wasmtime-types = { workspace = true }
 wasmparser = { workspace = true }
 indexmap = { workspace = true, features = ["serde"] }
 thiserror = { workspace = true }
-serde = { version = "1.0.94", features = ["derive"] }
+serde = "1.0.188"
+serde_derive = "1.0.188"
 log = { workspace = true }
 gimli = { workspace = true, features = ["write"] }
 object = { workspace = true, features = ['write_core'] }
diff --git a/crates/environ/src/address_map.rs b/crates/environ/src/address_map.rs
index c55250113..806fba8a5 100644
--- a/crates/environ/src/address_map.rs
+++ b/crates/environ/src/address_map.rs
@@ -3,7 +3,7 @@
 use crate::obj::ELF_WASMTIME_ADDRMAP;
 use object::write::{Object, StandardSegment};
 use object::{Bytes, LittleEndian, SectionKind, U32Bytes};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::convert::TryFrom;
 use std::ops::Range;
 
diff --git a/crates/environ/src/compilation.rs b/crates/environ/src/compilation.rs
index dc5ddc32c..eede6d3bf 100644
--- a/crates/environ/src/compilation.rs
+++ b/crates/environ/src/compilation.rs
@@ -9,7 +9,7 @@ use crate::{
 use anyhow::Result;
 use object::write::{Object, SymbolId};
 use object::{Architecture, BinaryFormat, FileFlags};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::any::Any;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
diff --git a/crates/environ/src/component/compiler.rs b/crates/environ/src/component/compiler.rs
index ed192e1df..13b4a3a4a 100644
--- a/crates/environ/src/component/compiler.rs
+++ b/crates/environ/src/component/compiler.rs
@@ -1,6 +1,6 @@
 use crate::component::{ComponentTranslation, ComponentTypes, TrampolineIndex};
 use anyhow::Result;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::any::Any;
 
 /// A triple of related functions/trampolines variants with differing calling
diff --git a/crates/environ/src/component/info.rs b/crates/environ/src/component/info.rs
index 8a1cf70c8..dff80ffe9 100644
--- a/crates/environ/src/component/info.rs
+++ b/crates/environ/src/component/info.rs
@@ -49,7 +49,7 @@
 use crate::component::*;
 use crate::{EntityIndex, PrimaryMap, SignatureIndex, WasmType};
 use indexmap::IndexMap;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Metadata as a result of compiling a component.
 pub struct ComponentTranslation {
diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs
index ed262379e..9d481f162 100644
--- a/crates/environ/src/component/types.rs
+++ b/crates/environ/src/component/types.rs
@@ -6,7 +6,7 @@ use crate::{
 use anyhow::{bail, Result};
 use cranelift_entity::EntityRef;
 use indexmap::{IndexMap, IndexSet};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::hash::Hash;
 use std::ops::Index;
@@ -100,8 +100,6 @@ indices! {
     pub struct TypeFlagsIndex(u32);
     /// Index pointing to an enum type in the component model.
     pub struct TypeEnumIndex(u32);
-    /// Index pointing to a union type in the component model.
-    pub struct TypeUnionIndex(u32);
     /// Index pointing to an option type in the component model (aka a
     /// `Option<T, E>`)
     pub struct TypeOptionIndex(u32);
@@ -252,7 +250,6 @@ pub struct ComponentTypes {
     tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
     enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
     flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
-    unions: PrimaryMap<TypeUnionIndex, TypeUnion>,
     options: PrimaryMap<TypeOptionIndex, TypeOption>,
     results: PrimaryMap<TypeResultIndex, TypeResult>,
     resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
@@ -293,7 +290,6 @@ impl ComponentTypes {
             InterfaceType::Tuple(i) => &self[*i].abi,
             InterfaceType::Flags(i) => &self[*i].abi,
             InterfaceType::Enum(i) => &self[*i].abi,
-            InterfaceType::Union(i) => &self[*i].abi,
             InterfaceType::Option(i) => &self[*i].abi,
             InterfaceType::Result(i) => &self[*i].abi,
         }
@@ -340,7 +336,6 @@ impl_index! {
     impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
     impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
     impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
-    impl Index<TypeUnionIndex> for ComponentTypes { TypeUnion => unions }
     impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
     impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
     impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
@@ -372,7 +367,6 @@ pub struct ComponentTypesBuilder {
     tuples: HashMap<TypeTuple, TypeTupleIndex>,
     enums: HashMap<TypeEnum, TypeEnumIndex>,
     flags: HashMap<TypeFlags, TypeFlagsIndex>,
-    unions: HashMap<TypeUnion, TypeUnionIndex>,
     options: HashMap<TypeOption, TypeOptionIndex>,
     results: HashMap<TypeResult, TypeResultIndex>,
 
@@ -613,9 +607,6 @@ impl ComponentTypesBuilder {
             }
             types::ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
             types::ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
-            types::ComponentDefinedType::Union(e) => {
-                InterfaceType::Union(self.union_type(types, e)?)
-            }
             types::ComponentDefinedType::Option(e) => {
                 InterfaceType::Option(self.option_type(types, e)?)
             }
@@ -734,24 +725,6 @@ impl ComponentTypesBuilder {
         self.add_enum_type(TypeEnum { names, abi, info })
     }
 
-    fn union_type(
-        &mut self,
-        types: types::TypesRef<'_>,
-        ty: &types::UnionType,
-    ) -> Result<TypeUnionIndex> {
-        let types = ty
-            .types
-            .iter()
-            .map(|ty| self.valtype(types, ty))
-            .collect::<Result<Box<[_]>>>()?;
-        let (info, abi) = VariantInfo::new(
-            types
-                .iter()
-                .map(|t| Some(self.component_types.canonical_abi(t))),
-        );
-        Ok(self.add_union_type(TypeUnion { types, abi, info }))
-    }
-
     fn option_type(
         &mut self,
         types: types::TypesRef<'_>,
@@ -828,11 +801,6 @@ impl ComponentTypesBuilder {
         intern_and_fill_flat_types!(self, variants, ty)
     }
 
-    /// Interns a new union type within this type information.
-    pub fn add_union_type(&mut self, ty: TypeUnion) -> TypeUnionIndex {
-        intern_and_fill_flat_types!(self, unions, ty)
-    }
-
     /// Interns a new enum type within this type information.
     pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
         intern_and_fill_flat_types!(self, enums, ty)
@@ -918,7 +886,6 @@ impl ComponentTypesBuilder {
             InterfaceType::Tuple(i) => &self.type_info.tuples[*i],
             InterfaceType::Flags(i) => &self.type_info.flags[*i],
             InterfaceType::Enum(i) => &self.type_info.enums[*i],
-            InterfaceType::Union(i) => &self.type_info.unions[*i],
             InterfaceType::Option(i) => &self.type_info.options[*i],
             InterfaceType::Result(i) => &self.type_info.results[*i],
         }
@@ -1065,7 +1032,6 @@ pub enum InterfaceType {
     Tuple(TypeTupleIndex),
     Flags(TypeFlagsIndex),
     Enum(TypeEnumIndex),
-    Union(TypeUnionIndex),
     Option(TypeOptionIndex),
     Result(TypeResultIndex),
     Own(TypeResourceTableIndex),
@@ -1511,21 +1477,6 @@ pub struct TypeEnum {
     pub info: VariantInfo,
 }
 
-/// Shape of a "union" type in interface types.
-///
-/// Note that this can be viewed as a specialization of the `variant` interface
-/// type where each type here has a name that's numbered. This is still a
-/// tagged union.
-#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
-pub struct TypeUnion {
-    /// The list of types this is a union over.
-    pub types: Box<[InterfaceType]>,
-    /// Byte information about this type in the canonical ABI.
-    pub abi: CanonicalAbiInfo,
-    /// Byte information about this variant type.
-    pub info: VariantInfo,
-}
-
 /// Shape of an "option" interface type.
 #[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
 pub struct TypeOption {
@@ -1715,7 +1666,6 @@ struct TypeInformationCache {
     tuples: PrimaryMap<TypeTupleIndex, TypeInformation>,
     enums: PrimaryMap<TypeEnumIndex, TypeInformation>,
     flags: PrimaryMap<TypeFlagsIndex, TypeInformation>,
-    unions: PrimaryMap<TypeUnionIndex, TypeInformation>,
     options: PrimaryMap<TypeOptionIndex, TypeInformation>,
     results: PrimaryMap<TypeResultIndex, TypeInformation>,
     lists: PrimaryMap<TypeListIndex, TypeInformation>,
@@ -1896,10 +1846,6 @@ impl TypeInformation {
         )
     }
 
-    fn unions(&mut self, types: &ComponentTypesBuilder, ty: &TypeUnion) {
-        self.build_variant(ty.types.iter().map(|t| Some(types.type_information(t))))
-    }
-
     fn results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult) {
         self.build_variant([
             ty.ok.as_ref().map(|ty| types.type_information(ty)),
diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs
index 000d843e2..5936de013 100644
--- a/crates/environ/src/fact/trampoline.rs
+++ b/crates/environ/src/fact/trampoline.rs
@@ -18,8 +18,8 @@
 use crate::component::{
     CanonicalAbiInfo, ComponentTypesBuilder, FlatType, InterfaceType, StringEncoding,
     TypeEnumIndex, TypeFlagsIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex,
-    TypeResourceTableIndex, TypeResultIndex, TypeTupleIndex, TypeUnionIndex, TypeVariantIndex,
-    VariantInfo, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
+    TypeResourceTableIndex, TypeResultIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo,
+    FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
 };
 use crate::fact::signature::Signature;
 use crate::fact::transcode::{FixedEncoding as FE, Transcode, Transcoder};
@@ -580,7 +580,6 @@ impl Compiler<'_, '_> {
             InterfaceType::Record(i) => self.types[*i].fields.len(),
             InterfaceType::Tuple(i) => self.types[*i].types.len(),
             InterfaceType::Variant(i) => self.types[*i].cases.len(),
-            InterfaceType::Union(i) => self.types[*i].types.len(),
             InterfaceType::Enum(i) => self.types[*i].names.len(),
 
             // 2 cases to consider for each of these variants.
@@ -617,7 +616,6 @@ impl Compiler<'_, '_> {
                     InterfaceType::Flags(f) => self.translate_flags(*f, src, dst_ty, dst),
                     InterfaceType::Tuple(t) => self.translate_tuple(*t, src, dst_ty, dst),
                     InterfaceType::Variant(v) => self.translate_variant(*v, src, dst_ty, dst),
-                    InterfaceType::Union(u) => self.translate_union(*u, src, dst_ty, dst),
                     InterfaceType::Enum(t) => self.translate_enum(*t, src, dst_ty, dst),
                     InterfaceType::Option(t) => self.translate_option(*t, src, dst_ty, dst),
                     InterfaceType::Result(t) => self.translate_result(*t, src, dst_ty, dst),
@@ -2203,44 +2201,6 @@ impl Compiler<'_, '_> {
         self.convert_variant(src, &src_info, dst, &dst_info, iter);
     }
 
-    fn translate_union(
-        &mut self,
-        src_ty: TypeUnionIndex,
-        src: &Source<'_>,
-        dst_ty: &InterfaceType,
-        dst: &Destination,
-    ) {
-        let src_ty = &self.types[src_ty];
-        let dst_ty = match dst_ty {
-            InterfaceType::Union(t) => &self.types[*t],
-            _ => panic!("expected an option"),
-        };
-        assert_eq!(src_ty.types.len(), dst_ty.types.len());
-        let src_info = variant_info(self.types, src_ty.types.iter().map(Some));
-        let dst_info = variant_info(self.types, dst_ty.types.iter().map(Some));
-
-        self.convert_variant(
-            src,
-            &src_info,
-            dst,
-            &dst_info,
-            src_ty
-                .types
-                .iter()
-                .zip(dst_ty.types.iter())
-                .enumerate()
-                .map(|(i, (src_ty, dst_ty))| {
-                    let i = u32::try_from(i).unwrap();
-                    VariantCase {
-                        src_i: i,
-                        dst_i: i,
-                        src_ty: Some(src_ty),
-                        dst_ty: Some(dst_ty),
-                    }
-                }),
-        );
-    }
-
     fn translate_enum(
         &mut self,
         src_ty: TypeEnumIndex,
diff --git a/crates/environ/src/fact/transcode.rs b/crates/environ/src/fact/transcode.rs
index 06cfccdef..ca34a8583 100644
--- a/crates/environ/src/fact/transcode.rs
+++ b/crates/environ/src/fact/transcode.rs
@@ -1,6 +1,6 @@
 use crate::fact::core_types::CoreTypes;
 use crate::MemoryIndex;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use wasm_encoder::{EntityType, ValType};
 
 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs
index 565329df0..5bce7ae16 100644
--- a/crates/environ/src/module.rs
+++ b/crates/environ/src/module.rs
@@ -3,7 +3,7 @@
 use crate::{ModuleTranslation, PrimaryMap, Tunables, WasmHeapType, WASM_PAGE_SIZE};
 use cranelift_entity::{packed_option::ReservedValue, EntityRef};
 use indexmap::IndexMap;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::BTreeMap;
 use std::convert::TryFrom;
 use std::mem;
diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs
index 260415ef8..00a5885c6 100644
--- a/crates/environ/src/module_environ.rs
+++ b/crates/environ/src/module_environ.rs
@@ -16,8 +16,8 @@ use std::path::PathBuf;
 use std::sync::Arc;
 use wasmparser::{
     types::Types, CustomSectionReader, DataKind, ElementItems, ElementKind, Encoding, ExternalKind,
-    FuncToValidate, FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload,
-    StructuralType, TypeRef, Validator, ValidatorResources,
+    FuncToValidate, FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, TypeRef,
+    Validator, ValidatorResources,
 };
 
 /// Object containing the standalone environment information.
@@ -237,20 +237,9 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                 self.result.module.types.reserve(num);
                 self.types.reserve_wasm_signatures(num);
 
-                for ty in types {
-                    let ty = ty?;
-                    if ty.is_final || ty.supertype_idx.is_some() {
-                        unimplemented!("gc proposal")
-                    }
-                    match ty.structural_type {
-                        StructuralType::Func(wasm_func_ty) => {
-                            let ty = self.convert_func_type(&wasm_func_ty);
-                            self.declare_type_func(ty)?;
-                        }
-                        StructuralType::Array(_) | StructuralType::Struct(_) => {
-                            unimplemented!("gc proposal")
-                        }
-                    }
+                for ty in types.into_iter_err_on_gc_types() {
+                    let ty = self.convert_func_type(&ty?);
+                    self.declare_type_func(ty)?;
                 }
             }
 
diff --git a/crates/environ/src/module_types.rs b/crates/environ/src/module_types.rs
index 026f6b36e..287cbb667 100644
--- a/crates/environ/src/module_types.rs
+++ b/crates/environ/src/module_types.rs
@@ -1,5 +1,5 @@
 use crate::{PrimaryMap, SignatureIndex, WasmFuncType};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::ops::Index;
 
diff --git a/crates/environ/src/stack_map.rs b/crates/environ/src/stack_map.rs
index 44c1f7a08..a6cbc5a83 100644
--- a/crates/environ/src/stack_map.rs
+++ b/crates/environ/src/stack_map.rs
@@ -1,4 +1,4 @@
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// A map for determining where live GC references live in a stack frame.
 ///
diff --git a/crates/environ/src/tunables.rs b/crates/environ/src/tunables.rs
index 49b21fe24..06d6b5ca5 100644
--- a/crates/environ/src/tunables.rs
+++ b/crates/environ/src/tunables.rs
@@ -1,4 +1,4 @@
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 
 /// Tunable parameters for WebAssembly compilation.
 #[derive(Clone, Hash, Serialize, Deserialize)]
diff --git a/crates/explorer/Cargo.toml b/crates/explorer/Cargo.toml
index 59eff18c9..408518e1e 100644
--- a/crates/explorer/Cargo.toml
+++ b/crates/explorer/Cargo.toml
@@ -12,6 +12,7 @@ version.workspace = true
 anyhow = { workspace = true }
 capstone = { workspace = true }
 serde = { workspace = true }
+serde_derive = { workspace = true }
 serde_json = { workspace = true }
 target-lexicon = { workspace = true }
 wasmprinter = { workspace = true }
diff --git a/crates/explorer/src/lib.rs b/crates/explorer/src/lib.rs
index 5dab3e847..0b92aae71 100644
--- a/crates/explorer/src/lib.rs
+++ b/crates/explorer/src/lib.rs
@@ -1,6 +1,6 @@
 use anyhow::Result;
 use capstone::arch::BuildsCapstone;
-use serde::Serialize;
+use serde_derive::Serialize;
 use std::{io::Write, str::FromStr};
 
 pub fn generate(
diff --git a/crates/fuzzing/src/generators/component_types.rs b/crates/fuzzing/src/generators/component_types.rs
index 36ea589a5..80b2838b1 100644
--- a/crates/fuzzing/src/generators/component_types.rs
+++ b/crates/fuzzing/src/generators/component_types.rs
@@ -78,15 +78,6 @@ pub fn arbitrary_val(ty: &component::Type, input: &mut Unstructured) -> arbitrar
             let name = input.choose(&names)?;
             en.new_val(name).unwrap()
         }
-        Type::Union(un) => {
-            let mut types = un.types();
-            let discriminant = input.int_in_range(0..=types.len() - 1)?;
-            un.new_val(
-                discriminant.try_into().unwrap(),
-                arbitrary_val(&types.nth(discriminant).unwrap(), input)?,
-            )
-            .unwrap()
-        }
         Type::Option(option) => {
             let discriminant = input.int_in_range(0..=1)?;
             option
diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml
index d1f536ae1..25cf74bbb 100644
--- a/crates/jit/Cargo.toml
+++ b/crates/jit/Cargo.toml
@@ -19,7 +19,8 @@ anyhow = { workspace = true }
 cfg-if = { workspace = true }
 gimli = { workspace = true }
 object = { workspace = true }
-serde = { version = "1.0.94", features = ["derive"] }
+serde = "1.0.188"
+serde_derive = "1.0.188"
 addr2line = { version = "0.21.0", default-features = false }
 bincode = "1.2.1"
 rustc-demangle = "0.1.16"
diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs
index 3330245f6..2a3c7bd42 100644
--- a/crates/jit/src/instantiate.rs
+++ b/crates/jit/src/instantiate.rs
@@ -9,7 +9,7 @@ use crate::profiling::ProfilingAgent;
 use anyhow::{bail, Context, Error, Result};
 use object::write::{Object, SectionId, StandardSegment, WritableBuffer};
 use object::SectionKind;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::convert::TryFrom;
 use std::ops::Range;
 use std::str;
diff --git a/crates/misc/component-fuzz-util/src/lib.rs b/crates/misc/component-fuzz-util/src/lib.rs
index 8d5c6458a..477681b6b 100644
--- a/crates/misc/component-fuzz-util/src/lib.rs
+++ b/crates/misc/component-fuzz-util/src/lib.rs
@@ -126,7 +126,6 @@ pub enum Type {
     // least one case.
     Variant(VecInRange<Option<Type>, 1, 200>),
     Enum(u32),
-    Union(VecInRange<Type, 1, 200>),
 
     Option(Box<Type>),
     Result {
@@ -144,7 +143,7 @@ impl Type {
         fuel: &mut u32,
     ) -> arbitrary::Result<Type> {
         *fuel = fuel.saturating_sub(1);
-        let max = if depth == 0 || *fuel == 0 { 12 } else { 21 };
+        let max = if depth == 0 || *fuel == 0 { 12 } else { 20 };
         Ok(match u.int_in_range(0..=max)? {
             0 => Type::Bool,
             1 => Type::S8,
@@ -171,13 +170,12 @@ impl Type {
                 *fuel -= amt;
                 Type::Enum(amt)
             }
-            18 => Type::Union(Type::generate_list(u, depth - 1, fuel)?),
-            19 => Type::Option(Box::new(Type::generate(u, depth - 1, fuel)?)),
-            20 => Type::Result {
+            18 => Type::Option(Box::new(Type::generate(u, depth - 1, fuel)?)),
+            19 => Type::Result {
                 ok: Type::generate_opt(u, depth - 1, fuel)?.map(Box::new),
                 err: Type::generate_opt(u, depth - 1, fuel)?.map(Box::new),
             },
-            21 => {
+            20 => {
                 // Generate 1 flag all the way up to 65 flags which exercises
                 // the 1 to 3 x u32 cases.
                 let amt = u.int_in_range(1..=(*fuel).min(65))?;
@@ -276,7 +274,6 @@ impl Type {
             Type::Record(types) => lower_record(types.iter(), vec),
             Type::Tuple(types) => lower_record(types.0.iter(), vec),
             Type::Variant(types) => lower_variant(types.0.iter().map(|t| t.as_ref()), vec),
-            Type::Union(types) => lower_variant(types.0.iter().map(Some), vec),
             Type::Option(ty) => lower_variant([None, Some(&**ty)].into_iter(), vec),
             Type::Result { ok, err } => {
                 lower_variant([ok.as_deref(), err.as_deref()].into_iter(), vec)
@@ -319,7 +316,6 @@ impl Type {
             Type::Tuple(types) => record_size_and_alignment(types.0.iter()),
 
             Type::Variant(types) => variant_size_and_alignment(types.0.iter().map(|t| t.as_ref())),
-            Type::Union(types) => variant_size_and_alignment(types.0.iter().map(Some)),
 
             Type::Enum(count) => variant_size_and_alignment((0..*count).map(|_| None)),
 
@@ -566,29 +562,6 @@ pub fn rust_type(ty: &Type, name_counter: &mut u32, declarations: &mut TokenStre
 
             quote!(#name)
         }
-        Type::Union(types) => {
-            let cases = types
-                .0
-                .iter()
-                .enumerate()
-                .map(|(index, ty)| {
-                    let name = format_ident!("U{index}");
-                    let ty = rust_type(ty, name_counter, declarations);
-                    quote!(#name(#ty),)
-                })
-                .collect::<TokenStream>();
-            let name = make_rust_name(name_counter);
-
-            declarations.extend(quote! {
-                #[derive(ComponentType, Lift, Lower, PartialEq, Debug, Clone, Arbitrary)]
-                #[component(union)]
-                enum #name {
-                    #cases
-                }
-            });
-
-            quote!(#name)
-        }
         Type::Enum(count) => {
             let cases = (0..*count)
                 .map(|index| {
@@ -692,7 +665,6 @@ impl<'a> TypesBuilder<'a> {
             | Type::Tuple(_)
             | Type::Variant(_)
             | Type::Enum(_)
-            | Type::Union(_)
             | Type::Option(_)
             | Type::Result { .. }
             | Type::Flags(_) => {
@@ -762,14 +734,6 @@ impl<'a> TypesBuilder<'a> {
                 }
                 decl.push_str(")");
             }
-            Type::Union(types) => {
-                decl.push_str("(union");
-                for ty in types.iter() {
-                    decl.push_str(" ");
-                    self.write_ref(ty, &mut decl);
-                }
-                decl.push_str(")");
-            }
             Type::Option(ty) => {
                 decl.push_str("(option ");
                 self.write_ref(ty, &mut decl);
diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml
index a94f0e22d..33925d7b0 100644
--- a/crates/types/Cargo.toml
+++ b/crates/types/Cargo.toml
@@ -10,6 +10,7 @@ edition.workspace = true
 
 [dependencies]
 cranelift-entity = { workspace = true, features = ['enable-serde'] }
-serde = { version = "1.0.94", features = ["derive"] }
+serde = "1.0.188"
+serde_derive = "1.0.188"
 thiserror = { workspace = true }
 wasmparser = { workspace = true }
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index 320c6e479..125be22ce 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -4,7 +4,7 @@
 pub use wasmparser;
 
 use cranelift_entity::entity_impl;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::fmt;
 
 mod error;
diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml
index bbe6865ae..56a696d4c 100644
--- a/crates/wasmtime/Cargo.toml
+++ b/crates/wasmtime/Cargo.toml
@@ -35,7 +35,8 @@ libc = "0.2"
 cfg-if = { workspace = true }
 log = { workspace = true }
 wat = { workspace = true, optional = true }
-serde = { version = "1.0.94", features = ["derive"] }
+serde = "1.0.188"
+serde_derive = "1.0.188"
 serde_json = { workspace = true }
 bincode = "1.2.1"
 indexmap = { workspace = true }
@@ -131,4 +132,4 @@ component-model = [
   "dep:encoding_rs",
 ]
 
-wmemcheck = ["wasmtime-runtime/wmemcheck", "wasmtime-cranelift/wmemcheck"]
\ No newline at end of file
+wmemcheck = ["wasmtime-runtime/wmemcheck", "wasmtime-cranelift/wmemcheck"]
diff --git a/crates/wasmtime/src/component/component.rs b/crates/wasmtime/src/component/component.rs
index 1b865f7c5..47b29d988 100644
--- a/crates/wasmtime/src/component/component.rs
+++ b/crates/wasmtime/src/component/component.rs
@@ -2,7 +2,7 @@ use crate::code::CodeObject;
 use crate::signatures::SignatureCollection;
 use crate::{Engine, Module, ResourcesRequired};
 use anyhow::{bail, Context, Result};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::fs;
 use std::mem;
 use std::path::Path;
diff --git a/crates/wasmtime/src/component/func/typed.rs b/crates/wasmtime/src/component/func/typed.rs
index 1295994da..93b74c138 100644
--- a/crates/wasmtime/src/component/func/typed.rs
+++ b/crates/wasmtime/src/component/func/typed.rs
@@ -1659,34 +1659,6 @@ pub fn typecheck_enum(
     }
 }
 
-/// Verify that the given wasm type is a union with the expected cases in the right order.
-pub fn typecheck_union(
-    ty: &InterfaceType,
-    types: &InstanceType<'_>,
-    expected: &[fn(&InterfaceType, &InstanceType<'_>) -> Result<()>],
-) -> Result<()> {
-    match ty {
-        InterfaceType::Union(index) => {
-            let union_types = &types.types[*index].types;
-
-            if union_types.len() != expected.len() {
-                bail!(
-                    "expected union of {} types, found {} types",
-                    expected.len(),
-                    union_types.len()
-                );
-            }
-
-            for (index, (ty, check)) in union_types.iter().zip(expected).enumerate() {
-                check(ty, types).with_context(|| format!("type mismatch for case {}", index))?;
-            }
-
-            Ok(())
-        }
-        other => bail!("expected `union` found `{}`", desc(other)),
-    }
-}
-
 /// Verify that the given wasm type is a flags type with the expected flags in the right order and with the right
 /// names.
 pub fn typecheck_flags(
@@ -2310,7 +2282,6 @@ pub fn desc(ty: &InterfaceType) -> &'static str {
         InterfaceType::Variant(_) => "variant",
         InterfaceType::Flags(_) => "flags",
         InterfaceType::Enum(_) => "enum",
-        InterfaceType::Union(_) => "union",
         InterfaceType::Own(_) => "owned resource",
         InterfaceType::Borrow(_) => "borrowed resource",
     }
diff --git a/crates/wasmtime/src/component/mod.rs b/crates/wasmtime/src/component/mod.rs
index a486ebe68..4129975de 100644
--- a/crates/wasmtime/src/component/mod.rs
+++ b/crates/wasmtime/src/component/mod.rs
@@ -23,9 +23,7 @@ pub use self::instance::{ExportInstance, Exports, Instance, InstancePre};
 pub use self::linker::{Linker, LinkerInstance};
 pub use self::resources::{Resource, ResourceAny};
 pub use self::types::{ResourceType, Type};
-pub use self::values::{
-    Enum, Flags, List, OptionVal, Record, ResultVal, Tuple, Union, Val, Variant,
-};
+pub use self::values::{Enum, Flags, List, OptionVal, Record, ResultVal, Tuple, Val, Variant};
 pub use wasmtime_component_macro::{flags, ComponentType, Lift, Lower};
 
 // These items are expected to be used by an eventual
@@ -35,8 +33,8 @@ pub use wasmtime_component_macro::{flags, ComponentType, Lift, Lower};
 pub mod __internal {
     pub use super::func::{
         bad_type_info, format_flags, lower_payload, typecheck_enum, typecheck_flags,
-        typecheck_record, typecheck_union, typecheck_variant, ComponentVariant, LiftContext,
-        LowerContext, MaybeUninitExt, Options,
+        typecheck_record, typecheck_variant, ComponentVariant, LiftContext, LowerContext,
+        MaybeUninitExt, Options,
     };
     pub use super::matching::InstanceType;
     pub use crate::map_maybe_uninit;
diff --git a/crates/wasmtime/src/component/types.rs b/crates/wasmtime/src/component/types.rs
index 23d08ba1b..43b25a13c 100644
--- a/crates/wasmtime/src/component/types.rs
+++ b/crates/wasmtime/src/component/types.rs
@@ -10,7 +10,7 @@ use std::sync::Arc;
 use wasmtime_environ::component::{
     CanonicalAbiInfo, ComponentTypes, InterfaceType, ResourceIndex, TypeEnumIndex, TypeFlagsIndex,
     TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResultIndex, TypeTupleIndex,
-    TypeUnionIndex, TypeVariantIndex,
+    TypeVariantIndex,
 };
 use wasmtime_environ::PrimaryMap;
 
@@ -210,29 +210,6 @@ impl Enum {
     }
 }
 
-/// A `union` interface type
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct Union(Handle<TypeUnionIndex>);
-
-impl Union {
-    /// Instantiate this type with the specified `discriminant` and `value`.
-    pub fn new_val(&self, discriminant: u32, value: Val) -> Result<Val> {
-        Ok(Val::Union(values::Union::new(self, discriminant, value)?))
-    }
-
-    pub(crate) fn from(index: TypeUnionIndex, ty: &InstanceType<'_>) -> Self {
-        Union(Handle::new(index, ty))
-    }
-
-    /// Retrieve the types of the cases of this `union` in declaration order.
-    pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
-        self.0.types[self.0.index]
-            .types
-            .iter()
-            .map(|ty| Type::from(ty, &self.0.instance()))
-    }
-}
-
 /// An `option` interface type
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct OptionType(Handle<TypeOptionIndex>);
@@ -333,7 +310,6 @@ pub enum Type {
     Tuple(Tuple),
     Variant(Variant),
     Enum(Enum),
-    Union(Union),
     Option(OptionType),
     Result(ResultType),
     Flags(Flags),
@@ -407,19 +383,6 @@ impl Type {
         }
     }
 
-    /// Retrieve the inner [`Union`] of a [`Type::Union`].
-    ///
-    /// # Panics
-    ///
-    /// This will panic if `self` is not a [`Type::Union`].
-    pub fn unwrap_union(&self) -> &Union {
-        if let Type::Union(handle) = self {
-            &handle
-        } else {
-            panic!("attempted to unwrap a {} as a union", self.desc())
-        }
-    }
-
     /// Retrieve the inner [`OptionType`] of a [`Type::Option`].
     ///
     /// # Panics
@@ -522,7 +485,6 @@ impl Type {
             InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
             InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
             InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
-            InterfaceType::Union(index) => Type::Union(Union::from(*index, instance)),
             InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
             InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
             InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
@@ -551,7 +513,6 @@ impl Type {
             Type::Tuple(_) => "tuple",
             Type::Variant(_) => "variant",
             Type::Enum(_) => "enum",
-            Type::Union(_) => "union",
             Type::Option(_) => "option",
             Type::Result(_) => "result",
             Type::Flags(_) => "flags",
diff --git a/crates/wasmtime/src/component/values.rs b/crates/wasmtime/src/component/values.rs
index f40a8f473..332a0659a 100644
--- a/crates/wasmtime/src/component/values.rs
+++ b/crates/wasmtime/src/component/values.rs
@@ -328,79 +328,6 @@ impl fmt::Debug for Enum {
     }
 }
 
-/// Represents runtime union values
-#[derive(PartialEq, Eq, Clone)]
-pub struct Union {
-    ty: types::Union,
-    discriminant: u32,
-    value: Option<Box<Val>>,
-}
-
-impl Union {
-    /// Instantiate the specified type with the specified `discriminant` and `value`.
-    pub fn new(ty: &types::Union, discriminant: u32, value: Val) -> Result<Self> {
-        if let Some(case_ty) = ty.types().nth(usize::try_from(discriminant)?) {
-            case_ty
-                .check(&value)
-                .with_context(|| format!("type mismatch for case {discriminant} of union"))?;
-
-            Ok(Self {
-                ty: ty.clone(),
-                discriminant,
-                value: Some(Box::new(value)),
-            })
-        } else {
-            Err(anyhow!(
-                "discriminant {discriminant} out of range: [0,{})",
-                ty.types().len()
-            ))
-        }
-    }
-
-    /// Returns the type of this value.
-    pub fn ty(&self) -> &types::Union {
-        &self.ty
-    }
-
-    /// Returns name of the discriminant of this value within the union type.
-    pub fn discriminant(&self) -> u32 {
-        self.discriminant
-    }
-
-    /// Returns the payload value for this union.
-    pub fn payload(&self) -> &Val {
-        self.value.as_ref().unwrap()
-    }
-
-    fn as_generic<'a>(
-        &'a self,
-        types: &'a ComponentTypes,
-        ty: InterfaceType,
-    ) -> GenericVariant<'a> {
-        let ty = match ty {
-            InterfaceType::Union(i) => &types[i],
-            _ => bad_type_info(),
-        };
-        GenericVariant {
-            discriminant: self.discriminant,
-            abi: &ty.abi,
-            info: &ty.info,
-            payload: self
-                .value
-                .as_deref()
-                .zip(Some(ty.types[self.discriminant as usize])),
-        }
-    }
-}
-
-impl fmt::Debug for Union {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple(&format!("U{}", self.discriminant()))
-            .field(self.payload())
-            .finish()
-    }
-}
-
 /// Represents runtime option values
 #[derive(PartialEq, Eq, Clone)]
 pub struct OptionVal {
@@ -652,7 +579,6 @@ pub enum Val {
     Tuple(Tuple),
     Variant(Variant),
     Enum(Enum),
-    Union(Union),
     Option(OptionVal),
     Result(ResultVal),
     Flags(Flags),
@@ -681,7 +607,6 @@ impl Val {
             Val::Tuple(Tuple { ty, .. }) => Type::Tuple(ty.clone()),
             Val::Variant(Variant { ty, .. }) => Type::Variant(ty.clone()),
             Val::Enum(Enum { ty, .. }) => Type::Enum(ty.clone()),
-            Val::Union(Union { ty, .. }) => Type::Union(ty.clone()),
             Val::Option(OptionVal { ty, .. }) => Type::Option(ty.clone()),
             Val::Result(ResultVal { ty, .. }) => Type::Result(ty.clone()),
             Val::Flags(Flags { ty, .. }) => Type::Flags(ty.clone()),
@@ -769,20 +694,6 @@ impl Val {
                     discriminant,
                 })
             }
-            InterfaceType::Union(i) => {
-                let (discriminant, value) = lift_variant(
-                    cx,
-                    cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
-                    cx.types[i].types.iter().copied().map(Some),
-                    src,
-                )?;
-
-                Val::Union(Union {
-                    ty: types::Union::from(i, &cx.instance_type()),
-                    discriminant,
-                    value,
-                })
-            }
             InterfaceType::Option(i) => {
                 let (discriminant, value) = lift_variant(
                     cx,
@@ -883,17 +794,6 @@ impl Val {
                     discriminant,
                 })
             }
-            InterfaceType::Union(i) => {
-                let ty = &cx.types[i];
-                let (discriminant, value) =
-                    load_variant(cx, &ty.info, ty.types.iter().copied().map(Some), bytes)?;
-
-                Val::Union(Union {
-                    ty: types::Union::from(i, &cx.instance_type()),
-                    discriminant,
-                    value,
-                })
-            }
             InterfaceType::Option(i) => {
                 let ty = &cx.types[i];
                 let (discriminant, value) =
@@ -997,7 +897,6 @@ impl Val {
                 }
             }
             Val::Variant(v) => v.as_generic(cx.types, ty).lower(cx, dst)?,
-            Val::Union(v) => v.as_generic(cx.types, ty).lower(cx, dst)?,
             Val::Option(v) => v.as_generic(cx.types, ty).lower(cx, dst)?,
             Val::Result(v) => v.as_generic(cx.types, ty).lower(cx, dst)?,
             Val::Enum(Enum { discriminant, .. }) => {
@@ -1080,7 +979,6 @@ impl Val {
 
             Val::Variant(v) => v.as_generic(cx.types, ty).store(cx, offset)?,
             Val::Enum(v) => v.as_generic(cx.types, ty).store(cx, offset)?,
-            Val::Union(v) => v.as_generic(cx.types, ty).store(cx, offset)?,
             Val::Option(v) => v.as_generic(cx.types, ty).store(cx, offset)?,
             Val::Result(v) => v.as_generic(cx.types, ty).store(cx, offset)?,
 
@@ -1165,8 +1063,6 @@ impl PartialEq for Val {
             (Self::Variant(_), _) => false,
             (Self::Enum(l), Self::Enum(r)) => l == r,
             (Self::Enum(_), _) => false,
-            (Self::Union(l), Self::Union(r)) => l == r,
-            (Self::Union(_), _) => false,
             (Self::Option(l), Self::Option(r)) => l == r,
             (Self::Option(_), _) => false,
             (Self::Result(l), Self::Result(r)) => l == r,
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index bfc14b115..e6d4c905f 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -1,7 +1,7 @@
 use crate::memory::MemoryCreator;
 use crate::trampoline::MemoryCreatorProxy;
 use anyhow::{bail, ensure, Result};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::{HashMap, HashSet};
 use std::fmt;
 #[cfg(any(feature = "cache", feature = "cranelift", feature = "winch"))]
diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs
index 7898738ed..8aa35208b 100644
--- a/crates/wasmtime/src/engine/serialization.rs
+++ b/crates/wasmtime/src/engine/serialization.rs
@@ -25,7 +25,7 @@ use crate::{Engine, ModuleVersionStrategy, Precompiled};
 use anyhow::{anyhow, bail, Context, Result};
 use object::write::{Object, StandardSegment};
 use object::{File, FileFlags, Object as _, ObjectSection, SectionKind};
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::BTreeMap;
 use std::str::FromStr;
 use wasmtime_environ::obj;
diff --git a/crates/wast/src/component.rs b/crates/wast/src/component.rs
index 497500982..2ce11c865 100644
--- a/crates/wast/src/component.rs
+++ b/crates/wast/src/component.rs
@@ -87,17 +87,6 @@ pub fn val(v: &WastVal<'_>, ty: &Type) -> Result<Val> {
             }
             _ => bail!("expected a variant value"),
         },
-        WastVal::Union(idx, payload) => match ty {
-            Type::Union(t) => {
-                let case = match t.types().nth(*idx as usize) {
-                    Some(case) => case,
-                    None => bail!("case {idx} too large"),
-                };
-                let payload = val(payload, &case)?;
-                t.new_val(*idx, payload)?
-            }
-            _ => bail!("expected a union value"),
-        },
         WastVal::Option(v) => match ty {
             Type::Option(t) => {
                 let v = match v {
@@ -260,15 +249,6 @@ pub fn match_val(expected: &WastVal<'_>, actual: &Val) -> Result<()> {
             }
             _ => mismatch(expected, actual),
         },
-        WastVal::Union(idx, e) => match actual {
-            Val::Union(a) => {
-                if a.discriminant() != *idx {
-                    bail!("expected discriminant `{idx}` got `{}`", a.discriminant());
-                }
-                match_val(e, a.payload())
-            }
-            _ => mismatch(expected, actual),
-        },
         WastVal::Option(e) => match actual {
             Val::Option(a) => match (e, a.value()) {
                 (None, None) => Ok(()),
@@ -348,7 +328,6 @@ fn mismatch(expected: &WastVal<'_>, actual: &Val) -> Result<()> {
         WastVal::Tuple(..) => "tuple",
         WastVal::Enum(..) => "enum",
         WastVal::Variant(..) => "variant",
-        WastVal::Union(..) => "union",
         WastVal::Option(..) => "option",
         WastVal::Result(..) => "result",
         WastVal::Flags(..) => "flags",
@@ -372,7 +351,6 @@ fn mismatch(expected: &WastVal<'_>, actual: &Val) -> Result<()> {
         Val::Tuple(..) => "tuple",
         Val::Enum(..) => "enum",
         Val::Variant(..) => "variant",
-        Val::Union(..) => "union",
         Val::Option(..) => "option",
         Val::Result(..) => "result",
         Val::Flags(..) => "flags",
diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs
index 2d86124f1..09a47e212 100644
--- a/crates/wit-bindgen/src/lib.rs
+++ b/crates/wit-bindgen/src/lib.rs
@@ -765,7 +765,6 @@ impl<'a> InterfaceGenerator<'a> {
             TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs),
             TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs),
             TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs),
-            TypeDefKind::Union(u) => self.type_union(id, name, u, &ty.docs),
             TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs),
             TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs),
             TypeDefKind::Future(_) => todo!("generate for future"),
@@ -902,16 +901,6 @@ impl<'a> InterfaceGenerator<'a> {
         );
     }
 
-    fn type_union(&mut self, id: TypeId, _name: &str, union: &Union, docs: &Docs) {
-        self.print_rust_enum(
-            id,
-            std::iter::zip(self.union_case_names(union), &union.cases)
-                .map(|(name, case)| (name, None, &case.docs, Some(&case.ty))),
-            docs,
-            "union",
-        );
-    }
-
     fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
         let info = self.info(id);
 
diff --git a/crates/wit-bindgen/src/rust.rs b/crates/wit-bindgen/src/rust.rs
index ec9f729c5..48100dfaf 100644
--- a/crates/wit-bindgen/src/rust.rs
+++ b/crates/wit-bindgen/src/rust.rs
@@ -1,7 +1,5 @@
 use crate::{types::TypeInfo, Ownership};
 use heck::*;
-use std::collections::HashMap;
-use std::fmt::Write;
 use wit_parser::*;
 
 #[derive(Debug, Copy, Clone, PartialEq)]
@@ -117,7 +115,6 @@ pub trait RustGenerator<'a> {
                     | TypeDefKind::Flags(_)
                     | TypeDefKind::Enum(_)
                     | TypeDefKind::Tuple(_)
-                    | TypeDefKind::Union(_)
                     | TypeDefKind::Handle(_)
                     | TypeDefKind::Resource => true,
                     TypeDefKind::Type(Type::Id(t)) => {
@@ -169,9 +166,6 @@ pub trait RustGenerator<'a> {
             TypeDefKind::Enum(_) => {
                 panic!("unsupported anonymous type reference: enum")
             }
-            TypeDefKind::Union(_) => {
-                panic!("unsupported anonymous type reference: union")
-            }
             TypeDefKind::Future(ty) => {
                 self.push_str("Future<");
                 self.print_optional_ty(ty.as_ref(), mode);
@@ -250,119 +244,6 @@ pub trait RustGenerator<'a> {
         result
     }
 
-    /// Writes the camel-cased 'name' of the passed type to `out`, as used to name union variants.
-    fn write_name(&self, ty: &Type, out: &mut String) {
-        match ty {
-            Type::Bool => out.push_str("Bool"),
-            Type::U8 => out.push_str("U8"),
-            Type::U16 => out.push_str("U16"),
-            Type::U32 => out.push_str("U32"),
-            Type::U64 => out.push_str("U64"),
-            Type::S8 => out.push_str("I8"),
-            Type::S16 => out.push_str("I16"),
-            Type::S32 => out.push_str("I32"),
-            Type::S64 => out.push_str("I64"),
-            Type::Float32 => out.push_str("F32"),
-            Type::Float64 => out.push_str("F64"),
-            Type::Char => out.push_str("Char"),
-            Type::String => out.push_str("String"),
-            Type::Id(id) => {
-                let ty = &self.resolve().types[*id];
-                match &ty.name {
-                    Some(name) => out.push_str(&name.to_upper_camel_case()),
-                    None => match &ty.kind {
-                        TypeDefKind::Option(ty) => {
-                            out.push_str("Optional");
-                            self.write_name(ty, out);
-                        }
-                        TypeDefKind::Result(_) => out.push_str("Result"),
-                        TypeDefKind::Tuple(_) => out.push_str("Tuple"),
-                        TypeDefKind::List(ty) => {
-                            self.write_name(ty, out);
-                            out.push_str("List")
-                        }
-                        TypeDefKind::Future(ty) => {
-                            self.write_optional_name(ty.as_ref(), out);
-                            out.push_str("Future");
-                        }
-                        TypeDefKind::Stream(s) => {
-                            self.write_optional_name(s.element.as_ref(), out);
-                            self.write_optional_name(s.end.as_ref(), out);
-                            out.push_str("Stream");
-                        }
-
-                        TypeDefKind::Type(ty) => self.write_name(ty, out),
-                        TypeDefKind::Record(_) => out.push_str("Record"),
-                        TypeDefKind::Flags(_) => out.push_str("Flags"),
-                        TypeDefKind::Variant(_) => out.push_str("Variant"),
-                        TypeDefKind::Enum(_) => out.push_str("Enum"),
-                        TypeDefKind::Union(_) => out.push_str("Union"),
-                        TypeDefKind::Handle(_) => todo!("#6722"),
-                        TypeDefKind::Resource => todo!("#6722"),
-                        TypeDefKind::Unknown => unreachable!(),
-                    },
-                }
-            }
-        }
-    }
-
-    fn write_optional_name(&self, ty: Option<&Type>, out: &mut String) {
-        match ty {
-            Some(ty) => self.write_name(ty, out),
-            None => out.push_str("()"),
-        }
-    }
-
-    /// Returns the names for the cases of the passed union.
-    fn union_case_names(&self, union: &Union) -> Vec<String> {
-        enum UsedState<'a> {
-            /// This name has been used once before.
-            ///
-            /// Contains a reference to the name given to the first usage so that a suffix can be added to it.
-            Once(&'a mut String),
-            /// This name has already been used multiple times.
-            ///
-            /// Contains the number of times this has already been used.
-            Multiple(usize),
-        }
-
-        // A `Vec` of the names we're assigning each of the union's cases in order.
-        let mut case_names = vec![String::new(); union.cases.len()];
-        // A map from case names to their `UsedState`.
-        let mut used = HashMap::new();
-        for (case, name) in union.cases.iter().zip(case_names.iter_mut()) {
-            self.write_name(&case.ty, name);
-
-            match used.get_mut(name.as_str()) {
-                None => {
-                    // Initialise this name's `UsedState`, with a mutable reference to this name
-                    // in case we have to add a suffix to it later.
-                    used.insert(name.clone(), UsedState::Once(name));
-                    // Since this is the first (and potentially only) usage of this name,
-                    // we don't need to add a suffix here.
-                }
-                Some(state) => match state {
-                    UsedState::Multiple(n) => {
-                        // Add a suffix of the index of this usage.
-                        write!(name, "{n}").unwrap();
-                        // Add one to the number of times this type has been used.
-                        *n += 1;
-                    }
-                    UsedState::Once(first) => {
-                        // Add a suffix of 0 to the first usage.
-                        first.push('0');
-                        // We now get a suffix of 1.
-                        name.push('1');
-                        // Then update the state.
-                        *state = UsedState::Multiple(2);
-                    }
-                },
-            }
-        }
-
-        case_names
-    }
-
     fn param_name(&self, ty: TypeId) -> String {
         let info = self.info(ty);
         let name = self.resolve().types[ty]
diff --git a/crates/wit-bindgen/src/types.rs b/crates/wit-bindgen/src/types.rs
index 9f8d9e89c..ad9d25b67 100644
--- a/crates/wit-bindgen/src/types.rs
+++ b/crates/wit-bindgen/src/types.rs
@@ -146,11 +146,6 @@ impl Types {
                 info = self.optional_type_info(resolve, r.ok.as_ref());
                 info |= self.optional_type_info(resolve, r.err.as_ref());
             }
-            TypeDefKind::Union(u) => {
-                for case in u.cases.iter() {
-                    info |= self.type_info(resolve, &case.ty);
-                }
-            }
             TypeDefKind::Future(ty) => {
                 info = self.optional_type_info(resolve, ty.as_ref());
             }
diff --git a/src/commands/settings.rs b/src/commands/settings.rs
index 54f2c1817..b51475d90 100644
--- a/src/commands/settings.rs
+++ b/src/commands/settings.rs
@@ -36,7 +36,7 @@ impl Serialize for SettingData {
 }
 
 // Gather together all of the setting data to displays
-#[derive(Serialize)]
+#[derive(serde_derive::Serialize)]
 struct Settings {
     triple: String,
 
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 8164ef4d2..4d6251cb6 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -670,6 +670,13 @@ user-id = 3618
 user-login = "dtolnay"
 user-name = "David Tolnay"
 
+[[publisher.serde]]
+version = "1.0.188"
+when = "2023-08-26"
+user-id = 3618
+user-login = "dtolnay"
+user-name = "David Tolnay"
+
 [[publisher.serde_derive]]
 version = "1.0.171"
 when = "2023-07-10"
@@ -677,6 +684,13 @@ user-id = 3618
 user-login = "dtolnay"
 user-name = "David Tolnay"
 
+[[publisher.serde_derive]]
+version = "1.0.188"
+when = "2023-08-26"
+user-id = 3618
+user-login = "dtolnay"
+user-name = "David Tolnay"
+
 [[publisher.serde_json]]
 version = "1.0.80"
 when = "2022-04-30"
@@ -704,6 +718,13 @@ user-id = 3618
 user-login = "dtolnay"
 user-name = "David Tolnay"
 
+[[publisher.syn]]
+version = "2.0.29"
+when = "2023-08-17"
+user-id = 3618
+user-login = "dtolnay"
+user-name = "David Tolnay"
+
 [[publisher.system-interface]]
 version = "0.26.0"
 when = "2023-06-30"
@@ -841,6 +862,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-encoder]]
+version = "0.32.0"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-metadata]]
 version = "0.9.0"
 when = "2023-07-11"
@@ -862,6 +890,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-metadata]]
+version = "0.10.3"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-mutate]]
 version = "0.2.30"
 when = "2023-07-26"
@@ -876,6 +911,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-mutate]]
+version = "0.2.32"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-smith]]
 version = "0.12.13"
 when = "2023-07-26"
@@ -890,6 +932,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-smith]]
+version = "0.12.15"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmparser]]
 version = "0.108.0"
 when = "2023-07-11"
@@ -911,6 +960,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmparser]]
+version = "0.112.0"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmprinter]]
 version = "0.2.62"
 when = "2023-07-26"
@@ -925,6 +981,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmprinter]]
+version = "0.2.64"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmtime]]
 version = "11.0.1"
 when = "2023-07-24"
@@ -1083,6 +1146,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wast]]
+version = "64.0.0"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wat]]
 version = "1.0.69"
 when = "2023-07-26"
@@ -1097,6 +1167,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wat]]
+version = "1.0.71"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wiggle]]
 version = "11.0.1"
 when = "2023-07-24"
@@ -1261,6 +1338,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-component]]
+version = "0.14.0"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-parser]]
 version = "0.9.2"
 when = "2023-07-26"
@@ -1275,6 +1359,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-parser]]
+version = "0.11.0"
+when = "2023-08-25"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[audits.embark-studios.wildcard-audits.spdx]]
 who = "Jake Shadle <opensource@embark-studios.com>"
 criteria = "safe-to-deploy"


Test patch:
diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml
index a5e1bd764..f3618d0de 100644
--- a/cranelift/filetests/Cargo.toml
+++ b/cranelift/filetests/Cargo.toml
@@ -30,6 +30,7 @@ similar ={ workspace = true }
 wat.workspace = true
 toml = { workspace = true }
 serde = { workspace = true }
+serde_derive = { workspace = true }
 cranelift-wasm.workspace = true
 wasmparser.workspace = true
 cranelift.workspace = true
diff --git a/cranelift/filetests/filetests/isa/riscv64/amodes.clif b/cranelift/filetests/filetests/isa/riscv64/amodes.clif
index 283f48080..8aeed39f4 100644
--- a/cranelift/filetests/filetests/isa/riscv64/amodes.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/amodes.clif
@@ -142,21 +142,21 @@ block0(v0: i64, v1: i64, v2: i64):
 
 ; VCode:
 ; block0:
-;   lui a6,1
-;   addi a6,a6,4
-;   add a7,a0,a1
-;   add a7,a7,a2
-;   add a6,a7,a6
+;   lui a5,1
+;   addi a7,a5,4
+;   add a6,a0,a1
+;   add a6,a6,a2
+;   add a6,a6,a7
 ;   lw a0,0(a6)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a6, 1
-;   addi a6, a6, 4
-;   add a7, a0, a1
-;   add a7, a7, a2
-;   add a6, a7, a6
+;   lui a5, 1
+;   addi a7, a5, 4
+;   add a6, a0, a1
+;   add a6, a6, a2
+;   add a6, a6, a7
 ;   lw a0, 0(a6)
 ;   ret
 
@@ -231,17 +231,17 @@ block0(v0: i64):
 
 ; VCode:
 ; block0:
-;   lui a2,244141
-;   addi a2,a2,2560
-;   add a2,a0,a2
+;   lui a1,244141
+;   addi a3,a1,2560
+;   add a2,a0,a3
 ;   lw a0,0(a2)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a2, 0x3b9ad
-;   addi a2, a2, -0x600
-;   add a2, a0, a2
+;   lui a1, 0x3b9ad
+;   addi a3, a1, -0x600
+;   add a2, a0, a3
 ;   lw a0, 0(a2)
 ;   ret
 
@@ -299,18 +299,18 @@ block0(v0: i64, v1: i64, v2: i64):
 
 ; VCode:
 ; block0:
-;   lui a5,1048575
-;   addi a5,a5,4094
-;   slli a4,a5,32
+;   lui a4,1048575
+;   addi a6,a4,4094
+;   slli a4,a6,32
 ;   srli a6,a4,32
 ;   lh a0,0(a6)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a5, 0xfffff
-;   addi a5, a5, -2
-;   slli a4, a5, 0x20
+;   lui a4, 0xfffff
+;   addi a6, a4, -2
+;   slli a4, a6, 0x20
 ;   srli a6, a4, 0x20
 ;   lh a0, 0(a6)
 ;   ret
@@ -325,18 +325,18 @@ block0(v0: i64, v1: i64, v2: i64):
 
 ; VCode:
 ; block0:
-;   lui a5,1
-;   addi a5,a5,2
-;   slli a4,a5,32
+;   lui a4,1
+;   addi a6,a4,2
+;   slli a4,a6,32
 ;   srli a6,a4,32
 ;   lh a0,0(a6)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a5, 1
-;   addi a5, a5, 2
-;   slli a4, a5, 0x20
+;   lui a4, 1
+;   addi a6, a4, 2
+;   slli a4, a6, 0x20
 ;   srli a6, a4, 0x20
 ;   lh a0, 0(a6)
 ;   ret
@@ -351,17 +351,17 @@ block0(v0: i64, v1: i64, v2: i64):
 
 ; VCode:
 ; block0:
-;   lui a4,1048575
-;   addi a4,a4,4094
-;   sext.w a4,a4
+;   lui a3,1048575
+;   addi a5,a3,4094
+;   sext.w a4,a5
 ;   lh a0,0(a4)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a4, 0xfffff
-;   addi a4, a4, -2
-;   sext.w a4, a4
+;   lui a3, 0xfffff
+;   addi a5, a3, -2
+;   sext.w a4, a5
 ;   lh a0, 0(a4)
 ;   ret
 
@@ -375,17 +375,17 @@ block0(v0: i64, v1: i64, v2: i64):
 
 ; VCode:
 ; block0:
-;   lui a4,1
-;   addi a4,a4,2
-;   sext.w a4,a4
+;   lui a3,1
+;   addi a5,a3,2
+;   sext.w a4,a5
 ;   lh a0,0(a4)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a4, 1
-;   addi a4, a4, 2
-;   sext.w a4, a4
+;   lui a3, 1
+;   addi a5, a3, 2
+;   sext.w a4, a5
 ;   lh a0, 0(a4)
 ;   ret
 
diff --git a/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif b/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif
index 60aa88785..6876d4d14 100644
--- a/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif
@@ -882,3 +882,37 @@ block0(v0: i64):
 ;   div a0, a0, a6
 ;   ret
 
+
+function %i8_iadd_const_neg1(i8) -> i8 {
+block0(v0: i8):
+  v1 = iconst.i8 -1
+  v2 = iadd.i8 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   addiw a0,a0,-1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addiw a0, a0, -1
+;   ret
+
+function %i8_iadd_const_ff(i8) -> i8 {
+block0(v0: i8):
+  v1 = iconst.i8 0xFF
+  v2 = iadd.i8 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   addiw a0,a0,-1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addiw a0, a0, -1
+;   ret
diff --git a/cranelift/filetests/filetests/isa/riscv64/atomic_store.clif b/cranelift/filetests/filetests/isa/riscv64/atomic_store.clif
index 8d0928903..918e14715 100644
--- a/cranelift/filetests/filetests/isa/riscv64/atomic_store.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/atomic_store.clif
@@ -53,15 +53,15 @@ block0(v0: i64):
 
 ; VCode:
 ; block0:
-;   lui a1,3
-;   addi a1,a1,57
+;   lui t2,3
+;   addi a1,t2,57
 ;   atomic_store.i64 a1,(a0)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a1, 3
-;   addi a1, a1, 0x39
+;   lui t2, 3
+;   addi a1, t2, 0x39
 ;   fence rw, w
 ;   sd a1, 0(a0)
 ;   ret
@@ -117,15 +117,15 @@ block0(v0: i64):
 
 ; VCode:
 ; block0:
-;   lui a1,3
-;   addi a1,a1,57
+;   lui t2,3
+;   addi a1,t2,57
 ;   atomic_store.i32 a1,(a0)
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a1, 3
-;   addi a1, a1, 0x39
+;   lui t2, 3
+;   addi a1, t2, 0x39
 ;   fence rw, w
 ;   sw a1, 0(a0)
 ;   ret
diff --git a/cranelift/filetests/filetests/isa/riscv64/bitops-float.clif b/cranelift/filetests/filetests/isa/riscv64/bitops-float.clif
index cc2bc4ca9..038fcd0e1 100644
--- a/cranelift/filetests/filetests/isa/riscv64/bitops-float.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/bitops-float.clif
@@ -22,9 +22,9 @@ block1(v4: f32):
 ; VCode:
 ; block0:
 ;   li a0,0
-;   li t1,0
-;   fmv.w.x fa6,t1
-;   fmv.x.w t4,fa6
+;   li t0,0
+;   fmv.w.x fa7,t0
+;   fmv.x.w t4,fa7
 ;   not t1,t4
 ;   fmv.w.x ft8,t1
 ;   fmv.x.w t3,ft8
@@ -35,7 +35,7 @@ block1(v4: f32):
 ; block1:
 ;   j label3
 ; block2:
-;   fmv.d fa1,fa6
+;   fmv.d fa1,fa7
 ;   j label3
 ; block3:
 ;   ret
@@ -43,9 +43,9 @@ block1(v4: f32):
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   mv a0, zero
-;   mv t1, zero
-;   fmv.w.x fa6, t1
-;   fmv.x.w t4, fa6
+;   mv t0, zero
+;   fmv.w.x fa7, t0
+;   fmv.x.w t4, fa7
 ;   not t1, t4
 ;   fmv.w.x ft8, t1
 ;   fmv.x.w t3, ft8
@@ -67,7 +67,7 @@ block1(v4: f32):
 ; block1: ; offset 0x58
 ;   j 8
 ; block2: ; offset 0x5c
-;   fmv.d fa1, fa6
+;   fmv.d fa1, fa7
 ; block3: ; offset 0x60
 ;   ret
 
diff --git a/cranelift/filetests/filetests/isa/riscv64/constants.clif b/cranelift/filetests/filetests/isa/riscv64/constants.clif
index a948f50fa..174aef40d 100644
--- a/cranelift/filetests/filetests/isa/riscv64/constants.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/constants.clif
@@ -58,14 +58,14 @@ block0:
 
 ; VCode:
 ; block0:
-;   lui t1,16
-;   addi a0,t1,4095
+;   lui t0,16
+;   addi a0,t0,4095
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui t1, 0x10
-;   addi a0, t1, -1
+;   lui t0, 0x10
+;   addi a0, t0, -1
 ;   ret
 
 function %f() -> i64 {
@@ -304,16 +304,12 @@ block0:
 
 ; VCode:
 ; block0:
-;   auipc a0,0; ld a0,12(a0); j 12; .8byte 0xfffffff7
+;   li a0,-9
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   auipc a0, 0
-;   ld a0, 0xc(a0)
-;   j 0xc
-;   .byte 0xf7, 0xff, 0xff, 0xff
-;   .byte 0x00, 0x00, 0x00, 0x00
+;   addi a0, zero, -9
 ;   ret
 
 function %f() -> i64 {
@@ -360,18 +356,18 @@ block0:
 
 ; VCode:
 ; block0:
-;   auipc t1,0; ld t1,12(t1); j 12; .8byte 0x3ff0000000000000
-;   fmv.d.x fa0,t1
+;   auipc t0,0; ld t0,12(t0); j 12; .8byte 0x3ff0000000000000
+;   fmv.d.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   auipc t1, 0
-;   ld t1, 0xc(t1)
+;   auipc t0, 0
+;   ld t0, 0xc(t0)
 ;   j 0xc
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   .byte 0x00, 0x00, 0xf0, 0x3f
-;   fmv.d.x fa0, t1
+;   fmv.d.x fa0, t0
 ;   ret
 
 function %f() -> f32 {
@@ -382,14 +378,14 @@ block0:
 
 ; VCode:
 ; block0:
-;   lui t1,264704
-;   fmv.w.x fa0,t1
+;   lui t0,264704
+;   fmv.w.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui t1, 0x40a00
-;   fmv.w.x fa0, t1
+;   lui t0, 0x40a00
+;   fmv.w.x fa0, t0
 ;   ret
 
 function %f() -> f64 {
@@ -400,18 +396,18 @@ block0:
 
 ; VCode:
 ; block0:
-;   auipc t1,0; ld t1,12(t1); j 12; .8byte 0x4049000000000000
-;   fmv.d.x fa0,t1
+;   auipc t0,0; ld t0,12(t0); j 12; .8byte 0x4049000000000000
+;   fmv.d.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   auipc t1, 0
-;   ld t1, 0xc(t1)
+;   auipc t0, 0
+;   ld t0, 0xc(t0)
 ;   j 0xc
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   .byte 0x00, 0x00, 0x49, 0x40
-;   fmv.d.x fa0, t1
+;   fmv.d.x fa0, t0
 ;   ret
 
 function %f() -> f32 {
@@ -422,14 +418,14 @@ block0:
 
 ; VCode:
 ; block0:
-;   lui t1,271488
-;   fmv.w.x fa0,t1
+;   lui t0,271488
+;   fmv.w.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui t1, 0x42480
-;   fmv.w.x fa0, t1
+;   lui t0, 0x42480
+;   fmv.w.x fa0, t0
 ;   ret
 
 function %f() -> f64 {
@@ -440,14 +436,14 @@ block0:
 
 ; VCode:
 ; block0:
-;   li t1,0
-;   fmv.d.x fa0,t1
+;   li t0,0
+;   fmv.d.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   mv t1, zero
-;   fmv.d.x fa0, t1
+;   mv t0, zero
+;   fmv.d.x fa0, t0
 ;   ret
 
 function %f() -> f32 {
@@ -458,14 +454,14 @@ block0:
 
 ; VCode:
 ; block0:
-;   li t1,0
-;   fmv.w.x fa0,t1
+;   li t0,0
+;   fmv.w.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   mv t1, zero
-;   fmv.w.x fa0, t1
+;   mv t0, zero
+;   fmv.w.x fa0, t0
 ;   ret
 
 function %f() -> f64 {
@@ -476,18 +472,18 @@ block0:
 
 ; VCode:
 ; block0:
-;   auipc t1,0; ld t1,12(t1); j 12; .8byte 0xc030000000000000
-;   fmv.d.x fa0,t1
+;   auipc t0,0; ld t0,12(t0); j 12; .8byte 0xc030000000000000
+;   fmv.d.x fa0,t0
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   auipc t1, 0
-;   ld t1, 0xc(t1)
+;   auipc t0, 0
+;   ld t0, 0xc(t0)
 ;   j 0xc
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   .byte 0x00, 0x00, 0x30, 0xc0
-;   fmv.d.x fa0, t1
+;   fmv.d.x fa0, t0
 ;   ret
 
 function %f() -> f32 {
@@ -498,16 +494,64 @@ block0:
 
 ; VCode:
 ; block0:
-;   auipc t1,0; ld t1,12(t1); j 8; .4byte 0xc1800000
-;   fmv.w.x fa0,t1
+;   lui t0,792576
+;   fmv.w.x fa0,t0
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   lui t0, 0xc1800
+;   fmv.w.x fa0, t0
+;   ret
+
+function %addi_1() -> i64 {
+block0:
+  v0 = iconst.i64 0xfff
+  return v0
+}
+
+; VCode:
+; block0:
+;   lui t0,1
+;   addi a0,t0,4095
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   auipc t1, 0
-;   lwu t1, 0xc(t1)
-;   j 8
-;   .byte 0x00, 0x00, 0x80, 0xc1
-;   fmv.w.x fa0, t1
+;   lui t0, 1
+;   addi a0, t0, -1
 ;   ret
 
+function %addi_2() -> i64 {
+block0:
+  v0 = iconst.i64 0x800
+  return v0
+}
+
+; VCode:
+; block0:
+;   lui t0,1
+;   addi a0,t0,2048
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   lui t0, 1
+;   addi a0, t0, -0x800
+;   ret
+
+function %addi_3() -> i64 {
+block0:
+  v0 = iconst.i64 0x7ff
+  return v0
+}
+
+; VCode:
+; block0:
+;   li a0,2047
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a0, zero, 0x7ff
+;   ret
diff --git a/cranelift/filetests/filetests/isa/riscv64/fcmp.clif b/cranelift/filetests/filetests/isa/riscv64/fcmp.clif
index e4c9cd3b0..2b5d00fed 100644
--- a/cranelift/filetests/filetests/isa/riscv64/fcmp.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/fcmp.clif
@@ -14,9 +14,9 @@ block1:
 
 ; VCode:
 ; block0:
-;   li t2,0
-;   fmv.d.x ft2,t2
-;   fle.d t2,ft2,ft2
+;   li t1,0
+;   fmv.d.x ft3,t1
+;   fle.d t2,ft3,ft3
 ;   bne t2,zero,taken(label2),not_taken(label1)
 ; block1:
 ;   j label3
@@ -27,9 +27,9 @@ block1:
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   mv t2, zero
-;   fmv.d.x ft2, t2
-;   fle.d t2, ft2, ft2
+;   mv t1, zero
+;   fmv.d.x ft3, t1
+;   fle.d t2, ft3, ft3
 ; block1: ; offset 0xc
 ;   ret
 
@@ -45,9 +45,9 @@ block1:
 
 ; VCode:
 ; block0:
-;   li t2,0
-;   fmv.d.x ft2,t2
-;   fle.d t2,ft2,ft2
+;   li t1,0
+;   fmv.d.x ft3,t1
+;   fle.d t2,ft3,ft3
 ;   bne t2,zero,taken(label2),not_taken(label1)
 ; block1:
 ;   j label3
@@ -58,9 +58,9 @@ block1:
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   mv t2, zero
-;   fmv.d.x ft2, t2
-;   fle.d t2, ft2, ft2
+;   mv t1, zero
+;   fmv.d.x ft3, t1
+;   fle.d t2, ft3, ft3
 ; block1: ; offset 0xc
 ;   ret
 
diff --git a/cranelift/filetests/filetests/isa/riscv64/iconst-icmp-small.clif b/cranelift/filetests/filetests/isa/riscv64/iconst-icmp-small.clif
index 48f0d33ce..f2a92f69d 100644
--- a/cranelift/filetests/filetests/isa/riscv64/iconst-icmp-small.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/iconst-icmp-small.clif
@@ -12,22 +12,22 @@ block0:
 
 ; VCode:
 ; block0:
-;   lui a3,14
-;   addi a3,a3,3532
-;   slli t2,a3,48
+;   lui a2,1048574
+;   addi a4,a2,3532
+;   slli t2,a4,48
 ;   srli a1,t2,48
-;   slli a3,a3,48
+;   slli a3,a4,48
 ;   srli a5,a3,48
 ;   ne a0,a1,a5##ty=i16
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   lui a3, 0xe
-;   addi a3, a3, -0x234
-;   slli t2, a3, 0x30
+;   lui a2, 0xffffe
+;   addi a4, a2, -0x234
+;   slli t2, a4, 0x30
 ;   srli a1, t2, 0x30
-;   slli a3, a3, 0x30
+;   slli a3, a4, 0x30
 ;   srli a5, a3, 0x30
 ;   beq a1, a5, 0xc
 ;   addi a0, zero, 1
diff --git a/cranelift/filetests/filetests/isa/riscv64/return-call.clif b/cranelift/filetests/filetests/isa/riscv64/return-call.clif
index 4d9972f5a..2691e2fd6 100644
--- a/cranelift/filetests/filetests/isa/riscv64/return-call.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/return-call.clif
@@ -96,20 +96,20 @@ block0(v0: f64):
 
 ; VCode:
 ; block0:
-;   auipc a1,0; ld a1,12(a1); j 12; .8byte 0x4030000000000000
-;   fmv.d.x ft4,a1
-;   fadd.d ft0,ft0,ft4
+;   auipc a0,0; ld a0,12(a0); j 12; .8byte 0x4030000000000000
+;   fmv.d.x ft5,a0
+;   fadd.d ft0,ft0,ft5
 ;   ret
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
-;   auipc a1, 0
-;   ld a1, 0xc(a1)
+;   auipc a0, 0
+;   ld a0, 0xc(a0)
 ;   j 0xc
 ;   .byte 0x00, 0x00, 0x00, 0x00
 ;   .byte 0x00, 0x00, 0x30, 0x40
-;   fmv.d.x ft4, a1
-;   fadd.d ft0, ft0, ft4
+;   fmv.d.x ft5, a0
+;   fadd.d ft0, ft0, ft5
 ;   ret
 
 function %call_f64(f64) -> f64 tail {
diff --git a/cranelift/filetests/filetests/isa/riscv64/simd-popcnt.clif b/cranelift/filetests/filetests/isa/riscv64/simd-popcnt.clif
index c2433a21c..67ee55554 100644
--- a/cranelift/filetests/filetests/isa/riscv64/simd-popcnt.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/simd-popcnt.clif
@@ -84,22 +84,22 @@ block0(v0: i16x8):
 ;   mv fp,sp
 ; block0:
 ;   vle8.v v1,16(fp) #avl=16, #vtype=(e8, m1, ta, ma)
-;   lui a2,5
-;   addi a2,a2,1365
+;   lui a1,5
+;   addi a3,a1,1365
 ;   vsrl.vi v8,v1,1 #avl=8, #vtype=(e16, m1, ta, ma)
-;   vand.vx v10,v8,a2 #avl=8, #vtype=(e16, m1, ta, ma)
+;   vand.vx v10,v8,a3 #avl=8, #vtype=(e16, m1, ta, ma)
 ;   vsub.vv v12,v1,v10 #avl=8, #vtype=(e16, m1, ta, ma)
-;   lui t2,3
-;   addi t2,t2,819
+;   lui t1,3
+;   addi a1,t1,819
 ;   vsrl.vi v18,v12,2 #avl=8, #vtype=(e16, m1, ta, ma)
-;   vand.vx v20,v18,t2 #avl=8, #vtype=(e16, m1, ta, ma)
-;   vand.vx v22,v12,t2 #avl=8, #vtype=(e16, m1, ta, ma)
+;   vand.vx v20,v18,a1 #avl=8, #vtype=(e16, m1, ta, ma)
+;   vand.vx v22,v12,a1 #avl=8, #vtype=(e16, m1, ta, ma)
 ;   vadd.vv v24,v22,v20 #avl=8, #vtype=(e16, m1, ta, ma)
-;   lui t1,1
-;   addi t1,t1,3855
+;   lui t0,1
+;   addi t2,t0,3855
 ;   vsrl.vi v30,v24,4 #avl=8, #vtype=(e16, m1, ta, ma)
 ;   vadd.vv v0,v24,v30 #avl=8, #vtype=(e16, m1, ta, ma)
-;   vand.vx v2,v0,t1 #avl=8, #vtype=(e16, m1, ta, ma)
+;   vand.vx v2,v0,t2 #avl=8, #vtype=(e16, m1, ta, ma)
 ;   li a7,257
 ;   vmul.vx v6,v2,a7 #avl=8, #vtype=(e16, m1, ta, ma)
 ;   li t1,8
@@ -120,23 +120,23 @@ block0(v0: i16x8):
 ;   .byte 0x57, 0x70, 0x08, 0xcc
 ;   addi t6, s0, 0x10
 ;   .byte 0x87, 0x80, 0x0f, 0x02
-;   lui a2, 5
-;   addi a2, a2, 0x555
+;   lui a1, 5
+;   addi a3, a1, 0x555
 ;   .byte 0x57, 0x70, 0x84, 0xcc
 ;   .byte 0x57, 0xb4, 0x10, 0xa2
-;   .byte 0x57, 0x45, 0x86, 0x26
+;   .byte 0x57, 0xc5, 0x86, 0x26
 ;   .byte 0x57, 0x06, 0x15, 0x0a
-;   lui t2, 3
-;   addi t2, t2, 0x333
+;   lui t1, 3
+;   addi a1, t1, 0x333
 ;   .byte 0x57, 0x39, 0xc1, 0xa2
-;   .byte 0x57, 0xca, 0x23, 0x27
-;   .byte 0x57, 0xcb, 0xc3, 0x26
+;   .byte 0x57, 0xca, 0x25, 0x27
+;   .byte 0x57, 0xcb, 0xc5, 0x26
 ;   .byte 0x57, 0x0c, 0x6a, 0x03
-;   lui t1, 1
-;   addi t1, t1, -0xf1
+;   lui t0, 1
+;   addi t2, t0, -0xf1
 ;   .byte 0x57, 0x3f, 0x82, 0xa3
 ;   .byte 0x57, 0x00, 0x8f, 0x03
-;   .byte 0x57, 0x41, 0x03, 0x26
+;   .byte 0x57, 0xc1, 0x03, 0x26
 ;   addi a7, zero, 0x101
 ;   .byte 0x57, 0xe3, 0x28, 0x96
 ;   addi t1, zero, 8
@@ -161,25 +161,25 @@ block0(v0: i32x4):
 ;   mv fp,sp
 ; block0:
 ;   vle8.v v1,16(fp) #avl=16, #vtype=(e8, m1, ta, ma)
-;   lui a2,349525
-;   addi a2,a2,1365
+;   lui a1,349525
+;   addi a3,a1,1365
 ;   vsrl.vi v8,v1,1 #avl=4, #vtype=(e32, m1, ta, ma)
-;   vand.vx v10,v8,a2 #avl=4, #vtype=(e32, m1, ta, ma)
+;   vand.vx v10,v8,a3 #avl=4, #vtype=(e32, m1, ta, ma)
 ;   vsub.vv v12,v1,v10 #avl=4, #vtype=(e32, m1, ta, ma)
-;   lui t2,209715
-;   addi t2,t2,819
+;   lui t1,209715
+;   addi a1,t1,819
 ;   vsrl.vi v18,v12,2 #avl=4, #vtype=(e32, m1, ta, ma)
-;   vand.vx v20,v18,t2 #avl=4, #vtype=(e32, m1, ta, ma)
-;   vand.vx v22,v12,t2 #avl=4, #vtype=(e32, m1, ta, ma)
+;   vand.vx v20,v18,a1 #avl=4, #vtype=(e32, m1, ta, ma)
+;   vand.vx v22,v12,a1 #avl=4, #vtype=(e32, m1, ta, ma)
 ;   vadd.vv v24,v22,v20 #avl=4, #vtype=(e32, m1, ta, ma)
-;   lui t1,61681
-;   addi t1,t1,3855
+;   lui t0,61681
+;   addi t2,t0,3855
 ;   vsrl.vi v30,v24,4 #avl=4, #vtype=(e32, m1, ta, ma)
 ;   vadd.vv v0,v24,v30 #avl=4, #vtype=(e32, m1, ta, ma)
-;   vand.vx v2,v0,t1 #avl=4, #vtype=(e32, m1, ta, ma)
-;   lui t3,4112
-;   addi t3,t3,257
-;   vmul.vx v8,v2,t3 #avl=4, #vtype=(e32, m1, ta, ma)
+;   vand.vx v2,v0,t2 #avl=4, #vtype=(e32, m1, ta, ma)
+;   lui a7,4112
+;   addi t4,a7,257
+;   vmul.vx v8,v2,t4 #avl=4, #vtype=(e32, m1, ta, ma)
 ;   li a1,24
 ;   vsrl.vx v12,v8,a1 #avl=4, #vtype=(e32, m1, ta, ma)
 ;   vse8.v v12,0(a0) #avl=16, #vtype=(e8, m1, ta, ma)
@@ -198,26 +198,26 @@ block0(v0: i32x4):
 ;   .byte 0x57, 0x70, 0x08, 0xcc
 ;   addi t6, s0, 0x10
 ;   .byte 0x87, 0x80, 0x0f, 0x02
-;   lui a2, 0x55555
-;   addi a2, a2, 0x555
+;   lui a1, 0x55555
+;   addi a3, a1, 0x555
 ;   .byte 0x57, 0x70, 0x02, 0xcd
 ;   .byte 0x57, 0xb4, 0x10, 0xa2
-;   .byte 0x57, 0x45, 0x86, 0x26
+;   .byte 0x57, 0xc5, 0x86, 0x26
 ;   .byte 0x57, 0x06, 0x15, 0x0a
-;   lui t2, 0x33333
-;   addi t2, t2, 0x333
+;   lui t1, 0x33333
+;   addi a1, t1, 0x333
 ;   .byte 0x57, 0x39, 0xc1, 0xa2
-;   .byte 0x57, 0xca, 0x23, 0x27
-;   .byte 0x57, 0xcb, 0xc3, 0x26
+;   .byte 0x57, 0xca, 0x25, 0x27
+;   .byte 0x57, 0xcb, 0xc5, 0x26
 ;   .byte 0x57, 0x0c, 0x6a, 0x03
-;   lui t1, 0xf0f1
-;   addi t1, t1, -0xf1
+;   lui t0, 0xf0f1
+;   addi t2, t0, -0xf1
 ;   .byte 0x57, 0x3f, 0x82, 0xa3
 ;   .byte 0x57, 0x00, 0x8f, 0x03
-;   .byte 0x57, 0x41, 0x03, 0x26
-;   lui t3, 0x1010
-;   addi t3, t3, 0x101
-;   .byte 0x57, 0x64, 0x2e, 0x96
+;   .byte 0x57, 0xc1, 0x03, 0x26
+;   lui a7, 0x1010
+;   addi t4, a7, 0x101
+;   .byte 0x57, 0xe4, 0x2e, 0x96
 ;   addi a1, zero, 0x18
 ;   .byte 0x57, 0xc6, 0x85, 0xa2
 ;   .byte 0x57, 0x70, 0x08, 0xcc
diff --git a/cranelift/filetests/filetests/isa/riscv64/simd-vhighbits.clif b/cranelift/filetests/filetests/isa/riscv64/simd-vhighbits.clif
index e3799c4f4..748d123e8 100644
--- a/cranelift/filetests/filetests/isa/riscv64/simd-vhighbits.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/simd-vhighbits.clif
@@ -18,9 +18,9 @@ block0(v0: i8x16):
 ;   vle8.v v0,16(fp) #avl=16, #vtype=(e8, m1, ta, ma)
 ;   vmslt.vx v2,v0,zero #avl=16, #vtype=(e8, m1, ta, ma)
 ;   vmv.x.s a1,v2 #avl=2, #vtype=(e64, m1, ta, ma)
-;   lui a4,16
-;   addi a4,a4,4095
-;   and a0,a1,a4
+;   lui a3,16
+;   addi a5,a3,4095
+;   and a0,a1,a5
 ;   ld ra,8(sp)
 ;   ld fp,0(sp)
 ;   add sp,+16
@@ -39,9 +39,9 @@ block0(v0: i8x16):
 ;   .byte 0x57, 0x41, 0x00, 0x6e
 ;   .byte 0x57, 0x70, 0x81, 0xcd
 ;   .byte 0xd7, 0x25, 0x20, 0x42
-;   lui a4, 0x10
-;   addi a4, a4, -1
-;   and a0, a1, a4
+;   lui a3, 0x10
+;   addi a5, a3, -1
+;   and a0, a1, a5
 ;   ld ra, 8(sp)
 ;   ld s0, 0(sp)
 ;   addi sp, sp, 0x10
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
index 74495be63..4cebd9c89 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
@@ -44,8 +44,8 @@
 ;;   slli t0,a0,32
 ;;   srli t2,t0,32
 ;;   ld t1,8(a2)
-;;   lui a0,1048575
-;;   addi a0,a0,4092
+;;   lui t0,1048575
+;;   addi a0,t0,4092
 ;;   add t1,t1,a0
 ;;   ugt t1,t2,t1##ty=i64
 ;;   bne t1,zero,taken(label3),not_taken(label1)
@@ -66,8 +66,8 @@
 ;;   slli t0,a0,32
 ;;   srli t2,t0,32
 ;;   ld t1,8(a1)
-;;   lui a0,1048575
-;;   addi a0,a0,4092
+;;   lui t0,1048575
+;;   addi a0,t0,4092
 ;;   add t1,t1,a0
 ;;   ugt t1,t2,t1##ty=i64
 ;;   bne t1,zero,taken(label3),not_taken(label1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
index 3cd1a6b88..e924c6054 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
@@ -44,8 +44,8 @@
 ;;   slli t0,a0,32
 ;;   srli t2,t0,32
 ;;   ld t1,8(a2)
-;;   lui a0,1048575
-;;   addi a0,a0,4095
+;;   lui t0,1048575
+;;   addi a0,t0,4095
 ;;   add t1,t1,a0
 ;;   ugt t1,t2,t1##ty=i64
 ;;   bne t1,zero,taken(label3),not_taken(label1)
@@ -66,8 +66,8 @@
 ;;   slli t0,a0,32
 ;;   srli t2,t0,32
 ;;   ld t1,8(a1)
-;;   lui a0,1048575
-;;   addi a0,a0,4095
+;;   lui t0,1048575
+;;   addi a0,t0,4095
 ;;   add t1,t1,a0
 ;;   ugt t1,t2,t1##ty=i64
 ;;   bne t1,zero,taken(label3),not_taken(label1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
index cb9f3b4a1..c643ef112 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
@@ -44,8 +44,8 @@
 ;;   slli a5,a0,32
 ;;   srli a7,a5,32
 ;;   ld a6,8(a2)
-;;   lui t3,1048575
-;;   addi t3,t3,4092
+;;   lui a5,1048575
+;;   addi t3,a5,4092
 ;;   add a6,a6,t3
 ;;   ugt t3,a7,a6##ty=i64
 ;;   ld a6,0(a2)
@@ -70,8 +70,8 @@
 ;;   slli a5,a0,32
 ;;   srli a7,a5,32
 ;;   ld a6,8(a1)
-;;   lui t3,1048575
-;;   addi t3,t3,4092
+;;   lui a5,1048575
+;;   addi t3,a5,4092
 ;;   add a6,a6,t3
 ;;   ugt t3,a7,a6##ty=i64
 ;;   ld a6,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
index fcbfb6926..75edd3399 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
@@ -44,8 +44,8 @@
 ;;   slli a5,a0,32
 ;;   srli a7,a5,32
 ;;   ld a6,8(a2)
-;;   lui t3,1048575
-;;   addi t3,t3,4095
+;;   lui a5,1048575
+;;   addi t3,a5,4095
 ;;   add a6,a6,t3
 ;;   ugt t3,a7,a6##ty=i64
 ;;   ld a6,0(a2)
@@ -70,8 +70,8 @@
 ;;   slli a5,a0,32
 ;;   srli a7,a5,32
 ;;   ld a6,8(a1)
-;;   lui t3,1048575
-;;   addi t3,t3,4095
+;;   lui a5,1048575
+;;   addi t3,a5,4095
 ;;   add a6,a6,t3
 ;;   ugt t3,a7,a6##ty=i64
 ;;   ld a6,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
index 878602f65..40265b82d 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
@@ -42,8 +42,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   ld t4,8(a2)
-;;   lui t0,1048575
-;;   addi t0,t0,4092
+;;   lui t3,1048575
+;;   addi t0,t3,4092
 ;;   add t4,t4,t0
 ;;   ugt t4,a0,t4##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
@@ -62,8 +62,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   ld t4,8(a1)
-;;   lui t0,1048575
-;;   addi t0,t0,4092
+;;   lui t3,1048575
+;;   addi t0,t3,4092
 ;;   add t4,t4,t0
 ;;   ugt t4,a0,t4##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
index 111316126..58be1eed5 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
@@ -42,8 +42,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   ld t4,8(a2)
-;;   lui t0,1048575
-;;   addi t0,t0,4095
+;;   lui t3,1048575
+;;   addi t0,t3,4095
 ;;   add t4,t4,t0
 ;;   ugt t4,a0,t4##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
@@ -62,8 +62,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   ld t4,8(a1)
-;;   lui t0,1048575
-;;   addi t0,t0,4095
+;;   lui t3,1048575
+;;   addi t0,t3,4095
 ;;   add t4,t4,t0
 ;;   ugt t4,a0,t4##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
index 169c79927..9150d1d44 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
@@ -42,8 +42,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   ld a4,8(a2)
-;;   lui a5,1048575
-;;   addi a5,a5,4092
+;;   lui a3,1048575
+;;   addi a5,a3,4092
 ;;   add a4,a4,a5
 ;;   ugt a5,a0,a4##ty=i64
 ;;   ld a4,0(a2)
@@ -66,8 +66,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   ld a4,8(a1)
-;;   lui a5,1048575
-;;   addi a5,a5,4092
+;;   lui a3,1048575
+;;   addi a5,a3,4092
 ;;   add a4,a4,a5
 ;;   ugt a5,a0,a4##ty=i64
 ;;   ld a4,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
index dcd8657c4..65c26f8ed 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_dynamic_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
@@ -42,8 +42,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   ld a4,8(a2)
-;;   lui a5,1048575
-;;   addi a5,a5,4095
+;;   lui a3,1048575
+;;   addi a5,a3,4095
 ;;   add a4,a4,a5
 ;;   ugt a5,a0,a4##ty=i64
 ;;   ld a4,0(a2)
@@ -66,8 +66,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   ld a4,8(a1)
-;;   lui a5,1048575
-;;   addi a5,a5,4095
+;;   lui a3,1048575
+;;   addi a5,a3,4095
 ;;   add a4,a4,a5
 ;;   ugt a5,a0,a4##ty=i64
 ;;   ld a4,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0_offset.wat
index f4a7174a6..607a6449a 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0_offset.wat
@@ -41,9 +41,9 @@
 ;; block0:
 ;;   slli a6,a0,32
 ;;   srli t3,a6,32
-;;   lui a7,65536
-;;   addi a7,a7,4092
-;;   ugt a7,t3,a7##ty=i64
+;;   lui a6,65536
+;;   addi t4,a6,4092
+;;   ugt a7,t3,t4##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t4,0(a2)
@@ -59,9 +59,9 @@
 ;; block0:
 ;;   slli a6,a0,32
 ;;   srli t3,a6,32
-;;   lui a7,65536
-;;   addi a7,a7,4092
-;;   ugt a7,t3,a7##ty=i64
+;;   lui a6,65536
+;;   addi t4,a6,4092
+;;   ugt a7,t3,t4##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t4,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
index af003621a..1229a6e2d 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
@@ -41,9 +41,9 @@
 ;; block0:
 ;;   slli t3,a0,32
 ;;   srli t0,t3,32
-;;   lui t4,65535
-;;   addi t4,t4,4092
-;;   ugt t4,t0,t4##ty=i64
+;;   lui t3,65535
+;;   addi t1,t3,4092
+;;   ugt t4,t0,t1##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t1,0(a2)
@@ -61,9 +61,9 @@
 ;; block0:
 ;;   slli t3,a0,32
 ;;   srli t0,t3,32
-;;   lui t4,65535
-;;   addi t4,t4,4092
-;;   ugt t4,t0,t4##ty=i64
+;;   lui t3,65535
+;;   addi t1,t3,4092
+;;   ugt t4,t0,t1##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t1,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0_offset.wat
index 6a6ccb51e..26987ecaf 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0_offset.wat
@@ -41,9 +41,9 @@
 ;; block0:
 ;;   slli a6,a0,32
 ;;   srli t3,a6,32
-;;   lui a7,65536
-;;   addi a7,a7,4095
-;;   ugt a7,t3,a7##ty=i64
+;;   lui a6,65536
+;;   addi t4,a6,4095
+;;   ugt a7,t3,t4##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t4,0(a2)
@@ -59,9 +59,9 @@
 ;; block0:
 ;;   slli a6,a0,32
 ;;   srli t3,a6,32
-;;   lui a7,65536
-;;   addi a7,a7,4095
-;;   ugt a7,t3,a7##ty=i64
+;;   lui a6,65536
+;;   addi t4,a6,4095
+;;   ugt a7,t3,t4##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t4,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
index 5a8fbbc12..befcadb35 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
@@ -41,9 +41,9 @@
 ;; block0:
 ;;   slli t3,a0,32
 ;;   srli t0,t3,32
-;;   lui t4,65535
-;;   addi t4,t4,4095
-;;   ugt t4,t0,t4##ty=i64
+;;   lui t3,65535
+;;   addi t1,t3,4095
+;;   ugt t4,t0,t1##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t1,0(a2)
@@ -61,9 +61,9 @@
 ;; block0:
 ;;   slli t3,a0,32
 ;;   srli t0,t3,32
-;;   lui t4,65535
-;;   addi t4,t4,4095
-;;   ugt t4,t0,t4##ty=i64
+;;   lui t3,65535
+;;   addi t1,t3,4095
+;;   ugt t4,t0,t1##ty=i64
 ;;   bne t4,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t1,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0_offset.wat
index b709b33b0..69e1a6252 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0_offset.wat
@@ -64,8 +64,8 @@
 ;;   slli a2,a0,32
 ;;   srli a3,a2,32
 ;;   lui a2,65536
-;;   addi a2,a2,4092
-;;   ugt a4,a3,a2##ty=i64
+;;   addi a4,a2,4092
+;;   ugt a4,a3,a4##ty=i64
 ;;   ld a2,0(a1)
 ;;   add a2,a2,a3
 ;;   li a3,0
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
index a827bbe98..adec7af58 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
@@ -41,9 +41,9 @@
 ;; block0:
 ;;   slli a3,a0,32
 ;;   srli a6,a3,32
-;;   lui a4,65535
-;;   addi a4,a4,4092
-;;   ugt a5,a6,a4##ty=i64
+;;   lui a3,65535
+;;   addi a5,a3,4092
+;;   ugt a5,a6,a5##ty=i64
 ;;   ld a4,0(a2)
 ;;   add a4,a4,a6
 ;;   lui a6,1
@@ -65,9 +65,9 @@
 ;; block0:
 ;;   slli a3,a0,32
 ;;   srli a6,a3,32
-;;   lui a4,65535
-;;   addi a4,a4,4092
-;;   ugt a5,a6,a4##ty=i64
+;;   lui a3,65535
+;;   addi a5,a3,4092
+;;   ugt a5,a6,a5##ty=i64
 ;;   ld a4,0(a1)
 ;;   add a4,a4,a6
 ;;   lui a6,1
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0_offset.wat
index 78de2ddc8..3fce6a818 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0_offset.wat
@@ -64,8 +64,8 @@
 ;;   slli a2,a0,32
 ;;   srli a3,a2,32
 ;;   lui a2,65536
-;;   addi a2,a2,4095
-;;   ugt a4,a3,a2##ty=i64
+;;   addi a4,a2,4095
+;;   ugt a4,a3,a4##ty=i64
 ;;   ld a2,0(a1)
 ;;   add a2,a2,a3
 ;;   li a3,0
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
index 83e1ce6e0..7d084f693 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i32_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
@@ -41,9 +41,9 @@
 ;; block0:
 ;;   slli a3,a0,32
 ;;   srli a6,a3,32
-;;   lui a4,65535
-;;   addi a4,a4,4095
-;;   ugt a5,a6,a4##ty=i64
+;;   lui a3,65535
+;;   addi a5,a3,4095
+;;   ugt a5,a6,a5##ty=i64
 ;;   ld a4,0(a2)
 ;;   add a4,a4,a6
 ;;   lui a6,1
@@ -65,9 +65,9 @@
 ;; block0:
 ;;   slli a3,a0,32
 ;;   srli a6,a3,32
-;;   lui a4,65535
-;;   addi a4,a4,4095
-;;   ugt a5,a6,a4##ty=i64
+;;   lui a3,65535
+;;   addi a5,a3,4095
+;;   ugt a5,a6,a5##ty=i64
 ;;   ld a4,0(a1)
 ;;   add a4,a4,a6
 ;;   lui a6,1
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0_offset.wat
index 480359814..fd6723d47 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4092
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4092
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a2)
@@ -55,9 +55,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4092
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4092
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
index e5dc45b23..3e1ed7491 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i32_access_0x1000_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4092
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4092
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a2)
@@ -57,9 +57,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4092
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4092
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0_offset.wat
index 1c3e1fdfc..93d4312b1 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4095
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4095
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a2)
@@ -55,9 +55,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4095
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4095
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
index 320be4fbc..bb5334efe 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_no_spectre_i8_access_0x1000_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4095
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4095
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a2)
@@ -57,9 +57,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4095
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4095
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0_offset.wat
index e30e0a0a1..6755ab634 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0_offset.wat
@@ -40,8 +40,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   mv a4,a2
-;;   lui a2,65536
-;;   addi a2,a2,4092
+;;   lui t2,65536
+;;   addi a2,t2,4092
 ;;   ugt a2,a0,a2##ty=i64
 ;;   ld a3,0(a4)
 ;;   add a0,a3,a0
@@ -61,8 +61,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   mv a4,a1
-;;   lui a1,65536
-;;   addi a1,a1,4092
+;;   lui t2,65536
+;;   addi a1,t2,4092
 ;;   ugt a1,a0,a1##ty=i64
 ;;   ld a2,0(a4)
 ;;   add a0,a2,a0
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
index 1c03fd957..0ac630495 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i32_access_0x1000_offset.wat
@@ -62,8 +62,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   lui a2,65535
-;;   addi a2,a2,4092
-;;   ugt a3,a0,a2##ty=i64
+;;   addi a3,a2,4092
+;;   ugt a3,a0,a3##ty=i64
 ;;   ld a2,0(a1)
 ;;   add a2,a2,a0
 ;;   lui a4,1
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0_offset.wat
index d755a4f65..d7d43f04b 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0_offset.wat
@@ -40,8 +40,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   mv a4,a2
-;;   lui a2,65536
-;;   addi a2,a2,4095
+;;   lui t2,65536
+;;   addi a2,t2,4095
 ;;   ugt a2,a0,a2##ty=i64
 ;;   ld a3,0(a4)
 ;;   add a0,a3,a0
@@ -61,8 +61,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   mv a4,a1
-;;   lui a1,65536
-;;   addi a1,a1,4095
+;;   lui t2,65536
+;;   addi a1,t2,4095
 ;;   ugt a1,a0,a1##ty=i64
 ;;   ld a2,0(a4)
 ;;   add a0,a2,a0
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
index 6f2b6a18a..0eb103d62 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0_guard_yes_spectre_i8_access_0x1000_offset.wat
@@ -62,8 +62,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   lui a2,65535
-;;   addi a2,a2,4095
-;;   ugt a3,a0,a2##ty=i64
+;;   addi a3,a2,4095
+;;   ugt a3,a0,a3##ty=i64
 ;;   ld a2,0(a1)
 ;;   add a2,a2,a0
 ;;   lui a4,1
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0_offset.wat
index c0f6b6f0d..715c36cb5 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4092
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4092
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a2)
@@ -55,9 +55,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4092
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4092
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0x1000_offset.wat
index b326b7a1c..5e6ea1ec8 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i32_access_0x1000_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4092
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4092
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a2)
@@ -57,9 +57,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4092
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4092
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0_offset.wat
index 05fa839f4..eafea70de 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4095
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4095
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a2)
@@ -55,9 +55,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a5,65536
-;;   addi a5,a5,4095
-;;   ugt a5,a0,a5##ty=i64
+;;   lui a4,65536
+;;   addi a6,a4,4095
+;;   ugt a5,a0,a6##ty=i64
 ;;   bne a5,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld a6,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0x1000_offset.wat
index 239f0c75c..6eef75cac 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_no_spectre_i8_access_0x1000_offset.wat
@@ -39,9 +39,9 @@
 
 ;; function u0:0:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4095
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4095
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a2)
@@ -57,9 +57,9 @@
 ;;
 ;; function u0:1:
 ;; block0:
-;;   lui a7,65535
-;;   addi a7,a7,4095
-;;   ugt a7,a0,a7##ty=i64
+;;   lui a6,65535
+;;   addi t3,a6,4095
+;;   ugt a7,a0,t3##ty=i64
 ;;   bne a7,zero,taken(label3),not_taken(label1)
 ;; block1:
 ;;   ld t3,0(a1)
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0_offset.wat
index 6d358beff..63d1719ad 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0_offset.wat
@@ -40,8 +40,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   mv a4,a2
-;;   lui a2,65536
-;;   addi a2,a2,4092
+;;   lui t2,65536
+;;   addi a2,t2,4092
 ;;   ugt a2,a0,a2##ty=i64
 ;;   ld a3,0(a4)
 ;;   add a0,a3,a0
@@ -61,8 +61,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   mv a4,a1
-;;   lui a1,65536
-;;   addi a1,a1,4092
+;;   lui t2,65536
+;;   addi a1,t2,4092
 ;;   ugt a1,a0,a1##ty=i64
 ;;   ld a2,0(a4)
 ;;   add a0,a2,a0
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0x1000_offset.wat
index b40a4633a..457db839f 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i32_access_0x1000_offset.wat
@@ -62,8 +62,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   lui a2,65535
-;;   addi a2,a2,4092
-;;   ugt a3,a0,a2##ty=i64
+;;   addi a3,a2,4092
+;;   ugt a3,a0,a3##ty=i64
 ;;   ld a2,0(a1)
 ;;   add a2,a2,a0
 ;;   lui a4,1
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0_offset.wat
index 4bbf4a4f3..7cf3a961b 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0_offset.wat
@@ -40,8 +40,8 @@
 ;; function u0:0:
 ;; block0:
 ;;   mv a4,a2
-;;   lui a2,65536
-;;   addi a2,a2,4095
+;;   lui t2,65536
+;;   addi a2,t2,4095
 ;;   ugt a2,a0,a2##ty=i64
 ;;   ld a3,0(a4)
 ;;   add a0,a3,a0
@@ -61,8 +61,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   mv a4,a1
-;;   lui a1,65536
-;;   addi a1,a1,4095
+;;   lui t2,65536
+;;   addi a1,t2,4095
 ;;   ugt a1,a0,a1##ty=i64
 ;;   ld a2,0(a4)
 ;;   add a0,a2,a0
diff --git a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0x1000_offset.wat b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0x1000_offset.wat
index 7915fdfc5..c74c7dc7b 100644
--- a/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0x1000_offset.wat
+++ b/cranelift/filetests/filetests/isa/riscv64/wasm/load_store_static_kind_i64_index_0xffffffff_guard_yes_spectre_i8_access_0x1000_offset.wat
@@ -62,8 +62,8 @@
 ;; function u0:1:
 ;; block0:
 ;;   lui a2,65535
-;;   addi a2,a2,4095
-;;   ugt a3,a0,a2##ty=i64
+;;   addi a3,a2,4095
+;;   ugt a3,a0,a3##ty=i64
 ;;   ld a2,0(a1)
 ;;   add a2,a2,a0
 ;;   lui a4,1
diff --git a/cranelift/filetests/filetests/runtests/bitops.clif b/cranelift/filetests/filetests/runtests/bitops.clif
index 3fd366aa5..3edac3e9a 100644
--- a/cranelift/filetests/filetests/runtests/bitops.clif
+++ b/cranelift/filetests/filetests/runtests/bitops.clif
@@ -4,12 +4,14 @@ target aarch64
 target s390x
 target riscv64
 target s390x has_mie2
+target x86_64
+
 set opt_level=speed
 target aarch64
 target s390x
 target riscv64
 target s390x has_mie2
-; target x86_64 TODO: Not yet implemented on x86_64
+target x86_64
 
 function %bnot_band() -> i8 {
 block0:
@@ -21,48 +23,6 @@ block0:
 }
 ; run
 
-function %bitselect_i8(i8, i8, i8) -> i8 {
-block0(v0: i8, v1: i8, v2: i8):
-    v3 = bitselect v0, v1, v2
-    return v3
-}
-
-; run: %bitselect_i8(0, 0, 0xFF) == 0xFF
-; run: %bitselect_i8(0x55, 0, 0xFF) == 0xAA
-; run: %bitselect_i8(0xF0, 32, 13) == 45
-; run: %bitselect_i8(0xFF, 0xFF, 0) == 0xFF
-
-function %bitselect_i16(i16, i16, i16) -> i16 {
-block0(v0: i16, v1: i16, v2: i16):
-    v3 = bitselect v0, v1, v2
-    return v3
-}
-
-; run: %bitselect_i16(0, 0, 0xFFFF) == 0xFFFF
-; run: %bitselect_i16(0x5555, 0, 0xFFFF) == 0xAAAA
-; run: %bitselect_i16(0xFFFF, 0xFFFF, 0) == 0xFFFF
-
-function %bitselect_i32(i32, i32, i32) -> i32 {
-block0(v0: i32, v1: i32, v2: i32):
-    v3 = bitselect v0, v1, v2
-    return v3
-}
-
-; run: %bitselect_i32(0, 0, 0xFFFFFFFF) == 0xFFFFFFFF
-; run: %bitselect_i32(0x55555555, 0, 0xFFFFFFFF) == 0xAAAAAAAA
-; run: %bitselect_i32(0xFFFFFFFF, 0xFFFFFFFF, 0) == 0xFFFFFFFF
-
-function %bitselect_i64(i64, i64, i64) -> i64 {
-block0(v0: i64, v1: i64, v2: i64):
-    v3 = bitselect v0, v1, v2
-    return v3
-}
-
-; run: %bitselect_i64(0, 0, 0xFFFFFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF
-; run: %bitselect_i64(0x5555555555555555, 0, 0xFFFFFFFFFFFFFFFF) == 0xAAAAAAAAAAAAAAAA
-; run: %bitselect_i64(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0) == 0xFFFFFFFFFFFFFFFF
-
-
 ;; We have a optimization rule in the midend that turns this into a bmask
 ;; It's easier to have a runtest to ensure that it is correct than to inspect the output.
 function %bitops_bmask(i16) -> i16 {
diff --git a/cranelift/filetests/filetests/runtests/bitselect-float.clif b/cranelift/filetests/filetests/runtests/bitselect-float.clif
new file mode 100644
index 000000000..8b4ae887f
--- /dev/null
+++ b/cranelift/filetests/filetests/runtests/bitselect-float.clif
@@ -0,0 +1,20 @@
+test run
+target x86_64
+
+function %bitselect_f32(f32, f32, f32) -> f32 {
+block0(v0: f32, v1: f32, v2: f32):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_f32(0x0.0, 0x0.0, 0x1.0) == 0x1.0
+; run: %bitselect_f32(0x1.3, 0x2.2, 0x3.3) == 0x1.98p1
+
+function %bitselect_f64(f64, f64, f64) -> f64 {
+block0(v0: f64, v1: f64, v2: f64):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_f64(0x0.0, 0x0.0, 0x1.0) == 0x1.0
+; run: %bitselect_f64(0x1.3, 0x2.2, 0x3.3) == 0x1.98p1
diff --git a/cranelift/filetests/filetests/runtests/bitselect.clif b/cranelift/filetests/filetests/runtests/bitselect.clif
new file mode 100644
index 000000000..04f3b3bd7
--- /dev/null
+++ b/cranelift/filetests/filetests/runtests/bitselect.clif
@@ -0,0 +1,55 @@
+test run
+set opt_level=none
+target aarch64
+target s390x
+target s390x has_mie2
+target riscv64
+target x86_64
+
+set opt_level=speed
+target aarch64
+target s390x
+target s390x has_mie2
+target riscv64
+target x86_64
+
+function %bitselect_i8(i8, i8, i8) -> i8 {
+block0(v0: i8, v1: i8, v2: i8):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_i8(0, 0, 0xFF) == 0xFF
+; run: %bitselect_i8(0x55, 0, 0xFF) == 0xAA
+; run: %bitselect_i8(0xF0, 32, 13) == 45
+; run: %bitselect_i8(0xFF, 0xFF, 0) == 0xFF
+
+function %bitselect_i16(i16, i16, i16) -> i16 {
+block0(v0: i16, v1: i16, v2: i16):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_i16(0, 0, 0xFFFF) == 0xFFFF
+; run: %bitselect_i16(0x5555, 0, 0xFFFF) == 0xAAAA
+; run: %bitselect_i16(0xFFFF, 0xFFFF, 0) == 0xFFFF
+
+function %bitselect_i32(i32, i32, i32) -> i32 {
+block0(v0: i32, v1: i32, v2: i32):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_i32(0, 0, 0xFFFFFFFF) == 0xFFFFFFFF
+; run: %bitselect_i32(0x55555555, 0, 0xFFFFFFFF) == 0xAAAAAAAA
+; run: %bitselect_i32(0xFFFFFFFF, 0xFFFFFFFF, 0) == 0xFFFFFFFF
+
+function %bitselect_i64(i64, i64, i64) -> i64 {
+block0(v0: i64, v1: i64, v2: i64):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_i64(0, 0, 0xFFFFFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF
+; run: %bitselect_i64(0x5555555555555555, 0, 0xFFFFFFFFFFFFFFFF) == 0xAAAAAAAAAAAAAAAA
+; run: %bitselect_i64(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0) == 0xFFFFFFFFFFFFFFFF
diff --git a/cranelift/filetests/filetests/runtests/i128-bitselect.clif b/cranelift/filetests/filetests/runtests/i128-bitselect.clif
new file mode 100644
index 000000000..59d4bffbb
--- /dev/null
+++ b/cranelift/filetests/filetests/runtests/i128-bitselect.clif
@@ -0,0 +1,16 @@
+test run
+set opt_level=none
+set enable_llvm_abi_extensions=true
+target s390x
+target s390x has_mie2
+target x86_64
+
+function %bitselect_i128(i128, i128, i128) -> i128 {
+block0(v0: i128, v1: i128, v2: i128):
+    v3 = bitselect v0, v1, v2
+    return v3
+}
+
+; run: %bitselect_i128(0, 0, 0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF
+; run: %bitselect_i128(0x5555555555555555_5555555555555555, 0, 0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF) == 0xAAAAAAAAAAAAAAAA_AAAAAAAAAAAAAAAA
+; run: %bitselect_i128(0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF, 0) == 0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF
diff --git a/cranelift/filetests/filetests/runtests/issue-6916.clif b/cranelift/filetests/filetests/runtests/issue-6916.clif
new file mode 100644
index 000000000..f7309a5ac
--- /dev/null
+++ b/cranelift/filetests/filetests/runtests/issue-6916.clif
@@ -0,0 +1,43 @@
+test interpret
+test run
+set opt_level=speed
+target x86_64
+target x86_64 has_avx
+target aarch64
+target s390x
+target riscv64 has_v
+
+function %simd_band(f32, f32) -> f32x4 fast {
+block0(v0: f32, v1: f32):
+    v2 = splat.f32x4 v0
+    v3 = splat.f32x4 v1
+    v4 = band v2, v3
+    return v4
+}
+; run: %simd_band(0x1.0, 0x1.0) == [0x1.0 0x1.0 0x1.0 0x1.0]
+
+function %simd_bor(f32, f32) -> f32x4 fast {
+block0(v0: f32, v1: f32):
+    v2 = splat.f32x4 v0
+    v3 = splat.f32x4 v1
+    v4 = bor v2, v3
+    return v4
+}
+; run: %simd_bor(0x1.0, 0x1.0) == [0x1.0 0x1.0 0x1.0 0x1.0]
+
+function %simd_bxor(f32, f32) -> f32x4 fast {
+block0(v0: f32, v1: f32):
+    v2 = splat.f32x4 v0
+    v3 = splat.f32x4 v1
+    v4 = bxor v2, v3
+    return v4
+}
+; run: %simd_bxor(0x1.0, 0x1.0) == [0x0.0 0x0.0 0x0.0 0x0.0]
+
+function %simd_bnot(f32) -> f32x4 fast {
+block0(v0: f32):
+    v1 = splat.f32x4 v0
+    v2 = bnot v1
+    return v2
+}
+; run: %simd_bnot(0x1.0) == [-0x1.fffffep1 -0x1.fffffep1 -0x1.fffffep1 -0x1.fffffep1]
diff --git a/cranelift/filetests/filetests/runtests/simd-bitselect.clif b/cranelift/filetests/filetests/runtests/simd-bitselect.clif
index 4b79c2314..700737985 100644
--- a/cranelift/filetests/filetests/runtests/simd-bitselect.clif
+++ b/cranelift/filetests/filetests/runtests/simd-bitselect.clif
@@ -64,3 +64,11 @@ block0:
     return v11
 }
 ; run
+
+function %bitselect_vconst_f64x2(f64x2, f64x2) -> f64x2 {
+block0(v1: f64x2, v2: f64x2):
+  v0 = vconst.f64x2 0xFF00000000000000FF00000000000000
+  v3 = bitselect v0, v1, v2
+  return v3
+}
+; run: %bitselect_vconst_f64x2(0x11111111111111111111111111111111, 0x00000000000000000000000000000000) == 0x11000000000000001100000000000000
diff --git a/cranelift/filetests/src/test_wasm/config.rs b/cranelift/filetests/src/test_wasm/config.rs
index 3836503e7..ab85af333 100644
--- a/cranelift/filetests/src/test_wasm/config.rs
+++ b/cranelift/filetests/src/test_wasm/config.rs
@@ -4,7 +4,7 @@
 
 use anyhow::{bail, ensure, Result};
 use cranelift_codegen::ir;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::BTreeMap;
 
 #[derive(Clone, Debug, Serialize, Deserialize)]
diff --git a/crates/component-macro/tests/codegen/unions.wit b/crates/component-macro/tests/codegen/unions.wit
deleted file mode 100644
index 252f513f2..000000000
--- a/crates/component-macro/tests/codegen/unions.wit
+++ /dev/null
@@ -1,66 +0,0 @@
-package foo:foo
-
-interface unions {
-  /// A union of all of the integral types
-  union all-integers {
-      /// Bool is equivalent to a 1 bit integer
-      /// and is treated that way in some languages
-      bool,
-      u8, u16, u32, u64,
-      s8, s16, s32, s64
-  }
-  union all-floats {
-      float32, float64
-  }
-  union all-text {
-      char, string
-  }
-
-  // Returns the same case as the input but with 1 added
-  add-one-integer: func(num: all-integers) -> all-integers
-  // Returns the same case as the input but with 1 added
-  add-one-float: func(num: all-floats) -> all-floats
-  // Returns the same case as the input but with the first character replaced
-  replace-first-char: func(text: all-text, letter: char) -> all-text
-
-  // Returns the index of the case provided
-  identify-integer: func(num: all-integers) -> u8
-  // Returns the index of the case provided
-  identify-float: func(num: all-floats) -> u8
-  // Returns the index of the case provided
-  identify-text: func(text: all-text) -> u8
-
-  union duplicated-s32 {
-      /// The first s32
-      s32,
-      /// The second s32
-      s32,
-      /// The third s32
-      s32
-  }
-
-  // Returns the same case as the input but with 1 added
-  add-one-duplicated: func(num: duplicated-s32) -> duplicated-s32
-
-  // Returns the index of the case provided
-  identify-duplicated: func(num: duplicated-s32) -> u8
-
-  /// A type containing numeric types that are distinct in most languages
-  union distinguishable-num {
-      /// A Floating Point Number
-      float64,
-      /// A Signed Integer
-      s64
-  }
-
-  // Returns the same case as the input but with 1 added
-  add-one-distinguishable-num: func(num: distinguishable-num) -> distinguishable-num
-
-  // Returns the index of the case provided
-  identify-distinguishable-num: func(num: distinguishable-num) -> u8
-}
-
-world the-unions {
-  import unions
-  export unions
-}
diff --git a/crates/component-macro/tests/codegen/variants.wit b/crates/component-macro/tests/codegen/variants.wit
index b6c47d896..a53938cb0 100644
--- a/crates/component-macro/tests/codegen/variants.wit
+++ b/crates/component-macro/tests/codegen/variants.wit
@@ -8,19 +8,10 @@ interface variants {
   e1-arg: func(x: e1)
   e1-result: func() -> e1
 
-  union u1 {
-      u32,
-      float32,
-  }
-
-  u1-arg: func(x: u1)
-  u1-result: func() -> u1
-
   record empty {}
 
   variant v1 {
       a,
-      b(u1),
       c(e1),
       d(string),
       e(empty),
@@ -40,7 +31,6 @@ interface variants {
     c: option<u32>,
     d: option<e1>,
     e: option<float32>,
-    f: option<u1>,
     g: option<option<bool>>,
   )
   option-result: func() -> tuple<
@@ -49,7 +39,6 @@ interface variants {
     option<u32>,
     option<e1>,
     option<float32>,
-    option<u1>,
     option<option<bool>>,
   >
 
diff --git a/tests/all/component_model/dynamic.rs b/tests/all/component_model/dynamic.rs
index 4f4092628..6d24163c5 100644
--- a/tests/all/component_model/dynamic.rs
+++ b/tests/all/component_model/dynamic.rs
@@ -436,8 +436,6 @@ fn everything() -> Result<()> {
                     (case "M" $m)
                 ))
                 (export $j "j" (type $j'))
-                (type $z' (union u32 float64))
-                (export $z "z" (type $z'))
 
                 (type $Foo' (record
                     (field "A" u32)
@@ -454,7 +452,6 @@ fn everything() -> Result<()> {
                     (field "V" string)
                     (field "W" char)
                     (field "Y" (tuple u32 u32))
-                    (field "Z" $z)
                     (field "AA" (option u32))
                     (field "BB" (result string (error string)))
                 ))
@@ -497,8 +494,8 @@ fn everything() -> Result<()> {
         .fields()
         .map(|field| field.ty)
         .collect::<Box<[component::Type]>>();
-    let (b_type, c_type, f_type, j_type, y_type, z_type, aa_type, bb_type) = (
-        &types[1], &types[2], &types[3], &types[4], &types[13], &types[14], &types[15], &types[16],
+    let (b_type, c_type, f_type, j_type, y_type, aa_type, bb_type) = (
+        &types[1], &types[2], &types[3], &types[4], &types[13], &types[14], &types[15],
     );
     let f_element_type = &f_type.unwrap_list().ty();
     let input = ty.unwrap_record().new_val([
@@ -536,10 +533,6 @@ fn everything() -> Result<()> {
                 .unwrap_tuple()
                 .new_val(Box::new([Val::U32(42), Val::U32(24)]))?,
         ),
-        (
-            "Z",
-            z_type.unwrap_union().new_val(1, Val::Float64(3.14159265))?,
-        ),
         (
             "AA",
             aa_type.unwrap_option().new_val(Some(Val::U32(314159265)))?,
diff --git a/tests/all/component_model/macros.rs b/tests/all/component_model/macros.rs
index 0bd2b2b5c..cf59adb48 100644
--- a/tests/all/component_model/macros.rs
+++ b/tests/all/component_model/macros.rs
@@ -115,94 +115,6 @@ fn record_derive() -> Result<()> {
     Ok(())
 }
 
-#[test]
-fn union_derive() -> Result<()> {
-    #[derive(ComponentType, Lift, Lower, PartialEq, Debug, Copy, Clone)]
-    #[component(union)]
-    enum Foo {
-        A(i32),
-        B(u32),
-        C(i32),
-    }
-
-    let engine = super::engine();
-    let mut store = Store::new(&engine, ());
-
-    // Happy path: component type matches case count and types
-
-    let component = Component::new(&engine, make_echo_component("(union s32 u32 s32)", 8))?;
-    let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")?;
-
-    for &input in &[Foo::A(-42), Foo::B(73), Foo::C(314159265)] {
-        let output = func.call_and_post_return(&mut store, (input,))?;
-
-        assert_eq!((input,), output);
-    }
-
-    // Sad path: case count mismatch (too few)
-
-    let component = Component::new(&engine, make_echo_component("(union s32 u32)", 8))?;
-    let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-
-    assert!(instance
-        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
-        .is_err());
-
-    // Sad path: case count mismatch (too many)
-
-    let component = Component::new(
-        &engine,
-        make_echo_component(r#"(union s32 u32 s32 s32)"#, 8),
-    )?;
-    let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-
-    assert!(instance
-        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
-        .is_err());
-
-    assert!(instance
-        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
-        .is_err());
-
-    // Sad path: case type mismatch
-
-    let component = Component::new(&engine, make_echo_component("(union s32 s32 s32)", 8))?;
-    let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-
-    assert!(instance
-        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
-        .is_err());
-
-    // Happy path redux, with generics this time
-
-    #[derive(ComponentType, Lift, Lower, PartialEq, Debug, Copy, Clone)]
-    #[component(union)]
-    enum Generic<A, B, C> {
-        A(A),
-        B(B),
-        C(C),
-    }
-
-    let component = Component::new(&engine, make_echo_component("(union s32 u32 s32)", 8))?;
-    let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Generic<i32, u32, i32>,), (Generic<i32, u32, i32>,)>(
-        &mut store, "echo",
-    )?;
-
-    for &input in &[
-        Generic::<i32, u32, i32>::A(-42),
-        Generic::B(73),
-        Generic::C(314159265),
-    ] {
-        let output = func.call_and_post_return(&mut store, (input,))?;
-
-        assert_eq!((input,), output);
-    }
-
-    Ok(())
-}
-
 #[test]
 fn variant_derive() -> Result<()> {
     #[derive(ComponentType, Lift, Lower, PartialEq, Eq, Debug, Copy, Clone)]
diff --git a/tests/all/wasi_testsuite.rs b/tests/all/wasi_testsuite.rs
index 8edeecaa8..a80a7aade 100644
--- a/tests/all/wasi_testsuite.rs
+++ b/tests/all/wasi_testsuite.rs
@@ -7,7 +7,7 @@
 
 use crate::cli_tests::get_wasmtime_command;
 use anyhow::{anyhow, Result};
-use serde::Deserialize;
+use serde_derive::Deserialize;
 use std::collections::HashMap;
 use std::ffi::OsStr;
 use std::fs;
diff --git a/tests/misc_testsuite/component-model/types.wast b/tests/misc_testsuite/component-model/types.wast
index ebe154ca9..79df86454 100644
--- a/tests/misc_testsuite/component-model/types.wast
+++ b/tests/misc_testsuite/component-model/types.wast
@@ -2,7 +2,7 @@
   (type string)
   (type (func (param "a" string)))
   (type $r (record (field "x" (result)) (field "y" string)))
-  (type $u (union $r string))
+  (type $u (variant (case "r" $r) (case "s" string)))
   (type $e (result $u (error u32)))
   (type (result $u))
   (type (result (error $u)))
diff --git a/winch/filetests/Cargo.toml b/winch/filetests/Cargo.toml
index 9250078b4..94e51b866 100644
--- a/winch/filetests/Cargo.toml
+++ b/winch/filetests/Cargo.toml
@@ -18,5 +18,6 @@ wat = { workspace = true }
 similar = { workspace = true }
 toml = { workspace = true }
 serde = { workspace = true }
+serde_derive = { workspace = true }
 cranelift-codegen = { workspace = true }
 capstone = { workspace = true }
diff --git a/winch/filetests/src/lib.rs b/winch/filetests/src/lib.rs
index ab6149dc5..b1f5daa86 100644
--- a/winch/filetests/src/lib.rs
+++ b/winch/filetests/src/lib.rs
@@ -5,7 +5,7 @@ mod test {
     use super::disasm::disasm;
     use anyhow::Context;
     use cranelift_codegen::settings::{self, Configurable};
-    use serde::{Deserialize, Serialize};
+    use serde_derive::{Deserialize, Serialize};
     use similar::TextDiff;
     use std::str::FromStr;
     use target_lexicon::Triple;