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

@@ -156,6 +156,14 @@
(decl fits_in_64 (Type) Type)
(extern extractor fits_in_64 fits_in_64)
;; An extractor that maches 32- and 64-bit types only.
(decl ty_32_or_64 (Type) Type)
(extern extractor ty_32_or_64 ty_32_or_64)
;; An extractor that maches 8- and 16-bit types only.
(decl ty_8_or_16 (Type) Type)
(extern extractor ty_8_or_16 ty_8_or_16)
;; An extractor that only matches 128-bit vector types.
(decl vec128 (Type) Type)
(extern extractor vec128 vec128)
@@ -230,6 +238,11 @@
(and (result_type ty)
inst))
;; Return a bitmask that will mask off a count to be within `ty`'s
;; bit-width. Used for shifts/rotates.
(decl ty_bits_mask (Type) u64)
(extern constructor ty_bits_mask ty_bits_mask)
;; Match a multi-lane type, extracting (# bits per lane, # lanes) from the given
;; type. Will only match when there is more than one lane.
(decl multi_lane (u8 u16) Type)