Repository: bytecodealliance/wasmtime
Pull request #6196 (2023-04-11 10:54:44)

egraphs: Add `bmask` bit pattern optimization rule
👋 Hey,

This is something I wrote in #5888 and then [@elliottt pointed out that It's just `bmask`](https://github.com/bytecodealliance/wasmtime/pull/5888/commits/497922f547c2299f5d317a73e843b48866c9e863#r1161902682). I checked if we had a rule for this in the mid end and we don't.

This is a really long rule, and I'm not sure how often it's going to fire. But I also got that lowering from [here](https://github.com/RustCrypto/utils/blob/0256fff4d67edb4956f5200b877f41038c4ef7e7/cmov/src/portable.rs#L46-L47) so it is out there in the real world.

This is based on top of #6140 so that we don't have to rebase that again.

I'm going to let the fuzzer run on this for a while.


Kmeakin: https://github.com/bytecodealliance/wasmtime/pull/6140 has been merged, so the first 2 commits can be removed

Patch:
diff --git a/cranelift/codegen/meta/src/isa/x86.rs b/cranelift/codegen/meta/src/isa/x86.rs
index 8fc6cd27b..e385388e3 100644
--- a/cranelift/codegen/meta/src/isa/x86.rs
+++ b/cranelift/codegen/meta/src/isa/x86.rs
@@ -38,7 +38,7 @@ fn define_settings(shared: &SettingGroup) -> SettingGroup {
         "has_sse42",
         "Has support for SSE4.2.",
         "SSE4.2: CPUID.01H:ECX.SSE4_2[bit 20]",
-        true,
+        false,
     );
     let has_avx = settings.add_bool(
         "has_avx",
diff --git a/cranelift/codegen/src/isa/aarch64/mod.rs b/cranelift/codegen/src/isa/aarch64/mod.rs
index a5403ca5c..1c3f2809c 100644
--- a/cranelift/codegen/src/isa/aarch64/mod.rs
+++ b/cranelift/codegen/src/isa/aarch64/mod.rs
@@ -1,7 +1,6 @@
 //! ARM 64-bit Instruction Set Architecture.
 
 use crate::dominator_tree::DominatorTree;
-use crate::ir::condcodes::IntCC;
 use crate::ir::{Function, Type};
 use crate::isa::aarch64::settings as aarch64_settings;
 #[cfg(feature = "unwind")]
@@ -134,12 +133,6 @@ impl TargetIsa for AArch64Backend {
         16
     }
 
-    fn unsigned_add_overflow_condition(&self) -> IntCC {
-        // Unsigned `>=`; this corresponds to the carry flag set on aarch64, which happens on
-        // overflow of an add.
-        IntCC::UnsignedGreaterThanOrEqual
-    }
-
     #[cfg(feature = "unwind")]
     fn emit_unwind_info(
         &self,
diff --git a/cranelift/codegen/src/isa/mod.rs b/cranelift/codegen/src/isa/mod.rs
index da778c9b6..6ea98af98 100644
--- a/cranelift/codegen/src/isa/mod.rs
+++ b/cranelift/codegen/src/isa/mod.rs
@@ -286,9 +286,6 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
         Err(RegisterMappingError::UnsupportedArchitecture)
     }
 
-    /// IntCC condition for Unsigned Addition Overflow (Carry).
-    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC;
-
     /// Creates unwind information for the function.
     ///
     /// Returns `None` if there is no unwind information for the function.
diff --git a/cranelift/codegen/src/isa/riscv64/mod.rs b/cranelift/codegen/src/isa/riscv64/mod.rs
index f567481e9..8babe53e9 100644
--- a/cranelift/codegen/src/isa/riscv64/mod.rs
+++ b/cranelift/codegen/src/isa/riscv64/mod.rs
@@ -2,7 +2,6 @@
 
 use crate::dominator_tree::DominatorTree;
 use crate::ir;
-use crate::ir::condcodes::IntCC;
 use crate::ir::Function;
 
 use crate::isa::riscv64::settings as riscv_settings;
@@ -130,10 +129,6 @@ impl TargetIsa for Riscv64Backend {
         self.isa_flags.iter().collect()
     }
 
-    fn unsigned_add_overflow_condition(&self) -> IntCC {
-        IntCC::UnsignedGreaterThanOrEqual
-    }
-
     #[cfg(feature = "unwind")]
     fn emit_unwind_info(
         &self,
diff --git a/cranelift/codegen/src/isa/s390x/mod.rs b/cranelift/codegen/src/isa/s390x/mod.rs
index d2705e78c..bcd3c733b 100644
--- a/cranelift/codegen/src/isa/s390x/mod.rs
+++ b/cranelift/codegen/src/isa/s390x/mod.rs
@@ -1,7 +1,6 @@
 //! IBM Z 64-bit Instruction Set Architecture.
 
 use crate::dominator_tree::DominatorTree;
-use crate::ir::condcodes::IntCC;
 use crate::ir::{Function, Type};
 use crate::isa::s390x::settings as s390x_settings;
 #[cfg(feature = "unwind")]
@@ -131,15 +130,6 @@ impl TargetIsa for S390xBackend {
         16
     }
 
-    fn unsigned_add_overflow_condition(&self) -> IntCC {
-        // The ADD LOGICAL family of instructions set the condition code
-        // differently from normal comparisons, in a way that cannot be
-        // represented by any of the standard IntCC values.  So we use a
-        // dummy value here, which gets remapped to the correct condition
-        // code mask during lowering.
-        IntCC::UnsignedGreaterThan
-    }
-
     #[cfg(feature = "unwind")]
     fn emit_unwind_info(
         &self,
diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle
index bde21d48d..97540660b 100644
--- a/cranelift/codegen/src/isa/x64/inst.isle
+++ b/cranelift/codegen/src/isa/x64/inst.isle
@@ -1642,6 +1642,9 @@
 (decl use_sse41 (bool) Type)
 (extern extractor infallible use_sse41 use_sse41)
 
+(decl pure use_sse42 () bool)
+(extern constructor use_sse42 use_sse42)
+
 (decl pure use_avx_simd () bool)
 (extern constructor use_avx_simd use_avx_simd)
 
@@ -4214,7 +4217,51 @@
 (rule (x64_pcmpgt $I8X16 x y) (x64_pcmpgtb x y))
 (rule (x64_pcmpgt $I16X8 x y) (x64_pcmpgtw x y))
 (rule (x64_pcmpgt $I32X4 x y) (x64_pcmpgtd x y))
-(rule (x64_pcmpgt $I64X2 x y) (x64_pcmpgtq x y))
+
+;; SSE4.2 gives a single-instruction for this lowering, but prior to that it's a
+;; bit more complicated.
+(rule 1 (x64_pcmpgt $I64X2 x y)
+        (if-let $true (use_sse42))
+        (x64_pcmpgtq x y))
+
+;; Without SSE4.2 a 64-bit comparison is expanded to a number of instructions.
+;; The basic idea is to delegate to a 32-bit comparison and work with the
+;; results from there. The comparison to execute is:
+;;
+;;    [ xhi ][ xlo ] > [ yhi ][ ylo ]
+;;
+;; If xhi != yhi, then the result is whatever the result of that comparison is.
+;; If xhi == yhi, then the result is the unsigned comparison of xlo/ylo since
+;; the 64-bit value is positive. To achieve this as part of the same comparison
+;; the upper bit of `xlo` and `ylo` is flipped to change the sign when compared
+;; as a 32-bit signed number. The result here is then:
+;;
+;; * if xlo and yhi had the same upper bit, then the unsigned comparison should
+;;   be the same as comparing the flipped versions as signed.
+;; * if xlo had an upper bit of 0 and ylo had an upper bit of 1, then xlo > ylo
+;;   is false. When flipping the bits xlo becomes negative and ylo becomes
+;;   positive when compared as 32-bits, so the result is the same.
+;; * if xlo had an upper bit of 1 and ylo had an upper bit of 0, then xlo > ylo
+;;   is true. When flipping the bits xlo becomes positive and ylo becomes
+;;   negative when compared as 32-bits, so the result is the same.
+;;
+;; Given all that the sequence here is to flip the upper bits of xlo and ylo,
+;; then compare the masked results for equality and for gt. If the upper 32-bits
+;; are not equal then the gt result for the upper bits is used. If the upper
+;; 32-bits are equal then the lower 32-bits comparison is used instead.
+(rule 0 (x64_pcmpgt $I64X2 x y)
+        (let (
+            (mask Xmm (x64_movdqu_load (emit_u128_le_const 0x00000000_80000000_00000000_80000000)))
+            (x_masked           Xmm (x64_pxor mask x))
+            (y_masked           Xmm (x64_pxor mask y))
+            (cmp32              Xmm (x64_pcmpgtd x_masked y_masked))
+            (low_halves_gt      Xmm (x64_pshufd cmp32 0xa0))
+            (high_halves_gt     Xmm (x64_pshufd cmp32 0xf5))
+            (cmp_eq             Xmm (x64_pcmpeqd x_masked y_masked))
+            (high_halves_eq     Xmm (x64_pshufd cmp_eq 0xf5))
+            (low_gt_and_high_eq Xmm (x64_pand low_halves_gt high_halves_eq))
+          )
+          (x64_por low_gt_and_high_eq high_halves_gt)))
 
 (decl x64_pcmpgtb (Xmm XmmMem) Xmm)
 (rule 0 (x64_pcmpgtb x y) (xmm_rm_r (SseOpcode.Pcmpgtb) x y))
diff --git a/cranelift/codegen/src/isa/x64/lower/isle.rs b/cranelift/codegen/src/isa/x64/lower/isle.rs
index bf328b526..36302e39c 100644
--- a/cranelift/codegen/src/isa/x64/lower/isle.rs
+++ b/cranelift/codegen/src/isa/x64/lower/isle.rs
@@ -229,6 +229,11 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
         self.backend.x64_flags.use_sse41()
     }
 
+    #[inline]
+    fn use_sse42(&mut self) -> bool {
+        self.backend.x64_flags.use_sse42()
+    }
+
     #[inline]
     fn imm8_from_value(&mut self, val: Value) -> Option<Imm8Reg> {
         let inst = self.lower_ctx.dfg().value_def(val).inst()?;
diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs
index 029c7f9f5..ad04e0e20 100644
--- a/cranelift/codegen/src/isa/x64/mod.rs
+++ b/cranelift/codegen/src/isa/x64/mod.rs
@@ -4,7 +4,7 @@ pub use self::inst::{args, CallInfo, EmitInfo, EmitState, Inst};
 
 use super::{OwnedTargetIsa, TargetIsa};
 use crate::dominator_tree::DominatorTree;
-use crate::ir::{condcodes::IntCC, Function, Type};
+use crate::ir::{Function, Type};
 #[cfg(feature = "unwind")]
 use crate::isa::unwind::systemv;
 use crate::isa::x64::{inst::regs::create_reg_env_systemv, settings as x64_settings};
@@ -124,12 +124,6 @@ impl TargetIsa for X64Backend {
         &self.triple
     }
 
-    fn unsigned_add_overflow_condition(&self) -> IntCC {
-        // Unsigned `<`; this corresponds to the carry flag set on x86, which
-        // indicates an add has overflowed.
-        IntCC::UnsignedLessThan
-    }
-
     #[cfg(feature = "unwind")]
     fn emit_unwind_info(
         &self,
@@ -222,13 +216,9 @@ fn isa_constructor(
     // Check for compatibility between flags and ISA level
     // requested. In particular, SIMD support requires SSE4.2.
     if shared_flags.enable_simd() {
-        if !isa_flags.has_sse3()
-            || !isa_flags.has_ssse3()
-            || !isa_flags.has_sse41()
-            || !isa_flags.has_sse42()
-        {
+        if !isa_flags.has_sse3() || !isa_flags.has_ssse3() || !isa_flags.has_sse41() {
             return Err(CodegenError::Unsupported(
-                "SIMD support requires SSE3, SSSE3, SSE4.1, and SSE4.2 on x86_64.".into(),
+                "SIMD support requires SSE3, SSSE3, and SSE4.1 on x86_64.".into(),
             ));
         }
     }
@@ -253,7 +243,6 @@ mod test {
         isa_builder.set("has_sse3", "false").unwrap();
         isa_builder.set("has_ssse3", "false").unwrap();
         isa_builder.set("has_sse41", "false").unwrap();
-        isa_builder.set("has_sse42", "false").unwrap();
         assert!(matches!(
             isa_builder.finish(shared_flags),
             Err(CodegenError::Unsupported(_)),
diff --git a/cranelift/codegen/src/opts/arithmetic.isle b/cranelift/codegen/src/opts/arithmetic.isle
index e0e79980e..00c56c240 100644
--- a/cranelift/codegen/src/opts/arithmetic.isle
+++ b/cranelift/codegen/src/opts/arithmetic.isle
@@ -67,6 +67,25 @@
       (if-let -1 (i64_sextend_imm64 ty c))
       (ineg ty x))
 
+;; (!x) + 1 == 1 + (!x) == !(x) - (-1) == ineg(x)
+(rule (simplify (iadd ty (bnot ty x) (iconst ty (u64_from_imm64 1))))
+      (ineg ty x))
+(rule (simplify (iadd ty (iconst ty (u64_from_imm64 1)) (bnot ty x)))
+      (ineg ty x))
+(rule (simplify (isub ty (bnot ty x) (iconst ty c)))
+      (if-let -1 (i64_sextend_imm64 ty c))
+      (ineg ty x))
+
+;; !(x - 1) == !(x + (-1)) == !((-1) + x) == ineg(x)
+(rule (simplify (bnot ty (isub ty x (iconst ty (u64_from_imm64 1)))))
+      (ineg ty x))
+(rule (simplify (bnot ty (iadd ty x (iconst ty c))))
+      (if-let -1 (i64_sextend_imm64 ty c))
+      (ineg ty x))
+(rule (simplify (bnot ty (iadd ty (iconst ty c) x)))
+      (if-let -1 (i64_sextend_imm64 ty c))
+      (ineg ty x))
+
 ;; x/1 == x.
 (rule (simplify (sdiv ty
                       x
diff --git a/cranelift/codegen/src/opts/bitops.isle b/cranelift/codegen/src/opts/bitops.isle
index bf32251ca..09836d3a6 100644
--- a/cranelift/codegen/src/opts/bitops.isle
+++ b/cranelift/codegen/src/opts/bitops.isle
@@ -92,3 +92,15 @@
 (rule (simplify (bxor ty x (iconst ty k)))
   (if-let -1 (i64_sextend_imm64 ty k))
   (bnot ty x))
+
+;; sshr((x | -x), N) == bmask(x) where N = ty_bits(ty) - 1.
+;;
+;; (x | -x) sets the sign bit to 1 if x is nonzero, and 0 if x is zero. sshr propagates
+;; the sign bit to the rest of the value.
+(rule (simplify (sshr ty (bor ty x (ineg ty x)) (iconst ty (u64_from_imm64 shift_amt))))
+      (if-let $true (u64_eq shift_amt (u64_sub (ty_bits ty) 1)))
+      (bmask ty x))
+
+(rule (simplify (sshr ty (bor ty (ineg ty x) x) (iconst ty (u64_from_imm64 shift_amt))))
+      (if-let $true (u64_eq shift_amt (u64_sub (ty_bits ty) 1)))
+      (bmask ty x))
diff --git a/cranelift/codegen/src/opts/shifts.isle b/cranelift/codegen/src/opts/shifts.isle
index 445f5467c..44c79a6f8 100644
--- a/cranelift/codegen/src/opts/shifts.isle
+++ b/cranelift/codegen/src/opts/shifts.isle
@@ -78,3 +78,8 @@
       (if-let (u64_from_imm64 shift_u64) shift)
       (if-let $true (u64_le shift_u64 (u64_sub (ty_bits_u64 wide) (ty_bits_u64 narrow))))
       x)
+
+;; ineg(ushr(x, k)) == sshr(x, k) when k == ty_bits - 1.
+(rule (simplify (ineg ty (ushr ty x sconst @ (iconst ty (u64_from_imm64 shift_amt)))))
+      (if-let $true (u64_eq shift_amt (u64_sub (ty_bits ty) 1)))
+      (sshr ty x sconst))
diff --git a/cranelift/native/src/lib.rs b/cranelift/native/src/lib.rs
index 342562100..5a4418160 100644
--- a/cranelift/native/src/lib.rs
+++ b/cranelift/native/src/lib.rs
@@ -80,7 +80,6 @@ pub fn infer_native_flags(isa_builder: &mut dyn Configurable) -> Result<(), &'st
         isa_builder.set("has_sse3", "false").unwrap();
         isa_builder.set("has_ssse3", "false").unwrap();
         isa_builder.set("has_sse41", "false").unwrap();
-        isa_builder.set("has_sse42", "false").unwrap();
 
         if std::is_x86_feature_detected!("sse3") {
             isa_builder.enable("has_sse3").unwrap();
diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs
index 030e0c9ed..d17eda818 100644
--- a/cranelift/wasm/src/environ/dummy.rs
+++ b/cranelift/wasm/src/environ/dummy.rs
@@ -655,10 +655,6 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
     ) -> WasmResult<ir::Value> {
         Ok(pos.ins().iconst(I32, 0))
     }
-
-    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
-        unimplemented!()
-    }
 }
 
 impl TargetEnvironment for DummyEnvironment {
diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs
index 03121c8c9..63712c3b9 100644
--- a/cranelift/wasm/src/environ/spec.rs
+++ b/cranelift/wasm/src/environ/spec.rs
@@ -522,10 +522,6 @@ pub trait FuncEnvironment: TargetEnvironment {
         Ok(())
     }
 
-    /// Returns the target ISA's condition to check for unsigned addition
-    /// overflowing.
-    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC;
-
     /// Whether or not to force relaxed simd instructions to have deterministic
     /// lowerings meaning they will produce the same results across all hosts,
     /// regardless of the cost to performance.
diff --git a/crates/component-macro/src/bindgen.rs b/crates/component-macro/src/bindgen.rs
index 2a813ef5f..b589665b5 100644
--- a/crates/component-macro/src/bindgen.rs
+++ b/crates/component-macro/src/bindgen.rs
@@ -78,7 +78,16 @@ impl Parse for Config {
                     Opt::Async(val) => opts.async_ = val,
                     Opt::TrappableErrorType(val) => opts.trappable_error_type = val,
                     Opt::DuplicateIfNecessary(val) => opts.duplicate_if_necessary = val,
-                    Opt::OnlyInterfaces(val) => opts.only_interfaces = val,
+                    Opt::Interfaces(s) => {
+                        if source.is_some() {
+                            return Err(Error::new(s.span(), "cannot specify a second source"));
+                        }
+                        source = Some(Source::Inline(format!(
+                            "default world interfaces {{ {} }}",
+                            s.value()
+                        )));
+                        opts.only_interfaces = true;
+                    }
                     Opt::With(val) => opts.with.extend(val),
                 }
             }
@@ -136,7 +145,7 @@ mod kw {
     syn::custom_keyword!(trappable_error_type);
     syn::custom_keyword!(world);
     syn::custom_keyword!(duplicate_if_necessary);
-    syn::custom_keyword!(only_interfaces);
+    syn::custom_keyword!(interfaces);
     syn::custom_keyword!(with);
 }
 
@@ -148,7 +157,7 @@ enum Opt {
     Async(bool),
     TrappableErrorType(Vec<TrappableError>),
     DuplicateIfNecessary(bool),
-    OnlyInterfaces(bool),
+    Interfaces(syn::LitStr),
     With(HashMap<String, String>),
 }
 
@@ -198,10 +207,10 @@ impl Parse for Opt {
                     })
                     .collect(),
             ))
-        } else if l.peek(kw::only_interfaces) {
-            input.parse::<kw::only_interfaces>()?;
+        } else if l.peek(kw::interfaces) {
+            input.parse::<kw::interfaces>()?;
             input.parse::<Token![:]>()?;
-            Ok(Opt::OnlyInterfaces(input.parse::<syn::LitBool>()?.value))
+            Ok(Opt::Interfaces(input.parse::<syn::LitStr>()?))
         } else if l.peek(kw::with) {
             input.parse::<kw::with>()?;
             input.parse::<Token![:]>()?;
diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs
index 55272b1b9..305d12355 100644
--- a/crates/cranelift/src/func_environ.rs
+++ b/crates/cranelift/src/func_environ.rs
@@ -2150,10 +2150,6 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
         Ok(())
     }
 
-    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
-        self.isa.unsigned_add_overflow_condition()
-    }
-
     fn relaxed_simd_deterministic(&self) -> bool {
         self.tunables.relaxed_simd_deterministic
     }
diff --git a/crates/fuzzing/src/generators/codegen_settings.rs b/crates/fuzzing/src/generators/codegen_settings.rs
index 30484d009..9f2841d91 100644
--- a/crates/fuzzing/src/generators/codegen_settings.rs
+++ b/crates/fuzzing/src/generators/codegen_settings.rs
@@ -35,7 +35,7 @@ impl CodegenSettings {
         }
     }
 
-    /// Features such as sse4.2 are unconditionally enabled on the x86_64 target
+    /// Features such as sse3 are unconditionally enabled on the x86_64 target
     /// because they are hard required for SIMD, but when SIMD is disabled, for
     /// example, we support disabling these features.
     ///
@@ -57,7 +57,7 @@ impl CodegenSettings {
             // to have test case failures unrelated to codegen setting input
             // that fail on one architecture to fail on other architectures as
             // well.
-            let new_flags = ["has_sse3", "has_ssse3", "has_sse41", "has_sse42"]
+            let new_flags = ["has_sse3", "has_ssse3", "has_sse41"]
                 .into_iter()
                 .map(|name| Ok((name, u.arbitrary()?)))
                 .collect::<arbitrary::Result<HashMap<_, bool>>>()?;
@@ -147,8 +147,8 @@ impl<'a> Arbitrary<'a> for CodegenSettings {
                     std:"sse3" => clif:"has_sse3" ratio: 1 in 1,
                     std:"ssse3" => clif:"has_ssse3" ratio: 1 in 1,
                     std:"sse4.1" => clif:"has_sse41" ratio: 1 in 1,
-                    std:"sse4.2" => clif:"has_sse42" ratio: 1 in 1,
 
+                    std:"sse4.2" => clif:"has_sse42",
                     std:"popcnt" => clif:"has_popcnt",
                     std:"avx" => clif:"has_avx",
                     std:"avx2" => clif:"has_avx2",
diff --git a/crates/wasmtime/README.md b/crates/wasmtime/README.md
index 7c2cddd49..a1b29d7fe 100644
--- a/crates/wasmtime/README.md
+++ b/crates/wasmtime/README.md
@@ -72,7 +72,7 @@ fn main() -> Result<()> {
     let engine = Engine::default();
     let wat = r#"
         (module
-            (import "host" "hello" (func $host_hello (param i32)))
+            (import "host" "host_func" (func $host_hello (param i32)))
 
             (func (export "hello")
                 i32.const 3
@@ -84,7 +84,7 @@ fn main() -> Result<()> {
     // Create a `Linker` which will be later used to instantiate this module.
     // Host functionality is defined by name within the `Linker`.
     let mut linker = Linker::new(&engine);
-    linker.func_wrap("host", "hello", |caller: Caller<'_, u32>, param: i32| {
+    linker.func_wrap("host", "host_func", |caller: Caller<'_, u32>, param: i32| {
         println!("Got {} from WebAssembly", param);
         println!("my host state is: {}", caller.data());
     })?;
diff --git a/crates/wasmtime/src/component/mod.rs b/crates/wasmtime/src/component/mod.rs
index 3dd7b740d..21550adef 100644
--- a/crates/wasmtime/src/component/mod.rs
+++ b/crates/wasmtime/src/component/mod.rs
@@ -292,11 +292,11 @@ pub(crate) use self::store::ComponentStoreData;
 ///         interface::ErrorType: RustErrorType,
 ///     },
 ///
-///     // Restrict the code generated to what's needed for the imported
-///     // interfaces of the world file provided. This option is most useful
-///     // in conjunction with the `with` option that permits remapping of
-///     // interface names in generated code.
-///     only_interfaces: true,
+///     // Restrict the code generated to what's needed for the interface
+///     // imports in the inlined WIT document fragment.
+///     interfaces: "
+///         import foo: package.foo;
+///     ",
 ///
 ///     // Remap interface names to module names, imported from elswhere.
 ///     // Using this option will prevent any code from being generated
diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs
index dd54cdc77..b1ba2004b 100644
--- a/crates/wasmtime/src/lib.rs
+++ b/crates/wasmtime/src/lib.rs
@@ -34,7 +34,7 @@
 //!     let engine = Engine::default();
 //!     let wat = r#"
 //!         (module
-//!             (import "host" "hello" (func $host_hello (param i32)))
+//!             (import "host" "host_func" (func $host_hello (param i32)))
 //!
 //!             (func (export "hello")
 //!                 i32.const 3
@@ -47,7 +47,7 @@
 //!     // `Store` has a type parameter to store host-specific data, which in
 //!     // this case we're using `4` for.
 //!     let mut store = Store::new(&engine, 4);
-//!     let host_hello = Func::wrap(&mut store, |caller: Caller<'_, u32>, param: i32| {
+//!     let host_func = Func::wrap(&mut store, |caller: Caller<'_, u32>, param: i32| {
 //!         println!("Got {} from WebAssembly", param);
 //!         println!("my host state is: {}", caller.data());
 //!     });
@@ -55,7 +55,7 @@
 //!     // Instantiation of a module requires specifying its imports and then
 //!     // afterwards we can fetch exports by name, as well as asserting the
 //!     // type signature of the function with `get_typed_func`.
-//!     let instance = Instance::new(&mut store, &module, &[host_hello.into()])?;
+//!     let instance = Instance::new(&mut store, &module, &[host_func.into()])?;
 //!     let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?;
 //!
 //!     // And finally we can call the wasm!
@@ -146,7 +146,7 @@
 //!     let engine = Engine::default();
 //!     let wat = r#"
 //!         (module
-//!             (import "host" "hello" (func $host_hello (param i32)))
+//!             (import "host" "host_func" (func $host_hello (param i32)))
 //!
 //!             (func (export "hello")
 //!                 i32.const 3
@@ -157,7 +157,7 @@
 //!
 //!     // Create a `Linker` and define our host function in it:
 //!     let mut linker = Linker::new(&engine);
-//!     linker.func_wrap("host", "hello", |caller: Caller<'_, u32>, param: i32| {
+//!     linker.func_wrap("host", "host_func", |caller: Caller<'_, u32>, param: i32| {
 //!         println!("Got {} from WebAssembly", param);
 //!         println!("my host state is: {}", caller.data());
 //!     })?;
diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs
index f564a5a95..5af48778c 100644
--- a/crates/wit-bindgen/src/lib.rs
+++ b/crates/wit-bindgen/src/lib.rs
@@ -1112,11 +1112,12 @@ impl<'a> InterfaceGenerator<'a> {
         }
 
         if self.gen.opts.tracing {
-            self.src.push_str(&format!(
+            uwrite!(
+                self.src,
                 "
                    let span = tracing::span!(
                        tracing::Level::TRACE,
-                       \"wit-bindgen guest import\",
+                       \"wit-bindgen import\",
                        module = \"{}\",
                        function = \"{}\",
                    );
@@ -1131,7 +1132,22 @@ impl<'a> InterfaceGenerator<'a> {
                     TypeOwner::None => "<no owner>",
                 },
                 func.name,
-            ));
+            );
+            let mut event_fields = func
+                .params
+                .iter()
+                .enumerate()
+                .map(|(i, (name, _ty))| {
+                    let name = to_rust_ident(&name);
+                    format!("{name} = tracing::field::debug(&arg{i})")
+                })
+                .collect::<Vec<String>>();
+            event_fields.push(format!("\"call\""));
+            uwrite!(
+                self.src,
+                "tracing::event!(tracing::Level::TRACE, {});\n",
+                event_fields.join(", ")
+            );
         }
 
         self.src.push_str("let host = get(caller.data_mut());\n");
@@ -1146,6 +1162,13 @@ impl<'a> InterfaceGenerator<'a> {
             uwrite!(self.src, ");\n");
         }
 
+        if self.gen.opts.tracing {
+            uwrite!(
+                self.src,
+                "tracing::event!(tracing::Level::TRACE, result = tracing::field::debug(&r), \"return\");"
+            );
+        }
+
         if self
             .special_case_trappable_error(owner, &func.results)
             .is_some()
@@ -1272,7 +1295,7 @@ impl<'a> InterfaceGenerator<'a> {
                 "
                    let span = tracing::span!(
                        tracing::Level::TRACE,
-                       \"wit-bindgen guest export\",
+                       \"wit-bindgen export\",
                        module = \"{}\",
                        function = \"{}\",
                    );


Test patch:
diff --git a/cranelift/filetests/filetests/egraph/arithmetic.clif b/cranelift/filetests/filetests/egraph/arithmetic.clif
index 7a014954d..630aebeca 100644
--- a/cranelift/filetests/filetests/egraph/arithmetic.clif
+++ b/cranelift/filetests/filetests/egraph/arithmetic.clif
@@ -73,6 +73,74 @@ block0(v0: i32):
     ; check: return v3
 }
 
+function %ineg_not_plus_one(i32) -> i32 {
+block0(v0: i32):
+    v1 = bnot v0
+    v2 = iconst.i32 1
+    v3 = iadd v1, v2
+    return v3
+}
+
+; check: v4 = ineg v0
+; check: return v4
+
+function %ineg_not_plus_one_reverse(i32) -> i32 {
+block0(v0: i32):
+    v1 = bnot v0
+    v2 = iconst.i32 1
+    v3 = iadd v2, v1
+    return v3
+}
+
+; check: v4 = ineg v0
+; check: return v4
+
+function %ineg_not_minus_neg_1(i32) -> i32 {
+block0(v0: i32):
+    v1 = bnot v0
+    v2 = iconst.i32 -1
+    v3 = isub v1, v2
+    return v3
+}
+
+; check: v4 = ineg v0
+; check: return v4
+
+function %ineg_not_sub_one(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i32 1
+    v2 = isub v0, v1
+    v3 = bnot v2
+    return v3
+}
+
+; check: v4 = ineg v0
+; check: return v4
+
+function %ineg_not_add_neg_one(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i32 -1
+    v2 = iadd v0, v1
+    v3 = bnot v2
+    return v3
+}
+
+; check: v4 = ineg v0
+; check: return v4
+
+function %ineg_not_add_neg_one_reverse(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i32 -1
+    v2 = iadd v1, v0
+    v3 = bnot v2
+    return v3
+}
+
+; check: v6 = ineg v0
+; check: return v6
+
+
+
 function %double_fneg(f32) -> f32 {
 block0(v1: f32):
     v2 = fneg v1
diff --git a/cranelift/filetests/filetests/egraph/bitops.clif b/cranelift/filetests/filetests/egraph/bitops.clif
index 88964da5a..9f02eed10 100644
--- a/cranelift/filetests/filetests/egraph/bitops.clif
+++ b/cranelift/filetests/filetests/egraph/bitops.clif
@@ -137,3 +137,44 @@ block0(v1: i64):
 
 ; check: v5 = bnot v1
 ; check: return v5
+
+function %bitops_bmask(i64) -> i64 {
+block0(v0: i64):
+    v1 = bnot v0
+    v2 = iconst.i64 1
+    v3 = iadd.i64 v1, v2
+    v4 = bor.i64 v0, v3
+    v5 = iconst.i64 63
+    v6 = ushr.i64 v4, v5
+    v7 = iconst.i64 1
+    v8 = isub.i64 v6, v7
+    v9 = bnot.i64 v8
+    return v9
+}
+
+; check: v14 = bmask.i64 v0
+; check: return v14
+
+function %bmask_sshr(i64) -> i64 {
+block0(v0: i64):
+    v1 = ineg v0
+    v2 = bor v0, v1
+    v3 = iconst.i64 63
+    v4 = sshr v2, v3
+    return v4
+}
+
+; check: v5 = bmask.i64 v0
+; check: return v5
+
+function %bmask_reverse_sshr(i64) -> i64 {
+block0(v0: i64):
+    v1 = ineg v0
+    v2 = bor v1, v0
+    v3 = iconst.i64 63
+    v4 = sshr v2, v3
+    return v4
+}
+
+; check: v5 = bmask.i64 v0
+; check: return v5
diff --git a/cranelift/filetests/filetests/egraph/shifts.clif b/cranelift/filetests/filetests/egraph/shifts.clif
index f03d2d41f..d9c9da277 100644
--- a/cranelift/filetests/filetests/egraph/shifts.clif
+++ b/cranelift/filetests/filetests/egraph/shifts.clif
@@ -204,3 +204,14 @@ block0(v0: i8):
     ; check: v5 = sextend.i64 v0
     ; check: return v5
 }
+
+
+function %ineg_ushr_to_sshr(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 63
+    v2 = ushr v0, v1
+    v3 = ineg v2
+    return v3
+    ; check: v4 = sshr v0, v1
+    ; check: return v4
+}
diff --git a/cranelift/filetests/filetests/isa/x64/simd-cmp-avx.clif b/cranelift/filetests/filetests/isa/x64/simd-cmp-avx.clif
index 9c69ac019..93d0cffe8 100644
--- a/cranelift/filetests/filetests/isa/x64/simd-cmp-avx.clif
+++ b/cranelift/filetests/filetests/isa/x64/simd-cmp-avx.clif
@@ -1,6 +1,6 @@
 test compile precise-output
 set enable_simd
-target x86_64 has_avx
+target x86_64 sse42 has_avx
 
 function %i8x16_eq(i8x16, i8x16) -> i8x16 {
 block0(v0: i8x16, v1: i8x16):
diff --git a/cranelift/filetests/filetests/runtests/bitops.clif b/cranelift/filetests/filetests/runtests/bitops.clif
index fe7615afb..3fd366aa5 100644
--- a/cranelift/filetests/filetests/runtests/bitops.clif
+++ b/cranelift/filetests/filetests/runtests/bitops.clif
@@ -1,4 +1,10 @@
 test run
+set opt_level=none
+target aarch64
+target s390x
+target riscv64
+target s390x has_mie2
+set opt_level=speed
 target aarch64
 target s390x
 target riscv64
@@ -55,3 +61,24 @@ block0(v0: i64, v1: i64, v2: i64):
 ; run: %bitselect_i64(0, 0, 0xFFFFFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF
 ; run: %bitselect_i64(0x5555555555555555, 0, 0xFFFFFFFFFFFFFFFF) == 0xAAAAAAAAAAAAAAAA
 ; run: %bitselect_i64(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0) == 0xFFFFFFFFFFFFFFFF
+
+
+;; We have a optimization rule in the midend that turns this into a bmask
+;; It's easier to have a runtest to ensure that it is correct than to inspect the output.
+function %bitops_bmask(i16) -> i16 {
+block0(v0: i16):
+    v1 = bnot v0
+    v2 = iconst.i16 1
+    v3 = iadd.i16 v1, v2
+    v4 = bor.i16 v0, v3
+    v5 = iconst.i16 15
+    v6 = ushr.i16 v4, v5
+    v7 = iconst.i16 1
+    v8 = isub.i16 v6, v7
+    v9 = bnot.i16 v8
+    return v9
+}
+; run: %bitops_bmask(0) == 0
+; run: %bitops_bmask(1) == -1
+; run: %bitops_bmask(0xFFFF) == -1
+; run: %bitops_bmask(0x8000) == -1
diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif b/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif
index ed074fe68..6d9cbc8e5 100644
--- a/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif
+++ b/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif
@@ -2,7 +2,8 @@ test interpret
 test run
 set enable_simd
 target x86_64
-target x86_64 has_avx
+target x86_64 sse42
+target x86_64 sse42 has_avx
 target aarch64
 target s390x
 
diff --git a/cranelift/filetests/src/test_wasm/env.rs b/cranelift/filetests/src/test_wasm/env.rs
index 8a0ea656b..23ca9bac8 100644
--- a/cranelift/filetests/src/test_wasm/env.rs
+++ b/cranelift/filetests/src/test_wasm/env.rs
@@ -604,10 +604,6 @@ impl<'a> FuncEnvironment for FuncEnv<'a> {
             .translate_atomic_notify(pos, index, heap, addr, count)
     }
 
-    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
-        self.inner.unsigned_add_overflow_condition()
-    }
-
     fn heaps(
         &self,
     ) -> &cranelift_codegen::entity::PrimaryMap<cranelift_wasm::Heap, cranelift_wasm::HeapData>
diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs
index 3bcead048..ac3953402 100644
--- a/crates/component-macro/tests/codegen.rs
+++ b/crates/component-macro/tests/codegen.rs
@@ -21,13 +21,6 @@ macro_rules! gentest {
                     duplicate_if_necessary: true,
                 });
             }
-            mod interfaces_only {
-                wasmtime::component::bindgen!({
-                    path: $path,
-                    world: $name,
-                    only_interfaces: true,
-                });
-            }
         }
         // ...
     };
diff --git a/crates/test-programs/wasi-http-tests/src/bin/outbound_request.rs b/crates/test-programs/wasi-http-tests/src/bin/outbound_request.rs
index fbb448dbb..384cf0177 100644
--- a/crates/test-programs/wasi-http-tests/src/bin/outbound_request.rs
+++ b/crates/test-programs/wasi-http-tests/src/bin/outbound_request.rs
@@ -101,8 +101,7 @@ fn request(
     })
 }
 
-fn main() -> Result<()> {       
-    let missing = "MISSING".to_string(); 
+fn main() -> Result<()> { 
     let r1 = request(
         types::MethodParam::Get,
         types::SchemeParam::Http,
@@ -115,7 +114,7 @@ fn main() -> Result<()> {
 
     println!("localhost:3000 /get: {r1:?}");
     assert_eq!(r1.status, 200);
-    let method = r1.header("x-wasmtime-test-method").unwrap_or(&missing);
+    let method = r1.header("x-wasmtime-test-method").unwrap();
     assert_eq!(method, "GET");
     assert_eq!(r1.body, b"");
 
@@ -131,7 +130,7 @@ fn main() -> Result<()> {
 
     println!("localhost:3000 /post: {r2:?}");
     assert_eq!(r2.status, 200);
-    let method = r2.header("x-wasmtime-test-method").unwrap_or(&missing);
+    let method = r2.header("x-wasmtime-test-method").unwrap();
     assert_eq!(method, "POST");
     assert_eq!(r2.body, b"{\"foo\": \"bar\"}");
 
@@ -147,7 +146,7 @@ fn main() -> Result<()> {
 
     println!("localhost:3000 /put: {r3:?}");
     assert_eq!(r3.status, 200);
-    let method = r3.header("x-wasmtime-test-method").unwrap_or(&missing);
+    let method = r3.header("x-wasmtime-test-method").unwrap();
     assert_eq!(method, "PUT");
     assert_eq!(r3.body, b"");
 
diff --git a/tests/all/component_model/bindgen/results.rs b/tests/all/component_model/bindgen/results.rs
index 19376a64a..a80341751 100644
--- a/tests/all/component_model/bindgen/results.rs
+++ b/tests/all/component_model/bindgen/results.rs
@@ -639,15 +639,10 @@ mod with_remapping {
 
     mod interfaces {
         wasmtime::component::bindgen!({
-            inline: "
-            default world result-playground {
-                import imports: interface {
-                    empty-error: func(a: float64) -> result<float64>
-                }
-
-                export empty-error: func(a: float64) -> result<float64>
+            interfaces: "
+            import imports: interface {
+                empty-error: func(a: float64) -> result<float64>
             }",
-            only_interfaces: true,
         });
     }