X64: port the rest of icmp to ISLE (#4254)
Finish migrating icmp to ISLE for x64
This commit is contained in:
@@ -1271,6 +1271,26 @@
|
||||
(decl lo_gpr (Value) Gpr)
|
||||
(rule (lo_gpr regs) (gpr_new (lo_reg regs)))
|
||||
|
||||
;;;; Helpers for Working With Integer Comparison Codes ;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
|
||||
;; An extractor that fails if the two arguments are equal. The first argument is
|
||||
;; returned when it does not match the second.
|
||||
(decl pure intcc_neq (IntCC IntCC) IntCC)
|
||||
(extern constructor intcc_neq intcc_neq)
|
||||
|
||||
;; This is a direct import of `IntCC::without_equal`.
|
||||
;; Get the corresponding IntCC with the equal component removed.
|
||||
;; For conditions without a zero component, this is a no-op.
|
||||
(decl intcc_without_eq (IntCC) IntCC)
|
||||
(extern constructor intcc_without_eq intcc_without_eq)
|
||||
|
||||
;; This is a direct import of `IntCC::unsigned`.
|
||||
;; Get the corresponding IntCC with the signed component removed.
|
||||
;; For conditions without a signed component, this is a no-op.
|
||||
(decl intcc_unsigned (IntCC) IntCC)
|
||||
(extern constructor intcc_unsigned intcc_unsigned)
|
||||
|
||||
;;;; Helpers for Getting Particular Physical Registers ;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; These should only be used for legalization purposes, when we can't otherwise
|
||||
|
||||
@@ -1459,6 +1459,7 @@
|
||||
;; unset).
|
||||
(rule (lower (icmp (IntCC.Equal) a @ (value_type (ty_vec128 ty)) b))
|
||||
(x64_pcmpeq ty a b))
|
||||
|
||||
;; To lower a not-equals comparison, we perform an equality comparison
|
||||
;; (PCMPEQ*) and then invert the bits (PXOR with all 1s).
|
||||
(rule (lower (icmp (IntCC.NotEqual) a @ (value_type (ty_vec128 ty)) b))
|
||||
@@ -1553,6 +1554,30 @@
|
||||
(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` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; CLIF's `fcmp` instruction always operates on XMM registers--both scalar and
|
||||
|
||||
@@ -903,16 +903,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
| Opcode::FmaxPseudo => implemented_in_isle(ctx),
|
||||
|
||||
Opcode::Icmp => {
|
||||
let condcode = ctx.data(insn).cond_code().unwrap();
|
||||
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
|
||||
let ty = ctx.input_ty(insn, 0);
|
||||
if ty == types::I128 && condcode != IntCC::Equal && condcode != IntCC::NotEqual {
|
||||
let condcode = emit_cmp(ctx, insn, condcode);
|
||||
let cc = CC::from_intcc(condcode);
|
||||
ctx.emit(Inst::setcc(cc, dst));
|
||||
} else {
|
||||
implemented_in_isle(ctx);
|
||||
}
|
||||
implemented_in_isle(ctx);
|
||||
}
|
||||
|
||||
Opcode::Fcmp => {
|
||||
|
||||
@@ -511,6 +511,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intcc_neq(&mut self, x: &IntCC, y: &IntCC) -> Option<IntCC> {
|
||||
if x != y {
|
||||
Some(*x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intcc_without_eq(&mut self, x: &IntCC) -> IntCC {
|
||||
x.without_equal()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intcc_unsigned(&mut self, x: &IntCC) -> IntCC {
|
||||
x.unsigned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intcc_to_cc(&mut self, intcc: &IntCC) -> CC {
|
||||
CC::from_intcc(*intcc)
|
||||
|
||||
Reference in New Issue
Block a user