Port branches to ISLE (AArch64) (#4943)
* Port branches to ISLE (AArch64) Ported the existing implementations of the following opcodes for AArch64 to ISLE: - `Brz` - `Brnz` - `Brif` - `Brff` - `BrIcmp` - `Jump` - `BrTable` Copyright (c) 2022 Arm Limited * Remove dead code Copyright (c) 2022 Arm Limited
This commit is contained in:
@@ -4,6 +4,16 @@
|
||||
;; register(s) within which the lowered instruction's result values live.
|
||||
(decl lower (Inst) InstOutput)
|
||||
|
||||
;; Variant of the main lowering constructor term, which receives an
|
||||
;; additional argument (a vector of branch targets to be used) for
|
||||
;; implementing branches.
|
||||
;; For two-branch instructions, the first target is `taken` and the second
|
||||
;; `not_taken`, even if it is a Fallthrough instruction: because we reorder
|
||||
;; blocks while we lower, the fallthrough in the new order is not (necessarily)
|
||||
;; the same as the fallthrough in CLIF. So, we use the explicitly-provided
|
||||
;; target.
|
||||
(decl lower_branch (Inst VecMachLabel) InstOutput)
|
||||
|
||||
;;;; Rules for `iconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (has_type ty (iconst (u64_from_imm64 n))))
|
||||
@@ -2497,12 +2507,185 @@
|
||||
|
||||
;;; Rules for `brz`/`brnz`/`brif`/`brff`/`bricmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO: requires icmp/fcmp first.
|
||||
;; `brz` following `icmp`, possibly converted via `bint`.
|
||||
(rule (lower_branch (brz (icmp cc x @ (value_type ty) y) _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(cond Cond (invert_cond cond)) ;; negate for `brz`
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (lower_icmp_into_flags cc x y ty)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
(rule (lower_branch (brz (bint (icmp cc x @ (value_type ty) y)) _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(cond Cond (invert_cond cond)) ;; negate for `brz`
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (lower_icmp_into_flags cc x y ty)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
;; `brnz` following `icmp`, possibly converted via `bint`.
|
||||
(rule (lower_branch (brnz (icmp cc x @ (value_type ty) y) _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (lower_icmp_into_flags cc x y ty)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
(rule (lower_branch (brnz (bint (icmp cc x @ (value_type ty) y)) _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (lower_icmp_into_flags cc x y ty)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
;; `brz` following `fcmp`, possibly converted via `bint`.
|
||||
(rule (lower_branch (brz (fcmp cc x @ (value_type (ty_scalar_float ty)) y) _ _) targets)
|
||||
(let ((cond Cond (fp_cond_code cc))
|
||||
(cond Cond (invert_cond cond)) ;; negate for `brz`
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (fpu_cmp (scalar_size ty) x y)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
(rule (lower_branch (brz (bint (fcmp cc x @ (value_type (ty_scalar_float ty)) y)) _ _) targets)
|
||||
(let ((cond Cond (fp_cond_code cc))
|
||||
(cond Cond (invert_cond cond)) ;; negate for `brz`
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (fpu_cmp (scalar_size ty) x y)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
;; `brnz` following `fcmp`, possibly converted via `bint`.
|
||||
(rule (lower_branch (brnz (fcmp cc x @ (value_type (ty_scalar_float ty)) y) _ _) targets)
|
||||
(let ((cond Cond (fp_cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (fpu_cmp (scalar_size ty) x y)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
(rule (lower_branch (brnz (bint (fcmp cc x @ (value_type (ty_scalar_float ty)) y)) _ _) targets)
|
||||
(let ((cond Cond (fp_cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (fpu_cmp (scalar_size ty) x y)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
;; standard `brz`
|
||||
(rule (lower_branch (brz c @ (value_type $I128) _ _) targets)
|
||||
(let ((flags ProducesFlags (flags_to_producesflags c))
|
||||
(c ValueRegs (put_in_regs c))
|
||||
(c_lo Reg (value_regs_get c 0))
|
||||
(c_hi Reg (value_regs_get c 1))
|
||||
(rt Reg (orr $I64 c_lo c_hi))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect flags
|
||||
(cond_br taken not_taken (cond_br_zero rt))))))
|
||||
(rule (lower_branch (brz c @ (value_type ty) _ _) targets)
|
||||
(if (ty_int_bool_ref_scalar_64 ty))
|
||||
(let ((flags ProducesFlags (flags_to_producesflags c))
|
||||
(rt Reg (put_in_reg_zext64 c))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect flags
|
||||
(cond_br taken not_taken (cond_br_zero rt))))))
|
||||
;; standard `brnz`
|
||||
(rule (lower_branch (brnz c @ (value_type $I128) _ _) targets)
|
||||
(let ((flags ProducesFlags (flags_to_producesflags c))
|
||||
(c ValueRegs (put_in_regs c))
|
||||
(c_lo Reg (value_regs_get c 0))
|
||||
(c_hi Reg (value_regs_get c 1))
|
||||
(rt Reg (orr $I64 c_lo c_hi))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect flags
|
||||
(cond_br taken not_taken (cond_br_not_zero rt))))))
|
||||
(rule (lower_branch (brnz c @ (value_type ty) _ _) targets)
|
||||
(if (ty_int_bool_ref_scalar_64 ty))
|
||||
(let ((flags ProducesFlags (flags_to_producesflags c))
|
||||
(rt Reg (put_in_reg_zext64 c))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect flags
|
||||
(cond_br taken not_taken (cond_br_not_zero rt))))))
|
||||
|
||||
;; `br_icmp`
|
||||
(rule (lower_branch (br_icmp cc x @ (value_type ty) y _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (lower_icmp_into_flags cc x y ty)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
|
||||
;; `brif`
|
||||
(rule (lower_branch (brif cc (ifcmp x @ (value_type ty) y) _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (lower_icmp_into_flags cc x y ty)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
;; If the `ifcmp` result is actually placed in a register, we need to move it
|
||||
;; back into the flags.
|
||||
(rule -1 (lower_branch (brif cc f _ _) targets)
|
||||
(let ((cond Cond (cond_code cc))
|
||||
(rn Reg (put_in_reg f))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (mov_to_nzcv rn)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
|
||||
;; `brff`
|
||||
(rule (lower_branch (brff cc (ffcmp x @ (value_type ty) y) _ _) targets)
|
||||
(let ((cond Cond (fp_cond_code cc))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (fpu_cmp (scalar_size ty) x y)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
;; If the `ffcmp` result is actually placed in a register, we need to move it
|
||||
;; back into the flags.
|
||||
(rule -1 (lower_branch (brff cc f _ _) targets)
|
||||
(let ((cond Cond (fp_cond_code cc))
|
||||
(rn Reg (put_in_reg f))
|
||||
(taken BranchTarget (branch_target targets 0))
|
||||
(not_taken BranchTarget (branch_target targets 1)))
|
||||
(side_effect
|
||||
(with_flags_side_effect (mov_to_nzcv rn)
|
||||
(cond_br taken not_taken
|
||||
(cond_br_cond cond))))))
|
||||
|
||||
;;; Rules for `jump` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO.
|
||||
(rule (lower_branch (jump _ _) targets)
|
||||
(side_effect (aarch64_jump (branch_target targets 0))))
|
||||
|
||||
;;; Rules for `br_table` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO.
|
||||
;; `targets` contains the default target with the list of branch targets
|
||||
;; concatenated.
|
||||
(rule (lower_branch (br_table idx _ _) targets)
|
||||
(let ((jt_size u32 (targets_jt_size targets))
|
||||
(_ InstOutput (side_effect
|
||||
(emit_island (targets_jt_space targets))))
|
||||
(ridx Reg (put_in_reg_zext32 idx)))
|
||||
(br_table_impl (u32_as_u64 jt_size) ridx targets)))
|
||||
|
||||
Reference in New Issue
Block a user