Port icmp to ISLE (AArch64) (#4898)

* Port `icmp` to ISLE (AArch64)

Ported the existing implementation of `icmp` (and, by extension, the
`lower_icmp` function) to ISLE for AArch64.

Copyright (c) 2022 Arm Limited

* Allow 'producer chains', eliminating `Nop0`s

Copyright (c) 2022 Arm Limited
This commit is contained in:
Damian Heaton
2022-09-13 16:56:50 +01:00
committed by GitHub
parent c3f8415ac7
commit e9b08b856d
11 changed files with 310 additions and 54 deletions

View File

@@ -1960,6 +1960,12 @@
(MInst.AluRRImm12 (ALUOp.AddS) size (writable_zero_reg) (MInst.AluRRImm12 (ALUOp.AddS) size (writable_zero_reg)
src1 src2))) src1 src2)))
(decl cmp (OperandSize Reg Reg) ProducesFlags)
(rule (cmp size src1 src2)
(ProducesFlags.ProducesFlagsSideEffect
(MInst.AluRRR (ALUOp.SubS) size (writable_zero_reg)
src1 src2)))
(decl cmp_imm (OperandSize Reg Imm12) ProducesFlags) (decl cmp_imm (OperandSize Reg Imm12) ProducesFlags)
(rule (cmp_imm size src1 src2) (rule (cmp_imm size src1 src2)
(ProducesFlags.ProducesFlagsSideEffect (ProducesFlags.ProducesFlagsSideEffect
@@ -1970,6 +1976,12 @@
(rule (cmp64_imm src1 src2) (rule (cmp64_imm src1 src2)
(cmp_imm (OperandSize.Size64) src1 src2)) (cmp_imm (OperandSize.Size64) src1 src2))
(decl cmp_extend (OperandSize Reg Reg ExtendOp) ProducesFlags)
(rule (cmp_extend size src1 src2 extend)
(ProducesFlags.ProducesFlagsSideEffect
(MInst.AluRRRExtend (ALUOp.SubS) size (writable_zero_reg)
src1 src2 extend)))
;; Helper for emitting `sbc` instructions. ;; Helper for emitting `sbc` instructions.
(decl sbc_paired (Type Reg Reg) ConsumesFlags) (decl sbc_paired (Type Reg Reg) ConsumesFlags)
(rule (sbc_paired ty src1 src2) (rule (sbc_paired ty src1 src2)
@@ -2199,6 +2211,13 @@
(MInst.CSNeg dst cond if_true if_false) (MInst.CSNeg dst cond if_true if_false)
dst))) dst)))
;; Helper for generating `MInst.CCmp` instructions.
;; Creates a new `ProducesFlags` from the supplied `ProducesFlags` followed
;; immediately by the `MInst.CCmp` instruction.
(decl ccmp (OperandSize Reg Reg NZCV Cond ProducesFlags) ProducesFlags)
(rule (ccmp size rn rm nzcv cond inst_input)
(produces_flags_append inst_input (MInst.CCmp size rn rm nzcv cond)))
;; Helper for generating `MInst.CCmpImm` instructions. ;; Helper for generating `MInst.CCmpImm` instructions.
(decl ccmp_imm (OperandSize u8 Reg UImm5 NZCV Cond) ConsumesFlags) (decl ccmp_imm (OperandSize u8 Reg UImm5 NZCV Cond) ConsumesFlags)
(rule (ccmp_imm size 1 rn imm nzcv cond) (rule (ccmp_imm size 1 rn imm nzcv cond)
@@ -2845,6 +2864,11 @@
;; TODO: Port lower_fp_condcode() to ISLE. ;; TODO: Port lower_fp_condcode() to ISLE.
(extern constructor fp_cond_code fp_cond_code) (extern constructor fp_cond_code fp_cond_code)
;; Lower an integer cond code.
(decl cond_code (IntCC) Cond)
;; TODO: Port lower_condcode() to ISLE.
(extern constructor cond_code cond_code)
;; Generate comparison to zero operator from input condition code ;; Generate comparison to zero operator from input condition code
(decl float_cc_cmp_zero_to_vec_misc_op (FloatCC) VecMisc2) (decl float_cc_cmp_zero_to_vec_misc_op (FloatCC) VecMisc2)
(extern constructor float_cc_cmp_zero_to_vec_misc_op float_cc_cmp_zero_to_vec_misc_op) (extern constructor float_cc_cmp_zero_to_vec_misc_op float_cc_cmp_zero_to_vec_misc_op)
@@ -3280,3 +3304,169 @@
(let ((dst WritableReg (temp_writable_reg $I64)) (let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.ElfTlsGetAddr name dst)))) (_ Unit (emit (MInst.ElfTlsGetAddr name dst))))
dst)) dst))
;; Helpers for lowering `icmp` sequences.
;; `lower_icmp` contains shared functionality for lowering `icmp`
;; sequences, which `lower_icmp_into_{reg,flags}` extend from.
(decl lower_icmp (IntCC Value Value Type) ProducesFlags)
(decl lower_icmp_into_reg (IntCC Value Value Type Type) ValueRegs)
(decl lower_icmp_into_flags (IntCC Value Value Type) ProducesFlags)
;; For most cases, `lower_icmp_into_flags` is the same as `lower_icmp`,
;; except for some I128 cases (see below).
(rule -1 (lower_icmp_into_flags cond x y ty) (lower_icmp cond x y ty))
;; Vectors.
;; `icmp` into flags for vectors is invalid.
(rule (lower_icmp_into_reg cond x y in_ty @ (multi_lane _ _) _out_ty)
(let ((cond Cond (cond_code cond))
(rn Reg (put_in_reg x))
(rm Reg (put_in_reg y)))
(vec_cmp rn rm in_ty cond)))
;; Determines the appropriate extend op given the value type and whether it is signed.
(decl lower_icmp_extend (Type bool) ExtendOp)
(rule (lower_icmp_extend $I8 $true) (ExtendOp.SXTB))
(rule (lower_icmp_extend $I16 $true) (ExtendOp.SXTH))
(rule (lower_icmp_extend $I8 $false) (ExtendOp.UXTB))
(rule (lower_icmp_extend $I16 $false) (ExtendOp.UXTH))
;; Integers <= 64-bits.
(rule (lower_icmp_into_reg cond rn rm in_ty out_ty)
(if (ty_int_bool_ref_scalar_64 in_ty))
(let ((cc Cond (cond_code cond)))
(with_flags
(lower_icmp cond rn rm in_ty)
(materialize_bool_result (ty_bits out_ty) cc))))
(rule 1 (lower_icmp cond rn rm (fits_in_16 ty))
(if (signed_cond_code cond))
(let ((rn Reg (put_in_reg_sext32 rn)))
(cmp_extend (operand_size ty) rn rm (lower_icmp_extend ty $true))))
(rule (lower_icmp cond rn (imm12_from_value rm) (fits_in_16 ty))
(let ((rn Reg (put_in_reg_zext32 rn)))
(cmp_imm (operand_size ty) rn rm)))
(rule -1 (lower_icmp cond rn rm (fits_in_16 ty))
(let ((rn Reg (put_in_reg_zext32 rn)))
(cmp_extend (operand_size ty) rn rm (lower_icmp_extend ty $false))))
(rule -2 (lower_icmp cond rn (imm12_from_value rm) ty)
(if (ty_int_bool_ref_scalar_64 ty))
(cmp_imm (operand_size ty) rn rm))
(rule -3 (lower_icmp cond rn rm ty)
(if (ty_int_bool_ref_scalar_64 ty))
(cmp (operand_size ty) rn rm))
;; 128-bit integers.
(rule (lower_icmp_into_reg cond @ (IntCC.Equal) rn rm $I128 out_ty)
(let ((cc Cond (cond_code cond)))
(with_flags
(lower_icmp cond rn rm $I128)
(materialize_bool_result (ty_bits out_ty) cc))))
(rule (lower_icmp_into_reg cond @ (IntCC.NotEqual) rn rm $I128 out_ty)
(let ((cc Cond (cond_code cond)))
(with_flags
(lower_icmp cond rn rm $I128)
(materialize_bool_result (ty_bits out_ty) cc))))
;; cmp lhs_lo, rhs_lo
;; ccmp lhs_hi, rhs_hi, #0, eq
(decl lower_icmp_i128_eq_ne (Value Value) ProducesFlags)
(rule (lower_icmp_i128_eq_ne lhs rhs)
(let ((lhs_lo Reg (value_regs_get lhs 0))
(lhs_hi Reg (value_regs_get lhs 1))
(rhs_lo Reg (value_regs_get rhs 0))
(rhs_hi Reg (value_regs_get rhs 1))
(cmp_inst ProducesFlags (cmp (OperandSize.Size64) lhs_lo rhs_lo)))
(ccmp (OperandSize.Size64) lhs_hi rhs_hi
(nzcv $false $false $false $false) (Cond.Eq) cmp_inst)))
(rule (lower_icmp (IntCC.Equal) lhs rhs $I128)
(lower_icmp_i128_eq_ne lhs rhs))
(rule (lower_icmp (IntCC.NotEqual) lhs rhs $I128)
(lower_icmp_i128_eq_ne lhs rhs))
;; cmp lhs_lo, rhs_lo
;; cset tmp1, unsigned_cond
;; cmp lhs_hi, rhs_hi
;; cset tmp2, cond
;; csel dst, tmp1, tmp2, eq
(rule -1 (lower_icmp_into_reg cond lhs rhs $I128 out_ty)
(let ((unsigned_cond Cond (cond_code (intcc_unsigned cond)))
(cond Cond (cond_code cond))
(lhs_lo Reg (value_regs_get lhs 0))
(lhs_hi Reg (value_regs_get lhs 1))
(rhs_lo Reg (value_regs_get rhs 0))
(rhs_hi Reg (value_regs_get rhs 1))
(tmp1 ValueRegs
(with_flags (cmp (OperandSize.Size64) lhs_lo rhs_lo)
(materialize_bool_result
(ty_bits out_ty) unsigned_cond)))
(tmp1 Reg (value_regs_get tmp1 0))
(dst ValueRegs
(with_flags (cmp (OperandSize.Size64) lhs_hi rhs_hi)
(lower_icmp_i128_consumer cond (ty_bits out_ty)
tmp1 lhs_hi rhs_hi))))
dst))
(decl lower_icmp_i128_consumer (Cond u8 Reg Reg Reg) ConsumesFlags)
(rule (lower_icmp_i128_consumer cond 1 tmp1 lhs_hi rhs_hi)
(let ((tmp2 WritableReg (temp_writable_reg $I64))
(dst WritableReg (temp_writable_reg $I64)))
(ConsumesFlags.ConsumesFlagsTwiceReturnsValueRegs
(MInst.CSet tmp2 cond)
(MInst.CSel dst (Cond.Eq) tmp1 tmp2)
(value_reg dst))))
(rule (lower_icmp_i128_consumer cond 128 tmp1 lhs_hi rhs_hi)
(let ((tmp2 WritableReg (temp_writable_reg $I64))
(dst WritableReg (temp_writable_reg $I64)))
(ConsumesFlags.ConsumesFlagsTwiceReturnsValueRegs
(MInst.CSetm tmp2 cond)
(MInst.CSel dst (Cond.Eq) tmp1 tmp2)
(value_regs dst dst))))
(rule -1 (lower_icmp_i128_consumer cond _out_ty_bits tmp1 lhs_hi rhs_hi)
(let ((tmp2 WritableReg (temp_writable_reg $I64))
(dst WritableReg (temp_writable_reg $I64)))
(ConsumesFlags.ConsumesFlagsTwiceReturnsValueRegs
(MInst.CSetm tmp2 cond)
(MInst.CSel dst (Cond.Eq) tmp1 tmp2)
(value_reg dst))))
;; Exceptional `lower_icmp_into_flags` rules.
;; We need to guarantee that the flags for `cond` are correct, so we
;; compare `dst` with 1.
(rule (lower_icmp_into_flags cond @ (IntCC.SignedGreaterThanOrEqual) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0))
(tmp Reg (imm $I64 (ImmExtend.Sign) 1))) ;; mov tmp, #1
(cmp (OperandSize.Size64) dst tmp)))
(rule (lower_icmp_into_flags cond @ (IntCC.UnsignedGreaterThanOrEqual) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0))
(tmp Reg (imm $I64 (ImmExtend.Zero) 1)))
(cmp (OperandSize.Size64) dst tmp)))
(rule (lower_icmp_into_flags cond @ (IntCC.SignedLessThanOrEqual) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0))
(tmp Reg (imm $I64 (ImmExtend.Sign) 1)))
(cmp (OperandSize.Size64) tmp dst)))
(rule (lower_icmp_into_flags cond @ (IntCC.UnsignedLessThanOrEqual) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0))
(tmp Reg (imm $I64 (ImmExtend.Zero) 1)))
(cmp (OperandSize.Size64) tmp dst)))
;; For strict comparisons, we compare with 0.
(rule (lower_icmp_into_flags cond @ (IntCC.SignedGreaterThan) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0)))
(cmp (OperandSize.Size64) dst (zero_reg))))
(rule (lower_icmp_into_flags cond @ (IntCC.UnsignedGreaterThan) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0)))
(cmp (OperandSize.Size64) dst (zero_reg))))
(rule (lower_icmp_into_flags cond @ (IntCC.SignedLessThan) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0)))
(cmp (OperandSize.Size64) (zero_reg) dst)))
(rule (lower_icmp_into_flags cond @ (IntCC.UnsignedLessThan) lhs rhs $I128)
(let ((dst ValueRegs (lower_icmp_into_reg cond lhs rhs $I128 $B1))
(dst Reg (value_regs_get dst 0)))
(cmp (OperandSize.Size64) (zero_reg) dst)))

