machinst: Reduce the number of vec allocations for edge blocks;

This commit is contained in:
Benjamin Bouvier
2020-05-06 18:47:12 +02:00
parent 9215b610ef
commit b24b711c16

View File

@@ -260,7 +260,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
let b = queue.pop_front().unwrap(); let b = queue.pop_front().unwrap();
ret.push(b); ret.push(b);
let mut succs: SmallVec<[Block; 16]> = SmallVec::new(); let mut succs: SmallVec<[Block; 16]> = SmallVec::new();
for inst in self.f.layout.block_insts(b) { for inst in self.f.layout.block_likely_branches(b) {
if self.f.dfg[inst].opcode().is_branch() { if self.f.dfg[inst].opcode().is_branch() {
visit_branch_targets(self.f, b, inst, |succ| { visit_branch_targets(self.f, b, inst, |succ| {
succs.push(succ); succs.push(succ);
@@ -292,9 +292,18 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
// Allocate a separate BlockIndex for each control-flow instruction so that we can create // Allocate a separate BlockIndex for each control-flow instruction so that we can create
// the edge blocks later. Each entry for a control-flow inst is the edge block; the list // the edge blocks later. Each entry for a control-flow inst is the edge block; the list
// has (control flow inst, edge block, orig block) tuples. // has (control flow inst, edge block, orig block) tuples.
let mut edge_blocks_by_inst: SecondaryMap<Inst, Vec<BlockIndex>> = //
SecondaryMap::with_default(vec![]); // In general, a given inst may have only one target, except for jump tables which have
let mut edge_blocks: Vec<(Inst, BlockIndex, Block)> = vec![]; // more. But SmallVec may store inline more than the spec'd number, so ask for slightly
// more.
let mut edge_blocks_by_inst: SecondaryMap<Inst, SmallVec<[BlockIndex; 2]>> =
SecondaryMap::with_default(SmallVec::new());
// Each basic block may at most have two edge blocks, since it may have a most two branch
// instructions. If we omit jump tables, we can model that 50% of branches are direct jumps
// (1 successor), and 50% are tests (2 successors). A distribution of edge_blocks per block
// matches this rough estimate that there are 1.5 edge block per block.
let mut edge_blocks: Vec<(Inst, BlockIndex, Block)> = Vec::with_capacity(bbs.len() * 3 / 2);
debug!("about to lower function: {:?}", self.f); debug!("about to lower function: {:?}", self.f);
debug!("bb map: {:?}", self.vcode.blocks_by_bb()); debug!("bb map: {:?}", self.vcode.blocks_by_bb());
@@ -302,9 +311,8 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
// Work backward (reverse block order, reverse through each block), skipping insns with zero // Work backward (reverse block order, reverse through each block), skipping insns with zero
// uses. // uses.
for bb in bbs.iter().rev() { for bb in bbs.iter().rev() {
for inst in self.f.layout.block_insts(*bb) { for inst in self.f.layout.block_likely_branches(*bb) {
let op = self.f.dfg[inst].opcode(); if self.f.dfg[inst].opcode().is_branch() {
if op.is_branch() {
// Find the original target. // Find the original target.
let mut add_succ = |next_bb| { let mut add_succ = |next_bb| {
let edge_block = next_bindex; let edge_block = next_bindex;
@@ -373,17 +381,14 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
targets.clear(); targets.clear();
} }
// Only codegen an instruction if it either has a side // Only codegen an instruction if it either has a side effect, or has at least
// effect, or has at least one use of one of its results. // one use of one of its results.
let num_uses = self.num_uses[inst]; if self.num_uses[inst] > 0 || has_side_effect(self.f, inst) {
let side_effect = has_side_effect(self.f, inst);
if side_effect || num_uses > 0 {
self.vcode.set_srcloc(self.srcloc(inst)); self.vcode.set_srcloc(self.srcloc(inst));
backend.lower(&mut self, inst); backend.lower(&mut self, inst);
self.vcode.end_ir_inst(); self.vcode.end_ir_inst();
} else { } else {
// If we're skipping the instruction, we need to dec-ref // If we're skipping the instruction, we need to dec-ref its arguments.
// its arguments.
for arg in self.f.dfg.inst_args(inst) { for arg in self.f.dfg.inst_args(inst) {
let val = self.f.dfg.resolve_aliases(*arg); let val = self.f.dfg.resolve_aliases(*arg);
match self.f.dfg.value_def(val) { match self.f.dfg.value_def(val) {