Repository: bytecodealliance/wasmtime
Pull request #6503 (2023-06-02 08:29:05)

Upgrade file per thread logger to 0.2.0
This should fix https://github.com/bytecodealliance/wasmtime/issues/6456. @rvolosatovs could you confirm this please?


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index b1b0abca1..bd5833de9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1303,9 +1303,9 @@ dependencies = [
 
 [[package]]
 name = "file-per-thread-logger"
-version = "0.1.6"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84f2e425d9790201ba4af4630191feac6dcc98765b118d4d18e91d23c2353866"
+checksum = "8a3cc21c33af89af0930c8cae4ade5e6fdc17b5d2c97b3d2e2edb67a1cf683f3"
 dependencies = [
  "env_logger 0.10.0",
  "log",
diff --git a/Cargo.toml b/Cargo.toml
index 0aacb7efa..75d415493 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -238,6 +238,7 @@ cfg-if = "1.0"
 tempfile = "3.1.0"
 filecheck = "0.5.0"
 libc = "0.2.60"
+file-per-thread-logger = "0.2.0"
 
 [features]
 default = [
diff --git a/cranelift/codegen/src/isa/riscv64/inst.isle b/cranelift/codegen/src/isa/riscv64/inst.isle
index 757ccef86..bddf9c65d 100644
--- a/cranelift/codegen/src/isa/riscv64/inst.isle
+++ b/cranelift/codegen/src/isa/riscv64/inst.isle
@@ -1501,6 +1501,10 @@
 
 
 
+;; Generate a mask for the bit-width of the given type
+(decl pure shift_mask (Type) u64)
+(rule (shift_mask ty) (u64_sub (ty_bits (lane_type ty)) 1))
+
 ;; for load immediate
 (decl imm (Type u64) Reg)
 (extern constructor imm imm)
@@ -1530,7 +1534,7 @@
 (decl imm12_const_add (i32 i32) Imm12)
 (extern constructor imm12_const_add imm12_const_add)
 
-(decl imm12_and (Imm12 i32) Imm12)
+(decl imm12_and (Imm12 u64) Imm12)
 (extern constructor imm12_and imm12_and)
 
 ;; Helper for get negative of Imm12
@@ -1548,6 +1552,9 @@
 (decl imm12_from_u64 (Imm12) u64)
 (extern extractor imm12_from_u64 imm12_from_u64)
 
+(decl pure partial u64_to_imm12 (u64) Imm12)
+(rule (u64_to_imm12 (imm12_from_u64 n)) n)
+
 
 ;; Imm5 Extractors
 
@@ -2144,83 +2151,6 @@
       (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 low high)
     )))
 
-
-(decl lower_i128_ishl (ValueRegs ValueRegs) ValueRegs)
-(rule
-  (lower_i128_ishl x y)
-  (let
-    ((tmp ValueRegs (gen_shamt $I128 (value_regs_get y 0)))
-      (shamt XReg (value_regs_get tmp 0))
-      (len_sub_shamt XReg (value_regs_get tmp 1))
-      ;;
-      (low XReg (rv_sll (value_regs_get x 0) shamt))
-      ;; high part.
-      (high_part1 XReg (rv_srl (value_regs_get x 0) len_sub_shamt))
-      (high_part2 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) high_part1))
-      ;;
-      (high_part3 XReg (rv_sll (value_regs_get x 1) shamt))
-      (high XReg (rv_or high_part2 high_part3 ))
-      ;;
-      (const64 XReg (load_u64_constant 64))
-      (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
-    (value_regs
-      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 (zero_reg) low)
-      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 low high))))
-
-(decl lower_i128_ushr (ValueRegs ValueRegs) ValueRegs)
-(rule
-  (lower_i128_ushr x y)
-  (let
-    ((tmp ValueRegs (gen_shamt $I128 (value_regs_get y 0)))
-      (shamt XReg (value_regs_get tmp 0))
-      (len_sub_shamt XReg (value_regs_get tmp 1))
-
-      ;; low part.
-      (low_part1 XReg (rv_sll (value_regs_get x 1) len_sub_shamt))
-      (low_part2 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) low_part1))
-      ;;
-      (low_part3 XReg (rv_srl (value_regs_get x 0) shamt))
-      (low XReg (rv_or low_part2 low_part3 ))
-      ;;
-      (const64 XReg (load_u64_constant 64))
-
-      ;;
-      (high XReg (rv_srl (value_regs_get x 1) shamt))
-      (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
-    (value_regs
-      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high low)
-      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 (zero_reg) high))))
-
-
-(decl lower_i128_sshr (ValueRegs ValueRegs) ValueRegs)
-(rule
-  (lower_i128_sshr x y)
-  (let
-    ((tmp ValueRegs (gen_shamt $I128 (value_regs_get y 0)))
-      (shamt XReg (value_regs_get tmp 0))
-      (len_sub_shamt XReg (value_regs_get tmp 1))
-
-      ;; low part.
-      (low_part1 XReg (rv_sll (value_regs_get x 1) len_sub_shamt))
-      (low_part2 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) low_part1))
-      ;;
-      (low_part3 XReg (rv_srl (value_regs_get x 0) shamt))
-      (low XReg (rv_or low_part2 low_part3 ))
-      ;;
-      (const64 XReg (load_u64_constant 64))
-      ;;
-      (high XReg (rv_sra (value_regs_get x 1) shamt))
-      ;;
-      (const_neg_1 XReg (load_imm12 -1))
-      ;;
-      (high_replacement XReg (gen_select_reg (IntCC.SignedLessThan) (value_regs_get x 1) (zero_reg) const_neg_1 (zero_reg)))
-      (const64 XReg (load_u64_constant 64))
-      (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
-    (value_regs
-      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high low)
-      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high_replacement high))))
-
-
 (decl gen_amode (Reg Offset32 Type) AMode)
 (extern constructor gen_amode gen_amode)
 
diff --git a/cranelift/codegen/src/isa/riscv64/lower.isle b/cranelift/codegen/src/isa/riscv64/lower.isle
index b02209b7a..22a04a131 100644
--- a/cranelift/codegen/src/isa/riscv64/lower.isle
+++ b/cranelift/codegen/src/isa/riscv64/lower.isle
@@ -515,87 +515,150 @@
   (lower_popcnt_i128 x))
 
 ;;;; Rules for `ishl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(rule 1 (lower (has_type $I8 (ishl x y)))
-  (rv_sllw x (rv_andi (value_regs_get y 0) (imm12_const 7))))
 
-(rule 2 (lower (has_type $I8 (ishl x (imm12_from_value y))))
-  (rv_slliw x (imm12_and y 7)))
-
-(rule 1 (lower (has_type $I16 (ishl x y)))
-  (rv_sllw x (rv_andi (value_regs_get y 0) (imm12_const 15))))
-
-(rule 2 (lower (has_type $I16 (ishl x (imm12_from_value y))))
-  (rv_slliw x (imm12_and y 15)))
+;; 8/16 bit types need a mask on the shift amount
+(rule 0 (lower (has_type (ty_int (ty_8_or_16 ty)) (ishl x y)))
+  (if-let mask (u64_to_imm12 (shift_mask ty)))
+  (rv_sllw x (rv_andi (value_regs_get y 0) mask)))
 
+;; Using the 32bit version of `sll` automatically masks the shift amount.
 (rule 1 (lower (has_type $I32 (ishl x y)))
   (rv_sllw x (value_regs_get y 0)))
-(rule 2 (lower (has_type $I32 (ishl x (imm12_from_value y))))
-  (rv_slliw x y))
 
-(rule 2 (lower (has_type $I64 (ishl x (imm12_from_value y))))
-  (rv_slli x y))
+;; Similarly, the 64bit version does the right thing.
 (rule 1 (lower (has_type $I64 (ishl x y)))
   (rv_sll x (value_regs_get y 0)))
 
+;; If the shift amount is known. We can mask it and encode it in the instruction.
+(rule 2 (lower (has_type (int_fits_in_32 ty) (ishl x (maybe_uextend (imm12_from_value y)))))
+  (rv_slliw x (imm12_and y (shift_mask ty))))
+
+;; We technically don't need to mask the shift amount here. The instruction
+;; does the right thing. But it's neater when pretty printing it.
+(rule 3 (lower (has_type ty @ $I64 (ishl x (maybe_uextend (imm12_from_value y)))))
+  (rv_slli x (imm12_and y (shift_mask ty))))
+
 ;; With `Zba` we have a shift that zero extends the LHS argument.
-(rule 3 (lower (has_type $I64 (ishl (uextend x @ (value_type $I32)) (maybe_uextend (imm12_from_value y)))))
+(rule 4 (lower (has_type $I64 (ishl (uextend x @ (value_type $I32)) (maybe_uextend (imm12_from_value y)))))
   (if-let $true (has_zba))
   (rv_slliuw x y))
 
 ;; I128 cases
-(rule 0 (lower (has_type $I128 (ishl x y)))
-  (lower_i128_ishl x y))
-
-;;;; Rules for `ushr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(rule 1 (lower (has_type $I8 (ushr x y)))
-  (rv_srlw (zext x $I8 $I64) (rv_andi (value_regs_get y 0) (imm12_const 7))))
+(rule 4 (lower (has_type $I128 (ishl x y)))
+  (let ((tmp ValueRegs (gen_shamt $I128 (value_regs_get y 0)))
+        (shamt XReg (value_regs_get tmp 0))
+        (len_sub_shamt XReg (value_regs_get tmp 1))
+        ;;
+        (low XReg (rv_sll (value_regs_get x 0) shamt))
+        ;; high part.
+        (high_part1 XReg (rv_srl (value_regs_get x 0) len_sub_shamt))
+        (high_part2 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) high_part1))
+        ;;
+        (high_part3 XReg (rv_sll (value_regs_get x 1) shamt))
+        (high XReg (rv_or high_part2 high_part3))
+        ;;
+        (const64 XReg (load_u64_constant 64))
+        (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
+    (value_regs
+      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 (zero_reg) low)
+      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 low high))))
 
-(rule 2 (lower (has_type $I8 (ushr x (imm12_from_value y))))
-  (rv_srliw (zext x $I8 $I64) (imm12_and y 7)))
 
-(rule 1 (lower (has_type $I16 (ushr x y)))
-  (rv_srlw (zext x $I16 $I64) (rv_andi (value_regs_get y 0) (imm12_const 15))))
+;;;; Rules for `ushr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(rule 2 (lower (has_type $I16 (ushr x (imm12_from_value y))))
-  (rv_srliw (zext x $I16 $I64) (imm12_and y 15)))
+;; 8/16 bit types need a mask on the shift amount, and the LHS needs to be
+;; zero extended.
+(rule 0 (lower (has_type (ty_int (fits_in_16 ty)) (ushr x y)))
+  (if-let mask (u64_to_imm12 (shift_mask ty)))
+  (rv_srlw (zext x ty $I64) (rv_andi (value_regs_get y 0) mask)))
 
+;; Using the 32bit version of `srl` automatically masks the shift amount.
 (rule 1 (lower (has_type $I32 (ushr x y)))
   (rv_srlw x (value_regs_get y 0)))
-(rule 2 (lower (has_type $I32 (ushr x (imm12_from_value y))))
-  (rv_srliw x y))
 
-(rule 2 (lower (has_type $I64 (ushr x (imm12_from_value y))))
-  (rv_srli x y))
+;; Similarly, the 64bit version does the right thing.
 (rule 1 (lower (has_type $I64 (ushr x y)))
   (rv_srl x (value_regs_get y 0)))
 
-(rule 0 (lower (has_type $I128 (ushr x y)))
-  (lower_i128_ushr x y))
+;; When the RHS is known we can just encode it in the instruction.
+(rule 2 (lower (has_type (ty_int (fits_in_16 ty)) (ushr x (maybe_uextend (imm12_from_value y)))))
+  (rv_srliw (zext x ty $I64) (imm12_and y (shift_mask ty))))
 
+(rule 3 (lower (has_type $I32 (ushr x (maybe_uextend (imm12_from_value y)))))
+  (rv_srliw x y))
 
-;;;; Rules for `sshr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(rule 1 (lower (has_type $I8 (sshr x y)))
-  (rv_sra (sext x $I8 $I64) (rv_andi (value_regs_get y 0) (imm12_const 7))))
+(rule 3 (lower (has_type $I64 (ushr x (maybe_uextend (imm12_from_value y)))))
+  (rv_srli x y))
 
-(rule 2 (lower (has_type $I8 (sshr x (imm12_from_value y))))
-  (rv_srai (sext x $I8 $I64) (imm12_and y 7)))
+(rule 3 (lower (has_type $I128 (ushr x y)))
+  (let ((tmp ValueRegs (gen_shamt $I128 (value_regs_get y 0)))
+        (shamt XReg (value_regs_get tmp 0))
+        (len_sub_shamt XReg (value_regs_get tmp 1))
+        ;; low part.
+        (low_part1 XReg (rv_sll (value_regs_get x 1) len_sub_shamt))
+        (low_part2 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) low_part1))
+        ;;
+        (low_part3 XReg (rv_srl (value_regs_get x 0) shamt))
+        (low XReg (rv_or low_part2 low_part3))
+        ;;
+        (const64 XReg (load_u64_constant 64))
+        ;;
+        (high XReg (rv_srl (value_regs_get x 1) shamt))
+        (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
+    (value_regs
+      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high low)
+      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 (zero_reg) high))))
 
