Refactor collect_branches_and_targets to not need a smallvec (#5803)

* Refactor collect_branches_and_targets to not need a smallvec

Basic blocks are terminated by at most one branch instruction now, so we
can use that assumption in `collect_branches_and_targets` to return the
last instruction we saw instead.

* Review comments
This commit is contained in:
Trevor Elliott
2023-02-16 13:30:17 -08:00
committed by GitHub
parent c7e2571866
commit d711872d63

View File

@@ -10,8 +10,8 @@ use crate::fx::{FxHashMap, FxHashSet};
use crate::inst_predicates::{has_lowering_side_effect, is_constant_64bit};
use crate::ir::{
ArgumentPurpose, Block, Constant, ConstantData, DataFlowGraph, ExternalName, Function,
GlobalValue, GlobalValueData, Immediate, Inst, InstructionData, MemFlags, Opcode, RelSourceLoc,
Type, Value, ValueDef, ValueLabelAssignments, ValueLabelStart,
GlobalValue, GlobalValueData, Immediate, Inst, InstructionData, MemFlags, RelSourceLoc, Type,
Value, ValueDef, ValueLabelAssignments, ValueLabelStart,
};
use crate::machinst::{
writable_value_regs, BlockIndex, BlockLoweringOrder, Callee, LoweredBlock, MachLabel, Reg,
@@ -898,39 +898,29 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
bindex: BlockIndex,
// Original CLIF block:
block: Block,
branches: &SmallVec<[Inst; 2]>,
targets: &SmallVec<[MachLabel; 2]>,
branch: Inst,
targets: &[MachLabel],
) -> CodegenResult<()> {
trace!(
"lower_clif_branches: block {} branches {:?} targets {:?}",
"lower_clif_branches: block {} branch {:?} targets {:?}",
block,
branches,
branch,
targets,
);
// 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_block_basic()` during the
// verifier pass.
assert!(branches.len() <= 2);
if branches.len() == 2 {
assert!(self.data(branches[1]).opcode() == Opcode::Jump);
}
// When considering code-motion opportunities, consider the current
// program point to be the first branch.
self.cur_inst = Some(branches[0]);
// Lower the first branch in ISLE. This will automatically handle
// the second branch (if any) by emitting a two-way conditional branch.
// program point to be this branch.
self.cur_inst = Some(branch);
// Lower the branch in ISLE.
backend
.lower_branch(self, branches[0], targets)
.lower_branch(self, branch, targets)
.unwrap_or_else(|| {
panic!(
"should be implemented in ISLE: branch = `{}`",
self.f.dfg.display_inst(branches[0]),
self.f.dfg.display_inst(branch),
)
});
let loc = self.srcloc(branches[0]);
let loc = self.srcloc(branch);
self.finish_ir_inst(loc);
// Add block param outputs for current block.
self.lower_branch_blockparam_args(bindex);
@@ -967,26 +957,20 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
&self,
bindex: BlockIndex,
_bb: Block,
branches: &mut SmallVec<[Inst; 2]>,
targets: &mut SmallVec<[MachLabel; 2]>,
) {
branches.clear();
) -> Option<Inst> {
targets.clear();
let mut last_inst = None;
for &(inst, succ) in self.vcode.block_order().succ_indices(bindex) {
// Avoid duplicates: this ensures a br_table is only inserted once.
if last_inst != Some(inst) {
branches.push(inst);
} else {
debug_assert!(
self.f.dfg.insts[inst].opcode() == Opcode::BrTable
|| self.f.dfg.insts[inst].opcode() == Opcode::Brif
);
debug_assert!(branches.len() == 1);
}
// Basic blocks may end in a single branch instruction, but those instructions may have
// multiple destinations. As such, all `inst` values in `succ_indices` must be the
// same, or this basic block would have multiple branch instructions present.
debug_assert!(last_inst.map_or(true, |prev| prev == inst));
last_inst = Some(inst);
targets.push(MachLabel::from_block(succ));
}
last_inst
}
/// Lower the function.
@@ -1010,7 +994,6 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
self.vcode.set_entry(BlockIndex::new(0));
// Reused vectors for branch lowering.
let mut branches: SmallVec<[Inst; 2]> = SmallVec::new();
let mut targets: SmallVec<[MachLabel; 2]> = SmallVec::new();
// get a copy of the lowered order; we hold this separately because we
@@ -1032,10 +1015,9 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
// End branches.
if let Some(bb) = lb.orig_block() {
self.collect_branches_and_targets(bindex, bb, &mut branches, &mut targets);
if branches.len() > 0 {
self.lower_clif_branches(backend, bindex, bb, &branches, &targets)?;
self.finish_ir_inst(self.srcloc(branches[0]));
if let Some(branch) = self.collect_branches_and_targets(bindex, bb, &mut targets) {
self.lower_clif_branches(backend, bindex, bb, branch, &targets)?;
self.finish_ir_inst(self.srcloc(branch));
}
} else {
// If no orig block, this must be a pure edge block;