diff --git a/cranelift/codegen/src/isle_prelude.rs b/cranelift/codegen/src/isle_prelude.rs index 0b04f75a5b23..bca77cfe6d67 100644 --- a/cranelift/codegen/src/isle_prelude.rs +++ b/cranelift/codegen/src/isle_prelude.rs @@ -27,6 +27,42 @@ macro_rules! isle_common_prelude_methods { self.checked_add_with_type(ty, a, b).is_none() } + #[inline] + fn imm64_rotl(&mut self, ty: Type, x: Imm64, k: Imm64) -> Imm64 { + let bw: u32 = ty.bits().min(64); + let amt: u32 = if bw == 0 { 0 } else { (k.bits() as u32) % bw }; + + let xv = x.bits() as u64; + let v = match bw { + 8 => (xv as u8).rotate_left(amt) as u64, + 16 => (xv as u16).rotate_left(amt) as u64, + 32 => (xv as u32).rotate_left(amt) as u64, + 64 => xv.rotate_left(amt), + _ => xv, + }; + + let masked = v & self.ty_mask(ty); + Imm64::new(masked as i64) + } + + #[inline] + fn imm64_rotr(&mut self, ty: Type, x: Imm64, k: Imm64) -> Imm64 { + let bw: u32 = ty.bits().min(64); + let amt: u32 = if bw == 0 { 0 } else { (k.bits() as u32) % bw }; + + let xv = x.bits() as u64; + let v = match bw { + 8 => (xv as u8).rotate_right(amt) as u64, + 16 => (xv as u16).rotate_right(amt) as u64, + 32 => (xv as u32).rotate_right(amt) as u64, + 64 => xv.rotate_right(amt), + _ => xv, + }; + + let masked = v & self.ty_mask(ty); + Imm64::new(masked as i64) + } + #[inline] fn imm64_sdiv(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option { // Sign extend `x` and `y`. diff --git a/cranelift/codegen/src/opts/cprop.isle b/cranelift/codegen/src/opts/cprop.isle index 2e9ea307ec0f..cea66a8e1dba 100644 --- a/cranelift/codegen/src/opts/cprop.isle +++ b/cranelift/codegen/src/opts/cprop.isle @@ -1,5 +1,17 @@ ;; Constant propagation. +(rule (simplify + (rotl (fits_in_64 ty) + (iconst ty kx) + (iconst ty kk))) + (subsume (iconst ty (imm64_rotl ty kx kk)))) + +(rule (simplify + (rotr (fits_in_64 ty) + (iconst ty kx) + (iconst ty kk))) + (subsume (iconst ty (imm64_rotr ty kx kk)))) + (rule (simplify (iadd (fits_in_64 ty) (iconst ty (u64_from_imm64 k1)) diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index 20a61cde2e67..01f1c5d73353 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -96,6 +96,12 @@ (decl pure imm64_icmp (Type IntCC Imm64 Imm64) Imm64) (extern constructor imm64_icmp imm64_icmp) +(decl pure imm64_rotl (Type Imm64 Imm64) Imm64) +(extern constructor imm64_rotl imm64_rotl) + +(decl pure imm64_rotr (Type Imm64 Imm64) Imm64) +(extern constructor imm64_rotr imm64_rotr) + ;; Each of these extractors tests whether the upper half of the input equals the ;; lower half of the input (decl u128_replicated_u64 (u64) u128)