-(rule 1 (lower (has_type $I16 (sshr x y)))
-  (rv_sra (sext x $I16 $I64) (rv_andi (value_regs_get y 0) (imm12_const 15))))
 
-(rule 2 (lower (has_type $I16 (sshr x (imm12_from_value y))))
-  (rv_srai (sext x $I16 $I64) (imm12_and y 15)))
+;;;; Rules for `sshr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 8/16 bit types need a mask on the shift amount, and the LHS needs to be
+;; zero extended.
+(rule 0 (lower (has_type (ty_int (fits_in_16 ty)) (sshr x y)))
+  (if-let mask (u64_to_imm12 (shift_mask ty)))
+  (rv_sraw (sext x ty $I64) (rv_andi (value_regs_get y 0) mask)))
 
+;; Using the 32bit version of `sra` automatically masks the shift amount.
 (rule 1 (lower (has_type $I32 (sshr x y)))
   (rv_sraw x (value_regs_get y 0)))
-(rule 2 (lower (has_type $I32 (sshr x (imm12_from_value y))))
-  (rv_sraiw x y))
+
+;; Similarly, the 64bit version does the right thing.
 (rule 1 (lower (has_type $I64 (sshr x y)))
   (rv_sra x (value_regs_get y 0)))
-(rule 2 (lower (has_type $I64 (sshr x (imm12_from_value y))))
+
+;; When the RHS is known we can just encode it in the instruction.
+(rule 2 (lower (has_type (ty_int (fits_in_16 ty)) (sshr x (maybe_uextend (imm12_from_value y)))))
+  (rv_sraiw (sext x ty $I64) (imm12_and y (shift_mask ty))))
+
+(rule 3 (lower (has_type $I32 (sshr x (maybe_uextend (imm12_from_value y)))))
+  (rv_sraiw x y))
+
+(rule 3 (lower (has_type $I64 (sshr x (maybe_uextend (imm12_from_value y)))))
   (rv_srai x y))
-(rule 0 (lower (has_type $I128 (sshr x y)))
-  (lower_i128_sshr x (value_regs_get y 0)))
+
+(rule 3 (lower (has_type $I128 (sshr x y)))
+  (let ((tmp ValueRegs (gen_shamt $I128 (value_regs_get y 0)))
+        (shamt XReg (value_regs_get tmp 0))
+        (len_sub_shamt XReg (value_regs_get tmp 1))
+        ;; low part.
+        (low_part1 XReg (rv_sll (value_regs_get x 1) len_sub_shamt))
+        (low_part2 XReg (gen_select_reg (IntCC.Equal) shamt (zero_reg) (zero_reg) low_part1))
+        ;;
+        (low_part3 XReg (rv_srl (value_regs_get x 0) shamt))
+        (low XReg (rv_or low_part2 low_part3))
+        ;;
+        (const64 XReg (load_u64_constant 64))
+        ;;
+        (high XReg (rv_sra (value_regs_get x 1) shamt))
+        ;;
+        (const_neg_1 XReg (load_imm12 -1))
+        ;;
+        (high_replacement XReg (gen_select_reg (IntCC.SignedLessThan) (value_regs_get x 1) (zero_reg) const_neg_1 (zero_reg)))
+        (const64 XReg (load_u64_constant 64))
+        (shamt_128 XReg (rv_andi (value_regs_get y 0) (imm12_const 127))))
+    (value_regs
+      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high low)
+      (gen_select_reg (IntCC.UnsignedGreaterThanOrEqual) shamt_128 const64 high_replacement high))))
 
 
 ;;;; Rules for `rotl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/cranelift/codegen/src/isa/riscv64/lower/isle.rs b/cranelift/codegen/src/isa/riscv64/lower/isle.rs
index 9eccd0e21..11626af92 100644
--- a/cranelift/codegen/src/isa/riscv64/lower/isle.rs
+++ b/cranelift/codegen/src/isa/riscv64/lower/isle.rs
@@ -213,7 +213,7 @@ impl generated_code::Context for RV64IsleContext<'_, '_, MInst, Riscv64Backend>
         v.clone()
     }
 
