Fix some 16- and 8-bit behavior in x64 backend related to rotates.

Uncovered by @bjorn3 (thanks!): 8- and 16-bit rotates were not working
properly in recent versions of Cranelift with part of the lowering
migrated to ISLE.

This PR fixes a few issues:

- 8- and 16-bit rotate-left needs to mask a constant amount, if any,
  because we use a 32-bit rotate instruction and so don't get the
  appropriate shift-amount masking for free from x86 semantics.

- `operand_size_from_type` was incorrect: it only handled 32- and 64-bit
  types and silently returned `OperandSize::Size32` for everything else.
  Now uses the `OperandSize::from_ty(ty)` helper as the pre-ISLE code
  did.

Our test coverage for narrow value types is not great; this PR adds some
runtests for rotl/rotr but more would always be better!
This commit is contained in:
Chris Fallin
2021-12-16 11:34:24 -08:00
parent d29b7c8a59
commit 1323ae417e
10 changed files with 352 additions and 229 deletions

View File

@@ -95,6 +95,11 @@ macro_rules! isle_prelude_methods {
ty.bits().try_into().unwrap()
}
#[inline]
fn ty_bits_mask(&mut self, ty: Type) -> u64 {
(1 << (self.ty_bits(ty) as u64)) - 1
}
#[inline]
fn ty_bits_u16(&mut self, ty: Type) -> u16 {
ty.bits()
@@ -118,6 +123,24 @@ macro_rules! isle_prelude_methods {
}
}
#[inline]
fn ty_32_or_64(&mut self, ty: Type) -> Option<Type> {
if ty.bits() == 32 || ty.bits() == 64 {
Some(ty)
} else {
None
}
}
#[inline]
fn ty_8_or_16(&mut self, ty: Type) -> Option<Type> {
if ty.bits() == 8 || ty.bits() == 16 {
Some(ty)
} else {
None
}
}
fn vec128(&mut self, ty: Type) -> Option<Type> {
if ty.is_vector() && ty.bits() == 128 {
Some(ty)