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:
@@ -57,11 +57,7 @@ where
|
||||
|
||||
#[inline]
|
||||
fn operand_size_of_type(&mut self, ty: Type) -> OperandSize {
|
||||
if ty.bits() == 64 {
|
||||
OperandSize::Size64
|
||||
} else {
|
||||
OperandSize::Size32
|
||||
}
|
||||
OperandSize::from_ty(ty)
|
||||
}
|
||||
|
||||
fn put_in_reg_mem(&mut self, val: Value) -> RegMem {
|
||||
@@ -125,6 +121,16 @@ where
|
||||
Some(Imm8Reg::Imm8 { imm })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mask_imm8_const(&mut self, imm8: &Imm8Reg, mask: u64) -> Imm8Reg {
|
||||
match imm8 {
|
||||
&Imm8Reg::Reg { reg } => Imm8Reg::Reg { reg },
|
||||
&Imm8Reg::Imm8 { imm } => Imm8Reg::Imm8 {
|
||||
imm: imm & (mask as u8),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn simm32_from_value(&mut self, val: Value) -> Option<RegMemImm> {
|
||||
let inst = self.lower_ctx.dfg().value_def(val).inst()?;
|
||||
|
||||
Reference in New Issue
Block a user