View File

@@ -1730,6 +1730,9 @@
(vec_size VectorSize (vector_size ty))) (vec_size VectorSize (vector_size ty)))
(value_reg (int_cmp_zero_swap cond rn vec_size)))) (value_reg (int_cmp_zero_swap cond rn vec_size))))
(rule -1 (lower (has_type out_ty (icmp cond x @ (value_type in_ty) y)))
(lower_icmp_into_reg cond x y in_ty out_ty))
;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (trap trap_code)) (rule (lower (trap trap_code))

View File

@@ -6,10 +6,10 @@ use generated_code::Context;
// Types that the generated ISLE code uses via `use super::*`. // Types that the generated ISLE code uses via `use super::*`.
use super::{ use super::{
fp_reg, lower_constant_f128, lower_constant_f32, lower_constant_f64, lower_fp_condcode, fp_reg, lower_condcode, lower_constant_f128, lower_constant_f32, lower_constant_f64,
stack_reg, writable_link_reg, writable_zero_reg, zero_reg, AMode, ASIMDFPModImm, lower_fp_condcode, stack_reg, writable_link_reg, writable_zero_reg, zero_reg, AMode,
ASIMDMovModImm, BranchTarget, CallIndInfo, CallInfo, Cond, CondBrKind, ExtendOp, FPUOpRI, ASIMDFPModImm, ASIMDMovModImm, BranchTarget, CallIndInfo, CallInfo, Cond, CondBrKind, ExtendOp,
FPUOpRIMod, FloatCC, Imm12, ImmLogic, ImmShift, Inst as MInst, IntCC, JTSequenceInfo, FPUOpRI, FPUOpRIMod, FloatCC, Imm12, ImmLogic, ImmShift, Inst as MInst, IntCC, JTSequenceInfo,
MachLabel, MemLabel, MoveWideConst, MoveWideOp, NarrowValueMode, Opcode, OperandSize, MachLabel, MemLabel, MoveWideConst, MoveWideOp, NarrowValueMode, Opcode, OperandSize,
PairAMode, Reg, SImm9, ScalarSize, ShiftOpAndAmt, UImm12Scaled, UImm5, VecMisc2, VectorSize, PairAMode, Reg, SImm9, ScalarSize, ShiftOpAndAmt, UImm12Scaled, UImm5, VecMisc2, VectorSize,
NZCV, NZCV,
@@ -517,6 +517,10 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
lower_fp_condcode(*cc) lower_fp_condcode(*cc)
} }
fn cond_code(&mut self, cc: &condcodes::IntCC) -> Cond {
lower_condcode(*cc)
}
fn preg_sp(&mut self) -> PReg { fn preg_sp(&mut self) -> PReg {
super::regs::stack_reg().to_real_reg().unwrap().into() super::regs::stack_reg().to_real_reg().unwrap().into()
} }

View File

@@ -293,11 +293,7 @@ pub(crate) fn lower_insn_to_regs(
panic!("Should never reach ifcmp as isel root!"); panic!("Should never reach ifcmp as isel root!");
} }
Opcode::Icmp => { Opcode::Icmp => implemented_in_isle(ctx),
let condcode = ctx.data(insn).cond_code().unwrap();
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
lower_icmp(ctx, insn, condcode, IcmpOutput::Register(rd))?;
}
Opcode::Fcmp => implemented_in_isle(ctx), Opcode::Fcmp => implemented_in_isle(ctx),

