diff --git a/.cargo/config.in b/.cargo/config.in
index 417f096bedc9d225368b8f6f57b276412428dcbb..48fa8e63c50a1b33119a52047eea9d60ae03b151 100644
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -25,7 +25,7 @@ replace-with = "vendored-sources"
 [source."https://github.com/CraneStation/Cranelift"]
 git = "https://github.com/CraneStation/Cranelift"
 replace-with = "vendored-sources"
-rev = "9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+rev = "182414f15c18538dfebbe040469ec8001e93ecc5"
 
 [source.crates-io]
 replace-with = "vendored-sources"
diff --git a/Cargo.lock b/Cargo.lock
index 090cba812b754a40858871991538f847528a5da5..22d99bb2418385c7e8353c7407fc154ebde3297b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -189,8 +189,8 @@ name = "baldrdash"
 version = "0.1.0"
 dependencies = [
  "bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
- "cranelift-wasm 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
+ "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-wasm 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -587,20 +587,21 @@ dependencies = [
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.42.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
 dependencies = [
- "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
+ "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.42.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
 dependencies = [
- "cranelift-bforest 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
- "cranelift-codegen-meta 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
- "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
+ "cranelift-bforest 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-codegen-meta 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-codegen-shared 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -610,23 +611,29 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.42.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
 dependencies = [
- "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
+ "cranelift-codegen-shared 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
 ]
 
+[[package]]
+name = "cranelift-codegen-shared"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
+
 [[package]]
 name = "cranelift-entity"
-version = "0.42.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.42.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
 dependencies = [
- "cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
+ "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -634,16 +641,16 @@ dependencies = [
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.42.0"
-source = "git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e#9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+version = "0.44.0"
+source = "git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5#182414f15c18538dfebbe040469ec8001e93ecc5"
 dependencies = [
- "cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
- "cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
- "cranelift-frontend 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)",
+ "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
+ "cranelift-frontend 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "wasmparser 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasmparser 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3459,7 +3466,7 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.37.0"
+version = "0.39.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -3803,12 +3810,13 @@ dependencies = [
 "checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
 "checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
-"checksum cranelift-bforest 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>"
-"checksum cranelift-codegen 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>"
-"checksum cranelift-codegen-meta 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>"
-"checksum cranelift-entity 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>"
-"checksum cranelift-frontend 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>"
-"checksum cranelift-wasm 0.42.0 (git+https://github.com/CraneStation/Cranelift?rev=9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e)" = "<none>"
+"checksum cranelift-bforest 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
+"checksum cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
+"checksum cranelift-codegen-meta 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
+"checksum cranelift-codegen-shared 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
+"checksum cranelift-entity 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
+"checksum cranelift-frontend 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
+"checksum cranelift-wasm 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)" = "<none>"
 "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
 "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
 "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
@@ -4059,7 +4067,7 @@ dependencies = [
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
 "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
 "checksum warp 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "33857527c63bc514452f885d0a57019f28139c58fef2b3566016ecc0d44e5d24"
-"checksum wasmparser 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82dbea680995dad585289fd47889cf9614133ebfcc3bda95737ef8bdc9e11db6"
+"checksum wasmparser 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a026c1436af49d5537c7561c7474f81f7a754e36445fe52e6e88795a9747291c"
 "checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
diff --git a/Cargo.toml b/Cargo.toml
index 722880c2f6ef075170e151f1622f1e80e58927be..9f8db22bfce984de9238fbcdf3df626519e0568b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -64,11 +64,11 @@ packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_
 
 [patch.crates-io.cranelift-codegen]
 git = "https://github.com/CraneStation/Cranelift"
-rev = "9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+rev = "182414f15c18538dfebbe040469ec8001e93ecc5"
 
 [patch.crates-io.cranelift-wasm]
 git = "https://github.com/CraneStation/Cranelift"
-rev = "9c6f8feb0f28f50434c0cf67f3f7c07486a42b7e"
+rev = "182414f15c18538dfebbe040469ec8001e93ecc5"
 
 [patch.crates-io.coreaudio-sys]
 path = "third_party/rust/coreaudio-sys"
diff --git a/js/src/wasm/cranelift/Cargo.toml b/js/src/wasm/cranelift/Cargo.toml
index b22a860f81146754a348ba6e9647249655c45fda..d8e972f22f61710368ec9d87eb7e5383319b07d6 100644
--- a/js/src/wasm/cranelift/Cargo.toml
+++ b/js/src/wasm/cranelift/Cargo.toml
@@ -13,8 +13,8 @@ name = "baldrdash"
 # cranelift-wasm to pinned commits. If you want to update Cranelift in Gecko,
 # you should update the following $TOP_LEVEL/Cargo.toml file: look for the
 # revision (rev) hashes of both cranelift dependencies (codegen and wasm).
-cranelift-codegen = { version = "0.42", default-features = false }
-cranelift-wasm = "0.42"
+cranelift-codegen = { version = "0.44", default-features = false }
+cranelift-wasm = "0.44"
 log = { version = "0.4.6", default-features = false, features = ["release_max_level_info"] }
 env_logger = "0.6"
 smallvec = { version = "0.6.6" }
diff --git a/third_party/rust/cranelift-bforest/.cargo-checksum.json b/third_party/rust/cranelift-bforest/.cargo-checksum.json
index c8d31b7866c96345101d137b14652f1de17a3166..a6097d2734d0323e1c260c3ef07676f86874cee1 100644
--- a/third_party/rust/cranelift-bforest/.cargo-checksum.json
+++ b/third_party/rust/cranelift-bforest/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"5c0fac24938cd87403f8055d56082b820a284f40a45be73c0fcd63fad0704285","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"d821f2fe04df070a05a2e1de29b913f9970dfb500b35511a39c2976f1f26c977","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"a86ee1c882c173e8af96fd53a416a0fb485dd3f045ac590ef313a9d9ecf90f56","src/pool.rs":"6090f8c0e0da16ebee0e31bca66392d0075b3aff529d30d4e716fa20cd0aef99","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"f6af616cc6e55e0ff0a292c52fb8bd5b093345fe5495e67f153dd94da153adab","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"d821f2fe04df070a05a2e1de29b913f9970dfb500b35511a39c2976f1f26c977","src/map.rs":"5d891d62814941e19dfc88ff36538efa3da5479f3f97de8219a6f610c9a1ee32","src/node.rs":"e620c64e78488035f11723b14892c7986c06ad37dc5b115a35a453ff1ae66ca3","src/path.rs":"a86ee1c882c173e8af96fd53a416a0fb485dd3f045ac590ef313a9d9ecf90f56","src/pool.rs":"56f987d338a9419696ffb3ff09a4322a0ec97554eeca255e8c5fae7941e44f57","src/set.rs":"b411158f813a310c7a6c337d4ada3bf0a021088c443875dc25233415dcbe0633"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-bforest/Cargo.toml b/third_party/rust/cranelift-bforest/Cargo.toml
index fee6d19b2e1122a12e7b8300413c67e60ea6a0f8..960827da52b542c77b359cffe418efc19d77758c 100644
--- a/third_party/rust/cranelift-bforest/Cargo.toml
+++ b/third_party/rust/cranelift-bforest/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 authors = ["The Cranelift Project Developers"]
 name = "cranelift-bforest"
-version = "0.42.0"
+version = "0.44.0"
 description = "A forest of B+-trees"
 license = "Apache-2.0 WITH LLVM-exception"
 documentation = "https://cranelift.readthedocs.io/"
@@ -12,7 +12,7 @@ keywords = ["btree", "forest", "set", "map"]
 edition = "2018"
 
 [dependencies]
-cranelift-entity = { path = "../cranelift-entity", version = "0.42.0", default-features = false }
+cranelift-entity = { path = "../cranelift-entity", version = "0.44.0", default-features = false }
 
 [features]
 default = ["std"]
diff --git a/third_party/rust/cranelift-bforest/src/pool.rs b/third_party/rust/cranelift-bforest/src/pool.rs
index 1b51cfe56bbb4e8915623136dee9795f9e813a4c..0848089eb6adaab03ea44afa905aee1dd95a3935 100644
--- a/third_party/rust/cranelift-bforest/src/pool.rs
+++ b/third_party/rust/cranelift-bforest/src/pool.rs
@@ -83,7 +83,7 @@ impl<F: Forest> NodePool<F> {
         NodeData<F>: fmt::Display,
         F::Key: fmt::Display,
     {
-        use crate::entity::SparseSet;
+        use crate::entity::EntitySet;
         use core::borrow::Borrow;
         use core::cmp::Ordering;
         use std::vec::Vec;
@@ -94,7 +94,13 @@ impl<F: Forest> NodePool<F> {
             assert!(size > 0, "Root must have more than one sub-tree");
         }
 
-        let mut done = SparseSet::new();
+        let mut done = match self[node] {
+            NodeData::Inner { size, .. } | NodeData::Leaf { size, .. } => {
+                EntitySet::with_capacity(size.into())
+            }
+            _ => EntitySet::new(),
+        };
+
         let mut todo = Vec::new();
 
         // Todo-list entries are:
@@ -104,11 +110,7 @@ impl<F: Forest> NodePool<F> {
         todo.push((None, node, None));
 
         while let Some((lkey, node, rkey)) = todo.pop() {
-            assert_eq!(
-                done.insert(node),
-                None,
-                "Node appears more than once in tree"
-            );
+            assert!(done.insert(node), "Node appears more than once in tree");
             let mut lower = lkey;
 
             match self[node] {
diff --git a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
index 272698e152a1438237618f57bda5563299aa2efc..61afd2416ccb6ca1761f346b5df066ff8f3e7470 100644
--- a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
+++ b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"e4a42edddd547e9aff7d2ccc3469f3685ae1eff54cece29d8f4fa1d2e80b063d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"7ff4532bb6c3c4570918cfac54c308f345d6710ad8696aa444503a60d42408a6","src/cdsl/cpu_modes.rs":"7c59ae347d6f9c769d6356fe49c8406934153eefa59d9bf37c182474fcbb9715","src/cdsl/encodings.rs":"da6fa16c95fe4a586c2d00ef4ccf79b4b0f64cd8923b3ca5a5a527da1e799a4f","src/cdsl/formats.rs":"5ed0d689b791d928e51f9608cb139dde7be810ff1dc4e03c58a6fe79e43eeffd","src/cdsl/instructions.rs":"cd1b1c6ccf90a3ba3506859d7bff9f7073a46c11aecf501b7b35af68e76240e2","src/cdsl/isa.rs":"9b6030a935f69b07726d239c23a78d654566785f1fed61ccefdaf7d4f0a97d0e","src/cdsl/mod.rs":"c85f62a7d8d6bedc81c673b8d02be01181f79f272dbc0325a76d52e7eec732e8","src/cdsl/operands.rs":"1cda258798d861c4f467783b5c70c1202a57f554861017eead6477af2ee34063","src/cdsl/recipes.rs":"9f50f29f243f2ed8dbca3ef8b2722e9671bc164b2956254a95ed62641315eab7","src/cdsl/regs.rs":"3e70d11c04a123c9d91075e14af6909a885f37a0c2f86df6aca1b337e2994763","src/cdsl/settings.rs":"7da3c5a9df8e47ed6ca7f1d820e28eae45e783f3759f6c55730d2f17d88f1013","src/cdsl/type_inference.rs":"c576403ca05921d6a416b21e7f5bd5a2219b635ad78ed1139dc8e3363ba61beb","src/cdsl/types.rs":"9f8221b5d3987b30943ba5f168190cb220b59350e9463ca264ecfd663dbbc3a2","src/cdsl/typevar.rs":"2b67b32524cdf783aeb1fcedbf82a33190104e87ed210ca0638cf6bb28eefd98","src/cdsl/xform.rs":"120be9a35b48d4b2c474bca9684c687797045d1d07554f639e1812cda16cc743","src/constant_hash.rs":"66d6f42c1e98cd4dbc95009997dc00256b57c11d2c2d9eac63b33e458c68a56f","src/default_map.rs":"8bbd6f4d9f93ef2126538cda633e6d9c80a5c7dc79b8d5a759c8be1fe2dbc605","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_binemit.rs":"80c27e9c66d2ac3dc8a41cc545f046bd4297ba6530805539e86461984fd2667d","src/gen_encodings.rs":"bb598d4eeb8e7365a023ebbb4cc0d8c9f57163b4d0d489047f0fcdbe83880adb","src/gen_inst.rs":"c31663699705cb35697dd23ee4f34d2502414a2d2f716b872e47aac1ba56e710","src/gen_legalizer.rs":"0e8ea0810da954d812f9110e900b9ba3830ff81be46c5985e0340e69f75ebbe8","src/gen_registers.rs":"9b581bd79a1370cdc6920ed18e8da84751813a4b1c9697e891bf0da4eceefc0d","src/gen_settings.rs":"765ca86fa735342c1875021c34a92cbc39836ba3ad1c12aa615204372a1f7b61","src/gen_types.rs":"c062eaf3a2ed7368b87213922906107bbaec184fe821184a34dacb4e5b0fc3dc","src/isa/arm32/mod.rs":"5ca444f18d438f879edb857c75e129931067794a669b607350c4ed648fd92520","src/isa/arm64/mod.rs":"9a1acc8533a1c9be332c565f399cf1c9b5a0a85290bf7bcb82b778fc412d5fa5","src/isa/mod.rs":"a728d5063d34a4ac572ad63ff0f458da33703c58cdd901a0c36276f426fbb0d1","src/isa/riscv/encodings.rs":"695159378a75cb143482c401c4e5ffefa28082cbb996e944942ef0cdc3d10db6","src/isa/riscv/mod.rs":"4945ad95284ac157593935722b75f120b4a0e22b133e69a1e9784e6cd3615c0a","src/isa/riscv/recipes.rs":"5cfdc71a3d5640de6ec956eb8eb6a3a85135daa1d6e30d1d6a693b6ad2d12e0e","src/isa/x86/encodings.rs":"886c875d740ba0b4b3d34c2c06eb33e2089a529eba1103bf962452e0bc34c0e5","src/isa/x86/instructions.rs":"c438579d98562e6efb67edf5983ffab26a3c7c2d8b20dccbd2667687031fa7f4","src/isa/x86/legalize.rs":"1f44559eac3e9db307759bbed8db5d15b1166303e3fa3c9c5fb386ad990e32a5","src/isa/x86/mod.rs":"7a3aeebfed131b86244fc4746b3dc42f4968d48cbb23a10214efb0a0d56c94c9","src/isa/x86/recipes.rs":"a9c128c26918eb01b400b78d7eee04a3cc61784b1288d26bd43b4ea7224f2a82","src/isa/x86/registers.rs":"3cde7d3275971d651ae0f25c88bfb81128b7a35183a969aed81776d4c5141e0e","src/isa/x86/settings.rs":"4e84ff135d6f21595bbd8f56d2e561abd3c123566f2332ac93bb4a9c627f0c00","src/lib.rs":"bc458358fd81d092f368b243d07682259dbed7a336b1eed5bcdf5228368289e9","src/shared/entities.rs":"d3dc9d6cb5ba30b1bbdcbfa4505e4897618064dab0b99006fd247d0c93f0b3dc","src/shared/formats.rs":"c6a4622fad932aadb7b5341aee5453c53ff08e0f1e1ee848752cf217fbce62b1","src/shared/immediates.rs":"954ef3c5724f26d16178fc2539111e5ecabebe9ea83d24b2b90d5a8ab411c1a9","src/shared/instructions.rs":"a21d36e9917d7d67c188a46c744c38011d81e892d7a5d32a22437047aecebdbf","src/shared/legalize.rs":"07c6a74ced50bcd7e06731165ede44880c418da0d9785e6e6b8fc02cea218d84","src/shared/mod.rs":"6c9010c934e85c668e089fded99805e9a3aa09a9d9ad408382c5345b6cb375b6","src/shared/settings.rs":"22825dd2b9d924ec147c675836ac3644adffd6a059c31b9470581c4597905c28","src/shared/types.rs":"b47799d381f3a554adcccf40824d83be56cd3ef08245c550ceff53363dfa7ad4","src/srcgen.rs":"79fee2f603b33f76f7c9c8b9452c745a363d732c40c0814d84001ff3ef805677","src/unique_table.rs":"90b7203b29241a1ede70f0a3e50d96799e0b41d8f7455170d6ffb127f87f3cc3"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"be4b8f4a7a9f0c0d345243f4b9bf51a5c0d72350c7602ae1dc2e9d5a44ed4ee3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/cdsl/ast.rs":"7b9d59fb1ee9efd13e2347d20b76c508bfe5992e0e4d4ccb837be763de1843db","src/cdsl/cpu_modes.rs":"b42421b48f77804c2cfae744dc9e3c98c3787746c2649af201e0d4b8997eadae","src/cdsl/encodings.rs":"299dbec5e67907cbb7e8b798913bbc606f26833cb08790d9dae159ba7d8b8c66","src/cdsl/formats.rs":"5ed0d689b791d928e51f9608cb139dde7be810ff1dc4e03c58a6fe79e43eeffd","src/cdsl/instructions.rs":"42b55c2c07878df6c23ba9b1bff78a47c933e9652252421aefd564d8c1f171f0","src/cdsl/isa.rs":"ccabd6848b69eb069c10db61c7e7f86080777495714bb53d03e663c40541be94","src/cdsl/mod.rs":"c85f62a7d8d6bedc81c673b8d02be01181f79f272dbc0325a76d52e7eec732e8","src/cdsl/operands.rs":"1cda258798d861c4f467783b5c70c1202a57f554861017eead6477af2ee34063","src/cdsl/recipes.rs":"9f50f29f243f2ed8dbca3ef8b2722e9671bc164b2956254a95ed62641315eab7","src/cdsl/regs.rs":"3e70d11c04a123c9d91075e14af6909a885f37a0c2f86df6aca1b337e2994763","src/cdsl/settings.rs":"7da3c5a9df8e47ed6ca7f1d820e28eae45e783f3759f6c55730d2f17d88f1013","src/cdsl/type_inference.rs":"4ba2099e2c5df4f603f0a51a4ac19761a4723009cbc0ae66a3e9b82f5c851c05","src/cdsl/types.rs":"9f8221b5d3987b30943ba5f168190cb220b59350e9463ca264ecfd663dbbc3a2","src/cdsl/typevar.rs":"e375a0719b918ef1922296e71758ba1ddc236b9378635db0de980ea36d427049","src/cdsl/xform.rs":"4d4769d47580e25f57ac119a2193a5e33b946545c7e75b0642d255e9cf81575f","src/constant_hash.rs":"91db790f44df312a7478271056db6edf9d12389ee9c675e2d1bb1b60c98353c9","src/default_map.rs":"5e1aeff22953d78083f5184a62da53c92e8b908f5edea30353c048e5201af9e3","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_binemit.rs":"dd850f3a34a80ece53bd8a40017e77c425c0d0ad044a4efd2c1ee02c71cb614f","src/gen_encodings.rs":"bb598d4eeb8e7365a023ebbb4cc0d8c9f57163b4d0d489047f0fcdbe83880adb","src/gen_inst.rs":"d2c157a9986f31515abd2f154d7d7d8ca61efc5a932bd7ae845af959b1fc1e66","src/gen_legalizer.rs":"9634204a42273d77f0a062bbb04b83e09b11452690af9cddb0faac990fa3b346","src/gen_registers.rs":"bcc1df255045b79d0772d2a1fc9aaac44764ed23ed7acf88f57050aca735dce2","src/gen_settings.rs":"4b34cdd93a52053e88cea7f00b8078518d69fec2e89da054c1d824a8144b666a","src/gen_types.rs":"f6c090e1646a43bf2fe81ae0a7029cc6f7dc6d43285368f56d86c35a21c469a6","src/isa/arm32/mod.rs":"5ca444f18d438f879edb857c75e129931067794a669b607350c4ed648fd92520","src/isa/arm64/mod.rs":"9a1acc8533a1c9be332c565f399cf1c9b5a0a85290bf7bcb82b778fc412d5fa5","src/isa/mod.rs":"a728d5063d34a4ac572ad63ff0f458da33703c58cdd901a0c36276f426fbb0d1","src/isa/riscv/encodings.rs":"cad44ff58cd7626d039824107b3d2d5e8d909e59a25e34c8b5c90ccad76a1c28","src/isa/riscv/mod.rs":"4945ad95284ac157593935722b75f120b4a0e22b133e69a1e9784e6cd3615c0a","src/isa/riscv/recipes.rs":"5cfdc71a3d5640de6ec956eb8eb6a3a85135daa1d6e30d1d6a693b6ad2d12e0e","src/isa/x86/encodings.rs":"e03d12d7ae5aadedc2ea5f0f7952a74b093adc2c747dd0b07be9202955d0ac47","src/isa/x86/instructions.rs":"c438579d98562e6efb67edf5983ffab26a3c7c2d8b20dccbd2667687031fa7f4","src/isa/x86/legalize.rs":"150cf83b605cf0bfc7618937c60d69dbc9504c6c4242806deeb87591b18f6793","src/isa/x86/mod.rs":"1d13c0a294ce85f09d60a2d33d24848733c6053b8d47298b7b0eefbc9b7ee317","src/isa/x86/opcodes.rs":"6558e45e8027b46b2201e0152affc7093a8b10d3e45ef2f457de37af3cc180a0","src/isa/x86/recipes.rs":"43744f2d242ff233e6bf4ed8e13b5c7b024bb0c4735ddd0f6012919f91ab0e85","src/isa/x86/registers.rs":"3cde7d3275971d651ae0f25c88bfb81128b7a35183a969aed81776d4c5141e0e","src/isa/x86/settings.rs":"4e84ff135d6f21595bbd8f56d2e561abd3c123566f2332ac93bb4a9c627f0c00","src/lib.rs":"bc458358fd81d092f368b243d07682259dbed7a336b1eed5bcdf5228368289e9","src/shared/entities.rs":"d3dc9d6cb5ba30b1bbdcbfa4505e4897618064dab0b99006fd247d0c93f0b3dc","src/shared/formats.rs":"2757a729ec9b38853b4810cacbd980f44fe8b200184f45b728eb98060578d1fc","src/shared/immediates.rs":"f13c09d14d148d03ab2c6dcfdcd96d5833d0842c49ea437cbf42a085f7cdb45f","src/shared/instructions.rs":"9128d67b0b9c0a86ccc278e637ec5484ce4e5a680f410ae9b0797598bcd42b8f","src/shared/legalize.rs":"e19c1b808b4c2930323b8de2b63fb478c470014d089cf1c4ad8b349c69259979","src/shared/mod.rs":"7b4de39ea3075ba8d1733319c03f1a19d903215b7bb55f877d0f8826f4b43c85","src/shared/settings.rs":"b141f6e6f0baa516ac5bfb919bc51c577353cd7b47ca796677e32eff2bdf16ce","src/shared/types.rs":"b47799d381f3a554adcccf40824d83be56cd3ef08245c550ceff53363dfa7ad4","src/srcgen.rs":"79fee2f603b33f76f7c9c8b9452c745a363d732c40c0814d84001ff3ef805677","src/unique_table.rs":"90b7203b29241a1ede70f0a3e50d96799e0b41d8f7455170d6ffb127f87f3cc3"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-codegen-meta/Cargo.toml b/third_party/rust/cranelift-codegen-meta/Cargo.toml
index c623493e30988907abae035b3809a8dbd09f6011..2d759573553ea64aca38dd0ea25dae6536175bf7 100644
--- a/third_party/rust/cranelift-codegen-meta/Cargo.toml
+++ b/third_party/rust/cranelift-codegen-meta/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "cranelift-codegen-meta"
 authors = ["The Cranelift Project Developers"]
-version = "0.42.0"
+version = "0.44.0"
 description = "Metaprogram for cranelift-codegen code generator library"
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
@@ -9,7 +9,8 @@ readme = "README.md"
 edition = "2018"
 
 [dependencies]
-cranelift-entity = { path = "../../cranelift-entity", version = "0.42.0", default-features = false }
+cranelift-codegen-shared = { path = "../shared", version = "0.44.0" }
+cranelift-entity = { path = "../../cranelift-entity", version = "0.44.0", default-features = false }
 
 [badges]
 maintenance = { status = "experimental" }
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs
index 798ee29d002375fbc1300de9db5078e76fd9e623..5618927bb47db9af5b76741d339990512fd4f122 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/ast.rs
@@ -4,12 +4,12 @@ use crate::cdsl::operands::{OperandKind, OperandKindFields};
 use crate::cdsl::types::ValueType;
 use crate::cdsl::typevar::{TypeSetBuilder, TypeVar};
 
-use cranelift_entity::{entity_impl, PrimaryMap};
+use cranelift_entity::{entity_impl, PrimaryMap, SparseMap, SparseMapValue};
 
 use std::fmt;
+use std::iter::IntoIterator;
 
-#[derive(Debug)]
-pub enum Expr {
+pub(crate) enum Expr {
     Var(VarIndex),
     Literal(Literal),
 }
@@ -44,7 +44,7 @@ impl Expr {
 }
 
 /// An AST definition associates a set of variables with the values produced by an expression.
-pub struct Def {
+pub(crate) struct Def {
     pub apply: Apply,
     pub defined_vars: Vec<VarIndex>,
 }
@@ -67,7 +67,7 @@ impl Def {
     }
 }
 
-pub struct DefPool {
+pub(crate) struct DefPool {
     pool: PrimaryMap<DefIndex, Def>,
 }
 
@@ -83,7 +83,7 @@ impl DefPool {
     pub fn next_index(&self) -> DefIndex {
         self.pool.next_key()
     }
-    pub fn create(&mut self, apply: Apply, defined_vars: Vec<VarIndex>) -> DefIndex {
+    pub fn create_inst(&mut self, apply: Apply, defined_vars: Vec<VarIndex>) -> DefIndex {
         self.pool.push(Def {
             apply,
             defined_vars,
@@ -92,57 +92,92 @@ impl DefPool {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct DefIndex(u32);
+pub(crate) struct DefIndex(u32);
 entity_impl!(DefIndex);
 
-#[derive(Debug, Clone)]
-enum LiteralValue {
+/// A definition which would lead to generate a block creation.
+#[derive(Clone)]
+pub(crate) struct Block {
+    /// Instruction index after which the block entry is set.
+    pub location: DefIndex,
+    /// Variable holding the new created block.
+    pub name: VarIndex,
+}
+
+pub(crate) struct BlockPool {
+    pool: SparseMap<DefIndex, Block>,
+}
+
+impl SparseMapValue<DefIndex> for Block {
+    fn key(&self) -> DefIndex {
+        self.location
+    }
+}
+
+impl BlockPool {
+    pub fn new() -> Self {
+        Self {
+            pool: SparseMap::new(),
+        }
+    }
+    pub fn get(&self, index: DefIndex) -> Option<&Block> {
+        self.pool.get(index)
+    }
+    pub fn create_block(&mut self, name: VarIndex, location: DefIndex) {
+        if self.pool.contains_key(location) {
+            panic!("Attempt to insert 2 blocks after the same instruction")
+        }
+        self.pool.insert(Block { location, name });
+    }
+    pub fn is_empty(&self) -> bool {
+        self.pool.is_empty()
+    }
+}
+
+// Implement IntoIterator such that we can iterate over blocks which are in the block pool.
+impl<'a> IntoIterator for &'a BlockPool {
+    type Item = <&'a SparseMap<DefIndex, Block> as IntoIterator>::Item;
+    type IntoIter = <&'a SparseMap<DefIndex, Block> as IntoIterator>::IntoIter;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.pool.into_iter()
+    }
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum Literal {
     /// A value of an enumerated immediate operand.
     ///
     /// Some immediate operand kinds like `intcc` and `floatcc` have an enumerated range of values
     /// corresponding to a Rust enum type. An `Enumerator` object is an AST leaf node representing one
     /// of the values.
-    Enumerator(&'static str),
+    Enumerator {
+        rust_type: String,
+        value: &'static str,
+    },
 
     /// A bitwise value of an immediate operand, used for bitwise exact floating point constants.
-    Bits(u64),
+    Bits { rust_type: String, value: u64 },
 
     /// A value of an integer immediate operand.
     Int(i64),
-}
-
-#[derive(Clone)]
-pub struct Literal {
-    kind: OperandKind,
-    value: LiteralValue,
-}
 
-impl fmt::Debug for Literal {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        write!(
-            fmt,
-            "Literal(kind={}, value={:?})",
-            self.kind.name, self.value
-        )
-    }
+    /// A empty list of variable set of arguments.
+    EmptyVarArgs,
 }
 
 impl Literal {
     pub fn enumerator_for(kind: &OperandKind, value: &'static str) -> Self {
-        if let OperandKindFields::ImmEnum(values) = &kind.fields {
-            assert!(
-                values.get(value).is_some(),
-                format!(
-                    "nonexistent value '{}' in enumeration '{}'",
-                    value, kind.name
-                )
-            );
-        } else {
-            panic!("enumerator is for enum values");
-        }
-        Self {
-            kind: kind.clone(),
-            value: LiteralValue::Enumerator(value),
+        let value = match &kind.fields {
+            OperandKindFields::ImmEnum(values) => values.get(value).expect(&format!(
+                "nonexistent value '{}' in enumeration '{}'",
+                value, kind.name
+            )),
+            _ => panic!("enumerator is for enum values"),
+        };
+        Literal::Enumerator {
+            rust_type: kind.rust_type.clone(),
+            value,
         }
     }
 
@@ -151,42 +186,36 @@ impl Literal {
             OperandKindFields::ImmValue => {}
             _ => panic!("bits_of is for immediate scalar types"),
         }
-        Self {
-            kind: kind.clone(),
-            value: LiteralValue::Bits(bits),
+        Literal::Bits {
+            rust_type: kind.rust_type.clone(),
+            value: bits,
         }
     }
 
     pub fn constant(kind: &OperandKind, value: i64) -> Self {
         match kind.fields {
             OperandKindFields::ImmValue => {}
-            _ => panic!("bits_of is for immediate scalar types"),
-        }
-        Self {
-            kind: kind.clone(),
-            value: LiteralValue::Int(value),
+            _ => panic!("constant is for immediate scalar types"),
         }
+        Literal::Int(value)
     }
 
-    pub fn to_rust_code(&self) -> String {
-        let maybe_values = match &self.kind.fields {
-            OperandKindFields::ImmEnum(values) => Some(values),
-            OperandKindFields::ImmValue => None,
-            _ => panic!("impossible per construction"),
-        };
+    pub fn empty_vararg() -> Self {
+        Literal::EmptyVarArgs
+    }
 
-        match self.value {
-            LiteralValue::Enumerator(value) => {
-                format!("{}::{}", self.kind.rust_type, maybe_values.unwrap()[value])
-            }
-            LiteralValue::Bits(bits) => format!("{}::with_bits({:#x})", self.kind.rust_type, bits),
-            LiteralValue::Int(val) => val.to_string(),
+    pub fn to_rust_code(&self) -> String {
+        match self {
+            Literal::Enumerator { rust_type, value } => format!("{}::{}", rust_type, value),
+            Literal::Bits { rust_type, value } => format!("{}::with_bits({:#x})", rust_type, value),
+            Literal::Int(val) => val.to_string(),
+            Literal::EmptyVarArgs => "&[]".into(),
         }
     }
 }
 
 #[derive(Clone, Copy, Debug)]
-pub enum PatternPosition {
+pub(crate) enum PatternPosition {
     Source,
     Destination,
 }
@@ -208,7 +237,7 @@ pub enum PatternPosition {
 /// deleted immediately.
 ///
 /// Temporary values are defined only in the destination pattern.
-pub struct Var {
+pub(crate) struct Var {
     pub name: &'static str,
 
     /// The `Def` defining this variable in a source pattern.
@@ -336,10 +365,10 @@ impl fmt::Debug for Var {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct VarIndex(u32);
+pub(crate) struct VarIndex(u32);
 entity_impl!(VarIndex);
 
-pub struct VarPool {
+pub(crate) struct VarPool {
     pool: PrimaryMap<VarIndex, Var>,
 }
 
@@ -364,8 +393,7 @@ impl VarPool {
 ///
 /// An `Apply` AST expression is created by using function call syntax on instructions. This
 /// applies to both bound and unbound polymorphic instructions.
-#[derive(Debug)]
-pub struct Apply {
+pub(crate) struct Apply {
     pub inst: Instruction,
     pub args: Vec<Expr>,
     pub value_types: Vec<ValueType>,
@@ -395,13 +423,38 @@ impl Apply {
             let arg = &args[imm_index];
             if let Some(literal) = arg.maybe_literal() {
                 let op = &inst.operands_in[imm_index];
-                assert!(
-                    op.kind.name == literal.kind.name,
-                    format!(
-                        "Passing literal of kind {} to field of wrong kind {}",
-                        literal.kind.name, op.kind.name
-                    )
-                );
+                match &op.kind.fields {
+                    OperandKindFields::ImmEnum(values) => {
+                        if let Literal::Enumerator { value, .. } = literal {
+                            assert!(
+                                values.iter().any(|(_key, v)| v == value),
+                                "Nonexistent enum value '{}' passed to field of kind '{}' -- \
+                                 did you use the right enum?",
+                                value,
+                                op.kind.name
+                            );
+                        } else {
+                            panic!(
+                                "Passed non-enum field value {:?} to field of kind {}",
+                                literal, op.kind.name
+                            );
+                        }
+                    }
+                    OperandKindFields::ImmValue => match &literal {
+                        Literal::Enumerator { value, .. } => panic!(
+                            "Expected immediate value in immediate field of kind '{}', \
+                             obtained enum value '{}'",
+                            op.kind.name, value
+                        ),
+                        Literal::Bits { .. } | Literal::Int(_) | Literal::EmptyVarArgs => {}
+                    },
+                    _ => {
+                        panic!(
+                            "Literal passed to non-literal field of kind {}",
+                            op.kind.name
+                        );
+                    }
+                }
             }
         }
 
@@ -511,14 +564,15 @@ impl Apply {
 
 // Simple helpers for legalize actions construction.
 
-pub enum DummyExpr {
+pub(crate) enum DummyExpr {
     Var(DummyVar),
     Literal(Literal),
     Apply(InstSpec, Vec<DummyExpr>),
+    Block(DummyVar),
 }
 
 #[derive(Clone)]
-pub struct DummyVar {
+pub(crate) struct DummyVar {
     pub name: &'static str,
 }
 
@@ -533,16 +587,16 @@ impl Into<DummyExpr> for Literal {
     }
 }
 
-pub fn var(name: &'static str) -> DummyVar {
+pub(crate) fn var(name: &'static str) -> DummyVar {
     DummyVar { name }
 }
 
-pub struct DummyDef {
+pub(crate) struct DummyDef {
     pub expr: DummyExpr,
     pub defined_vars: Vec<DummyVar>,
 }
 
-pub struct ExprBuilder {
+pub(crate) struct ExprBuilder {
     expr: DummyExpr,
 }
 
@@ -558,6 +612,11 @@ impl ExprBuilder {
             defined_vars,
         }
     }
+
+    pub fn block(name: DummyVar) -> Self {
+        let expr = DummyExpr::Block(name);
+        Self { expr }
+    }
 }
 
 macro_rules! def_rhs {
@@ -589,3 +648,11 @@ macro_rules! def {
         def_rhs!($($tt)*).assign_to(Vec::new())
     }
 }
+
+// Helper macro to define legalization recipes.
+macro_rules! ebb {
+    // An basic block definition, splitting the current block in 2.
+    ($block: ident) => {
+        ExprBuilder::block($block).assign_to(Vec::new())
+    };
+}
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs
index 4b4406d2d3887fc5ca45f02289d1a05d4de6202f..6436d2e4a26d7af0ee72f048b2d263537997ebb5 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/cpu_modes.rs
@@ -5,7 +5,7 @@ use crate::cdsl::encodings::Encoding;
 use crate::cdsl::types::{LaneType, ValueType};
 use crate::cdsl::xform::{TransformGroup, TransformGroupIndex};
 
-pub struct CpuMode {
+pub(crate) struct CpuMode {
     pub name: &'static str,
     default_legalize: Option<TransformGroupIndex>,
     monomorphic_legalize: Option<TransformGroupIndex>,
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs
index cd05eb9b38afab8f0b4466564bbc5e882c8cc4c9..77d6bc737464e70da963b19f61b1b923911abe98 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/encodings.rs
@@ -20,7 +20,7 @@ use crate::cdsl::types::ValueType;
 /// 3. With operands providing constraints: `icmp.i32(intcc.eq, x, y)`.
 ///
 /// If the instruction is polymorphic, all type variables must be provided.
-pub struct EncodingContent {
+pub(crate) struct EncodingContent {
     /// The `Instruction` or `BoundInstruction` being encoded.
     inst: InstSpec,
 
@@ -49,9 +49,9 @@ impl EncodingContent {
     }
 }
 
-pub type Encoding = Rc<EncodingContent>;
+pub(crate) type Encoding = Rc<EncodingContent>;
 
-pub struct EncodingBuilder {
+pub(crate) struct EncodingBuilder {
     inst: InstSpec,
     recipe: EncodingRecipeNumber,
     encbits: u16,
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs
index 2737099cc442ba8b313d07e39c45464a6da340f6..178077e456fe76a0f8258c351fa5ca6225d5d798 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/instructions.rs
@@ -13,6 +13,7 @@ use crate::cdsl::operands::Operand;
 use crate::cdsl::type_inference::Constraint;
 use crate::cdsl::types::{LaneType, ReferenceType, ValueType, VectorType};
 use crate::cdsl::typevar::TypeVar;
+use cranelift_codegen_shared::condcodes::IntCC;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct OpcodeNumber(u32);
@@ -614,6 +615,12 @@ pub enum FormatPredicateKind {
     /// Is the immediate format field member equal to zero? (float64 version)
     IsZero64BitFloat,
 
+    /// Is the immediate format field member equal zero in all lanes?
+    IsAllZeroes128Bit,
+
+    /// Does the immediate format field member have ones in all bits of all lanes?
+    IsAllOnes128Bit,
+
     /// Has the value list (in member_name) the size specified in parameter?
     LengthEquals(usize),
 
@@ -622,6 +629,9 @@ pub enum FormatPredicateKind {
 
     /// Is the referenced data object colocated?
     IsColocatedData,
+
+    /// Does the operation have a specific condition code?
+    HasConditionCode(IntCC),
 }
 
 #[derive(Clone, Hash, PartialEq, Eq)]
@@ -690,6 +700,14 @@ impl FormatPredicateNode {
             FormatPredicateKind::IsZero64BitFloat => {
                 format!("predicates::is_zero_64_bit_float({})", self.member_name)
             }
+            FormatPredicateKind::IsAllZeroes128Bit => format!(
+                "predicates::is_all_zeroes_128_bit(func.dfg.constants.get({}))",
+                self.member_name
+            ),
+            FormatPredicateKind::IsAllOnes128Bit => format!(
+                "predicates::is_all_ones_128_bit(func.dfg.constants.get({}))",
+                self.member_name
+            ),
             FormatPredicateKind::LengthEquals(num) => format!(
                 "predicates::has_length_of({}, {}, func)",
                 self.member_name, num
@@ -700,6 +718,10 @@ impl FormatPredicateNode {
             FormatPredicateKind::IsColocatedData => {
                 format!("predicates::is_colocated_data({}, func)", self.member_name)
             }
+            FormatPredicateKind::HasConditionCode(code) => format!(
+                "predicates::is_equal({}, IntCC::{:?})",
+                self.member_name, code
+            ),
         }
     }
 }
@@ -929,6 +951,28 @@ impl InstructionPredicate {
         ))
     }
 
+    pub fn new_is_all_zeroes_128bit(
+        format: &InstructionFormat,
+        field_name: &'static str,
+    ) -> InstructionPredicateNode {
+        InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new(
+            format,
+            field_name,
+            FormatPredicateKind::IsAllZeroes128Bit,
+        ))
+    }
+
+    pub fn new_is_all_ones_128bit(
+        format: &InstructionFormat,
+        field_name: &'static str,
+    ) -> InstructionPredicateNode {
+        InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new(
+            format,
+            field_name,
+            FormatPredicateKind::IsAllOnes128Bit,
+        ))
+    }
+
     pub fn new_length_equals(format: &InstructionFormat, size: usize) -> InstructionPredicateNode {
         assert!(
             format.has_value_list,
@@ -961,6 +1005,18 @@ impl InstructionPredicate {
         ))
     }
 
+    pub fn new_has_condition_code(
+        format: &InstructionFormat,
+        condition_code: IntCC,
+        field_name: &'static str,
+    ) -> InstructionPredicateNode {
+        InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new(
+            format,
+            field_name,
+            FormatPredicateKind::HasConditionCode(condition_code),
+        ))
+    }
+
     pub fn and(mut self, new_node: InstructionPredicateNode) -> Self {
         let node = self.node;
         let mut and_nodes = match node {
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
index e561ce2e9cc884599632a15088f77c9172545d22..512105d09a3b3ffc7efbfbdf2ab5e8dad18aebd8 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
@@ -8,7 +8,7 @@ use crate::cdsl::regs::IsaRegs;
 use crate::cdsl::settings::SettingGroup;
 use crate::cdsl::xform::{TransformGroupIndex, TransformGroups};
 
-pub struct TargetIsa {
+pub(crate) struct TargetIsa {
     pub name: &'static str,
     pub instructions: InstructionGroup,
     pub settings: SettingGroup,
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs
index a56d81463c558d6e65c73fee6dcf3c9eec921e16..51817399694fd2e1dfef073bf1bf60e9ebde4428 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/type_inference.rs
@@ -122,7 +122,7 @@ enum TypeEnvRank {
 }
 
 /// Class encapsulating the necessary bookkeeping for type inference.
-pub struct TypeEnvironment {
+pub(crate) struct TypeEnvironment {
     vars: HashSet<VarIndex>,
     ranks: HashMap<TypeVar, TypeEnvRank>,
     equivalency_map: HashMap<TypeVar, TypeVar>,
@@ -602,7 +602,7 @@ fn infer_definition(
 }
 
 /// Perform type inference on an transformation. Return an updated type environment or error.
-pub fn infer_transform(
+pub(crate) fn infer_transform(
     src: DefIndex,
     dst: &Vec<DefIndex>,
     def_pool: &DefPool,
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs
index 71c2fd2e292a6d67b3a6de426abf9e85bd6027f0..78e702cacf1dc8bab575e73c35b82589608521c4 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/typevar.rs
@@ -851,7 +851,7 @@ impl TypeSetBuilder {
 
     pub fn build(self) -> TypeSet {
         let min_lanes = if self.includes_scalars { 1 } else { 2 };
-;
+
         let bools = range_to_set(self.bools.to_range(1..MAX_BITS, None))
             .into_iter()
             .filter(legal_bool)
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs
index b90d552b9a5b089b5f356cbd6707952937a1e617..6304469718b070532951da1c715997e8cef78cd5 100644
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/xform.rs
@@ -1,5 +1,6 @@
 use crate::cdsl::ast::{
-    Apply, DefIndex, DefPool, DummyDef, DummyExpr, Expr, PatternPosition, VarIndex, VarPool,
+    Apply, BlockPool, DefIndex, DefPool, DummyDef, DummyExpr, Expr, PatternPosition, VarIndex,
+    VarPool,
 };
 use crate::cdsl::instructions::Instruction;
 use crate::cdsl::type_inference::{infer_transform, TypeEnvironment};
@@ -17,11 +18,12 @@ use std::iter::FromIterator;
 /// cases when it applies.
 ///
 /// The source pattern can contain only a single instruction.
-pub struct Transform {
+pub(crate) struct Transform {
     pub src: DefIndex,
     pub dst: Vec<DefIndex>,
     pub var_pool: VarPool,
     pub def_pool: DefPool,
+    pub block_pool: BlockPool,
     pub type_env: TypeEnvironment,
 }
 
@@ -31,6 +33,7 @@ impl Transform {
     fn new(src: DummyDef, dst: Vec<DummyDef>) -> Self {
         let mut var_pool = VarPool::new();
         let mut def_pool = DefPool::new();
+        let mut block_pool = BlockPool::new();
 
         let mut input_vars: Vec<VarIndex> = Vec::new();
         let mut defined_vars: Vec<VarIndex> = Vec::new();
@@ -47,6 +50,7 @@ impl Transform {
             &mut defined_vars,
             &mut var_pool,
             &mut def_pool,
+            &mut block_pool,
         )[0];
 
         let num_src_inputs = input_vars.len();
@@ -59,6 +63,7 @@ impl Transform {
             &mut defined_vars,
             &mut var_pool,
             &mut def_pool,
+            &mut block_pool,
         );
 
         // Sanity checks.
@@ -122,6 +127,7 @@ impl Transform {
             dst,
             var_pool,
             def_pool,
+            block_pool,
             type_env,
         }
     }
@@ -138,6 +144,27 @@ impl Transform {
     }
 }
 
+/// Inserts, if not present, a name in the `symbol_table`. Then returns its index in the variable
+/// pool `var_pool`. If the variable was not present in the symbol table, then add it to the list of
+/// `defined_vars`.
+fn var_index(
+    name: &'static str,
+    symbol_table: &mut SymbolTable,
+    defined_vars: &mut Vec<VarIndex>,
+    var_pool: &mut VarPool,
+) -> VarIndex {
+    match symbol_table.get(name) {
+        Some(&existing_var) => existing_var,
+        None => {
+            // Materialize the variable.
+            let new_var = var_pool.create(name);
+            symbol_table.insert(name, new_var);
+            defined_vars.push(new_var);
+            new_var
+        }
+    }
+}
+
 /// Given a list of symbols defined in a Def, rewrite them to local symbols. Yield the new locals.
 fn rewrite_defined_vars(
     position: PatternPosition,
@@ -149,16 +176,7 @@ fn rewrite_defined_vars(
 ) -> Vec<VarIndex> {
     let mut new_defined_vars = Vec::new();
     for var in &dummy_def.defined_vars {
-        let own_var = match symbol_table.get(var.name) {
-            Some(&existing_var) => existing_var,
-            None => {
-                // Materialize the variable.
-                let new_var = var_pool.create(var.name);
-                symbol_table.insert(var.name, new_var);
-                defined_vars.push(new_var);
-                new_var
-            }
-        };
+        let own_var = var_index(var.name, symbol_table, defined_vars, var_pool);
         var_pool.get_mut(own_var).set_def(position, def_index);
         new_defined_vars.push(own_var);
     }
@@ -197,23 +215,12 @@ fn rewrite_expr(
     for (i, arg) in dummy_args.into_iter().enumerate() {
         match arg {
             DummyExpr::Var(var) => {
-                let own_var = match symbol_table.get(var.name) {
-                    Some(&own_var) => {
-                        let var = var_pool.get(own_var);
-                        assert!(
-                            var.is_input() || var.get_def(position).is_some(),
-                            format!("{:?} used as both input and def", var)
-                        );
-                        own_var
-                    }
-                    None => {
-                        // First time we're using this variable.
-                        let own_var = var_pool.create(var.name);
-                        symbol_table.insert(var.name, own_var);
-                        input_vars.push(own_var);
-                        own_var
-                    }
-                };
+                let own_var = var_index(var.name, symbol_table, input_vars, var_pool);
+                let var = var_pool.get(own_var);
+                assert!(
+                    var.is_input() || var.get_def(position).is_some(),
+                    format!("{:?} used as both input and def", var)
+                );
                 args.push(Expr::Var(own_var));
             }
             DummyExpr::Literal(literal) => {
@@ -223,6 +230,9 @@ fn rewrite_expr(
             DummyExpr::Apply(..) => {
                 panic!("Recursive apply is not allowed.");
             }
+            DummyExpr::Block(_block) => {
+                panic!("Blocks are not valid arguments.");
+            }
         }
     }
 
@@ -237,8 +247,18 @@ fn rewrite_def_list(
     defined_vars: &mut Vec<VarIndex>,
     var_pool: &mut VarPool,
     def_pool: &mut DefPool,
+    block_pool: &mut BlockPool,
 ) -> Vec<DefIndex> {
     let mut new_defs = Vec::new();
+    // Register variable names of new blocks first as a block name can be used to jump forward. Thus
+    // the name has to be registered first to avoid misinterpreting it as an input-var.
+    for dummy_def in dummy_defs.iter() {
+        if let DummyExpr::Block(ref var) = dummy_def.expr {
+            var_index(var.name, symbol_table, defined_vars, var_pool);
+        }
+    }
+
+    // Iterate over the definitions and blocks, to map variables names to inputs or outputs.
     for dummy_def in dummy_defs {
         let def_index = def_pool.next_index();
 
@@ -250,25 +270,40 @@ fn rewrite_def_list(
             defined_vars,
             var_pool,
         );
-        let new_apply = rewrite_expr(position, dummy_def.expr, symbol_table, input_vars, var_pool);
+        if let DummyExpr::Block(var) = dummy_def.expr {
+            let var_index = *symbol_table
+                .get(var.name)
+                .or_else(|| {
+                    panic!(
+                        "Block {} was not registered during the first visit",
+                        var.name
+                    )
+                })
+                .unwrap();
+            var_pool.get_mut(var_index).set_def(position, def_index);
+            block_pool.create_block(var_index, def_index);
+        } else {
+            let new_apply =
+                rewrite_expr(position, dummy_def.expr, symbol_table, input_vars, var_pool);
 
-        assert!(
-            def_pool.next_index() == def_index,
-            "shouldn't have created new defs in the meanwhile"
-        );
-        assert_eq!(
-            new_apply.inst.value_results.len(),
-            new_defined_vars.len(),
-            "number of Var results in instruction is incorrect"
-        );
+            assert!(
+                def_pool.next_index() == def_index,
+                "shouldn't have created new defs in the meanwhile"
+            );
+            assert_eq!(
+                new_apply.inst.value_results.len(),
+                new_defined_vars.len(),
+                "number of Var results in instruction is incorrect"
+            );
 
-        new_defs.push(def_pool.create(new_apply, new_defined_vars));
+            new_defs.push(def_pool.create_inst(new_apply, new_defined_vars));
+        }
     }
     new_defs
 }
 
 /// A group of related transformations.
-pub struct TransformGroup {
+pub(crate) struct TransformGroup {
     pub name: &'static str,
     pub doc: &'static str,
     pub chain_with: Option<TransformGroupIndex>,
@@ -294,10 +329,10 @@ impl TransformGroup {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct TransformGroupIndex(u32);
+pub(crate) struct TransformGroupIndex(u32);
 entity_impl!(TransformGroupIndex);
 
-pub struct TransformGroupBuilder {
+pub(crate) struct TransformGroupBuilder {
     name: &'static str,
     doc: &'static str,
     chain_with: Option<TransformGroupIndex>,
@@ -369,7 +404,7 @@ impl TransformGroupBuilder {
     }
 }
 
-pub struct TransformGroups {
+pub(crate) struct TransformGroups {
     groups: PrimaryMap<TransformGroupIndex, TransformGroup>,
 }
 
diff --git a/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs b/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs
index 4090e4d77d97dae8ff09bae9193106be24ae8940..ce6214efa81c3bb5990c6ede1cdaf75171b74f6a 100644
--- a/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/constant_hash.rs
@@ -1,6 +1,6 @@
 use std::iter;
 
-pub fn simple_hash(s: &str) -> usize {
+pub(crate) fn simple_hash(s: &str) -> usize {
     let mut h: u32 = 5381;
     for c in s.chars() {
         h = (h ^ c as u32).wrapping_add(h.rotate_right(6));
@@ -11,7 +11,7 @@ pub fn simple_hash(s: &str) -> usize {
 /// Compute an open addressed, quadratically probed hash table containing
 /// `items`. The returned table is a list containing the elements of the
 /// iterable `items` and `None` in unused slots.
-pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
+pub(crate) fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
     items: I,
     num_items: usize,
     hash_function: H,
diff --git a/third_party/rust/cranelift-codegen-meta/src/default_map.rs b/third_party/rust/cranelift-codegen-meta/src/default_map.rs
index da6d471439af58092afb708bc8fab61d94c03008..0a2f7fc41a71836c62c504ddd1601499d0b36aa9 100644
--- a/third_party/rust/cranelift-codegen-meta/src/default_map.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/default_map.rs
@@ -1,7 +1,7 @@
 use std::collections::HashMap;
 use std::hash::Hash;
 
-pub trait MapWithDefault<K, V: Default> {
+pub(crate) trait MapWithDefault<K, V: Default> {
     fn get_or_default(&mut self, k: K) -> &mut V;
 }
 
diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs b/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs
index 53929fe8c5a143351e797e316ab5d798a1f0d212..fed145cbd4f3241817c512a2e72f99e1a9531d45 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_binemit.rs
@@ -211,7 +211,7 @@ fn gen_isa(formats: &FormatRegistry, isa_name: &str, recipes: &Recipes, fmt: &mu
     fmt.line("}");
 }
 
-pub fn generate(
+pub(crate) fn generate(
     formats: &FormatRegistry,
     isa_name: &str,
     recipes: &Recipes,
diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs b/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs
index 7d8353dad312d4f586555f9194568a18ef37f737..ed28a83794ba6eb9b8bff6d4f50721dadb888716 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_inst.rs
@@ -97,9 +97,14 @@ fn gen_instruction_data(registry: &FormatRegistry, fmt: &mut Formatter) {
 
 fn gen_arguments_method(registry: &FormatRegistry, fmt: &mut Formatter, is_mut: bool) {
     let (method, mut_, rslice, as_slice) = if is_mut {
-        ("arguments_mut", "mut ", "ref_slice_mut", "as_mut_slice")
+        (
+            "arguments_mut",
+            "mut ",
+            "core::slice::from_mut",
+            "as_mut_slice",
+        )
     } else {
-        ("arguments", "", "ref_slice", "as_slice")
+        ("arguments", "", "core::slice::from_ref", "as_slice")
     };
 
     fmtln!(
diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs b/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs
index da1fb1f58f584a0851e048a8409c25f7f70a8255..bceed3fac68f5dce9579124950291742412b87f5 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_legalizer.rs
@@ -401,14 +401,30 @@ fn gen_transform<'a>(
     // Guard the actual expansion by `predicate`.
     fmt.line("if predicate {");
     fmt.indent(|fmt| {
+        // If we are adding some blocks, we need to recall the original block, such that we can
+        // recompute it.
+        if !transform.block_pool.is_empty() {
+            fmt.line("let orig_ebb = pos.current_ebb().unwrap();");
+        }
+
         // If we're going to delete `inst`, we need to detach its results first so they can be
         // reattached during pattern expansion.
         if !replace_inst {
             fmt.line("pos.func.dfg.clear_results(inst);");
         }
 
+        // Emit new block creation.
+        for block in &transform.block_pool {
+            let var = transform.var_pool.get(block.name);
+            fmtln!(fmt, "let {} = pos.func.dfg.make_ebb();", var.name);
+        }
+
         // Emit the destination pattern.
         for &def_index in &transform.dst {
+            if let Some(block) = transform.block_pool.get(def_index) {
+                let var = transform.var_pool.get(block.name);
+                fmtln!(fmt, "pos.insert_ebb({});", var.name);
+            }
             emit_dst_inst(
                 transform.def_pool.get(def_index),
                 &transform.def_pool,
@@ -417,16 +433,32 @@ fn gen_transform<'a>(
             );
         }
 
+        // Insert a new block after the last instruction, if needed.
+        let def_next_index = transform.def_pool.next_index();
+        if let Some(block) = transform.block_pool.get(def_next_index) {
+            let var = transform.var_pool.get(block.name);
+            fmtln!(fmt, "pos.insert_ebb({});", var.name);
+        }
+
         // Delete the original instruction if we didn't have an opportunity to replace it.
         if !replace_inst {
             fmt.line("let removed = pos.remove_inst();");
             fmt.line("debug_assert_eq!(removed, inst);");
         }
 
-        if transform.def_pool.get(transform.src).apply.inst.is_branch {
-            // A branch might have been legalized into multiple branches, so we need to recompute
-            // the cfg.
-            fmt.line("cfg.recompute_ebb(pos.func, pos.current_ebb().unwrap());");
+        if transform.block_pool.is_empty() {
+            if transform.def_pool.get(transform.src).apply.inst.is_branch {
+                // A branch might have been legalized into multiple branches, so we need to recompute
+                // the cfg.
+                fmt.line("cfg.recompute_ebb(pos.func, pos.current_ebb().unwrap());");
+            }
+        } else {
+            // Update CFG for the new blocks.
+            fmt.line("cfg.recompute_ebb(pos.func, orig_ebb);");
+            for block in &transform.block_pool {
+                let var = transform.var_pool.get(block.name);
+                fmtln!(fmt, "cfg.recompute_ebb(pos.func, {});", var.name);
+            }
         }
 
         fmt.line("return true;");
@@ -577,7 +609,7 @@ fn gen_isa(
 }
 
 /// Generate the legalizer files.
-pub fn generate(
+pub(crate) fn generate(
     isas: &Vec<TargetIsa>,
     format_registry: &FormatRegistry,
     transform_groups: &TransformGroups,
diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs b/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs
index 08edfa9e21960ce4b07c28b0a4ba952d9ec67b6c..8f778f8601073ccf03a1266398c3f1258f999ec5 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_registers.rs
@@ -133,7 +133,7 @@ fn gen_isa(isa: &TargetIsa, fmt: &mut Formatter) {
     fmtln!(fmt, "}");
 }
 
-pub fn generate(isa: &TargetIsa, filename: &str, out_dir: &str) -> Result<(), error::Error> {
+pub(crate) fn generate(isa: &TargetIsa, filename: &str, out_dir: &str) -> Result<(), error::Error> {
     let mut fmt = Formatter::new();
     gen_isa(&isa, &mut fmt);
     fmt.update_file(filename, out_dir)?;
diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs b/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs
index cdd07d78bd64c9dbf7c372e0b641407b5ec92c77..84c81cddc4aa32a93be0f40e779f524486f66938 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_settings.rs
@@ -431,7 +431,7 @@ fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) {
     gen_display(group, fmt);
 }
 
-pub fn generate(
+pub(crate) fn generate(
     settings: &SettingGroup,
     parent_group: ParentGroup,
     filename: &str,
diff --git a/third_party/rust/cranelift-codegen-meta/src/gen_types.rs b/third_party/rust/cranelift-codegen-meta/src/gen_types.rs
index d4b4c60d65533dca8d4686d60147b5a9996a9cfb..6ced212b8d5402fa6e0e034499c08b242968fa44 100644
--- a/third_party/rust/cranelift-codegen-meta/src/gen_types.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/gen_types.rs
@@ -68,7 +68,7 @@ fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> {
 }
 
 /// Generate the types file.
-pub fn generate(filename: &str, out_dir: &str) -> Result<(), error::Error> {
+pub(crate) fn generate(filename: &str, out_dir: &str) -> Result<(), error::Error> {
     let mut fmt = srcgen::Formatter::new();
     emit_types(&mut fmt)?;
     fmt.update_file(filename, out_dir)?;
diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs
index 02a3bc7b61659128cd615d3831943dfb15b7d291..6ddc13b0a3320b3382b32869f4d6d026609928eb 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/encodings.rs
@@ -18,7 +18,7 @@ fn enc(inst: impl Into<InstSpec>, recipe: EncodingRecipeNumber, bits: u16) -> En
     EncodingBuilder::new(inst.into(), recipe, bits)
 }
 
-pub struct PerCpuModeEncodings<'defs> {
+pub(crate) struct PerCpuModeEncodings<'defs> {
     pub inst_pred_reg: InstructionPredicateRegistry,
     pub enc32: Vec<Encoding>,
     pub enc64: Vec<Encoding>,
diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs
index 9bdb751b26c1cc632b32c2e580a17104012bf21c..01f25d9d7f03c1e90ff833cfbfed2231bca87bbc 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/encodings.rs
@@ -1,5 +1,6 @@
 #![allow(non_snake_case)]
 
+use cranelift_codegen_shared::condcodes::IntCC;
 use std::collections::HashMap;
 
 use crate::cdsl::encodings::{Encoding, EncodingBuilder};
@@ -16,9 +17,11 @@ use crate::shared::types::Int::{I16, I32, I64, I8};
 use crate::shared::types::Reference::{R32, R64};
 use crate::shared::Definitions as SharedDefinitions;
 
+use crate::isa::x86::opcodes::*;
+
 use super::recipes::{RecipeGroup, Template};
 
-pub struct PerCpuModeEncodings {
+pub(crate) struct PerCpuModeEncodings {
     pub enc32: Vec<Encoding>,
     pub enc64: Vec<Encoding>,
     pub recipes: Recipes,
@@ -150,6 +153,20 @@ impl PerCpuModeEncodings {
         self.enc64(inst.bind(I64), template.rex().w());
     }
 
+    /// Add encodings for `inst.b32` to X86_32.
+    /// Add encodings for `inst.b32` to X86_64 with and without REX.
+    /// Add encodings for `inst.b64` to X86_64 with a REX.W prefix.
+    fn enc_b32_b64(&mut self, inst: impl Into<InstSpec>, template: Template) {
+        let inst: InstSpec = inst.into();
+        self.enc32(inst.bind(B32), template.nonrex());
+
+        // REX-less encoding must come after REX encoding so we don't use it by default. Otherwise
+        // reg-alloc would never use r8 and up.
+        self.enc64(inst.bind(B32), template.rex());
+        self.enc64(inst.bind(B32), template.nonrex());
+        self.enc64(inst.bind(B64), template.rex().w());
+    }
+
     /// Add encodings for `inst.i32` to X86_32.
     /// Add encodings for `inst.i32` to X86_64 with a REX prefix.
     /// Add encodings for `inst.i64` to X86_64 with a REX.W prefix.
@@ -279,6 +296,12 @@ impl PerCpuModeEncodings {
         }
     }
 
+    /// Add the same encoding/template pairing to both X86_32 and X86_64
+    fn enc_32_64(&mut self, inst: impl Clone + Into<InstSpec>, template: Template) {
+        self.enc32(inst.clone(), template.clone());
+        self.enc64(inst, template);
+    }
+
     /// Add the same encoding/recipe pairing to both X86_32 and X86_64
     fn enc_32_64_rec(
         &mut self,
@@ -290,6 +313,20 @@ impl PerCpuModeEncodings {
         self.enc64_rec(inst, recipe, bits);
     }
 
+    /// Add the same encoding to both X86_32 and X86_64; assumes configuration (e.g. REX, operand binding) has already happened
+    fn enc_32_64_func<T>(
+        &mut self,
+        inst: impl Clone + Into<InstSpec>,
+        template: Template,
+        builder_closure: T,
+    ) where
+        T: FnOnce(EncodingBuilder) -> EncodingBuilder,
+    {
+        let encoding = self.make_encoding(inst.into(), template, builder_closure);
+        self.enc32.push(encoding.clone());
+        self.enc64.push(encoding);
+    }
+
     /// Add the same encoding to both X86_32 and X86_64; assumes configuration (e.g. REX, operand
     /// binding) has already happened.
     fn enc_32_64_maybe_isap(
@@ -539,6 +576,7 @@ pub(crate) fn define(
     let rec_gvaddr4 = r.template("gvaddr4");
     let rec_gvaddr8 = r.template("gvaddr8");
     let rec_icscc = r.template("icscc");
+    let rec_icscc_fpr = r.template("icscc_fpr");
     let rec_icscc_ib = r.template("icscc_ib");
     let rec_icscc_id = r.template("icscc_id");
     let rec_indirect_jmp = r.template("indirect_jmp");
@@ -622,6 +660,7 @@ pub(crate) fn define(
     let rec_urm_noflags = r.template("urm_noflags");
     let rec_urm_noflags_abcd = r.template("urm_noflags_abcd");
     let rec_vconst = r.template("vconst");
+    let rec_vconst_optimized = r.template("vconst_optimized");
 
     // Predicates shorthands.
     let all_ones_funcaddrs_and_not_is_pic =
@@ -644,82 +683,91 @@ pub(crate) fn define(
     e.enc64_rec(get_pinned_reg.bind(I64), rec_get_pinned_reg, 0);
     e.enc_x86_64(
         set_pinned_reg.bind(I64),
-        rec_set_pinned_reg.opcodes(vec![0x89]).rex().w(),
+        rec_set_pinned_reg.opcodes(&MOV_STORE).rex().w(),
     );
 
-    e.enc_i32_i64(iadd, rec_rr.opcodes(vec![0x01]));
-    e.enc_i32_i64(iadd_ifcout, rec_rout.opcodes(vec![0x01]));
-    e.enc_i32_i64(iadd_ifcin, rec_rin.opcodes(vec![0x11]));
-    e.enc_i32_i64(iadd_ifcarry, rec_rio.opcodes(vec![0x11]));
+    e.enc_i32_i64(iadd, rec_rr.opcodes(&ADD));
+    e.enc_i32_i64(iadd_ifcout, rec_rout.opcodes(&ADD));
+    e.enc_i32_i64(iadd_ifcin, rec_rin.opcodes(&ADC));
+    e.enc_i32_i64(iadd_ifcarry, rec_rio.opcodes(&ADC));
 
-    e.enc_i32_i64(isub, rec_rr.opcodes(vec![0x29]));
-    e.enc_i32_i64(isub_ifbout, rec_rout.opcodes(vec![0x29]));
-    e.enc_i32_i64(isub_ifbin, rec_rin.opcodes(vec![0x19]));
-    e.enc_i32_i64(isub_ifborrow, rec_rio.opcodes(vec![0x19]));
+    e.enc_i32_i64(isub, rec_rr.opcodes(&SUB));
+    e.enc_i32_i64(isub_ifbout, rec_rout.opcodes(&SUB));
+    e.enc_i32_i64(isub_ifbin, rec_rin.opcodes(&SBB));
+    e.enc_i32_i64(isub_ifborrow, rec_rio.opcodes(&SBB));
 
-    e.enc_i32_i64(band, rec_rr.opcodes(vec![0x21]));
-    e.enc_i32_i64(bor, rec_rr.opcodes(vec![0x09]));
-    e.enc_i32_i64(bxor, rec_rr.opcodes(vec![0x31]));
+    e.enc_i32_i64(band, rec_rr.opcodes(&AND));
+    e.enc_b32_b64(band, rec_rr.opcodes(&AND));
+    e.enc_i32_i64(bor, rec_rr.opcodes(&OR));
+    e.enc_b32_b64(bor, rec_rr.opcodes(&OR));
+    e.enc_i32_i64(bxor, rec_rr.opcodes(&XOR));
+    e.enc_b32_b64(bxor, rec_rr.opcodes(&XOR));
 
     // x86 has a bitwise not instruction NOT.
-    e.enc_i32_i64(bnot, rec_ur.opcodes(vec![0xf7]).rrr(2));
+    e.enc_i32_i64(bnot, rec_ur.opcodes(&NOT).rrr(2));
+    e.enc_b32_b64(bnot, rec_ur.opcodes(&NOT).rrr(2));
 
     // Also add a `b1` encodings for the logic instructions.
     // TODO: Should this be done with 8-bit instructions? It would improve partial register
     // dependencies.
-    e.enc_both(band.bind(B1), rec_rr.opcodes(vec![0x21]));
-    e.enc_both(bor.bind(B1), rec_rr.opcodes(vec![0x09]));
-    e.enc_both(bxor.bind(B1), rec_rr.opcodes(vec![0x31]));
+    e.enc_both(band.bind(B1), rec_rr.opcodes(&AND));
+    e.enc_both(bor.bind(B1), rec_rr.opcodes(&OR));
+    e.enc_both(bxor.bind(B1), rec_rr.opcodes(&XOR));
 
-    e.enc_i32_i64(imul, rec_rrx.opcodes(vec![0x0f, 0xaf]));
-    e.enc_i32_i64(x86_sdivmodx, rec_div.opcodes(vec![0xf7]).rrr(7));
-    e.enc_i32_i64(x86_udivmodx, rec_div.opcodes(vec![0xf7]).rrr(6));
+    e.enc_i32_i64(imul, rec_rrx.opcodes(&IMUL));
+    e.enc_i32_i64(x86_sdivmodx, rec_div.opcodes(&IDIV).rrr(7));
+    e.enc_i32_i64(x86_udivmodx, rec_div.opcodes(&DIV).rrr(6));
 
-    e.enc_i32_i64(x86_smulx, rec_mulx.opcodes(vec![0xf7]).rrr(5));
-    e.enc_i32_i64(x86_umulx, rec_mulx.opcodes(vec![0xf7]).rrr(4));
+    e.enc_i32_i64(x86_smulx, rec_mulx.opcodes(&IMUL_RDX_RAX).rrr(5));
+    e.enc_i32_i64(x86_umulx, rec_mulx.opcodes(&MUL).rrr(4));
 
-    e.enc_i32_i64(copy, rec_umr.opcodes(vec![0x89]));
-    e.enc_r32_r64_rex_only(copy, rec_umr.opcodes(vec![0x89]));
-    e.enc_both(copy.bind(B1), rec_umr.opcodes(vec![0x89]));
-    e.enc_both(copy.bind(I8), rec_umr.opcodes(vec![0x89]));
-    e.enc_both(copy.bind(I16), rec_umr.opcodes(vec![0x89]));
+    e.enc_i32_i64(copy, rec_umr.opcodes(&MOV_STORE));
+    e.enc_r32_r64_rex_only(copy, rec_umr.opcodes(&MOV_STORE));
+    e.enc_both(copy.bind(B1), rec_umr.opcodes(&MOV_STORE));
+    e.enc_both(copy.bind(I8), rec_umr.opcodes(&MOV_STORE));
+    e.enc_both(copy.bind(I16), rec_umr.opcodes(&MOV_STORE));
 
     // TODO For x86-64, only define REX forms for now, since we can't describe the
     // special regunit immediate operands with the current constraint language.
     for &ty in &[I8, I16, I32] {
-        e.enc32(regmove.bind(ty), rec_rmov.opcodes(vec![0x89]));
-        e.enc64(regmove.bind(ty), rec_rmov.opcodes(vec![0x89]).rex());
-    }
-    e.enc64(regmove.bind(I64), rec_rmov.opcodes(vec![0x89]).rex().w());
-    e.enc_both(regmove.bind(B1), rec_rmov.opcodes(vec![0x89]));
-    e.enc_both(regmove.bind(I8), rec_rmov.opcodes(vec![0x89]));
-    e.enc32(regmove.bind_ref(R32), rec_rmov.opcodes(vec![0x89]));
-    e.enc64(regmove.bind_ref(R32), rec_rmov.opcodes(vec![0x89]).rex());
+        e.enc32(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE));
+        e.enc64(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE).rex());
+    }
+    for &ty in &[B8, B16, B32] {
+        e.enc32(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE));
+        e.enc64(regmove.bind(ty), rec_rmov.opcodes(&MOV_STORE).rex());
+    }
+    e.enc64(regmove.bind(I64), rec_rmov.opcodes(&MOV_STORE).rex().w());
+    e.enc64(regmove.bind(B64), rec_rmov.opcodes(&MOV_STORE).rex().w());
+    e.enc_both(regmove.bind(B1), rec_rmov.opcodes(&MOV_STORE));
+    e.enc_both(regmove.bind(I8), rec_rmov.opcodes(&MOV_STORE));
+    e.enc32(regmove.bind_ref(R32), rec_rmov.opcodes(&MOV_STORE));
+    e.enc64(regmove.bind_ref(R32), rec_rmov.opcodes(&MOV_STORE).rex());
     e.enc64(
         regmove.bind_ref(R64),
-        rec_rmov.opcodes(vec![0x89]).rex().w(),
+        rec_rmov.opcodes(&MOV_STORE).rex().w(),
     );
 
-    e.enc_i32_i64(iadd_imm, rec_r_ib.opcodes(vec![0x83]).rrr(0));
-    e.enc_i32_i64(iadd_imm, rec_r_id.opcodes(vec![0x81]).rrr(0));
+    e.enc_i32_i64(iadd_imm, rec_r_ib.opcodes(&ADD_IMM8_SIGN_EXTEND).rrr(0));
+    e.enc_i32_i64(iadd_imm, rec_r_id.opcodes(&ADD_IMM).rrr(0));
 
-    e.enc_i32_i64(band_imm, rec_r_ib.opcodes(vec![0x83]).rrr(4));
-    e.enc_i32_i64(band_imm, rec_r_id.opcodes(vec![0x81]).rrr(4));
+    e.enc_i32_i64(band_imm, rec_r_ib.opcodes(&AND_IMM8_SIGN_EXTEND).rrr(4));
+    e.enc_i32_i64(band_imm, rec_r_id.opcodes(&AND_IMM).rrr(4));
 
-    e.enc_i32_i64(bor_imm, rec_r_ib.opcodes(vec![0x83]).rrr(1));
-    e.enc_i32_i64(bor_imm, rec_r_id.opcodes(vec![0x81]).rrr(1));
+    e.enc_i32_i64(bor_imm, rec_r_ib.opcodes(&OR_IMM8_SIGN_EXTEND).rrr(1));
+    e.enc_i32_i64(bor_imm, rec_r_id.opcodes(&OR_IMM).rrr(1));
 
-    e.enc_i32_i64(bxor_imm, rec_r_ib.opcodes(vec![0x83]).rrr(6));
-    e.enc_i32_i64(bxor_imm, rec_r_id.opcodes(vec![0x81]).rrr(6));
+    e.enc_i32_i64(bxor_imm, rec_r_ib.opcodes(&XOR_IMM8_SIGN_EXTEND).rrr(6));
+    e.enc_i32_i64(bxor_imm, rec_r_id.opcodes(&XOR_IMM).rrr(6));
 
     // TODO: band_imm.i64 with an unsigned 32-bit immediate can be encoded as band_imm.i32. Can
     // even use the single-byte immediate for 0xffff_ffXX masks.
 
     // Immediate constants.
-    e.enc32(iconst.bind(I32), rec_pu_id.opcodes(vec![0xb8]));
+    e.enc32(iconst.bind(I32), rec_pu_id.opcodes(&MOV_IMM));
 
-    e.enc64(iconst.bind(I32), rec_pu_id.rex().opcodes(vec![0xb8]));
-    e.enc64(iconst.bind(I32), rec_pu_id.opcodes(vec![0xb8]));
+    e.enc64(iconst.bind(I32), rec_pu_id.rex().opcodes(&MOV_IMM));
+    e.enc64(iconst.bind(I32), rec_pu_id.opcodes(&MOV_IMM));
 
     // The 32-bit immediate movl also zero-extends to 64 bits.
     let f_unary_imm = formats.get(formats.by_name("UnaryImm"));
@@ -727,34 +775,32 @@ pub(crate) fn define(
 
     e.enc64_func(
         iconst.bind(I64),
-        rec_pu_id.opcodes(vec![0xb8]).rex(),
+        rec_pu_id.opcodes(&MOV_IMM).rex(),
         |encoding| encoding.inst_predicate(is_unsigned_int32.clone()),
     );
-    e.enc64_func(
-        iconst.bind(I64),
-        rec_pu_id.opcodes(vec![0xb8]),
-        |encoding| encoding.inst_predicate(is_unsigned_int32),
-    );
+    e.enc64_func(iconst.bind(I64), rec_pu_id.opcodes(&MOV_IMM), |encoding| {
+        encoding.inst_predicate(is_unsigned_int32)
+    });
 
     // Sign-extended 32-bit immediate.
     e.enc64(
         iconst.bind(I64),
-        rec_u_id.rex().opcodes(vec![0xc7]).rrr(0).w(),
+        rec_u_id.rex().opcodes(&MOV_IMM_SIGNEXTEND).rrr(0).w(),
     );
 
-    // Finally, the 0xb8 opcode takes an 8-byte immediate with a REX.W prefix.
-    e.enc64(iconst.bind(I64), rec_pu_iq.opcodes(vec![0xb8]).rex().w());
+    // Finally, the MOV_IMM opcode takes an 8-byte immediate with a REX.W prefix.
+    e.enc64(iconst.bind(I64), rec_pu_iq.opcodes(&MOV_IMM).rex().w());
 
     // Bool constants (uses MOV)
     for &ty in &[B1, B8, B16, B32] {
-        e.enc_both(bconst.bind(ty), rec_pu_id_bool.opcodes(vec![0xb8]));
+        e.enc_both(bconst.bind(ty), rec_pu_id_bool.opcodes(&MOV_IMM));
     }
-    e.enc64(bconst.bind(B64), rec_pu_id_bool.opcodes(vec![0xb8]).rex());
+    e.enc64(bconst.bind(B64), rec_pu_id_bool.opcodes(&MOV_IMM).rex());
 
     let is_zero_int = InstructionPredicate::new_is_zero_int(f_unary_imm, "imm");
     e.enc_both_instp(
         iconst.bind(I8),
-        rec_u_id_z.opcodes(vec![0x30]),
+        rec_u_id_z.opcodes(&XORB),
         is_zero_int.clone(),
     );
     // You may expect that i16 encodings would have an 0x66 prefix on the opcode to indicate that
@@ -766,19 +812,15 @@ pub(crate) fn define(
     // an appropriate i16 encoding available.
     e.enc_both_instp(
         iconst.bind(I16),
-        rec_u_id_z.opcodes(vec![0x31]),
+        rec_u_id_z.opcodes(&XOR),
         is_zero_int.clone(),
     );
     e.enc_both_instp(
         iconst.bind(I32),
-        rec_u_id_z.opcodes(vec![0x31]),
+        rec_u_id_z.opcodes(&XOR),
         is_zero_int.clone(),
     );
-    e.enc_x86_64_instp(
-        iconst.bind(I64),
-        rec_u_id_z.opcodes(vec![0x31]),
-        is_zero_int,
-    );
+    e.enc_x86_64_instp(iconst.bind(I64), rec_u_id_z.opcodes(&XOR), is_zero_int);
 
     // Shifts and rotates.
     // Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit
@@ -789,97 +831,49 @@ pub(crate) fn define(
         // to bind any.
         e.enc32(
             inst.bind(I32).bind_any(),
-            rec_rc.opcodes(vec![0xd3]).rrr(rrr),
+            rec_rc.opcodes(&ROTATE_CL).rrr(rrr),
         );
         e.enc64(
             inst.bind(I64).bind_any(),
-            rec_rc.opcodes(vec![0xd3]).rrr(rrr).rex().w(),
+            rec_rc.opcodes(&ROTATE_CL).rrr(rrr).rex().w(),
         );
         e.enc64(
             inst.bind(I32).bind_any(),
-            rec_rc.opcodes(vec![0xd3]).rrr(rrr).rex(),
+            rec_rc.opcodes(&ROTATE_CL).rrr(rrr).rex(),
         );
         e.enc64(
             inst.bind(I32).bind_any(),
-            rec_rc.opcodes(vec![0xd3]).rrr(rrr),
+            rec_rc.opcodes(&ROTATE_CL).rrr(rrr),
         );
     }
 
-    for &(inst, rrr) in &[
-        (rotl_imm, 0),
-        (rotr_imm, 1),
-        (ishl_imm, 4),
-        (ushr_imm, 5),
-        (sshr_imm, 7),
-    ] {
-        e.enc_i32_i64(inst, rec_r_ib.opcodes(vec![0xc1]).rrr(rrr));
-    }
+    e.enc_i32_i64(rotl_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(0));
+    e.enc_i32_i64(rotr_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(1));
+    e.enc_i32_i64(ishl_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(4));
+    e.enc_i32_i64(ushr_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(5));
+    e.enc_i32_i64(sshr_imm, rec_r_ib.opcodes(&ROTATE_IMM8).rrr(7));
 
     // Population count.
-    e.enc32_isap(
-        popcnt.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]),
-        use_popcnt,
-    );
+    e.enc32_isap(popcnt.bind(I32), rec_urm.opcodes(&POPCNT), use_popcnt);
     e.enc64_isap(
         popcnt.bind(I64),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]).rex().w(),
-        use_popcnt,
-    );
-    e.enc64_isap(
-        popcnt.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]).rex(),
-        use_popcnt,
-    );
-    e.enc64_isap(
-        popcnt.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xb8]),
+        rec_urm.opcodes(&POPCNT).rex().w(),
         use_popcnt,
     );
+    e.enc64_isap(popcnt.bind(I32), rec_urm.opcodes(&POPCNT).rex(), use_popcnt);
+    e.enc64_isap(popcnt.bind(I32), rec_urm.opcodes(&POPCNT), use_popcnt);
 
     // Count leading zero bits.
-    e.enc32_isap(
-        clz.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]),
-        use_lzcnt,
-    );
-    e.enc64_isap(
-        clz.bind(I64),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]).rex().w(),
-        use_lzcnt,
-    );
-    e.enc64_isap(
-        clz.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]).rex(),
-        use_lzcnt,
-    );
-    e.enc64_isap(
-        clz.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbd]),
-        use_lzcnt,
-    );
+    e.enc32_isap(clz.bind(I32), rec_urm.opcodes(&LZCNT), use_lzcnt);
+    e.enc64_isap(clz.bind(I64), rec_urm.opcodes(&LZCNT).rex().w(), use_lzcnt);
+    e.enc64_isap(clz.bind(I32), rec_urm.opcodes(&LZCNT).rex(), use_lzcnt);
+    e.enc64_isap(clz.bind(I32), rec_urm.opcodes(&LZCNT), use_lzcnt);
 
     // Count trailing zero bits.
-    e.enc32_isap(
-        ctz.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]),
-        use_bmi1,
-    );
-    e.enc64_isap(
-        ctz.bind(I64),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]).rex().w(),
-        use_bmi1,
-    );
-    e.enc64_isap(
-        ctz.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]).rex(),
-        use_bmi1,
-    );
-    e.enc64_isap(
-        ctz.bind(I32),
-        rec_urm.opcodes(vec![0xf3, 0x0f, 0xbc]),
-        use_bmi1,
-    );
+    e.enc32_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT), use_bmi1);
+    e.enc64_isap(ctz.bind(I64), rec_urm.opcodes(&TZCNT).rex().w(), use_bmi1);
+    e.enc64_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT).rex(), use_bmi1);
+    e.enc64_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT), use_bmi1);
 
     // Loads and stores.
     let f_load_complex = formats.get(formats.by_name("LoadComplex"));
@@ -888,41 +882,41 @@ pub(crate) fn define(
     for recipe in &[rec_ldWithIndex, rec_ldWithIndexDisp8, rec_ldWithIndexDisp32] {
         e.enc_i32_i64_instp(
             load_complex,
-            recipe.opcodes(vec![0x8b]),
+            recipe.opcodes(&MOV_LOAD),
             is_load_complex_length_two.clone(),
         );
         e.enc_x86_64_instp(
             uload32_complex,
-            recipe.opcodes(vec![0x8b]),
+            recipe.opcodes(&MOV_LOAD),
             is_load_complex_length_two.clone(),
         );
 
         e.enc64_instp(
             sload32_complex,
-            recipe.opcodes(vec![0x63]).rex().w(),
+            recipe.opcodes(&MOVSXD).rex().w(),
             is_load_complex_length_two.clone(),
         );
 
         e.enc_i32_i64_instp(
             uload16_complex,
-            recipe.opcodes(vec![0x0f, 0xb7]),
+            recipe.opcodes(&MOVZX_WORD),
             is_load_complex_length_two.clone(),
         );
         e.enc_i32_i64_instp(
             sload16_complex,
-            recipe.opcodes(vec![0x0f, 0xbf]),
+            recipe.opcodes(&MOVSX_WORD),
             is_load_complex_length_two.clone(),
         );
 
         e.enc_i32_i64_instp(
             uload8_complex,
-            recipe.opcodes(vec![0x0f, 0xb6]),
+            recipe.opcodes(&MOVZX_BYTE),
             is_load_complex_length_two.clone(),
         );
 
         e.enc_i32_i64_instp(
             sload8_complex,
-            recipe.opcodes(vec![0x0f, 0xbe]),
+            recipe.opcodes(&MOVSX_BYTE),
             is_load_complex_length_two.clone(),
         );
     }
@@ -933,22 +927,22 @@ pub(crate) fn define(
     for recipe in &[rec_stWithIndex, rec_stWithIndexDisp8, rec_stWithIndexDisp32] {
         e.enc_i32_i64_instp(
             store_complex,
-            recipe.opcodes(vec![0x89]),
+            recipe.opcodes(&MOV_STORE),
             is_store_complex_length_three.clone(),
         );
         e.enc_x86_64_instp(
             istore32_complex,
-            recipe.opcodes(vec![0x89]),
+            recipe.opcodes(&MOV_STORE),
             is_store_complex_length_three.clone(),
         );
         e.enc_both_instp(
             istore16_complex.bind(I32),
-            recipe.opcodes(vec![0x66, 0x89]),
+            recipe.opcodes(&MOV_STORE_16),
             is_store_complex_length_three.clone(),
         );
         e.enc_x86_64_instp(
             istore16_complex.bind(I64),
-            recipe.opcodes(vec![0x66, 0x89]),
+            recipe.opcodes(&MOV_STORE_16),
             is_store_complex_length_three.clone(),
         );
     }
@@ -960,20 +954,20 @@ pub(crate) fn define(
     ] {
         e.enc_both_instp(
             istore8_complex.bind(I32),
-            recipe.opcodes(vec![0x88]),
+            recipe.opcodes(&MOV_BYTE_STORE),
             is_store_complex_length_three.clone(),
         );
         e.enc_x86_64_instp(
             istore8_complex.bind(I64),
-            recipe.opcodes(vec![0x88]),
+            recipe.opcodes(&MOV_BYTE_STORE),
             is_store_complex_length_three.clone(),
         );
     }
 
     for recipe in &[rec_st, rec_stDisp8, rec_stDisp32] {
-        e.enc_i32_i64_ld_st(store, true, recipe.opcodes(vec![0x89]));
-        e.enc_x86_64(istore32.bind(I64).bind_any(), recipe.opcodes(vec![0x89]));
-        e.enc_i32_i64_ld_st(istore16, false, recipe.opcodes(vec![0x66, 0x89]));
+        e.enc_i32_i64_ld_st(store, true, recipe.opcodes(&MOV_STORE));
+        e.enc_x86_64(istore32.bind(I64).bind_any(), recipe.opcodes(&MOV_STORE));
+        e.enc_i32_i64_ld_st(istore16, false, recipe.opcodes(&MOV_STORE_16));
     }
 
     // Byte stores are more complicated because the registers they can address
@@ -981,40 +975,46 @@ pub(crate) fn define(
     // the corresponding st* recipes when a REX prefix is applied.
 
     for recipe in &[rec_st_abcd, rec_stDisp8_abcd, rec_stDisp32_abcd] {
-        e.enc_both(istore8.bind(I32).bind_any(), recipe.opcodes(vec![0x88]));
-        e.enc_x86_64(istore8.bind(I64).bind_any(), recipe.opcodes(vec![0x88]));
+        e.enc_both(
+            istore8.bind(I32).bind_any(),
+            recipe.opcodes(&MOV_BYTE_STORE),
+        );
+        e.enc_x86_64(
+            istore8.bind(I64).bind_any(),
+            recipe.opcodes(&MOV_BYTE_STORE),
+        );
     }
 
-    e.enc_i32_i64(spill, rec_spillSib32.opcodes(vec![0x89]));
-    e.enc_i32_i64(regspill, rec_regspill32.opcodes(vec![0x89]));
-    e.enc_r32_r64_rex_only(spill, rec_spillSib32.opcodes(vec![0x89]));
-    e.enc_r32_r64_rex_only(regspill, rec_regspill32.opcodes(vec![0x89]));
+    e.enc_i32_i64(spill, rec_spillSib32.opcodes(&MOV_STORE));
+    e.enc_i32_i64(regspill, rec_regspill32.opcodes(&MOV_STORE));
+    e.enc_r32_r64_rex_only(spill, rec_spillSib32.opcodes(&MOV_STORE));
+    e.enc_r32_r64_rex_only(regspill, rec_regspill32.opcodes(&MOV_STORE));
 
     // Use a 32-bit write for spilling `b1`, `i8` and `i16` to avoid
     // constraining the permitted registers.
     // See MIN_SPILL_SLOT_SIZE which makes this safe.
 
-    e.enc_both(spill.bind(B1), rec_spillSib32.opcodes(vec![0x89]));
-    e.enc_both(regspill.bind(B1), rec_regspill32.opcodes(vec![0x89]));
+    e.enc_both(spill.bind(B1), rec_spillSib32.opcodes(&MOV_STORE));
+    e.enc_both(regspill.bind(B1), rec_regspill32.opcodes(&MOV_STORE));
     for &ty in &[I8, I16] {
-        e.enc_both(spill.bind(ty), rec_spillSib32.opcodes(vec![0x89]));
-        e.enc_both(regspill.bind(ty), rec_regspill32.opcodes(vec![0x89]));
+        e.enc_both(spill.bind(ty), rec_spillSib32.opcodes(&MOV_STORE));
+        e.enc_both(regspill.bind(ty), rec_regspill32.opcodes(&MOV_STORE));
     }
 
     for recipe in &[rec_ld, rec_ldDisp8, rec_ldDisp32] {
-        e.enc_i32_i64_ld_st(load, true, recipe.opcodes(vec![0x8b]));
-        e.enc_x86_64(uload32.bind(I64), recipe.opcodes(vec![0x8b]));
-        e.enc64(sload32.bind(I64), recipe.opcodes(vec![0x63]).rex().w());
-        e.enc_i32_i64_ld_st(uload16, true, recipe.opcodes(vec![0x0f, 0xb7]));
-        e.enc_i32_i64_ld_st(sload16, true, recipe.opcodes(vec![0x0f, 0xbf]));
-        e.enc_i32_i64_ld_st(uload8, true, recipe.opcodes(vec![0x0f, 0xb6]));
-        e.enc_i32_i64_ld_st(sload8, true, recipe.opcodes(vec![0x0f, 0xbe]));
+        e.enc_i32_i64_ld_st(load, true, recipe.opcodes(&MOV_LOAD));
+        e.enc_x86_64(uload32.bind(I64), recipe.opcodes(&MOV_LOAD));
+        e.enc64(sload32.bind(I64), recipe.opcodes(&MOVSXD).rex().w());
+        e.enc_i32_i64_ld_st(uload16, true, recipe.opcodes(&MOVZX_WORD));
+        e.enc_i32_i64_ld_st(sload16, true, recipe.opcodes(&MOVSX_WORD));
+        e.enc_i32_i64_ld_st(uload8, true, recipe.opcodes(&MOVZX_BYTE));
+        e.enc_i32_i64_ld_st(sload8, true, recipe.opcodes(&MOVSX_BYTE));
     }
 
-    e.enc_i32_i64(fill, rec_fillSib32.opcodes(vec![0x8b]));
-    e.enc_i32_i64(regfill, rec_regfill32.opcodes(vec![0x8b]));
-    e.enc_r32_r64_rex_only(fill, rec_fillSib32.opcodes(vec![0x8b]));
-    e.enc_r32_r64_rex_only(regfill, rec_regfill32.opcodes(vec![0x8b]));
+    e.enc_i32_i64(fill, rec_fillSib32.opcodes(&MOV_LOAD));
+    e.enc_i32_i64(regfill, rec_regfill32.opcodes(&MOV_LOAD));
+    e.enc_r32_r64_rex_only(fill, rec_fillSib32.opcodes(&MOV_LOAD));
+    e.enc_r32_r64_rex_only(regfill, rec_regfill32.opcodes(&MOV_LOAD));
 
     // No-op fills, created by late-stage redundant-fill removal.
     for &ty in &[I64, I32, I16, I8] {
@@ -1030,44 +1030,44 @@ pub(crate) fn define(
 
     // Load 32 bits from `b1`, `i8` and `i16` spill slots. See `spill.b1` above.
 
-    e.enc_both(fill.bind(B1), rec_fillSib32.opcodes(vec![0x8b]));
-    e.enc_both(regfill.bind(B1), rec_regfill32.opcodes(vec![0x8b]));
+    e.enc_both(fill.bind(B1), rec_fillSib32.opcodes(&MOV_LOAD));
+    e.enc_both(regfill.bind(B1), rec_regfill32.opcodes(&MOV_LOAD));
     for &ty in &[I8, I16] {
-        e.enc_both(fill.bind(ty), rec_fillSib32.opcodes(vec![0x8b]));
-        e.enc_both(regfill.bind(ty), rec_regfill32.opcodes(vec![0x8b]));
+        e.enc_both(fill.bind(ty), rec_fillSib32.opcodes(&MOV_LOAD));
+        e.enc_both(regfill.bind(ty), rec_regfill32.opcodes(&MOV_LOAD));
     }
 
     // Push and Pop.
-    e.enc32(x86_push.bind(I32), rec_pushq.opcodes(vec![0x50]));
-    e.enc_x86_64(x86_push.bind(I64), rec_pushq.opcodes(vec![0x50]));
+    e.enc32(x86_push.bind(I32), rec_pushq.opcodes(&PUSH_REG));
+    e.enc_x86_64(x86_push.bind(I64), rec_pushq.opcodes(&PUSH_REG));
 
-    e.enc32(x86_pop.bind(I32), rec_popq.opcodes(vec![0x58]));
-    e.enc_x86_64(x86_pop.bind(I64), rec_popq.opcodes(vec![0x58]));
+    e.enc32(x86_pop.bind(I32), rec_popq.opcodes(&POP_REG));
+    e.enc_x86_64(x86_pop.bind(I64), rec_popq.opcodes(&POP_REG));
 
     // Copy Special
     // For x86-64, only define REX forms for now, since we can't describe the
     // special regunit immediate operands with the current constraint language.
-    e.enc64(copy_special, rec_copysp.opcodes(vec![0x89]).rex().w());
-    e.enc32(copy_special, rec_copysp.opcodes(vec![0x89]));
+    e.enc64(copy_special, rec_copysp.opcodes(&MOV_STORE).rex().w());
+    e.enc32(copy_special, rec_copysp.opcodes(&MOV_STORE));
 
     // Copy to SSA.  These have to be done with special _rex_only encoders, because the standard
     // machinery for deciding whether a REX.{RXB} prefix is needed doesn't take into account
     // the source register, which is specified directly in the instruction.
-    e.enc_i32_i64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(vec![0x89]));
-    e.enc_r32_r64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(vec![0x89]));
-    e.enc_both_rex_only(copy_to_ssa.bind(B1), rec_umr_reg_to_ssa.opcodes(vec![0x89]));
-    e.enc_both_rex_only(copy_to_ssa.bind(I8), rec_umr_reg_to_ssa.opcodes(vec![0x89]));
+    e.enc_i32_i64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(&MOV_STORE));
+    e.enc_r32_r64_rex_only(copy_to_ssa, rec_umr_reg_to_ssa.opcodes(&MOV_STORE));
+    e.enc_both_rex_only(copy_to_ssa.bind(B1), rec_umr_reg_to_ssa.opcodes(&MOV_STORE));
+    e.enc_both_rex_only(copy_to_ssa.bind(I8), rec_umr_reg_to_ssa.opcodes(&MOV_STORE));
     e.enc_both_rex_only(
         copy_to_ssa.bind(I16),
-        rec_umr_reg_to_ssa.opcodes(vec![0x89]),
+        rec_umr_reg_to_ssa.opcodes(&MOV_STORE),
     );
     e.enc_both_rex_only(
         copy_to_ssa.bind(F64),
-        rec_furm_reg_to_ssa.opcodes(vec![0xf2, 0x0f, 0x10]),
+        rec_furm_reg_to_ssa.opcodes(&MOVSD_LOAD),
     );
     e.enc_both_rex_only(
         copy_to_ssa.bind(F32),
-        rec_furm_reg_to_ssa.opcodes(vec![0xf3, 0x0f, 0x10]),
+        rec_furm_reg_to_ssa.opcodes(&MOVSS_LOAD),
     );
 
     // Stack-slot-to-the-same-stack-slot copy, which is guaranteed to turn
@@ -1083,204 +1083,159 @@ pub(crate) fn define(
     }
 
     // Adjust SP down by a dynamic value (or up, with a negative operand).
-    e.enc32(adjust_sp_down.bind(I32), rec_adjustsp.opcodes(vec![0x29]));
+    e.enc32(adjust_sp_down.bind(I32), rec_adjustsp.opcodes(&SUB));
     e.enc64(
         adjust_sp_down.bind(I64),
-        rec_adjustsp.opcodes(vec![0x29]).rex().w(),
+        rec_adjustsp.opcodes(&SUB).rex().w(),
     );
 
     // Adjust SP up by an immediate (or down, with a negative immediate).
-    e.enc32(adjust_sp_up_imm, rec_adjustsp_ib.opcodes(vec![0x83]));
-    e.enc32(adjust_sp_up_imm, rec_adjustsp_id.opcodes(vec![0x81]));
+    e.enc32(adjust_sp_up_imm, rec_adjustsp_ib.opcodes(&CMP_IMM8));
+    e.enc32(adjust_sp_up_imm, rec_adjustsp_id.opcodes(&CMP_IMM));
     e.enc64(
         adjust_sp_up_imm,
-        rec_adjustsp_ib.opcodes(vec![0x83]).rex().w(),
+        rec_adjustsp_ib.opcodes(&CMP_IMM8).rex().w(),
     );
     e.enc64(
         adjust_sp_up_imm,
-        rec_adjustsp_id.opcodes(vec![0x81]).rex().w(),
+        rec_adjustsp_id.opcodes(&CMP_IMM).rex().w(),
     );
 
     // Adjust SP down by an immediate (or up, with a negative immediate).
     e.enc32(
         adjust_sp_down_imm,
-        rec_adjustsp_ib.opcodes(vec![0x83]).rrr(5),
-    );
-    e.enc32(
-        adjust_sp_down_imm,
-        rec_adjustsp_id.opcodes(vec![0x81]).rrr(5),
+        rec_adjustsp_ib.opcodes(&CMP_IMM8).rrr(5),
     );
+    e.enc32(adjust_sp_down_imm, rec_adjustsp_id.opcodes(&CMP_IMM).rrr(5));
     e.enc64(
         adjust_sp_down_imm,
-        rec_adjustsp_ib.opcodes(vec![0x83]).rrr(5).rex().w(),
+        rec_adjustsp_ib.opcodes(&CMP_IMM8).rrr(5).rex().w(),
     );
     e.enc64(
         adjust_sp_down_imm,
-        rec_adjustsp_id.opcodes(vec![0x81]).rrr(5).rex().w(),
+        rec_adjustsp_id.opcodes(&CMP_IMM).rrr(5).rex().w(),
     );
 
     // Float loads and stores.
+    e.enc_both(load.bind(F32).bind_any(), rec_fld.opcodes(&MOVSS_LOAD));
+    e.enc_both(load.bind(F32).bind_any(), rec_fldDisp8.opcodes(&MOVSS_LOAD));
     e.enc_both(
         load.bind(F32).bind_any(),
-        rec_fld.opcodes(vec![0xf3, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        load.bind(F32).bind_any(),
-        rec_fldDisp8.opcodes(vec![0xf3, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        load.bind(F32).bind_any(),
-        rec_fldDisp32.opcodes(vec![0xf3, 0x0f, 0x10]),
+        rec_fldDisp32.opcodes(&MOVSS_LOAD),
     );
 
     e.enc_both(
         load_complex.bind(F32),
-        rec_fldWithIndex.opcodes(vec![0xf3, 0x0f, 0x10]),
+        rec_fldWithIndex.opcodes(&MOVSS_LOAD),
     );
     e.enc_both(
         load_complex.bind(F32),
-        rec_fldWithIndexDisp8.opcodes(vec![0xf3, 0x0f, 0x10]),
+        rec_fldWithIndexDisp8.opcodes(&MOVSS_LOAD),
     );
     e.enc_both(
         load_complex.bind(F32),
-        rec_fldWithIndexDisp32.opcodes(vec![0xf3, 0x0f, 0x10]),
+        rec_fldWithIndexDisp32.opcodes(&MOVSS_LOAD),
     );
 
+    e.enc_both(load.bind(F64).bind_any(), rec_fld.opcodes(&MOVSD_LOAD));
+    e.enc_both(load.bind(F64).bind_any(), rec_fldDisp8.opcodes(&MOVSD_LOAD));
     e.enc_both(
         load.bind(F64).bind_any(),
-        rec_fld.opcodes(vec![0xf2, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        load.bind(F64).bind_any(),
-        rec_fldDisp8.opcodes(vec![0xf2, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        load.bind(F64).bind_any(),
-        rec_fldDisp32.opcodes(vec![0xf2, 0x0f, 0x10]),
+        rec_fldDisp32.opcodes(&MOVSD_LOAD),
     );
 
     e.enc_both(
         load_complex.bind(F64),
-        rec_fldWithIndex.opcodes(vec![0xf2, 0x0f, 0x10]),
+        rec_fldWithIndex.opcodes(&MOVSD_LOAD),
     );
     e.enc_both(
         load_complex.bind(F64),
-        rec_fldWithIndexDisp8.opcodes(vec![0xf2, 0x0f, 0x10]),
+        rec_fldWithIndexDisp8.opcodes(&MOVSD_LOAD),
     );
     e.enc_both(
         load_complex.bind(F64),
-        rec_fldWithIndexDisp32.opcodes(vec![0xf2, 0x0f, 0x10]),
+        rec_fldWithIndexDisp32.opcodes(&MOVSD_LOAD),
     );
 
+    e.enc_both(store.bind(F32).bind_any(), rec_fst.opcodes(&MOVSS_STORE));
     e.enc_both(
         store.bind(F32).bind_any(),
-        rec_fst.opcodes(vec![0xf3, 0x0f, 0x11]),
+        rec_fstDisp8.opcodes(&MOVSS_STORE),
     );
     e.enc_both(
         store.bind(F32).bind_any(),
-        rec_fstDisp8.opcodes(vec![0xf3, 0x0f, 0x11]),
-    );
-    e.enc_both(
-        store.bind(F32).bind_any(),
-        rec_fstDisp32.opcodes(vec![0xf3, 0x0f, 0x11]),
+        rec_fstDisp32.opcodes(&MOVSS_STORE),
     );
 
     e.enc_both(
         store_complex.bind(F32),
-        rec_fstWithIndex.opcodes(vec![0xf3, 0x0f, 0x11]),
+        rec_fstWithIndex.opcodes(&MOVSS_STORE),
     );
     e.enc_both(
         store_complex.bind(F32),
-        rec_fstWithIndexDisp8.opcodes(vec![0xf3, 0x0f, 0x11]),
+        rec_fstWithIndexDisp8.opcodes(&MOVSS_STORE),
     );
     e.enc_both(
         store_complex.bind(F32),
-        rec_fstWithIndexDisp32.opcodes(vec![0xf3, 0x0f, 0x11]),
+        rec_fstWithIndexDisp32.opcodes(&MOVSS_STORE),
     );
 
+    e.enc_both(store.bind(F64).bind_any(), rec_fst.opcodes(&MOVSD_STORE));
     e.enc_both(
         store.bind(F64).bind_any(),
-        rec_fst.opcodes(vec![0xf2, 0x0f, 0x11]),
+        rec_fstDisp8.opcodes(&MOVSD_STORE),
     );
     e.enc_both(
         store.bind(F64).bind_any(),
-        rec_fstDisp8.opcodes(vec![0xf2, 0x0f, 0x11]),
-    );
-    e.enc_both(
-        store.bind(F64).bind_any(),
-        rec_fstDisp32.opcodes(vec![0xf2, 0x0f, 0x11]),
+        rec_fstDisp32.opcodes(&MOVSD_STORE),
     );
 
     e.enc_both(
         store_complex.bind(F64),
-        rec_fstWithIndex.opcodes(vec![0xf2, 0x0f, 0x11]),
+        rec_fstWithIndex.opcodes(&MOVSD_STORE),
     );
     e.enc_both(
         store_complex.bind(F64),
-        rec_fstWithIndexDisp8.opcodes(vec![0xf2, 0x0f, 0x11]),
+        rec_fstWithIndexDisp8.opcodes(&MOVSD_STORE),
     );
     e.enc_both(
         store_complex.bind(F64),
-        rec_fstWithIndexDisp32.opcodes(vec![0xf2, 0x0f, 0x11]),
+        rec_fstWithIndexDisp32.opcodes(&MOVSD_STORE),
     );
 
-    e.enc_both(
-        fill.bind(F32),
-        rec_ffillSib32.opcodes(vec![0xf3, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        regfill.bind(F32),
-        rec_fregfill32.opcodes(vec![0xf3, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        fill.bind(F64),
-        rec_ffillSib32.opcodes(vec![0xf2, 0x0f, 0x10]),
-    );
-    e.enc_both(
-        regfill.bind(F64),
-        rec_fregfill32.opcodes(vec![0xf2, 0x0f, 0x10]),
-    );
+    e.enc_both(fill.bind(F32), rec_ffillSib32.opcodes(&MOVSS_LOAD));
+    e.enc_both(regfill.bind(F32), rec_fregfill32.opcodes(&MOVSS_LOAD));
+    e.enc_both(fill.bind(F64), rec_ffillSib32.opcodes(&MOVSD_LOAD));
+    e.enc_both(regfill.bind(F64), rec_fregfill32.opcodes(&MOVSD_LOAD));
 
-    e.enc_both(
-        spill.bind(F32),
-        rec_fspillSib32.opcodes(vec![0xf3, 0x0f, 0x11]),
-    );
-    e.enc_both(
-        regspill.bind(F32),
-        rec_fregspill32.opcodes(vec![0xf3, 0x0f, 0x11]),
-    );
-    e.enc_both(
-        spill.bind(F64),
-        rec_fspillSib32.opcodes(vec![0xf2, 0x0f, 0x11]),
-    );
-    e.enc_both(
-        regspill.bind(F64),
-        rec_fregspill32.opcodes(vec![0xf2, 0x0f, 0x11]),
-    );
+    e.enc_both(spill.bind(F32), rec_fspillSib32.opcodes(&MOVSS_STORE));
+    e.enc_both(regspill.bind(F32), rec_fregspill32.opcodes(&MOVSS_STORE));
+    e.enc_both(spill.bind(F64), rec_fspillSib32.opcodes(&MOVSD_STORE));
+    e.enc_both(regspill.bind(F64), rec_fregspill32.opcodes(&MOVSD_STORE));
 
     // Function addresses.
 
     // Non-PIC, all-ones funcaddresses.
     e.enc32_isap(
         func_addr.bind(I32),
-        rec_fnaddr4.opcodes(vec![0xb8]),
+        rec_fnaddr4.opcodes(&MOV_IMM),
         not_all_ones_funcaddrs_and_not_is_pic,
     );
     e.enc64_isap(
         func_addr.bind(I64),
-        rec_fnaddr8.opcodes(vec![0xb8]).rex().w(),
+        rec_fnaddr8.opcodes(&MOV_IMM).rex().w(),
         not_all_ones_funcaddrs_and_not_is_pic,
     );
 
     // Non-PIC, all-zeros funcaddresses.
     e.enc32_isap(
         func_addr.bind(I32),
-        rec_allones_fnaddr4.opcodes(vec![0xb8]),
+        rec_allones_fnaddr4.opcodes(&MOV_IMM),
         all_ones_funcaddrs_and_not_is_pic,
     );
     e.enc64_isap(
         func_addr.bind(I64),
-        rec_allones_fnaddr8.opcodes(vec![0xb8]).rex().w(),
+        rec_allones_fnaddr8.opcodes(&MOV_IMM).rex().w(),
         all_ones_funcaddrs_and_not_is_pic,
     );
 
@@ -1289,14 +1244,14 @@ pub(crate) fn define(
     let is_colocated_func = InstructionPredicate::new_is_colocated_func(f_func_addr, "func_ref");
     e.enc64_instp(
         func_addr.bind(I64),
-        rec_pcrel_fnaddr8.opcodes(vec![0x8d]).rex().w(),
+        rec_pcrel_fnaddr8.opcodes(&LEA).rex().w(),
         is_colocated_func,
     );
 
     // 64-bit, non-colocated, PIC.
     e.enc64_isap(
         func_addr.bind(I64),
-        rec_got_fnaddr8.opcodes(vec![0x8b]).rex().w(),
+        rec_got_fnaddr8.opcodes(&MOV_LOAD).rex().w(),
         is_pic,
     );
 
@@ -1305,19 +1260,19 @@ pub(crate) fn define(
     // Non-PIC.
     e.enc32_isap(
         symbol_value.bind(I32),
-        rec_gvaddr4.opcodes(vec![0xb8]),
+        rec_gvaddr4.opcodes(&MOV_IMM),
         not_is_pic,
     );
     e.enc64_isap(
         symbol_value.bind(I64),
-        rec_gvaddr8.opcodes(vec![0xb8]).rex().w(),
+        rec_gvaddr8.opcodes(&MOV_IMM).rex().w(),
         not_is_pic,
     );
 
     // PIC, colocated.
     e.enc64_func(
         symbol_value.bind(I64),
-        rec_pcrel_gvaddr8.opcodes(vec![0x8d]).rex().w(),
+        rec_pcrel_gvaddr8.opcodes(&LEA).rex().w(),
         |encoding| {
             encoding
                 .isa_predicate(is_pic)
@@ -1328,7 +1283,7 @@ pub(crate) fn define(
     // PIC, non-colocated.
     e.enc64_isap(
         symbol_value.bind(I64),
-        rec_got_gvaddr8.opcodes(vec![0x8b]).rex().w(),
+        rec_got_gvaddr8.opcodes(&MOV_LOAD).rex().w(),
         is_pic,
     );
 
@@ -1336,102 +1291,102 @@ pub(crate) fn define(
     //
     // TODO: Add encoding rules for stack_load and stack_store, so that they
     // don't get legalized to stack_addr + load/store.
-    e.enc32(stack_addr.bind(I32), rec_spaddr4_id.opcodes(vec![0x8d]));
-    e.enc64(
-        stack_addr.bind(I64),
-        rec_spaddr8_id.opcodes(vec![0x8d]).rex().w(),
-    );
+    e.enc32(stack_addr.bind(I32), rec_spaddr4_id.opcodes(&LEA));
+    e.enc64(stack_addr.bind(I64), rec_spaddr8_id.opcodes(&LEA).rex().w());
 
     // Call/return
 
     // 32-bit, both PIC and non-PIC.
-    e.enc32(call, rec_call_id.opcodes(vec![0xe8]));
+    e.enc32(call, rec_call_id.opcodes(&CALL_RELATIVE));
 
     // 64-bit, colocated, both PIC and non-PIC. Use the call instruction's pc-relative field.
     let f_call = formats.get(formats.by_name("Call"));
     let is_colocated_func = InstructionPredicate::new_is_colocated_func(f_call, "func_ref");
-    e.enc64_instp(call, rec_call_id.opcodes(vec![0xe8]), is_colocated_func);
+    e.enc64_instp(call, rec_call_id.opcodes(&CALL_RELATIVE), is_colocated_func);
 
     // 64-bit, non-colocated, PIC. There is no 64-bit non-colocated non-PIC version, since non-PIC
     // is currently using the large model, which requires calls be lowered to
     // func_addr+call_indirect.
-    e.enc64_isap(call, rec_call_plt_id.opcodes(vec![0xe8]), is_pic);
+    e.enc64_isap(call, rec_call_plt_id.opcodes(&CALL_RELATIVE), is_pic);
 
     e.enc32(
         call_indirect.bind(I32),
-        rec_call_r.opcodes(vec![0xff]).rrr(2),
+        rec_call_r.opcodes(&JUMP_ABSOLUTE).rrr(2),
     );
     e.enc64(
         call_indirect.bind(I64),
-        rec_call_r.opcodes(vec![0xff]).rrr(2).rex(),
+        rec_call_r.opcodes(&JUMP_ABSOLUTE).rrr(2).rex(),
     );
     e.enc64(
         call_indirect.bind(I64),
-        rec_call_r.opcodes(vec![0xff]).rrr(2),
+        rec_call_r.opcodes(&JUMP_ABSOLUTE).rrr(2),
     );
 
-    e.enc32(return_, rec_ret.opcodes(vec![0xc3]));
-    e.enc64(return_, rec_ret.opcodes(vec![0xc3]));
+    e.enc32(return_, rec_ret.opcodes(&RET_NEAR));
+    e.enc64(return_, rec_ret.opcodes(&RET_NEAR));
 
     // Branches.
-    e.enc32(jump, rec_jmpb.opcodes(vec![0xeb]));
-    e.enc64(jump, rec_jmpb.opcodes(vec![0xeb]));
-    e.enc32(jump, rec_jmpd.opcodes(vec![0xe9]));
-    e.enc64(jump, rec_jmpd.opcodes(vec![0xe9]));
+    e.enc32(jump, rec_jmpb.opcodes(&JUMP_SHORT));
+    e.enc64(jump, rec_jmpb.opcodes(&JUMP_SHORT));
+    e.enc32(jump, rec_jmpd.opcodes(&JUMP_NEAR_RELATIVE));
+    e.enc64(jump, rec_jmpd.opcodes(&JUMP_NEAR_RELATIVE));
 
-    e.enc_both(brif, rec_brib.opcodes(vec![0x70]));
-    e.enc_both(brif, rec_brid.opcodes(vec![0x0f, 0x80]));
+    e.enc_both(brif, rec_brib.opcodes(&JUMP_SHORT_IF_OVERFLOW));
+    e.enc_both(brif, rec_brid.opcodes(&JUMP_NEAR_IF_OVERFLOW));
 
     // Not all float condition codes are legal, see `supported_floatccs`.
-    e.enc_both(brff, rec_brfb.opcodes(vec![0x70]));
-    e.enc_both(brff, rec_brfd.opcodes(vec![0x0f, 0x80]));
+    e.enc_both(brff, rec_brfb.opcodes(&JUMP_SHORT_IF_OVERFLOW));
+    e.enc_both(brff, rec_brfd.opcodes(&JUMP_NEAR_IF_OVERFLOW));
 
     // Note that the tjccd opcode will be prefixed with 0x0f.
-    e.enc_i32_i64(brz, rec_tjccb.opcodes(vec![0x74]));
-    e.enc_i32_i64(brz, rec_tjccd.opcodes(vec![0x84]));
-    e.enc_i32_i64(brnz, rec_tjccb.opcodes(vec![0x75]));
-    e.enc_i32_i64(brnz, rec_tjccd.opcodes(vec![0x85]));
+    e.enc_i32_i64(brz, rec_tjccb.opcodes(&JUMP_SHORT_IF_EQUAL));
+    e.enc_i32_i64(brz, rec_tjccd.opcodes(&TEST_BYTE_REG));
+    e.enc_i32_i64(brnz, rec_tjccb.opcodes(&JUMP_SHORT_IF_NOT_EQUAL));
+    e.enc_i32_i64(brnz, rec_tjccd.opcodes(&TEST_REG));
 
     // Branch on a b1 value in a register only looks at the low 8 bits. See also
     // bint encodings below.
     //
     // Start with the worst-case encoding for X86_32 only. The register allocator
     // can't handle a branch with an ABCD-constrained operand.
-    e.enc32(brz.bind(B1), rec_t8jccd_long.opcodes(vec![0x84]));
-    e.enc32(brnz.bind(B1), rec_t8jccd_long.opcodes(vec![0x85]));
+    e.enc32(brz.bind(B1), rec_t8jccd_long.opcodes(&TEST_BYTE_REG));
+    e.enc32(brnz.bind(B1), rec_t8jccd_long.opcodes(&TEST_REG));
 
-    e.enc_both(brz.bind(B1), rec_t8jccb_abcd.opcodes(vec![0x74]));
-    e.enc_both(brz.bind(B1), rec_t8jccd_abcd.opcodes(vec![0x84]));
-    e.enc_both(brnz.bind(B1), rec_t8jccb_abcd.opcodes(vec![0x75]));
-    e.enc_both(brnz.bind(B1), rec_t8jccd_abcd.opcodes(vec![0x85]));
+    e.enc_both(brz.bind(B1), rec_t8jccb_abcd.opcodes(&JUMP_SHORT_IF_EQUAL));
+    e.enc_both(brz.bind(B1), rec_t8jccd_abcd.opcodes(&TEST_BYTE_REG));
+    e.enc_both(
+        brnz.bind(B1),
+        rec_t8jccb_abcd.opcodes(&JUMP_SHORT_IF_NOT_EQUAL),
+    );
+    e.enc_both(brnz.bind(B1), rec_t8jccd_abcd.opcodes(&TEST_REG));
 
     // Jump tables.
     e.enc64(
         jump_table_entry.bind(I64),
-        rec_jt_entry.opcodes(vec![0x63]).rex().w(),
+        rec_jt_entry.opcodes(&MOVSXD).rex().w(),
     );
-    e.enc32(jump_table_entry.bind(I32), rec_jt_entry.opcodes(vec![0x8b]));
+    e.enc32(jump_table_entry.bind(I32), rec_jt_entry.opcodes(&MOV_LOAD));
 
     e.enc64(
         jump_table_base.bind(I64),
-        rec_jt_base.opcodes(vec![0x8d]).rex().w(),
+        rec_jt_base.opcodes(&LEA).rex().w(),
     );
-    e.enc32(jump_table_base.bind(I32), rec_jt_base.opcodes(vec![0x8d]));
+    e.enc32(jump_table_base.bind(I32), rec_jt_base.opcodes(&LEA));
 
     e.enc_x86_64(
         indirect_jump_table_br.bind(I64),
-        rec_indirect_jmp.opcodes(vec![0xff]).rrr(4),
+        rec_indirect_jmp.opcodes(&JUMP_ABSOLUTE).rrr(4),
     );
     e.enc32(
         indirect_jump_table_br.bind(I32),
-        rec_indirect_jmp.opcodes(vec![0xff]).rrr(4),
+        rec_indirect_jmp.opcodes(&JUMP_ABSOLUTE).rrr(4),
     );
 
     // Trap as ud2
-    e.enc32(trap, rec_trap.opcodes(vec![0x0f, 0x0b]));
-    e.enc64(trap, rec_trap.opcodes(vec![0x0f, 0x0b]));
-    e.enc32(resumable_trap, rec_trap.opcodes(vec![0x0f, 0x0b]));
-    e.enc64(resumable_trap, rec_trap.opcodes(vec![0x0f, 0x0b]));
+    e.enc32(trap, rec_trap.opcodes(&UNDEFINED2));
+    e.enc64(trap, rec_trap.opcodes(&UNDEFINED2));
+    e.enc32(resumable_trap, rec_trap.opcodes(&UNDEFINED2));
+    e.enc64(resumable_trap, rec_trap.opcodes(&UNDEFINED2));
 
     // Debug trap as int3
     e.enc32_rec(debugtrap, rec_debugtrap, 0);
@@ -1443,31 +1398,28 @@ pub(crate) fn define(
     e.enc64_rec(trapff, rec_trapff, 0);
 
     // Comparisons
-    e.enc_i32_i64(icmp, rec_icscc.opcodes(vec![0x39]));
-    e.enc_i32_i64(icmp_imm, rec_icscc_ib.opcodes(vec![0x83]).rrr(7));
-    e.enc_i32_i64(icmp_imm, rec_icscc_id.opcodes(vec![0x81]).rrr(7));
-    e.enc_i32_i64(ifcmp, rec_rcmp.opcodes(vec![0x39]));
-    e.enc_i32_i64(ifcmp_imm, rec_rcmp_ib.opcodes(vec![0x83]).rrr(7));
-    e.enc_i32_i64(ifcmp_imm, rec_rcmp_id.opcodes(vec![0x81]).rrr(7));
+    e.enc_i32_i64(icmp, rec_icscc.opcodes(&CMP_REG));
+    e.enc_i32_i64(icmp_imm, rec_icscc_ib.opcodes(&CMP_IMM8).rrr(7));
+    e.enc_i32_i64(icmp_imm, rec_icscc_id.opcodes(&CMP_IMM).rrr(7));
+    e.enc_i32_i64(ifcmp, rec_rcmp.opcodes(&CMP_REG));
+    e.enc_i32_i64(ifcmp_imm, rec_rcmp_ib.opcodes(&CMP_IMM8).rrr(7));
+    e.enc_i32_i64(ifcmp_imm, rec_rcmp_id.opcodes(&CMP_IMM).rrr(7));
     // TODO: We could special-case ifcmp_imm(x, 0) to TEST(x, x).
 
-    e.enc32(ifcmp_sp.bind(I32), rec_rcmp_sp.opcodes(vec![0x39]));
-    e.enc64(
-        ifcmp_sp.bind(I64),
-        rec_rcmp_sp.opcodes(vec![0x39]).rex().w(),
-    );
+    e.enc32(ifcmp_sp.bind(I32), rec_rcmp_sp.opcodes(&CMP_REG));
+    e.enc64(ifcmp_sp.bind(I64), rec_rcmp_sp.opcodes(&CMP_REG).rex().w());
 
     // Convert flags to bool.
     // This encodes `b1` as an 8-bit low register with the value 0 or 1.
-    e.enc_both(trueif, rec_seti_abcd.opcodes(vec![0x0f, 0x90]));
-    e.enc_both(trueff, rec_setf_abcd.opcodes(vec![0x0f, 0x90]));
+    e.enc_both(trueif, rec_seti_abcd.opcodes(&SET_BYTE_IF_OVERFLOW));
+    e.enc_both(trueff, rec_setf_abcd.opcodes(&SET_BYTE_IF_OVERFLOW));
 
     // Conditional move (a.k.a integer select).
-    e.enc_i32_i64(selectif, rec_cmov.opcodes(vec![0x0f, 0x40]));
+    e.enc_i32_i64(selectif, rec_cmov.opcodes(&CMOV_OVERFLOW));
 
     // Bit scan forwards and reverse
-    e.enc_i32_i64(x86_bsf, rec_bsf_and_bsr.opcodes(vec![0x0f, 0xbc]));
-    e.enc_i32_i64(x86_bsr, rec_bsf_and_bsr.opcodes(vec![0x0f, 0xbd]));
+    e.enc_i32_i64(x86_bsf, rec_bsf_and_bsr.opcodes(&BIT_SCAN_FORWARD));
+    e.enc_i32_i64(x86_bsr, rec_bsf_and_bsr.opcodes(&BIT_SCAN_REVERSE));
 
     // Convert bool to int.
     //
@@ -1477,24 +1429,24 @@ pub(crate) fn define(
     // Encode movzbq as movzbl, because it's equivalent and shorter.
     e.enc32(
         bint.bind(I32).bind(B1),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]),
+        rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE),
     );
 
     e.enc64(
         bint.bind(I64).bind(B1),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(),
+        rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(),
     );
     e.enc64(
         bint.bind(I64).bind(B1),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]),
+        rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE),
     );
     e.enc64(
         bint.bind(I32).bind(B1),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(),
+        rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(),
     );
     e.enc64(
         bint.bind(I32).bind(B1),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]),
+        rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE),
     );
 
     // Numerical conversions.
@@ -1517,103 +1469,103 @@ pub(crate) fn define(
     // movsbl
     e.enc32(
         sextend.bind(I32).bind(I8),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xbe]),
+        rec_urm_noflags_abcd.opcodes(&MOVSX_BYTE),
     );
     e.enc64(
         sextend.bind(I32).bind(I8),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xbe]).rex(),
+        rec_urm_noflags.opcodes(&MOVSX_BYTE).rex(),
     );
     e.enc64(
         sextend.bind(I32).bind(I8),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xbe]),
+        rec_urm_noflags_abcd.opcodes(&MOVSX_BYTE),
     );
 
     // movswl
     e.enc32(
         sextend.bind(I32).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xbf]),
+        rec_urm_noflags.opcodes(&MOVSX_WORD),
     );
     e.enc64(
         sextend.bind(I32).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xbf]).rex(),
+        rec_urm_noflags.opcodes(&MOVSX_WORD).rex(),
     );
     e.enc64(
         sextend.bind(I32).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xbf]),
+        rec_urm_noflags.opcodes(&MOVSX_WORD),
     );
 
     // movsbq
     e.enc64(
         sextend.bind(I64).bind(I8),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xbe]).rex().w(),
+        rec_urm_noflags.opcodes(&MOVSX_BYTE).rex().w(),
     );
 
     // movswq
     e.enc64(
         sextend.bind(I64).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xbf]).rex().w(),
+        rec_urm_noflags.opcodes(&MOVSX_WORD).rex().w(),
     );
 
     // movslq
     e.enc64(
         sextend.bind(I64).bind(I32),
-        rec_urm_noflags.opcodes(vec![0x63]).rex().w(),
+        rec_urm_noflags.opcodes(&MOVSXD).rex().w(),
     );
 
     // movzbl
     e.enc32(
         uextend.bind(I32).bind(I8),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]),
+        rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE),
     );
     e.enc64(
         uextend.bind(I32).bind(I8),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(),
+        rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(),
     );
     e.enc64(
         uextend.bind(I32).bind(I8),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]),
+        rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE),
     );
 
     // movzwl
     e.enc32(
         uextend.bind(I32).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb7]),
+        rec_urm_noflags.opcodes(&MOVZX_WORD),
     );
     e.enc64(
         uextend.bind(I32).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb7]).rex(),
+        rec_urm_noflags.opcodes(&MOVZX_WORD).rex(),
     );
     e.enc64(
         uextend.bind(I32).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb7]),
+        rec_urm_noflags.opcodes(&MOVZX_WORD),
     );
 
     // movzbq, encoded as movzbl because it's equivalent and shorter.
     e.enc64(
         uextend.bind(I64).bind(I8),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb6]).rex(),
+        rec_urm_noflags.opcodes(&MOVZX_BYTE).rex(),
     );
     e.enc64(
         uextend.bind(I64).bind(I8),
-        rec_urm_noflags_abcd.opcodes(vec![0x0f, 0xb6]),
+        rec_urm_noflags_abcd.opcodes(&MOVZX_BYTE),
     );
 
     // movzwq, encoded as movzwl because it's equivalent and shorter
     e.enc64(
         uextend.bind(I64).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb7]).rex(),
+        rec_urm_noflags.opcodes(&MOVZX_WORD).rex(),
     );
     e.enc64(
         uextend.bind(I64).bind(I16),
-        rec_urm_noflags.opcodes(vec![0x0f, 0xb7]),
+        rec_urm_noflags.opcodes(&MOVZX_WORD),
     );
 
     // A 32-bit register copy clears the high 32 bits.
     e.enc64(
         uextend.bind(I64).bind(I32),
-        rec_umr.opcodes(vec![0x89]).rex(),
+        rec_umr.opcodes(&MOV_STORE).rex(),
     );
-    e.enc64(uextend.bind(I64).bind(I32), rec_umr.opcodes(vec![0x89]));
+    e.enc64(uextend.bind(I64).bind(I32), rec_umr.opcodes(&MOV_STORE));
 
     // Floating point
 
@@ -1623,7 +1575,7 @@ pub(crate) fn define(
     let is_zero_32_bit_float = InstructionPredicate::new_is_zero_32bit_float(f_unary_ieee32, "imm");
     e.enc32_instp(
         f32const,
-        rec_f32imm_z.opcodes(vec![0x0f, 0x57]),
+        rec_f32imm_z.opcodes(&XORPS),
         is_zero_32_bit_float.clone(),
     );
 
@@ -1631,148 +1583,133 @@ pub(crate) fn define(
     let is_zero_64_bit_float = InstructionPredicate::new_is_zero_64bit_float(f_unary_ieee64, "imm");
     e.enc32_instp(
         f64const,
-        rec_f64imm_z.opcodes(vec![0x66, 0x0f, 0x57]),
+        rec_f64imm_z.opcodes(&XORPD),
         is_zero_64_bit_float.clone(),
     );
 
-    e.enc_x86_64_instp(
-        f32const,
-        rec_f32imm_z.opcodes(vec![0x0f, 0x57]),
-        is_zero_32_bit_float,
-    );
-    e.enc_x86_64_instp(
-        f64const,
-        rec_f64imm_z.opcodes(vec![0x66, 0x0f, 0x57]),
-        is_zero_64_bit_float,
-    );
+    e.enc_x86_64_instp(f32const, rec_f32imm_z.opcodes(&XORPS), is_zero_32_bit_float);
+    e.enc_x86_64_instp(f64const, rec_f64imm_z.opcodes(&XORPD), is_zero_64_bit_float);
 
     // movd
     e.enc_both(
         bitcast.bind(F32).bind(I32),
-        rec_frurm.opcodes(vec![0x66, 0x0f, 0x6e]),
+        rec_frurm.opcodes(&MOVD_LOAD_XMM),
     );
     e.enc_both(
         bitcast.bind(I32).bind(F32),
-        rec_rfumr.opcodes(vec![0x66, 0x0f, 0x7e]),
+        rec_rfumr.opcodes(&MOVD_STORE_XMM),
     );
 
     // movq
     e.enc64(
         bitcast.bind(F64).bind(I64),
-        rec_frurm.opcodes(vec![0x66, 0x0f, 0x6e]).rex().w(),
+        rec_frurm.opcodes(&MOVD_LOAD_XMM).rex().w(),
     );
     e.enc64(
         bitcast.bind(I64).bind(F64),
-        rec_rfumr.opcodes(vec![0x66, 0x0f, 0x7e]).rex().w(),
+        rec_rfumr.opcodes(&MOVD_STORE_XMM).rex().w(),
     );
 
     // movaps
-    e.enc_both(copy.bind(F32), rec_furm.opcodes(vec![0x0f, 0x28]));
-    e.enc_both(copy.bind(F64), rec_furm.opcodes(vec![0x0f, 0x28]));
+    e.enc_both(copy.bind(F32), rec_furm.opcodes(&MOVAPS_LOAD));
+    e.enc_both(copy.bind(F64), rec_furm.opcodes(&MOVAPS_LOAD));
 
     // TODO For x86-64, only define REX forms for now, since we can't describe the special regunit
     // immediate operands with the current constraint language.
-    e.enc32(regmove.bind(F32), rec_frmov.opcodes(vec![0x0f, 0x28]));
-    e.enc64(regmove.bind(F32), rec_frmov.opcodes(vec![0x0f, 0x28]).rex());
+    e.enc32(regmove.bind(F32), rec_frmov.opcodes(&MOVAPS_LOAD));
+    e.enc64(regmove.bind(F32), rec_frmov.opcodes(&MOVAPS_LOAD).rex());
 
     // TODO For x86-64, only define REX forms for now, since we can't describe the special regunit
     // immediate operands with the current constraint language.
-    e.enc32(regmove.bind(F64), rec_frmov.opcodes(vec![0x0f, 0x28]));
-    e.enc64(regmove.bind(F64), rec_frmov.opcodes(vec![0x0f, 0x28]).rex());
+    e.enc32(regmove.bind(F64), rec_frmov.opcodes(&MOVAPS_LOAD));
+    e.enc64(regmove.bind(F64), rec_frmov.opcodes(&MOVAPS_LOAD).rex());
 
     // cvtsi2ss
-    e.enc_i32_i64(
-        fcvt_from_sint.bind(F32),
-        rec_frurm.opcodes(vec![0xf3, 0x0f, 0x2a]),
-    );
+    e.enc_i32_i64(fcvt_from_sint.bind(F32), rec_frurm.opcodes(&CVTSI2SS));
 
     // cvtsi2sd
-    e.enc_i32_i64(
-        fcvt_from_sint.bind(F64),
-        rec_frurm.opcodes(vec![0xf2, 0x0f, 0x2a]),
-    );
+    e.enc_i32_i64(fcvt_from_sint.bind(F64), rec_frurm.opcodes(&CVTSI2SD));
 
     // cvtss2sd
-    e.enc_both(
-        fpromote.bind(F64).bind(F32),
-        rec_furm.opcodes(vec![0xf3, 0x0f, 0x5a]),
-    );
+    e.enc_both(fpromote.bind(F64).bind(F32), rec_furm.opcodes(&CVTSS2SD));
 
     // cvtsd2ss
-    e.enc_both(
-        fdemote.bind(F32).bind(F64),
-        rec_furm.opcodes(vec![0xf2, 0x0f, 0x5a]),
-    );
+    e.enc_both(fdemote.bind(F32).bind(F64), rec_furm.opcodes(&CVTSD2SS));
 
     // cvttss2si
     e.enc_both(
         x86_cvtt2si.bind(I32).bind(F32),
-        rec_rfurm.opcodes(vec![0xf3, 0x0f, 0x2c]),
+        rec_rfurm.opcodes(&CVTTSS2SI),
     );
     e.enc64(
         x86_cvtt2si.bind(I64).bind(F32),
-        rec_rfurm.opcodes(vec![0xf3, 0x0f, 0x2c]).rex().w(),
+        rec_rfurm.opcodes(&CVTTSS2SI).rex().w(),
     );
 
     // cvttsd2si
     e.enc_both(
         x86_cvtt2si.bind(I32).bind(F64),
-        rec_rfurm.opcodes(vec![0xf2, 0x0f, 0x2c]),
+        rec_rfurm.opcodes(&CVTTSD2SI),
     );
     e.enc64(
         x86_cvtt2si.bind(I64).bind(F64),
-        rec_rfurm.opcodes(vec![0xf2, 0x0f, 0x2c]).rex().w(),
+        rec_rfurm.opcodes(&CVTTSD2SI).rex().w(),
     );
 
     // Exact square roots.
-    e.enc_both(sqrt.bind(F32), rec_furm.opcodes(vec![0xf3, 0x0f, 0x51]));
-    e.enc_both(sqrt.bind(F64), rec_furm.opcodes(vec![0xf2, 0x0f, 0x51]));
+    e.enc_both(sqrt.bind(F32), rec_furm.opcodes(&SQRTSS));
+    e.enc_both(sqrt.bind(F64), rec_furm.opcodes(&SQRTSD));
 
     // Rounding. The recipe looks at the opcode to pick an immediate.
     for inst in &[nearest, floor, ceil, trunc] {
-        e.enc_both_isap(
-            inst.bind(F32),
-            rec_furmi_rnd.opcodes(vec![0x66, 0x0f, 0x3a, 0x0a]),
-            use_sse41,
-        );
-        e.enc_both_isap(
-            inst.bind(F64),
-            rec_furmi_rnd.opcodes(vec![0x66, 0x0f, 0x3a, 0x0b]),
-            use_sse41,
-        );
+        e.enc_both_isap(inst.bind(F32), rec_furmi_rnd.opcodes(&ROUNDSS), use_sse41);
+        e.enc_both_isap(inst.bind(F64), rec_furmi_rnd.opcodes(&ROUNDSD), use_sse41);
     }
 
     // Binary arithmetic ops.
-    for &(inst, opc) in &[
-        (fadd, 0x58),
-        (fsub, 0x5c),
-        (fmul, 0x59),
-        (fdiv, 0x5e),
-        (x86_fmin, 0x5d),
-        (x86_fmax, 0x5f),
-    ] {
-        e.enc_both(inst.bind(F32), rec_fa.opcodes(vec![0xf3, 0x0f, opc]));
-        e.enc_both(inst.bind(F64), rec_fa.opcodes(vec![0xf2, 0x0f, opc]));
-    }
+    e.enc_both(fadd.bind(F32), rec_fa.opcodes(&ADDSS));
+    e.enc_both(fadd.bind(F64), rec_fa.opcodes(&ADDSD));
+
+    e.enc_both(fsub.bind(F32), rec_fa.opcodes(&SUBSS));
+    e.enc_both(fsub.bind(F64), rec_fa.opcodes(&SUBSD));
+
+    e.enc_both(fmul.bind(F32), rec_fa.opcodes(&MULSS));
+    e.enc_both(fmul.bind(F64), rec_fa.opcodes(&MULSD));
+
+    e.enc_both(fdiv.bind(F32), rec_fa.opcodes(&DIVSS));
+    e.enc_both(fdiv.bind(F64), rec_fa.opcodes(&DIVSD));
+
+    e.enc_both(x86_fmin.bind(F32), rec_fa.opcodes(&MINSS));
+    e.enc_both(x86_fmin.bind(F64), rec_fa.opcodes(&MINSD));
+
+    e.enc_both(x86_fmax.bind(F32), rec_fa.opcodes(&MAXSS));
+    e.enc_both(x86_fmax.bind(F64), rec_fa.opcodes(&MAXSD));
 
     // Binary bitwise ops.
-    for &(inst, opc) in &[(band, 0x54), (bor, 0x56), (bxor, 0x57)] {
-        e.enc_both(inst.bind(F32), rec_fa.opcodes(vec![0x0f, opc]));
-        e.enc_both(inst.bind(F64), rec_fa.opcodes(vec![0x0f, opc]));
-    }
+    //
+    // The F64 version is intentionally encoded using the single-precision opcode:
+    // the operation is identical and the encoding is one byte shorter.
+    e.enc_both(band.bind(F32), rec_fa.opcodes(&ANDPS));
+    e.enc_both(band.bind(F64), rec_fa.opcodes(&ANDPS));
+
+    e.enc_both(bor.bind(F32), rec_fa.opcodes(&ORPS));
+    e.enc_both(bor.bind(F64), rec_fa.opcodes(&ORPS));
+
+    e.enc_both(bxor.bind(F32), rec_fa.opcodes(&XORPS));
+    e.enc_both(bxor.bind(F64), rec_fa.opcodes(&XORPS));
 
     // The `andnps(x,y)` instruction computes `~x&y`, while band_not(x,y)` is `x&~y.
-    e.enc_both(band_not.bind(F32), rec_fax.opcodes(vec![0x0f, 0x55]));
-    e.enc_both(band_not.bind(F64), rec_fax.opcodes(vec![0x0f, 0x55]));
+    e.enc_both(band_not.bind(F32), rec_fax.opcodes(&ANDNPS));
+    e.enc_both(band_not.bind(F64), rec_fax.opcodes(&ANDNPS));
 
     // Comparisons.
     //
     // This only covers the condition codes in `supported_floatccs`, the rest are
     // handled by legalization patterns.
-    e.enc_both(fcmp.bind(F32), rec_fcscc.opcodes(vec![0x0f, 0x2e]));
-    e.enc_both(fcmp.bind(F64), rec_fcscc.opcodes(vec![0x66, 0x0f, 0x2e]));
-    e.enc_both(ffcmp.bind(F32), rec_fcmp.opcodes(vec![0x0f, 0x2e]));
-    e.enc_both(ffcmp.bind(F64), rec_fcmp.opcodes(vec![0x66, 0x0f, 0x2e]));
+    e.enc_both(fcmp.bind(F32), rec_fcscc.opcodes(&UCOMISS));
+    e.enc_both(fcmp.bind(F64), rec_fcscc.opcodes(&UCOMISD));
+    e.enc_both(ffcmp.bind(F32), rec_fcmp.opcodes(&UCOMISS));
+    e.enc_both(ffcmp.bind(F64), rec_fcmp.opcodes(&UCOMISD));
 
     // SIMD vector size: eventually multiple vector sizes may be supported but for now only
     // SSE-sized vectors are available.
@@ -1785,9 +1722,9 @@ pub(crate) fn define(
     let allowed_simd_type = |t: &LaneType| t.lane_bits() >= 8 && t.lane_bits() < 128;
 
     // PSHUFB, 8-bit shuffle using two XMM registers.
-    for ty in ValueType::all_lane_types().filter(|t| t.lane_bits() == 8) {
+    for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
         let instruction = x86_pshufb.bind_vector_from_lane(ty, sse_vector_size);
-        let template = rec_fa.nonrex().opcodes(vec![0x66, 0x0f, 0x38, 00]);
+        let template = rec_fa.nonrex().opcodes(&PSHUFB);
         e.enc32_isap(instruction.clone(), template.clone(), use_ssse3_simd);
         e.enc64_isap(instruction, template, use_ssse3_simd);
     }
@@ -1795,22 +1732,20 @@ pub(crate) fn define(
     // PSHUFD, 32-bit shuffle using one XMM register and a u8 immediate.
     for ty in ValueType::all_lane_types().filter(|t| t.lane_bits() == 32) {
         let instruction = x86_pshufd.bind_vector_from_lane(ty, sse_vector_size);
-        let template = rec_r_ib_unsigned_fpr
-            .nonrex()
-            .opcodes(vec![0x66, 0x0f, 0x70]);
+        let template = rec_r_ib_unsigned_fpr.nonrex().opcodes(&PSHUFD);
         e.enc32(instruction.clone(), template.clone());
         e.enc64(instruction, template);
     }
 
     // SIMD scalar_to_vector; this uses MOV to copy the scalar value to an XMM register; according
     // to the Intel manual: "When the destination operand is an XMM register, the source operand is
-    // written to the low doubleword of the register and the regiser is zero-extended to 128 bits."
+    // written to the low doubleword of the register and the register is zero-extended to 128 bits."
     for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
         let instruction = scalar_to_vector.bind_vector_from_lane(ty, sse_vector_size);
         if ty.is_float() {
             e.enc_32_64_rec(instruction, rec_null_fpr, 0);
         } else {
-            let template = rec_frurm.opcodes(vec![0x66, 0x0f, 0x6e]); // MOVD/MOVQ
+            let template = rec_frurm.opcodes(&MOVD_LOAD_XMM);
             if ty.lane_bits() < 64 {
                 // no 32-bit encodings for 64-bit widths
                 e.enc32(instruction.clone(), template.clone());
@@ -1820,17 +1755,17 @@ pub(crate) fn define(
     }
 
     // SIMD insertlane
-    let mut x86_pinsr_mapping: HashMap<u64, (Vec<u8>, Option<SettingPredicateNumber>)> =
+    let mut x86_pinsr_mapping: HashMap<u64, (&'static [u8], Option<SettingPredicateNumber>)> =
         HashMap::new();
-    x86_pinsr_mapping.insert(8, (vec![0x66, 0x0f, 0x3a, 0x20], Some(use_sse41_simd))); // PINSRB
-    x86_pinsr_mapping.insert(16, (vec![0x66, 0x0f, 0xc4], None)); // PINSRW from SSE2
-    x86_pinsr_mapping.insert(32, (vec![0x66, 0x0f, 0x3a, 0x22], Some(use_sse41_simd))); // PINSRD
-    x86_pinsr_mapping.insert(64, (vec![0x66, 0x0f, 0x3a, 0x22], Some(use_sse41_simd))); // PINSRQ, only x86_64
+    x86_pinsr_mapping.insert(8, (&PINSRB, Some(use_sse41_simd)));
+    x86_pinsr_mapping.insert(16, (&PINSRW, None));
+    x86_pinsr_mapping.insert(32, (&PINSR, Some(use_sse41_simd)));
+    x86_pinsr_mapping.insert(64, (&PINSR, Some(use_sse41_simd)));
 
     for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
         if let Some((opcode, isap)) = x86_pinsr_mapping.get(&ty.lane_bits()) {
             let instruction = x86_pinsr.bind_vector_from_lane(ty, sse_vector_size);
-            let template = rec_r_ib_unsigned_r.opcodes(opcode.clone());
+            let template = rec_r_ib_unsigned_r.opcodes(opcode);
             if ty.lane_bits() < 64 {
                 e.enc_32_64_maybe_isap(instruction, template.nonrex(), isap.clone());
             } else {
@@ -1844,36 +1779,36 @@ pub(crate) fn define(
     // For legalizing insertlane with floats, INSERTPS from SSE4.1.
     {
         let instruction = x86_insertps.bind_vector_from_lane(F32, sse_vector_size);
-        let template = rec_fa_ib.nonrex().opcodes(vec![0x66, 0x0f, 0x3a, 0x21]);
+        let template = rec_fa_ib.nonrex().opcodes(&INSERTPS);
         e.enc_32_64_maybe_isap(instruction, template, Some(use_sse41_simd));
     }
 
     // For legalizing insertlane with floats,  MOVSD from SSE2.
     {
         let instruction = x86_movsd.bind_vector_from_lane(F64, sse_vector_size);
-        let template = rec_fa.nonrex().opcodes(vec![0xf2, 0x0f, 0x10]);
+        let template = rec_fa.nonrex().opcodes(&MOVSD_LOAD);
         e.enc_32_64_maybe_isap(instruction, template, None); // from SSE2
     }
 
     // For legalizing insertlane with floats, MOVLHPS from SSE.
     {
         let instruction = x86_movlhps.bind_vector_from_lane(F64, sse_vector_size);
-        let template = rec_fa.nonrex().opcodes(vec![0x0f, 0x16]);
+        let template = rec_fa.nonrex().opcodes(&MOVLHPS);
         e.enc_32_64_maybe_isap(instruction, template, None); // from SSE
     }
 
     // SIMD extractlane
-    let mut x86_pextr_mapping: HashMap<u64, (Vec<u8>, Option<SettingPredicateNumber>)> =
+    let mut x86_pextr_mapping: HashMap<u64, (&'static [u8], Option<SettingPredicateNumber>)> =
         HashMap::new();
-    x86_pextr_mapping.insert(8, (vec![0x66, 0x0f, 0x3a, 0x14], Some(use_sse41_simd))); // PEXTRB
-    x86_pextr_mapping.insert(16, (vec![0x66, 0x0f, 0xc5], None)); // PEXTRW from SSE2, SSE4.1 has a PEXTRW that can move to reg/m16 but the opcode is four bytes
-    x86_pextr_mapping.insert(32, (vec![0x66, 0x0f, 0x3a, 0x16], Some(use_sse41_simd))); // PEXTRD
-    x86_pextr_mapping.insert(64, (vec![0x66, 0x0f, 0x3a, 0x16], Some(use_sse41_simd))); // PEXTRQ, only x86_64
+    x86_pextr_mapping.insert(8, (&PEXTRB, Some(use_sse41_simd)));
+    x86_pextr_mapping.insert(16, (&PEXTRW_SSE2, None));
+    x86_pextr_mapping.insert(32, (&PEXTR, Some(use_sse41_simd)));
+    x86_pextr_mapping.insert(64, (&PEXTR, Some(use_sse41_simd)));
 
     for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
         if let Some((opcode, isap)) = x86_pextr_mapping.get(&ty.lane_bits()) {
             let instruction = x86_pextr.bind_vector_from_lane(ty, sse_vector_size);
-            let template = rec_r_ib_unsigned_gpr.opcodes(opcode.clone());
+            let template = rec_r_ib_unsigned_gpr.opcodes(opcode);
             if ty.lane_bits() < 64 {
                 e.enc_32_64_maybe_isap(instruction, template.nonrex(), isap.clone());
             } else {
@@ -1917,6 +1852,28 @@ pub(crate) fn define(
         }
     }
 
+    // SIMD vconst for special cases (all zeroes, all ones)
+    // this must be encoded prior to the MOVUPS implementation (below) so the compiler sees this
+    // encoding first
+    for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
+        let f_unary_const = formats.get(formats.by_name("UnaryConst"));
+        let instruction = vconst.bind_vector_from_lane(ty, sse_vector_size);
+
+        let is_zero_128bit =
+            InstructionPredicate::new_is_all_zeroes_128bit(f_unary_const, "constant_handle");
+        let template = rec_vconst_optimized.nonrex().opcodes(&PXOR);
+        e.enc_32_64_func(instruction.clone(), template, |builder| {
+            builder.inst_predicate(is_zero_128bit)
+        });
+
+        let is_ones_128bit =
+            InstructionPredicate::new_is_all_ones_128bit(f_unary_const, "constant_handle");
+        let template = rec_vconst_optimized.nonrex().opcodes(&PCMPEQB);
+        e.enc_32_64_func(instruction, template, |builder| {
+            builder.inst_predicate(is_ones_128bit)
+        });
+    }
+
     // SIMD vconst using MOVUPS
     // TODO it would be ideal if eventually this became the more efficient MOVAPS but we would have
     // to guarantee that the constants are aligned when emitted and there is currently no mechanism
@@ -1925,20 +1882,98 @@ pub(crate) fn define(
     // in memory) but some performance measurements are needed.
     for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
         let instruction = vconst.bind_vector_from_lane(ty, sse_vector_size);
-        let template = rec_vconst.nonrex().opcodes(vec![0x0f, 0x10]);
+        let template = rec_vconst.nonrex().opcodes(&MOVUPS_LOAD);
+        e.enc_32_64_maybe_isap(instruction, template, None); // from SSE
+    }
+
+    // SIMD bor using ORPS
+    for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
+        let instruction = bor.bind_vector_from_lane(ty, sse_vector_size);
+        let template = rec_fa.nonrex().opcodes(&ORPS);
         e.enc_32_64_maybe_isap(instruction, template, None); // from SSE
     }
 
+    // SIMD register movement: store, load, spill, fill, regmove. All of these use encodings of
+    // MOVUPS and MOVAPS from SSE (TODO ideally all of these would either use MOVAPS when we have
+    // alignment or type-specific encodings, see https://github.com/CraneStation/cranelift/issues/1039).
+    for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
+        // Store
+        let bound_store = store.bind_vector_from_lane(ty, sse_vector_size).bind_any();
+        e.enc_32_64(bound_store.clone(), rec_fst.opcodes(&MOVUPS_STORE));
+        e.enc_32_64(bound_store.clone(), rec_fstDisp8.opcodes(&MOVUPS_STORE));
+        e.enc_32_64(bound_store, rec_fstDisp32.opcodes(&MOVUPS_STORE));
+
+        // Load
+        let bound_load = load.bind_vector_from_lane(ty, sse_vector_size).bind_any();
+        e.enc_32_64(bound_load.clone(), rec_fld.opcodes(&MOVUPS_LOAD));
+        e.enc_32_64(bound_load.clone(), rec_fldDisp8.opcodes(&MOVUPS_LOAD));
+        e.enc_32_64(bound_load, rec_fldDisp32.opcodes(&MOVUPS_LOAD));
+
+        // Spill
+        let bound_spill = spill.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64(bound_spill, rec_fspillSib32.opcodes(&MOVUPS_STORE));
+        let bound_regspill = regspill.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64(bound_regspill, rec_fregspill32.opcodes(&MOVUPS_STORE));
+
+        // Fill
+        let bound_fill = fill.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64(bound_fill, rec_ffillSib32.opcodes(&MOVUPS_LOAD));
+        let bound_regfill = regfill.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64(bound_regfill, rec_fregfill32.opcodes(&MOVUPS_LOAD));
+        let bound_fill_nop = fill_nop.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64_rec(bound_fill_nop, rec_ffillnull, 0);
+
+        // Regmove
+        let bound_regmove = regmove.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64(bound_regmove, rec_frmov.opcodes(&MOVAPS_LOAD));
+
+        // Copy
+        let bound_copy = copy.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64(bound_copy, rec_furm.opcodes(&MOVAPS_LOAD));
+        let bound_copy_nop = copy_nop.bind_vector_from_lane(ty, sse_vector_size);
+        e.enc_32_64_rec(bound_copy_nop, rec_stacknull, 0);
+    }
+
+    // SIMD integer addition
+    for (ty, opcodes) in &[(I8, &PADDB), (I16, &PADDW), (I32, &PADDD), (I64, &PADDQ)] {
+        let iadd = iadd.bind_vector_from_lane(ty.clone(), sse_vector_size);
+        e.enc_32_64(iadd, rec_fa.opcodes(*opcodes));
+    }
+
+    // SIMD icmp using PCMPEQ*
+    let mut pcmpeq_mapping: HashMap<u64, (&[u8], Option<SettingPredicateNumber>)> = HashMap::new();
+    pcmpeq_mapping.insert(8, (&PCMPEQB, None));
+    pcmpeq_mapping.insert(16, (&PCMPEQW, None));
+    pcmpeq_mapping.insert(32, (&PCMPEQD, None));
+    pcmpeq_mapping.insert(64, (&PCMPEQQ, Some(use_sse41_simd)));
+    for ty in ValueType::all_lane_types().filter(|t| t.is_int() && allowed_simd_type(t)) {
+        if let Some((opcodes, isa_predicate)) = pcmpeq_mapping.get(&ty.lane_bits()) {
+            let instruction = icmp.bind_vector_from_lane(ty, sse_vector_size);
+            let f_int_compare = formats.get(formats.by_name("IntCompare"));
+            let has_eq_condition_code =
+                InstructionPredicate::new_has_condition_code(f_int_compare, IntCC::Equal, "cond");
+            let template = rec_icscc_fpr.nonrex().opcodes(*opcodes);
+            e.enc_32_64_func(instruction, template, |builder| {
+                let builder = builder.inst_predicate(has_eq_condition_code);
+                if let Some(p) = isa_predicate {
+                    builder.isa_predicate(*p)
+                } else {
+                    builder
+                }
+            });
+        }
+    }
+
     // Reference type instructions
 
     // Null references implemented as iconst 0.
-    e.enc32(null.bind_ref(R32), rec_pu_id_ref.opcodes(vec![0xb8]));
+    e.enc32(null.bind_ref(R32), rec_pu_id_ref.opcodes(&MOV_IMM));
 
-    e.enc64(null.bind_ref(R64), rec_pu_id_ref.rex().opcodes(vec![0xb8]));
-    e.enc64(null.bind_ref(R64), rec_pu_id_ref.opcodes(vec![0xb8]));
+    e.enc64(null.bind_ref(R64), rec_pu_id_ref.rex().opcodes(&MOV_IMM));
+    e.enc64(null.bind_ref(R64), rec_pu_id_ref.opcodes(&MOV_IMM));
 
     // is_null, implemented by testing whether the value is 0.
-    e.enc_r32_r64_rex_only(is_null, rec_is_zero.opcodes(vec![0x85]));
+    e.enc_r32_r64_rex_only(is_null, rec_is_zero.opcodes(&TEST_REG));
 
     // safepoint instruction calls sink, no actual encoding.
     e.enc32_rec(safepoint, rec_safepoint, 0);
diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs
index dfd7f84334b78ebef3ef492f2be9909c2cd8d181..57057ce6bb4791b4014e6965738974c63323743b 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/legalize.rs
@@ -45,6 +45,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
     let selectif = insts.by_name("selectif");
     let smulhi = insts.by_name("smulhi");
     let splat = insts.by_name("splat");
+    let shuffle = insts.by_name("shuffle");
     let srem = insts.by_name("srem");
     let udiv = insts.by_name("udiv");
     let umulhi = insts.by_name("umulhi");
@@ -328,6 +329,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
             def!(y = splat_any8x16(x)),
             vec![
                 def!(a = scalar_to_vector(x)), // move into the lowest 8 bits of an XMM register
+                // TODO replace the following two instructions with `vconst(0)` when this is possible; see https://github.com/CraneStation/cranelift/issues/1052
                 def!(b = f64const(ieee64_zero)), // zero out a different XMM register; the shuffle mask for moving the lowest byte to all other byte lanes is 0x0
                 def!(c = bitcast_f64_to_any8x16(b)), // no instruction emitted; informs the SSA that the 0 in b can be used as a vector of this type
                 def!(y = x86_pshufb(a, c)), // PSHUFB takes two XMM operands, one of which is a shuffle mask (i.e. b)
@@ -380,6 +382,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
         );
     }
 
+    narrow.custom_legalize(shuffle, "convert_shuffle");
     narrow.custom_legalize(extractlane, "convert_extractlane");
     narrow.custom_legalize(insertlane, "convert_insertlane");
 
diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
index 6ced50939654a7dbe2579af41e6727052dc0a10a..e18c54ad640279b90d82e0655efc5d14c24d9aef 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
@@ -9,6 +9,7 @@ use crate::shared::Definitions as SharedDefinitions;
 mod encodings;
 mod instructions;
 mod legalize;
+mod opcodes;
 mod recipes;
 mod registers;
 mod settings;
diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/opcodes.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/opcodes.rs
new file mode 100644
index 0000000000000000000000000000000000000000..12b60e532b39732cebf17f5e09808406e13a03b1
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/opcodes.rs
@@ -0,0 +1,377 @@
+//! Static, named definitions of instruction opcodes.
+
+/// Empty opcode for use as a default.
+pub static EMPTY: [u8; 0] = [];
+
+/// Add with carry flag r{16,32,64} to r/m of the same size.
+pub static ADC: [u8; 1] = [0x11];
+
+/// Add r{16,32,64} to r/m of the same size.
+pub static ADD: [u8; 1] = [0x01];
+
+/// Add imm{16,32} to r/m{16,32,64}, possibly sign-extended.
+pub static ADD_IMM: [u8; 1] = [0x81];
+
+/// Add sign-extended imm8 to r/m{16,32,64}.
+pub static ADD_IMM8_SIGN_EXTEND: [u8; 1] = [0x83];
+
+/// Add the low double-precision floating-point value from xmm2/mem to xmm1
+/// and store the result in xmm1.
+pub static ADDSD: [u8; 3] = [0xf2, 0x0f, 0x58];
+
+/// Add the low single-precision floating-point value from xmm2/mem to xmm1
+/// and store the result in xmm1.
+pub static ADDSS: [u8; 3] = [0xf3, 0x0f, 0x58];
+
+/// r/m{16,32,64} AND register of the same size (Intel docs have a typo).
+pub static AND: [u8; 1] = [0x21];
+
+/// imm{16,32} AND r/m{16,32,64}, possibly sign-extended.
+pub static AND_IMM: [u8; 1] = [0x81];
+
+/// r/m{16,32,64} AND sign-extended imm8.
+pub static AND_IMM8_SIGN_EXTEND: [u8; 1] = [0x83];
+
+/// Return the bitwise logical AND NOT of packed single-precision floating-point
+/// values in xmm1 and xmm2/mem.
+pub static ANDNPS: [u8; 2] = [0x0f, 0x55];
+
+/// Return the bitwise logical AND of packed single-precision floating-point values
+/// in xmm1 and xmm2/mem.
+pub static ANDPS: [u8; 2] = [0x0f, 0x54];
+
+/// Bit scan forward (stores index of first encountered 1 from the front).
+pub static BIT_SCAN_FORWARD: [u8; 2] = [0x0f, 0xbc];
+
+/// Bit scan reverse (stores index of first encountered 1 from the back).
+pub static BIT_SCAN_REVERSE: [u8; 2] = [0x0f, 0xbd];
+
+/// Call near, relative, displacement relative to next instruction (sign-extended).
+pub static CALL_RELATIVE: [u8; 1] = [0xe8];
+
+/// Move r/m{16,32,64} if overflow (OF=1).
+pub static CMOV_OVERFLOW: [u8; 2] = [0x0f, 0x40];
+
+/// Compare imm{16,32} with r/m{16,32,64} (sign-extended if 64).
+pub static CMP_IMM: [u8; 1] = [0x81];
+
+/// Compare imm8 with r/m{16,32,64}.
+pub static CMP_IMM8: [u8; 1] = [0x83];
+
+/// Compare r{16,32,64} with r/m of the same size.
+pub static CMP_REG: [u8; 1] = [0x39];
+
+/// Convert scalar double-precision floating-point value to scalar single-precision
+/// floating-point value.
+pub static CVTSD2SS: [u8; 3] = [0xf2, 0x0f, 0x5a];
+
+/// Convert doubleword integer to scalar double-precision floating-point value.
+pub static CVTSI2SD: [u8; 3] = [0xf2, 0x0f, 0x2a];
+
+/// Convert doubleword integer to scalar single-precision floating-point value.
+pub static CVTSI2SS: [u8; 3] = [0xf3, 0x0f, 0x2a];
+
+/// Convert scalar single-precision floating-point value to scalar double-precision
+/// float-point value.
+pub static CVTSS2SD: [u8; 3] = [0xf3, 0x0f, 0x5a];
+
+/// Convert with truncation scalar double-precision floating-point value to signed
+/// integer.
+pub static CVTTSD2SI: [u8; 3] = [0xf2, 0x0f, 0x2c];
+
+/// Convert with truncation scalar single-precision floating-point value to integer.
+pub static CVTTSS2SI: [u8; 3] = [0xf3, 0x0f, 0x2c];
+
+/// Unsigned divide for {16,32,64}-bit.
+pub static DIV: [u8; 1] = [0xf7];
+
+/// Divide low double-precision floating-point value in xmm1 by low double-precision
+/// floating-point value in xmm2/m64.
+pub static DIVSD: [u8; 3] = [0xf2, 0x0f, 0x5e];
+
+/// Divide low single-precision floating-point value in xmm1 by low single-precision
+/// floating-point value in xmm2/m32.
+pub static DIVSS: [u8; 3] = [0xf3, 0x0f, 0x5e];
+
+/// Signed divide for {16,32,64}-bit.
+pub static IDIV: [u8; 1] = [0xf7];
+
+/// Signed multiply for {16,32,64}-bit, generic registers.
+pub static IMUL: [u8; 2] = [0x0f, 0xaf];
+
+/// Signed multiply for {16,32,64}-bit, storing into RDX:RAX.
+pub static IMUL_RDX_RAX: [u8; 1] = [0xf7];
+
+/// Insert scalar single-precision floating-point value.
+pub static INSERTPS: [u8; 4] = [0x66, 0x0f, 0x3a, 0x21];
+
+/// Either:
+///  1. Jump near, absolute indirect, RIP = 64-bit offset from register or memory.
+///  2. Jump far, absolute indirect, address given in m16:64.
+pub static JUMP_ABSOLUTE: [u8; 1] = [0xff];
+
+/// Jump near, relative, RIP = RIP + 32-bit displacement sign extended to 64 bits.
+pub static JUMP_NEAR_RELATIVE: [u8; 1] = [0xe9];
+
+/// Jump near (rel32) if overflow (OF=1).
+pub static JUMP_NEAR_IF_OVERFLOW: [u8; 2] = [0x0f, 0x80];
+
+/// Jump short, relative, RIP = RIP + 8-bit displacement sign extended to 64 bits.
+pub static JUMP_SHORT: [u8; 1] = [0xeb];
+
+/// Jump short (rel8) if equal (ZF=1).
+pub static JUMP_SHORT_IF_EQUAL: [u8; 1] = [0x74];
+
+/// Jump short (rel8) if not equal (ZF=0).
+pub static JUMP_SHORT_IF_NOT_EQUAL: [u8; 1] = [0x75];
+
+/// Jump short (rel8) if overflow (OF=1).
+pub static JUMP_SHORT_IF_OVERFLOW: [u8; 1] = [0x70];
+
+/// Store effective address for m in register r{16,32,64}.
+pub static LEA: [u8; 1] = [0x8d];
+
+/// Count the number of leading zero bits.
+pub static LZCNT: [u8; 3] = [0xf3, 0x0f, 0xbd];
+
+/// Return the maximum scalar double-precision floating-point value between
+/// xmm2/m64 and xmm1.
+pub static MAXSD: [u8; 3] = [0xf2, 0x0f, 0x5f];
+
+/// Return the maximum scalar single-precision floating-point value between
+/// xmm2/m32 and xmm1.
+pub static MAXSS: [u8; 3] = [0xf3, 0x0f, 0x5f];
+
+/// Return the minimum scalar double-precision floating-point value between
+/// xmm2/m64 and xmm1.
+pub static MINSD: [u8; 3] = [0xf2, 0x0f, 0x5d];
+
+/// Return the minimum scalar single-precision floating-point value between
+/// xmm2/m32 and xmm1.
+pub static MINSS: [u8; 3] = [0xf3, 0x0f, 0x5d];
+
+/// Move r8 to r/m8.
+pub static MOV_BYTE_STORE: [u8; 1] = [0x88];
+
+/// Move imm{16,32,64} to same-sized register.
+pub static MOV_IMM: [u8; 1] = [0xb8];
+
+/// Move imm{16,32} to r{16,32,64}, sign-extended if 64-bit target.
+pub static MOV_IMM_SIGNEXTEND: [u8; 1] = [0xc7];
+
+/// Move {r/m16, r/m32, r/m64} to same-sized register.
+pub static MOV_LOAD: [u8; 1] = [0x8b];
+
+/// Move r16 to r/m16.
+pub static MOV_STORE_16: [u8; 2] = [0x66, 0x89];
+
+/// Move {r16, r32, r64} to same-sized register or memory.
+pub static MOV_STORE: [u8; 1] = [0x89];
+
+/// Move aligned packed single-precision floating-point values from x/m to xmm (SSE).
+pub static MOVAPS_LOAD: [u8; 2] = [0x0f, 0x28];
+
+/// Move doubleword from r/m32 to xmm (SSE2). Quadword with REX prefix.
+pub static MOVD_LOAD_XMM: [u8; 3] = [0x66, 0x0f, 0x6e];
+
+/// Move doubleword from xmm to r/m32 (SSE2). Quadword with REX prefix.
+pub static MOVD_STORE_XMM: [u8; 3] = [0x66, 0x0f, 0x7e];
+
+/// Move packed single-precision floating-point values low to high (SSE).
+pub static MOVLHPS: [u8; 2] = [0x0f, 0x16];
+
+/// Move scalar double-precision floating-point value (from reg/mem to reg).
+pub static MOVSD_LOAD: [u8; 3] = [0xf2, 0x0f, 0x10];
+
+/// Move scalar double-precision floating-point value (from reg to reg/mem).
+pub static MOVSD_STORE: [u8; 3] = [0xf2, 0x0f, 0x11];
+
+/// Move scalar single-precision floating-point value (from reg to reg/mem).
+pub static MOVSS_STORE: [u8; 3] = [0xf3, 0x0f, 0x11];
+
+/// Move scalar single-precision floating-point-value (from reg/mem to reg).
+pub static MOVSS_LOAD: [u8; 3] = [0xf3, 0x0f, 0x10];
+
+/// Move byte to register with sign-extension.
+pub static MOVSX_BYTE: [u8; 2] = [0x0f, 0xbe];
+
+/// Move word to register with sign-extension.
+pub static MOVSX_WORD: [u8; 2] = [0x0f, 0xbf];
+
+/// Move doubleword to register with sign-extension.
+pub static MOVSXD: [u8; 1] = [0x63];
+
+/// Move unaligned packed single-precision floating-point from x/m to xmm (SSE).
+pub static MOVUPS_LOAD: [u8; 2] = [0x0f, 0x10];
+
+/// Move unaligned packed single-precision floating-point value from xmm to x/m (SSE).
+pub static MOVUPS_STORE: [u8; 2] = [0x0f, 0x11];
+
+/// Move byte to register with zero-extension.
+pub static MOVZX_BYTE: [u8; 2] = [0x0f, 0xb6];
+
+/// Move word to register with zero-extension.
+pub static MOVZX_WORD: [u8; 2] = [0x0f, 0xb7];
+
+/// Unsigned multiply for {16,32,64}-bit.
+pub static MUL: [u8; 1] = [0xf7];
+
+/// Multiply the low double-precision floating-point value in xmm2/m64 by the
+/// low double-precision floating-point value in xmm1.
+pub static MULSD: [u8; 3] = [0xf2, 0x0f, 0x59];
+
+/// Multiply the low single-precision floating-point value in xmm2/m32 by the
+/// low single-precision floating-point value in xmm1.
+pub static MULSS: [u8; 3] = [0xf3, 0x0f, 0x59];
+
+/// Reverse each bit of r/m{16,32,64}.
+pub static NOT: [u8; 1] = [0xf7];
+
+/// r{16,32,64} OR register of same size.
+pub static OR: [u8; 1] = [0x09];
+
+/// imm{16,32} OR r/m{16,32,64}, possibly sign-extended.
+pub static OR_IMM: [u8; 1] = [0x81];
+
+/// r/m{16,32,64} OR sign-extended imm8.
+pub static OR_IMM8_SIGN_EXTEND: [u8; 1] = [0x83];
+
+/// Return the bitwise logical OR of packed single-precision values in xmm and x/m (SSE).
+pub static ORPS: [u8; 2] = [0x0f, 0x56];
+
+/// Add packed byte integers from xmm2/m128 and xmm1 (SSE2).
+pub static PADDB: [u8; 3] = [0x66, 0x0f, 0xfc];
+
+/// Add packed doubleword integers from xmm2/m128 and xmm1 (SSE2).
+pub static PADDD: [u8; 3] = [0x66, 0x0f, 0xfe];
+
+/// Add packed quadword integers from xmm2/m128 and xmm1 (SSE2).
+pub static PADDQ: [u8; 3] = [0x66, 0x0f, 0xd4];
+
+/// Add packed word integers from xmm2/m128 and xmm1 (SSE2).
+pub static PADDW: [u8; 3] = [0x66, 0x0f, 0xfd];
+
+/// Compare packed data for equal (SSE2).
+pub static PCMPEQB: [u8; 3] = [0x66, 0x0f, 0x74];
+
+/// Compare packed data for equal (SSE2).
+pub static PCMPEQD: [u8; 3] = [0x66, 0x0f, 0x76];
+
+/// Compare packed data for equal (SSE4.1).
+pub static PCMPEQQ: [u8; 4] = [0x66, 0x0f, 0x38, 0x29];
+
+/// Compare packed data for equal (SSE2).
+pub static PCMPEQW: [u8; 3] = [0x66, 0x0f, 0x75];
+
+/// Extract doubleword or quadword, depending on REX.W (SSE4.1).
+pub static PEXTR: [u8; 4] = [0x66, 0x0f, 0x3a, 0x16];
+
+/// Extract byte (SSE4.1).
+pub static PEXTRB: [u8; 4] = [0x66, 0x0f, 0x3a, 0x14];
+
+/// Extract word (SSE2). There is a 4-byte SSE4.1 variant that can also move to m/16.
+pub static PEXTRW_SSE2: [u8; 3] = [0x66, 0x0f, 0xc5];
+
+/// Insert doubleword or quadword, depending on REX.W (SSE4.1).
+pub static PINSR: [u8; 4] = [0x66, 0x0f, 0x3a, 0x22];
+
+/// Insert byte (SSE4.1).
+pub static PINSRB: [u8; 4] = [0x66, 0x0f, 0x3a, 0x20];
+
+/// Insert word (SSE2).
+pub static PINSRW: [u8; 3] = [0x66, 0x0f, 0xc4];
+
+/// Pop top of stack into r{16,32,64}; increment stack pointer.
+pub static POP_REG: [u8; 1] = [0x58];
+
+/// Returns the count of number of bits set to 1.
+pub static POPCNT: [u8; 3] = [0xf3, 0x0f, 0xb8];
+
+/// Shuffle bytes in xmm1 according to contents of xmm2/m128 (SSE3).
+pub static PSHUFB: [u8; 4] = [0x66, 0x0f, 0x38, 0x00];
+
+/// Shuffle the doublewords in xmm2/m128 based on the encoding in imm8 and
+/// store the result in xmm1 (SSE2).
+pub static PSHUFD: [u8; 3] = [0x66, 0x0f, 0x70];
+
+/// Push r{16,32,64}.
+pub static PUSH_REG: [u8; 1] = [0x50];
+
+/// Logical exclusive OR (SSE2).
+pub static PXOR: [u8; 3] = [0x66, 0x0f, 0xef];
+
+/// Near return to calling procedure.
+pub static RET_NEAR: [u8; 1] = [0xc3];
+
+/// General rotation opcode. Kind of rotation depends on encoding.
+pub static ROTATE_CL: [u8; 1] = [0xd3];
+
+/// General rotation opcode. Kind of rotation depends on encoding.
+pub static ROTATE_IMM8: [u8; 1] = [0xc1];
+
+/// Round scalar doubl-precision floating-point values.
+pub static ROUNDSD: [u8; 4] = [0x66, 0x0f, 0x3a, 0x0b];
+
+/// Round scalar single-precision floating-point values.
+pub static ROUNDSS: [u8; 4] = [0x66, 0x0f, 0x3a, 0x0a];
+
+/// Subtract with borrow r{16,32,64} from r/m of the same size.
+pub static SBB: [u8; 1] = [0x19];
+
+/// Set byte if overflow (OF=1).
+pub static SET_BYTE_IF_OVERFLOW: [u8; 2] = [0x0f, 0x90];
+
+/// Compute square root of scalar double-precision floating-point value.
+pub static SQRTSD: [u8; 3] = [0xf2, 0x0f, 0x51];
+
+/// Compute square root of scalar single-precision value.
+pub static SQRTSS: [u8; 3] = [0xf3, 0x0f, 0x51];
+
+/// Subtract r{16,32,64} from r/m of same size.
+pub static SUB: [u8; 1] = [0x29];
+
+/// Subtract the low double-precision floating-point value in xmm2/m64 from xmm1
+/// and store the result in xmm1.
+pub static SUBSD: [u8; 3] = [0xf2, 0x0f, 0x5c];
+
+/// Subtract the low single-precision floating-point value in xmm2/m32 from xmm1
+/// and store the result in xmm1.
+pub static SUBSS: [u8; 3] = [0xf3, 0x0f, 0x5c];
+
+/// AND r8 with r/m8; set SF, ZF, PF according to result.
+pub static TEST_BYTE_REG: [u8; 1] = [0x84];
+
+/// AND {r16, r32, r64} with r/m of the same size; set SF, ZF, PF according to result.
+pub static TEST_REG: [u8; 1] = [0x85];
+
+/// Count the number of trailing zero bits.
+pub static TZCNT: [u8; 3] = [0xf3, 0x0f, 0xbc];
+
+/// Compare low double-precision floating-point values in xmm1 and xmm2/mem64
+/// and set the EFLAGS flags accordingly.
+pub static UCOMISD: [u8; 3] = [0x66, 0x0f, 0x2e];
+
+/// Compare low single-precision floating-point values in xmm1 and xmm2/mem32
+/// and set the EFLAGS flags accordingly.
+pub static UCOMISS: [u8; 2] = [0x0f, 0x2e];
+
+/// Raise invalid opcode instruction.
+pub static UNDEFINED2: [u8; 2] = [0x0f, 0x0b];
+
+/// imm{16,32} XOR r/m{16,32,64}, possibly sign-extended.
+pub static XOR_IMM: [u8; 1] = [0x81];
+
+/// r/m{16,32,64} XOR sign-extended imm8.
+pub static XOR_IMM8_SIGN_EXTEND: [u8; 1] = [0x83];
+
+/// r/m{16,32,64} XOR register of the same size.
+pub static XOR: [u8; 1] = [0x31];
+
+/// r/m8 XOR r8.
+pub static XORB: [u8; 1] = [0x30];
+
+/// Bitwise logical XOR of packed double-precision floating-point values.
+pub static XORPD: [u8; 3] = [0x66, 0x0f, 0x57];
+
+/// Bitwise logical XOR of packed single-precision floating-point values.
+pub static XORPS: [u8; 2] = [0x0f, 0x57];
diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs
index 11a9972d98079a5554ab81c5c09d070b485d038d..ce0999c04ccd0645ad0e30eba4d79e11dbd1445b 100644
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/recipes.rs
@@ -10,10 +10,12 @@ use crate::cdsl::regs::IsaRegs;
 use crate::cdsl::settings::SettingGroup;
 use crate::shared::Definitions as SharedDefinitions;
 
+use crate::isa::x86::opcodes;
+
 /// Helper data structure to create recipes and template recipes.
 /// It contains all the recipes and recipe templates that might be used in the encodings crate of
 /// this same directory.
-pub struct RecipeGroup<'builder> {
+pub(crate) struct RecipeGroup<'builder> {
     /// Memoized format pointer, to pass it to builders later.
     formats: &'builder FormatRegistry,
 
@@ -186,7 +188,7 @@ pub struct Template<'builder> {
     /// Value of the RRR bits (between 0 and 0b111).
     rrr_bits: u16,
     /// Opcode bytes.
-    op_bytes: Vec<u8>,
+    op_bytes: &'static [u8],
 }
 
 impl<'builder> Template<'builder> {
@@ -204,7 +206,7 @@ impl<'builder> Template<'builder> {
             rex: false,
             w_bit: 0,
             rrr_bits: 0,
-            op_bytes: Vec::new(),
+            op_bytes: &opcodes::EMPTY,
         }
     }
 
@@ -226,7 +228,7 @@ impl<'builder> Template<'builder> {
     }
 
     // Copy setters.
-    pub fn opcodes(&self, op_bytes: Vec<u8>) -> Self {
+    pub fn opcodes(&self, op_bytes: &'static [u8]) -> Self {
         assert!(!op_bytes.is_empty());
         let mut copy = self.clone();
         copy.op_bytes = op_bytes;
@@ -396,11 +398,11 @@ pub(crate) fn define<'shared>(
     let f_trap = formats.by_name("Trap");
     let f_unary = formats.by_name("Unary");
     let f_unary_bool = formats.by_name("UnaryBool");
+    let f_unary_const = formats.by_name("UnaryConst");
     let f_unary_global_value = formats.by_name("UnaryGlobalValue");
     let f_unary_ieee32 = formats.by_name("UnaryIeee32");
     let f_unary_ieee64 = formats.by_name("UnaryIeee64");
     let f_unary_imm = formats.by_name("UnaryImm");
-    let f_unary_imm128 = formats.by_name("UnaryImm128");
 
     // Predicates shorthands.
     let use_sse41 = settings.predicate_by_name("use_sse41");
@@ -2437,14 +2439,26 @@ pub(crate) fn define<'shared>(
     );
 
     recipes.add_template_recipe(
-        EncodingRecipeBuilder::new("vconst", f_unary_imm128, 5)
+        EncodingRecipeBuilder::new("vconst", f_unary_const, 5)
             .operands_out(vec![fpr])
             .clobbers_flags(false)
             .emit(
                 r#"
                     {{PUT_OP}}(bits, rex2(0, out_reg0), sink);
                     modrm_riprel(out_reg0, sink);
-                    const_disp4(imm, func, sink);
+                    const_disp4(constant_handle, func, sink);
+                "#,
+            ),
+    );
+
+    recipes.add_template_recipe(
+        EncodingRecipeBuilder::new("vconst_optimized", f_unary_const, 1)
+            .operands_out(vec![fpr])
+            .clobbers_flags(false)
+            .emit(
+                r#"
+                    {{PUT_OP}}(bits, rex2(out_reg0, out_reg0), sink);
+                    modrm_rr(out_reg0, out_reg0, sink);
                 "#,
             ),
     );
@@ -2908,26 +2922,27 @@ pub(crate) fn define<'shared>(
                     {{PUT_OP}}(bits, rex2(in_reg0, in_reg1), sink);
                     modrm_rr(in_reg0, in_reg1, sink);
                     // `setCC` instruction, no REX.
-                    use crate::ir::condcodes::IntCC::*;
-                    let setcc = match cond {
-                        Equal => 0x94,
-                        NotEqual => 0x95,
-                        SignedLessThan => 0x9c,
-                        SignedGreaterThanOrEqual => 0x9d,
-                        SignedGreaterThan => 0x9f,
-                        SignedLessThanOrEqual => 0x9e,
-                        UnsignedLessThan => 0x92,
-                        UnsignedGreaterThanOrEqual => 0x93,
-                        UnsignedGreaterThan => 0x97,
-                        UnsignedLessThanOrEqual => 0x96,
-                    };
+                    let setcc = 0x90 | icc2opc(cond);
                     sink.put1(0x0f);
-                    sink.put1(setcc);
+                    sink.put1(setcc as u8);
                     modrm_rr(out_reg0, 0, sink);
                 "#,
             ),
     );
 
+    recipes.add_template_recipe(
+        EncodingRecipeBuilder::new("icscc_fpr", f_int_compare, 1)
+            .operands_in(vec![fpr, fpr])
+            .operands_out(vec![0])
+            .emit(
+                r#"
+                    // Comparison instruction.
+                    {{PUT_OP}}(bits, rex2(in_reg1, in_reg0), sink);
+                    modrm_rr(in_reg1, in_reg0, sink);
+                "#,
+            ),
+    );
+
     {
         let format = formats.get(f_int_compare_imm);
 
@@ -2946,21 +2961,9 @@ pub(crate) fn define<'shared>(
                         let imm: i64 = imm.into();
                         sink.put1(imm as u8);
                         // `setCC` instruction, no REX.
-                        use crate::ir::condcodes::IntCC::*;
-                        let setcc = match cond {
-                            Equal => 0x94,
-                            NotEqual => 0x95,
-                            SignedLessThan => 0x9c,
-                            SignedGreaterThanOrEqual => 0x9d,
-                            SignedGreaterThan => 0x9f,
-                            SignedLessThanOrEqual => 0x9e,
-                            UnsignedLessThan => 0x92,
-                            UnsignedGreaterThanOrEqual => 0x93,
-                            UnsignedGreaterThan => 0x97,
-                            UnsignedLessThanOrEqual => 0x96,
-                        };
+                        let setcc = 0x90 | icc2opc(cond);
                         sink.put1(0x0f);
-                        sink.put1(setcc);
+                        sink.put1(setcc as u8);
                         modrm_rr(out_reg0, 0, sink);
                     "#,
                 ),
@@ -2981,21 +2984,9 @@ pub(crate) fn define<'shared>(
                         let imm: i64 = imm.into();
                         sink.put4(imm as u32);
                         // `setCC` instruction, no REX.
-                        use crate::ir::condcodes::IntCC::*;
-                        let setcc = match cond {
-                            Equal => 0x94,
-                            NotEqual => 0x95,
-                            SignedLessThan => 0x9c,
-                            SignedGreaterThanOrEqual => 0x9d,
-                            SignedGreaterThan => 0x9f,
-                            SignedLessThanOrEqual => 0x9e,
-                            UnsignedLessThan => 0x92,
-                            UnsignedGreaterThanOrEqual => 0x93,
-                            UnsignedGreaterThan => 0x97,
-                            UnsignedLessThanOrEqual => 0x96,
-                        };
+                        let setcc = 0x90 | icc2opc(cond);
                         sink.put1(0x0f);
-                        sink.put1(setcc);
+                        sink.put1(setcc as u8);
                         modrm_rr(out_reg0, 0, sink);
                     "#,
                 ),
diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs b/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs
index 5309afc1b0b3b319fe6b31e7ba2e6359ee6ae481..73aaa42634180b4c3b5de293f955c75efed43337 100644
--- a/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/shared/formats.rs
@@ -6,10 +6,10 @@ pub(crate) fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry
 
     registry.insert(Builder::new("Unary").value());
     registry.insert(Builder::new("UnaryImm").imm(&imm.imm64));
-    registry.insert(Builder::new("UnaryImm128").imm(&imm.uimm128));
     registry.insert(Builder::new("UnaryIeee32").imm(&imm.ieee32));
     registry.insert(Builder::new("UnaryIeee64").imm(&imm.ieee64));
     registry.insert(Builder::new("UnaryBool").imm(&imm.boolean));
+    registry.insert(Builder::new("UnaryConst").imm(&imm.pool_constant));
     registry.insert(Builder::new("UnaryGlobalValue").imm(&entities.global_value));
 
     registry.insert(Builder::new("Binary").value().value());
@@ -43,6 +43,12 @@ pub(crate) fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry
             .value()
             .imm_with_name("lane", &imm.uimm8),
     );
+    registry.insert(
+        Builder::new("Shuffle")
+            .value()
+            .value()
+            .imm_with_name("mask", &imm.uimm128),
+    );
 
     registry.insert(Builder::new("IntCompare").imm(&imm.intcc).value().value());
     registry.insert(
@@ -59,7 +65,7 @@ pub(crate) fn define(imm: &Immediates, entities: &EntityRefs) -> FormatRegistry
             .value()
             .value(),
     );
-    registry.insert(Builder::new("FloatCond").imm(&imm.floatcc).value());;
+    registry.insert(Builder::new("FloatCond").imm(&imm.floatcc).value());
 
     registry.insert(
         Builder::new("IntSelect")
diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs b/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs
index 30c1a73970f4d82b4fd66cef01a2698446f7b486..f9c114a6a03dff3d4e062c60f940daaea15a2a2f 100644
--- a/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/shared/immediates.rs
@@ -23,6 +23,12 @@ pub(crate) struct Immediates {
     /// const.
     pub uimm128: OperandKind,
 
+    /// A constant stored in the constant pool.
+    ///
+    /// This operand is used to pass constants to instructions like vconst while storing the
+    /// actual bytes in the constant pool.
+    pub pool_constant: OperandKind,
+
     /// A 32-bit immediate signed offset.
     ///
     /// This is used to represent an immediate address offset in load/store instructions.
@@ -84,6 +90,12 @@ impl Immediates {
 
             uimm128: Builder::new_imm("uimm128")
                 .doc("A 128-bit immediate unsigned integer.")
+                .rust_type("ir::Immediate")
+                .build(),
+
+            pool_constant: Builder::new_imm("poolConstant")
+                .doc("A constant stored in the constant pool.")
+                .default_member("constant_handle")
                 .rust_type("ir::Constant")
                 .build(),
 
@@ -117,6 +129,8 @@ impl Immediates {
                 intcc_values.insert("ugt", "UnsignedGreaterThan");
                 intcc_values.insert("ule", "UnsignedLessThanOrEqual");
                 intcc_values.insert("ult", "UnsignedLessThan");
+                intcc_values.insert("of", "Overflow");
+                intcc_values.insert("nof", "NotOverflow");
                 Builder::new_enum("intcc", intcc_values)
                     .doc("An integer comparison condition code.")
                     .default_member("cond")
diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs b/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs
index bae1327b603359cb0bf202a4b4ccd28b439d9a9c..679ee1a2c12a1ddef2652c4a1a8985854569220d 100644
--- a/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/shared/instructions.rs
@@ -1090,7 +1090,7 @@ pub(crate) fn define(
 
     let N = &operand_doc(
         "N",
-        &imm.uimm128,
+        &imm.pool_constant,
         "The 16 immediate bytes of a 128-bit vector",
     );
     let a = &operand_doc("a", TxN, "A constant vector value");
@@ -1108,6 +1108,41 @@ pub(crate) fn define(
         .operands_out(vec![a]),
     );
 
+    let mask = &operand_doc(
+        "mask",
+        &imm.uimm128,
+        "The 16 immediate bytes used for selecting the elements to shuffle",
+    );
+    let Tx16 = &TypeVar::new(
+        "Tx16",
+        "A SIMD vector with exactly 16 lanes of 8-bit values; eventually this may support other \
+         lane counts and widths",
+        TypeSetBuilder::new()
+            .ints(8..8)
+            .bools(8..8)
+            .simd_lanes(16..16)
+            .includes_scalars(false)
+            .build(),
+    );
+    let a = &operand_doc("a", Tx16, "A vector value");
+    let b = &operand_doc("b", Tx16, "A vector value");
+
+    ig.push(
+        Inst::new(
+            "shuffle",
+            r#"
+        SIMD vector shuffle.
+        
+        Shuffle two vectors using the given immediate bytes. For each of the 16 bytes of the
+        immediate, a value i of 0-15 selects the i-th element of the first vector and a value i of 
+        16-31 selects the (i-16)th element of the second vector. Immediate values outside of the 
+        0-31 range place a 0 in the resulting vector lane.
+        "#,
+        )
+        .operands_in(vec![a, b, mask])
+        .operands_out(vec![a]),
+    );
+
     let a = &operand_doc("a", Ref, "A constant reference null value");
 
     ig.push(
@@ -1551,6 +1586,8 @@ pub(crate) fn define(
     let x = &operand("x", Int);
     let y = &operand("y", Int);
 
+    // TODO(ryzokuken): Add documentation for unsigned overflow.
+    // TODO(ryzokuken): Add documentation for signed overflow.
     ig.push(
         Inst::new(
             "icmp",
diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs b/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs
index f9cec3557e279312e52029022bf481fda347358d..fef4c1e1ecb29ed4df9fe3dfd47c1cde97bd55d0 100644
--- a/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/shared/legalize.rs
@@ -64,7 +64,6 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
     let f64const = insts.by_name("f64const");
     let fcopysign = insts.by_name("fcopysign");
     let fcvt_from_sint = insts.by_name("fcvt_from_sint");
-    let fcvt_from_uint = insts.by_name("fcvt_from_uint");
     let fneg = insts.by_name("fneg");
     let iadd = insts.by_name("iadd");
     let iadd_cin = insts.by_name("iadd_cin");
@@ -94,6 +93,7 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
     let isub_borrow = insts.by_name("isub_borrow");
     let isub_ifbin = insts.by_name("isub_ifbin");
     let isub_ifbout = insts.by_name("isub_ifbout");
+    let jump = insts.by_name("jump");
     let load = insts.by_name("load");
     let popcnt = insts.by_name("popcnt");
     let rotl = insts.by_name("rotl");
@@ -190,6 +190,8 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
     let ah = var("ah");
     let cc = var("cc");
     let ebb = var("ebb");
+    let ebb1 = var("ebb1");
+    let ebb2 = var("ebb2");
     let ptr = var("ptr");
     let flags = var("flags");
     let offset = var("off");
@@ -260,11 +262,13 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
     );
 
     narrow.legalize(
-        def!(brnz.I128(x, ebb, vararg)),
+        def!(brnz.I128(x, ebb1, vararg)),
         vec![
             def!((xl, xh) = isplit(x)),
-            def!(brnz(xl, ebb, vararg)),
-            def!(brnz(xh, ebb, vararg)),
+            def!(brnz(xl, ebb1, vararg)),
+            def!(jump(ebb2, Literal::empty_vararg())),
+            ebb!(ebb2),
+            def!(brnz(xh, ebb1, vararg)),
         ],
     );
 
@@ -542,21 +546,12 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
         ],
     );
 
-    // Expansions for fcvt_from_{u,s}int for smaller integer types.
-    // These use expand and not widen because the controlling type variable for
-    // these instructions are f32/f64, which are legalized as part of the expand
+    // Expansion for fcvt_from_sint for smaller integer types.
+    // This uses expand and not widen because the controlling type variable for
+    // this instruction is f32/f64, which is legalized as part of the expand
     // group.
     for &dest_ty in &[F32, F64] {
         for &src_ty in &[I8, I16] {
-            let bound_inst = fcvt_from_uint.bind(dest_ty).bind(src_ty);
-            expand.legalize(
-                def!(a = bound_inst(b)),
-                vec![
-                    def!(x = uextend.I32(b)),
-                    def!(a = fcvt_from_uint.dest_ty(x)),
-                ],
-            );
-
             let bound_inst = fcvt_from_sint.bind(dest_ty).bind(src_ty);
             expand.legalize(
                 def!(a = bound_inst(b)),
diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs b/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs
index 12921da5ef8a6bc53c8b4552ad5dc7081aa86224..73cdb4254d8c1a579f4a051569b3159bbe64e536 100644
--- a/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/shared/mod.rs
@@ -29,7 +29,7 @@ pub(crate) fn define() -> Definitions {
     let mut all_instructions = AllInstructions::new();
 
     let immediates = Immediates::new();
-    let entities = EntityRefs::new();;
+    let entities = EntityRefs::new();
     let format_registry = formats::define(&immediates, &entities);
     let instructions = instructions::define(
         &mut all_instructions,
diff --git a/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs b/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs
index 63c5d3c01aeb575199d3cbfc80f052d4afc64e91..43fe357ab7030da3bc6bc03b745f1ed5a8f5e474 100644
--- a/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/shared/settings.rs
@@ -8,11 +8,12 @@ pub fn define() -> SettingGroup {
         r#"
         Optimization level:
 
-        - default: Very profitable optimizations enabled, none slow.
-        - best: Enable all optimizations
-        - fastest: Optimize for compile time by disabling most optimizations.
+        - none: Minimise compile time by disabling most optimizations.
+        - speed: Generate the fastest possible code
+        - speed_and_size: like "speed", but also perform transformations
+          aimed at reducing code size.
         "#,
-        vec!["default", "best", "fastest"],
+        vec!["none", "speed", "speed_and_size"],
     );
 
     settings.add_bool(
diff --git a/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json b/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json
new file mode 100644
index 0000000000000000000000000000000000000000..c9e84bff2fd081819ed5ba145a7248676b48a6b2
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"17643920d895c99deb5b2849b2a9b55ff5cc61877f9c297914b8ba1987bb0731","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"a410bc2f5dcbde499c0cd299c2620bc8111e3c5b3fccdd9e2d85caf3c24fdab3","src/condcodes.rs":"838c9becb7d42ef0eb98e70505b52783a2e900b6532316708466f2157fa807d9","src/lib.rs":"f42e7d8606285e8e2b8994486bdad7e0796abc4778efdf55dbd20e4320a25e62"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-codegen-shared/Cargo.toml b/third_party/rust/cranelift-codegen-shared/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..d58b92fd50467406c19208a1afd70190639760a4
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+authors = ["The Cranelift Project Developers"]
+name = "cranelift-codegen-shared"
+version = "0.44.0"
+description = "For code shared between cranelift-codegen-meta and cranelift-codegen"
+license = "Apache-2.0 WITH LLVM-exception"
+repository = "https://github.com/CraneStation/cranelift"
+readme = "README.md"
+edition = "2018"
+
+[dependencies]
diff --git a/third_party/rust/cranelift-codegen-shared/LICENSE b/third_party/rust/cranelift-codegen-shared/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..f9d81955f4bcb8f96a025e2ecc46f39ec536d465
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/LICENSE
@@ -0,0 +1,220 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+--- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
diff --git a/third_party/rust/cranelift-codegen-shared/README.md b/third_party/rust/cranelift-codegen-shared/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..54f9f5d6d29d614713b5d3a382ca6c759c809145
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/README.md
@@ -0,0 +1,2 @@
+This crate contains shared definitions for use in both `cranelift-codegen-meta` and `cranelift
+-codegen`.
diff --git a/third_party/rust/cranelift-codegen/src/ir/condcodes.rs b/third_party/rust/cranelift-codegen-shared/src/condcodes.rs
similarity index 95%
rename from third_party/rust/cranelift-codegen/src/ir/condcodes.rs
rename to third_party/rust/cranelift-codegen-shared/src/condcodes.rs
index 743e30954d948606f759700a851f1c0892aeb197..1171eef2f6a7a1c9317e71e37bab47a9ffb60f97 100644
--- a/third_party/rust/cranelift-codegen/src/ir/condcodes.rs
+++ b/third_party/rust/cranelift-codegen-shared/src/condcodes.rs
@@ -51,6 +51,10 @@ pub enum IntCC {
     UnsignedGreaterThan,
     /// Unsigned `<=`.
     UnsignedLessThanOrEqual,
+    /// Signed Overflow.
+    Overflow,
+    /// Signed No Overflow.
+    NotOverflow,
 }
 
 impl CondCode for IntCC {
@@ -67,6 +71,8 @@ impl CondCode for IntCC {
             UnsignedGreaterThanOrEqual => UnsignedLessThan,
             UnsignedGreaterThan => UnsignedLessThanOrEqual,
             UnsignedLessThanOrEqual => UnsignedGreaterThan,
+            Overflow => NotOverflow,
+            NotOverflow => Overflow,
         }
     }
 
@@ -83,6 +89,8 @@ impl CondCode for IntCC {
             UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual,
             UnsignedLessThan => UnsignedGreaterThan,
             UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual,
+            Overflow => Overflow,
+            NotOverflow => NotOverflow,
         }
     }
 }
@@ -101,6 +109,8 @@ impl Display for IntCC {
             UnsignedGreaterThanOrEqual => "uge",
             UnsignedLessThan => "ult",
             UnsignedLessThanOrEqual => "ule",
+            Overflow => "of",
+            NotOverflow => "nof",
         })
     }
 }
@@ -121,6 +131,8 @@ impl FromStr for IntCC {
             "ugt" => Ok(UnsignedGreaterThan),
             "ule" => Ok(UnsignedLessThanOrEqual),
             "ult" => Ok(UnsignedLessThan),
+            "of" => Ok(Overflow),
+            "nof" => Ok(NotOverflow),
             _ => Err(()),
         }
     }
@@ -270,7 +282,7 @@ mod tests {
     use super::*;
     use std::string::ToString;
 
-    static INT_ALL: [IntCC; 10] = [
+    static INT_ALL: [IntCC; 12] = [
         IntCC::Equal,
         IntCC::NotEqual,
         IntCC::SignedLessThan,
@@ -281,6 +293,8 @@ mod tests {
         IntCC::UnsignedGreaterThanOrEqual,
         IntCC::UnsignedGreaterThan,
         IntCC::UnsignedLessThanOrEqual,
+        IntCC::Overflow,
+        IntCC::NotOverflow,
     ];
 
     #[test]
diff --git a/third_party/rust/cranelift-codegen-shared/src/lib.rs b/third_party/rust/cranelift-codegen-shared/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..87de6e79516fbf412fda6406fd245ad41d846e0e
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-shared/src/lib.rs
@@ -0,0 +1,26 @@
+//! This library contains code that is common to both the `cranelift-codegen` and
+//! `cranelift-codegen-meta` libraries.
+
+#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
+#![warn(unused_import_braces)]
+#![cfg_attr(feature = "std", deny(unstable_features))]
+#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
+#![cfg_attr(
+    feature = "cargo-clippy",
+    warn(
+        clippy::float_arithmetic,
+        clippy::mut_mut,
+        clippy::nonminimal_bool,
+        clippy::option_map_unwrap_or,
+        clippy::option_map_unwrap_or_else,
+        clippy::print_stdout,
+        clippy::unicode_not_nfc,
+        clippy::use_self
+    )
+)]
+
+pub mod condcodes;
+
+/// Version number of this crate.
+pub const VERSION: &str = env!("CARGO_PKG_VERSION");
diff --git a/third_party/rust/cranelift-codegen/.cargo-checksum.json b/third_party/rust/cranelift-codegen/.cargo-checksum.json
index 63ff84e15a8c55674844ca15b7fc2ef08d889158..99baf1647ff60bee610ca1b8c0b1a094051c0c12 100644
--- a/third_party/rust/cranelift-codegen/.cargo-checksum.json
+++ b/third_party/rust/cranelift-codegen/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"99b4b834ec33e1d1917296497e286dad5819fed0600b5ce288a114133efbe734","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"8587e8557a046dc858f7662f63f1fa54e57ff92ed87b30fbcdfce6feafda9d60","src/abi.rs":"76ee030cf0780fe63ccbf855b1161f215e3e2991cb9abe71ca9aff25e5f1dbc2","src/binemit/memorysink.rs":"da415b20c563e636bcccaafb43dbdb77d6c48f9c205b16229865abb1afa40964","src/binemit/mod.rs":"90c56d36091646bba7f0ab1b5064d68b8b0c24ece874fcf8c621830b743e9688","src/binemit/relaxation.rs":"7b1082203c688beab4d705e601ad4fde10c5bf1fec414ad1ee6993e4f6b95e01","src/binemit/shrink.rs":"5755efc978f5056a33c0ecb1bd5e08310397f54a67434ecead184fc6ee047133","src/binemit/stackmap.rs":"da3187d96d21b14927279061ccaba4c880d0ad7169b83bd32c1381d45a39af70","src/bitset.rs":"d57a79058a31b094b4bbe9d34876a5543286df1e08b5ceadfd05a9efc5a3b1ce","src/cfg_printer.rs":"a84dee96d8c6f4775b8ba022243cf1c0bcf847c6d7ec532698cfd331655aa453","src/constant_hash.rs":"77eb898f7b0a4ae3b8165a03c25fcd23ce9c1d0cd32c793fa6cb31666ce27eb1","src/context.rs":"54b0acb1fb10e98f20804c367d5b2343f8ec918900f8f843e12e0925649b7515","src/cursor.rs":"874d1c7ef6e114d6ae47e0a1f92da7c5cec2e555597558042a3b214da7bc5fe4","src/dbg.rs":"1898d94cff0975815eb348651702e95c8f2f63886501d3b7043ee75668480472","src/dce.rs":"d8ab7c0cac0416f9d75afdacc60ba02e532361ec927c3f8bd171b1a53ec8b31a","src/divconst_magic_numbers.rs":"09691389c9055bef7a0cfd5d77fbfeba4be468d05d981d4de088516a94b8b28e","src/dominator_tree.rs":"6817b893c2c5ba5f2fc4e632fb8f8b7210a9ea9862d389d5247ff94b992b0d27","src/flowgraph.rs":"c975c05949017f0b2efeff85bf82017b6a5779ed92e25f13742aeea76ca95c52","src/fx.rs":"8a5d07487906d8316a179e826fcd817a92a4860686256a6fd9d78ba47c63f330","src/ir/builder.rs":"6f111f2a65dfe27633dcec918f74b767277131a72cd94b7bec2e1ef5c4308d5b","src/ir/condcodes.rs":"5247c8d849e1372d2a22379c33a4a88226ec6187be18ca6f2c4e0f315d812aa8","src/ir/constant.rs":"378d02256c3e21d89b70c6b0956ef70c034a5f14c1d2aaaec1f172a38b7b2279","src/ir/dfg.rs":"03abeb42420006b5d655a396d3724f34507e27e815aec6b30902e5a3fbd52a13","src/ir/entities.rs":"976f51a1e704b63b0bc701eb814b10ec8eee373d8f93ee73ceeeaeeea2c5b821","src/ir/extfunc.rs":"f26200741eb91be0d9a72a7aea194fd28f78696754ed9c26e88c8dd277ecd082","src/ir/extname.rs":"ed2c0b52cdaecc7f0ba9a894ef9fffe139e09b520e43dcd6f0c887a3d41a31ac","src/ir/function.rs":"fdbd33def70bfc49648c232d9fdb65eb8ed694a6a1a8bde1e06d6e40d4970230","src/ir/globalvalue.rs":"906d29f3d4190b811f66fc549c4e0408bdd2807eac98e33c0b3d5c2b876acc02","src/ir/heap.rs":"a59d3e5901412b53c0b53a8cdf10765ff5921de9c410ae9acea226c89827df3c","src/ir/immediates.rs":"671cc8bfcc347d7409ddba2bc661d985979f144cd663da232d9ba6a54e5c94c5","src/ir/instructions.rs":"7fe853efeb0379486d7878f7925962144ce208d230107d83e5a9165997a07587","src/ir/jumptable.rs":"7764abc9aa027a5a89d22059b360372bd9a19686887c5a7830f7637d6f188e1e","src/ir/layout.rs":"b80c4609e6101228b6d7fa341b60730137ecdcc2f918120f6473dbf62f31b9ad","src/ir/libcall.rs":"3e540afdd1d9a68b1be0ddb983a8db39312a052aae9ba92fb2440746f69fef06","src/ir/memflags.rs":"dbcf3798ab66dc764b73fb7f139a621c54cc6bcc683f1f70a33ed7e8c3486bfd","src/ir/mod.rs":"7590a2035a6f88a830e6c440d3c5a22102e921445806d04627e46ee42d82d167","src/ir/progpoint.rs":"49433f22bd6ff3a96ad0733ff612f3617b312e4492b6b663187141966f6aa701","src/ir/sourceloc.rs":"e1442572958b138f7637a14b662200ea9f729a513b77108be2a39745d8c2a0d5","src/ir/stackslot.rs":"a116aec3d41fcb570044584d06c97e21fc65d68b31f921ab6b5d7a2daddb614b","src/ir/table.rs":"dcc3b663a989b2b084402b08dc9a0e928dbd052e194a46a1886cc6f0cf1a5f2c","src/ir/trapcode.rs":"59e223193617b8c1043ddd3a907c6131f2987e8fe0965ebfd9f7c056c064b7c5","src/ir/types.rs":"8cfe8028008c93c37a593e82c230f95e8674d727cce5715aa55c93e140da4ced","src/ir/valueloc.rs":"1bf764fde5ff8140fa2b59f0192086ed17e9ba7018c74719788b74fc5ca05636","src/isa/arm32/abi.rs":"74775c5f1eb95764e46815fa8b31891416a616fdd212972eb77aead43b3345a9","src/isa/arm32/binemit.rs":"eecd7296c27d2520db8e86dd462833ecf06afd33548b03ae676c02454cdd13c2","src/isa/arm32/enc_tables.rs":"e94b12af802de59484cab1124d2ac8a88d08433f6e1a476724ed0403f4b5967f","src/isa/arm32/mod.rs":"bf862e984034f09a83bf0f5f18eb93e09cb23f1a5a994b554c478d174d672c64","src/isa/arm32/registers.rs":"254b568a02480f46bb4967a24a438390231014258f0c159f0a41dbafe8e66d56","src/isa/arm32/settings.rs":"2314460f885c24f9571d640f9737a8e0b7d20ca02bcda1127f878fd3891c0529","src/isa/arm64/abi.rs":"52353ed2e2133dacddaad70a876ecebb9c179c19b911ffa823b5b89d3ee7a17c","src/isa/arm64/binemit.rs":"3afbb78f6d9ae5614d908023f84b774c0493c8757ad86fd8301baf0928bb0104","src/isa/arm64/enc_tables.rs":"73fedf7da610a982e37c76e5211dbce880f77841b71c678b0dab2b9e7217cb7c","src/isa/arm64/mod.rs":"49b7f398ec8baa2802a283f780bd039e2a630591e74cf1dddc8d9147345c2816","src/isa/arm64/registers.rs":"308cfcfd9ff2191d7656e7350bb36e41803664eb86ae490fb4b4d3549b25b6a2","src/isa/arm64/settings.rs":"5405ce3560b7ba0705ef525c706eb9f1593e901e1767b837c012084397639042","src/isa/call_conv.rs":"56dfbf8f23a82942566d2a81deaf2147777061b3b49532b4f9fdcd3aae51aa56","src/isa/constraints.rs":"bddb5c68e56b122a53d8be215e41d22ccf8c4563630b1486e6eb31c0d3337565","src/isa/enc_tables.rs":"382e714f9500afc292c563cb66d4c963d6787e58f197b1db242db7a099c22b9a","src/isa/encoding.rs":"7ea5b4400530172f96e263561682886ea6c67e706398d44a83933ef7f0ac98a5","src/isa/mod.rs":"79ecb214ca28d4690b2ace20f6d4cdc36f393ef03f679a9d18a03653d230e160","src/isa/registers.rs":"004b090b7390fa07c1add81ef4a8c79bd7a6001a22cb014a4a83a9fa6ae3aeca","src/isa/riscv/abi.rs":"36557b91ad16a1344c80fbb16a62b46eac88500d76cb9ebcd4eae224dd67b2de","src/isa/riscv/binemit.rs":"264d223da311d4482ebf2f55438b665c67b163058251bc78173c76ba983a31ef","src/isa/riscv/enc_tables.rs":"8491f2082b24c7dedeb7c36cfd913bf9aeaa0a4c8fc754166e9285f4ae002f40","src/isa/riscv/mod.rs":"41136889df9512d8311f8c015cf3f654557a17d784a17fcefeb0afa2f0ec3674","src/isa/riscv/registers.rs":"666c2abe1a93db5f1573d1603db6c13c37f3fc877c0c93b64d1b971921bfa950","src/isa/riscv/settings.rs":"f6362769e9bc5be0c12b091e414ce924b0d2053b05b0ae88fef118cb8c68761e","src/isa/stack.rs":"5d30e2e19662ff3b3a641888bbb29640094ccd51b9a73368a056352afee46320","src/isa/x86/abi.rs":"13013f247c8e0fca46fe43568ef3186616fa469a321dee0a41fc2cc25220ec10","src/isa/x86/binemit.rs":"75d88b4ce66ec125940a2543a28e975c542a81a841c3c81282fc98ef78c1e032","src/isa/x86/enc_tables.rs":"ad7e3e384a784c24cc9750bb75f16f3b1cc231ae8f34b6b5d4138ee76d66b2cc","src/isa/x86/mod.rs":"d69e7f441c049b87aa1820639aaf12436bde1b0286757b03bec19fe7492049cc","src/isa/x86/registers.rs":"bed70bbe1f56f3ef03ea7cd1bea68eb911913cb4c8b93167e044dfc639f7f461","src/isa/x86/settings.rs":"d3e403db3507830f79bcc976c17340b57052cf1b50877fcf1a79549f2a054458","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"70a6819cbb116f07d0a09f8e5b0e2fe91145f423ad02e10225f8879ff4e61351","src/legalizer/call.rs":"be6074c64c1a00e5e81159dd94c8401fef62205b22c15e07e0c56cf922554d00","src/legalizer/globalvalue.rs":"59ab09a0faf593c7f228500b3fd3bacfc0412bdcb2864ec3621aa65adc4a5693","src/legalizer/heap.rs":"ce25c9575dbc3ef102f199b3bd5652e8c6b88ff323711c89ae41d0070b61adcb","src/legalizer/libcall.rs":"875daf54ac05114e50eba801b25b2c201351e9f6c276ba0358b356498c54d1c6","src/legalizer/mod.rs":"7911a03e4229fa6ea371b714b3a50b677adbeeab749b8809bf29fe298cd9d7ff","src/legalizer/split.rs":"696d2a641f52eeb4f2a2106b0641f751f61c560e6e3cbbac544df28b203a4445","src/legalizer/table.rs":"c36d03525312e3191aba8ee00c26a87c1ea200f9a9a0370f0cc84eeacff71786","src/lib.rs":"357c72bc31010fdf0e412000efd7e5538a36361f8562accec6a60e750c111876","src/licm.rs":"07534926e2986c01e3b76a2faf2336f5b96411f06d93d44d74e991f76265e29d","src/loop_analysis.rs":"58fc3cc0e700f05e3131ff1b16ff975d4f32a68c790f095d8445bd300356d3c0","src/nan_canonicalization.rs":"9619bb5554791bd1be75ecd98564d6c9f5b65132bc07c5c4d8c210cd79b66f82","src/partition_slice.rs":"bc13504e7658aab565918d965a0b67e941eb572e583870571bc6dbb2b9aad272","src/postopt.rs":"d4c487f0299fb905bb5a5822e38dea6f70afa4d4577288988b5bec8660bc1ba0","src/predicates.rs":"f52499cc39778f5e935140ea42405ce23e8a2ef9a21faf6378445dcee7e6a0f0","src/print_errors.rs":"3fbd77a01b5404a4bbcf2970e44299ad33948c71f4014d92026415daa8325314","src/redundant_reload_remover.rs":"3b2e49280375c9294fb7e190a8b02ef4fcef05ffcf1cb9e6e583cdc8e484bde1","src/ref_slice.rs":"421a61323c11858a596d50220487f399e1bcedeff0e8d1b716dd4b3531eb01a5","src/regalloc/affinity.rs":"19cec5495c8bddc1fcc8f3c8659d527a5a3ea373ffcc130e3fbd5b462ef15930","src/regalloc/branch_splitting.rs":"50ff6a6d257a9cb35d302ed61fa45ff1be4d2ff0f695aa2cedd161bd725a598c","src/regalloc/coalescing.rs":"d83be1c1067eb56f2f8f16380450a327d6495b4c6f1f489ded68271c055aec07","src/regalloc/coloring.rs":"6308e0f4f71b24e8d5abc94a98c4d20eff753c02238872119c7f4390f026e0a4","src/regalloc/context.rs":"0b3d5009c23b58cc9ccca2ece9d85dbdea52f843f52452e7813dd7a3229547d3","src/regalloc/diversion.rs":"49edbe958591acb304093e601179de7a79de0a4557748b98ddb736a865ef6a43","src/regalloc/live_value_tracker.rs":"28823003dc72e8a4702776a8ab5ffd878712700a272b64376b0de2022e0ee31a","src/regalloc/liveness.rs":"a59673fda65d1e3c0e5b3f4468686d05a389c877bee7b10323264595c3c54677","src/regalloc/liverange.rs":"7a28454e5f70d570db439b966a01ead759b65eb65c5845f9c58bf2f230a5f2ab","src/regalloc/mod.rs":"50399d6569687a87bf1481304aca42506d946e34465e38ca8093e06485ab5fb6","src/regalloc/pressure.rs":"04738e95418f0f858885dfc45183efc3dfb59c8d2ad2fd88bbd9a73a62907730","src/regalloc/register_set.rs":"739909ac35f48619d67f161ffec30c398d6839797ebea00ba5abd4b0ad0065f0","src/regalloc/reload.rs":"0dc6620ac72545065c14fda91f37bbe7904bf8f99e578d5fe532f1ccc76b9b21","src/regalloc/safepoint.rs":"93a4f963990298a2f2d64148c72859a4a0d5d3176b404834ab743b756882bf56","src/regalloc/solver.rs":"3e133a4cd81a029cf34cc329fcaa0169ce6ce4a8642eb5b24faabc4a8a120191","src/regalloc/spilling.rs":"dff4af64409c9a1db7697423576826c3920c26c892fbdde89ee31c680d672e03","src/regalloc/virtregs.rs":"865d5cdd7a6e87c8a2e5d41f89ba9c1a95531653363fd43c19a4d80b309534d8","src/result.rs":"c10354d615f93caa446c3c8c49d6ba3af762816af470f9c4accf04315cce9753","src/scoped_hash_map.rs":"5afafb3a4039094c3a2aad1582354220d21f399aa50046e7f4a1259e1976597e","src/settings.rs":"a9bbb526efd0f88f35448d2d560cc41c2d804cca46ca1973d2be9e508c016c65","src/simple_gvn.rs":"c8feb380d4831badc59aa1e65efeafa6702711585817fe5f6b31de6b265fac24","src/simple_preopt.rs":"f54526eecc1ddc07069900bd3fbcf998abbfb594582bd700423c50ee5fba34b8","src/stack_layout.rs":"c5de271e296fc424f1a30017620bc88500369c8e553fef6e95beccb9c6640e7c","src/timing.rs":"a6808943eec68f5d3ff32132d40c07c142e6aa8073473561573a013978883e4f","src/topo_order.rs":"b01ed68a7300691f41ac434e58a5267b10a8b4a7056d65035e24aa8a6722122a","src/unreachable_code.rs":"40cc71a02887ee4065c76ce96dda0a363a8cc134ec784fe5ed1f276db76596ce","src/value_label.rs":"d3f4422bdea00f1efe7f2b35384f8e3dfa609dee5eae629721d45bedfe087e9f","src/verifier/cssa.rs":"e3e1d77b763c0ba82d3b59ab5b4667fd3152d5a08be50b58b0c82f86376bb062","src/verifier/flags.rs":"cac8ba7ed5fe621eaa425112b931423cb5f3523d580fcf0b7536deb252e96186","src/verifier/liveness.rs":"ac3413b464ee8b5aa5928bee724799b9a1e0cbbdce433c819b9d870483ed070a","src/verifier/locations.rs":"05db00e49552a1ca6cfa0e8ccf38d35778edd0ececc4f20a50b0fb81b37a8312","src/verifier/mod.rs":"8162be3e9008dd661075700285bc9ef39ea0dd152d5fd66c64cf578c214c155d","src/write.rs":"35dff9d0f5ed74779e536cbc6b1de7381cec521a0c54f6d8513041d118bbfc4b"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"3809cc2ba9d09e454815c696dd901849becd4819983b7cd74c17c08360998c2f","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"8587e8557a046dc858f7662f63f1fa54e57ff92ed87b30fbcdfce6feafda9d60","src/abi.rs":"76ee030cf0780fe63ccbf855b1161f215e3e2991cb9abe71ca9aff25e5f1dbc2","src/binemit/memorysink.rs":"da415b20c563e636bcccaafb43dbdb77d6c48f9c205b16229865abb1afa40964","src/binemit/mod.rs":"90c56d36091646bba7f0ab1b5064d68b8b0c24ece874fcf8c621830b743e9688","src/binemit/relaxation.rs":"7b1082203c688beab4d705e601ad4fde10c5bf1fec414ad1ee6993e4f6b95e01","src/binemit/shrink.rs":"5755efc978f5056a33c0ecb1bd5e08310397f54a67434ecead184fc6ee047133","src/binemit/stackmap.rs":"f7742f4daafef83a8748f6e5e10cb669eecc4fd18e02e73fdf06d56696b7efa9","src/bitset.rs":"d57a79058a31b094b4bbe9d34876a5543286df1e08b5ceadfd05a9efc5a3b1ce","src/cfg_printer.rs":"a84dee96d8c6f4775b8ba022243cf1c0bcf847c6d7ec532698cfd331655aa453","src/constant_hash.rs":"77eb898f7b0a4ae3b8165a03c25fcd23ce9c1d0cd32c793fa6cb31666ce27eb1","src/context.rs":"9c36ff1d2759997e52dd4c5db64423da46ce0cada5166aab29068a378a162f34","src/cursor.rs":"874d1c7ef6e114d6ae47e0a1f92da7c5cec2e555597558042a3b214da7bc5fe4","src/dbg.rs":"1898d94cff0975815eb348651702e95c8f2f63886501d3b7043ee75668480472","src/dce.rs":"d8ab7c0cac0416f9d75afdacc60ba02e532361ec927c3f8bd171b1a53ec8b31a","src/divconst_magic_numbers.rs":"09691389c9055bef7a0cfd5d77fbfeba4be468d05d981d4de088516a94b8b28e","src/dominator_tree.rs":"6817b893c2c5ba5f2fc4e632fb8f8b7210a9ea9862d389d5247ff94b992b0d27","src/flowgraph.rs":"c975c05949017f0b2efeff85bf82017b6a5779ed92e25f13742aeea76ca95c52","src/fx.rs":"8a5d07487906d8316a179e826fcd817a92a4860686256a6fd9d78ba47c63f330","src/ir/builder.rs":"6f111f2a65dfe27633dcec918f74b767277131a72cd94b7bec2e1ef5c4308d5b","src/ir/constant.rs":"378d02256c3e21d89b70c6b0956ef70c034a5f14c1d2aaaec1f172a38b7b2279","src/ir/dfg.rs":"8539e19a9b7548c8b2d177e9966a2306592aafa89f8bd38763bce53c41b7e95f","src/ir/entities.rs":"e6e5e857f77c59b51ea66888a1a034514dc3686fedc3ccdf453ab9855215d196","src/ir/extfunc.rs":"f26200741eb91be0d9a72a7aea194fd28f78696754ed9c26e88c8dd277ecd082","src/ir/extname.rs":"ed2c0b52cdaecc7f0ba9a894ef9fffe139e09b520e43dcd6f0c887a3d41a31ac","src/ir/function.rs":"fdbd33def70bfc49648c232d9fdb65eb8ed694a6a1a8bde1e06d6e40d4970230","src/ir/globalvalue.rs":"906d29f3d4190b811f66fc549c4e0408bdd2807eac98e33c0b3d5c2b876acc02","src/ir/heap.rs":"a59d3e5901412b53c0b53a8cdf10765ff5921de9c410ae9acea226c89827df3c","src/ir/immediates.rs":"ce0492c864c6c5dabcfb2716a09f05d6f26cbfb6bbcc8c69c70eeb9e91826ac1","src/ir/instructions.rs":"c65afa7cd6fe48ec8a7e70330e4cc50cca91981dc92eb3715d9b0a06dea20b67","src/ir/jumptable.rs":"7764abc9aa027a5a89d22059b360372bd9a19686887c5a7830f7637d6f188e1e","src/ir/layout.rs":"e2fa46073f973be1375d005bfe187d50ba353b369d6a8b424cd558d9c61ddd49","src/ir/libcall.rs":"3e540afdd1d9a68b1be0ddb983a8db39312a052aae9ba92fb2440746f69fef06","src/ir/memflags.rs":"dbcf3798ab66dc764b73fb7f139a621c54cc6bcc683f1f70a33ed7e8c3486bfd","src/ir/mod.rs":"cbe204ea9943ab5a1b4a433cccae49c97122912a48dd26e24d664ae08ae2f63b","src/ir/progpoint.rs":"49433f22bd6ff3a96ad0733ff612f3617b312e4492b6b663187141966f6aa701","src/ir/sourceloc.rs":"e1442572958b138f7637a14b662200ea9f729a513b77108be2a39745d8c2a0d5","src/ir/stackslot.rs":"a116aec3d41fcb570044584d06c97e21fc65d68b31f921ab6b5d7a2daddb614b","src/ir/table.rs":"dcc3b663a989b2b084402b08dc9a0e928dbd052e194a46a1886cc6f0cf1a5f2c","src/ir/trapcode.rs":"7098eafab9f8708124bb81507900f26316d34fa8343e465f5a677db8a415978f","src/ir/types.rs":"8cfe8028008c93c37a593e82c230f95e8674d727cce5715aa55c93e140da4ced","src/ir/valueloc.rs":"1bf764fde5ff8140fa2b59f0192086ed17e9ba7018c74719788b74fc5ca05636","src/isa/arm32/abi.rs":"74775c5f1eb95764e46815fa8b31891416a616fdd212972eb77aead43b3345a9","src/isa/arm32/binemit.rs":"eecd7296c27d2520db8e86dd462833ecf06afd33548b03ae676c02454cdd13c2","src/isa/arm32/enc_tables.rs":"e94b12af802de59484cab1124d2ac8a88d08433f6e1a476724ed0403f4b5967f","src/isa/arm32/mod.rs":"cfb590b852414c3a3757e4187976944a472a304af518b7921c3f4f750d72609e","src/isa/arm32/registers.rs":"254b568a02480f46bb4967a24a438390231014258f0c159f0a41dbafe8e66d56","src/isa/arm32/settings.rs":"2314460f885c24f9571d640f9737a8e0b7d20ca02bcda1127f878fd3891c0529","src/isa/arm64/abi.rs":"52353ed2e2133dacddaad70a876ecebb9c179c19b911ffa823b5b89d3ee7a17c","src/isa/arm64/binemit.rs":"3afbb78f6d9ae5614d908023f84b774c0493c8757ad86fd8301baf0928bb0104","src/isa/arm64/enc_tables.rs":"73fedf7da610a982e37c76e5211dbce880f77841b71c678b0dab2b9e7217cb7c","src/isa/arm64/mod.rs":"45aa2f74b323764b6334c09f65b8a27cd82dd1de3cc2d9b207b6d94e55bcbed6","src/isa/arm64/registers.rs":"308cfcfd9ff2191d7656e7350bb36e41803664eb86ae490fb4b4d3549b25b6a2","src/isa/arm64/settings.rs":"5405ce3560b7ba0705ef525c706eb9f1593e901e1767b837c012084397639042","src/isa/call_conv.rs":"56dfbf8f23a82942566d2a81deaf2147777061b3b49532b4f9fdcd3aae51aa56","src/isa/constraints.rs":"bddb5c68e56b122a53d8be215e41d22ccf8c4563630b1486e6eb31c0d3337565","src/isa/enc_tables.rs":"382e714f9500afc292c563cb66d4c963d6787e58f197b1db242db7a099c22b9a","src/isa/encoding.rs":"7ea5b4400530172f96e263561682886ea6c67e706398d44a83933ef7f0ac98a5","src/isa/mod.rs":"d32ab806081a2bf1ef06f1f9ae6f69846f333d797b6e539a364400c5d7aaeb84","src/isa/registers.rs":"004b090b7390fa07c1add81ef4a8c79bd7a6001a22cb014a4a83a9fa6ae3aeca","src/isa/riscv/abi.rs":"36557b91ad16a1344c80fbb16a62b46eac88500d76cb9ebcd4eae224dd67b2de","src/isa/riscv/binemit.rs":"264d223da311d4482ebf2f55438b665c67b163058251bc78173c76ba983a31ef","src/isa/riscv/enc_tables.rs":"8491f2082b24c7dedeb7c36cfd913bf9aeaa0a4c8fc754166e9285f4ae002f40","src/isa/riscv/mod.rs":"d7e5e1f4b8ba2a3058d1b416796f6a88522a9472816cb078b5859030f496ac44","src/isa/riscv/registers.rs":"666c2abe1a93db5f1573d1603db6c13c37f3fc877c0c93b64d1b971921bfa950","src/isa/riscv/settings.rs":"f6362769e9bc5be0c12b091e414ce924b0d2053b05b0ae88fef118cb8c68761e","src/isa/stack.rs":"5d30e2e19662ff3b3a641888bbb29640094ccd51b9a73368a056352afee46320","src/isa/x86/abi.rs":"13013f247c8e0fca46fe43568ef3186616fa469a321dee0a41fc2cc25220ec10","src/isa/x86/binemit.rs":"86622ac2971907d858d9d0a49ff9e51899db8e3f6930dc2ad2ed8c419668a603","src/isa/x86/enc_tables.rs":"b926172bbdaaf1259b0870a2e85228fb50f1274fbe16861b382a963aa00de23d","src/isa/x86/mod.rs":"6ed0ad8a7fa2bec526a99f3b1b9c9fc1cb5f62e5ea49685304e1721c85d81aae","src/isa/x86/registers.rs":"bed70bbe1f56f3ef03ea7cd1bea68eb911913cb4c8b93167e044dfc639f7f461","src/isa/x86/settings.rs":"d3e403db3507830f79bcc976c17340b57052cf1b50877fcf1a79549f2a054458","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"70a6819cbb116f07d0a09f8e5b0e2fe91145f423ad02e10225f8879ff4e61351","src/legalizer/call.rs":"be6074c64c1a00e5e81159dd94c8401fef62205b22c15e07e0c56cf922554d00","src/legalizer/globalvalue.rs":"59ab09a0faf593c7f228500b3fd3bacfc0412bdcb2864ec3621aa65adc4a5693","src/legalizer/heap.rs":"6f722a5ba720acdf19c58ba7c9820ea3a5b5017af3bda70adeeeb8b3c1408eb1","src/legalizer/libcall.rs":"875daf54ac05114e50eba801b25b2c201351e9f6c276ba0358b356498c54d1c6","src/legalizer/mod.rs":"7911a03e4229fa6ea371b714b3a50b677adbeeab749b8809bf29fe298cd9d7ff","src/legalizer/split.rs":"696d2a641f52eeb4f2a2106b0641f751f61c560e6e3cbbac544df28b203a4445","src/legalizer/table.rs":"c36d03525312e3191aba8ee00c26a87c1ea200f9a9a0370f0cc84eeacff71786","src/lib.rs":"579e060edc61558e05590ce3dd3a65b39a169e0c2b20c47a53fdee14cbbf7146","src/licm.rs":"07534926e2986c01e3b76a2faf2336f5b96411f06d93d44d74e991f76265e29d","src/loop_analysis.rs":"58fc3cc0e700f05e3131ff1b16ff975d4f32a68c790f095d8445bd300356d3c0","src/nan_canonicalization.rs":"9619bb5554791bd1be75ecd98564d6c9f5b65132bc07c5c4d8c210cd79b66f82","src/partition_slice.rs":"bc13504e7658aab565918d965a0b67e941eb572e583870571bc6dbb2b9aad272","src/postopt.rs":"d4c487f0299fb905bb5a5822e38dea6f70afa4d4577288988b5bec8660bc1ba0","src/predicates.rs":"89511e94976129136140515a7229b5d56f524e883c987296872322443d549adb","src/print_errors.rs":"3fbd77a01b5404a4bbcf2970e44299ad33948c71f4014d92026415daa8325314","src/redundant_reload_remover.rs":"3b2e49280375c9294fb7e190a8b02ef4fcef05ffcf1cb9e6e583cdc8e484bde1","src/regalloc/affinity.rs":"19cec5495c8bddc1fcc8f3c8659d527a5a3ea373ffcc130e3fbd5b462ef15930","src/regalloc/branch_splitting.rs":"50ff6a6d257a9cb35d302ed61fa45ff1be4d2ff0f695aa2cedd161bd725a598c","src/regalloc/coalescing.rs":"334820e453defd28e7aba1c2d6b5db6813bbe228c9a0607c55d1e792c3d8497d","src/regalloc/coloring.rs":"413ad9f6c1efc4775a173e8f3e8255946dbccce57c5ff2e640159f6b247e90c2","src/regalloc/context.rs":"0b3d5009c23b58cc9ccca2ece9d85dbdea52f843f52452e7813dd7a3229547d3","src/regalloc/diversion.rs":"49edbe958591acb304093e601179de7a79de0a4557748b98ddb736a865ef6a43","src/regalloc/live_value_tracker.rs":"34458e7ea99492250faf93adfef7731baed7c1db85483475a256f9b822f8b9cb","src/regalloc/liveness.rs":"1eeae58f9cf1bcf3379de7a1cba9610cd3fe42bc0668181e94cb0a37f1c9a5e2","src/regalloc/liverange.rs":"60f8c9a1707e2db1aa5dae23cc9db46689557556492f14a1b1002bcf0a71de1e","src/regalloc/mod.rs":"50399d6569687a87bf1481304aca42506d946e34465e38ca8093e06485ab5fb6","src/regalloc/pressure.rs":"04738e95418f0f858885dfc45183efc3dfb59c8d2ad2fd88bbd9a73a62907730","src/regalloc/register_set.rs":"739909ac35f48619d67f161ffec30c398d6839797ebea00ba5abd4b0ad0065f0","src/regalloc/reload.rs":"0dc6620ac72545065c14fda91f37bbe7904bf8f99e578d5fe532f1ccc76b9b21","src/regalloc/safepoint.rs":"93a4f963990298a2f2d64148c72859a4a0d5d3176b404834ab743b756882bf56","src/regalloc/solver.rs":"3e133a4cd81a029cf34cc329fcaa0169ce6ce4a8642eb5b24faabc4a8a120191","src/regalloc/spilling.rs":"6bba892c9ba7eafa7e45e5f3925f1a6a5b1023a98e3302bf11ffc65cabb3dd5f","src/regalloc/virtregs.rs":"90e6ddbeb364057a7d2b792c0534e1a3123281b0bd86c5004fe9ead311f5d82a","src/result.rs":"c10354d615f93caa446c3c8c49d6ba3af762816af470f9c4accf04315cce9753","src/scoped_hash_map.rs":"5afafb3a4039094c3a2aad1582354220d21f399aa50046e7f4a1259e1976597e","src/settings.rs":"5e342908104df9e9eca8816a01289edc6def8940e97b94ddd14d1cb77afeab31","src/simple_gvn.rs":"c8feb380d4831badc59aa1e65efeafa6702711585817fe5f6b31de6b265fac24","src/simple_preopt.rs":"f54526eecc1ddc07069900bd3fbcf998abbfb594582bd700423c50ee5fba34b8","src/stack_layout.rs":"c5de271e296fc424f1a30017620bc88500369c8e553fef6e95beccb9c6640e7c","src/timing.rs":"a6808943eec68f5d3ff32132d40c07c142e6aa8073473561573a013978883e4f","src/topo_order.rs":"674d4f482a9d68a0850d37fcf785ea64802ed30e3efce5a684d6a2c500efc515","src/unreachable_code.rs":"40cc71a02887ee4065c76ce96dda0a363a8cc134ec784fe5ed1f276db76596ce","src/value_label.rs":"10f6fd479bc3dca5a018f566620a15e190d7e3cfee9f90e918bafc7e365fe9af","src/verifier/cssa.rs":"1600586748a88843354e76e3f73a2fb837a4c6570eaf1473731e3ea77b87b43a","src/verifier/flags.rs":"2794b0165cc858e9ea2ef0437c5eb1b493754a8dd79f4f876d9eb8a533d5f427","src/verifier/liveness.rs":"97e339f9ff6aeeb304cfda5125ff6c1c693dc96421c8e330f48d4037c9d4fa82","src/verifier/locations.rs":"ed78d5675cf74901e4dbc486058f55a7dd3d21fdc8b0032a92f8a679c78440f0","src/verifier/mod.rs":"3badebb547382f612b3dd8e804f62910f6785b8020b724b7cc6fd15306b1a731","src/write.rs":"20513f9a001cf3505625f065a2098c245877a134adcd5c153257561dd8c5fcde"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-codegen/Cargo.toml b/third_party/rust/cranelift-codegen/Cargo.toml
index 2d81a660e84ee00e99440660775343071d5b44ac..eb6a1094c86dfc0554ea1b7a078dbd73612bebca 100644
--- a/third_party/rust/cranelift-codegen/Cargo.toml
+++ b/third_party/rust/cranelift-codegen/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 authors = ["The Cranelift Project Developers"]
 name = "cranelift-codegen"
-version = "0.42.0"
+version = "0.44.0"
 description = "Low-level code generator library"
 license = "Apache-2.0 WITH LLVM-exception"
 documentation = "https://cranelift.readthedocs.io/"
@@ -13,8 +13,9 @@ build = "build.rs"
 edition = "2018"
 
 [dependencies]
-cranelift-entity = { path = "../cranelift-entity", version = "0.42.0", default-features = false }
-cranelift-bforest = { path = "../cranelift-bforest", version = "0.42.0", default-features = false }
+cranelift-codegen-shared = { path = "./shared", version = "0.44.0" }
+cranelift-entity = { path = "../cranelift-entity", version = "0.44.0", default-features = false }
+cranelift-bforest = { path = "../cranelift-bforest", version = "0.44.0", default-features = false }
 failure = { version = "0.1.1", default-features = false, features = ["derive"] }
 failure_derive = { version = "0.1.1", default-features = false }
 hashmap_core = { version = "0.1.9", optional = true }
@@ -28,7 +29,7 @@ smallvec = { version = "0.6.10" }
 # accomodated in `tests`.
 
 [build-dependencies]
-cranelift-codegen-meta = { path = "meta", version = "0.42.0", default-features = false }
+cranelift-codegen-meta = { path = "meta", version = "0.44.0", default-features = false }
 
 [features]
 default = ["std"]
diff --git a/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs b/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs
index 8d0d2a3204bc7b1fb228a242502d6b4cb046458a..4051b47e191cc48bad69aa8d543fddd291309652 100644
--- a/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs
+++ b/third_party/rust/cranelift-codegen/src/binemit/stackmap.rs
@@ -3,10 +3,13 @@ use crate::ir;
 use crate::isa::TargetIsa;
 use std::vec::Vec;
 
+type Num = u32;
+const NUM_BITS: usize = std::mem::size_of::<Num>() * 8;
+
 /// Wrapper class for longer bit vectors that cannot be represented by a single BitSet.
 #[derive(Clone, Debug)]
 pub struct Stackmap {
-    bitmap: Vec<BitSet<u32>>,
+    bitmap: Vec<BitSet<Num>>,
 }
 
 impl Stackmap {
@@ -52,34 +55,32 @@ impl Stackmap {
             }
         }
 
-        Stackmap::from_vec(&vec)
+        Stackmap::from_slice(&vec)
     }
 
-    /// Create a vec of Bitsets from a vec of bools.
-    pub fn from_vec(vec: &Vec<bool>) -> Self {
-        let mut rem = vec.len();
-        let num_word = ((rem as f32) / 32.0).ceil() as usize;
+    /// Create a vec of Bitsets from a slice of bools.
+    pub fn from_slice(vec: &[bool]) -> Self {
+        let len = vec.len();
+        let num_word = len / NUM_BITS + (len % NUM_BITS != 0) as usize;
         let mut bitmap = Vec::with_capacity(num_word);
 
-        for i in 0..num_word {
+        for segment in vec.chunks(NUM_BITS) {
             let mut curr_word = 0;
-            let count = if rem > 32 { 32 } else { rem };
-            for j in 0..count {
-                if vec[i * 32 + j] {
-                    curr_word |= 1 << j;
+            for (i, set) in segment.iter().enumerate() {
+                if *set {
+                    curr_word |= 1 << i;
                 }
             }
-            bitmap.push(BitSet::<u32>(curr_word));
-            rem -= count;
+            bitmap.push(BitSet(curr_word));
         }
         Self { bitmap }
     }
 
     /// Returns a specified bit.
     pub fn get_bit(&self, bit_index: usize) -> bool {
-        assert!(bit_index < 32 * self.bitmap.len());
-        let word_index = bit_index / 32;
-        let word_offset = (bit_index % 32) as u8;
+        assert!(bit_index < NUM_BITS * self.bitmap.len());
+        let word_index = bit_index / NUM_BITS;
+        let word_offset = (bit_index % NUM_BITS) as u8;
         self.bitmap[word_index].contains(word_offset)
     }
 }
@@ -91,26 +92,26 @@ mod tests {
     #[test]
     fn stackmaps() {
         let vec: Vec<bool> = Vec::new();
-        assert!(Stackmap::from_vec(&vec).bitmap.is_empty());
+        assert!(Stackmap::from_slice(&vec).bitmap.is_empty());
 
-        let mut vec: [bool; 32] = Default::default();
+        let mut vec: [bool; NUM_BITS] = Default::default();
         let set_true_idx = [5, 7, 24, 31];
 
-        for idx in set_true_idx.iter() {
-            vec[*idx] = true;
+        for &idx in &set_true_idx {
+            vec[idx] = true;
         }
 
         let mut vec = vec.to_vec();
         assert_eq!(
-            vec![BitSet::<u32>(2164261024)],
-            Stackmap::from_vec(&vec).bitmap
+            vec![BitSet::<Num>(2164261024)],
+            Stackmap::from_slice(&vec).bitmap
         );
 
         vec.push(false);
         vec.push(true);
-        let res = Stackmap::from_vec(&vec);
+        let res = Stackmap::from_slice(&vec);
         assert_eq!(
-            vec![BitSet::<u32>(2164261024), BitSet::<u32>(2)],
+            vec![BitSet::<Num>(2164261024), BitSet::<Num>(2)],
             res.bitmap
         );
 
diff --git a/third_party/rust/cranelift-codegen/src/context.rs b/third_party/rust/cranelift-codegen/src/context.rs
index 0f4e9ad420cbee1a48afd7dc3bdcabf54f82b41c..8bbe2893de4f877dbdf210aa57382ee93b3c43c1 100644
--- a/third_party/rust/cranelift-codegen/src/context.rs
+++ b/third_party/rust/cranelift-codegen/src/context.rs
@@ -132,18 +132,18 @@ impl Context {
         self.verify_if(isa)?;
         debug!("Compiling:\n{}", self.func.display(isa));
 
+        let opt_level = isa.flags().opt_level();
+
         self.compute_cfg();
-        if isa.flags().opt_level() != OptLevel::Fastest {
+        if opt_level != OptLevel::None {
             self.preopt(isa)?;
         }
         if isa.flags().enable_nan_canonicalization() {
             self.canonicalize_nans(isa)?;
         }
         self.legalize(isa)?;
-        if isa.flags().opt_level() != OptLevel::Fastest {
+        if opt_level != OptLevel::None {
             self.postopt(isa)?;
-        }
-        if isa.flags().opt_level() == OptLevel::Best {
             self.compute_domtree();
             self.compute_loop_analysis();
             self.licm(isa)?;
@@ -151,13 +151,15 @@ impl Context {
         }
         self.compute_domtree();
         self.eliminate_unreachable_code(isa)?;
-        if isa.flags().opt_level() != OptLevel::Fastest {
+        if opt_level != OptLevel::None {
             self.dce(isa)?;
         }
         self.regalloc(isa)?;
         self.prologue_epilogue(isa)?;
-        if isa.flags().opt_level() == OptLevel::Best {
+        if opt_level == OptLevel::Speed || opt_level == OptLevel::SpeedAndSize {
             self.redundant_reload_remover(isa)?;
+        }
+        if opt_level == OptLevel::SpeedAndSize {
             self.shrink_instructions(isa)?;
         }
         let result = self.relax_branches(isa);
diff --git a/third_party/rust/cranelift-codegen/src/ir/dfg.rs b/third_party/rust/cranelift-codegen/src/ir/dfg.rs
index f4e2875952ae0bd6c0a9fca17698880617cd380c..5b3054b59d2a878303dbcceaba1bf873737b4ec1 100644
--- a/third_party/rust/cranelift-codegen/src/ir/dfg.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/dfg.rs
@@ -5,7 +5,7 @@ use crate::ir;
 use crate::ir::builder::ReplaceBuilder;
 use crate::ir::extfunc::ExtFuncData;
 use crate::ir::instructions::{BranchInfo, CallInfo, InstructionData};
-use crate::ir::{types, ConstantPool};
+use crate::ir::{types, ConstantPool, Immediate};
 use crate::ir::{
     Ebb, FuncRef, Inst, SigRef, Signature, Type, Value, ValueLabelAssignments, ValueList,
     ValueListPool,
@@ -19,6 +19,7 @@ use core::mem;
 use core::ops::{Index, IndexMut};
 use core::u16;
 use std::collections::HashMap;
+use std::vec::Vec;
 
 /// A data flow graph defines all instructions and extended basic blocks in a function as well as
 /// the data flow dependencies between them. The DFG also tracks values which can be either
@@ -70,6 +71,9 @@ pub struct DataFlowGraph {
 
     /// Constants used within the function
     pub constants: ConstantPool,
+
+    /// Stores large immediates that otherwise will not fit on InstructionData
+    pub immediates: PrimaryMap<Immediate, Vec<u8>>,
 }
 
 impl DataFlowGraph {
@@ -85,6 +89,7 @@ impl DataFlowGraph {
             ext_funcs: PrimaryMap::new(),
             values_labels: None,
             constants: ConstantPool::new(),
+            immediates: PrimaryMap::new(),
         }
     }
 
@@ -98,7 +103,8 @@ impl DataFlowGraph {
         self.signatures.clear();
         self.ext_funcs.clear();
         self.values_labels = None;
-        self.constants.clear()
+        self.constants.clear();
+        self.immediates.clear();
     }
 
     /// Get the total number of instructions created in this function, whether they are currently
diff --git a/third_party/rust/cranelift-codegen/src/ir/entities.rs b/third_party/rust/cranelift-codegen/src/ir/entities.rs
index ab78e0f3a82c06647e3a495fb09641a9b482ebb4..1f8e1fc6a231c86de2c46b1f001958891ecfd306 100644
--- a/third_party/rust/cranelift-codegen/src/ir/entities.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/entities.rs
@@ -25,7 +25,12 @@ use core::u32;
 #[cfg(feature = "enable-serde")]
 use serde::{Deserialize, Serialize};
 
-/// An opaque reference to an extended basic block in a function.
+/// An opaque reference to an [extended basic
+/// block](https://en.wikipedia.org/wiki/Extended_basic_block) in a
+/// [`Function`](super::function::Function).
+///
+/// You can get an `Ebb` using
+/// [`FunctionBuilder::create_ebb`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_ebb)
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct Ebb(u32);
 entity_impl!(Ebb, "ebb");
@@ -44,6 +49,18 @@ impl Ebb {
 }
 
 /// An opaque reference to an SSA value.
+///
+/// You can get a constant `Value` from the following
+/// [`InstBuilder`](super::InstBuilder) instructions:
+///
+/// - [`iconst`](super::InstBuilder::iconst) for integer constants
+/// - [`f32const`](super::InstBuilder::f32const) for 32-bit float constants
+/// - [`f64const`](super::InstBuilder::f64const) for 64-bit float constants
+/// - [`bconst`](super::InstBuilder::bconst) for boolean constants
+/// - [`vconst`](super::InstBuilder::vconst) for vector constants
+/// - [`null`](super::InstBuilder::null) for null reference constants
+///
+/// Any `InstBuilder` instruction that has an output will also return a `Value`.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct Value(u32);
 entity_impl!(Value, "v");
@@ -62,12 +79,34 @@ impl Value {
     }
 }
 
-/// An opaque reference to an instruction in a function.
+/// An opaque reference to an instruction in a [`Function`](super::Function).
+///
+/// Most usage of `Inst` is internal. `Inst`ructions are returned by
+/// [`InstBuilder`](super::InstBuilder) instructions that do not return a
+/// [`Value`], such as control flow and trap instructions.
+///
+/// If you look around the API, you can find many inventive uses for `Inst`,
+/// such as [annotating specific instructions with a comment][inst_comment]
+/// or [performing reflection at compile time](super::DataFlowGraph::analyze_branch)
+/// on the type of instruction.
+///
+/// [inst_comment]: https://github.com/bjorn3/rustc_codegen_cranelift/blob/0f8814fd6da3d436a90549d4bb19b94034f2b19c/src/pretty_clif.rs
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct Inst(u32);
 entity_impl!(Inst, "inst");
 
 /// An opaque reference to a stack slot.
+///
+/// Stack slots represent an address on the
+/// [call stack](https://en.wikipedia.org/wiki/Call_stack).
+///
+/// `StackSlot`s can be created with
+/// [`FunctionBuilder::create_stackslot`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_stack_slot).
+///
+/// `StackSlot`s are most often used with
+/// [`stack_addr`](super::InstBuilder::stack_addr),
+/// [`stack_load`](super::InstBuilder::stack_load), and
+/// [`stack_store`](super::InstBuilder::stack_store).
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
 pub struct StackSlot(u32);
@@ -87,6 +126,22 @@ impl StackSlot {
 }
 
 /// An opaque reference to a global value.
+///
+/// A `GlobalValue` is a [`Value`](Value) that will be live across the entire
+/// function lifetime. It can be preloaded from other global values.
+///
+/// You can create a `GlobalValue` in the following ways:
+///
+/// - When compiling to WASM, you can use it to load values from a
+/// [`VmContext`](super::GlobalValueData::VMContext) using
+/// [`FuncEnvironment::make_global`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_global).
+/// - When compiling to native code, you can use it for objects in static memory with
+/// [`Module::declare_data_in_func`](https://docs.rs/cranelift-module/*/cranelift_module/struct.Module.html#method.declare_data_in_func).
+/// - For any compilation target, it can be registered with
+/// [`FunctionBuilder::create_global_value`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_global_value).
+///
+/// `GlobalValue`s can be retrieved with
+/// [`InstBuilder:global_value`](super::InstBuilder::global_value).
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct GlobalValue(u32);
 entity_impl!(GlobalValue, "gv");
@@ -104,7 +159,11 @@ impl GlobalValue {
     }
 }
 
-/// An opaque reference to a constant
+/// An opaque reference to a constant.
+///
+/// You can store [`ConstantData`](super::ConstantData) in a
+/// [`ConstantPool`](super::ConstantPool) for efficient storage and retrieval.
+/// See [`ConstantPool::insert`](super::ConstantPool::insert).
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct Constant(u32);
 entity_impl!(Constant, "const");
@@ -122,7 +181,39 @@ impl Constant {
     }
 }
 
-/// An opaque reference to a jump table.
+/// An opaque reference to an immediate.
+///
+/// Some immediates (e.g. SIMD shuffle masks) are too large to store in the
+/// [`InstructionData`](super::instructions::InstructionData) struct and therefore must be
+/// tracked separately in [`DataFlowGraph::immediates`](super::dfg::DataFlowGraph). `Immediate`
+/// provides a way to reference values stored there.
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Immediate(u32);
+entity_impl!(Immediate, "imm");
+
+impl Immediate {
+    /// Create an immediate reference from its number.
+    ///
+    /// This method is for use by the parser.
+    pub fn with_number(n: u32) -> Option<Self> {
+        if n < u32::MAX {
+            Some(Immediate(n))
+        } else {
+            None
+        }
+    }
+}
+
+/// An opaque reference to a [jump table](https://en.wikipedia.org/wiki/Branch_table).
+///
+/// `JumpTable`s are used for indirect branching and are specialized for dense,
+/// 0-based jump offsets. If you want a jump table which doesn't start at 0,
+/// or is not contiguous, consider using a [`Switch`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.Switch.html) instead.
+///
+/// `JumpTable` are used with [`br_table`](super::InstBuilder::br_table).
+///
+/// `JumpTable`s can be created with
+/// [`create_jump_table`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_jump_table).
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
 pub struct JumpTable(u32);
@@ -141,7 +232,22 @@ impl JumpTable {
     }
 }
 
-/// A reference to an external function.
+/// An opaque reference to another [`Function`](super::Function).
+///
+/// `FuncRef`s are used for [direct](super::InstBuilder::call) function calls
+/// and by [`func_addr`](super::InstBuilder::func_addr) for use in
+/// [indirect](super::InstBuilder::call_indirect) function calls.
+///
+/// `FuncRef`s can be created with
+///
+/// - [`FunctionBuilder::import_function`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_function)
+/// for external functions
+/// - [`Module::declare_func_in_func`](https://docs.rs/cranelift-module/*/cranelift_module/struct.Module.html#method.declare_func_in_func)
+/// for functions declared elsewhere in the same native
+/// [`Module`](https://docs.rs/cranelift-module/*/cranelift_module/struct.Module.html)
+/// - [`FuncEnvironment::make_direct_func`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_direct_func)
+/// for functions declared in the same WebAssembly
+/// [`FuncEnvironment`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_direct_func)
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct FuncRef(u32);
 entity_impl!(FuncRef, "fn");
@@ -159,7 +265,18 @@ impl FuncRef {
     }
 }
 
-/// A reference to a function signature.
+/// An opaque reference to a function [`Signature`](super::Signature).
+///
+/// `SigRef`s are used to declare a function with
+/// [`FunctionBuiler::import_function`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_function)
+/// as well as to make an [indirect function call](super::InstBuilder::call_indirect).
+///
+/// `SigRef`s can be created with
+/// [`FunctionBuilder::import_signature`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.import_signature).
+///
+/// You can retrieve the [`Signature`](super::Signature) that was used to create a `SigRef` with
+/// [`FunctionBuilder::signature`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.signature) or
+/// [`func.dfg.signatures`](super::dfg::DataFlowGraph::signatures).
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct SigRef(u32);
 entity_impl!(SigRef, "sig");
@@ -177,7 +294,12 @@ impl SigRef {
     }
 }
 
-/// A reference to a heap.
+/// An opaque reference to a [heap](https://en.wikipedia.org/wiki/Memory_management#DYNAMIC).
+///
+/// Heaps are used to access dynamically allocated memory through
+/// [`heap_addr`](super::InstBuilder::heap_addr).
+///
+/// To create a heap, use [`FunctionBuilder::create_heap`](https://docs.rs/cranelift-frontend/*/cranelift_frontend/struct.FunctionBuilder.html#method.create_heap).
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Heap(u32);
 entity_impl!(Heap, "heap");
@@ -195,7 +317,13 @@ impl Heap {
     }
 }
 
-/// A reference to a table.
+/// An opaque reference to a [WebAssembly
+/// table](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables).
+///
+/// `Table`s are used to store a list of function references.
+/// They can be created with [`FuncEnvironment::make_table`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.make_table).
+/// They can be used with
+/// [`FuncEnvironment::translate_call_indirect`](https://docs.rs/cranelift-wasm/*/cranelift_wasm/trait.FuncEnvironment.html#tymethod.translate_call_indirect).
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Table(u32);
 entity_impl!(Table, "table");
@@ -213,7 +341,7 @@ impl Table {
     }
 }
 
-/// A reference to any of the entities defined in this module that can appear in CLIF IR.
+/// An opaque reference to any of the entities defined in this module that can appear in CLIF IR.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum AnyEntity {
     /// The whole function.
diff --git a/third_party/rust/cranelift-codegen/src/ir/immediates.rs b/third_party/rust/cranelift-codegen/src/ir/immediates.rs
index 2c5ee27c473ae5d740235cc800700084298608fe..408fe17cf3e39165f46db4af78130afd01dbbe14 100644
--- a/third_party/rust/cranelift-codegen/src/ir/immediates.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/immediates.rs
@@ -6,7 +6,6 @@
 
 use core::fmt::{self, Display, Formatter};
 use core::iter::FromIterator;
-use core::mem;
 use core::str::{from_utf8, FromStr};
 use core::{i32, u32};
 use std::vec::Vec;
@@ -290,13 +289,13 @@ impl FromStr for Uimm32 {
     }
 }
 
-/// A 128-bit unsigned integer immediate operand.
+/// A 128-bit immediate operand.
 ///
 /// This is used as an immediate value in SIMD instructions.
 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
-pub struct Uimm128(pub [u8; 16]);
+pub struct V128Imm(pub [u8; 16]);
 
-impl Uimm128 {
+impl V128Imm {
     /// Iterate over the bytes in the constant
     pub fn bytes(&self) -> impl Iterator<Item = &u8> {
         self.0.iter()
@@ -313,7 +312,7 @@ impl Uimm128 {
     }
 }
 
-impl Display for Uimm128 {
+impl Display for V128Imm {
     // Print a 128-bit vector in hexadecimal, e.g. 0x000102030405060708090a0b0c0d0e0f.
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         write!(f, "0x")?;
@@ -333,24 +332,24 @@ impl Display for Uimm128 {
     }
 }
 
-impl From<u64> for Uimm128 {
+impl From<u64> for V128Imm {
     fn from(x: u64) -> Self {
         let mut buffer: [u8; 16] = [0; 16]; // zero-fill
         (0..8).for_each(|byte| buffer[byte] = (x >> (byte as u64 * 8) & 0xff) as u8); // insert each byte from the u64 into v in little-endian order
-        Uimm128(buffer)
+        V128Imm(buffer)
     }
 }
 
-impl From<&[u8]> for Uimm128 {
+impl From<&[u8]> for V128Imm {
     fn from(slice: &[u8]) -> Self {
         assert_eq!(slice.len(), 16);
         let mut buffer = [0; 16];
         buffer.copy_from_slice(slice);
-        Uimm128(buffer)
+        V128Imm(buffer)
     }
 }
 
-impl FromStr for Uimm128 {
+impl FromStr for V128Imm {
     type Err = &'static str;
 
     // parse a 128-bit vector from a hexadecimal string, formatted as above
@@ -384,7 +383,7 @@ impl FromStr for Uimm128 {
                     position = position.wrapping_sub(1); // should only wrap on the last iteration
                 }
 
-                Ok(Uimm128(buffer))
+                Ok(V128Imm(buffer))
             }
         }
     }
@@ -396,7 +395,7 @@ impl FromStr for Uimm128 {
 ///  - this requires the input type (i.e. $ty) to implement ToBytes
 macro_rules! construct_uimm128_from_iterator_of {
     ( $ty:ident, $lanes:expr ) => {
-        impl FromIterator<$ty> for Uimm128 {
+        impl FromIterator<$ty> for V128Imm {
             fn from_iter<T: IntoIterator<Item = $ty>>(iter: T) -> Self {
                 let mut buffer: [u8; 16] = [0; 16];
                 iter.into_iter()
@@ -405,14 +404,14 @@ macro_rules! construct_uimm128_from_iterator_of {
                     .flat_map(|b| b)
                     .enumerate()
                     .for_each(|(i, b)| buffer[i] = b);
-                Uimm128(buffer)
+                V128Imm(buffer)
             }
         }
     };
 }
 
 /// Special case for booleans since we have to decide the bit-width based on the number of items
-impl FromIterator<bool> for Uimm128 {
+impl FromIterator<bool> for V128Imm {
     fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
         let bools = Vec::from_iter(iter);
         let count = bools.len();
@@ -425,7 +424,7 @@ impl FromIterator<bool> for Uimm128 {
             .enumerate()
             .map(|(i, &b)| (i * step, if b { 1 } else { 0 }))
             .for_each(|(i, b)| buffer[i] = b);
-        Uimm128(buffer)
+        V128Imm(buffer)
     }
 }
 
@@ -809,7 +808,7 @@ impl Ieee32 {
 
     /// Create a new `Ieee32` representing the number `x`.
     pub fn with_float(x: f32) -> Self {
-        Ieee32(unsafe { mem::transmute(x) })
+        Ieee32(x.to_bits())
     }
 
     /// Get the bitwise representation.
@@ -882,7 +881,7 @@ impl Ieee64 {
 
     /// Create a new `Ieee64` representing the number `x`.
     pub fn with_float(x: f64) -> Self {
-        Ieee64(unsafe { mem::transmute(x) })
+        Ieee64(x.to_bits())
     }
 
     /// Get the bitwise representation.
@@ -931,6 +930,7 @@ impl IntoBytes for Ieee64 {
 mod tests {
     use super::*;
     use core::fmt::Display;
+    use core::mem;
     use core::str::FromStr;
     use core::{f32, f64};
     use std::string::ToString;
@@ -1069,51 +1069,51 @@ mod tests {
 
     #[test]
     fn format_uimm128() {
-        assert_eq!(Uimm128::from(0).to_string(), "0x00");
-        assert_eq!(Uimm128::from(42).to_string(), "0x2a");
-        assert_eq!(Uimm128::from(3735928559).to_string(), "0xdeadbeef");
+        assert_eq!(V128Imm::from(0).to_string(), "0x00");
+        assert_eq!(V128Imm::from(42).to_string(), "0x2a");
+        assert_eq!(V128Imm::from(3735928559).to_string(), "0xdeadbeef");
         assert_eq!(
-            Uimm128::from(0x0102030405060708).to_string(),
+            V128Imm::from(0x0102030405060708).to_string(),
             "0x0102030405060708"
         );
     }
 
     #[test]
     fn parse_uimm128() {
-        parse_ok::<Uimm128>("0x00", "0x00");
-        parse_ok::<Uimm128>("0x00000042", "0x42");
-        parse_ok::<Uimm128>(
+        parse_ok::<V128Imm>("0x00", "0x00");
+        parse_ok::<V128Imm>("0x00000042", "0x42");
+        parse_ok::<V128Imm>(
             "0x0102030405060708090a0b0c0d0e0f00",
             "0x0102030405060708090a0b0c0d0e0f00",
         );
-        parse_ok::<Uimm128>("0x_0000_0043_21", "0x4321");
+        parse_ok::<V128Imm>("0x_0000_0043_21", "0x4321");
 
-        parse_err::<Uimm128>("", "Expected a hexadecimal string, e.g. 0x1234");
-        parse_err::<Uimm128>("0x", "Expected a hexadecimal string, e.g. 0x1234");
-        parse_err::<Uimm128>(
+        parse_err::<V128Imm>("", "Expected a hexadecimal string, e.g. 0x1234");
+        parse_err::<V128Imm>("0x", "Expected a hexadecimal string, e.g. 0x1234");
+        parse_err::<V128Imm>(
             "0x042",
             "Hexadecimal string must have an even number of digits",
         );
-        parse_err::<Uimm128>(
+        parse_err::<V128Imm>(
             "0x00000000000000000000000000000000000000000000000000",
             "Hexadecimal string has too many digits to fit in a 128-bit vector",
         );
-        parse_err::<Uimm128>("0xrstu", "Unable to parse as hexadecimal");
-        parse_err::<Uimm128>("0x__", "Hexadecimal string must have some digits");
+        parse_err::<V128Imm>("0xrstu", "Unable to parse as hexadecimal");
+        parse_err::<V128Imm>("0x__", "Hexadecimal string must have some digits");
     }
 
     #[test]
     fn uimm128_equivalence() {
         assert_eq!(
-            "0x01".parse::<Uimm128>().unwrap().0,
+            "0x01".parse::<V128Imm>().unwrap().0,
             [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
         assert_eq!(
-            Uimm128::from_iter(vec![1, 0, 0, 0]).0,
+            V128Imm::from_iter(vec![1, 0, 0, 0]).0,
             [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
         assert_eq!(
-            Uimm128::from(1).0,
+            V128Imm::from(1).0,
             [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
     }
@@ -1121,19 +1121,19 @@ mod tests {
     #[test]
     fn uimm128_endianness() {
         assert_eq!(
-            "0x42".parse::<Uimm128>().unwrap().0,
+            "0x42".parse::<V128Imm>().unwrap().0,
             [0x42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
         assert_eq!(
-            "0x00".parse::<Uimm128>().unwrap().0,
+            "0x00".parse::<V128Imm>().unwrap().0,
             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
         assert_eq!(
-            "0x12345678".parse::<Uimm128>().unwrap().0,
+            "0x12345678".parse::<V128Imm>().unwrap().0,
             [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
         assert_eq!(
-            "0x1234_5678".parse::<Uimm128>().unwrap().0,
+            "0x1234_5678".parse::<V128Imm>().unwrap().0,
             [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
         );
     }
@@ -1141,17 +1141,17 @@ mod tests {
     #[test]
     fn uimm128_from_iter() {
         assert_eq!(
-            Uimm128::from_iter(vec![4, 3, 2, 1]).0,
+            V128Imm::from_iter(vec![4, 3, 2, 1]).0,
             [4, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0]
         );
 
         assert_eq!(
-            Uimm128::from_iter(vec![false, true]).0,
+            V128Imm::from_iter(vec![false, true]).0,
             [/* false */ 0, 0, 0, 0, 0, 0, 0, 0, /* true */ 1, 0, 0, 0, 0, 0, 0, 0]
         );
 
         assert_eq!(
-            Uimm128::from_iter(vec![false, true, false, true, false, true, false, true]).0,
+            V128Imm::from_iter(vec![false, true, false, true, false, true, false, true]).0,
             [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0]
         );
 
@@ -1160,7 +1160,7 @@ mod tests {
             1 as u8, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0,
         ];
         assert_eq!(
-            Uimm128::from_iter(u8s).0,
+            V128Imm::from_iter(u8s).0,
             [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0]
         );
 
@@ -1170,7 +1170,7 @@ mod tests {
             .map(|&f| Ieee32::from(f))
             .collect();
         assert_eq!(
-            Uimm128::from_iter(ieee32s).0,
+            V128Imm::from_iter(ieee32s).0,
             [
                 /* 32.4 == */ 0x9a, 0x99, 0x01, 0x42, /* 0 == */ 0, 0, 0, 0,
                 /* 1 == */ 0, 0, 0x80, 0x3f, /* 6.6666 == */ 0xca, 0x54, 0xd5, 0x40,
diff --git a/third_party/rust/cranelift-codegen/src/ir/instructions.rs b/third_party/rust/cranelift-codegen/src/ir/instructions.rs
index 30e8d14689eabf4329870e936d3e85a705cf81b9..b3c3d0d2115d21969a8d7b9f1519ddb62ff80e94 100644
--- a/third_party/rust/cranelift-codegen/src/ir/instructions.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/instructions.rs
@@ -18,7 +18,6 @@ use crate::isa;
 
 use crate::bitset::BitSet;
 use crate::entity;
-use crate::ref_slice::{ref_slice, ref_slice_mut};
 
 /// Some instructions use an external list of argument values because there is not enough space in
 /// the 16-byte `InstructionData` struct. These value lists are stored in a memory pool in
diff --git a/third_party/rust/cranelift-codegen/src/ir/layout.rs b/third_party/rust/cranelift-codegen/src/ir/layout.rs
index 78a46285767ee1daac2e0d41cdc63dc0f114521f..632c03dc590dbe1566b59ba58852541d8305d5a0 100644
--- a/third_party/rust/cranelift-codegen/src/ir/layout.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/layout.rs
@@ -698,7 +698,7 @@ impl Layout {
 
 #[derive(Clone, Debug, Default)]
 struct InstNode {
-    // The Ebb containing this instruction, or `None` if the instruction is not yet inserted.
+    /// The Ebb containing this instruction, or `None` if the instruction is not yet inserted.
     ebb: PackedOption<Ebb>,
     prev: PackedOption<Inst>,
     next: PackedOption<Inst>,
diff --git a/third_party/rust/cranelift-codegen/src/ir/mod.rs b/third_party/rust/cranelift-codegen/src/ir/mod.rs
index 930f5d496d79dbdb5d5b4639b6bea0a6f89d3323..2ee589f6af948b331463482301bd10e1520eae9c 100644
--- a/third_party/rust/cranelift-codegen/src/ir/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/mod.rs
@@ -1,7 +1,6 @@
 //! Representation of Cranelift IR functions.
 
 mod builder;
-pub mod condcodes;
 pub mod constant;
 pub mod dfg;
 pub mod entities;
@@ -31,7 +30,8 @@ pub use crate::ir::builder::{InsertBuilder, InstBuilder, InstBuilderBase, InstIn
 pub use crate::ir::constant::{ConstantData, ConstantOffset, ConstantPool};
 pub use crate::ir::dfg::{DataFlowGraph, ValueDef};
 pub use crate::ir::entities::{
-    Constant, Ebb, FuncRef, GlobalValue, Heap, Inst, JumpTable, SigRef, StackSlot, Table, Value,
+    Constant, Ebb, FuncRef, GlobalValue, Heap, Immediate, Inst, JumpTable, SigRef, StackSlot,
+    Table, Value,
 };
 pub use crate::ir::extfunc::{
     AbiParam, ArgumentExtension, ArgumentPurpose, ExtFuncData, Signature,
@@ -54,6 +54,7 @@ pub use crate::ir::table::TableData;
 pub use crate::ir::trapcode::TrapCode;
 pub use crate::ir::types::Type;
 pub use crate::ir::valueloc::{ArgumentLoc, ValueLoc};
+pub use cranelift_codegen_shared::condcodes;
 
 use crate::binemit;
 use crate::entity::{entity_impl, PrimaryMap, SecondaryMap};
diff --git a/third_party/rust/cranelift-codegen/src/ir/trapcode.rs b/third_party/rust/cranelift-codegen/src/ir/trapcode.rs
index 273a77670cc9ef617559af47aa8064e301e735b9..5621e1d91cf3e39abc42071b05429e9720718725 100644
--- a/third_party/rust/cranelift-codegen/src/ir/trapcode.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/trapcode.rs
@@ -2,11 +2,14 @@
 
 use core::fmt::{self, Display, Formatter};
 use core::str::FromStr;
+#[cfg(feature = "enable-serde")]
+use serde::{Deserialize, Serialize};
 
 /// A trap code describing the reason for a trap.
 ///
 /// All trap instructions have an explicit trap code.
 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
 pub enum TrapCode {
     /// The current stack space was exhausted.
     ///
diff --git a/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs b/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs
index ced1b88767e9c1aad1a37ff848cd73da157c1f7a..ed5854593b651d933b3cf1f7d46e7330593a69c0 100644
--- a/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/arm32/mod.rs
@@ -126,6 +126,14 @@ impl TargetIsa for Isa {
     fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) {
         emit_function(func, binemit::emit_inst, sink, self)
     }
+
+    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
+        ir::condcodes::IntCC::UnsignedLessThan
+    }
+
+    fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
+        ir::condcodes::IntCC::UnsignedGreaterThanOrEqual
+    }
 }
 
 impl fmt::Display for Isa {
diff --git a/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs b/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs
index d787524a6a8c7ab7ba5fa6b8f43850b574fb0253..71ae93c0fe50d60ab95b6596d58685c7ad13009c 100644
--- a/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/arm64/mod.rs
@@ -114,6 +114,14 @@ impl TargetIsa for Isa {
     fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) {
         emit_function(func, binemit::emit_inst, sink, self)
     }
+
+    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
+        ir::condcodes::IntCC::UnsignedLessThan
+    }
+
+    fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
+        ir::condcodes::IntCC::UnsignedGreaterThanOrEqual
+    }
 }
 
 impl fmt::Display for Isa {
diff --git a/third_party/rust/cranelift-codegen/src/isa/mod.rs b/third_party/rust/cranelift-codegen/src/isa/mod.rs
index c36d29ce2b74249a6df6d06b2aa68767e506bb50..6457eb9ad792a93784ba686958c48f387381c647 100644
--- a/third_party/rust/cranelift-codegen/src/isa/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/mod.rs
@@ -371,4 +371,10 @@ pub trait TargetIsa: fmt::Display + Sync {
 
     /// Emit a whole function into memory.
     fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut binemit::MemoryCodeSink);
+
+    /// IntCC condition for Unsigned Addition Overflow (Carry).
+    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC;
+
+    /// IntCC condition for Unsigned Subtraction Overflow (Borrow/Carry).
+    fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC;
 }
diff --git a/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs b/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs
index 233e92a3bbfb0dc6d2702e5d1a5dce754626ca36..93ef3787f0e79914433515d4c548f425ba30ab50 100644
--- a/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/riscv/mod.rs
@@ -121,6 +121,14 @@ impl TargetIsa for Isa {
     fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) {
         emit_function(func, binemit::emit_inst, sink, self)
     }
+
+    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
+        unimplemented!()
+    }
+
+    fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
+        unimplemented!()
+    }
 }
 
 #[cfg(test)]
diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs b/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs
index a5924ed0303123c244909b87fb387e47fc6ad36a..cda6ae58074f76231988f9b0bcfd5c0c02629dd9 100644
--- a/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/binemit.rs
@@ -272,8 +272,8 @@ fn sib<CS: CodeSink + ?Sized>(scale: u8, index: RegUnit, base: RegUnit, sink: &m
 fn icc2opc(cond: IntCC) -> u16 {
     use crate::ir::condcodes::IntCC::*;
     match cond {
-        // 0x0 = Overflow.
-        // 0x1 = !Overflow.
+        Overflow => 0x0,
+        NotOverflow => 0x1,
         UnsignedLessThan => 0x2,
         UnsignedGreaterThanOrEqual => 0x3,
         Equal => 0x4,
diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
index f67d7f0b69831b3c7104de43fe43ba58ac96187e..94333116e66c7a31da9421bc71b113c2e34e7b53 100644
--- a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
@@ -406,12 +406,16 @@ fn expand_fcvt_from_uint(
     let mut pos = FuncCursor::new(func).at_inst(inst);
     pos.use_srcloc(inst);
 
-    // Conversion from unsigned 32-bit is easy on x86-64.
-    // TODO: This should be guarded by an ISA check.
-    if xty == ir::types::I32 {
-        let wide = pos.ins().uextend(ir::types::I64, x);
-        pos.func.dfg.replace(inst).fcvt_from_sint(ty, wide);
-        return;
+    // Conversion from an unsigned int smaller than 64bit is easy on x86-64.
+    match xty {
+        ir::types::I8 | ir::types::I16 | ir::types::I32 => {
+            // TODO: This should be guarded by an ISA check.
+            let wide = pos.ins().uextend(ir::types::I64, x);
+            pos.func.dfg.replace(inst).fcvt_from_sint(ty, wide);
+            return;
+        }
+        ir::types::I64 => {}
+        _ => unimplemented!(),
     }
 
     let old_ebb = pos.func.layout.pp_ebb(inst);
@@ -895,6 +899,80 @@ fn expand_fcvt_to_uint_sat(
     cfg.recompute_ebb(pos.func, done);
 }
 
+/// Convert shuffle instructions.
+fn convert_shuffle(
+    inst: ir::Inst,
+    func: &mut ir::Function,
+    _cfg: &mut ControlFlowGraph,
+    _isa: &dyn TargetIsa,
+) {
+    let mut pos = FuncCursor::new(func).at_inst(inst);
+    pos.use_srcloc(inst);
+
+    if let ir::InstructionData::Shuffle { args, mask, .. } = pos.func.dfg[inst] {
+        // A mask-building helper: in 128-bit SIMD, 0-15 indicate which lane to read from and a 1
+        // in the most significant position zeroes the lane.
+        let zero_unknown_lane_index = |b: u8| if b > 15 { 0b10000000 } else { b };
+
+        // We only have to worry about aliasing here because copies will be introduced later (in
+        // regalloc).
+        let a = pos.func.dfg.resolve_aliases(args[0]);
+        let b = pos.func.dfg.resolve_aliases(args[1]);
+        let mask = pos
+            .func
+            .dfg
+            .immediates
+            .get(mask)
+            .expect("The shuffle immediate should have been recorded before this point")
+            .clone();
+        if a == b {
+            // PSHUFB the first argument (since it is the same as the second).
+            let constructed_mask = mask
+                .iter()
+                // If the mask is greater than 15 it still may be referring to a lane in b.
+                .map(|&b| if b > 15 { b.wrapping_sub(16) } else { b })
+                .map(zero_unknown_lane_index)
+                .collect();
+            let handle = pos.func.dfg.constants.insert(constructed_mask);
+            // Move the built mask into another XMM register.
+            let a_type = pos.func.dfg.value_type(a);
+            let mask_value = pos.ins().vconst(a_type, handle);
+            // Shuffle the single incoming argument.
+            pos.func.dfg.replace(inst).x86_pshufb(a, mask_value);
+        } else {
+            // PSHUFB the first argument, placing zeroes for unused lanes.
+            let constructed_mask = mask.iter().cloned().map(zero_unknown_lane_index).collect();
+            let handle = pos.func.dfg.constants.insert(constructed_mask);
+            // Move the built mask into another XMM register.
+            let a_type = pos.func.dfg.value_type(a);
+            let mask_value = pos.ins().vconst(a_type, handle);
+            // Shuffle the first argument.
+            let shuffled_first_arg = pos.ins().x86_pshufb(a, mask_value);
+
+            // PSHUFB the second argument, placing zeroes for unused lanes.
+            let constructed_mask = mask
+                .iter()
+                .map(|b| b.wrapping_sub(16))
+                .map(zero_unknown_lane_index)
+                .collect();
+            let handle = pos.func.dfg.constants.insert(constructed_mask);
+            // Move the built mask into another XMM register.
+            let b_type = pos.func.dfg.value_type(b);
+            let mask_value = pos.ins().vconst(b_type, handle);
+            // Shuffle the second argument.
+            let shuffled_second_arg = pos.ins().x86_pshufb(b, mask_value);
+
+            // OR the vectors together to form the final shuffled value.
+            pos.func
+                .dfg
+                .replace(inst)
+                .bor(shuffled_first_arg, shuffled_second_arg);
+
+            // TODO when AVX512 is enabled we should replace this sequence with a single VPERMB
+        };
+    }
+}
+
 /// Because floats already exist in XMM registers, we can keep them there when executing a CLIF
 /// extractlane instruction
 fn convert_extractlane(
diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
index 52ab055440f74cd89f331dc6ab7beca94c9b7aeb..8136170cd70039e9df29e80fe690318d81697920 100644
--- a/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
@@ -142,6 +142,14 @@ impl TargetIsa for Isa {
         let _tt = timing::prologue_epilogue();
         abi::prologue_epilogue(func, self)
     }
+
+    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
+        ir::condcodes::IntCC::UnsignedLessThan
+    }
+
+    fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
+        ir::condcodes::IntCC::UnsignedLessThan
+    }
 }
 
 impl fmt::Display for Isa {
diff --git a/third_party/rust/cranelift-codegen/src/legalizer/heap.rs b/third_party/rust/cranelift-codegen/src/legalizer/heap.rs
index 332553e803f97291fcde141f48c10008d20f4086..a6d9d9637d34392fbf835a04bcd887e8f94ef7fd 100644
--- a/third_party/rust/cranelift-codegen/src/legalizer/heap.rs
+++ b/third_party/rust/cranelift-codegen/src/legalizer/heap.rs
@@ -83,7 +83,11 @@ fn dynamic_addr(
         // We need an overflow check for the adjusted offset.
         let access_size_val = pos.ins().iconst(offset_ty, access_size as i64);
         let (adj_offset, overflow) = pos.ins().iadd_ifcout(offset, access_size_val);
-        pos.ins().trapnz(overflow, ir::TrapCode::HeapOutOfBounds);
+        pos.ins().trapif(
+            isa.unsigned_add_overflow_condition(),
+            overflow,
+            ir::TrapCode::HeapOutOfBounds,
+        );
         oob = pos
             .ins()
             .icmp(IntCC::UnsignedGreaterThan, adj_offset, bound);
diff --git a/third_party/rust/cranelift-codegen/src/lib.rs b/third_party/rust/cranelift-codegen/src/lib.rs
index 1e97dfd6e0d17672ee848ee2159e34ef340fa8a3..73f2114561d6584a9998e4b203e6552f8126f8b7 100644
--- a/third_party/rust/cranelift-codegen/src/lib.rs
+++ b/third_party/rust/cranelift-codegen/src/lib.rs
@@ -95,7 +95,6 @@ mod partition_slice;
 mod postopt;
 mod predicates;
 mod redundant_reload_remover;
-mod ref_slice;
 mod regalloc;
 mod result;
 mod scoped_hash_map;
diff --git a/third_party/rust/cranelift-codegen/src/predicates.rs b/third_party/rust/cranelift-codegen/src/predicates.rs
index f9005461116bd82f7fdd4be1efdfde4fda21a658..16672b145b80482959a972034c7adf3206b7d64f 100644
--- a/third_party/rust/cranelift-codegen/src/predicates.rs
+++ b/third_party/rust/cranelift-codegen/src/predicates.rs
@@ -31,6 +31,18 @@ pub fn is_zero_32_bit_float<T: Into<ir::immediates::Ieee32>>(x: T) -> bool {
     x32.bits() == 0
 }
 
+/// Check that a 128-bit vector contains all zeroes.
+#[allow(dead_code)]
+pub fn is_all_zeroes_128_bit<'b, T: PartialEq<&'b [u8; 16]>>(x: T) -> bool {
+    x.eq(&&[0; 16])
+}
+
+/// Check that a 128-bit vector contains all ones.
+#[allow(dead_code)]
+pub fn is_all_ones_128_bit<'b, T: PartialEq<&'b [u8; 16]>>(x: T) -> bool {
+    x.eq(&&[0xff; 16])
+}
+
 /// Check that `x` is the same as `y`.
 #[allow(dead_code)]
 pub fn is_equal<T: Eq + Copy, O: Into<T> + Copy>(x: T, y: O) -> bool {
@@ -109,4 +121,19 @@ mod tests {
         assert!(!is_signed_int(x1, 16, 4));
         assert!(!is_signed_int(x2, 16, 4));
     }
+
+    #[test]
+    fn is_all_zeroes() {
+        assert!(is_all_zeroes_128_bit(&[0; 16]));
+        assert!(is_all_zeroes_128_bit(vec![
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        ]));
+        assert!(!is_all_zeroes_128_bit(&[1; 16]));
+    }
+
+    #[test]
+    fn is_all_ones() {
+        assert!(!is_all_ones_128_bit(&[0; 16]));
+        assert!(is_all_ones_128_bit(&[0xff; 16]));
+    }
 }
diff --git a/third_party/rust/cranelift-codegen/src/ref_slice.rs b/third_party/rust/cranelift-codegen/src/ref_slice.rs
deleted file mode 100644
index 2fad921cea31a487e0688a1c102706d8e8975933..0000000000000000000000000000000000000000
--- a/third_party/rust/cranelift-codegen/src/ref_slice.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! Functions for converting a reference into a singleton slice.
-//!
-//! See also the [`ref_slice` crate](https://crates.io/crates/ref_slice).
-//!
-//! We define the functions here to avoid external dependencies, and to ensure that they are
-//! inlined in this crate.
-//!
-//! Despite their using an unsafe block, these functions are completely safe.
-
-use core::slice;
-
-pub fn ref_slice<T>(s: &T) -> &[T] {
-    unsafe { slice::from_raw_parts(s, 1) }
-}
-
-pub fn ref_slice_mut<T>(s: &mut T) -> &mut [T] {
-    unsafe { slice::from_raw_parts_mut(s, 1) }
-}
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
index 4ba19ebbf4713aef49011d2ffead285510630db9..8a1f1d81bb622458468bf2967d3c99e779ce0126 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
@@ -199,7 +199,8 @@ impl<'a> Context<'a> {
                 if self.liveness[param].reaches_use(
                     pred_inst,
                     pred_ebb,
-                    self.liveness.context(&self.func.layout),
+                    self.liveness.forest(),
+                    &self.func.layout,
                 ) {
                     self.isolate_param(ebb, param);
                 }
@@ -240,7 +241,6 @@ impl<'a> Context<'a> {
             // `ebb`, it can never be used as an EBB argument.
             let interference = {
                 let lr = &self.liveness[arg];
-                let ctx = self.liveness.context(&self.func.layout);
 
                 // There are two ways the argument value can interfere with `ebb`:
                 //
@@ -255,7 +255,7 @@ impl<'a> Context<'a> {
                 );
 
                 // The only other possibility is that `arg` is live-in to `ebb`.
-                lr.is_livein(ebb, ctx)
+                lr.is_livein(ebb, self.liveness.forest(), &self.func.layout)
             };
 
             if interference {
@@ -435,8 +435,12 @@ impl<'a> Context<'a> {
 
             // Check for interference between `parent` and `value`. Since `parent` dominates
             // `value`, we only have to check if it overlaps the definition.
-            let ctx = self.liveness.context(&self.func.layout);
-            if self.liveness[parent.value].overlaps_def(node.def, node.ebb, ctx) {
+            if self.liveness[parent.value].overlaps_def(
+                node.def,
+                node.ebb,
+                self.liveness.forest(),
+                &self.func.layout,
+            ) {
                 // The two values are interfering, so they can't be in the same virtual register.
                 debug!("-> interference: {} overlaps def of {}", parent, value);
                 return false;
@@ -593,7 +597,6 @@ impl<'a> Context<'a> {
         // This gives us the closest dominating value def for each of the values.
         self.forest.clear();
         self.values.clear();
-        let ctx = self.liveness.context(&self.func.layout);
         for node in nodes {
             // Accumulate ordered values for the new vreg.
             if node.is_value() {
@@ -623,7 +626,12 @@ impl<'a> Context<'a> {
                 // Check if the parent value interferes with the virtual copy.
                 let inst = node.def.unwrap_inst();
                 if node.set_id != parent.set_id
-                    && self.liveness[parent.value].reaches_use(inst, node.ebb, ctx)
+                    && self.liveness[parent.value].reaches_use(
+                        inst,
+                        node.ebb,
+                        self.liveness.forest(),
+                        &self.func.layout,
+                    )
                 {
                     debug!(
                         " - interference: {} overlaps vcopy at {}:{}",
@@ -647,7 +655,12 @@ impl<'a> Context<'a> {
             // Both node and parent are values, so check for interference.
             debug_assert!(node.is_value() && parent.is_value());
             if node.set_id != parent.set_id
-                && self.liveness[parent.value].overlaps_def(node.def, node.ebb, ctx)
+                && self.liveness[parent.value].overlaps_def(
+                    node.def,
+                    node.ebb,
+                    self.liveness.forest(),
+                    &self.func.layout,
+                )
             {
                 // The two values are interfering.
                 debug!(" - interference: {} overlaps def of {}", parent, node.value);
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs b/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs
index 1e69c342a91218b3d836b16f29699843cba33771..23a546a479fd6b52e22e37a55eade6f34a0feb09 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/coloring.rs
@@ -54,7 +54,7 @@ use crate::regalloc::affinity::Affinity;
 use crate::regalloc::diversion::RegDiversions;
 use crate::regalloc::live_value_tracker::{LiveValue, LiveValueTracker};
 use crate::regalloc::liveness::Liveness;
-use crate::regalloc::liverange::{LiveRange, LiveRangeContext};
+use crate::regalloc::liverange::{LiveRange, LiveRangeForest};
 use crate::regalloc::register_set::RegisterSet;
 use crate::regalloc::solver::{Solver, SolverError};
 use crate::timing;
@@ -461,7 +461,7 @@ impl<'a> Context<'a> {
                     "Can't handle EBB arguments: {}",
                     self.cur.display_inst(inst)
                 );
-                self.undivert_regs(|lr, _| !lr.is_local());
+                self.undivert_regs(|lr, _, _| !lr.is_local());
             }
         }
 
@@ -725,8 +725,13 @@ impl<'a> Context<'a> {
                         // This code runs after calling `solver.inputs_done()` so we must identify
                         // the new variable as killed or live-through. Always special-case the
                         // pinned register as a through variable.
-                        let ctx = self.liveness.context(&self.cur.func.layout);
-                        if self.liveness[value].killed_at(inst, ctx.order.pp_ebb(inst), ctx) {
+                        let layout = &self.cur.func.layout;
+                        if self.liveness[value].killed_at(
+                            inst,
+                            layout.pp_ebb(inst),
+                            self.liveness.forest(),
+                            layout,
+                        ) {
                             self.solver.add_killed_var(value, op.regclass, cur_reg);
                         } else {
                             self.solver.add_through_var(value, op.regclass, cur_reg);
@@ -755,7 +760,7 @@ impl<'a> Context<'a> {
         //
         // Values with a global live range that are not live in to `dest` could appear as branch
         // arguments, so they can't always be un-diverted.
-        self.undivert_regs(|lr, ctx| lr.is_livein(dest, ctx));
+        self.undivert_regs(|lr, forest, layout| lr.is_livein(dest, forest, layout));
 
         // Now handle the EBB arguments.
         let br_args = self.cur.func.dfg.inst_variable_args(inst);
@@ -825,14 +830,14 @@ impl<'a> Context<'a> {
     /// are reallocated to their global register assignments.
     fn undivert_regs<Pred>(&mut self, mut pred: Pred)
     where
-        Pred: FnMut(&LiveRange, LiveRangeContext<Layout>) -> bool,
+        Pred: FnMut(&LiveRange, &LiveRangeForest, &Layout) -> bool,
     {
         for (&value, rdiv) in self.divert.iter() {
             let lr = self
                 .liveness
                 .get(value)
                 .expect("Missing live range for diverted register");
-            if pred(lr, self.liveness.context(&self.cur.func.layout)) {
+            if pred(lr, self.liveness.forest(), &self.cur.func.layout) {
                 if let Affinity::Reg(rci) = lr.affinity {
                     let rc = self.reginfo.rc(rci);
                     // Stack diversions should not be possible here. They only live transiently
@@ -1080,20 +1085,21 @@ impl<'a> Context<'a> {
         use crate::ir::instructions::BranchInfo::*;
 
         let inst = self.cur.current_inst().expect("Not on an instruction");
-        let ctx = self.liveness.context(&self.cur.func.layout);
+        let layout = &self.cur.func.layout;
+        let forest = self.liveness.forest();
         match self.cur.func.dfg.analyze_branch(inst) {
             NotABranch => false,
             SingleDest(ebb, _) => {
                 let lr = &self.liveness[value];
-                lr.is_livein(ebb, ctx)
+                lr.is_livein(ebb, forest, layout)
             }
             Table(jt, ebb) => {
                 let lr = &self.liveness[value];
                 !lr.is_local()
-                    && (ebb.map_or(false, |ebb| lr.is_livein(ebb, ctx))
+                    && (ebb.map_or(false, |ebb| lr.is_livein(ebb, forest, layout))
                         || self.cur.func.jump_tables[jt]
                             .iter()
-                            .any(|ebb| lr.is_livein(*ebb, ctx)))
+                            .any(|ebb| lr.is_livein(*ebb, forest, layout)))
             }
         }
     }
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs b/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs
index 1b08862e37b25505821aac7b01b1f65749169ba9..adfe56c410ecd0702ec0c864311cf99ba7a2d756 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/live_value_tracker.rs
@@ -191,7 +191,6 @@ impl LiveValueTracker {
                 .idom_sets
                 .get(&idom)
                 .expect("No stored live set for dominator");
-            let ctx = liveness.context(layout);
             // Get just the values that are live-in to `ebb`.
             for &value in idom_live_list.as_slice(&self.idom_pool) {
                 let lr = liveness
@@ -199,7 +198,7 @@ impl LiveValueTracker {
                     .expect("Immediate dominator value has no live range");
 
                 // Check if this value is live-in here.
-                if let Some(endpoint) = lr.livein_local_end(ebb, ctx) {
+                if let Some(endpoint) = lr.livein_local_end(ebb, liveness.forest(), layout) {
                     self.live.push(value, endpoint, lr);
                 }
             }
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs b/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs
index 7b31aedd541ab9874b46293bc43306933c3eda9b..1ace6bf6d15116349410bdb752464dd2d1967204 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/liveness.rs
@@ -181,7 +181,7 @@ use crate::ir::dfg::ValueDef;
 use crate::ir::{Ebb, Function, Inst, Layout, ProgramPoint, Value};
 use crate::isa::{EncInfo, OperandConstraint, TargetIsa};
 use crate::regalloc::affinity::Affinity;
-use crate::regalloc::liverange::{LiveRange, LiveRangeContext, LiveRangeForest};
+use crate::regalloc::liverange::{LiveRange, LiveRangeForest};
 use crate::timing;
 use core::mem;
 use core::ops::Index;
@@ -314,16 +314,16 @@ impl Liveness {
         }
     }
 
+    /// Current forest storage.
+    pub fn forest(&self) -> &LiveRangeForest {
+        &self.forest
+    }
+
     /// Current live ranges.
     pub fn ranges(&self) -> &LiveRangeSet {
         &self.ranges
     }
 
-    /// Get a context needed for working with a `LiveRange`.
-    pub fn context<'a>(&'a self, layout: &'a Layout) -> LiveRangeContext<'a, Layout> {
-        LiveRangeContext::new(layout, &self.forest)
-    }
-
     /// Clear all data structures in this liveness analysis.
     pub fn clear(&mut self) {
         self.ranges.clear();
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs b/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs
index 5629ea40ec2f94e9a62fd26f31471c1738484a8d..fb8fcc5fffbb0387e36da274fabbeddd35c30134 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/liverange.rs
@@ -58,8 +58,16 @@
 //!
 //! # Implementation notes
 //!
-//! A few notes about the implementation of this data structure. This should not concern someone
-//! only looking to use the public interface.
+//! A few notes about the implementation of the live intervals field `liveins`. This should not
+//! concern someone only looking to use the public interface.
+//!
+//! ## Current representation
+//!
+//! Our current implementation uses a B-tree map with the necessary interface for an efficient
+//! implementation of coalescing, implemented as a generic data-structure bforest::Map.
+//!
+//! A `BTreeMap<Ebb, Inst>` could have been used for the live-in intervals, but it doesn't provide
+//! the necessary API to make coalescing easy, nor does it optimize for our types' sizes.
 //!
 //! ## EBB ordering
 //!
@@ -99,13 +107,6 @@
 //! It is more complicated to work with, though, so it is probably not worth it. The performance
 //! benefits of switching to a numerical EBB order only appears if the binary search is doing
 //! EBB-EBB comparisons.
-//!
-//! ## B-tree representation
-//!
-//! A `BTreeMap<Ebb, Inst>` could also be used for the live-in intervals. It looks like the
-//! standard library B-tree doesn't provide the necessary interface for an efficient implementation
-//! of coalescing, so we would need to roll our own.
-//!
 
 use crate::bforest;
 use crate::entity::SparseMapValue;
@@ -141,13 +142,13 @@ use core::marker::PhantomData;
 /// Inserting new instructions in the layout is safe, but removing instructions is not. Besides the
 /// instructions using or defining their value, `LiveRange` structs can contain references to
 /// branch and jump instructions.
-pub type LiveRange = GenLiveRange<Layout>;
+pub type LiveRange = GenericLiveRange<Layout>;
 
 /// Generic live range implementation.
 ///
 /// The intended generic parameter is `PO=Layout`, but tests are simpler with a mock order.
 /// Use `LiveRange` instead of using this generic directly.
-pub struct GenLiveRange<PO: ProgramOrder> {
+pub struct GenericLiveRange<PO: ProgramOrder> {
     /// The value described by this live range.
     /// This member can't be modified in case the live range is stored in a `SparseMap`.
     value: Value,
@@ -178,32 +179,6 @@ pub struct GenLiveRange<PO: ProgramOrder> {
     po: PhantomData<*const PO>,
 }
 
-/// Context information needed to query a `LiveRange`.
-pub struct LiveRangeContext<'a, PO: 'a + ProgramOrder> {
-    /// Ordering of EBBs.
-    pub order: &'a PO,
-    /// Memory pool.
-    pub forest: &'a bforest::MapForest<Ebb, Inst>,
-}
-
-impl<'a, PO: ProgramOrder> LiveRangeContext<'a, PO> {
-    /// Make a new context.
-    pub fn new(order: &'a PO, forest: &'a bforest::MapForest<Ebb, Inst>) -> Self {
-        Self { order, forest }
-    }
-}
-
-impl<'a, PO: ProgramOrder> Clone for LiveRangeContext<'a, PO> {
-    fn clone(&self) -> Self {
-        LiveRangeContext {
-            order: self.order,
-            forest: self.forest,
-        }
-    }
-}
-
-impl<'a, PO: ProgramOrder> Copy for LiveRangeContext<'a, PO> {}
-
 /// Forest of B-trees used for storing live ranges.
 pub type LiveRangeForest = bforest::MapForest<Ebb, Inst>;
 
@@ -215,7 +190,23 @@ impl<'a, PO: ProgramOrder> bforest::Comparator<Ebb> for Cmp<'a, PO> {
     }
 }
 
-impl<PO: ProgramOrder> GenLiveRange<PO> {
+/// A simple helper macro to make comparisons more natural to read.
+macro_rules! cmp {
+    ($order:ident, $a:ident > $b:expr) => {
+        $order.cmp($a, $b) == Ordering::Greater
+    };
+    ($order:ident, $a:ident >= $b:expr) => {
+        $order.cmp($a, $b) != Ordering::Less
+    };
+    ($order:ident, $a:ident < $b:expr) => {
+        $order.cmp($a, $b) == Ordering::Less
+    };
+    ($order:ident, $a:ident <= $b:expr) => {
+        $order.cmp($a, $b) != Ordering::Greater
+    };
+}
+
+impl<PO: ProgramOrder> GenericLiveRange<PO> {
     /// Create a new live range for `value` defined at `def`.
     ///
     /// The live range will be created as dead, but it can be extended with `extend_in_ebb()`.
@@ -252,15 +243,13 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
         //
         // We're assuming here that `to` never precedes `def_begin` in the same EBB, but we can't
         // check it without a method for getting `to`'s EBB.
-        if order.cmp(ebb, self.def_end) != Ordering::Greater
-            && order.cmp(to, self.def_begin) != Ordering::Less
-        {
+        if cmp!(order, ebb <= self.def_end) && cmp!(order, to >= self.def_begin) {
             let to_pp = to.into();
             debug_assert_ne!(
                 to_pp, self.def_begin,
                 "Can't use value in the defining instruction."
             );
-            if order.cmp(to, self.def_end) == Ordering::Greater {
+            if cmp!(order, to > self.def_end) {
                 self.def_end = to_pp;
             }
             return false;
@@ -274,7 +263,7 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
         if let Some(end) = c.goto(ebb) {
             // There's an interval beginning at `ebb`. See if it extends.
             first_time_livein = false;
-            if order.cmp(end, to) == Ordering::Less {
+            if cmp!(order, end < to) {
                 *c.value_mut().unwrap() = to;
             } else {
                 return first_time_livein;
@@ -282,10 +271,10 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
         } else if let Some((_, end)) = c.prev() {
             // There's no interval beginning at `ebb`, but we could still be live-in at `ebb` with
             // a coalesced interval that begins before and ends after.
-            if order.cmp(end, ebb) == Ordering::Greater {
+            if cmp!(order, end > ebb) {
                 // Yep, the previous interval overlaps `ebb`.
                 first_time_livein = false;
-                if order.cmp(end, to) == Ordering::Less {
+                if cmp!(order, end < to) {
                     *c.value_mut().unwrap() = to;
                 } else {
                     return first_time_livein;
@@ -306,7 +295,7 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
             c.insert(ebb, to);
         }
 
-        // Now `c` to left pointing at an interval that ends in `to`.
+        // Now `c` is left pointing at an interval that ends in `to`.
         debug_assert_eq!(c.value(), Some(to));
 
         // See if it can be coalesced with the following interval.
@@ -370,13 +359,13 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
     /// If the live range is live through all of `ebb`, the terminator of `ebb` is a correct
     /// answer, but it is also possible that an even later program point is returned. So don't
     /// depend on the returned `Inst` to belong to `ebb`.
-    pub fn livein_local_end(&self, ebb: Ebb, ctx: LiveRangeContext<PO>) -> Option<Inst> {
-        let cmp = Cmp(ctx.order);
+    pub fn livein_local_end(&self, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> Option<Inst> {
+        let cmp = Cmp(order);
         self.liveins
-            .get_or_less(ebb, ctx.forest, &cmp)
+            .get_or_less(ebb, forest, &cmp)
             .and_then(|(_, inst)| {
                 // We have an entry that ends at `inst`.
-                if ctx.order.cmp(inst, ebb) == Ordering::Greater {
+                if cmp!(order, inst > ebb) {
                     Some(inst)
                 } else {
                     None
@@ -387,16 +376,16 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
     /// Is this value live-in to `ebb`?
     ///
     /// An EBB argument is not considered to be live in.
-    pub fn is_livein(&self, ebb: Ebb, ctx: LiveRangeContext<PO>) -> bool {
-        self.livein_local_end(ebb, ctx).is_some()
+    pub fn is_livein(&self, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> bool {
+        self.livein_local_end(ebb, forest, order).is_some()
     }
 
     /// Get all the live-in intervals.
     ///
     /// Note that the intervals are stored in a compressed form so each entry may span multiple
     /// EBBs where the value is live in.
-    pub fn liveins<'a>(&'a self, ctx: LiveRangeContext<'a, PO>) -> bforest::MapIter<'a, Ebb, Inst> {
-        self.liveins.iter(ctx.forest)
+    pub fn liveins<'a>(&'a self, forest: &'a LiveRangeForest) -> bforest::MapIter<'a, Ebb, Inst> {
+        self.liveins.iter(forest)
     }
 
     /// Check if this live range overlaps a definition in `ebb`.
@@ -404,7 +393,8 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
         &self,
         def: ExpandedProgramPoint,
         ebb: Ebb,
-        ctx: LiveRangeContext<PO>,
+        forest: &LiveRangeForest,
+        order: &PO,
     ) -> bool {
         // Two defs at the same program point always overlap, even if one is dead.
         if def == self.def_begin.into() {
@@ -412,43 +402,40 @@ impl<PO: ProgramOrder> GenLiveRange<PO> {
         }
 
         // Check for an overlap with the local range.
-        if ctx.order.cmp(def, self.def_begin) != Ordering::Less
-            && ctx.order.cmp(def, self.def_end) == Ordering::Less
-        {
+        if cmp!(order, def >= self.def_begin) && cmp!(order, def < self.def_end) {
             return true;
         }
 
         // Check for an overlap with a live-in range.
-        match self.livein_local_end(ebb, ctx) {
-            Some(inst) => ctx.order.cmp(def, inst) == Ordering::Less,
+        match self.livein_local_end(ebb, forest, order) {
+            Some(inst) => cmp!(order, def < inst),
             None => false,
         }
     }
 
     /// Check if this live range reaches a use at `user` in `ebb`.
-    pub fn reaches_use(&self, user: Inst, ebb: Ebb, ctx: LiveRangeContext<PO>) -> bool {
+    pub fn reaches_use(&self, user: Inst, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> bool {
         // Check for an overlap with the local range.
-        if ctx.order.cmp(user, self.def_begin) == Ordering::Greater
-            && ctx.order.cmp(user, self.def_end) != Ordering::Greater
-        {
+        if cmp!(order, user > self.def_begin) && cmp!(order, user <= self.def_end) {
             return true;
         }
 
         // Check for an overlap with a live-in range.
-        match self.livein_local_end(ebb, ctx) {
-            Some(inst) => ctx.order.cmp(user, inst) != Ordering::Greater,
+        match self.livein_local_end(ebb, forest, order) {
+            Some(inst) => cmp!(order, user <= inst),
             None => false,
         }
     }
 
     /// Check if this live range is killed at `user` in `ebb`.
-    pub fn killed_at(&self, user: Inst, ebb: Ebb, ctx: LiveRangeContext<PO>) -> bool {
-        self.def_local_end() == user.into() || self.livein_local_end(ebb, ctx) == Some(user)
+    pub fn killed_at(&self, user: Inst, ebb: Ebb, forest: &LiveRangeForest, order: &PO) -> bool {
+        self.def_local_end() == user.into()
+            || self.livein_local_end(ebb, forest, order) == Some(user)
     }
 }
 
 /// Allow a `LiveRange` to be stored in a `SparseMap` indexed by values.
-impl<PO: ProgramOrder> SparseMapValue<Value> for GenLiveRange<PO> {
+impl<PO: ProgramOrder> SparseMapValue<Value> for GenericLiveRange<PO> {
     fn key(&self) -> Value {
         self.value
     }
@@ -456,7 +443,7 @@ impl<PO: ProgramOrder> SparseMapValue<Value> for GenLiveRange<PO> {
 
 #[cfg(test)]
 mod tests {
-    use super::{GenLiveRange, LiveRangeContext};
+    use super::GenericLiveRange;
     use crate::bforest;
     use crate::entity::EntityRef;
     use crate::ir::{Ebb, Inst, Value};
@@ -509,7 +496,11 @@ mod tests {
         }
 
         // Validate the live range invariants.
-        fn validate(&self, lr: &GenLiveRange<ProgOrder>, forest: &bforest::MapForest<Ebb, Inst>) {
+        fn validate(
+            &self,
+            lr: &GenericLiveRange<ProgOrder>,
+            forest: &bforest::MapForest<Ebb, Inst>,
+        ) {
             // The def interval must cover a single EBB.
             let def_ebb = self.pp_ebb(lr.def_begin);
             assert_eq!(def_ebb, self.pp_ebb(lr.def_end));
@@ -553,36 +544,34 @@ mod tests {
         let i1 = Inst::new(1);
         let i2 = Inst::new(2);
         let e2 = Ebb::new(2);
-        let lr = GenLiveRange::new(v0, i1.into(), Default::default());
+        let lr = GenericLiveRange::new(v0, i1.into(), Default::default());
         let forest = &bforest::MapForest::new();
-        let ctx = LiveRangeContext::new(PO, forest);
         assert!(lr.is_dead());
         assert!(lr.is_local());
         assert_eq!(lr.def(), i1.into());
         assert_eq!(lr.def_local_end(), i1.into());
-        assert_eq!(lr.livein_local_end(e2, ctx), None);
-        PO.validate(&lr, ctx.forest);
+        assert_eq!(lr.livein_local_end(e2, forest, PO), None);
+        PO.validate(&lr, forest);
 
         // A dead live range overlaps its own def program point.
-        assert!(lr.overlaps_def(i1.into(), e0, ctx));
-        assert!(!lr.overlaps_def(i2.into(), e0, ctx));
-        assert!(!lr.overlaps_def(e0.into(), e0, ctx));
+        assert!(lr.overlaps_def(i1.into(), e0, forest, PO));
+        assert!(!lr.overlaps_def(i2.into(), e0, forest, PO));
+        assert!(!lr.overlaps_def(e0.into(), e0, forest, PO));
     }
 
     #[test]
     fn dead_arg_range() {
         let v0 = Value::new(0);
         let e2 = Ebb::new(2);
-        let lr = GenLiveRange::new(v0, e2.into(), Default::default());
+        let lr = GenericLiveRange::new(v0, e2.into(), Default::default());
         let forest = &bforest::MapForest::new();
-        let ctx = LiveRangeContext::new(PO, forest);
         assert!(lr.is_dead());
         assert!(lr.is_local());
         assert_eq!(lr.def(), e2.into());
         assert_eq!(lr.def_local_end(), e2.into());
         // The def interval of an EBB argument does not count as live-in.
-        assert_eq!(lr.livein_local_end(e2, ctx), None);
-        PO.validate(&lr, ctx.forest);
+        assert_eq!(lr.livein_local_end(e2, forest, PO), None);
+        PO.validate(&lr, forest);
     }
 
     #[test]
@@ -592,7 +581,7 @@ mod tests {
         let i11 = Inst::new(11);
         let i12 = Inst::new(12);
         let i13 = Inst::new(13);
-        let mut lr = GenLiveRange::new(v0, i11.into(), Default::default());
+        let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default());
         let forest = &mut bforest::MapForest::new();
 
         assert_eq!(lr.extend_in_ebb(e10, i13, PO, forest), false);
@@ -616,7 +605,7 @@ mod tests {
         let i11 = Inst::new(11);
         let i12 = Inst::new(12);
         let i13 = Inst::new(13);
-        let mut lr = GenLiveRange::new(v0, e10.into(), Default::default());
+        let mut lr = GenericLiveRange::new(v0, e10.into(), Default::default());
         let forest = &mut bforest::MapForest::new();
 
         // Extending a dead EBB argument in its own block should not indicate that a live-in
@@ -651,7 +640,7 @@ mod tests {
         let i21 = Inst::new(21);
         let i22 = Inst::new(22);
         let i23 = Inst::new(23);
-        let mut lr = GenLiveRange::new(v0, i11.into(), Default::default());
+        let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default());
         let forest = &mut bforest::MapForest::new();
 
         assert_eq!(lr.extend_in_ebb(e10, i12, PO, forest), false);
@@ -659,25 +648,16 @@ mod tests {
         // Adding a live-in interval.
         assert_eq!(lr.extend_in_ebb(e20, i22, PO, forest), true);
         PO.validate(&lr, forest);
-        assert_eq!(
-            lr.livein_local_end(e20, LiveRangeContext::new(PO, forest)),
-            Some(i22)
-        );
+        assert_eq!(lr.livein_local_end(e20, forest, PO), Some(i22));
 
         // Non-extending the live-in.
         assert_eq!(lr.extend_in_ebb(e20, i21, PO, forest), false);
-        assert_eq!(
-            lr.livein_local_end(e20, LiveRangeContext::new(PO, forest)),
-            Some(i22)
-        );
+        assert_eq!(lr.livein_local_end(e20, forest, PO), Some(i22));
 
         // Extending the existing live-in.
         assert_eq!(lr.extend_in_ebb(e20, i23, PO, forest), false);
         PO.validate(&lr, forest);
-        assert_eq!(
-            lr.livein_local_end(e20, LiveRangeContext::new(PO, forest)),
-            Some(i23)
-        );
+        assert_eq!(lr.livein_local_end(e20, forest, PO), Some(i23));
     }
 
     #[test]
@@ -690,56 +670,33 @@ mod tests {
         let i31 = Inst::new(31);
         let e40 = Ebb::new(40);
         let i41 = Inst::new(41);
-        let mut lr = GenLiveRange::new(v0, i11.into(), Default::default());
+        let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default());
         let forest = &mut bforest::MapForest::new();
 
         assert_eq!(lr.extend_in_ebb(e30, i31, PO, forest), true);
-        assert_eq!(
-            lr.liveins(LiveRangeContext::new(PO, forest))
-                .collect::<Vec<_>>(),
-            [(e30, i31)]
-        );
+        assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e30, i31)]);
 
         // Coalesce to previous
         assert_eq!(lr.extend_in_ebb(e40, i41, PO, forest), true);
-        assert_eq!(
-            lr.liveins(LiveRangeContext::new(PO, forest))
-                .collect::<Vec<_>>(),
-            [(e30, i41)]
-        );
+        assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e30, i41)]);
 
         // Coalesce to next
         assert_eq!(lr.extend_in_ebb(e20, i21, PO, forest), true);
-        assert_eq!(
-            lr.liveins(LiveRangeContext::new(PO, forest))
-                .collect::<Vec<_>>(),
-            [(e20, i41)]
-        );
+        assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e20, i41)]);
 
-        let mut lr = GenLiveRange::new(v0, i11.into(), Default::default());
+        let mut lr = GenericLiveRange::new(v0, i11.into(), Default::default());
 
         assert_eq!(lr.extend_in_ebb(e40, i41, PO, forest), true);
-        assert_eq!(
-            lr.liveins(LiveRangeContext::new(PO, forest))
-                .collect::<Vec<_>>(),
-            [(e40, i41)]
-        );
+        assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e40, i41)]);
 
         assert_eq!(lr.extend_in_ebb(e20, i21, PO, forest), true);
         assert_eq!(
-            lr.liveins(LiveRangeContext::new(PO, forest))
-                .collect::<Vec<_>>(),
+            lr.liveins(forest).collect::<Vec<_>>(),
             [(e20, i21), (e40, i41)]
         );
 
         // Coalesce to previous and next
         assert_eq!(lr.extend_in_ebb(e30, i31, PO, forest), true);
-        assert_eq!(
-            lr.liveins(LiveRangeContext::new(PO, forest))
-                .collect::<Vec<_>>(),
-            [(e20, i41)]
-        );
+        assert_eq!(lr.liveins(forest).collect::<Vec<_>>(), [(e20, i41)]);
     }
-
-    // TODO: Add more tests that exercise the binary search algorithm.
 }
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
index f45dd41c94e5d894a64a84195aeffd33f8b19f45..0012ad01d85837eb12615c897bc4ddc9984cd31c 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
@@ -319,17 +319,18 @@ impl<'a> Context<'a> {
             for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() {
                 let mut reguse = RegUse::new(arg, idx, op.regclass.into());
                 let lr = &self.liveness[arg];
-                let ctx = self.liveness.context(&self.cur.func.layout);
                 match op.kind {
                     ConstraintKind::Stack => continue,
                     ConstraintKind::FixedReg(_) => reguse.fixed = true,
                     ConstraintKind::Tied(_) => {
                         // A tied operand must kill the used value.
-                        reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                        reguse.tied =
+                            !lr.killed_at(inst, ebb, self.liveness.forest(), &self.cur.func.layout);
                     }
                     ConstraintKind::FixedTied(_) => {
                         reguse.fixed = true;
-                        reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                        reguse.tied =
+                            !lr.killed_at(inst, ebb, self.liveness.forest(), &self.cur.func.layout);
                     }
                     ConstraintKind::Reg => {}
                 }
diff --git a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
index fc267c3f610d36af20aabb2112cb9bd5f4042917..df2b4804905ad4725967a1b7ebdb1158f3c838f2 100644
--- a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
@@ -18,9 +18,9 @@ use crate::entity::{EntityList, ListPool};
 use crate::entity::{Keys, PrimaryMap, SecondaryMap};
 use crate::ir::{Function, Value};
 use crate::packed_option::PackedOption;
-use crate::ref_slice::ref_slice;
 use core::cmp::Ordering;
 use core::fmt;
+use core::slice;
 use smallvec::SmallVec;
 use std::vec::Vec;
 
@@ -104,7 +104,7 @@ impl VirtRegs {
         'a: 'b,
     {
         self.get(*value)
-            .map_or_else(|| ref_slice(value), |vr| self.values(vr))
+            .map_or_else(|| slice::from_ref(value), |vr| self.values(vr))
     }
 
     /// Check if `a` and `b` belong to the same congruence class.
diff --git a/third_party/rust/cranelift-codegen/src/settings.rs b/third_party/rust/cranelift-codegen/src/settings.rs
index 99d3647cbdeb778f79ef409346b4c2b73c35ebd9..c310972170f27fa884a3ab6a9a6be74677d963e7 100644
--- a/third_party/rust/cranelift-codegen/src/settings.rs
+++ b/third_party/rust/cranelift-codegen/src/settings.rs
@@ -14,10 +14,10 @@
 //! use cranelift_codegen::settings::{self, Configurable};
 //!
 //! let mut b = settings::builder();
-//! b.set("opt_level", "fastest");
+//! b.set("opt_level", "speed_and_size");
 //!
 //! let f = settings::Flags::new(b);
-//! assert_eq!(f.opt_level(), settings::OptLevel::Fastest);
+//! assert_eq!(f.opt_level(), settings::OptLevel::SpeedAndSize);
 //! ```
 
 use crate::constant_hash::{probe, simple_hash};
@@ -378,7 +378,7 @@ mod tests {
         assert_eq!(
             f.to_string(),
             "[shared]\n\
-             opt_level = \"default\"\n\
+             opt_level = \"none\"\n\
              libcall_call_conv = \"isa_default\"\n\
              baldrdash_prologue_words = 0\n\
              probestack_size_log2 = 12\n\
@@ -398,7 +398,7 @@ mod tests {
              probestack_func_adjusts_sp = false\n\
              jump_tables_enabled = true\n"
         );
-        assert_eq!(f.opt_level(), super::OptLevel::Default);
+        assert_eq!(f.opt_level(), super::OptLevel::None);
         assert_eq!(f.enable_simd(), false);
         assert_eq!(f.baldrdash_prologue_words(), 0);
     }
@@ -428,13 +428,15 @@ mod tests {
         );
         assert_eq!(
             b.set("opt_level", "true"),
-            Err(BadValue("any among default, best, fastest".to_string()))
+            Err(BadValue(
+                "any among none, speed, speed_and_size".to_string()
+            ))
         );
-        assert_eq!(b.set("opt_level", "best"), Ok(()));
+        assert_eq!(b.set("opt_level", "speed"), Ok(()));
         assert_eq!(b.set("enable_simd", "0"), Ok(()));
 
         let f = Flags::new(b);
         assert_eq!(f.enable_simd(), false);
-        assert_eq!(f.opt_level(), super::OptLevel::Best);
+        assert_eq!(f.opt_level(), super::OptLevel::Speed);
     }
 }
diff --git a/third_party/rust/cranelift-codegen/src/topo_order.rs b/third_party/rust/cranelift-codegen/src/topo_order.rs
index 7dcec7274b062eeeccef953338ccd25165d3ed4c..8824f4cc0a8dc298e3ffed56a63a5b13c1eeb461 100644
--- a/third_party/rust/cranelift-codegen/src/topo_order.rs
+++ b/third_party/rust/cranelift-codegen/src/topo_order.rs
@@ -1,7 +1,7 @@
 //! Topological order of EBBs, according to the dominator tree.
 
 use crate::dominator_tree::DominatorTree;
-use crate::entity::SparseSet;
+use crate::entity::EntitySet;
 use crate::ir::{Ebb, Layout};
 use std::vec::Vec;
 
@@ -19,7 +19,7 @@ pub struct TopoOrder {
     next: usize,
 
     /// Set of visited EBBs.
-    visited: SparseSet<Ebb>,
+    visited: EntitySet<Ebb>,
 
     /// Stack of EBBs to be visited next, already in `visited`.
     stack: Vec<Ebb>,
@@ -31,7 +31,7 @@ impl TopoOrder {
         Self {
             preferred: Vec::new(),
             next: 0,
-            visited: SparseSet::new(),
+            visited: EntitySet::new(),
             stack: Vec::new(),
         }
     }
@@ -64,6 +64,7 @@ impl TopoOrder {
     /// - All EBBs in the `preferred` iterator given to `reset` will be returned.
     /// - All dominators are visited before the EBB returned.
     pub fn next(&mut self, layout: &Layout, domtree: &DominatorTree) -> Option<Ebb> {
+        self.visited.resize(layout.ebb_capacity());
         // Any entries in `stack` should be returned immediately. They have already been added to
         // `visited`.
         while self.stack.is_empty() {
@@ -73,7 +74,7 @@ impl TopoOrder {
                     // We have the next EBB in the preferred order.
                     self.next += 1;
                     // Push it along with any non-visited dominators.
-                    while self.visited.insert(ebb).is_none() {
+                    while self.visited.insert(ebb) {
                         self.stack.push(ebb);
                         match domtree.idom(ebb) {
                             Some(idom) => ebb = layout.inst_ebb(idom).expect("idom not in layout"),
diff --git a/third_party/rust/cranelift-codegen/src/value_label.rs b/third_party/rust/cranelift-codegen/src/value_label.rs
index 2bd3bdc13df703aed743e494f9de470ef05d82ab..d3d1e0672caa88b3902801c5ac8a929954cf0754 100644
--- a/third_party/rust/cranelift-codegen/src/value_label.rs
+++ b/third_party/rust/cranelift-codegen/src/value_label.rs
@@ -96,8 +96,8 @@ where
     ebbs.sort_by_key(|ebb| func.offsets[*ebb]); // Ensure inst offsets always increase
     let encinfo = isa.encoding_info();
     let values_locations = &func.locations;
-    let liveness_context = regalloc.liveness().context(&func.layout);
     let liveness_ranges = regalloc.liveness().ranges();
+    let liveness_forest = regalloc.liveness().forest();
 
     let mut ranges = HashMap::new();
     let mut add_range = |label, range: (u32, u32), loc: ValueLoc| {
@@ -126,7 +126,10 @@ where
             // Remove killed values.
             tracked_values.retain(|(x, label, start_offset, last_loc)| {
                 let range = liveness_ranges.get(*x);
-                if range.expect("value").killed_at(inst, ebb, liveness_context) {
+                if range
+                    .expect("value")
+                    .killed_at(inst, ebb, &liveness_forest, &func.layout)
+                {
                     add_range(*label, (*start_offset, end_offset), *last_loc);
                     return false;
                 }
@@ -173,7 +176,7 @@ where
                 // Ignore dead/inactive Values.
                 let range = liveness_ranges.get(*v);
                 match range {
-                    Some(r) => r.reaches_use(inst, ebb, liveness_context),
+                    Some(r) => r.reaches_use(inst, ebb, &liveness_forest, &func.layout),
                     None => false,
                 }
             });
diff --git a/third_party/rust/cranelift-codegen/src/verifier/cssa.rs b/third_party/rust/cranelift-codegen/src/verifier/cssa.rs
index 6014ff803043ac4622d5c092b5145f64bc0520a4..3878f096d19cebbf03aee7b060790a6ce8590a09 100644
--- a/third_party/rust/cranelift-codegen/src/verifier/cssa.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/cssa.rs
@@ -118,8 +118,12 @@ impl<'a> CssaVerifier<'a> {
                     if self.preorder.dominates(prev_ebb, def_ebb)
                         && self.domtree.dominates(prev_def, def, &self.func.layout)
                     {
-                        let ctx = self.liveness.context(&self.func.layout);
-                        if self.liveness[prev_val].overlaps_def(def, def_ebb, ctx) {
+                        if self.liveness[prev_val].overlaps_def(
+                            def,
+                            def_ebb,
+                            self.liveness.forest(),
+                            &self.func.layout,
+                        ) {
                             return fatal!(
                                 errors,
                                 val,
diff --git a/third_party/rust/cranelift-codegen/src/verifier/flags.rs b/third_party/rust/cranelift-codegen/src/verifier/flags.rs
index 43a235def5309bad2095c8dfe2169f99a5731a29..d39b6e048796556be094bf433511baf6e649c45e 100644
--- a/third_party/rust/cranelift-codegen/src/verifier/flags.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/flags.rs
@@ -1,6 +1,6 @@
 //! Verify CPU flags values.
 
-use crate::entity::{SecondaryMap, SparseSet};
+use crate::entity::{EntitySet, SecondaryMap};
 use crate::flowgraph::{BasicBlock, ControlFlowGraph};
 use crate::ir;
 use crate::ir::instructions::BranchInfo;
@@ -50,7 +50,7 @@ impl<'a> FlagsVerifier<'a> {
     fn check(&mut self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
         // List of EBBs that need to be processed. EBBs may be re-added to this list when we detect
         // that one of their successor blocks needs a live-in flags value.
-        let mut worklist = SparseSet::new();
+        let mut worklist = EntitySet::with_capacity(self.func.layout.ebb_capacity());
         for ebb in self.func.layout.ebbs() {
             worklist.insert(ebb);
         }
diff --git a/third_party/rust/cranelift-codegen/src/verifier/liveness.rs b/third_party/rust/cranelift-codegen/src/verifier/liveness.rs
index c396a4680355ac8459b5ce2070a74024a93bd4ee..37b59c154dde1c93862629ccca30fd6f9b74c231 100644
--- a/third_party/rust/cranelift-codegen/src/verifier/liveness.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/liveness.rs
@@ -2,13 +2,12 @@
 
 use crate::flowgraph::{BasicBlock, ControlFlowGraph};
 use crate::ir::entities::AnyEntity;
-use crate::ir::{ExpandedProgramPoint, Function, Inst, ProgramOrder, ProgramPoint, Value};
+use crate::ir::{ExpandedProgramPoint, Function, ProgramPoint, Value};
 use crate::isa::TargetIsa;
 use crate::regalloc::liveness::Liveness;
 use crate::regalloc::liverange::LiveRange;
 use crate::timing;
 use crate::verifier::{VerifierErrors, VerifierStepResult};
-use core::cmp::Ordering;
 
 /// Verify liveness information for `func`.
 ///
@@ -106,7 +105,9 @@ impl<'a> LivenessVerifier<'a> {
                         Some(lr) => lr,
                         None => return fatal!(errors, inst, "{} has no live range", val),
                     };
-                    if !self.live_at_use(lr, inst) {
+
+                    debug_assert!(self.func.layout.inst_ebb(inst).unwrap() == ebb);
+                    if !lr.reaches_use(inst, ebb, self.liveness.forest(), &self.func.layout) {
                         return fatal!(errors, inst, "{} is not live at this use", val);
                     }
 
@@ -126,24 +127,6 @@ impl<'a> LivenessVerifier<'a> {
         Ok(())
     }
 
-    /// Is `lr` live at the use `inst`?
-    fn live_at_use(&self, lr: &LiveRange, inst: Inst) -> bool {
-        let ctx = self.liveness.context(&self.func.layout);
-
-        // Check if `inst` is in the def range, not including the def itself.
-        if ctx.order.cmp(lr.def(), inst) == Ordering::Less
-            && ctx.order.cmp(inst, lr.def_local_end()) != Ordering::Greater
-        {
-            return true;
-        }
-
-        // Otherwise see if `inst` is in one of the live-in ranges.
-        match lr.livein_local_end(ctx.order.inst_ebb(inst).unwrap(), ctx) {
-            Some(end) => ctx.order.cmp(inst, end) != Ordering::Greater,
-            None => false,
-        }
-    }
-
     /// Check the integrity of the live range `lr`.
     fn check_lr(
         &self,
@@ -196,7 +179,7 @@ impl<'a> LivenessVerifier<'a> {
         }
 
         // Now check the live-in intervals against the CFG.
-        for (mut ebb, end) in lr.liveins(self.liveness.context(l)) {
+        for (mut ebb, end) in lr.liveins(self.liveness.forest()) {
             if !l.is_ebb_inserted(ebb) {
                 return fatal!(
                     errors,
@@ -223,8 +206,8 @@ impl<'a> LivenessVerifier<'a> {
             // Check all the EBBs in the interval independently.
             loop {
                 // If `val` is live-in at `ebb`, it must be live at all the predecessors.
-                for BasicBlock { inst: pred, .. } in self.cfg.pred_iter(ebb) {
-                    if !self.live_at_use(lr, pred) {
+                for BasicBlock { inst: pred, ebb } in self.cfg.pred_iter(ebb) {
+                    if !lr.reaches_use(pred, ebb, self.liveness.forest(), &self.func.layout) {
                         return fatal!(
                             errors,
                             pred,
diff --git a/third_party/rust/cranelift-codegen/src/verifier/locations.rs b/third_party/rust/cranelift-codegen/src/verifier/locations.rs
index cf17ae13de669fdd8694d3a2de7c98f1401852a4..d32bb7e4bdc49dee0053db4456401d43832ba03e 100644
--- a/third_party/rust/cranelift-codegen/src/verifier/locations.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/locations.rs
@@ -334,10 +334,10 @@ impl<'a> LocationVerifier<'a> {
                     let lr = &liveness[value];
                     if is_after_branch && unique_predecessor {
                         // Forward diversions based on the targeted branch.
-                        if !lr.is_livein(ebb, liveness.context(&self.func.layout)) {
+                        if !lr.is_livein(ebb, liveness.forest(), &self.func.layout) {
                             val_to_remove.push(value)
                         }
-                    } else if lr.is_livein(ebb, liveness.context(&self.func.layout)) {
+                    } else if lr.is_livein(ebb, liveness.forest(), &self.func.layout) {
                         return fatal!(
                             errors,
                             inst,
@@ -359,7 +359,7 @@ impl<'a> LocationVerifier<'a> {
                 for (&value, d) in divert.iter() {
                     let lr = &liveness[value];
                     if let Some(ebb) = ebb {
-                        if lr.is_livein(ebb, liveness.context(&self.func.layout)) {
+                        if lr.is_livein(ebb, liveness.forest(), &self.func.layout) {
                             return fatal!(
                                 errors,
                                 inst,
@@ -371,7 +371,7 @@ impl<'a> LocationVerifier<'a> {
                         }
                     }
                     for ebb in self.func.jump_tables[jt].iter() {
-                        if lr.is_livein(*ebb, liveness.context(&self.func.layout)) {
+                        if lr.is_livein(*ebb, liveness.forest(), &self.func.layout) {
                             return fatal!(
                                 errors,
                                 inst,
diff --git a/third_party/rust/cranelift-codegen/src/verifier/mod.rs b/third_party/rust/cranelift-codegen/src/verifier/mod.rs
index 5bc10d9d92eb3344d91d2d6927347b639abf31f6..02cc3f0c526da3c233263048eec521be4343c4b7 100644
--- a/third_party/rust/cranelift-codegen/src/verifier/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/mod.rs
@@ -696,10 +696,16 @@ impl<'a> Verifier<'a> {
                 }
             }
 
+            Unary {
+                opcode: Opcode::Bitcast,
+                arg,
+            } => {
+                self.verify_bitcast(inst, arg, errors)?;
+            }
+
             // Exhaustive list so we can't forget to add new formats
             Unary { .. }
             | UnaryImm { .. }
-            | UnaryImm128 { .. }
             | UnaryIeee32 { .. }
             | UnaryIeee64 { .. }
             | UnaryBool { .. }
@@ -708,6 +714,8 @@ impl<'a> Verifier<'a> {
             | Ternary { .. }
             | InsertLane { .. }
             | ExtractLane { .. }
+            | UnaryConst { .. }
+            | Shuffle { .. }
             | IntCompare { .. }
             | IntCompareImm { .. }
             | IntCond { .. }
@@ -981,6 +989,28 @@ impl<'a> Verifier<'a> {
         }
     }
 
+    fn verify_bitcast(
+        &self,
+        inst: Inst,
+        arg: Value,
+        errors: &mut VerifierErrors,
+    ) -> VerifierStepResult<()> {
+        let typ = self.func.dfg.ctrl_typevar(inst);
+        let value_type = self.func.dfg.value_type(arg);
+
+        if typ.lane_bits() < value_type.lane_bits() {
+            fatal!(
+                errors,
+                inst,
+                "The bitcast argument {} doesn't fit in a type of {} bits",
+                arg,
+                typ.lane_bits()
+            )
+        } else {
+            Ok(())
+        }
+    }
+
     fn domtree_integrity(
         &self,
         domtree: &DominatorTree,
@@ -1746,21 +1776,47 @@ impl<'a> Verifier<'a> {
     ) -> VerifierStepResult<()> {
         let inst_data = &self.func.dfg[inst];
 
-        // If this is some sort of a store instruction, get the memflags, else, just return.
-        let memflags = match *inst_data {
+        match *inst_data {
             ir::InstructionData::Store { flags, .. }
-            | ir::InstructionData::StoreComplex { flags, .. } => flags,
-            _ => return Ok(()),
-        };
-
-        if memflags.readonly() {
-            fatal!(
-                errors,
-                inst,
-                "A store instruction cannot have the `readonly` MemFlag"
-            )
-        } else {
-            Ok(())
+            | ir::InstructionData::StoreComplex { flags, .. } => {
+                if flags.readonly() {
+                    fatal!(
+                        errors,
+                        inst,
+                        "A store instruction cannot have the `readonly` MemFlag"
+                    )
+                } else {
+                    Ok(())
+                }
+            }
+            ir::InstructionData::ExtractLane {
+                opcode: ir::instructions::Opcode::Extractlane,
+                lane,
+                arg,
+                ..
+            }
+            | ir::InstructionData::InsertLane {
+                opcode: ir::instructions::Opcode::Insertlane,
+                lane,
+                args: [arg, _],
+                ..
+            } => {
+                // We must be specific about the opcodes above because other instructions are using
+                // the ExtractLane/InsertLane formats.
+                let ty = self.func.dfg.value_type(arg);
+                if u16::from(lane) >= ty.lane_count() {
+                    fatal!(
+                        errors,
+                        inst,
+                        "The lane {} does not index into the type {}",
+                        lane,
+                        ty
+                    )
+                } else {
+                    Ok(())
+                }
+            }
+            _ => Ok(()),
         }
     }
 
@@ -1782,12 +1838,51 @@ impl<'a> Verifier<'a> {
         Ok(())
     }
 
+    fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+        self.func
+            .signature
+            .params
+            .iter()
+            .enumerate()
+            .filter(|(_, &param)| param.value_type == types::INVALID)
+            .for_each(|(i, _)| {
+                report!(
+                    errors,
+                    AnyEntity::Function,
+                    "Parameter at position {} has an invalid type",
+                    i
+                );
+            });
+
+        self.func
+            .signature
+            .returns
+            .iter()
+            .enumerate()
+            .filter(|(_, &ret)| ret.value_type == types::INVALID)
+            .for_each(|(i, _)| {
+                report!(
+                    errors,
+                    AnyEntity::Function,
+                    "Return value at position {} has an invalid type",
+                    i
+                )
+            });
+
+        if errors.has_error() {
+            Err(())
+        } else {
+            Ok(())
+        }
+    }
+
     pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
         self.verify_global_values(errors)?;
         self.verify_heaps(errors)?;
         self.verify_tables(errors)?;
         self.verify_jump_tables(errors)?;
         self.typecheck_entry_block_params(errors)?;
+        self.typecheck_function_signature(errors)?;
 
         for ebb in self.func.layout.ebbs() {
             for inst in self.func.layout.ebb_insts(ebb) {
@@ -1814,7 +1909,7 @@ mod tests {
     use super::{Verifier, VerifierError, VerifierErrors};
     use crate::entity::EntityList;
     use crate::ir::instructions::{InstructionData, Opcode};
-    use crate::ir::Function;
+    use crate::ir::{types, AbiParam, Function};
     use crate::settings;
 
     macro_rules! assert_err_with_msg {
@@ -1873,4 +1968,30 @@ mod tests {
 
         assert_err_with_msg!(errors, "instruction format");
     }
+
+    #[test]
+    fn test_function_invalid_param() {
+        let mut func = Function::new();
+        func.signature.params.push(AbiParam::new(types::INVALID));
+
+        let mut errors = VerifierErrors::default();
+        let flags = &settings::Flags::new(settings::builder());
+        let verifier = Verifier::new(&func, flags.into());
+
+        let _ = verifier.typecheck_function_signature(&mut errors);
+        assert_err_with_msg!(errors, "Parameter at position 0 has an invalid type");
+    }
+
+    #[test]
+    fn test_function_invalid_return_value() {
+        let mut func = Function::new();
+        func.signature.returns.push(AbiParam::new(types::INVALID));
+
+        let mut errors = VerifierErrors::default();
+        let flags = &settings::Flags::new(settings::builder());
+        let verifier = Verifier::new(&func, flags.into());
+
+        let _ = verifier.typecheck_function_signature(&mut errors);
+        assert_err_with_msg!(errors, "Return value at position 0 has an invalid type");
+    }
 }
diff --git a/third_party/rust/cranelift-codegen/src/write.rs b/third_party/rust/cranelift-codegen/src/write.rs
index 4b616cab2ebb7123f738d7e7c8fa8c52730a2f4a..8d974c1ec54cba18f45a5193331feca06111b4df 100644
--- a/third_party/rust/cranelift-codegen/src/write.rs
+++ b/third_party/rust/cranelift-codegen/src/write.rs
@@ -5,7 +5,7 @@
 
 use crate::entity::SecondaryMap;
 use crate::ir::entities::AnyEntity;
-use crate::ir::immediates::Uimm128;
+use crate::ir::immediates::V128Imm;
 use crate::ir::{
     DataFlowGraph, DisplayFunctionAnnotations, Ebb, Function, Inst, SigRef, Type, Value, ValueDef,
     ValueLoc,
@@ -488,11 +488,6 @@ pub fn write_operands(
     match dfg[inst] {
         Unary { arg, .. } => write!(w, " {}", arg),
         UnaryImm { imm, .. } => write!(w, " {}", imm),
-        UnaryImm128 { imm, .. } => {
-            let data = dfg.constants.get(imm);
-            let uimm128 = Uimm128::from(&data[..]);
-            write!(w, " {}", uimm128)
-        }
         UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
         UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
         UnaryBool { imm, .. } => write!(w, " {}", imm),
@@ -510,6 +505,20 @@ pub fn write_operands(
         NullAry { .. } => write!(w, " "),
         InsertLane { lane, args, .. } => write!(w, " {}, {}, {}", args[0], lane, args[1]),
         ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane),
+        UnaryConst {
+            constant_handle, ..
+        } => {
+            let data = dfg.constants.get(constant_handle);
+            let v128 = V128Imm::from(&data[..]);
+            write!(w, " {}", v128)
+        }
+        Shuffle { mask, args, .. } => {
+            let data = dfg.immediates.get(mask).expect(
+                "Expected the shuffle mask to already be inserted into the immediates table",
+            );
+            let v128 = V128Imm::from(&data[..]);
+            write!(w, " {}, {}, {}", args[0], args[1], v128)
+        }
         IntCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
         IntCompareImm { cond, arg, imm, .. } => write!(w, " {} {}, {}", cond, arg, imm),
         IntCond { cond, arg, .. } => write!(w, " {} {}", cond, arg),
diff --git a/third_party/rust/cranelift-entity/.cargo-checksum.json b/third_party/rust/cranelift-entity/.cargo-checksum.json
index b2f67d3a17f733f4690308a89a6f51b35767049f..898fbb1bd08b6593543e16abaf38dfa0ea8b0bbb 100644
--- a/third_party/rust/cranelift-entity/.cargo-checksum.json
+++ b/third_party/rust/cranelift-entity/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"6625897aa38b637e103d905200be02306f4efd8fb06681d69ecf005468a965cb","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"c47e858b6a46f8b5f584ca7f83c466e0fa616bbed9cb28622c53d4c1faf197c4","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"7aa57f77ae010ceabbff08700eca020030ec8ca16342db1f7e7390d186b3c156","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"8237b5c473fd219dc606efd7c989ec5216e4ae62c6cbb2857fbe11593c42aae9","src/set.rs":"97b860818c9577546201271f7ca457a5784c2e4447b68202a274f7fe75e937f2","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"a355d658ab113a09938162676fde122551e54bd86be0699e3e763a0074b3c73f","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/boxed_slice.rs":"687428ee0442013c0d5962dd78d0964830233bc4cb19aa530d30da0f1dc437a9","src/iter.rs":"4a4d3309fe9aad14fd7702f02459f4277b4ddb50dba700e58dcc75665ffebfb3","src/keys.rs":"b8c2fba26dee15bf3d1880bb2b41e8d66fe1428d242ee6d9fd30ee94bbd0407d","src/lib.rs":"c47e858b6a46f8b5f584ca7f83c466e0fa616bbed9cb28622c53d4c1faf197c4","src/list.rs":"fc3decc81bcef92e106aae53e586a0ef21d70916fa53a48f7b813c5da44b8dc2","src/map.rs":"7aa57f77ae010ceabbff08700eca020030ec8ca16342db1f7e7390d186b3c156","src/packed_option.rs":"9d47f5b8302ee685c096817e376144e363507d1c77ef562d3ae4dbddae568195","src/primary.rs":"8237b5c473fd219dc606efd7c989ec5216e4ae62c6cbb2857fbe11593c42aae9","src/set.rs":"eeb3b67030083aa6dd35c0ea7c50130d1cf6693ce302f902928440d5807d5472","src/sparse.rs":"cf345a81d69a5dddaed4778b6aaaf06c70da2c1fd4cd21e366ed6ca5906ffdab"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-entity/Cargo.toml b/third_party/rust/cranelift-entity/Cargo.toml
index 22b34d33d77df4cb8b789575903039ba17add429..65b9bc7aaae985d7e39716365ca45eea04cafd9b 100644
--- a/third_party/rust/cranelift-entity/Cargo.toml
+++ b/third_party/rust/cranelift-entity/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 authors = ["The Cranelift Project Developers"]
 name = "cranelift-entity"
-version = "0.42.0"
+version = "0.44.0"
 description = "Data structures using entity references as mapping keys"
 license = "Apache-2.0 WITH LLVM-exception"
 documentation = "https://cranelift.readthedocs.io/"
diff --git a/third_party/rust/cranelift-entity/src/set.rs b/third_party/rust/cranelift-entity/src/set.rs
index a4759a17128fde1d9e244eb39a4208fd9201ed5b..fa74ba453fc1245fb74b1d3dfc810420e6e52712 100644
--- a/third_party/rust/cranelift-entity/src/set.rs
+++ b/third_party/rust/cranelift-entity/src/set.rs
@@ -33,6 +33,14 @@ where
         }
     }
 
+    /// Creates a new empty set with the specified capacity.
+    pub fn with_capacity(capacity: usize) -> Self {
+        Self {
+            elems: Vec::with_capacity((capacity + 7) / 8),
+            ..Self::new()
+        }
+    }
+
     /// Get the element at `k` if it exists.
     pub fn contains(&self, k: K) -> bool {
         let index = k.index();
@@ -45,9 +53,11 @@ where
 
     /// Is this set completely empty?
     pub fn is_empty(&self) -> bool {
-        // Note that this implementation will become incorrect should it ever become possible
-        // to remove elements from an `EntitySet`.
-        self.len == 0
+        if self.len != 0 {
+            false
+        } else {
+            self.elems.iter().all(|&e| e == 0)
+        }
     }
 
     /// Returns the cardinality of the set.  More precisely, it returns the number of calls to
@@ -93,6 +103,34 @@ where
         self.elems[index / 8] |= 1 << (index % 8);
         result
     }
+
+    /// Removes and returns the entity from the set if it exists.
+    pub fn pop(&mut self) -> Option<K> {
+        if self.len == 0 {
+            return None;
+        }
+
+        // Clear the last known entity in the list.
+        let last_index = self.len - 1;
+        self.elems[last_index / 8] &= !(1 << (last_index % 8));
+
+        // Set the length to the next last stored entity or zero if we pop'ed
+        // the last entity.
+        self.len = self
+            .elems
+            .iter()
+            .enumerate()
+            .rev()
+            .find(|(_, &byte)| byte != 0)
+            // Map `i` from byte index to bit level index.
+            // `(i + 1) * 8` = Last bit in byte.
+            // `last - byte.leading_zeros()` = last set bit in byte.
+            // `as usize` won't ever truncate as the potential range is `0..=8`.
+            .map(|(i, byte)| ((i + 1) * 8) - byte.leading_zeros() as usize)
+            .unwrap_or(0);
+
+        Some(K::new(last_index))
+    }
 }
 
 #[cfg(test)]
@@ -101,7 +139,7 @@ mod tests {
     use core::u32;
 
     // `EntityRef` impl for testing.
-    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
     struct E(u32);
 
     impl EntityRef for E {
@@ -159,4 +197,51 @@ mod tests {
         m.clear();
         assert!(m.is_empty());
     }
+
+    #[test]
+    fn pop_ordered() {
+        let r0 = E(0);
+        let r1 = E(1);
+        let r2 = E(2);
+        let mut m = EntitySet::new();
+        m.insert(r0);
+        m.insert(r1);
+        m.insert(r2);
+
+        assert_eq!(r2, m.pop().unwrap());
+        assert_eq!(r1, m.pop().unwrap());
+        assert_eq!(r0, m.pop().unwrap());
+        assert!(m.pop().is_none());
+        assert!(m.pop().is_none());
+    }
+
+    #[test]
+    fn pop_unordered() {
+        let mut ebbs = [
+            E(0),
+            E(1),
+            E(6),
+            E(7),
+            E(5),
+            E(9),
+            E(10),
+            E(2),
+            E(3),
+            E(11),
+            E(12),
+        ];
+
+        let mut m = EntitySet::new();
+        for &ebb in &ebbs {
+            m.insert(ebb);
+        }
+        assert_eq!(m.len, 13);
+        ebbs.sort();
+
+        for &ebb in ebbs.iter().rev() {
+            assert_eq!(ebb, m.pop().unwrap());
+        }
+
+        assert!(m.is_empty());
+    }
 }
diff --git a/third_party/rust/cranelift-frontend/.cargo-checksum.json b/third_party/rust/cranelift-frontend/.cargo-checksum.json
index 8b9cdc8ba2ac7d5513f67468e4898200af305299..f8d531fc58aff87b7a803b45f0679eb4add142bb 100644
--- a/third_party/rust/cranelift-frontend/.cargo-checksum.json
+++ b/third_party/rust/cranelift-frontend/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"d3ad74a39dc6d5efeb4c02171789e53f50b2ecbe34d4bd6dcfc7856b52e50be5","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"3d306290ac5fa2f42cb97c5bae00b9baeefcbf20a911b1c3cd90ddcaaefe2bfe","src/lib.rs":"0e75d619694313f8f44d648ecffe18197844906aba7a1e3b8bb179c9c2389aa6","src/ssa.rs":"ca882f303e0ac8a269e77e511d657115fcb2bf739315dea43ee7828921048512","src/switch.rs":"5c540b9f0e5b805b9962c0079fec722fa63ad68d93fae1986fbc65e9cf15d16a","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"d664b9c245e2c8985efb57a604bd937b945549a3725d25f9e3825567dfb7946e","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"3d306290ac5fa2f42cb97c5bae00b9baeefcbf20a911b1c3cd90ddcaaefe2bfe","src/lib.rs":"0e75d619694313f8f44d648ecffe18197844906aba7a1e3b8bb179c9c2389aa6","src/ssa.rs":"ca882f303e0ac8a269e77e511d657115fcb2bf739315dea43ee7828921048512","src/switch.rs":"5c540b9f0e5b805b9962c0079fec722fa63ad68d93fae1986fbc65e9cf15d16a","src/variable.rs":"f082efaa4b2d3c5eb48f6344149408074e1e15cb581f7a63f549313c7a1037be"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-frontend/Cargo.toml b/third_party/rust/cranelift-frontend/Cargo.toml
index 3cd888220165e636b57e3c9dc1076450da9d6473..e30bde657ed9f428143036362d1f597d4c7de088 100644
--- a/third_party/rust/cranelift-frontend/Cargo.toml
+++ b/third_party/rust/cranelift-frontend/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 authors = ["The Cranelift Project Developers"]
 name = "cranelift-frontend"
-version = "0.42.0"
+version = "0.44.0"
 description = "Cranelift IR builder helper"
 license = "Apache-2.0 WITH LLVM-exception"
 documentation = "https://cranelift.readthedocs.io/"
@@ -11,7 +11,7 @@ readme = "README.md"
 edition = "2018"
 
 [dependencies]
-cranelift-codegen = { path = "../cranelift-codegen", version = "0.42.0", default-features = false }
+cranelift-codegen = { path = "../cranelift-codegen", version = "0.44.0", default-features = false }
 target-lexicon = "0.8.1"
 log = { version = "0.4.6", default-features = false }
 hashmap_core = { version = "0.1.9", optional = true }
diff --git a/third_party/rust/cranelift-wasm/.cargo-checksum.json b/third_party/rust/cranelift-wasm/.cargo-checksum.json
index ee7a481209ab56aa1854439ed48a6c5a878291ee..d633e598b287d73fcb01745b0f825a9165f81448 100644
--- a/third_party/rust/cranelift-wasm/.cargo-checksum.json
+++ b/third_party/rust/cranelift-wasm/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"3a4cfc0e561c29c298b550e6681a10a8bd99d5d33503604f9cb422c4f52831d3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"cb28478d7fc02ad68e82e52a80524a81db50463da982b23ce03abe1e7b50560f","src/environ/dummy.rs":"848079947623af4227935cfc980a8dfad03d314e9fa7408ee8a520a1043b68c8","src/environ/mod.rs":"b046f5344a1017357c1ee9d661d2193e0247327df293436fa1381a0f45f80584","src/environ/spec.rs":"d3363a0989ee2c31d5d31d7bd74d0bb23c3ae3b838b56661749f1f33ef986523","src/func_translator.rs":"2f1a80ede583cb14cfc2714c1d96855d6d0fdc5e044e092b0257179cd118d876","src/lib.rs":"43a29f5dfb3f3f0d3cf85a89eee68e699aae2f80252c09b62b56673c763a1c74","src/module_translator.rs":"7d41cd6b8c09eab6b9448cba46cc4c2f843ed6952b393338d257d5629dabfd62","src/sections_translator.rs":"e49fed0596052b82d0e0010d1fcfdf52e214a16a3aeaa8e57e871927b522c77d","src/state.rs":"fc2a8d468b4b681d9262fdb8762f3300ffce709cb0b2e48f3835a5b9164e7c93","src/translation_utils.rs":"aae22673eb5227840a225c9af831e68a272c6b2ad1300f54c3f0a6116ce88a65","tests/wasm_testsuite.rs":"fc3c9c7b7b504b199cb524b29a18e633f68704de289c865049496ac636c38e0b"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"70f4c05be2e949e3f35c6c2e7990af6802916ded9e4017b679dc988079b621c2","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"87679cdb53e8cbec3b1aa45afb2124727c1c059f8bd10363d27daf318a9f9a36","src/code_translator.rs":"090fea0cff980468f423b1ea63a7cb1d8c4bf8349b588f577a700c90aa70a6c2","src/environ/dummy.rs":"848079947623af4227935cfc980a8dfad03d314e9fa7408ee8a520a1043b68c8","src/environ/mod.rs":"b046f5344a1017357c1ee9d661d2193e0247327df293436fa1381a0f45f80584","src/environ/spec.rs":"00911480a1eb3c85d635a197ff833e5180936364b2f61f9215f545b06829f362","src/func_translator.rs":"8f921c722f3e6b18c52a72e96d916b4f990bcdd42228e5be0ce3f182acc0eccb","src/lib.rs":"9c77bfa21596b8336e628e7808cde8cf167bbf1462b8f98abc6eddf90b1215d4","src/module_translator.rs":"c5d7506fffaf8f9034265273dad38983c898915cc7dbf445c659637b4838a3d3","src/sections_translator.rs":"55d0c1998f8007a559e7b3edd1c1fb3424f28596816fc0564acc2aae0dc08f3f","src/state.rs":"f7003dc78fdbb82c5c78188da1dca0bfcc0d907424dbdaa8a246184427850516","src/translation_utils.rs":"4b871e496e5bffc23e7094da01aa5d4cfa901e530e7d45f876e2c5bbe2ed897e","tests/wasm_testsuite.rs":"fc3c9c7b7b504b199cb524b29a18e633f68704de289c865049496ac636c38e0b"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cranelift-wasm/Cargo.toml b/third_party/rust/cranelift-wasm/Cargo.toml
index c140de53a7f2e0d00b881ed90a262b6d8d548bdd..fd7f51608d7c3482887b983845d7ff3616747daf 100644
--- a/third_party/rust/cranelift-wasm/Cargo.toml
+++ b/third_party/rust/cranelift-wasm/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-wasm"
-version = "0.42.0"
+version = "0.44.0"
 authors = ["The Cranelift Project Developers"]
 description = "Translator from WebAssembly to Cranelift IR"
 repository = "https://github.com/CraneStation/cranelift"
@@ -11,10 +11,10 @@ keywords = ["webassembly", "wasm"]
 edition = "2018"
 
 [dependencies]
-wasmparser = { version = "0.37.0", default-features = false }
-cranelift-codegen = { path = "../cranelift-codegen", version = "0.42.0", default-features = false }
-cranelift-entity = { path = "../cranelift-entity", version = "0.42.0", default-features = false }
-cranelift-frontend = { path = "../cranelift-frontend", version = "0.42.0", default-features = false }
+wasmparser = { version = "0.39.1", default-features = false }
+cranelift-codegen = { path = "../cranelift-codegen", version = "0.44.0", default-features = false }
+cranelift-entity = { path = "../cranelift-entity", version = "0.44.0", default-features = false }
+cranelift-frontend = { path = "../cranelift-frontend", version = "0.44.0", default-features = false }
 hashmap_core = { version = "0.1.9", optional = true }
 failure = { version = "0.1.1", default-features = false, features = ["derive"] }
 failure_derive = { version = "0.1.1", default-features = false }
diff --git a/third_party/rust/cranelift-wasm/src/code_translator.rs b/third_party/rust/cranelift-wasm/src/code_translator.rs
index c420147550ffc9eab7a246e6423d9a018177b2ea..0bf7f4b0b466898fb7cbbfeec39fe79e8c752c33 100644
--- a/third_party/rust/cranelift-wasm/src/code_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/code_translator.rs
@@ -907,7 +907,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::I64AtomicRmw16UCmpxchg { .. }
         | Operator::I64AtomicRmw32UCmpxchg { .. }
         | Operator::Fence { .. } => {
-            wasm_unsupported!("proposed thread operator {:?}", op);
+            return Err(wasm_unsupported!("proposed thread operator {:?}", op));
         }
         Operator::MemoryInit { .. }
         | Operator::DataDrop { .. }
@@ -920,7 +920,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::TableSet { .. }
         | Operator::TableGrow { .. }
         | Operator::TableSize { .. } => {
-            wasm_unsupported!("proposed bulk memory operator {:?}", op);
+            return Err(wasm_unsupported!("proposed bulk memory operator {:?}", op));
         }
         Operator::V128Const { value } => {
             let handle = builder.func.dfg.constants.insert(value.bytes().to_vec());
@@ -974,9 +974,24 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
                 builder,
             ))
         }
+        Operator::V8x16Shuffle { lanes, .. } => {
+            let (vector_a, vector_b) = state.pop2();
+            let a = optionally_bitcast_vector(vector_a, I8X16, builder);
+            let b = optionally_bitcast_vector(vector_b, I8X16, builder);
+            let mask = builder.func.dfg.immediates.push(lanes.to_vec());
+            let shuffled = builder.ins().shuffle(a, b, mask);
+            state.push1(shuffled)
+            // At this point the original types of a and b are lost; users of this value (i.e. this
+            // WASM-to-CLIF translator) may need to raw_bitcast for type-correctness. This is due
+            // to WASM using the less specific v128 type for certain operations and more specific
+            // types (e.g. i8x16) for others.
+        }
+        Operator::I8x16Add | Operator::I16x8Add | Operator::I32x4Add | Operator::I64x2Add => {
+            let (a, b) = state.pop2();
+            state.push1(builder.ins().iadd(a, b))
+        }
         Operator::V128Load { .. }
         | Operator::V128Store { .. }
-        | Operator::V8x16Shuffle { .. }
         | Operator::I8x16Eq
         | Operator::I8x16Ne
         | Operator::I8x16LtS
@@ -1030,7 +1045,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::I8x16Shl
         | Operator::I8x16ShrS
         | Operator::I8x16ShrU
-        | Operator::I8x16Add
         | Operator::I8x16AddSaturateS
         | Operator::I8x16AddSaturateU
         | Operator::I8x16Sub
@@ -1043,7 +1057,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::I16x8Shl
         | Operator::I16x8ShrS
         | Operator::I16x8ShrU
-        | Operator::I16x8Add
         | Operator::I16x8AddSaturateS
         | Operator::I16x8AddSaturateU
         | Operator::I16x8Sub
@@ -1056,7 +1069,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::I32x4Shl
         | Operator::I32x4ShrS
         | Operator::I32x4ShrU
-        | Operator::I32x4Add
         | Operator::I32x4Sub
         | Operator::I32x4Mul
         | Operator::I64x2Neg
@@ -1065,7 +1077,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::I64x2Shl
         | Operator::I64x2ShrS
         | Operator::I64x2ShrU
-        | Operator::I64x2Add
         | Operator::I64x2Sub
         | Operator::F32x4Abs
         | Operator::F32x4Neg
@@ -1098,7 +1109,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
         | Operator::I16x8LoadSplat { .. }
         | Operator::I32x4LoadSplat { .. }
         | Operator::I64x2LoadSplat { .. } => {
-            wasm_unsupported!("proposed SIMD operator {:?}", op);
+            return Err(wasm_unsupported!("proposed SIMD operator {:?}", op));
         }
     };
     Ok(())
diff --git a/third_party/rust/cranelift-wasm/src/environ/spec.rs b/third_party/rust/cranelift-wasm/src/environ/spec.rs
index ba87cc992a9ca2615b9c454f7f3e73b5224d0981..e83e675e72150b8a8e1d81387c43aed7d6294a37 100644
--- a/third_party/rust/cranelift-wasm/src/environ/spec.rs
+++ b/third_party/rust/cranelift-wasm/src/environ/spec.rs
@@ -6,7 +6,7 @@
 //!
 //! [Wasmtime]: https://github.com/CraneStation/wasmtime
 
-use crate::state::VisibleTranslationState;
+use crate::state::TranslationState;
 use crate::translation_utils::{
     FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
 };
@@ -80,7 +80,7 @@ pub enum WasmError {
 /// on the arguments to this macro.
 #[macro_export]
 macro_rules! wasm_unsupported {
-    ($($arg:tt)*) => { return Err($crate::environ::WasmError::Unsupported(format!($($arg)*))) }
+    ($($arg:tt)*) => { $crate::environ::WasmError::Unsupported(format!($($arg)*)) }
 }
 
 impl From<BinaryReaderError> for WasmError {
@@ -281,7 +281,7 @@ pub trait FuncEnvironment {
         &mut self,
         _op: &Operator,
         _builder: &mut FunctionBuilder,
-        _state: &VisibleTranslationState,
+        _state: &TranslationState,
     ) -> WasmResult<()> {
         Ok(())
     }
@@ -292,7 +292,7 @@ pub trait FuncEnvironment {
         &mut self,
         _op: &Operator,
         _builder: &mut FunctionBuilder,
-        _state: &VisibleTranslationState,
+        _state: &TranslationState,
     ) -> WasmResult<()> {
         Ok(())
     }
diff --git a/third_party/rust/cranelift-wasm/src/func_translator.rs b/third_party/rust/cranelift-wasm/src/func_translator.rs
index b49cffd47489b72b152412e4abe4712a6bcd1354..f947ddd065304fa826e2ea790e616cc34d1880e5 100644
--- a/third_party/rust/cranelift-wasm/src/func_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/func_translator.rs
@@ -6,7 +6,7 @@
 
 use crate::code_translator::translate_operator;
 use crate::environ::{FuncEnvironment, ReturnMode, WasmResult};
-use crate::state::{TranslationState, VisibleTranslationState};
+use crate::state::TranslationState;
 use crate::translation_utils::get_vmctx_value_label;
 use crate::wasm_unsupported;
 use cranelift_codegen::entity::EntityRef;
@@ -179,8 +179,12 @@ fn declare_locals<FE: FuncEnvironment + ?Sized>(
         I64 => builder.ins().iconst(ir::types::I64, 0),
         F32 => builder.ins().f32const(ir::immediates::Ieee32::with_bits(0)),
         F64 => builder.ins().f64const(ir::immediates::Ieee64::with_bits(0)),
+        V128 => {
+            let constant_handle = builder.func.dfg.constants.insert([0; 16].to_vec());
+            builder.ins().vconst(ir::types::I8X16, constant_handle)
+        }
         AnyRef => builder.ins().null(environ.reference_type()),
-        ty => wasm_unsupported!("unsupported local type {:?}", ty),
+        ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)),
     };
 
     let ty = builder.func.dfg.value_type(zeroval);
@@ -211,9 +215,9 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
     while !state.control_stack.is_empty() {
         builder.set_srcloc(cur_srcloc(&reader));
         let op = reader.read_operator()?;
-        environ.before_translate_operator(&op, builder, &VisibleTranslationState::new(state))?;
+        environ.before_translate_operator(&op, builder, state)?;
         translate_operator(&op, builder, state, environ)?;
-        environ.after_translate_operator(&op, builder, &VisibleTranslationState::new(state))?;
+        environ.after_translate_operator(&op, builder, state)?;
     }
 
     // The final `End` operator left us in the exit block where we need to manually add a return
diff --git a/third_party/rust/cranelift-wasm/src/lib.rs b/third_party/rust/cranelift-wasm/src/lib.rs
index 3c1065228babaf39a02ddefa0824ad948111b58e..d47feb631d0fc146c8b0a9df03aba6ee612a4c3b 100644
--- a/third_party/rust/cranelift-wasm/src/lib.rs
+++ b/third_party/rust/cranelift-wasm/src/lib.rs
@@ -62,7 +62,7 @@ pub use crate::environ::{
 };
 pub use crate::func_translator::FuncTranslator;
 pub use crate::module_translator::translate_module;
-pub use crate::state::VisibleTranslationState;
+pub use crate::state::TranslationState;
 pub use crate::translation_utils::{
     get_vmctx_value_label, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex,
     DefinedTableIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex,
diff --git a/third_party/rust/cranelift-wasm/src/module_translator.rs b/third_party/rust/cranelift-wasm/src/module_translator.rs
index 8d8b55397de2a4f9a1a9c6b3ea2137a9d14b59d7..462f79ab24818daa5b883c58202bc73b5144ef6b 100644
--- a/third_party/rust/cranelift-wasm/src/module_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/module_translator.rs
@@ -7,7 +7,7 @@ use crate::sections_translator::{
     parse_name_section, parse_start_section, parse_table_section, parse_type_section,
 };
 use cranelift_codegen::timing;
-use wasmparser::{CustomSectionKind, ModuleReader, SectionCode};
+use wasmparser::{CustomSectionContent, ModuleReader, SectionContent};
 
 /// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR
 /// [`Function`](cranelift_codegen::ir::Function).
@@ -20,83 +20,73 @@ pub fn translate_module<'data>(
 
     while !reader.eof() {
         let section = reader.read()?;
-        match section.code {
-            SectionCode::Type => {
-                let types = section.get_type_section_reader()?;
+        match section.content()? {
+            SectionContent::Type(types) => {
                 parse_type_section(types, environ)?;
             }
 
-            SectionCode::Import => {
-                let imports = section.get_import_section_reader()?;
+            SectionContent::Import(imports) => {
                 parse_import_section(imports, environ)?;
             }
 
-            SectionCode::Function => {
-                let functions = section.get_function_section_reader()?;
+            SectionContent::Function(functions) => {
                 parse_function_section(functions, environ)?;
             }
 
-            SectionCode::Table => {
-                let tables = section.get_table_section_reader()?;
+            SectionContent::Table(tables) => {
                 parse_table_section(tables, environ)?;
             }
 
-            SectionCode::Memory => {
-                let memories = section.get_memory_section_reader()?;
+            SectionContent::Memory(memories) => {
                 parse_memory_section(memories, environ)?;
             }
 
-            SectionCode::Global => {
-                let globals = section.get_global_section_reader()?;
+            SectionContent::Global(globals) => {
                 parse_global_section(globals, environ)?;
             }
 
-            SectionCode::Export => {
-                let exports = section.get_export_section_reader()?;
+            SectionContent::Export(exports) => {
                 parse_export_section(exports, environ)?;
             }
 
-            SectionCode::Start => {
-                let start = section.get_start_section_content()?;
+            SectionContent::Start(start) => {
                 parse_start_section(start, environ)?;
             }
 
-            SectionCode::Element => {
-                let elements = section.get_element_section_reader()?;
+            SectionContent::Element(elements) => {
                 parse_element_section(elements, environ)?;
             }
 
-            SectionCode::Code => {
-                let code = section.get_code_section_reader()?;
+            SectionContent::Code(code) => {
                 parse_code_section(code, environ)?;
             }
 
-            SectionCode::Data => {
-                let data = section.get_data_section_reader()?;
+            SectionContent::Data(data) => {
                 parse_data_section(data, environ)?;
             }
 
-            SectionCode::DataCount => {
+            SectionContent::DataCount(_) => {
                 return Err(WasmError::InvalidWebAssembly {
                     message: "don't know how to handle the data count section yet",
                     offset: reader.current_position(),
                 });
             }
 
-            SectionCode::Custom {
-                kind: CustomSectionKind::Name,
-                name: _,
-            } => {
-                let names = section.get_name_section_reader()?;
-                parse_name_section(names, environ)?;
-            }
-
-            SectionCode::Custom { name, kind: _ } => {
-                let mut reader = section.get_binary_reader();
-                let len = reader.bytes_remaining();
-                let payload = reader.read_bytes(len)?;
-                environ.custom_section(name, payload)?;
-            }
+            SectionContent::Custom {
+                name,
+                binary,
+                content,
+            } => match content {
+                Some(CustomSectionContent::Name(names)) => {
+                    parse_name_section(names, environ)?;
+                }
+                _ => {
+                    let mut reader = binary.clone();
+                    let len = reader.bytes_remaining();
+                    let payload = reader.read_bytes(len)?;
+                    environ.custom_section(name, payload)?;
+                }
+            },
         }
     }
 
diff --git a/third_party/rust/cranelift-wasm/src/sections_translator.rs b/third_party/rust/cranelift-wasm/src/sections_translator.rs
index 67830af3ff1bb6dda3fe14afcc389debb429ad94..a961a71ca9209ce4eef73c3f1836037eefdf71fa 100644
--- a/third_party/rust/cranelift-wasm/src/sections_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/sections_translator.rs
@@ -14,6 +14,7 @@ use crate::translation_utils::{
 };
 use crate::{wasm_unsupported, HashMap};
 use core::convert::TryFrom;
+use cranelift_codegen::ir::immediates::V128Imm;
 use cranelift_codegen::ir::{self, AbiParam, Signature};
 use cranelift_entity::EntityRef;
 use std::vec::Vec;
@@ -52,7 +53,12 @@ pub fn parse_type_section(
                 }));
                 environ.declare_signature(sig)?;
             }
-            ty => wasm_unsupported!("unsupported type in type section: {:?}", ty),
+            ty => {
+                return Err(wasm_unsupported!(
+                    "unsupported type in type section: {:?}",
+                    ty
+                ))
+            }
         }
     }
     Ok(())
@@ -201,11 +207,17 @@ pub fn parse_global_section(
             Operator::I64Const { value } => GlobalInit::I64Const(value),
             Operator::F32Const { value } => GlobalInit::F32Const(value.bits()),
             Operator::F64Const { value } => GlobalInit::F64Const(value.bits()),
+            Operator::V128Const { value } => {
+                GlobalInit::V128Const(V128Imm::from(value.bytes().to_vec().as_slice()))
+            }
             Operator::GetGlobal { global_index } => {
                 GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
             }
             ref s => {
-                wasm_unsupported!("unsupported init expr in global section: {:?}", s);
+                return Err(wasm_unsupported!(
+                    "unsupported init expr in global section: {:?}",
+                    s
+                ));
             }
         };
         let global = Global {
@@ -280,7 +292,10 @@ pub fn parse_element_section<'data>(
                     (Some(GlobalIndex::from_u32(global_index)), 0)
                 }
                 ref s => {
-                    wasm_unsupported!("unsupported init expr in element section: {:?}", s);
+                    return Err(wasm_unsupported!(
+                        "unsupported init expr in element section: {:?}",
+                        s
+                    ));
                 }
             };
             let items_reader = items.get_items_reader()?;
@@ -296,7 +311,10 @@ pub fn parse_element_section<'data>(
                 elems.into_boxed_slice(),
             )?
         } else {
-            wasm_unsupported!("unsupported passive elements section: {:?}", kind);
+            return Err(wasm_unsupported!(
+                "unsupported passive elements section: {:?}",
+                kind
+            ));
         }
     }
     Ok(())
@@ -336,7 +354,12 @@ pub fn parse_data_section<'data>(
                 Operator::GetGlobal { global_index } => {
                     (Some(GlobalIndex::from_u32(global_index)), 0)
                 }
-                ref s => wasm_unsupported!("unsupported init expr in data section: {:?}", s),
+                ref s => {
+                    return Err(wasm_unsupported!(
+                        "unsupported init expr in data section: {:?}",
+                        s
+                    ))
+                }
             };
             environ.declare_data_initialization(
                 MemoryIndex::from_u32(memory_index),
@@ -345,7 +368,10 @@ pub fn parse_data_section<'data>(
                 data,
             )?;
         } else {
-            wasm_unsupported!("unsupported passive data section: {:?}", kind);
+            return Err(wasm_unsupported!(
+                "unsupported passive data section: {:?}",
+                kind
+            ));
         }
     }
 
diff --git a/third_party/rust/cranelift-wasm/src/state.rs b/third_party/rust/cranelift-wasm/src/state.rs
index 7016035b725d221ebae2eac1c9de78cc3d8f03eb..7359482893d86545b1cad4116b479614381d6a07 100644
--- a/third_party/rust/cranelift-wasm/src/state.rs
+++ b/third_party/rust/cranelift-wasm/src/state.rs
@@ -124,28 +124,6 @@ impl ControlStackFrame {
     }
 }
 
-/// VisibleTranslationState wraps a TranslationState with an interface appropriate for users
-/// outside this `cranelift-wasm`.
-///
-/// VisibleTranslationState is currently very minimal (only exposing reachability information), but
-/// is anticipated to grow in the future, with functions to inspect or modify the wasm operand
-/// stack for example.
-pub struct VisibleTranslationState<'a> {
-    state: &'a TranslationState,
-}
-
-impl<'a> VisibleTranslationState<'a> {
-    /// Build a VisibleTranslationState from an existing TranslationState
-    pub fn new(state: &'a TranslationState) -> Self {
-        VisibleTranslationState { state }
-    }
-
-    /// True if the current translation state expresses reachable code, false if it is unreachable
-    pub fn reachable(&self) -> bool {
-        self.state.reachable
-    }
-}
-
 /// Contains information passed along during the translation and that records:
 ///
 /// - The current value and control stacks.
@@ -154,12 +132,12 @@ impl<'a> VisibleTranslationState<'a> {
 pub struct TranslationState {
     /// A stack of values corresponding to the active values in the input wasm function at this
     /// point.
-    pub stack: Vec<Value>,
+    pub(crate) stack: Vec<Value>,
     /// A stack of active control flow operations at this point in the input wasm function.
-    pub control_stack: Vec<ControlStackFrame>,
+    pub(crate) control_stack: Vec<ControlStackFrame>,
     /// Is the current translation state still reachable? This is false when translating operators
     /// like End, Return, or Unreachable.
-    pub reachable: bool,
+    pub(crate) reachable: bool,
 
     // Map of global variables that have already been created by `FuncEnvironment::make_global`.
     globals: HashMap<GlobalIndex, GlobalVariable>,
@@ -181,9 +159,18 @@ pub struct TranslationState {
     functions: HashMap<FuncIndex, (ir::FuncRef, usize)>,
 }
 
+// Public methods that are exposed to non-`cranelift_wasm` API consumers.
+impl TranslationState {
+    /// True if the current translation state expresses reachable code, false if it is unreachable.
+    #[inline]
+    pub fn reachable(&self) -> bool {
+        self.reachable
+    }
+}
+
 impl TranslationState {
     /// Construct a new, empty, `TranslationState`
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         Self {
             stack: Vec::new(),
             control_stack: Vec::new(),
@@ -211,7 +198,7 @@ impl TranslationState {
     ///
     /// This resets the state to containing only a single block representing the whole function.
     /// The exit block is the last block in the function which will contain the return instruction.
-    pub fn initialize(&mut self, sig: &ir::Signature, exit_block: Ebb) {
+    pub(crate) fn initialize(&mut self, sig: &ir::Signature, exit_block: Ebb) {
         self.clear();
         self.push_block(
             exit_block,
@@ -223,34 +210,34 @@ impl TranslationState {
     }
 
     /// Push a value.
-    pub fn push1(&mut self, val: Value) {
+    pub(crate) fn push1(&mut self, val: Value) {
         self.stack.push(val);
     }
 
     /// Push multiple values.
-    pub fn pushn(&mut self, vals: &[Value]) {
+    pub(crate) fn pushn(&mut self, vals: &[Value]) {
         self.stack.extend_from_slice(vals);
     }
 
     /// Pop one value.
-    pub fn pop1(&mut self) -> Value {
+    pub(crate) fn pop1(&mut self) -> Value {
         self.stack.pop().unwrap()
     }
 
     /// Peek at the top of the stack without popping it.
-    pub fn peek1(&self) -> Value {
+    pub(crate) fn peek1(&self) -> Value {
         *self.stack.last().unwrap()
     }
 
     /// Pop two values. Return them in the order they were pushed.
-    pub fn pop2(&mut self) -> (Value, Value) {
+    pub(crate) fn pop2(&mut self) -> (Value, Value) {
         let v2 = self.stack.pop().unwrap();
         let v1 = self.stack.pop().unwrap();
         (v1, v2)
     }
 
     /// Pop three values. Return them in the order they were pushed.
-    pub fn pop3(&mut self) -> (Value, Value, Value) {
+    pub(crate) fn pop3(&mut self) -> (Value, Value, Value) {
         let v3 = self.stack.pop().unwrap();
         let v2 = self.stack.pop().unwrap();
         let v1 = self.stack.pop().unwrap();
@@ -260,18 +247,18 @@ impl TranslationState {
     /// Pop the top `n` values on the stack.
     ///
     /// The popped values are not returned. Use `peekn` to look at them before popping.
-    pub fn popn(&mut self, n: usize) {
+    pub(crate) fn popn(&mut self, n: usize) {
         let new_len = self.stack.len() - n;
         self.stack.truncate(new_len);
     }
 
     /// Peek at the top `n` values on the stack in the order they were pushed.
-    pub fn peekn(&self, n: usize) -> &[Value] {
+    pub(crate) fn peekn(&self, n: usize) -> &[Value] {
         &self.stack[self.stack.len() - n..]
     }
 
     /// Push a block on the control stack.
-    pub fn push_block(&mut self, following_code: Ebb, num_result_types: usize) {
+    pub(crate) fn push_block(&mut self, following_code: Ebb, num_result_types: usize) {
         self.control_stack.push(ControlStackFrame::Block {
             destination: following_code,
             original_stack_size: self.stack.len(),
@@ -281,7 +268,7 @@ impl TranslationState {
     }
 
     /// Push a loop on the control stack.
-    pub fn push_loop(&mut self, header: Ebb, following_code: Ebb, num_result_types: usize) {
+    pub(crate) fn push_loop(&mut self, header: Ebb, following_code: Ebb, num_result_types: usize) {
         self.control_stack.push(ControlStackFrame::Loop {
             header,
             destination: following_code,
@@ -291,7 +278,12 @@ impl TranslationState {
     }
 
     /// Push an if on the control stack.
-    pub fn push_if(&mut self, branch_inst: Inst, following_code: Ebb, num_result_types: usize) {
+    pub(crate) fn push_if(
+        &mut self,
+        branch_inst: Inst,
+        following_code: Ebb,
+        num_result_types: usize,
+    ) {
         self.control_stack.push(ControlStackFrame::If {
             branch_inst,
             destination: following_code,
@@ -308,7 +300,7 @@ impl TranslationState {
     /// Get the `GlobalVariable` reference that should be used to access the global variable
     /// `index`. Create the reference if necessary.
     /// Also return the WebAssembly type of the global.
-    pub fn get_global<FE: FuncEnvironment + ?Sized>(
+    pub(crate) fn get_global<FE: FuncEnvironment + ?Sized>(
         &mut self,
         func: &mut ir::Function,
         index: u32,
@@ -323,7 +315,7 @@ impl TranslationState {
 
     /// Get the `Heap` reference that should be used to access linear memory `index`.
     /// Create the reference if necessary.
-    pub fn get_heap<FE: FuncEnvironment + ?Sized>(
+    pub(crate) fn get_heap<FE: FuncEnvironment + ?Sized>(
         &mut self,
         func: &mut ir::Function,
         index: u32,
@@ -338,7 +330,7 @@ impl TranslationState {
 
     /// Get the `Table` reference that should be used to access table `index`.
     /// Create the reference if necessary.
-    pub fn get_table<FE: FuncEnvironment + ?Sized>(
+    pub(crate) fn get_table<FE: FuncEnvironment + ?Sized>(
         &mut self,
         func: &mut ir::Function,
         index: u32,
@@ -355,7 +347,7 @@ impl TranslationState {
     /// `index`. Also return the number of WebAssembly arguments in the signature.
     ///
     /// Create the signature if necessary.
-    pub fn get_indirect_sig<FE: FuncEnvironment + ?Sized>(
+    pub(crate) fn get_indirect_sig<FE: FuncEnvironment + ?Sized>(
         &mut self,
         func: &mut ir::Function,
         index: u32,
@@ -375,7 +367,7 @@ impl TranslationState {
     /// `index`. Also return the number of WebAssembly arguments in the signature.
     ///
     /// Create the function reference if necessary.
-    pub fn get_direct_func<FE: FuncEnvironment + ?Sized>(
+    pub(crate) fn get_direct_func<FE: FuncEnvironment + ?Sized>(
         &mut self,
         func: &mut ir::Function,
         index: u32,
diff --git a/third_party/rust/cranelift-wasm/src/translation_utils.rs b/third_party/rust/cranelift-wasm/src/translation_utils.rs
index f033b8660c7306d5d59658f57a8434558d0d2b42..df910c534bdd82da45d3dd680db5cdc938a00977 100644
--- a/third_party/rust/cranelift-wasm/src/translation_utils.rs
+++ b/third_party/rust/cranelift-wasm/src/translation_utils.rs
@@ -4,6 +4,7 @@ use crate::wasm_unsupported;
 use core::u32;
 use cranelift_codegen::entity::entity_impl;
 use cranelift_codegen::ir;
+use cranelift_codegen::ir::immediates::V128Imm;
 #[cfg(feature = "enable-serde")]
 use serde::{Deserialize, Serialize};
 use wasmparser;
@@ -65,7 +66,7 @@ pub struct Global {
     pub initializer: GlobalInit,
 }
 
-/// Globals are initialized via the four `const` operators or by referring to another import.
+/// Globals are initialized via the `const` operators or by referring to another import.
 #[derive(Debug, Clone, Copy, Hash)]
 pub enum GlobalInit {
     /// An `i32.const`.
@@ -76,6 +77,8 @@ pub enum GlobalInit {
     F32Const(u32),
     /// An `f64.const`.
     F64Const(u64),
+    /// A `vconst`.
+    V128Const(V128Imm),
     /// A `get_global` of another global.
     GetGlobal(GlobalIndex),
     ///< The global is imported from, and thus initialized by, a different module.
@@ -120,7 +123,8 @@ pub fn type_to_type(ty: wasmparser::Type) -> WasmResult<ir::Type> {
         wasmparser::Type::I64 => Ok(ir::types::I64),
         wasmparser::Type::F32 => Ok(ir::types::F32),
         wasmparser::Type::F64 => Ok(ir::types::F64),
-        ty => wasm_unsupported!("type_to_type: wasm type {:?}", ty),
+        wasmparser::Type::V128 => Ok(ir::types::I8X16),
+        ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)),
     }
 }
 
@@ -132,8 +136,12 @@ pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> {
         wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
         wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
         wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
+        wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
         wasmparser::Type::AnyFunc => Ok(None),
-        ty => wasm_unsupported!("tabletype_to_type: table wasm type {:?}", ty),
+        ty => Err(wasm_unsupported!(
+            "tabletype_to_type: table wasm type {:?}",
+            ty
+        )),
     }
 }
 
@@ -145,13 +153,14 @@ pub fn blocktype_to_type(ty_or_ft: wasmparser::TypeOrFuncType) -> WasmResult<Opt
             wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
             wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
             wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
+            wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
             wasmparser::Type::EmptyBlockType => Ok(None),
-            ty => wasm_unsupported!("blocktype_to_type: type {:?}", ty),
+            ty => Err(wasm_unsupported!("blocktype_to_type: type {:?}", ty)),
         },
-        wasmparser::TypeOrFuncType::FuncType(_) => wasm_unsupported!(
+        wasmparser::TypeOrFuncType::FuncType(_) => Err(wasm_unsupported!(
             "blocktype_to_type: multi-value block signature {:?}",
             ty_or_ft
-        ),
+        )),
     }
 }
 
@@ -173,11 +182,12 @@ pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> WasmResult<usize> {
             wasmparser::Type::I32
             | wasmparser::Type::F32
             | wasmparser::Type::I64
-            | wasmparser::Type::F64 => Ok(1),
-            ty => wasm_unsupported!("unsupported return value type {:?}", ty),
+            | wasmparser::Type::F64
+            | wasmparser::Type::V128 => Ok(1),
+            ty => Err(wasm_unsupported!("unsupported return value type {:?}", ty)),
         },
         wasmparser::TypeOrFuncType::FuncType(_) => {
-            wasm_unsupported!("multi-value block signature {:?}", ty);
+            Err(wasm_unsupported!("multi-value block signature {:?}", ty))
         }
     }
 }
diff --git a/third_party/rust/wasmparser/.cargo-checksum.json b/third_party/rust/wasmparser/.cargo-checksum.json
index d26ed3d342aa03e34b26e3aedc4c6b8b887697e3..0cbe8f9f1e759495455ba0cd2d9433b6e7f805f0 100644
--- a/third_party/rust/wasmparser/.cargo-checksum.json
+++ b/third_party/rust/wasmparser/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"adda6d221a7562818654f99b9f3a577dfde76db43726eb12248dc5b255b0d44e","Cargo.toml":"4616d1871f9a1ad11f50e46800ac5cc424a06234be2edde1ef9bec05dbf7ef99","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"13ea373a411dfa7371cd994736289bb000db51957da92315fecbcc9fe7dcab92","benches/benchmark.rs":"951abd671bd1a5a33d09379b023de000e89fc5f99a5950f0b3b2f571021aa402","compare-master.sh":"165490eab36ef4eceb2913a6c5cdeff479a05e1e0119a7f4551b03dbcda51ad4","examples/dump.rs":"de2bbdba75e21b9ff92b32697b3d9941f8695b8f7e3a8dee8fc5d7f4c3a0649c","examples/simple.rs":"c79ae542913e72cfcd03711543d173b2e8f62783e6c206459953bdb94dbb8c0c","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"39e0a785a41e2513926ab140a1e07f38a6e898737d098d1d038ba5229e7c24b3","src/lib.rs":"abcb8d4f9a604fbc0997add13a0213bc9abc163ac6c2d4534096a3d620a0bd0f","src/limits.rs":"4e4f9b7ed1d26e7a6727e36b136015cd9f4e38f596b3c8f82236789f45905cae","src/operators_validator.rs":"3c7b9acc1abab2ceb931047301b1f43385d32ecd3274b3fae217b4096e82f3ac","src/parser.rs":"c5afcf039a62952f4e674773416d4c4507711d10b4248ed3bce5e1223cc97034","src/primitives.rs":"e04f3ef6463a24f917c0d8b0377f9db86a3c756d99d5278226046122b76a52d5","src/readers/code_section.rs":"2034c399b76428ac993c22f551f3c541b132d8b4ccc74e34f0043e25534d107b","src/readers/data_count_section.rs":"27ef37517b6beac21245008b14b5416b851c52d0af8e2ae85c1456674e1c9a9e","src/readers/data_section.rs":"e7e2a539d2d3049d4a8f68df9ea2f21d97e7061657bbd91845e1df3e9c1f2ebc","src/readers/element_section.rs":"e31e1d819c0b10acf58b8975238554245defe36db1c3206683b056c52978fb21","src/readers/export_section.rs":"7c74f7a11406a95c162f6ad4f77aafd0b1eee309f33b69f06bea12b23925e143","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"1db4bf7290d04783d5cf526050d025b15a1daaf2bd97fca1a92ecb873d48f641","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"13822fff4190b72f6ae14e29635d2c148a38ee972e148eb99a4688b0309bc2c9","src/readers/module.rs":"3b5e687874fd6211b8e083d7a8589c50dd80377eb85c605b21e505da5f546899","src/readers/name_section.rs":"297f57393d5fef745ec265438108aa6eb7ed2762c03c3beb539493612442f3da","src/readers/operators.rs":"da43ee8afcb0c1d6e7f1e19e8a10143101f0c598b1e533a394c7397f43881a82","src/readers/producers_section.rs":"674f402fc4545c94487f827153871b37adab44ed5eff4070a436eb18e514023a","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"ababe84d51e4817ad19f827aa2b5239578e7f202e5ec06dd688b618885138434","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"9190318f1fdca501196eb4a1437ab7c74a46d19e9f9b9967d9f81c52d80f0019","src/validator.rs":"94700288b65cf2ff392bedffa2387b3a10d05d883b2343ba3315566759cf1d79","test-all.sh":"f36e3e9bf9c39456bab3ac170d3a09911becf2b7e0d0e2a58854ce1750da0d1f","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"82dbea680995dad585289fd47889cf9614133ebfcc3bda95737ef8bdc9e11db6"}
\ No newline at end of file
+{"files":{"Cargo.lock":"b5d7bacf94229b33c94e3d7c8f158334481a23f2fc86ccecd18ac671582d476f","Cargo.toml":"0f7b7d8e284e9faf9850ce67b1d494b1bb4d080d1ed9be01e8a09435a906d35c","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"df9c5aa22ca3bcf6221c7e4297cd741cbbdfb39294b4ef28c4d382688395611a","benches/benchmark.rs":"951abd671bd1a5a33d09379b023de000e89fc5f99a5950f0b3b2f571021aa402","compare-master.sh":"165490eab36ef4eceb2913a6c5cdeff479a05e1e0119a7f4551b03dbcda51ad4","examples/dump.rs":"de2bbdba75e21b9ff92b32697b3d9941f8695b8f7e3a8dee8fc5d7f4c3a0649c","examples/simple.rs":"c79ae542913e72cfcd03711543d173b2e8f62783e6c206459953bdb94dbb8c0c","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"39e0a785a41e2513926ab140a1e07f38a6e898737d098d1d038ba5229e7c24b3","src/lib.rs":"a17f353162053e0e915a0e0d1f4d4ba86a7a8e4ff949c83faad004b707ac003f","src/limits.rs":"4e4f9b7ed1d26e7a6727e36b136015cd9f4e38f596b3c8f82236789f45905cae","src/operators_validator.rs":"147d2999314421361e0a20370178f638120c4199f4dc7388f9adca5e42b05d62","src/parser.rs":"c5afcf039a62952f4e674773416d4c4507711d10b4248ed3bce5e1223cc97034","src/primitives.rs":"65b7ddf0fb0bde4df0823a23ced952720e7dd8c4b630fdcd988096ccb8ea1379","src/readers/code_section.rs":"2034c399b76428ac993c22f551f3c541b132d8b4ccc74e34f0043e25534d107b","src/readers/data_count_section.rs":"27ef37517b6beac21245008b14b5416b851c52d0af8e2ae85c1456674e1c9a9e","src/readers/data_section.rs":"e7e2a539d2d3049d4a8f68df9ea2f21d97e7061657bbd91845e1df3e9c1f2ebc","src/readers/element_section.rs":"e31e1d819c0b10acf58b8975238554245defe36db1c3206683b056c52978fb21","src/readers/export_section.rs":"7c74f7a11406a95c162f6ad4f77aafd0b1eee309f33b69f06bea12b23925e143","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"1db4bf7290d04783d5cf526050d025b15a1daaf2bd97fca1a92ecb873d48f641","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"188aa45a893f4d17df7633a3df6a32438b64e192e001ddcc50543e007b4f7db4","src/readers/module.rs":"311b877264bf9d035280cad0c61eb3640c15505c4da5e8ba45c7bf9e067abbd4","src/readers/name_section.rs":"297f57393d5fef745ec265438108aa6eb7ed2762c03c3beb539493612442f3da","src/readers/operators.rs":"da43ee8afcb0c1d6e7f1e19e8a10143101f0c598b1e533a394c7397f43881a82","src/readers/producers_section.rs":"674f402fc4545c94487f827153871b37adab44ed5eff4070a436eb18e514023a","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"ababe84d51e4817ad19f827aa2b5239578e7f202e5ec06dd688b618885138434","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"7397b77201d62a98e24858545a32597b782ff66d4ae6f02a5df59ff27925a9af","src/validator.rs":"4dfd7176fc1fced1730ecf6ee8c9225751a6ba3047862b9cfc8b151d9526a378","test-all.sh":"f36e3e9bf9c39456bab3ac170d3a09911becf2b7e0d0e2a58854ce1750da0d1f","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"a026c1436af49d5537c7561c7474f81f7a754e36445fe52e6e88795a9747291c"}
\ No newline at end of file
diff --git a/third_party/rust/wasmparser/Cargo.lock b/third_party/rust/wasmparser/Cargo.lock
index d72a79860bbcc92eac485472dd0bec7864736152..2c6547dbb7dd305360d6e73380c2201c17f7f815 100644
--- a/third_party/rust/wasmparser/Cargo.lock
+++ b/third_party/rust/wasmparser/Cargo.lock
@@ -2,7 +2,7 @@
 # It is not intended for manual editing.
 [[package]]
 name = "arrayvec"
-version = "0.4.10"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -10,22 +10,37 @@ dependencies = [
 
 [[package]]
 name = "atty"
-version = "0.2.11"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
- "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "autocfg"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "bitflags"
-version = "1.0.4"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bstr"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "byteorder"
-version = "1.3.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -35,22 +50,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cc"
-version = "1.0.40"
+version = "1.0.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cfg-if"
-version = "0.1.7"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "clap"
-version = "2.32.0"
+version = "2.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -58,102 +73,115 @@ name = "cloudabi"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cmake"
-version = "0.1.41"
+version = "0.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "criterion"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "criterion-plot"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.2.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.3.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.2.2"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "csv"
-version = "1.0.5"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "csv-core"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "either"
-version = "1.5.1"
+version = "1.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -176,36 +204,39 @@ name = "itertools"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "itoa"
-version = "0.4.3"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lazy_static"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.50"
+version = "0.2.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "memchr"
-version = "2.2.0"
+version = "2.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "memoffset"
-version = "0.2.1"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "nodrop"
@@ -214,31 +245,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num-traits"
-version = "0.2.6"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "num_cpus"
-version = "1.10.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "0.4.27"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "quote"
-version = "0.6.11"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -246,12 +280,12 @@ name = "rand_core"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand_core"
-version = "0.4.0"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -261,10 +295,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -272,29 +306,30 @@ name = "rand_xoshiro"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rayon"
-version = "1.0.3"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.4.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -306,26 +341,29 @@ dependencies = [
 ]
 
 [[package]]
-name = "redox_syscall"
-version = "0.1.51"
+name = "regex-automata"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
-name = "redox_termios"
-version = "0.1.1"
+name = "rustc_version"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "ryu"
-version = "0.2.7"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "same-file"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -333,124 +371,127 @@ dependencies = [
 
 [[package]]
 name = "scopeguard"
-version = "0.3.3"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.89"
+version = "1.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.89"
+version = "1.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.39"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
-version = "0.15.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "termion"
-version = "1.5.1"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "textwrap"
-version = "0.10.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tinytemplate"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "unicode-width"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-xid"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "wabt"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "wabt-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wabt-sys"
-version = "0.6.1"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "walkdir"
-version = "2.2.7"
+version = "2.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.37.0"
+version = "0.39.1"
 dependencies = [
- "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "wabt 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -467,7 +508,7 @@ name = "winapi-util"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -476,63 +517,67 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
-"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
-"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
-"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
+"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
+"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
+"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
+"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
+"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245"
+"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
 "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
-"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7"
-"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
-"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
+"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
+"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
+"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "3c84c596dcf125d6781f58e3f4254677ec2a6d8aa56e8501ac277100990b3229"
-"checksum criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1c6e5ee5b9652d4f851418c448af105642e1f99e9a2741a8ff45c0d2c911b1e0"
-"checksum criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4107e4a5abb94267e0149922b8ff49dc70a87cc202820fdbfc0d3e1edbdc4b16"
-"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
-"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
-"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
-"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04"
-"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
-"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac"
+"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
+"checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394"
+"checksum criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e"
+"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
+"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
+"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
+"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
+"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d"
+"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c"
+"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
 "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
 "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
-"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
-"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
-"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
-"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
-"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
+"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
+"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
+"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
+"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
 "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
-"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
-"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
-"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
-"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
+"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
+"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
+"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
+"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
 "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
 "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929"
-"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473"
-"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
+"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
+"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
-"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
-"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
-"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
-"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
-"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560"
-"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c"
-"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
-"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2"
-"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
-"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
-"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115"
-"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
-"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
-"checksum wabt 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94b5f5d6984ca42df66280baa8a15ac188a173ddaf4580b574a98931c01920e7"
-"checksum wabt-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b064c81821100adb4b71923cecfc67fef083db21c3bbd454b0162c7ffe63eeaa"
-"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
-"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
+"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
+"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
+"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
+"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a"
+"checksum serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = "11e410fde43e157d789fc290d26bc940778ad0fdd47836426fbac36573710dbb"
+"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
+"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
+"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20"
+"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5c5c1286c6e578416982609f47594265f9d489f9b836157d403ad605a46693"
+"checksum wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af5d153dc96aad7dc13ab90835b892c69867948112d95299e522d370c4e13a08"
+"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/third_party/rust/wasmparser/Cargo.toml b/third_party/rust/wasmparser/Cargo.toml
index d1c5f48155f418285a274d08b2dbb994f75177b8..6d2d22f7f5835095c3a8d50fa5182064180cb1c6 100644
--- a/third_party/rust/wasmparser/Cargo.toml
+++ b/third_party/rust/wasmparser/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "wasmparser"
-version = "0.37.0"
+version = "0.39.1"
 authors = ["Yury Delendik <ydelendik@mozilla.com>"]
 exclude = ["fuzz/**/*", "tests/**/*", "testsuite/**/*"]
 description = "A simple event-driven library for parsing WebAssembly binary files.\n"
@@ -31,7 +31,7 @@ optional = true
 version = "0.2"
 
 [dev-dependencies.wabt]
-version = "0.9.1"
+version = "0.9.2"
 
 [features]
 core = ["hashbrown"]
diff --git a/third_party/rust/wasmparser/README.md b/third_party/rust/wasmparser/README.md
index 87986366a4b48cec8d1363a24833ad9ab90aabbf..18bd6787be847e4aebde1a243a3025c99c01b11f 100644
--- a/third_party/rust/wasmparser/README.md
+++ b/third_party/rust/wasmparser/README.md
@@ -3,7 +3,7 @@
 [![Build Status](https://travis-ci.org/yurydelendik/wasmparser.rs.svg?branch=master)](https://travis-ci.org/yurydelendik/wasmparser.rs)
 [![crates.io link](https://img.shields.io/crates/v/wasmparser.svg)](https://crates.io/crates/wasmparser)
 
-The decoder library provides lightwight and fast decoding/parsing of WebAssembly binary files.
+The decoder library provides lightweight and fast decoding/parsing of WebAssembly binary files.
 
 The other goal is minimal memory footprint. For this reason, there is no AST or IR of WebAssembly data.
 
diff --git a/third_party/rust/wasmparser/src/lib.rs b/third_party/rust/wasmparser/src/lib.rs
index 545cceae837159c33325df01477d9d10a367547c..4039660e58edec77d856248ca017f39b56bf3905 100644
--- a/third_party/rust/wasmparser/src/lib.rs
+++ b/third_party/rust/wasmparser/src/lib.rs
@@ -83,6 +83,7 @@ pub use crate::operators_validator::OperatorValidatorConfig;
 pub use crate::operators_validator::WasmModuleResources;
 
 pub use crate::readers::CodeSectionReader;
+pub use crate::readers::CustomSectionContent;
 pub use crate::readers::Data;
 pub use crate::readers::DataKind;
 pub use crate::readers::DataSectionReader;
@@ -114,6 +115,7 @@ pub use crate::readers::ProducersSectionReader;
 pub use crate::readers::Reloc;
 pub use crate::readers::RelocSectionReader;
 pub use crate::readers::Section;
+pub use crate::readers::SectionContent;
 pub use crate::readers::SectionIterator;
 pub use crate::readers::SectionIteratorLimited;
 pub use crate::readers::SectionReader;
diff --git a/third_party/rust/wasmparser/src/operators_validator.rs b/third_party/rust/wasmparser/src/operators_validator.rs
index 07897d99cec06693302690ee63ad29989bb8094a..e575fe82b896059af6e87a1a85a4deacefdf5213 100644
--- a/third_party/rust/wasmparser/src/operators_validator.rs
+++ b/third_party/rust/wasmparser/src/operators_validator.rs
@@ -24,9 +24,12 @@ use crate::primitives::{
 };
 
 /// Test if `subtype` is a subtype of `supertype`.
-fn is_subtype_supertype(subtype: Type, supertype: Type) -> bool {
+pub(crate) fn is_subtype_supertype(subtype: Type, supertype: Type) -> bool {
     match supertype {
-        Type::AnyRef => subtype == Type::AnyRef || subtype == Type::AnyFunc,
+        Type::AnyRef => {
+            subtype == Type::AnyRef || subtype == Type::AnyFunc || subtype == Type::Null
+        }
+        Type::AnyFunc => subtype == Type::AnyFunc || subtype == Type::Null,
         _ => subtype == supertype,
     }
 }
@@ -135,7 +138,13 @@ impl FuncState {
             }
         };
         if block_type == BlockType::If {
-            self.stack_types.pop();
+            let last_block = self.blocks.last().unwrap();
+            if !last_block.is_stack_polymorphic()
+                || self.stack_types.len() > last_block.stack_starts_at
+            {
+                self.stack_types.pop();
+            }
+            assert!(self.stack_types.len() >= last_block.stack_starts_at);
         }
         for (i, ty) in start_types.iter().rev().enumerate() {
             if !self.assert_stack_type_at(i, *ty) {
@@ -563,6 +572,7 @@ impl OperatorValidator {
             | TypeOrFuncType::Type(Type::I64)
             | TypeOrFuncType::Type(Type::F32)
             | TypeOrFuncType::Type(Type::F64) => Ok(()),
+            TypeOrFuncType::Type(Type::V128) => self.check_simd_enabled(),
             TypeOrFuncType::FuncType(idx) => {
                 let idx = idx as usize;
                 let types = resources.types();
@@ -1312,12 +1322,12 @@ impl OperatorValidator {
             }
             Operator::RefNull => {
                 self.check_reference_types_enabled()?;
-                self.func_state.change_frame_with_type(0, Type::AnyRef)?;
+                self.func_state.change_frame_with_type(0, Type::Null)?;
             }
             Operator::RefIsNull => {
                 self.check_reference_types_enabled()?;
                 self.check_operands(&[Type::AnyRef])?;
-                self.func_state.change_frame_with_type(0, Type::I32)?;
+                self.func_state.change_frame_with_type(1, Type::I32)?;
             }
             Operator::V128Load { ref memarg } => {
                 self.check_simd_enabled()?;
diff --git a/third_party/rust/wasmparser/src/primitives.rs b/third_party/rust/wasmparser/src/primitives.rs
index 7fa8938ce24c9b078ec9eb98bacced40c5bc457d..1bb8db6d263f2c82d3d02fb874fcdca8e7438737 100644
--- a/third_party/rust/wasmparser/src/primitives.rs
+++ b/third_party/rust/wasmparser/src/primitives.rs
@@ -84,6 +84,7 @@ pub enum Type {
     AnyRef,
     Func,
     EmptyBlockType,
+    Null,
 }
 
 /// Either a value type or a function type.
diff --git a/third_party/rust/wasmparser/src/readers/mod.rs b/third_party/rust/wasmparser/src/readers/mod.rs
index 52488b195089506c47fa52bae71a2da200aaf3dd..3c6d58945800aa37c5377b7668c4dd68a26a93dc 100644
--- a/third_party/rust/wasmparser/src/readers/mod.rs
+++ b/third_party/rust/wasmparser/src/readers/mod.rs
@@ -42,8 +42,10 @@ pub use self::import_section::Import;
 pub use self::import_section::ImportSectionReader;
 pub use self::init_expr::InitExpr;
 pub use self::memory_section::MemorySectionReader;
+pub use self::module::CustomSectionContent;
 pub use self::module::ModuleReader;
 pub use self::module::Section;
+pub use self::module::SectionContent;
 use self::start_section::read_start_section_content;
 pub use self::table_section::TableSectionReader;
 pub use self::type_section::TypeSectionReader;
diff --git a/third_party/rust/wasmparser/src/readers/module.rs b/third_party/rust/wasmparser/src/readers/module.rs
index 535d99b669033a3cfc7c79c83d3527b9d640350e..36a9c3390b6b39e0bed0d7678bb849b6e23f2662 100644
--- a/third_party/rust/wasmparser/src/readers/module.rs
+++ b/third_party/rust/wasmparser/src/readers/module.rs
@@ -247,6 +247,86 @@ impl<'a> Section<'a> {
             end: self.offset + self.data.len(),
         }
     }
+
+    pub fn content<'b>(&self) -> Result<SectionContent<'b>>
+    where
+        'a: 'b,
+    {
+        let c = match self.code {
+            SectionCode::Type => SectionContent::Type(self.get_type_section_reader()?),
+            SectionCode::Function => SectionContent::Function(self.get_function_section_reader()?),
+            SectionCode::Code => SectionContent::Code(self.get_code_section_reader()?),
+            SectionCode::Export => SectionContent::Export(self.get_export_section_reader()?),
+            SectionCode::Import => SectionContent::Import(self.get_import_section_reader()?),
+            SectionCode::Global => SectionContent::Global(self.get_global_section_reader()?),
+            SectionCode::Memory => SectionContent::Memory(self.get_memory_section_reader()?),
+            SectionCode::Data => SectionContent::Data(self.get_data_section_reader()?),
+            SectionCode::Table => SectionContent::Table(self.get_table_section_reader()?),
+            SectionCode::Element => SectionContent::Element(self.get_element_section_reader()?),
+            SectionCode::Start => SectionContent::Start(self.get_start_section_content()?),
+            SectionCode::DataCount => {
+                SectionContent::DataCount(self.get_data_count_section_content()?)
+            }
+            SectionCode::Custom { kind, name } => {
+                let binary = self.get_binary_reader();
+                let content = match kind {
+                    CustomSectionKind::Name => {
+                        Some(CustomSectionContent::Name(self.get_name_section_reader()?))
+                    }
+                    CustomSectionKind::Producers => Some(CustomSectionContent::Producers(
+                        self.get_producers_section_reader()?,
+                    )),
+                    CustomSectionKind::Linking => Some(CustomSectionContent::Linking(
+                        self.get_linking_section_reader()?,
+                    )),
+                    CustomSectionKind::Reloc => Some(CustomSectionContent::Reloc(
+                        self.get_reloc_section_reader()?,
+                    )),
+                    CustomSectionKind::SourceMappingURL => {
+                        Some(CustomSectionContent::SourceMappingURL(
+                            self.get_sourcemappingurl_section_content()?,
+                        ))
+                    }
+
+                    _ => None,
+                };
+                SectionContent::Custom {
+                    name,
+                    binary,
+                    content,
+                }
+            }
+        };
+        Ok(c)
+    }
+}
+
+pub enum SectionContent<'a> {
+    Type(TypeSectionReader<'a>),
+    Function(FunctionSectionReader<'a>),
+    Code(CodeSectionReader<'a>),
+    Export(ExportSectionReader<'a>),
+    Import(ImportSectionReader<'a>),
+    Global(GlobalSectionReader<'a>),
+    Memory(MemorySectionReader<'a>),
+    Data(DataSectionReader<'a>),
+    Table(TableSectionReader<'a>),
+    Element(ElementSectionReader<'a>),
+    Start(u32),
+    DataCount(u32),
+    Custom {
+        name: &'a str,
+        binary: BinaryReader<'a>,
+        content: Option<CustomSectionContent<'a>>,
+    },
+}
+
+pub enum CustomSectionContent<'a> {
+    Name(NameSectionReader<'a>),
+    Producers(ProducersSectionReader<'a>),
+    Linking(LinkingSectionReader<'a>),
+    Reloc(RelocSectionReader<'a>),
+    SourceMappingURL(&'a str),
 }
 
 /// Reads top-level WebAssembly file structure: header and sections.
diff --git a/third_party/rust/wasmparser/src/tests.rs b/third_party/rust/wasmparser/src/tests.rs
index 84386855b90ed70cf9e11614524e7a3df05cd2ef..247345740441c3b2a45c7cffee107360c076a1d7 100644
--- a/third_party/rust/wasmparser/src/tests.rs
+++ b/third_party/rust/wasmparser/src/tests.rs
@@ -45,6 +45,7 @@ mod simple_tests {
         data
     }
 
+    #[allow(dead_code)]
     fn scan_tests_files(prefix: &str) -> Vec<PathBuf> {
         let mut files = Vec::new();
 
@@ -325,11 +326,12 @@ mod wast_tests {
     use crate::BinaryReaderError;
     use std::fs::{read, read_dir};
     use wabt::script::{Command, CommandKind, ModuleBinary, ScriptParser};
+    use wabt::Features;
 
     const SPEC_TESTS_PATH: &str = "testsuite";
 
-    fn validate_module(module: ModuleBinary) -> Result<(), BinaryReaderError> {
-        let config = ValidatingParserConfig {
+    fn default_config() -> ValidatingParserConfig {
+        ValidatingParserConfig {
             operator_config: OperatorValidatorConfig {
                 enable_threads: false,
                 enable_reference_types: false,
@@ -340,8 +342,13 @@ mod wast_tests {
                 #[cfg(feature = "deterministic")]
                 deterministic_only: true,
             },
-        };
+        }
+    }
 
+    fn validate_module(
+        module: ModuleBinary,
+        config: ValidatingParserConfig,
+    ) -> Result<(), BinaryReaderError> {
         let data = &module.into_vec();
         let mut parser = ValidatingParser::new(data.as_slice(), Some(config));
         let mut max_iteration = 100000000;
@@ -360,16 +367,35 @@ mod wast_tests {
         Ok(())
     }
 
-    fn skip_test(filename: &str, line: u64) -> bool {
-        match (filename, line) {
-            _ => false,
+    fn to_features(config: &ValidatingParserConfig) -> Features {
+        let mut features = Features::new();
+        if config.operator_config.enable_simd {
+            features.enable_simd();
         }
+        if config.operator_config.enable_reference_types {
+            features.enable_reference_types();
+        }
+        features
     }
 
-    fn run_wabt_scripts(filename: &str, wast: &[u8]) {
+    fn run_wabt_scripts<F>(
+        filename: &str,
+        wast: &[u8],
+        config: ValidatingParserConfig,
+        skip_test: F,
+    ) where
+        F: Fn(&str, u64) -> bool,
+    {
         println!("Parsing {:?}", filename);
+        // Check if we need to skip entire wast file test/parsing.
+        if skip_test(filename, /* line = */ 0) {
+            println!("{}: skipping", filename);
+            return;
+        }
+
+        let features = to_features(&config);
         let mut parser: ScriptParser<f32, f64> =
-            ScriptParser::from_str(std::str::from_utf8(wast).expect("valid utf8 wast"))
+            ScriptParser::from_source_and_name_with_features(wast, filename, features)
                 .expect("script parser");
 
         while let Some(Command { kind, line }) = parser.next().expect("parser") {
@@ -382,14 +408,14 @@ mod wast_tests {
                 CommandKind::Module { module, .. }
                 | CommandKind::AssertUninstantiable { module, .. }
                 | CommandKind::AssertUnlinkable { module, .. } => {
-                    if let Err(err) = validate_module(module) {
+                    if let Err(err) = validate_module(module, config.clone()) {
                         panic!("{}:{}: invalid module: {}", filename, line, err.message);
                     }
                 }
                 CommandKind::AssertInvalid { module, .. }
                 | CommandKind::AssertMalformed { module, .. } => {
                     // TODO diffentiate between assert_invalid and assert_malformed
-                    if let Ok(_) = validate_module(module) {
+                    if let Ok(_) = validate_module(module, config.clone()) {
                         panic!(
                             "{}:{}: invalid module was successfully parsed",
                             filename, line
@@ -408,6 +434,76 @@ mod wast_tests {
         }
     }
 
+    fn run_proposal_tests<F>(name: &str, config: ValidatingParserConfig, skip_test: F)
+    where
+        F: Fn(&str, u64) -> bool,
+    {
+        let proposal_dir = format!("{}/proposals/{}", SPEC_TESTS_PATH, name);
+        for entry in read_dir(&proposal_dir).unwrap() {
+            let dir = entry.unwrap();
+            if !dir.file_type().unwrap().is_file()
+                || dir.path().extension().map(|s| s.to_str().unwrap()) != Some("wast")
+            {
+                continue;
+            }
+
+            let data = read(&dir.path()).expect("wast data");
+            run_wabt_scripts(
+                dir.file_name().to_str().expect("name"),
+                &data,
+                config,
+                |name, line| skip_test(name, line),
+            );
+        }
+    }
+
+    #[test]
+    fn run_proposals_tests() {
+        run_proposal_tests(
+            "simd",
+            {
+                let mut config: ValidatingParserConfig = default_config();
+                config.operator_config.enable_simd = true;
+                config
+            },
+            |name, line| match (name, line) {
+                ("simd_address.wast", _)
+                | ("simd_const.wast", _)
+                | ("simd_f32x4_cmp.wast", _)
+                | ("simd_store.wast", _)
+                | ("simd_lane.wast", _)
+                | ("simd_load.wast", _) => true,
+                _ => false,
+            },
+        );
+
+        run_proposal_tests(
+            "reference-types",
+            {
+                let mut config: ValidatingParserConfig = default_config();
+                config.operator_config.enable_reference_types = true;
+                config
+            },
+            |name, line| match (name, line) {
+                ("ref_null.wast", _)
+                | ("ref_is_null.wast", _)
+                | ("ref_func.wast", _)
+                | ("linking.wast", _)
+                | ("globals.wast", _)
+                | ("imports.wast", _)
+                | ("br_table.wast", _)
+                | ("select.wast", _)
+                | ("table_get.wast", _)
+                | ("table_set.wast", _)
+                | ("table_size.wast", _)
+                | ("table_fill.wast", _)
+                | ("table_grow.wast", _)
+                | ("exports.wast", _) => true,
+                _ => false,
+            },
+        );
+    }
+
     #[test]
     fn run_spec_tests() {
         for entry in read_dir(SPEC_TESTS_PATH).unwrap() {
@@ -419,7 +515,12 @@ mod wast_tests {
             }
 
             let data = read(&dir.path()).expect("wast data");
-            run_wabt_scripts(dir.file_name().to_str().expect("name"), &data);
+            run_wabt_scripts(
+                dir.file_name().to_str().expect("name"),
+                &data,
+                default_config(),
+                |_, _| false,
+            );
         }
     }
 }
diff --git a/third_party/rust/wasmparser/src/validator.rs b/third_party/rust/wasmparser/src/validator.rs
index d783a63b8c7b692738de4dbf4b0f3e7c53ddc1c0..b84ae69b63d60adec5fa2586f304ced6b2b26a37 100644
--- a/third_party/rust/wasmparser/src/validator.rs
+++ b/third_party/rust/wasmparser/src/validator.rs
@@ -34,8 +34,8 @@ use crate::primitives::{
 use crate::parser::{Parser, ParserInput, ParserState, WasmDecoder};
 
 use crate::operators_validator::{
-    FunctionEnd, OperatorValidator, OperatorValidatorConfig, WasmModuleResources,
-    DEFAULT_OPERATOR_VALIDATOR_CONFIG,
+    is_subtype_supertype, FunctionEnd, OperatorValidator, OperatorValidatorConfig,
+    WasmModuleResources, DEFAULT_OPERATOR_VALIDATOR_CONFIG,
 };
 
 use crate::readers::FunctionBody;
@@ -196,6 +196,12 @@ impl<'a> ValidatingParser<'a> {
     fn check_value_type(&self, ty: Type) -> ValidatorResult<'a, ()> {
         match ty {
             Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
+            Type::Null | Type::AnyFunc | Type::AnyRef => {
+                if !self.config.operator_config.enable_reference_types {
+                    return self.create_error("reference types support is not enabled");
+                }
+                Ok(())
+            }
             Type::V128 => {
                 if !self.config.operator_config.enable_simd {
                     return self.create_error("SIMD support is not enabled");
@@ -301,6 +307,12 @@ impl<'a> ValidatingParser<'a> {
             Operator::I64Const { .. } => Type::I64,
             Operator::F32Const { .. } => Type::F32,
             Operator::F64Const { .. } => Type::F64,
+            Operator::RefNull => {
+                if !self.config.operator_config.enable_reference_types {
+                    return self.create_error("reference types support is not enabled");
+                }
+                Type::Null
+            }
             Operator::V128Const { .. } => {
                 if !self.config.operator_config.enable_simd {
                     return self.create_error("SIMD support is not enabled");
@@ -315,7 +327,7 @@ impl<'a> ValidatingParser<'a> {
             }
             _ => return self.create_error("invalid init_expr operator"),
         };
-        if ty != state.ty {
+        if !is_subtype_supertype(ty, state.ty) {
             return self.create_error("invalid init_expr type");
         }
         Ok(())
@@ -781,67 +793,72 @@ impl<'b> ValidatingOperatorParser<'b> {
 /// The resources parameter contains all needed data to validate the operators.
 pub fn validate_function_body(
     bytes: &[u8],
+    offset: usize,
     func_index: u32,
     resources: &dyn WasmModuleResources,
     operator_config: Option<OperatorValidatorConfig>,
-) -> bool {
+) -> Result<()> {
     let operator_config = operator_config.unwrap_or(DEFAULT_OPERATOR_VALIDATOR_CONFIG);
-    let function_body = FunctionBody::new(0, bytes);
-    let mut locals_reader = if let Ok(r) = function_body.get_locals_reader() {
-        r
-    } else {
-        return false;
-    };
+    let function_body = FunctionBody::new(offset, bytes);
+    let mut locals_reader = function_body.get_locals_reader()?;
     let local_count = locals_reader.get_count() as usize;
     if local_count > MAX_WASM_FUNCTION_LOCALS {
-        return false;
+        Err(BinaryReaderError {
+            message: "locals exceed maximum",
+            offset: locals_reader.original_position(),
+        })?;
     }
     let mut locals: Vec<(u32, Type)> = Vec::with_capacity(local_count);
     let mut locals_total: usize = 0;
     for _ in 0..local_count {
-        let (count, ty) = if let Ok(r) = locals_reader.read() {
-            r
-        } else {
-            return false;
-        };
-        locals_total = if let Some(r) = locals_total.checked_add(count as usize) {
-            r
-        } else {
-            return false;
-        };
+        let (count, ty) = locals_reader.read()?;
+        locals_total =
+            locals_total
+                .checked_add(count as usize)
+                .ok_or_else(|| BinaryReaderError {
+                    message: "locals overflow",
+                    offset: locals_reader.original_position(),
+                })?;
         if locals_total > MAX_WASM_FUNCTION_LOCALS {
-            return false;
+            Err(BinaryReaderError {
+                message: "locals exceed maximum",
+                offset: locals_reader.original_position(),
+            })?;
         }
         locals.push((count, ty));
     }
-    let operators_reader = if let Ok(r) = function_body.get_operators_reader() {
-        r
-    } else {
-        return false;
-    };
+    let operators_reader = function_body.get_operators_reader()?;
     let func_type_index = resources.func_type_indices()[func_index as usize];
     let func_type = &resources.types()[func_type_index as usize];
     let mut operator_validator = OperatorValidator::new(func_type, &locals, operator_config);
     let mut eof_found = false;
-    for op in operators_reader.into_iter() {
-        let op = match op {
-            Err(_) => return false,
-            Ok(ref op) => op,
-        };
-        match operator_validator.process_operator(op, resources) {
-            Err(_) => return false,
-            Ok(FunctionEnd::Yes) => {
+    let mut last_op = 0;
+    for item in operators_reader.into_iter_with_offsets() {
+        let (ref op, offset) = item?;
+        match operator_validator
+            .process_operator(op, resources)
+            .map_err(|message| BinaryReaderError { message, offset })?
+        {
+            FunctionEnd::Yes => {
                 eof_found = true;
             }
-            Ok(FunctionEnd::No) => (),
+            FunctionEnd::No => {
+                last_op = offset;
+            }
         }
     }
-    eof_found
+    if !eof_found {
+        Err(BinaryReaderError {
+            message: "end of function not found",
+            offset: last_op,
+        })?;
+    }
+    Ok(())
 }
 
 /// Test whether the given buffer contains a valid WebAssembly module,
 /// analogous to WebAssembly.validate in the JS API.
-pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool {
+pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> Result<()> {
     let mut parser = ValidatingParser::new(bytes, config);
     let mut parser_input = None;
     let mut func_ranges = Vec::new();
@@ -850,7 +867,7 @@ pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool {
         let state = parser.read_with_input(next_input);
         match *state {
             ParserState::EndWasm => break,
-            ParserState::Error(_) => return false,
+            ParserState::Error(e) => Err(e)?,
             ParserState::BeginFunctionBody { range } => {
                 parser_input = Some(ParserInput::SkipFunctionBody);
                 func_ranges.push(range);
@@ -862,23 +879,19 @@ pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> bool {
     for (i, range) in func_ranges.into_iter().enumerate() {
         let function_body = range.slice(bytes);
         let function_index = i as u32 + parser.func_imports_count;
-        if !validate_function_body(
+        validate_function_body(
             function_body,
+            range.start,
             function_index,
             &parser.resources,
             operator_config,
-        ) {
-            return false;
-        }
+        )?;
     }
-    true
+    Ok(())
 }
 
 #[test]
 fn test_validate() {
-    assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0], None));
-    assert!(!validate(
-        &[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0],
-        None
-    ));
+    assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0], None).is_ok());
+    assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0], None).is_err());
 }