-    fn imm12_and(&mut self, imm: Imm12, x: i32) -> Imm12 {
+    fn imm12_and(&mut self, imm: Imm12, x: u64) -> Imm12 {
         Imm12::from_bits(imm.as_i16() & (x as i16))
     }
 
diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs
index 1022ae175..d642219d2 100644
--- a/cranelift/interpreter/src/step.rs
+++ b/cranelift/interpreter/src/step.rs
@@ -7,7 +7,7 @@ use crate::value::{DataValueExt, ValueConversionKind, ValueError, ValueResult};
 use cranelift_codegen::data_value::DataValue;
 use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
 use cranelift_codegen::ir::{
-    types, AbiParam, AtomicRmwOp, Block, BlockCall, ExternalName, FuncRef, Function,
+    types, AbiParam, AtomicRmwOp, Block, BlockCall, Endianness, ExternalName, FuncRef, Function,
     InstructionData, MemFlags, Opcode, TrapCode, Type, Value as ValueRef,
 };
 use log::trace;
@@ -904,11 +904,21 @@ where
         Opcode::IsInvalid => unimplemented!("IsInvalid"),
         Opcode::Bitcast | Opcode::ScalarToVector => {
             let input_ty = inst_context.type_of(inst_context.args()[0]).unwrap();
-            let arg0 = extractlanes(&arg(0), input_ty)?;
-            let lanes = &arg0
-                .into_iter()
-                .map(|x| DataValue::convert(x, ValueConversionKind::Exact(ctrl_ty.lane_type())))
-                .collect::<ValueResult<SimdVec<DataValue>>>()?;
+            let lanes = &if input_ty.is_vector() {
+                assert_eq!(
+                    inst.memflags()
+                        .expect("byte order flag to be set")
+                        .endianness(Endianness::Little),
+                    Endianness::Little,
+                    "Only little endian bitcasts on vectors are supported"
+                );
+                extractlanes(&arg(0), ctrl_ty)?
+            } else {
+                extractlanes(&arg(0), input_ty)?
+                    .into_iter()
+                    .map(|x| DataValue::convert(x, ValueConversionKind::Exact(ctrl_ty.lane_type())))
+                    .collect::<ValueResult<SimdVec<DataValue>>>()?
+            };
             assign(match inst.opcode() {
                 Opcode::Bitcast => vectorizelanes(lanes, ctrl_ty)?,
                 Opcode::ScalarToVector => vectorizelanes_all(lanes, ctrl_ty)?,
diff --git a/crates/cache/Cargo.toml b/crates/cache/Cargo.toml
index b7fb05988..6ff7e9884 100644
--- a/crates/cache/Cargo.toml
+++ b/crates/cache/Cargo.toml
@@ -13,7 +13,7 @@ anyhow = { workspace = true }
 base64 = "0.21.0"
 bincode = "1.1.4"
 directories-next = "2.0"
-file-per-thread-logger = "0.1.1"
+file-per-thread-logger = { workspace = true }
 log = { workspace = true }
 serde = { version = "1.0.94", features = ["derive"] }
 sha2 = "0.10.2"
diff --git a/crates/cli-flags/Cargo.toml b/crates/cli-flags/Cargo.toml
index 45bf2b748..38a08f02b 100644
--- a/crates/cli-flags/Cargo.toml
+++ b/crates/cli-flags/Cargo.toml
@@ -11,7 +11,7 @@ edition.workspace = true
 [dependencies]
 anyhow = { workspace = true }
 clap = { workspace = true }
-file-per-thread-logger = "0.1.1"
+file-per-thread-logger = { workspace = true }
 pretty_env_logger = "0.4.0"
 rayon = "1.5.0"
 wasmtime = { workspace = true }
diff --git a/fuzz/fuzz_targets/differential.rs b/fuzz/fuzz_targets/differential.rs
index 5c6a35a20..da17604f1 100644
--- a/fuzz/fuzz_targets/differential.rs
+++ b/fuzz/fuzz_targets/differential.rs
@@ -326,6 +326,8 @@ fn winch_supports_module(module: &[u8]) -> bool {
                         | I64GeS { .. }
                         | I32GeU { .. }
                         | I64GeU { .. }
+                        | I32Eqz { .. }
+                        | I64Eqz { .. }
                         | LocalGet { .. }
                         | LocalSet { .. }
                         | Call { .. }
diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml
index e34328225..75562d49a 100644
--- a/supply-chain/audits.toml
+++ b/supply-chain/audits.toml
@@ -721,6 +721,12 @@ are only created when requested by the application, however, and otherwise
 only does its stated purpose.
 """
 
+[[audits.file-per-thread-logger]]
+who = "Benjamin Bouvier <public@benj.me>"
+criteria = "safe-to-deploy"
+version = "0.2.0"
+notes = "Simple version bump."
+
 [[audits.file-per-thread-logger]]
 who = "Dan Gohman <dev@sunfishcode.online>"
 criteria = "safe-to-deploy"
diff --git a/winch/codegen/src/codegen/context.rs b/winch/codegen/src/codegen/context.rs
index 12d3f8de4..ff667537e 100644
--- a/winch/codegen/src/codegen/context.rs
+++ b/winch/codegen/src/codegen/context.rs
@@ -124,6 +124,17 @@ impl<'a> CodeGenContext<'a> {
         };
     }
 
+    /// Prepares arguments for emitting a unary operation.
+    pub fn unop<F, M>(&mut self, masm: &mut M, size: OperandSize, emit: &mut F)
+    where
+        F: FnMut(&mut M, RegImm, OperandSize),
+        M: MacroAssembler,
+    {
+        let reg = self.pop_to_reg(masm, None, size);
+        emit(masm, reg.into(), size);
+        self.stack.push(Val::reg(reg));
+    }
+
     /// Prepares arguments for emitting an i32 binary operation.
     pub fn i32_binop<F, M>(&mut self, masm: &mut M, emit: &mut F)
     where
diff --git a/winch/codegen/src/isa/x64/asm.rs b/winch/codegen/src/isa/x64/asm.rs
index a0b21d862..ee442ffba 100644
--- a/winch/codegen/src/isa/x64/asm.rs
+++ b/winch/codegen/src/isa/x64/asm.rs
@@ -166,10 +166,7 @@ impl Assembler {
                 Address::Offset { base, offset: imm } => self.mov_mr(*base, *imm, *reg, size),
             },
 
-            _ => panic!(
-                "Invalid operand combination for mov; src={:?}, dst={:?}",
-                src, dst
-            ),
+            _ => Self::handle_invalid_operand_combination(src, dst),
         }
     }
 
@@ -245,15 +242,12 @@ impl Assembler {
                     self.sub_ir(val, *dst, size)
                 } else {
                     let scratch = regs::scratch();
-                    self.mov_ir(*imm as u64, scratch, size);
+                    self.load_constant(imm, scratch, size);
                     self.sub_rr(scratch, *dst, size);
                 }
             }
             (Operand::Reg(src), Operand::Reg(dst)) => self.sub_rr(*src, *dst, size),
-            _ => panic!(
-                "Invalid operand combination for sub; src = {:?} dst = {:?}",
-                src, dst
-            ),
+            _ => Self::handle_invalid_operand_combination(src, dst),
         }
     }
 
@@ -289,15 +283,12 @@ impl Assembler {
                     self.mul_ir(val, *dst, size);
                 } else {
                     let scratch = regs::scratch();
-                    self.mov_ir(*imm as u64, scratch, size);
+                    self.load_constant(imm, scratch, size);
                     self.mul_rr(scratch, *dst, size);
                 }
             }
             (Operand::Reg(src), Operand::Reg(dst)) => self.mul_rr(*src, *dst, size),
-            _ => panic!(
-                "Invalid operand combination for mul; src = {:?} dst = {:?}",
-                src, dst
-            ),
+            _ => Self::handle_invalid_operand_combination(src, dst),
         }
     }
 
@@ -445,15 +436,12 @@ impl Assembler {
                     self.add_ir(val, *dst, size)
                 } else {
                     let scratch = regs::scratch();
-                    self.mov_ir(*imm as u64, scratch, size);
+                    self.load_constant(imm, scratch, size);
                     self.add_rr(scratch, *dst, size);
                 }
             }
             (Operand::Reg(src), Operand::Reg(dst)) => self.add_rr(*src, *dst, size),
-            _ => panic!(
-                "Invalid operand combination for add; src = {:?} dst = {:?}",
-                src, dst
-            ),
+            _ => Self::handle_invalid_operand_combination(src, dst),
         }
     }
 
@@ -500,15 +488,12 @@ impl Assembler {
                     self.cmp_ir(val, *dst, size)
                 } else {
                     let scratch = regs::scratch();
-                    self.mov_ir(*imm as u64, scratch, size);
+                    self.load_constant(imm, scratch, size);
                     self.cmp_rr(scratch, *dst, size);
                 }
             }
             (Operand::Reg(src), Operand::Reg(dst)) => self.cmp_rr(*src, *dst, size),
-            _ => panic!(
-                "Invalid operand combination for cmp; src = {:?} dst = {:?}",
-                src, dst
-            ),
+            _ => Self::handle_invalid_operand_combination(src, dst),
         }
     }
 
@@ -580,4 +565,12 @@ impl Assembler {
             }
         }
     }
+
+    fn load_constant(&mut self, imm: &i64, dst: Reg, size: OperandSize) {
+        self.mov_ir(*imm as u64, dst, size);
+    }
+
+    fn handle_invalid_operand_combination(src: Operand, dst: Operand) {
+        panic!("Invalid operand combination; src={:?}, dst={:?}", src, dst);
+    }
 }
diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs
index 2dcf56201..eaa1a7ec1 100644
--- a/winch/codegen/src/visitor.rs
+++ b/winch/codegen/src/visitor.rs
@@ -67,6 +67,8 @@ macro_rules! def_unsupported {
     (emit I64GeS $($rest:tt)*) => {};
     (emit I32GeU $($rest:tt)*) => {};
     (emit I64GeU $($rest:tt)*) => {};
+    (emit I32Eqz $($rest:tt)*) => {};
+    (emit I64Eqz $($rest:tt)*) => {};
     (emit LocalGet $($rest:tt)*) => {};
     (emit LocalSet $($rest:tt)*) => {};
     (emit Call $($rest:tt)*) => {};
@@ -268,6 +270,22 @@ where
         self.cmp_i64s(CmpKind::GeU);
     }
 
+    fn visit_i32_eqz(&mut self) {
+        use OperandSize::*;
+
+        self.context.unop(self.masm, S32, &mut |masm, reg, size| {
+            masm.cmp_with_set(reg, reg, RegImm::imm(0), CmpKind::Eq, size);
+        });
+    }
+
+    fn visit_i64_eqz(&mut self) {
+        use OperandSize::*;
+
+        self.context.unop(self.masm, S64, &mut |masm, reg, size| {
+            masm.cmp_with_set(reg, reg, RegImm::imm(0), CmpKind::Eq, size);
+        });
+    }
+
     fn visit_end(&mut self) {}
 
     fn visit_local_get(&mut self, index: u32) {


Test patch:
diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml
index 4ff5037bd..04b4a57ed 100644
--- a/cranelift/filetests/Cargo.toml
+++ b/cranelift/filetests/Cargo.toml
@@ -18,7 +18,7 @@ cranelift-reader = { workspace = true }
 cranelift-jit = { workspace = true, features = ["selinux-fix"] }
 cranelift-module = { workspace = true }
 cranelift-control = { workspace = true }
-file-per-thread-logger = "0.1.2"
+file-per-thread-logger = { workspace = true }
 filecheck = { workspace = true }
 gimli = { workspace = true }
 log = { workspace = true }
diff --git a/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif b/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif
index 2d621572d..60aa88785 100644
--- a/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif
+++ b/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif
@@ -568,7 +568,7 @@ block0(v0: i32, v1: i32):
 
 ; VCode:
 ; block0:
-;   slliw a2,a0,53
+;   slliw a2,a0,21
 ;   subw a0,a1,a2
 ;   ret
 ;
diff --git a/cranelift/filetests/filetests/isa/riscv64/ishl-const.clif b/cranelift/filetests/filetests/isa/riscv64/ishl-const.clif
new file mode 100644
index 000000000..18abb7683
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/ishl-const.clif
@@ -0,0 +1,602 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+
+function %ishl_i8_const_i8(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i8_const_i16(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i16 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i8_const_i32(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i32 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i8_const_i64(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i64 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i8_const_i128(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ishl v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i16_const_i8(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i8 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i16_const_i16(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i16 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i16_const_i32(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i32 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i16_const_i64(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i64 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i16_const_i128(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ishl v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i32_const_i8(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i8 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i32_const_i16(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i16 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i32_const_i32(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i32 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i32_const_i64(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i64 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i32_const_i128(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ishl v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slliw a0, a0, 5
+;   ret
+
+function %ishl_i64_const_i8(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i8 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 5
+;   ret
+
+function %ishl_i64_const_i16(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i16 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 5
+;   ret
+
+function %ishl_i64_const_i32(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i32 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 5
+;   ret
+
+function %ishl_i64_const_i64(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 5
+;   ret
+
+function %ishl_i64_const_i128(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ishl v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 5
+;   ret
+
+function %ishl_i128_const_i8(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i8 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a0,a2
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a2 eq zero)
+;   sll a0,a1,a2
+;   or a2,t1,a0
+;   li a4,64
+;   andi a6,t2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a2##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a0, a2
+;   srl t4, a0, a5
+;   beqz a2, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a2
+;   or a2, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, t2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a2, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_const_i16(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i16 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a0,a2
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a2 eq zero)
+;   sll a0,a1,a2
+;   or a2,t1,a0
+;   li a4,64
+;   andi a6,t2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a2##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a0, a2
+;   srl t4, a0, a5
+;   beqz a2, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a2
+;   or a2, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, t2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a2, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_const_i32(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i32 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a0,a2
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a2 eq zero)
+;   sll a0,a1,a2
+;   or a2,t1,a0
+;   li a4,64
+;   andi a6,t2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a2##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a0, a2
+;   srl t4, a0, a5
+;   beqz a2, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a2
+;   or a2, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, t2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a2, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_const_i64(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i64 5
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a0,a2
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a2 eq zero)
+;   sll a0,a1,a2
+;   or a2,t1,a0
+;   li a4,64
+;   andi a6,t2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a2##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a0, a2
+;   srl t4, a0, a5
+;   beqz a2, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a2
+;   or a2, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, t2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a2, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_const_i128(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ishl v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   li a2,5
+;   li a3,0
+;   andi a3,a2,63
+;   li a4,64
+;   sub a6,a4,a3
+;   sll t3,a0,a3
+;   srl t0,a0,a6
+;   select_reg t2,zero,t0##condition=(a3 eq zero)
+;   sll a1,a1,a3
+;   or a3,t2,a1
+;   li a5,64
+;   andi a7,a2,127
+;   select_reg a0,zero,t3##condition=(a7 uge a5)
+;   select_reg a1,t3,a3##condition=(a7 uge a5)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a2, zero, 5
+;   mv a3, zero
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a3
+;   sll t3, a0, a3
+;   srl t0, a0, a6
+;   beqz a3, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   sll a1, a1, a3
+;   or a3, t2, a1
+;   addi a5, zero, 0x40
+;   andi a7, a2, 0x7f
+;   bgeu a7, a5, 0xc
+;   ori a0, t3, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a7, a5, 0xc
+;   ori a1, a3, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/ishl.clif b/cranelift/filetests/filetests/isa/riscv64/ishl.clif
new file mode 100644
index 000000000..76d257e56
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/ishl.clif
@@ -0,0 +1,580 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+
+function %ishl_i8_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,7
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 7
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i8_i16(i8, i16) -> i8 {
+block0(v0: i8, v1: i16):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,7
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 7
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i8_i32(i8, i32) -> i8 {
+block0(v0: i8, v1: i32):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,7
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 7
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i8_i64(i8, i64) -> i8 {
+block0(v0: i8, v1: i64):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,7
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 7
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i8_i128(i8, i128) -> i8 {
+block0(v0: i8, v1: i128):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,7
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 7
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i16_i8(i16, i8) -> i16 {
+block0(v0: i16, v1: i8):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,15
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 0xf
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i16_i16(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,15
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 0xf
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i16_i32(i16, i32) -> i16 {
+block0(v0: i16, v1: i32):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,15
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 0xf
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i16_i64(i16, i64) -> i16 {
+block0(v0: i16, v1: i64):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,15
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 0xf
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i16_i128(i16, i128) -> i16 {
+block0(v0: i16, v1: i128):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a1,a1,15
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a1, a1, 0xf
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i32_i8(i32, i8) -> i32 {
+block0(v0: i32, v1: i8):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i32_i16(i32, i16) -> i32 {
+block0(v0: i32, v1: i16):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i32_i32(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i32_i64(i32, i64) -> i32 {
+block0(v0: i32, v1: i64):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i32_i128(i32, i128) -> i32 {
+block0(v0: i32, v1: i128):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sllw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sllw a0, a0, a1
+;   ret
+
+function %ishl_i64_i8(i64, i8) -> i64 {
+block0(v0: i64, v1: i8):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sll a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sll a0, a0, a1
+;   ret
+
+function %ishl_i64_i16(i64, i16) -> i64 {
+block0(v0: i64, v1: i16):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sll a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sll a0, a0, a1
+;   ret
+
+function %ishl_i64_i32(i64, i32) -> i64 {
+block0(v0: i64, v1: i32):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sll a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sll a0, a0, a1
+;   ret
+
+function %ishl_i64_i64(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sll a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sll a0, a0, a1
+;   ret
+
+function %ishl_i64_i128(i64, i128) -> i64 {
+block0(v0: i64, v1: i128):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sll a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sll a0, a0, a1
+;   ret
+
+function %ishl_i128_i8(i128, i8) -> i128 {
+block0(v0: i128, v1: i8):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a0,a3
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a3 eq zero)
+;   sll a0,a1,a3
+;   or a3,t1,a0
+;   li a4,64
+;   andi a6,a2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a3##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a0, a3
+;   srl t4, a0, a5
+;   beqz a3, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a3
+;   or a3, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a3, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_i16(i128, i16) -> i128 {
+block0(v0: i128, v1: i16):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a0,a3
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a3 eq zero)
+;   sll a0,a1,a3
+;   or a3,t1,a0
+;   li a4,64
+;   andi a6,a2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a3##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a0, a3
+;   srl t4, a0, a5
+;   beqz a3, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a3
+;   or a3, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a3, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_i32(i128, i32) -> i128 {
+block0(v0: i128, v1: i32):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a0,a3
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a3 eq zero)
+;   sll a0,a1,a3
+;   or a3,t1,a0
+;   li a4,64
+;   andi a6,a2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a3##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a0, a3
+;   srl t4, a0, a5
+;   beqz a3, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a3
+;   or a3, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a3, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_i64(i128, i64) -> i128 {
+block0(v0: i128, v1: i64):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a0,a3
+;   srl t4,a0,a5
+;   select_reg t1,zero,t4##condition=(a3 eq zero)
+;   sll a0,a1,a3
+;   or a3,t1,a0
+;   li a4,64
+;   andi a6,a2,127
+;   select_reg a0,zero,a7##condition=(a6 uge a4)
+;   select_reg a1,a7,a3##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a0, a3
+;   srl t4, a0, a5
+;   beqz a3, 0xc
+;   ori t1, t4, 0
+;   j 8
+;   ori t1, zero, 0
+;   sll a0, a1, a3
+;   or a3, t1, a0
+;   addi a4, zero, 0x40
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 0xc
+;   ori a0, a7, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a3, 0
+;   j 8
+;   ori a1, a7, 0
+;   ret
+
+function %ishl_i128_i128(i128, i128) -> i128 {
+block0(v0: i128, v1: i128):
+    v2 = ishl v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a6,a4,a3
+;   sll t3,a0,a3
+;   srl t0,a0,a6
+;   select_reg t2,zero,t0##condition=(a3 eq zero)
+;   sll a1,a1,a3
+;   or a3,t2,a1
+;   li a5,64
+;   andi a7,a2,127
+;   select_reg a0,zero,t3##condition=(a7 uge a5)
+;   select_reg a1,t3,a3##condition=(a7 uge a5)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a3
+;   sll t3, a0, a3
+;   srl t0, a0, a6
+;   beqz a3, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   sll a1, a1, a3
+;   or a3, t2, a1
+;   addi a5, zero, 0x40
+;   andi a7, a2, 0x7f
+;   bgeu a7, a5, 0xc
+;   ori a0, t3, 0
+;   j 8
+;   ori a0, zero, 0
+;   bgeu a7, a5, 0xc
+;   ori a1, a3, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/rotl.clif b/cranelift/filetests/filetests/isa/riscv64/rotl.clif
new file mode 100644
index 000000000..24fa616a4
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/rotl.clif
@@ -0,0 +1,344 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+function %i128_rotl(i128, i128) -> i128 {
+block0(v0: i128, v1: i128):
+  v2 = rotl.i128 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a6,a4,a3
+;   sll t3,a0,a3
+;   srl t0,a1,a6
+;   mv t1,a1
+;   select_reg t2,zero,t0##condition=(a3 eq zero)
+;   or a1,t3,t2
+;   sll a4,t1,a3
+;   srl a5,a0,a6
+;   select_reg a7,zero,a5##condition=(a3 eq zero)
+;   or t4,a4,a7
+;   li t1,64
+;   andi a2,a2,127
+;   select_reg a0,t4,a1##condition=(a2 uge t1)
+;   select_reg a1,a1,t4##condition=(a2 uge t1)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a3
+;   sll t3, a0, a3
+;   srl t0, a1, a6
+;   ori t1, a1, 0
+;   beqz a3, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   or a1, t3, t2
+;   sll a4, t1, a3
+;   srl a5, a0, a6
+;   beqz a3, 0xc
+;   ori a7, a5, 0
+;   j 8
+;   ori a7, zero, 0
+;   or t4, a4, a7
+;   addi t1, zero, 0x40
+;   andi a2, a2, 0x7f
+;   bgeu a2, t1, 0xc
+;   ori a0, a1, 0
+;   j 8
+;   ori a0, t4, 0
+;   bgeu a2, t1, 8
+;   ori a1, t4, 0
+;   ret
+
+function %f4(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+  v2 = rotl.i64 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   mv a7,a0
+;   andi a0,a1,63
+;   li a2,64
+;   sub a4,a2,a0
+;   mv t0,a7
+;   sll a6,t0,a0
+;   srl t3,t0,a4
+;   select_reg t0,zero,t3##condition=(a0 eq zero)
+;   or a0,a6,t0
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   ori a7, a0, 0
+;   andi a0, a1, 0x3f
+;   addi a2, zero, 0x40
+;   sub a4, a2, a0
+;   ori t0, a7, 0
+;   sll a6, t0, a0
+;   srl t3, t0, a4
+;   beqz a0, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   or a0, a6, t0
+;   ret
+
+function %f5(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+  v2 = rotl.i32 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,32
+;   srli a2,a0,32
+;   andi a4,a1,31
+;   li a6,32
+;   sub t3,a6,a4
+;   sll t0,a2,a4
+;   srl t2,a2,t3
+;   select_reg a1,zero,t2##condition=(a4 eq zero)
+;   or a0,t0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x20
+;   srli a2, a0, 0x20
+;   andi a4, a1, 0x1f
+;   addi a6, zero, 0x20
+;   sub t3, a6, a4
+;   sll t0, a2, a4
+;   srl t2, a2, t3
+;   beqz a4, 0xc
+;   ori a1, t2, 0
+;   j 8
+;   ori a1, zero, 0
+;   or a0, t0, a1
+;   ret
+
+function %f6(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+  v2 = rotl.i16 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,a1,15
+;   li a6,16
+;   sub t3,a6,a4
+;   sll t0,a2,a4
+;   srl t2,a2,t3
+;   select_reg a1,zero,t2##condition=(a4 eq zero)
+;   or a0,t0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   addi a6, zero, 0x10
+;   sub t3, a6, a4
+;   sll t0, a2, a4
+;   srl t2, a2, t3
+;   beqz a4, 0xc
+;   ori a1, t2, 0
+;   j 8
+;   ori a1, zero, 0
+;   or a0, t0, a1
+;   ret
+
+function %f7(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+  v2 = rotl.i8 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   andi a0,a0,255
+;   andi a2,a1,7
+;   li a4,8
+;   sub a6,a4,a2
+;   sll t3,a0,a2
+;   srl t0,a0,a6
+;   select_reg t2,zero,t0##condition=(a2 eq zero)
+;   or a0,t3,t2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a0, a0, 0xff
+;   andi a2, a1, 7
+;   addi a4, zero, 8
+;   sub a6, a4, a2
+;   sll t3, a0, a2
+;   srl t0, a0, a6
+;   beqz a2, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   or a0, t3, t2
+;   ret
+
+function %f21(i64) -> i64 {
+block0(v0: i64):
+  v1 = iconst.i32 17
+  v2 = rotl.i64 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   li a6,17
+;   andi a1,a6,63
+;   li a2,64
+;   sub a4,a2,a1
+;   sll a6,a0,a1
+;   srl t3,a0,a4
+;   select_reg t0,zero,t3##condition=(a1 eq zero)
+;   or a0,a6,t0
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a6, zero, 0x11
+;   andi a1, a6, 0x3f
+;   addi a2, zero, 0x40
+;   sub a4, a2, a1
+;   sll a6, a0, a1
+;   srl t3, a0, a4
+;   beqz a1, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   or a0, a6, t0
+;   ret
+
+function %f22(i32) -> i32 {
+block0(v0: i32):
+  v1 = iconst.i32 17
+  v2 = rotl.i32 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   li t3,17
+;   slli a0,a0,32
+;   srli a2,a0,32
+;   andi a4,t3,31
+;   li a6,32
+;   sub t3,a6,a4
+;   sll t0,a2,a4
+;   srl t2,a2,t3
+;   select_reg a1,zero,t2##condition=(a4 eq zero)
+;   or a0,t0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t3, zero, 0x11
+;   slli a0, a0, 0x20
+;   srli a2, a0, 0x20
+;   andi a4, t3, 0x1f
+;   addi a6, zero, 0x20
+;   sub t3, a6, a4
+;   sll t0, a2, a4
+;   srl t2, a2, t3
+;   beqz a4, 0xc
+;   ori a1, t2, 0
+;   j 8
+;   ori a1, zero, 0
+;   or a0, t0, a1
+;   ret
+
+function %f23(i16) -> i16 {
+block0(v0: i16):
+  v1 = iconst.i32 10
+  v2 = rotl.i16 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   li t3,10
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,t3,15
+;   li a6,16
+;   sub t3,a6,a4
+;   sll t0,a2,a4
+;   srl t2,a2,t3
+;   select_reg a1,zero,t2##condition=(a4 eq zero)
+;   or a0,t0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t3, zero, 0xa
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, t3, 0xf
+;   addi a6, zero, 0x10
+;   sub t3, a6, a4
+;   sll t0, a2, a4
+;   srl t2, a2, t3
+;   beqz a4, 0xc
+;   ori a1, t2, 0
+;   j 8
+;   ori a1, zero, 0
+;   or a0, t0, a1
+;   ret
+
+function %f24(i8) -> i8 {
+block0(v0: i8):
+  v1 = iconst.i32 3
+  v2 = rotl.i8 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   li a7,3
+;   andi a0,a0,255
+;   andi a2,a7,7
+;   li a4,8
+;   sub a6,a4,a2
+;   sll t3,a0,a2
+;   srl t0,a0,a6
+;   select_reg t2,zero,t0##condition=(a2 eq zero)
+;   or a0,t3,t2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a7, zero, 3
+;   andi a0, a0, 0xff
+;   andi a2, a7, 7
+;   addi a4, zero, 8
+;   sub a6, a4, a2
+;   sll t3, a0, a2
+;   srl t0, a0, a6
+;   beqz a2, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   or a0, t3, t2
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/rotr.clif b/cranelift/filetests/filetests/isa/riscv64/rotr.clif
new file mode 100644
index 000000000..8a277577a
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/rotr.clif
@@ -0,0 +1,232 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+function %i128_rotr(i128, i128) -> i128 {
+block0(v0: i128, v1: i128):
+  v2 = rotr.i128 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a6,a4,a3
+;   srl t3,a0,a3
+;   sll t0,a1,a6
+;   mv t1,a1
+;   select_reg t2,zero,t0##condition=(a3 eq zero)
+;   or a1,t3,t2
+;   srl a4,t1,a3
+;   sll a5,a0,a6
+;   select_reg a7,zero,a5##condition=(a3 eq zero)
+;   or t4,a4,a7
+;   li t1,64
+;   andi a2,a2,127
+;   select_reg a0,t4,a1##condition=(a2 uge t1)
+;   select_reg a1,a1,t4##condition=(a2 uge t1)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a3
+;   srl t3, a0, a3
+;   sll t0, a1, a6
+;   ori t1, a1, 0
+;   beqz a3, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   or a1, t3, t2
+;   srl a4, t1, a3
+;   sll a5, a0, a6
+;   beqz a3, 0xc
+;   ori a7, a5, 0
+;   j 8
+;   ori a7, zero, 0
+;   or t4, a4, a7
+;   addi t1, zero, 0x40
+;   andi a2, a2, 0x7f
+;   bgeu a2, t1, 0xc
+;   ori a0, a1, 0
+;   j 8
+;   ori a0, t4, 0
+;   bgeu a2, t1, 8
+;   ori a1, t4, 0
+;   ret
+
+function %f0(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+  v2 = rotr.i64 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   mv a7,a0
+;   andi a0,a1,63
+;   li a2,64
+;   sub a4,a2,a0
+;   mv t0,a7
+;   srl a6,t0,a0
+;   sll t3,t0,a4
+;   select_reg t0,zero,t3##condition=(a0 eq zero)
+;   or a0,a6,t0
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   ori a7, a0, 0
+;   andi a0, a1, 0x3f
+;   addi a2, zero, 0x40
+;   sub a4, a2, a0
+;   ori t0, a7, 0
+;   srl a6, t0, a0
+;   sll t3, t0, a4
+;   beqz a0, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   or a0, a6, t0
+;   ret
+
+function %f1(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+  v2 = rotr.i32 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,32
+;   srli a2,a0,32
+;   andi a4,a1,31
+;   li a6,32
+;   sub t3,a6,a4
+;   srl t0,a2,a4
+;   sll t2,a2,t3
+;   select_reg a1,zero,t2##condition=(a4 eq zero)
+;   or a0,t0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x20
+;   srli a2, a0, 0x20
+;   andi a4, a1, 0x1f
+;   addi a6, zero, 0x20
+;   sub t3, a6, a4
+;   srl t0, a2, a4
+;   sll t2, a2, t3
+;   beqz a4, 0xc
+;   ori a1, t2, 0
+;   j 8
+;   ori a1, zero, 0
+;   or a0, t0, a1
+;   ret
+
+function %f2(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+  v2 = rotr.i16 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,a1,15
+;   li a6,16
+;   sub t3,a6,a4
+;   srl t0,a2,a4
+;   sll t2,a2,t3
+;   select_reg a1,zero,t2##condition=(a4 eq zero)
+;   or a0,t0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   addi a6, zero, 0x10
+;   sub t3, a6, a4
+;   srl t0, a2, a4
+;   sll t2, a2, t3
+;   beqz a4, 0xc
+;   ori a1, t2, 0
+;   j 8
+;   ori a1, zero, 0
+;   or a0, t0, a1
+;   ret
+
+function %f3(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+  v2 = rotr.i8 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   andi a0,a0,255
+;   andi a2,a1,7
+;   li a4,8
+;   sub a6,a4,a2
+;   srl t3,a0,a2
+;   sll t0,a0,a6
+;   select_reg t2,zero,t0##condition=(a2 eq zero)
+;   or a0,t3,t2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a0, a0, 0xff
+;   andi a2, a1, 7
+;   addi a4, zero, 8
+;   sub a6, a4, a2
+;   srl t3, a0, a2
+;   sll t0, a0, a6
+;   beqz a2, 0xc
+;   ori t2, t0, 0
+;   j 8
+;   ori t2, zero, 0
+;   or a0, t3, t2
+;   ret
+
+function %rotr_i64_const_i32(i64) -> i64 {
+block0(v0: i64):
+  v1 = iconst.i32 17
+  v2 = rotr.i64 v0, v1
+  return v2
+}
+
+; VCode:
+; block0:
+;   li a6,17
+;   andi a1,a6,63
+;   li a2,64
+;   sub a4,a2,a1
+;   srl a6,a0,a1
+;   sll t3,a0,a4
+;   select_reg t0,zero,t3##condition=(a1 eq zero)
+;   or a0,a6,t0
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a6, zero, 0x11
+;   andi a1, a6, 0x3f
+;   addi a2, zero, 0x40
+;   sub a4, a2, a1
+;   srl a6, a0, a1
+;   sll t3, a0, a4
+;   beqz a1, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   or a0, a6, t0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/shift-op.clif b/cranelift/filetests/filetests/isa/riscv64/shift-op.clif
deleted file mode 100644
index 9ac2368f1..000000000
--- a/cranelift/filetests/filetests/isa/riscv64/shift-op.clif
+++ /dev/null
@@ -1,41 +0,0 @@
-test compile precise-output
-set unwind_info=false
-target riscv64
-
-function %f(i64) -> i64 {
-block0(v0: i64):
-  v1 = iconst.i64 3
-  v2 = ishl.i64 v0, v1
-  v3 = iadd.i64 v0, v2
-  return v3
-}
-
-; VCode:
-; block0:
-;   slli a1,a0,3
-;   add a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a1, a0, 3
-;   add a0, a0, a1
-;   ret
-
-function %f(i32) -> i32 {
-block0(v0: i32):
-  v1 = iconst.i32 53
-  v2 = ishl.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slliw a0,a0,53
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slliw a0, a0, 0x15
-;   ret
-
diff --git a/cranelift/filetests/filetests/isa/riscv64/shift-rotate.clif b/cranelift/filetests/filetests/isa/riscv64/shift-rotate.clif
deleted file mode 100644
index d58cfae5f..000000000
--- a/cranelift/filetests/filetests/isa/riscv64/shift-rotate.clif
+++ /dev/null
@@ -1,845 +0,0 @@
-test compile precise-output
-set unwind_info=false
-target riscv64
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; ROR, variable
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-function %i128_rotr(i128, i128) -> i128 {
-block0(v0: i128, v1: i128):
-  v2 = rotr.i128 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a3,a2,63
-;   li a4,64
-;   sub a6,a4,a3
-;   srl t3,a0,a3
-;   sll t0,a1,a6
-;   mv t1,a1
-;   select_reg t2,zero,t0##condition=(a3 eq zero)
-;   or a1,t3,t2
-;   srl a4,t1,a3
-;   sll a5,a0,a6
-;   select_reg a7,zero,a5##condition=(a3 eq zero)
-;   or t4,a4,a7
-;   li t1,64
-;   andi a2,a2,127
-;   select_reg a0,t4,a1##condition=(a2 uge t1)
-;   select_reg a1,a1,t4##condition=(a2 uge t1)
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a3, a2, 0x3f
-;   addi a4, zero, 0x40
-;   sub a6, a4, a3
-;   srl t3, a0, a3
-;   sll t0, a1, a6
-;   ori t1, a1, 0
-;   beqz a3, 0xc
-;   ori t2, t0, 0
-;   j 8
-;   ori t2, zero, 0
-;   or a1, t3, t2
-;   srl a4, t1, a3
-;   sll a5, a0, a6
-;   beqz a3, 0xc
-;   ori a7, a5, 0
-;   j 8
-;   ori a7, zero, 0
-;   or t4, a4, a7
-;   addi t1, zero, 0x40
-;   andi a2, a2, 0x7f
-;   bgeu a2, t1, 0xc
-;   ori a0, a1, 0
-;   j 8
-;   ori a0, t4, 0
-;   bgeu a2, t1, 8
-;   ori a1, t4, 0
-;   ret
-
-function %f0(i64, i64) -> i64 {
-block0(v0: i64, v1: i64):
-  v2 = rotr.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   mv a7,a0
-;   andi a0,a1,63
-;   li a2,64
-;   sub a4,a2,a0
-;   mv t0,a7
-;   srl a6,t0,a0
-;   sll t3,t0,a4
-;   select_reg t0,zero,t3##condition=(a0 eq zero)
-;   or a0,a6,t0
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   ori a7, a0, 0
-;   andi a0, a1, 0x3f
-;   addi a2, zero, 0x40
-;   sub a4, a2, a0
-;   ori t0, a7, 0
-;   srl a6, t0, a0
-;   sll t3, t0, a4
-;   beqz a0, 0xc
-;   ori t0, t3, 0
-;   j 8
-;   ori t0, zero, 0
-;   or a0, a6, t0
-;   ret
-
-function %f1(i32, i32) -> i32 {
-block0(v0: i32, v1: i32):
-  v2 = rotr.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,32
-;   srli a2,a0,32
-;   andi a4,a1,31
-;   li a6,32
-;   sub t3,a6,a4
-;   srl t0,a2,a4
-;   sll t2,a2,t3
-;   select_reg a1,zero,t2##condition=(a4 eq zero)
-;   or a0,t0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x20
-;   srli a2, a0, 0x20
-;   andi a4, a1, 0x1f
-;   addi a6, zero, 0x20
-;   sub t3, a6, a4
-;   srl t0, a2, a4
-;   sll t2, a2, t3
-;   beqz a4, 0xc
-;   ori a1, t2, 0
-;   j 8
-;   ori a1, zero, 0
-;   or a0, t0, a1
-;   ret
-
-function %f2(i16, i16) -> i16 {
-block0(v0: i16, v1: i16):
-  v2 = rotr.i16 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,48
-;   srli a2,a0,48
-;   andi a4,a1,15
-;   li a6,16
-;   sub t3,a6,a4
-;   srl t0,a2,a4
-;   sll t2,a2,t3
-;   select_reg a1,zero,t2##condition=(a4 eq zero)
-;   or a0,t0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x30
-;   srli a2, a0, 0x30
-;   andi a4, a1, 0xf
-;   addi a6, zero, 0x10
-;   sub t3, a6, a4
-;   srl t0, a2, a4
-;   sll t2, a2, t3
-;   beqz a4, 0xc
-;   ori a1, t2, 0
-;   j 8
-;   ori a1, zero, 0
-;   or a0, t0, a1
-;   ret
-
-function %f3(i8, i8) -> i8 {
-block0(v0: i8, v1: i8):
-  v2 = rotr.i8 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a0,a0,255
-;   andi a2,a1,7
-;   li a4,8
-;   sub a6,a4,a2
-;   srl t3,a0,a2
-;   sll t0,a0,a6
-;   select_reg t2,zero,t0##condition=(a2 eq zero)
-;   or a0,t3,t2
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a0, a0, 0xff
-;   andi a2, a1, 7
-;   addi a4, zero, 8
-;   sub a6, a4, a2
-;   srl t3, a0, a2
-;   sll t0, a0, a6
-;   beqz a2, 0xc
-;   ori t2, t0, 0
-;   j 8
-;   ori t2, zero, 0
-;   or a0, t3, t2
-;   ret
-
-function %i128_rotl(i128, i128) -> i128 {
-block0(v0: i128, v1: i128):
-  v2 = rotl.i128 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a3,a2,63
-;   li a4,64
-;   sub a6,a4,a3
-;   sll t3,a0,a3
-;   srl t0,a1,a6
-;   mv t1,a1
-;   select_reg t2,zero,t0##condition=(a3 eq zero)
-;   or a1,t3,t2
-;   sll a4,t1,a3
-;   srl a5,a0,a6
-;   select_reg a7,zero,a5##condition=(a3 eq zero)
-;   or t4,a4,a7
-;   li t1,64
-;   andi a2,a2,127
-;   select_reg a0,t4,a1##condition=(a2 uge t1)
-;   select_reg a1,a1,t4##condition=(a2 uge t1)
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a3, a2, 0x3f
-;   addi a4, zero, 0x40
-;   sub a6, a4, a3
-;   sll t3, a0, a3
-;   srl t0, a1, a6
-;   ori t1, a1, 0
-;   beqz a3, 0xc
-;   ori t2, t0, 0
-;   j 8
-;   ori t2, zero, 0
-;   or a1, t3, t2
-;   sll a4, t1, a3
-;   srl a5, a0, a6
-;   beqz a3, 0xc
-;   ori a7, a5, 0
-;   j 8
-;   ori a7, zero, 0
-;   or t4, a4, a7
-;   addi t1, zero, 0x40
-;   andi a2, a2, 0x7f
-;   bgeu a2, t1, 0xc
-;   ori a0, a1, 0
-;   j 8
-;   ori a0, t4, 0
-;   bgeu a2, t1, 8
-;   ori a1, t4, 0
-;   ret
-
-function %f4(i64, i64) -> i64 {
-block0(v0: i64, v1: i64):
-  v2 = rotl.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   mv a7,a0
-;   andi a0,a1,63
-;   li a2,64
-;   sub a4,a2,a0
-;   mv t0,a7
-;   sll a6,t0,a0
-;   srl t3,t0,a4
-;   select_reg t0,zero,t3##condition=(a0 eq zero)
-;   or a0,a6,t0
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   ori a7, a0, 0
-;   andi a0, a1, 0x3f
-;   addi a2, zero, 0x40
-;   sub a4, a2, a0
-;   ori t0, a7, 0
-;   sll a6, t0, a0
-;   srl t3, t0, a4
-;   beqz a0, 0xc
-;   ori t0, t3, 0
-;   j 8
-;   ori t0, zero, 0
-;   or a0, a6, t0
-;   ret
-
-function %f5(i32, i32) -> i32 {
-block0(v0: i32, v1: i32):
-  v2 = rotl.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,32
-;   srli a2,a0,32
-;   andi a4,a1,31
-;   li a6,32
-;   sub t3,a6,a4
-;   sll t0,a2,a4
-;   srl t2,a2,t3
-;   select_reg a1,zero,t2##condition=(a4 eq zero)
-;   or a0,t0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x20
-;   srli a2, a0, 0x20
-;   andi a4, a1, 0x1f
-;   addi a6, zero, 0x20
-;   sub t3, a6, a4
-;   sll t0, a2, a4
-;   srl t2, a2, t3
-;   beqz a4, 0xc
-;   ori a1, t2, 0
-;   j 8
-;   ori a1, zero, 0
-;   or a0, t0, a1
-;   ret
-
-function %f6(i16, i16) -> i16 {
-block0(v0: i16, v1: i16):
-  v2 = rotl.i16 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,48
-;   srli a2,a0,48
-;   andi a4,a1,15
-;   li a6,16
-;   sub t3,a6,a4
-;   sll t0,a2,a4
-;   srl t2,a2,t3
-;   select_reg a1,zero,t2##condition=(a4 eq zero)
-;   or a0,t0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x30
-;   srli a2, a0, 0x30
-;   andi a4, a1, 0xf
-;   addi a6, zero, 0x10
-;   sub t3, a6, a4
-;   sll t0, a2, a4
-;   srl t2, a2, t3
-;   beqz a4, 0xc
-;   ori a1, t2, 0
-;   j 8
-;   ori a1, zero, 0
-;   or a0, t0, a1
-;   ret
-
-function %f7(i8, i8) -> i8 {
-block0(v0: i8, v1: i8):
-  v2 = rotl.i8 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a0,a0,255
-;   andi a2,a1,7
-;   li a4,8
-;   sub a6,a4,a2
-;   sll t3,a0,a2
-;   srl t0,a0,a6
-;   select_reg t2,zero,t0##condition=(a2 eq zero)
-;   or a0,t3,t2
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a0, a0, 0xff
-;   andi a2, a1, 7
-;   addi a4, zero, 8
-;   sub a6, a4, a2
-;   sll t3, a0, a2
-;   srl t0, a0, a6
-;   beqz a2, 0xc
-;   ori t2, t0, 0
-;   j 8
-;   ori t2, zero, 0
-;   or a0, t3, t2
-;   ret
-
-function %f8(i64, i64) -> i64 {
-block0(v0: i64, v1: i64):
-  v2 = ushr.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   srl a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   srl a0, a0, a1
-;   ret
-
-function %f9(i32, i32) -> i32 {
-block0(v0: i32, v1: i32):
-  v2 = ushr.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   srlw a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   srlw a0, a0, a1
-;   ret
-
-function %f10(i16, i16) -> i16 {
-block0(v0: i16, v1: i16):
-  v2 = ushr.i16 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,48
-;   srli a2,a0,48
-;   andi a4,a1,15
-;   srlw a0,a2,a4
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x30
-;   srli a2, a0, 0x30
-;   andi a4, a1, 0xf
-;   srlw a0, a2, a4
-;   ret
-
-function %f11(i8, i8) -> i8 {
-block0(v0: i8, v1: i8):
-  v2 = ushr.i8 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a0,a0,255
-;   andi a2,a1,7
-;   srlw a0,a0,a2
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a0, a0, 0xff
-;   andi a2, a1, 7
-;   srlw a0, a0, a2
-;   ret
-
-function %f12(i64, i64) -> i64 {
-block0(v0: i64, v1: i64):
-  v2 = ishl.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   sll a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   sll a0, a0, a1
-;   ret
-
-function %f13(i32, i32) -> i32 {
-block0(v0: i32, v1: i32):
-  v2 = ishl.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   sllw a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   sllw a0, a0, a1
-;   ret
-
-function %f14(i16, i16) -> i16 {
-block0(v0: i16, v1: i16):
-  v2 = ishl.i16 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a1,a1,15
-;   sllw a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a1, a1, 0xf
-;   sllw a0, a0, a1
-;   ret
-
-function %f15(i8, i8) -> i8 {
-block0(v0: i8, v1: i8):
-  v2 = ishl.i8 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   andi a1,a1,7
-;   sllw a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   andi a1, a1, 7
-;   sllw a0, a0, a1
-;   ret
-
-function %f16(i64, i64) -> i64 {
-block0(v0: i64, v1: i64):
-  v2 = sshr.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   sra a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   sra a0, a0, a1
-;   ret
-
-function %f17(i32, i32) -> i32 {
-block0(v0: i32, v1: i32):
-  v2 = sshr.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   sraw a0,a0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   sraw a0, a0, a1
-;   ret
-
-function %f18(i16, i16) -> i16 {
-block0(v0: i16, v1: i16):
-  v2 = sshr.i16 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,48
-;   srai a2,a0,48
-;   andi a4,a1,15
-;   sra a0,a2,a4
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x30
-;   srai a2, a0, 0x30
-;   andi a4, a1, 0xf
-;   sra a0, a2, a4
-;   ret
-
-function %f19(i8, i8) -> i8 {
-block0(v0: i8, v1: i8):
-  v2 = sshr.i8 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,56
-;   srai a2,a0,56
-;   andi a4,a1,7
-;   sra a0,a2,a4
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x38
-;   srai a2, a0, 0x38
-;   andi a4, a1, 7
-;   sra a0, a2, a4
-;   ret
-
-function %f20(i64) -> i64 {
-block0(v0: i64):
-  v1 = iconst.i32 17
-  v2 = rotr.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   li a6,17
-;   andi a1,a6,63
-;   li a2,64
-;   sub a4,a2,a1
-;   srl a6,a0,a1
-;   sll t3,a0,a4
-;   select_reg t0,zero,t3##condition=(a1 eq zero)
-;   or a0,a6,t0
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   addi a6, zero, 0x11
-;   andi a1, a6, 0x3f
-;   addi a2, zero, 0x40
-;   sub a4, a2, a1
-;   srl a6, a0, a1
-;   sll t3, a0, a4
-;   beqz a1, 0xc
-;   ori t0, t3, 0
-;   j 8
-;   ori t0, zero, 0
-;   or a0, a6, t0
-;   ret
-
-function %f21(i64) -> i64 {
-block0(v0: i64):
-  v1 = iconst.i32 17
-  v2 = rotl.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   li a6,17
-;   andi a1,a6,63
-;   li a2,64
-;   sub a4,a2,a1
-;   sll a6,a0,a1
-;   srl t3,a0,a4
-;   select_reg t0,zero,t3##condition=(a1 eq zero)
-;   or a0,a6,t0
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   addi a6, zero, 0x11
-;   andi a1, a6, 0x3f
-;   addi a2, zero, 0x40
-;   sub a4, a2, a1
-;   sll a6, a0, a1
-;   srl t3, a0, a4
-;   beqz a1, 0xc
-;   ori t0, t3, 0
-;   j 8
-;   ori t0, zero, 0
-;   or a0, a6, t0
-;   ret
-
-function %f22(i32) -> i32 {
-block0(v0: i32):
-  v1 = iconst.i32 17
-  v2 = rotl.i32 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   li t3,17
-;   slli a0,a0,32
-;   srli a2,a0,32
-;   andi a4,t3,31
-;   li a6,32
-;   sub t3,a6,a4
-;   sll t0,a2,a4
-;   srl t2,a2,t3
-;   select_reg a1,zero,t2##condition=(a4 eq zero)
-;   or a0,t0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   addi t3, zero, 0x11
-;   slli a0, a0, 0x20
-;   srli a2, a0, 0x20
-;   andi a4, t3, 0x1f
-;   addi a6, zero, 0x20
-;   sub t3, a6, a4
-;   sll t0, a2, a4
-;   srl t2, a2, t3
-;   beqz a4, 0xc
-;   ori a1, t2, 0
-;   j 8
-;   ori a1, zero, 0
-;   or a0, t0, a1
-;   ret
-
-function %f23(i16) -> i16 {
-block0(v0: i16):
-  v1 = iconst.i32 10
-  v2 = rotl.i16 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   li t3,10
-;   slli a0,a0,48
-;   srli a2,a0,48
-;   andi a4,t3,15
-;   li a6,16
-;   sub t3,a6,a4
-;   sll t0,a2,a4
-;   srl t2,a2,t3
-;   select_reg a1,zero,t2##condition=(a4 eq zero)
-;   or a0,t0,a1
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   addi t3, zero, 0xa
-;   slli a0, a0, 0x30
-;   srli a2, a0, 0x30
-;   andi a4, t3, 0xf
-;   addi a6, zero, 0x10
-;   sub t3, a6, a4
-;   sll t0, a2, a4
-;   srl t2, a2, t3
-;   beqz a4, 0xc
-;   ori a1, t2, 0
-;   j 8
-;   ori a1, zero, 0
-;   or a0, t0, a1
-;   ret
-
-function %f24(i8) -> i8 {
-block0(v0: i8):
-  v1 = iconst.i32 3
-  v2 = rotl.i8 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   li a7,3
-;   andi a0,a0,255
-;   andi a2,a7,7
-;   li a4,8
-;   sub a6,a4,a2
-;   sll t3,a0,a2
-;   srl t0,a0,a6
-;   select_reg t2,zero,t0##condition=(a2 eq zero)
-;   or a0,t3,t2
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   addi a7, zero, 3
-;   andi a0, a0, 0xff
-;   andi a2, a7, 7
-;   addi a4, zero, 8
-;   sub a6, a4, a2
-;   sll t3, a0, a2
-;   srl t0, a0, a6
-;   beqz a2, 0xc
-;   ori t2, t0, 0
-;   j 8
-;   ori t2, zero, 0
-;   or a0, t3, t2
-;   ret
-
-function %f25(i64) -> i64 {
-block0(v0: i64):
-  v1 = iconst.i32 17
-  v2 = ushr.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   srli a0,a0,17
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   srli a0, a0, 0x11
-;   ret
-
-function %f26(i64) -> i64 {
-block0(v0: i64):
-  v1 = iconst.i32 17
-  v2 = sshr.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   srai a0,a0,17
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   srai a0, a0, 0x11
-;   ret
-
-function %f27(i64) -> i64 {
-block0(v0: i64):
-  v1 = iconst.i32 17
-  v2 = ishl.i64 v0, v1
-  return v2
-}
-
-; VCode:
-; block0:
-;   slli a0,a0,17
-;   ret
-;
-; Disassembled:
-; block0: ; offset 0x0
-;   slli a0, a0, 0x11
-;   ret
-
diff --git a/cranelift/filetests/filetests/isa/riscv64/sshr-const.clif b/cranelift/filetests/filetests/isa/riscv64/sshr-const.clif
new file mode 100644
index 000000000..16c1fb652
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/sshr-const.clif
@@ -0,0 +1,683 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+
+function %sshr_i8_const_i8(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,56
+;   srai a1,t2,56
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x38
+;   srai a1, t2, 0x38
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i8_const_i16(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i16 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,56
+;   srai a1,t2,56
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x38
+;   srai a1, t2, 0x38
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i8_const_i32(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i32 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,56
+;   srai a1,t2,56
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x38
+;   srai a1, t2, 0x38
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i8_const_i64(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i64 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,56
+;   srai a1,t2,56
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x38
+;   srai a1, t2, 0x38
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i8_const_i128(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = sshr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,56
+;   srai a1,t2,56
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x38
+;   srai a1, t2, 0x38
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i16_const_i8(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i8 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srai a1,t2,48
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srai a1, t2, 0x30
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i16_const_i16(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i16 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srai a1,t2,48
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srai a1, t2, 0x30
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i16_const_i32(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i32 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srai a1,t2,48
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srai a1, t2, 0x30
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i16_const_i64(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i64 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srai a1,t2,48
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srai a1, t2, 0x30
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i16_const_i128(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = sshr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srai a1,t2,48
+;   sraiw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srai a1, t2, 0x30
+;   sraiw a0, a1, 5
+;   ret
+
+function %sshr_i32_const_i8(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i8 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraiw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraiw a0, a0, 5
+;   ret
+
+function %sshr_i32_const_i16(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i16 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraiw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraiw a0, a0, 5
+;   ret
+
+function %sshr_i32_const_i32(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i32 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraiw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraiw a0, a0, 5
+;   ret
+
+function %sshr_i32_const_i64(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i64 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraiw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraiw a0, a0, 5
+;   ret
+
+function %sshr_i32_const_i128(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = sshr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   sraiw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraiw a0, a0, 5
+;   ret
+
+function %sshr_i64_const_i8(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i8 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srai a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srai a0, a0, 5
+;   ret
+
+function %sshr_i64_const_i16(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i16 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srai a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srai a0, a0, 5
+;   ret
+
+function %sshr_i64_const_i32(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i32 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srai a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srai a0, a0, 5
+;   ret
+
+function %sshr_i64_const_i64(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srai a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srai a0, a0, 5
+;   ret
+
+function %sshr_i64_const_i128(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = sshr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   srai a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srai a0, a0, 5
+;   ret
+
+function %sshr_i128_const_i8(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i8 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li a2,5
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a2, zero, 5
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_const_i16(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i16 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li a2,5
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a2, zero, 5
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_const_i32(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i32 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li a2,5
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a2, zero, 5
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_const_i64(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i64 5
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li a2,5
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a2, zero, 5
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_const_i128(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = sshr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   li a3,5
+;   li a4,0
+;   andi a2,a3,63
+;   li a4,64
+;   sub a6,a4,a2
+;   sll t3,a1,a6
+;   select_reg t0,zero,t3##condition=(a2 eq zero)
+;   srl t2,a0,a2
+;   or a4,t0,t2
+;   li a5,64
+;   sra a5,a1,a2
+;   li a7,-1
+;   select_reg t4,a7,zero##condition=(a1 slt zero)
+;   li t1,64
+;   andi a1,a3,127
+;   select_reg a0,a5,a4##condition=(a1 uge t1)
+;   select_reg a1,t4,a5##condition=(a1 uge t1)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi a3, zero, 5
+;   mv a4, zero
+;   andi a2, a3, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a2
+;   sll t3, a1, a6
+;   beqz a2, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   srl t2, a0, a2
+;   or a4, t0, t2
+;   addi a5, zero, 0x40
+;   sra a5, a1, a2
+;   addi a7, zero, -1
+;   bltz a1, 0xc
+;   ori t4, zero, 0
+;   j 8
+;   ori t4, a7, 0
+;   addi t1, zero, 0x40
+;   andi a1, a3, 0x7f
+;   bgeu a1, t1, 0xc
+;   ori a0, a4, 0
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a1, t1, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, t4, 0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/sshr.clif b/cranelift/filetests/filetests/isa/riscv64/sshr.clif
new file mode 100644
index 000000000..265d29d1a
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/sshr.clif
@@ -0,0 +1,661 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+
+function %sshr_i8_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,56
+;   srai a2,a0,56
+;   andi a4,a1,7
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x38
+;   srai a2, a0, 0x38
+;   andi a4, a1, 7
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i8_i16(i8, i16) -> i8 {
+block0(v0: i8, v1: i16):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,56
+;   srai a2,a0,56
+;   andi a4,a1,7
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x38
+;   srai a2, a0, 0x38
+;   andi a4, a1, 7
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i8_i32(i8, i32) -> i8 {
+block0(v0: i8, v1: i32):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,56
+;   srai a2,a0,56
+;   andi a4,a1,7
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x38
+;   srai a2, a0, 0x38
+;   andi a4, a1, 7
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i8_i64(i8, i64) -> i8 {
+block0(v0: i8, v1: i64):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,56
+;   srai a2,a0,56
+;   andi a4,a1,7
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x38
+;   srai a2, a0, 0x38
+;   andi a4, a1, 7
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i8_i128(i8, i128) -> i8 {
+block0(v0: i8, v1: i128):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a2,a0,56
+;   srai a3,a2,56
+;   andi a5,a1,7
+;   sraw a0,a3,a5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a2, a0, 0x38
+;   srai a3, a2, 0x38
+;   andi a5, a1, 7
+;   sraw a0, a3, a5
+;   ret
+
+function %sshr_i16_i8(i16, i8) -> i16 {
+block0(v0: i16, v1: i8):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srai a2,a0,48
+;   andi a4,a1,15
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srai a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i16_i16(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srai a2,a0,48
+;   andi a4,a1,15
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srai a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i16_i32(i16, i32) -> i16 {
+block0(v0: i16, v1: i32):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srai a2,a0,48
+;   andi a4,a1,15
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srai a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i16_i64(i16, i64) -> i16 {
+block0(v0: i16, v1: i64):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srai a2,a0,48
+;   andi a4,a1,15
+;   sraw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srai a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   sraw a0, a2, a4
+;   ret
+
+function %sshr_i16_i128(i16, i128) -> i16 {
+block0(v0: i16, v1: i128):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a2,a0,48
+;   srai a3,a2,48
+;   andi a5,a1,15
+;   sraw a0,a3,a5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a2, a0, 0x30
+;   srai a3, a2, 0x30
+;   andi a5, a1, 0xf
+;   sraw a0, a3, a5
+;   ret
+
+function %sshr_i32_i8(i32, i8) -> i32 {
+block0(v0: i32, v1: i8):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraw a0, a0, a1
+;   ret
+
+function %sshr_i32_i16(i32, i16) -> i32 {
+block0(v0: i32, v1: i16):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraw a0, a0, a1
+;   ret
+
+function %sshr_i32_i32(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraw a0, a0, a1
+;   ret
+
+function %sshr_i32_i64(i32, i64) -> i32 {
+block0(v0: i32, v1: i64):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraw a0, a0, a1
+;   ret
+
+function %sshr_i32_i128(i32, i128) -> i32 {
+block0(v0: i32, v1: i128):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sraw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sraw a0, a0, a1
+;   ret
+
+function %sshr_i64_i8(i64, i8) -> i64 {
+block0(v0: i64, v1: i8):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sra a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sra a0, a0, a1
+;   ret
+
+function %sshr_i64_i16(i64, i16) -> i64 {
+block0(v0: i64, v1: i16):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sra a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sra a0, a0, a1
+;   ret
+
+function %sshr_i64_i32(i64, i32) -> i64 {
+block0(v0: i64, v1: i32):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sra a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sra a0, a0, a1
+;   ret
+
+function %sshr_i64_i64(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sra a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sra a0, a0, a1
+;   ret
+
+function %sshr_i64_i128(i64, i128) -> i64 {
+block0(v0: i64, v1: i128):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   sra a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   sra a0, a0, a1
+;   ret
+
+function %sshr_i128_i8(i128, i8) -> i128 {
+block0(v0: i128, v1: i8):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_i16(i128, i16) -> i128 {
+block0(v0: i128, v1: i16):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_i32(i128, i32) -> i128 {
+block0(v0: i128, v1: i32):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_i64(i128, i64) -> i128 {
+block0(v0: i128, v1: i64):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   sra a4,a1,a3
+;   li a6,-1
+;   select_reg t3,a6,zero##condition=(a1 slt zero)
+;   li t0,64
+;   andi t2,a2,127
+;   select_reg a0,a4,a0##condition=(t2 uge t0)
+;   select_reg a1,t3,a4##condition=(t2 uge t0)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   sra a4, a1, a3
+;   addi a6, zero, -1
+;   bltz a1, 0xc
+;   ori t3, zero, 0
+;   j 8
+;   ori t3, a6, 0
+;   addi t0, zero, 0x40
+;   andi t2, a2, 0x7f
+;   bgeu t2, t0, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu t2, t0, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, t3, 0
+;   ret
+
+function %sshr_i128_i128(i128, i128) -> i128 {
+block0(v0: i128, v1: i128):
+    v2 = sshr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a6,a4,a3
+;   sll t3,a1,a6
+;   select_reg t0,zero,t3##condition=(a3 eq zero)
+;   srl t2,a0,a3
+;   or a4,t0,t2
+;   li a5,64
+;   sra a5,a1,a3
+;   li a7,-1
+;   select_reg t4,a7,zero##condition=(a1 slt zero)
+;   li t1,64
+;   andi a1,a2,127
+;   select_reg a0,a5,a4##condition=(a1 uge t1)
+;   select_reg a1,t4,a5##condition=(a1 uge t1)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a3
+;   sll t3, a1, a6
+;   beqz a3, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   srl t2, a0, a3
+;   or a4, t0, t2
+;   addi a5, zero, 0x40
+;   sra a5, a1, a3
+;   addi a7, zero, -1
+;   bltz a1, 0xc
+;   ori t4, zero, 0
+;   j 8
+;   ori t4, a7, 0
+;   addi t1, zero, 0x40
+;   andi a1, a2, 0x7f
+;   bgeu a1, t1, 0xc
+;   ori a0, a4, 0
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a1, t1, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, t4, 0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/ushr-const.clif b/cranelift/filetests/filetests/isa/riscv64/ushr-const.clif
new file mode 100644
index 000000000..9a8a7b3de
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/ushr-const.clif
@@ -0,0 +1,632 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+
+function %ushr_i8_const_i8(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i8 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi t2,a0,255
+;   srliw a0,t2,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi t2, a0, 0xff
+;   srliw a0, t2, 5
+;   ret
+
+function %ushr_i8_const_i16(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i16 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi t2,a0,255
+;   srliw a0,t2,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi t2, a0, 0xff
+;   srliw a0, t2, 5
+;   ret
+
+function %ushr_i8_const_i32(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i32 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi t2,a0,255
+;   srliw a0,t2,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi t2, a0, 0xff
+;   srliw a0, t2, 5
+;   ret
+
+function %ushr_i8_const_i64(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i64 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi t2,a0,255
+;   srliw a0,t2,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi t2, a0, 0xff
+;   srliw a0, t2, 5
+;   ret
+
+function %ushr_i8_const_i128(i8) -> i8 {
+block0(v0: i8):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ushr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   andi t2,a0,255
+;   srliw a0,t2,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi t2, a0, 0xff
+;   srliw a0, t2, 5
+;   ret
+
+function %ushr_i16_const_i8(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i8 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srli a1,t2,48
+;   srliw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srli a1, t2, 0x30
+;   srliw a0, a1, 5
+;   ret
+
+function %ushr_i16_const_i16(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i16 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srli a1,t2,48
+;   srliw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srli a1, t2, 0x30
+;   srliw a0, a1, 5
+;   ret
+
+function %ushr_i16_const_i32(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i32 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srli a1,t2,48
+;   srliw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srli a1, t2, 0x30
+;   srliw a0, a1, 5
+;   ret
+
+function %ushr_i16_const_i64(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i64 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srli a1,t2,48
+;   srliw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srli a1, t2, 0x30
+;   srliw a0, a1, 5
+;   ret
+
+function %ushr_i16_const_i128(i16) -> i16 {
+block0(v0: i16):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ushr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   slli t2,a0,48
+;   srli a1,t2,48
+;   srliw a0,a1,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli t2, a0, 0x30
+;   srli a1, t2, 0x30
+;   srliw a0, a1, 5
+;   ret
+
+function %ushr_i32_const_i8(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i8 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srliw a0, a0, 5
+;   ret
+
+function %ushr_i32_const_i16(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i16 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srliw a0, a0, 5
+;   ret
+
+function %ushr_i32_const_i32(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i32 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srliw a0, a0, 5
+;   ret
+
+function %ushr_i32_const_i64(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i64 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srliw a0, a0, 5
+;   ret
+
+function %ushr_i32_const_i128(i32) -> i32 {
+block0(v0: i32):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ushr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   srliw a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srliw a0, a0, 5
+;   ret
+
+function %ushr_i64_const_i8(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i8 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srli a0, a0, 5
+;   ret
+
+function %ushr_i64_const_i16(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i16 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srli a0, a0, 5
+;   ret
+
+function %ushr_i64_const_i32(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i32 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srli a0, a0, 5
+;   ret
+
+function %ushr_i64_const_i64(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srli a0, a0, 5
+;   ret
+
+function %ushr_i64_const_i128(i64) -> i64 {
+block0(v0: i64):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ushr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   srli a0,a0,5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srli a0, a0, 5
+;   ret
+
+function %ushr_i128_const_i8(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i8 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a2 eq zero)
+;   srl t1,a0,a2
+;   or a0,t4,t1
+;   li a3,64
+;   srl a4,a1,a2
+;   andi a6,t2,127
+;   select_reg a0,a4,a0##condition=(a6 uge a3)
+;   select_reg a1,zero,a4##condition=(a6 uge a3)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a1, a5
+;   beqz a2, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a2
+;   or a0, t4, t1
+;   addi a3, zero, 0x40
+;   srl a4, a1, a2
+;   andi a6, t2, 0x7f
+;   bgeu a6, a3, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu a6, a3, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_const_i16(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i16 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a2 eq zero)
+;   srl t1,a0,a2
+;   or a0,t4,t1
+;   li a3,64
+;   srl a4,a1,a2
+;   andi a6,t2,127
+;   select_reg a0,a4,a0##condition=(a6 uge a3)
+;   select_reg a1,zero,a4##condition=(a6 uge a3)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a1, a5
+;   beqz a2, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a2
+;   or a0, t4, t1
+;   addi a3, zero, 0x40
+;   srl a4, a1, a2
+;   andi a6, t2, 0x7f
+;   bgeu a6, a3, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu a6, a3, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_const_i32(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i32 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a2 eq zero)
+;   srl t1,a0,a2
+;   or a0,t4,t1
+;   li a3,64
+;   srl a4,a1,a2
+;   andi a6,t2,127
+;   select_reg a0,a4,a0##condition=(a6 uge a3)
+;   select_reg a1,zero,a4##condition=(a6 uge a3)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a1, a5
+;   beqz a2, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a2
+;   or a0, t4, t1
+;   addi a3, zero, 0x40
+;   srl a4, a1, a2
+;   andi a6, t2, 0x7f
+;   bgeu a6, a3, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu a6, a3, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_const_i64(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i64 5
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   li t2,5
+;   andi a2,t2,63
+;   li a3,64
+;   sub a5,a3,a2
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a2 eq zero)
+;   srl t1,a0,a2
+;   or a0,t4,t1
+;   li a3,64
+;   srl a4,a1,a2
+;   andi a6,t2,127
+;   select_reg a0,a4,a0##condition=(a6 uge a3)
+;   select_reg a1,zero,a4##condition=(a6 uge a3)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   addi t2, zero, 5
+;   andi a2, t2, 0x3f
+;   addi a3, zero, 0x40
+;   sub a5, a3, a2
+;   sll a7, a1, a5
+;   beqz a2, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a2
+;   or a0, t4, t1
+;   addi a3, zero, 0x40
+;   srl a4, a1, a2
+;   andi a6, t2, 0x7f
+;   bgeu a6, a3, 8
+;   j 8
+;   ori a0, a4, 0
+;   bgeu a6, a3, 0xc
+;   ori a1, a4, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_const_i128(i128) -> i128 {
+block0(v0: i128):
+    v1 = iconst.i64 5
+    v2 = uextend.i128 v1
+    v3 = ushr v0, v2
+    return v3
+}
+
+; VCode:
+; block0:
+;   mv a3,a0
+;   li a0,5
+;   li a2,0
+;   andi a2,a0,63
+;   li a4,64
+;   sub a6,a4,a2
+;   sll t3,a1,a6
+;   select_reg t0,zero,t3##condition=(a2 eq zero)
+;   mv t3,a3
+;   srl t2,t3,a2
+;   or a4,t0,t2
+;   li a3,64
+;   srl a5,a1,a2
+;   andi a7,a0,127
+;   select_reg a0,a5,a4##condition=(a7 uge a3)
+;   select_reg a1,zero,a5##condition=(a7 uge a3)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   ori a3, a0, 0
+;   addi a0, zero, 5
+;   mv a2, zero
+;   andi a2, a0, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a2
+;   sll t3, a1, a6
+;   beqz a2, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   ori t3, a3, 0
+;   srl t2, t3, a2
+;   or a4, t0, t2
+;   addi a3, zero, 0x40
+;   srl a5, a1, a2
+;   andi a7, a0, 0x7f
+;   bgeu a7, a3, 0xc
+;   ori a0, a4, 0
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a7, a3, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/riscv64/ushr.clif b/cranelift/filetests/filetests/isa/riscv64/ushr.clif
new file mode 100644
index 000000000..c1603e5ae
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/riscv64/ushr.clif
@@ -0,0 +1,608 @@
+test compile precise-output
+set unwind_info=false
+target riscv64
+
+
+function %ushr_i8_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a0,a0,255
+;   andi a2,a1,7
+;   srlw a0,a0,a2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a0, a0, 0xff
+;   andi a2, a1, 7
+;   srlw a0, a0, a2
+;   ret
+
+function %ushr_i8_i16(i8, i16) -> i8 {
+block0(v0: i8, v1: i16):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a0,a0,255
+;   andi a2,a1,7
+;   srlw a0,a0,a2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a0, a0, 0xff
+;   andi a2, a1, 7
+;   srlw a0, a0, a2
+;   ret
+
+function %ushr_i8_i32(i8, i32) -> i8 {
+block0(v0: i8, v1: i32):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a0,a0,255
+;   andi a2,a1,7
+;   srlw a0,a0,a2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a0, a0, 0xff
+;   andi a2, a1, 7
+;   srlw a0, a0, a2
+;   ret
+
+function %ushr_i8_i64(i8, i64) -> i8 {
+block0(v0: i8, v1: i64):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a0,a0,255
+;   andi a2,a1,7
+;   srlw a0,a0,a2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a0, a0, 0xff
+;   andi a2, a1, 7
+;   srlw a0, a0, a2
+;   ret
+
+function %ushr_i8_i128(i8, i128) -> i8 {
+block0(v0: i8, v1: i128):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   mv a5,a1
+;   andi a1,a0,255
+;   andi a3,a5,7
+;   srlw a0,a1,a3
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   ori a5, a1, 0
+;   andi a1, a0, 0xff
+;   andi a3, a5, 7
+;   srlw a0, a1, a3
+;   ret
+
+function %ushr_i16_i8(i16, i8) -> i16 {
+block0(v0: i16, v1: i8):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,a1,15
+;   srlw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   srlw a0, a2, a4
+;   ret
+
+function %ushr_i16_i16(i16, i16) -> i16 {
+block0(v0: i16, v1: i16):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,a1,15
+;   srlw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   srlw a0, a2, a4
+;   ret
+
+function %ushr_i16_i32(i16, i32) -> i16 {
+block0(v0: i16, v1: i32):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,a1,15
+;   srlw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   srlw a0, a2, a4
+;   ret
+
+function %ushr_i16_i64(i16, i64) -> i16 {
+block0(v0: i16, v1: i64):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a0,a0,48
+;   srli a2,a0,48
+;   andi a4,a1,15
+;   srlw a0,a2,a4
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a0, a0, 0x30
+;   srli a2, a0, 0x30
+;   andi a4, a1, 0xf
+;   srlw a0, a2, a4
+;   ret
+
+function %ushr_i16_i128(i16, i128) -> i16 {
+block0(v0: i16, v1: i128):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   slli a2,a0,48
+;   srli a3,a2,48
+;   andi a5,a1,15
+;   srlw a0,a3,a5
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   slli a2, a0, 0x30
+;   srli a3, a2, 0x30
+;   andi a5, a1, 0xf
+;   srlw a0, a3, a5
+;   ret
+
+function %ushr_i32_i8(i32, i8) -> i32 {
+block0(v0: i32, v1: i8):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srlw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srlw a0, a0, a1
+;   ret
+
+function %ushr_i32_i16(i32, i16) -> i32 {
+block0(v0: i32, v1: i16):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srlw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srlw a0, a0, a1
+;   ret
+
+function %ushr_i32_i32(i32, i32) -> i32 {
+block0(v0: i32, v1: i32):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srlw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srlw a0, a0, a1
+;   ret
+
+function %ushr_i32_i64(i32, i64) -> i32 {
+block0(v0: i32, v1: i64):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srlw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srlw a0, a0, a1
+;   ret
+
+function %ushr_i32_i128(i32, i128) -> i32 {
+block0(v0: i32, v1: i128):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srlw a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srlw a0, a0, a1
+;   ret
+
+function %ushr_i64_i8(i64, i8) -> i64 {
+block0(v0: i64, v1: i8):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srl a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srl a0, a0, a1
+;   ret
+
+function %ushr_i64_i16(i64, i16) -> i64 {
+block0(v0: i64, v1: i16):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srl a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srl a0, a0, a1
+;   ret
+
+function %ushr_i64_i32(i64, i32) -> i64 {
+block0(v0: i64, v1: i32):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srl a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srl a0, a0, a1
+;   ret
+
+function %ushr_i64_i64(i64, i64) -> i64 {
+block0(v0: i64, v1: i64):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srl a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srl a0, a0, a1
+;   ret
+
+function %ushr_i64_i128(i64, i128) -> i64 {
+block0(v0: i64, v1: i128):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   srl a0,a0,a1
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   srl a0, a0, a1
+;   ret
+
+function %ushr_i128_i8(i128, i8) -> i128 {
+block0(v0: i128, v1: i8):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   srl a5,a1,a3
+;   andi a6,a2,127
+;   select_reg a0,a5,a0##condition=(a6 uge a4)
+;   select_reg a1,zero,a5##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   srl a5, a1, a3
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 8
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_i16(i128, i16) -> i128 {
+block0(v0: i128, v1: i16):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   srl a5,a1,a3
+;   andi a6,a2,127
+;   select_reg a0,a5,a0##condition=(a6 uge a4)
+;   select_reg a1,zero,a5##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   srl a5, a1, a3
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 8
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_i32(i128, i32) -> i128 {
+block0(v0: i128, v1: i32):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   srl a5,a1,a3
+;   andi a6,a2,127
+;   select_reg a0,a5,a0##condition=(a6 uge a4)
+;   select_reg a1,zero,a5##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   srl a5, a1, a3
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 8
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_i64(i128, i64) -> i128 {
+block0(v0: i128, v1: i64):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a5,a4,a3
+;   sll a7,a1,a5
+;   select_reg t4,zero,a7##condition=(a3 eq zero)
+;   srl t1,a0,a3
+;   or a0,t4,t1
+;   li a4,64
+;   srl a5,a1,a3
+;   andi a6,a2,127
+;   select_reg a0,a5,a0##condition=(a6 uge a4)
+;   select_reg a1,zero,a5##condition=(a6 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a5, a4, a3
+;   sll a7, a1, a5
+;   beqz a3, 0xc
+;   ori t4, a7, 0
+;   j 8
+;   ori t4, zero, 0
+;   srl t1, a0, a3
+;   or a0, t4, t1
+;   addi a4, zero, 0x40
+;   srl a5, a1, a3
+;   andi a6, a2, 0x7f
+;   bgeu a6, a4, 8
+;   j 8
+;   ori a0, a5, 0
+;   bgeu a6, a4, 0xc
+;   ori a1, a5, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
+function %ushr_i128_i128(i128, i128) -> i128 {
+block0(v0: i128, v1: i128):
+    v2 = ushr v0, v1
+    return v2
+}
+
+; VCode:
+; block0:
+;   andi a3,a2,63
+;   li a4,64
+;   sub a6,a4,a3
+;   sll t3,a1,a6
+;   select_reg t0,zero,t3##condition=(a3 eq zero)
+;   srl t2,a0,a3
+;   or a5,t0,t2
+;   li a4,64
+;   srl a6,a1,a3
+;   andi a7,a2,127
+;   select_reg a0,a6,a5##condition=(a7 uge a4)
+;   select_reg a1,zero,a6##condition=(a7 uge a4)
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   andi a3, a2, 0x3f
+;   addi a4, zero, 0x40
+;   sub a6, a4, a3
+;   sll t3, a1, a6
+;   beqz a3, 0xc
+;   ori t0, t3, 0
+;   j 8
+;   ori t0, zero, 0
+;   srl t2, a0, a3
+;   or a5, t0, t2
+;   addi a4, zero, 0x40
+;   srl a6, a1, a3
+;   andi a7, a2, 0x7f
+;   bgeu a7, a4, 0xc
+;   ori a0, a5, 0
+;   j 8
+;   ori a0, a6, 0
+;   bgeu a7, a4, 0xc
+;   ori a1, a6, 0
+;   j 8
+;   ori a1, zero, 0
+;   ret
+
diff --git a/cranelift/filetests/filetests/runtests/simd-bitcast.clif b/cranelift/filetests/filetests/runtests/simd-bitcast.clif
index fdc3454b7..8140fc267 100644
--- a/cranelift/filetests/filetests/runtests/simd-bitcast.clif
+++ b/cranelift/filetests/filetests/runtests/simd-bitcast.clif
@@ -35,3 +35,19 @@ block0(v0: f64x2):
 }
 ; run: %bitcast_fi64x2([0x0.0 -NaN:0x7ffffffffffff]) == [0 18446744073709551615]
 ; run: %bitcast_fi64x2([-NaN:0x7ffffffffffff 0x0.000000000007fp-1022]) == [-1 127]
+
+function %bitcast_more_lanes_little(i64x2) -> i32x4 {
+block0(v0: i64x2):
+    v1 = bitcast.i32x4 little v0
+    return v1
+}
+; run: %bitcast_more_lanes_little(0x00000000000000000000000000000000) == 0x00000000000000000000000000000000
+; run: %bitcast_more_lanes_little(0x00000000000000ff00000000000000ff) == 0x00000000000000ff00000000000000ff
+
+function %bitcast_fewer_lanes_little(i16x8) -> i64x2 {
+block0(v0: i16x8):
+    v1 = bitcast.i64x2 little v0
+    return v1
+}
+; run: %bitcast_fewer_lanes_little(0x00000000000000000000000000000000) == 0x00000000000000000000000000000000
+; run: %bitcast_fewer_lanes_little(0x00ff0000000000000000000000000000) == 0x00ff0000000000000000000000000000
diff --git a/winch/filetests/filetests/x64/i32_eqz/const.wat b/winch/filetests/filetests/x64/i32_eqz/const.wat
new file mode 100644
index 000000000..d6624bef9
--- /dev/null
+++ b/winch/filetests/filetests/x64/i32_eqz/const.wat
@@ -0,0 +1,19 @@
+;;! target = "x86_64"
+
+(module
+    (func (result i32)
+        (i32.const 1)
+        (i32.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec08             	sub	rsp, 8
+;;    8:	 4c893424             	mov	qword ptr [rsp], r14
+;;    c:	 b801000000           	mov	eax, 1
+;;   11:	 83f800               	cmp	eax, 0
+;;   14:	 b800000000           	mov	eax, 0
+;;   19:	 400f94c0             	sete	al
+;;   1d:	 4883c408             	add	rsp, 8
+;;   21:	 5d                   	pop	rbp
+;;   22:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i32_eqz/local.wat b/winch/filetests/filetests/x64/i32_eqz/local.wat
new file mode 100644
index 000000000..a1631bc81
--- /dev/null
+++ b/winch/filetests/filetests/x64/i32_eqz/local.wat
@@ -0,0 +1,28 @@
+;;! target = "x86_64"
+
+(module
+    (func (result i32)
+        (local $foo i32)
+
+        (i32.const 2)
+        (local.set $foo)
+
+        (local.get $foo)
+        (i32.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec10             	sub	rsp, 0x10
+;;    8:	 48c744240800000000   	
+;; 				mov	qword ptr [rsp + 8], 0
+;;   11:	 4c89742404           	mov	qword ptr [rsp + 4], r14
+;;   16:	 b802000000           	mov	eax, 2
+;;   1b:	 8944240c             	mov	dword ptr [rsp + 0xc], eax
+;;   1f:	 8b44240c             	mov	eax, dword ptr [rsp + 0xc]
+;;   23:	 83f800               	cmp	eax, 0
+;;   26:	 b800000000           	mov	eax, 0
+;;   2b:	 400f94c0             	sete	al
+;;   2f:	 4883c410             	add	rsp, 0x10
+;;   33:	 5d                   	pop	rbp
+;;   34:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i32_eqz/param.wat b/winch/filetests/filetests/x64/i32_eqz/param.wat
new file mode 100644
index 000000000..66b553645
--- /dev/null
+++ b/winch/filetests/filetests/x64/i32_eqz/param.wat
@@ -0,0 +1,20 @@
+;;! target = "x86_64"
+
+(module
+    (func (param i32) (result i32)
+        (local.get 0)
+        (i32.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec10             	sub	rsp, 0x10
+;;    8:	 897c240c             	mov	dword ptr [rsp + 0xc], edi
+;;    c:	 4c89742404           	mov	qword ptr [rsp + 4], r14
+;;   11:	 8b44240c             	mov	eax, dword ptr [rsp + 0xc]
+;;   15:	 83f800               	cmp	eax, 0
+;;   18:	 b800000000           	mov	eax, 0
+;;   1d:	 400f94c0             	sete	al
+;;   21:	 4883c410             	add	rsp, 0x10
+;;   25:	 5d                   	pop	rbp
+;;   26:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_eqz/32_const.wat b/winch/filetests/filetests/x64/i64_eqz/32_const.wat
new file mode 100644
index 000000000..257d0f006
--- /dev/null
+++ b/winch/filetests/filetests/x64/i64_eqz/32_const.wat
@@ -0,0 +1,19 @@
+;;! target = "x86_64"
+
+(module
+    (func (result i32)
+        (i64.const 1)
+        (i64.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec08             	sub	rsp, 8
+;;    8:	 4c893424             	mov	qword ptr [rsp], r14
+;;    c:	 48c7c001000000       	mov	rax, 1
+;;   13:	 4883f800             	cmp	rax, 0
+;;   17:	 b800000000           	mov	eax, 0
+;;   1c:	 400f94c0             	sete	al
+;;   20:	 4883c408             	add	rsp, 8
+;;   24:	 5d                   	pop	rbp
+;;   25:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_eqz/64_const.wat b/winch/filetests/filetests/x64/i64_eqz/64_const.wat
new file mode 100644
index 000000000..7326c59de
--- /dev/null
+++ b/winch/filetests/filetests/x64/i64_eqz/64_const.wat
@@ -0,0 +1,20 @@
+;;! target = "x86_64"
+
+(module
+    (func (result i32)
+        (i64.const 9223372036854775807)
+        (i64.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec08             	sub	rsp, 8
+;;    8:	 4c893424             	mov	qword ptr [rsp], r14
+;;    c:	 48b8ffffffffffffff7f 	
+;; 				movabs	rax, 0x7fffffffffffffff
+;;   16:	 4883f800             	cmp	rax, 0
+;;   1a:	 b800000000           	mov	eax, 0
+;;   1f:	 400f94c0             	sete	al
+;;   23:	 4883c408             	add	rsp, 8
+;;   27:	 5d                   	pop	rbp
+;;   28:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_eqz/local.wat b/winch/filetests/filetests/x64/i64_eqz/local.wat
new file mode 100644
index 000000000..849164e6c
--- /dev/null
+++ b/winch/filetests/filetests/x64/i64_eqz/local.wat
@@ -0,0 +1,28 @@
+;;! target = "x86_64"
+
+(module
+    (func (result i32)
+        (local $foo i64)
+
+        (i64.const 2)
+        (local.set $foo)
+
+        (local.get $foo)
+        (i64.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec10             	sub	rsp, 0x10
+;;    8:	 48c744240800000000   	
+;; 				mov	qword ptr [rsp + 8], 0
+;;   11:	 4c893424             	mov	qword ptr [rsp], r14
+;;   15:	 48c7c002000000       	mov	rax, 2
+;;   1c:	 4889442408           	mov	qword ptr [rsp + 8], rax
+;;   21:	 488b442408           	mov	rax, qword ptr [rsp + 8]
+;;   26:	 4883f800             	cmp	rax, 0
+;;   2a:	 b800000000           	mov	eax, 0
+;;   2f:	 400f94c0             	sete	al
+;;   33:	 4883c410             	add	rsp, 0x10
+;;   37:	 5d                   	pop	rbp
+;;   38:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_eqz/param.wat b/winch/filetests/filetests/x64/i64_eqz/param.wat
new file mode 100644
index 000000000..48972c40b
--- /dev/null
+++ b/winch/filetests/filetests/x64/i64_eqz/param.wat
@@ -0,0 +1,20 @@
+;;! target = "x86_64"
+
+(module
+    (func (param i64) (result i32)
+        (local.get 0)
+        (i64.eqz)
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec10             	sub	rsp, 0x10
+;;    8:	 48897c2408           	mov	qword ptr [rsp + 8], rdi
+;;    d:	 4c893424             	mov	qword ptr [rsp], r14
+;;   11:	 488b442408           	mov	rax, qword ptr [rsp + 8]
+;;   16:	 4883f800             	cmp	rax, 0
+;;   1a:	 b800000000           	mov	eax, 0
+;;   1f:	 400f94c0             	sete	al
+;;   23:	 4883c410             	add	rsp, 0x10
+;;   27:	 5d                   	pop	rbp
+;;   28:	 c3                   	ret