View File

@@ -1362,12 +1362,6 @@
(decl intcc_without_eq (IntCC) IntCC) (decl intcc_without_eq (IntCC) IntCC)
(extern constructor intcc_without_eq intcc_without_eq) (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 ;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Helpers for Getting Particular Physical Registers ;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; These should only be used for legalization purposes, when we can't otherwise ;; These should only be used for legalization purposes, when we can't otherwise

View File

@@ -596,11 +596,6 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
x.without_equal() x.without_equal()
} }
#[inline]
fn intcc_unsigned(&mut self, x: &IntCC) -> IntCC {
x.unsigned()
}
#[inline] #[inline]
fn intcc_to_cc(&mut self, intcc: &IntCC) -> CC { fn intcc_to_cc(&mut self, intcc: &IntCC) -> CC {
CC::from_intcc(*intcc) CC::from_intcc(*intcc)

View File

@@ -8,8 +8,8 @@ use target_lexicon::Triple;
pub use super::MachLabel; pub use super::MachLabel;
pub use crate::ir::{ pub use crate::ir::{
dynamic_to_fixed, ArgumentExtension, Constant, DynamicStackSlot, ExternalName, FuncRef, condcodes, dynamic_to_fixed, ArgumentExtension, Constant, DynamicStackSlot, ExternalName,
GlobalValue, Immediate, SigRef, StackSlot, FuncRef, GlobalValue, Immediate, SigRef, StackSlot,
}; };
pub use crate::isa::unwind::UnwindInst; pub use crate::isa::unwind::UnwindInst;
pub use crate::machinst::{ pub use crate::machinst::{
@@ -1087,6 +1087,27 @@ macro_rules! isle_prelude_methods {
fn gen_move(&mut self, ty: Type, dst: WritableReg, src: Reg) -> MInst { fn gen_move(&mut self, ty: Type, dst: WritableReg, src: Reg) -> MInst {
MInst::gen_move(dst, src, ty) MInst::gen_move(dst, src, ty)
} }
#[inline]
fn intcc_unsigned(&mut self, x: &IntCC) -> IntCC {
x.unsigned()
}
#[inline]
fn signed_cond_code(&mut self, cc: &condcodes::IntCC) -> Option<condcodes::IntCC> {
match cc {
IntCC::Equal
| IntCC::UnsignedGreaterThanOrEqual
| IntCC::UnsignedGreaterThan
| IntCC::UnsignedLessThanOrEqual
| IntCC::UnsignedLessThan
| IntCC::NotEqual => None,
IntCC::SignedGreaterThanOrEqual
| IntCC::SignedGreaterThan
| IntCC::SignedLessThanOrEqual
| IntCC::SignedLessThan => Some(*cc),
}
}
}; };
} }

View File

@@ -571,6 +571,16 @@
(decl pure is_sinkable_inst (Value) Inst) (decl pure is_sinkable_inst (Value) Inst)
(extern constructor is_sinkable_inst is_sinkable_inst) (extern constructor is_sinkable_inst is_sinkable_inst)
;; 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)
;; Pure constructor that only matches signed integer cond codes.
(decl pure signed_cond_code (IntCC) IntCC)
(extern constructor signed_cond_code signed_cond_code)
;; Instruction creation helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Instruction creation helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Emit an instruction. ;; Emit an instruction.
@@ -657,11 +667,17 @@
;; them. ;; them.
(AlreadyExistingFlags) (AlreadyExistingFlags)
(ProducesFlagsSideEffect (inst MInst)) (ProducesFlagsSideEffect (inst MInst))
(ProducesFlagsTwiceSideEffect (inst1 MInst) (inst2 MInst))
;; Not directly combinable with a ConsumesFlags; ;; Not directly combinable with a ConsumesFlags;
;; used in s390x and unwrapped directly by `trapif`. ;; used in s390x and unwrapped directly by `trapif`.
(ProducesFlagsReturnsReg (inst MInst) (result Reg)) (ProducesFlagsReturnsReg (inst MInst) (result Reg))
(ProducesFlagsReturnsResultWithConsumer (inst MInst) (result Reg)))) (ProducesFlagsReturnsResultWithConsumer (inst MInst) (result Reg))))
;; Chain another producer to a `ProducesFlags`.
(decl produces_flags_append (ProducesFlags MInst) ProducesFlags)
(rule (produces_flags_append (ProducesFlags.ProducesFlagsSideEffect inst1) inst2)
(ProducesFlags.ProducesFlagsTwiceSideEffect inst1 inst2))
;; Newtype wrapper around `MInst` for instructions that consume flags. ;; Newtype wrapper around `MInst` for instructions that consume flags.
;; ;;
;; Variant determines how result is given when combined with a ;; Variant determines how result is given when combined with a
@@ -761,6 +777,43 @@
(_v Unit (emit consumer_inst_4))) (_v Unit (emit consumer_inst_4)))
consumer_result)) consumer_result))
(rule (with_flags (ProducesFlags.ProducesFlagsTwiceSideEffect producer_inst1 producer_inst2)
(ConsumesFlags.ConsumesFlagsReturnsReg consumer_inst consumer_result))
(let ((_ Unit (emit producer_inst1))
(_ Unit (emit producer_inst2))
(_ Unit (emit consumer_inst)))
(value_reg consumer_result)))
(rule (with_flags (ProducesFlags.ProducesFlagsTwiceSideEffect producer_inst1 producer_inst2)
(ConsumesFlags.ConsumesFlagsTwiceReturnsValueRegs consumer_inst_1
consumer_inst_2
consumer_result))
;; We must emit these instructions in order as the creator of
;; the ConsumesFlags may be relying on dataflow dependencies
;; amongst them.
(let ((_ Unit (emit producer_inst1))
(_ Unit (emit producer_inst2))
(_ Unit (emit consumer_inst_1))
(_ Unit (emit consumer_inst_2)))
consumer_result))
(rule (with_flags (ProducesFlags.ProducesFlagsTwiceSideEffect producer_inst1 producer_inst2)
(ConsumesFlags.ConsumesFlagsFourTimesReturnsValueRegs consumer_inst_1
consumer_inst_2
consumer_inst_3
consumer_inst_4
consumer_result))
;; We must emit these instructions in order as the creator of
;; the ConsumesFlags may be relying on dataflow dependencies
;; amongst them.
(let ((_ Unit (emit producer_inst1))
(_ Unit (emit producer_inst2))
(_ Unit (emit consumer_inst_1))
(_ Unit (emit consumer_inst_2))
(_ Unit (emit consumer_inst_3))
(_ Unit (emit consumer_inst_4)))
consumer_result))
(decl with_flags_reg (ProducesFlags ConsumesFlags) Reg) (decl with_flags_reg (ProducesFlags ConsumesFlags) Reg)
(rule (with_flags_reg p c) (rule (with_flags_reg p c)
(let ((v ValueRegs (with_flags p c))) (let ((v ValueRegs (with_flags p c)))

View File

@@ -45,10 +45,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, lo ; cset x7, lo
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, lt ; cset x10, lt
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_ult_i128(i128, i128) -> b1 { function %icmp_ult_i128(i128, i128) -> b1 {
@@ -59,10 +59,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, lo ; cset x7, lo
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, lo ; cset x10, lo
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_sle_i128(i128, i128) -> b1 { function %icmp_sle_i128(i128, i128) -> b1 {
@@ -73,10 +73,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, ls ; cset x7, ls
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, le ; cset x10, le
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_ule_i128(i128, i128) -> b1 { function %icmp_ule_i128(i128, i128) -> b1 {
@@ -87,10 +87,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, ls ; cset x7, ls
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, ls ; cset x10, ls
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_sgt_i128(i128, i128) -> b1 { function %icmp_sgt_i128(i128, i128) -> b1 {
@@ -101,10 +101,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, hi ; cset x7, hi
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, gt ; cset x10, gt
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_ugt_i128(i128, i128) -> b1 { function %icmp_ugt_i128(i128, i128) -> b1 {
@@ -115,10 +115,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, hi ; cset x7, hi
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, hi ; cset x10, hi
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_sge_i128(i128, i128) -> b1 { function %icmp_sge_i128(i128, i128) -> b1 {
@@ -129,10 +129,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, hs ; cset x7, hs
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, ge ; cset x10, ge
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %icmp_uge_i128(i128, i128) -> b1 { function %icmp_uge_i128(i128, i128) -> b1 {
@@ -143,10 +143,10 @@ block0(v0: i128, v1: i128):
; block0: ; block0:
; subs xzr, x0, x2 ; subs xzr, x0, x2
; cset x8, hs ; cset x7, hs
; subs xzr, x1, x3 ; subs xzr, x1, x3
; cset x11, hs ; cset x10, hs
; csel x0, x8, x11, eq ; csel x0, x7, x10, eq
; ret ; ret
function %f(i64, i64) -> i64 { function %f(i64, i64) -> i64 {

View File

@@ -15,11 +15,11 @@ block0:
} }
; block0: ; block0:
; movz x3, #56780 ; movz x2, #56780
; uxth w5, w3 ; uxth w4, w2
; movz x7, #56780 ; movz x6, #56780
; subs wzr, w5, w7, UXTH ; subs wzr, w4, w6, UXTH
; cset x4, ne ; cset x9, ne
; and w0, w4, #1 ; and w0, w9, #1
; ret ; ret

View File

@@ -9,8 +9,8 @@ block0(v0: i32x4, v1: i32x4):
} }
; block0: ; block0:
; cmeq v0.4s, v0.4s, v1.4s ; cmeq v4.4s, v0.4s, v1.4s
; mvn v0.16b, v0.16b ; mvn v0.16b, v4.16b
; ret ; ret
function %icmp_ugt_i32x4(i32x4, i32x4) -> b32x4 { function %icmp_ugt_i32x4(i32x4, i32x4) -> b32x4 {