Simplify LowerBackend interface (#5432)
* Refactor lower_branch to have Unit result Branches cannot have any output, so it is more straightforward to have the ISLE term return Unit instead of InstOutput. Also provide a new `emit_side_effect` term to simplify implementation of `lower_branch` rules with Unit result. * Simplify LowerBackend interface Move all remaining asserts from the LowerBackend::lower and ::lower_branch_group into the common call site. Change return value of ::lower to Option<InstOutput>, and return value of ::lower_branch_group to Option<()> to match ISLE term signature. Only pass the first branch into ::lower_branch_group and rename it to ::lower_branch. As a result of all those changes, LowerBackend routines now consists solely to calls to the corresponding ISLE routines.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
;; A variant of the main lowering constructor term, used for branches.
|
||||
;; The only difference is that it gets an extra argument holding a vector
|
||||
;; of branch targets to be used.
|
||||
(decl partial lower_branch (Inst MachLabelSlice) InstOutput)
|
||||
(decl partial lower_branch (Inst MachLabelSlice) Unit)
|
||||
|
||||
;;;; Rules for `iconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -2865,55 +2865,55 @@
|
||||
;; Rules for `jump` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower_branch (jump _ _) (single_target target))
|
||||
(side_effect (jmp_known target)))
|
||||
(emit_side_effect (jmp_known target)))
|
||||
|
||||
;; Rules for `brz` and `brnz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule 2 (lower_branch (brz (icmp cc a b) _ _) (two_targets taken not_taken))
|
||||
(let ((cmp IcmpCondResult (invert_icmp_cond_result (emit_cmp cc a b))))
|
||||
(side_effect (jmp_cond_icmp cmp taken not_taken))))
|
||||
(emit_side_effect (jmp_cond_icmp cmp taken not_taken))))
|
||||
|
||||
(rule 2 (lower_branch (brz (uextend (icmp cc a b)) _ _) (two_targets taken not_taken))
|
||||
(let ((cmp IcmpCondResult (invert_icmp_cond_result (emit_cmp cc a b))))
|
||||
(side_effect (jmp_cond_icmp cmp taken not_taken))))
|
||||
(emit_side_effect (jmp_cond_icmp cmp taken not_taken))))
|
||||
|
||||
|
||||
(rule 2 (lower_branch (brz (fcmp cc a b) _ _) (two_targets taken not_taken))
|
||||
(let ((cmp FcmpCondResult (emit_fcmp (floatcc_inverse cc) a b)))
|
||||
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
(emit_side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
|
||||
(rule 2 (lower_branch (brz (uextend (fcmp cc a b)) _ _) (two_targets taken not_taken))
|
||||
(let ((cmp FcmpCondResult (emit_fcmp (floatcc_inverse cc) a b)))
|
||||
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
(emit_side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
|
||||
(rule 1 (lower_branch (brz val @ (value_type $I128) _ _) (two_targets taken not_taken))
|
||||
(side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.NZ) val) taken not_taken)))
|
||||
(emit_side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.NZ) val) taken not_taken)))
|
||||
|
||||
(rule 0 (lower_branch (brz val @ (value_type (ty_int_bool_or_ref)) _ _) (two_targets taken not_taken))
|
||||
(side_effect
|
||||
(emit_side_effect
|
||||
(with_flags_side_effect (cmp_zero_int_bool_ref val)
|
||||
(jmp_cond (CC.Z) taken not_taken))))
|
||||
|
||||
|
||||
(rule 2 (lower_branch (brnz (icmp cc a b) _ _) (two_targets taken not_taken))
|
||||
(side_effect (jmp_cond_icmp (emit_cmp cc a b) taken not_taken)))
|
||||
(emit_side_effect (jmp_cond_icmp (emit_cmp cc a b) taken not_taken)))
|
||||
|
||||
(rule 2 (lower_branch (brnz (fcmp cc a b) _ _) (two_targets taken not_taken))
|
||||
(let ((cmp FcmpCondResult (emit_fcmp cc a b)))
|
||||
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
(emit_side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
|
||||
(rule 2 (lower_branch (brnz (uextend (icmp cc a b)) _ _) (two_targets taken not_taken))
|
||||
(side_effect (jmp_cond_icmp (emit_cmp cc a b) taken not_taken)))
|
||||
(emit_side_effect (jmp_cond_icmp (emit_cmp cc a b) taken not_taken)))
|
||||
|
||||
(rule 2 (lower_branch (brnz (uextend (fcmp cc a b)) _ _) (two_targets taken not_taken))
|
||||
(let ((cmp FcmpCondResult (emit_fcmp cc a b)))
|
||||
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
(emit_side_effect (jmp_cond_fcmp cmp taken not_taken))))
|
||||
|
||||
(rule 1 (lower_branch (brnz val @ (value_type $I128) _ _) (two_targets taken not_taken))
|
||||
(side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.Z) val) taken not_taken)))
|
||||
(emit_side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.Z) val) taken not_taken)))
|
||||
|
||||
(rule 0 (lower_branch (brnz val @ (value_type (ty_int_bool_or_ref)) _ _) (two_targets taken not_taken))
|
||||
(side_effect
|
||||
(emit_side_effect
|
||||
(with_flags_side_effect (cmp_zero_int_bool_ref val)
|
||||
(jmp_cond (CC.NZ) taken not_taken))))
|
||||
|
||||
@@ -2944,7 +2944,7 @@
|
||||
;; Rules for `br_table` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower_branch (br_table idx @ (value_type ty) _ _) (jump_table_targets default_target jt_targets))
|
||||
(side_effect (jmp_table_seq ty idx default_target jt_targets)))
|
||||
(emit_side_effect (jmp_table_seq ty idx default_target jt_targets)))
|
||||
|
||||
;; Rules for `select_spectre_guard` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
@@ -299,51 +299,17 @@ fn lower_to_amode(ctx: &mut Lower<Inst>, spec: InsnInput, offset: i32) -> Amode
|
||||
impl LowerBackend for X64Backend {
|
||||
type MInst = Inst;
|
||||
|
||||
fn lower(&self, ctx: &mut Lower<Inst>, ir_inst: IRInst) -> CodegenResult<InstOutput> {
|
||||
if let Some(temp_regs) = isle::lower(ctx, self, ir_inst) {
|
||||
return Ok(temp_regs);
|
||||
}
|
||||
|
||||
let ty = if ctx.num_outputs(ir_inst) > 0 {
|
||||
Some(ctx.output_ty(ir_inst, 0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
unreachable!(
|
||||
"not implemented in ISLE: inst = `{}`, type = `{:?}`",
|
||||
ctx.dfg().display_inst(ir_inst),
|
||||
ty
|
||||
);
|
||||
fn lower(&self, ctx: &mut Lower<Inst>, ir_inst: IRInst) -> Option<InstOutput> {
|
||||
isle::lower(ctx, self, ir_inst)
|
||||
}
|
||||
|
||||
fn lower_branch_group(
|
||||
fn lower_branch(
|
||||
&self,
|
||||
ctx: &mut Lower<Inst>,
|
||||
branches: &[IRInst],
|
||||
ir_inst: IRInst,
|
||||
targets: &[MachLabel],
|
||||
) -> CodegenResult<()> {
|
||||
// A block should end with at most two branches. The first may be a
|
||||
// conditional branch; a conditional branch can be followed only by an
|
||||
// unconditional branch or fallthrough. Otherwise, if only one branch,
|
||||
// it may be an unconditional branch, a fallthrough, a return, or a
|
||||
// trap. These conditions are verified by `is_ebb_basic()` during the
|
||||
// verifier pass.
|
||||
assert!(branches.len() <= 2);
|
||||
if branches.len() == 2 {
|
||||
let op1 = ctx.data(branches[1]).opcode();
|
||||
assert!(op1 == Opcode::Jump);
|
||||
}
|
||||
|
||||
if let Some(temp_regs) = isle::lower_branch(ctx, self, branches[0], targets) {
|
||||
assert!(temp_regs.len() == 0);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
unreachable!(
|
||||
"not implemented in ISLE: branch = `{}`",
|
||||
ctx.dfg().display_inst(branches[0]),
|
||||
);
|
||||
) -> Option<()> {
|
||||
isle::lower_branch(ctx, self, ir_inst, targets)
|
||||
}
|
||||
|
||||
fn maybe_pinned_reg(&self) -> Option<Reg> {
|
||||
|
||||
@@ -68,7 +68,7 @@ pub(crate) fn lower_branch(
|
||||
backend: &X64Backend,
|
||||
branch: Inst,
|
||||
targets: &[MachLabel],
|
||||
) -> Option<InstOutput> {
|
||||
) -> Option<()> {
|
||||
// TODO: reuse the ISLE context across lowerings so we can reuse its
|
||||
// internal heap allocations.
|
||||
let mut isle_ctx = IsleContext { lower_ctx, backend };
|
||||
|
||||
Reference in New Issue
Block a user