cranelift: Fix shifts and implement rotates in interpreter (#4519)

* cranelift: Fix shifts and implement rotates in interpreter

* x64: Implement `rotl`/`rotr` for some small type combinations
This commit is contained in:
Afonso Bordado
2022-08-11 20:15:52 +01:00
committed by GitHub
parent 67870d1518
commit e4adc46e6d
9 changed files with 868 additions and 70 deletions

View File

@@ -818,31 +818,17 @@
;;;; Rules for `rotl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; `i16` and `i8`: we need to extend the shift amount, or mask the
;; constant.
;; `i64` and smaller: we can rely on x86's rotate-amount masking since
;; we operate on the whole register. For const's we mask the constant.
(rule (lower (has_type (ty_8_or_16 ty) (rotl src amt)))
(let ((amt_ Gpr (extend_to_gpr amt $I32 (ExtendKind.Zero))))
(x64_rotl ty src (gpr_to_imm8_gpr amt_))))
(rule (lower (has_type (fits_in_64 ty) (rotl src amt)))
(x64_rotl ty src (put_masked_in_imm8_gpr amt ty)))
(rule (lower (has_type (ty_8_or_16 ty)
(rule (lower (has_type (fits_in_64 ty)
(rotl src (u64_from_iconst amt))))
(x64_rotl ty src
(const_to_type_masked_imm8 amt ty)))
;; `i64` and `i32`: we can rely on x86's rotate-amount masking since
;; we operate on the whole register.
(rule (lower (has_type (ty_32_or_64 ty) (rotl src amt)))
;; NB: Only the low bits of `amt` matter since we logically mask the
;; shift amount to the value's bit width.
(let ((amt_ Gpr (lo_gpr amt)))
(x64_rotl ty src amt_)))
(rule (lower (has_type (ty_32_or_64 ty)
(rotl src (u64_from_iconst amt))))
(x64_rotl ty src
(const_to_type_masked_imm8 amt ty)))
;; `i128`.
@@ -858,31 +844,17 @@
;;;; Rules for `rotr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; `i16` and `i8`: we need to extend the shift amount, or mask the
;; constant.
;; `i64` and smaller: we can rely on x86's rotate-amount masking since
;; we operate on the whole register. For const's we mask the constant.
(rule (lower (has_type (ty_8_or_16 ty) (rotr src amt)))
(let ((amt_ Gpr (extend_to_gpr amt $I32 (ExtendKind.Zero))))
(x64_rotr ty src amt_)))
(rule (lower (has_type (fits_in_64 ty) (rotr src amt)))
(x64_rotr ty src (put_masked_in_imm8_gpr amt ty)))
(rule (lower (has_type (ty_8_or_16 ty)
(rule (lower (has_type (fits_in_64 ty)
(rotr src (u64_from_iconst amt))))
(x64_rotr ty src
(const_to_type_masked_imm8 amt ty)))
;; `i64` and `i32`: we can rely on x86's rotate-amount masking since
;; we operate on the whole register.
(rule (lower (has_type (ty_32_or_64 ty) (rotr src amt)))
;; NB: Only the low bits of `amt` matter since we logically mask the
;; shift amount to the value's bit width.
(let ((amt_ Gpr (lo_gpr amt)))
(x64_rotr ty src amt_)))
(rule (lower (has_type (ty_32_or_64 ty)
(rotr src (u64_from_iconst amt))))
(x64_rotr ty src
(const_to_type_masked_imm8 amt ty)))
;; `i128`.