riscv64: Fix masking on iabs (#5505)

* cranelift: Add `iabs.i128` runtest

* riscv64: Fix incorrect extension in iabs

When lowering iabs, we were accidentally comparing the unextended value
this caused the instruction to misbehave with certain top bits.

This commit also adds a zbb lowering that does not use jumps.
This commit is contained in:
Afonso Bordado
2023-01-04 01:37:25 +00:00
committed by GitHub
parent 276bc6ad2e
commit 52ba72f341
8 changed files with 172 additions and 15 deletions

View File

@@ -2011,9 +2011,13 @@
(step WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.Rev8 rs step tmp rd))))
(writable_reg_to_reg rd)))
(decl pure has_zbkb () bool)
(extern constructor has_zbkb has_zbkb)
(decl pure has_zbb () bool)
(extern constructor has_zbb has_zbb)
(decl gen_brev8 (Reg Type) Reg)
(rule 1
(gen_brev8 rs _)
@@ -2038,14 +2042,41 @@
((tmp Reg (gen_bit_not y)))
(alu_rrr (AluOPRRR.Xor) x tmp)))
(decl lower_iabs (Reg Type) Reg)
(rule
(lower_iabs r ty)
(let
((tmp Reg (ext_int_if_need $true r ty))
(a Reg (gen_bit_not r))
(a2 Reg (alu_rr_imm12 (AluOPRRI.Addi) a (imm12_const 1))))
(gen_select_reg (IntCC.SignedLessThan) r (zero_reg) a2 r)))
;; Negates x
;; Equivalent to 0 - x
(decl neg (Type ValueRegs) ValueRegs)
(rule 1 (neg (fits_in_64 (ty_int ty)) val)
(value_reg
(alu_rrr (AluOPRRR.Sub) (zero_reg) (value_regs_get val 0))))
(rule 2 (neg $I128 val)
(i128_sub (value_regs_zero) val))
;; Selects the greatest of two registers as signed values.
(decl max (Type Reg Reg) Reg)
(rule (max (fits_in_64 (ty_int ty)) x y)
(if-let $true (has_zbb))
(alu_rrr (AluOPRRR.Max) x y))
(rule (max (fits_in_64 (ty_int ty)) x y)
(if-let $false (has_zbb))
(gen_select_reg (IntCC.SignedGreaterThan) x y x y))
(decl lower_iabs (Type Reg) Reg)
; I64 and lower
; Generate the following code:
; sext.{b,h,w} a0, a0
; neg a1, a0
; max a0, a0, a1
(rule (lower_iabs (fits_in_64 ty) val)
(let ((extended Reg (ext_int_if_need $true val ty))
(negated Reg (neg $I64 extended)))
(max $I64 extended negated)))
(decl gen_trapff (FloatCC Reg Reg Type TrapCode) InstOutput)
(rule

View File

@@ -76,11 +76,8 @@
;;;; Rules for `ineg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; `i64` and smaller.
(rule 1 (lower (has_type (fits_in_64 ty) (ineg x)))
(alu_rrr (AluOPRRR.Sub) (zero_reg) x))
(rule 2 (lower (has_type $I128 (ineg x)))
(i128_sub (value_regs_zero) x))
(rule (lower (has_type ty (ineg val)))
(neg ty val))
;;;; Rules for `imul` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -871,7 +868,7 @@
;;; Rules for `iabs` ;;;;;;;;;;;;;
(rule
(lower (has_type (fits_in_64 ty) (iabs x)))
(lower_iabs x ty))
(lower_iabs ty x))
;;;; Rules for calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@@ -306,6 +306,9 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Riscv64Backend> {
fn has_zbkb(&mut self) -> bool {
self.backend.isa_flags.has_zbkb()
}
fn has_zbb(&mut self) -> bool {
self.backend.isa_flags.has_zbb()
}
fn inst_output_get(&mut self, x: InstOutput, index: u8) -> ValueRegs {
x[index as usize]