x64: Migrate trapif and trapff to ISLE (#4545)
https://github.com/bytecodealliance/wasmtime/pull/4545
This commit is contained in:
@@ -1452,6 +1452,24 @@
|
||||
(rule (lower (trap code))
|
||||
(side_effect (x64_ud2 code)))
|
||||
|
||||
;;;; Rules for `trapif` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The flags must not have been clobbered by any other instruction between the
|
||||
;; iadd_ifcout and this instruction, as verified by the CLIF validator; so we
|
||||
;; can simply use the flags here.
|
||||
(rule (lower (trapif cc flags @ (iadd_ifcout _ _) tc))
|
||||
(side_effect
|
||||
(trap_if_icmp (icmp_cond_result (flags_to_producesflags flags) cc) tc)))
|
||||
|
||||
;; Verification ensures that the input is always a single-def ifcmp.
|
||||
(rule (lower (trapif cc (ifcmp a b) tc))
|
||||
(side_effect (trap_if_icmp (emit_cmp cc a b) tc)))
|
||||
|
||||
;;;; Rules for `trapff` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (trapff cc (ffcmp a b) tc))
|
||||
(side_effect (trap_if_fcmp (emit_fcmp cc a b) tc)))
|
||||
|
||||
;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (resumable_trap code))
|
||||
@@ -1475,12 +1493,11 @@
|
||||
|
||||
;;;; Rules for `icmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; For GPR-held values we only need to emit `CMP + SETCC`. We rely here on
|
||||
;; Cranelift's verification that `a` and `b` are of the same type.
|
||||
;; Unfortunately for clarity, the registers are flipped here (TODO).
|
||||
(rule (lower (icmp cc a @ (value_type (fits_in_64 ty)) b))
|
||||
(let ((size OperandSize (raw_operand_size_of_type ty)))
|
||||
(with_flags (x64_cmp size b a) (x64_setcc cc))))
|
||||
(lower_icmp_bool (emit_cmp cc a b)))
|
||||
|
||||
(rule (lower (icmp cc a @ (value_type $I128) b))
|
||||
(lower_icmp_bool (emit_cmp cc a b)))
|
||||
|
||||
;; For XMM-held values, we lower to `PCMP*` instructions, sometimes more than
|
||||
;; one. To note: what is different here about the output values is that each
|
||||
@@ -1552,61 +1569,6 @@
|
||||
;; TODO: not used by WebAssembly translation
|
||||
;; (rule (lower (icmp (IntCC.UnsignedLessThanOrEqual) a @ (value_type $I64X2) b))
|
||||
|
||||
;; For I128 values (held in two GPRs), the instruction sequences depend on what
|
||||
;; kind of condition is tested.
|
||||
(rule (lower (icmp (IntCC.Equal) a @ (value_type $I128) b))
|
||||
(let ((a_lo Gpr (value_regs_get_gpr a 0))
|
||||
(a_hi Gpr (value_regs_get_gpr a 1))
|
||||
(b_lo Gpr (value_regs_get_gpr b 0))
|
||||
(b_hi Gpr (value_regs_get_gpr b 1))
|
||||
(cmp_lo Reg (with_flags_reg (x64_cmp (OperandSize.Size64) b_lo a_lo) (x64_setcc (CC.Z))))
|
||||
(cmp_hi Reg (with_flags_reg (x64_cmp (OperandSize.Size64) b_hi a_hi) (x64_setcc (CC.Z))))
|
||||
;; At this point, `cmp_lo` and `cmp_hi` contain either 0 or 1 in the
|
||||
;; lowest 8 bits--`SETcc` guarantees this. The upper bits may be
|
||||
;; unchanged so we must compare against 1 below; this instruction
|
||||
;; combines `cmp_lo` and `cmp_hi` for that final comparison.
|
||||
(cmp Reg (x64_and $I64 cmp_lo cmp_hi)))
|
||||
;; We must compare one more time against the immediate value 1 to
|
||||
;; check if both `cmp_lo` and `cmp_hi` are true. If `cmp AND 1 == 0`
|
||||
;; then the `ZF` will be set (see `TEST` definition); if either of
|
||||
;; the halves `AND`s to 0, they were not equal, therefore we `SETcc`
|
||||
;; with `NZ`.
|
||||
(with_flags (x64_test (OperandSize.Size64) (RegMemImm.Imm 1) cmp) (x64_setcc (CC.NZ)))))
|
||||
|
||||
(rule (lower (icmp (IntCC.NotEqual) a @ (value_type $I128) b))
|
||||
(let ((a_lo Gpr (value_regs_get_gpr a 0))
|
||||
(a_hi Gpr (value_regs_get_gpr a 1))
|
||||
(b_lo Gpr (value_regs_get_gpr b 0))
|
||||
(b_hi Gpr (value_regs_get_gpr b 1))
|
||||
(cmp_lo Reg (with_flags_reg (x64_cmp (OperandSize.Size64) b_lo a_lo) (x64_setcc (CC.NZ))))
|
||||
(cmp_hi Reg (with_flags_reg (x64_cmp (OperandSize.Size64) b_hi a_hi) (x64_setcc (CC.NZ))))
|
||||
;; See comments for `IntCC.Equal`.
|
||||
(cmp Reg (x64_or $I64 cmp_lo cmp_hi)))
|
||||
(with_flags (x64_test (OperandSize.Size64) (RegMemImm.Imm 1) cmp) (x64_setcc (CC.NZ)))))
|
||||
|
||||
;; Result = (a_hi <> b_hi) ||
|
||||
;; (a_hi == b_hi && a_lo <> b_lo)
|
||||
(rule (lower (icmp cc a @ (value_type $I128) b))
|
||||
(if (intcc_neq cc (IntCC.Equal)))
|
||||
(if (intcc_neq cc (IntCC.NotEqual)))
|
||||
(let ((a_lo Gpr (value_regs_get_gpr a 0))
|
||||
(a_hi Gpr (value_regs_get_gpr a 1))
|
||||
(b_lo Gpr (value_regs_get_gpr b 0))
|
||||
(b_hi Gpr (value_regs_get_gpr b 1))
|
||||
(cmp_hi ValueRegs (with_flags (x64_cmp (OperandSize.Size64) b_hi a_hi)
|
||||
(consumes_flags_concat
|
||||
(x64_setcc (intcc_without_eq cc))
|
||||
(x64_setcc (CC.Z)))))
|
||||
(cc_hi Reg (value_regs_get cmp_hi 0))
|
||||
(eq_hi Reg (value_regs_get cmp_hi 1))
|
||||
|
||||
(cmp_lo Reg (with_flags_reg (x64_cmp (OperandSize.Size64) b_lo a_lo)
|
||||
(x64_setcc (intcc_unsigned cc))))
|
||||
|
||||
(res_lo Reg (x64_and $I64 eq_hi cmp_lo))
|
||||
(res Reg (x64_or $I64 cc_hi res_lo)))
|
||||
(x64_and $I64 res (RegMemImm.Imm 1))))
|
||||
|
||||
|
||||
;;;; Rules for `fcmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -1627,58 +1589,8 @@
|
||||
;; - less than assigns Z = 0, P = 0, C = 1
|
||||
;; - equal assigns Z = 1, P = 0, C = 0
|
||||
|
||||
(rule (lower (fcmp (FloatCC.Equal) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(let ((maybe ValueRegs (with_flags (x64_ucomis b a)
|
||||
(consumes_flags_concat
|
||||
(x64_setcc (CC.NP))
|
||||
(x64_setcc (CC.Z)))))
|
||||
(maybe_np Gpr (value_regs_get_gpr maybe 0))
|
||||
(maybe_z Gpr (value_regs_get_gpr maybe 1)))
|
||||
(x64_and $I32 maybe_np maybe_z)))
|
||||
|
||||
(rule (lower (fcmp (FloatCC.NotEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(let ((maybe ValueRegs (with_flags (x64_ucomis b a)
|
||||
(consumes_flags_concat
|
||||
(x64_setcc (CC.P))
|
||||
(x64_setcc (CC.NZ)))))
|
||||
(maybe_p Gpr (value_regs_get_gpr maybe 0))
|
||||
(maybe_nz Gpr (value_regs_get_gpr maybe 1)))
|
||||
(x64_or $I32 maybe_p maybe_nz)))
|
||||
|
||||
;; Some scalar lowerings correspond to one condition code.
|
||||
|
||||
(rule (lower (fcmp (FloatCC.Ordered) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.NP))))
|
||||
(rule (lower (fcmp (FloatCC.Unordered) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.P))))
|
||||
(rule (lower (fcmp (FloatCC.OrderedNotEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.NZ))))
|
||||
(rule (lower (fcmp (FloatCC.UnorderedOrEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.Z))))
|
||||
(rule (lower (fcmp (FloatCC.GreaterThan) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.NBE))))
|
||||
(rule (lower (fcmp (FloatCC.GreaterThanOrEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.NB))))
|
||||
(rule (lower (fcmp (FloatCC.UnorderedOrLessThan) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.B))))
|
||||
(rule (lower (fcmp (FloatCC.UnorderedOrLessThanOrEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
(with_flags (x64_ucomis b a) (x64_setcc (CC.BE))))
|
||||
|
||||
;; Other scalar lowerings are made possible by flipping the operands and
|
||||
;; reversing the condition code.
|
||||
|
||||
(rule (lower (fcmp (FloatCC.LessThan) a @ (value_type (ty_scalar_float ty)) b))
|
||||
;; Same flags as `GreaterThan`.
|
||||
(with_flags (x64_ucomis a b) (x64_setcc (CC.NBE))))
|
||||
(rule (lower (fcmp (FloatCC.LessThanOrEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
;; Same flags as `GreaterThanOrEqual`.
|
||||
(with_flags (x64_ucomis a b) (x64_setcc (CC.NB))))
|
||||
(rule (lower (fcmp (FloatCC.UnorderedOrGreaterThan) a @ (value_type (ty_scalar_float ty)) b))
|
||||
;; Same flags as `UnorderedOrLessThan`.
|
||||
(with_flags (x64_ucomis a b) (x64_setcc (CC.B))))
|
||||
(rule (lower (fcmp (FloatCC.UnorderedOrGreaterThanOrEqual) a @ (value_type (ty_scalar_float ty)) b))
|
||||
;; Same flags as `UnorderedOrLessThanOrEqual`.
|
||||
(with_flags (x64_ucomis a b) (x64_setcc (CC.BE))))
|
||||
(rule (lower (fcmp cc a @ (value_type (ty_scalar_float ty)) b))
|
||||
(lower_fcmp_bool (emit_fcmp cc a b)))
|
||||
|
||||
;; For vector lowerings, we use `CMPP*` instructions with a 3-bit operand that
|
||||
;; determines the comparison to make. Note that comparisons that succeed will
|
||||
|
||||
Reference in New Issue
Block a user