diff --git a/cranelift/codegen/src/isle_prelude.rs b/cranelift/codegen/src/isle_prelude.rs index 26788399c7..0e3e293c1f 100644 --- a/cranelift/codegen/src/isle_prelude.rs +++ b/cranelift/codegen/src/isle_prelude.rs @@ -140,33 +140,33 @@ macro_rules! isle_common_prelude_methods { } #[inline] - fn u64_sextend_u32(&mut self, x: u64) -> u64 { - x as u32 as i32 as i64 as u64 + fn i64_sextend_imm64(&mut self, ty: Type, mut x: Imm64) -> i64 { + x.sign_extend_from_width(ty.bits()); + x.bits() } #[inline] - fn u64_uextend_u32(&mut self, x: u64) -> u64 { - x & 0xffff_ffff + fn u64_uextend_imm64(&mut self, ty: Type, x: Imm64) -> u64 { + (x.bits() as u64) & self.ty_mask(ty) } #[inline] fn imm64_icmp(&mut self, ty: Type, cc: &IntCC, x: Imm64, y: Imm64) -> Imm64 { - let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0); - let mask = u64::MAX >> shift; - let x = (x.bits() as u64) & mask; - let y = (y.bits() as u64) & mask; - let sext = |v| ((v << shift) as i64) >> shift; + let ux = self.u64_uextend_imm64(ty, x); + let uy = self.u64_uextend_imm64(ty, y); + let sx = self.i64_sextend_imm64(ty, x); + let sy = self.i64_sextend_imm64(ty, y); let result = match cc { - IntCC::Equal => x == y, - IntCC::NotEqual => x != y, - IntCC::UnsignedGreaterThanOrEqual => x >= y, - IntCC::UnsignedGreaterThan => x > y, - IntCC::UnsignedLessThanOrEqual => x <= y, - IntCC::UnsignedLessThan => x < y, - IntCC::SignedGreaterThanOrEqual => sext(x) >= sext(y), - IntCC::SignedGreaterThan => sext(x) > sext(y), - IntCC::SignedLessThanOrEqual => sext(x) <= sext(y), - IntCC::SignedLessThan => sext(x) < sext(y), + IntCC::Equal => ux == uy, + IntCC::NotEqual => ux != uy, + IntCC::UnsignedGreaterThanOrEqual => ux >= uy, + IntCC::UnsignedGreaterThan => ux > uy, + IntCC::UnsignedLessThanOrEqual => ux <= uy, + IntCC::UnsignedLessThan => ux < uy, + IntCC::SignedGreaterThanOrEqual => sx >= sy, + IntCC::SignedGreaterThan => sx > sy, + IntCC::SignedLessThanOrEqual => sx <= sy, + IntCC::SignedLessThan => sx < sy, }; Imm64::new(result.into()) } @@ -586,12 +586,7 @@ macro_rules! isle_common_prelude_methods { #[inline] fn imm64_masked(&mut self, ty: Type, x: u64) -> Imm64 { - debug_assert!(ty.bits() <= 64); - // Careful: we can't do `(1 << bits) - 1` because that - // would overflow for `bits == 64`. Instead, - // right-shift an all-ones mask. - let mask = u64::MAX >> (64 - ty.bits()); - Imm64::new((x & mask) as i64) + Imm64::new((x & self.ty_mask(ty)) as i64) } #[inline] diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle index 3b6b067a9a..d889fd8faa 100644 --- a/cranelift/codegen/src/opts/algebraic.isle +++ b/cranelift/codegen/src/opts/algebraic.isle @@ -6,12 +6,6 @@ ;; than a piece of the input or a new node that we construct; but we ;; can freely rewrite e.g. `x+y-y` to `x`. -;; uextend/sextend of a constant. -(rule (simplify (uextend $I64 (iconst $I32 (u64_from_imm64 imm)))) - (iconst $I64 (imm64 (u64_uextend_u32 imm)))) -(rule (simplify (sextend $I64 (iconst $I32 (u64_from_imm64 imm)))) - (iconst $I64 (imm64 (u64_sextend_u32 imm)))) - ;; x+0 == 0+x == x. (rule (simplify (iadd ty x diff --git a/cranelift/codegen/src/opts/cprop.isle b/cranelift/codegen/src/opts/cprop.isle index ee843087e2..7c58ee6ad6 100644 --- a/cranelift/codegen/src/opts/cprop.isle +++ b/cranelift/codegen/src/opts/cprop.isle @@ -70,6 +70,12 @@ (iconst _ k2))) (subsume (iconst ty (imm64_sshr ty k1 k2)))) +(rule (simplify (uextend wide (iconst narrow imm))) + (subsume (iconst wide (imm64 (u64_uextend_imm64 narrow imm))))) + +(rule (simplify (sextend wide (iconst narrow imm))) + (subsume (iconst wide (imm64_masked wide (i64_as_u64 (i64_sextend_imm64 narrow imm)))))) + (rule (simplify (icmp result_ty cc diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index 6f603ff63b..701f414a92 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -144,11 +144,11 @@ (decl pure u64_eq (u64 u64) bool) (extern constructor u64_eq u64_eq) -(decl pure u64_sextend_u32 (u64) u64) -(extern constructor u64_sextend_u32 u64_sextend_u32) +(decl pure i64_sextend_imm64 (Type Imm64) i64) +(extern constructor i64_sextend_imm64 i64_sextend_imm64) -(decl pure u64_uextend_u32 (u64) u64) -(extern constructor u64_uextend_u32 u64_uextend_u32) +(decl pure u64_uextend_imm64 (Type Imm64) u64) +(extern constructor u64_uextend_imm64 u64_uextend_imm64) (decl pure imm64_icmp (Type IntCC Imm64 Imm64) Imm64) (extern constructor imm64_icmp imm64_icmp)