This commit is contained in:
Chris Fallin 2022-11-29 00:27:38 -08:00
parent a676310629
commit 5859930639
2 changed files with 70 additions and 22 deletions

View file

@ -52,9 +52,9 @@ impl<'a> Context<'a> {
.zip(body.blocks[target.block].params.iter().map(|(_, val)| val)) .zip(body.blocks[target.block].params.iter().map(|(_, val)| val))
{ {
affinities affinities
.entry(param) .entry(arg)
.or_insert_with(|| smallvec![]) .or_insert_with(|| smallvec![])
.push(arg); .push(param);
} }
}); });
} }
@ -124,6 +124,8 @@ impl<'a> Context<'a> {
// use (first observed), allocate a local. // use (first observed), allocate a local.
fn handle_use( fn handle_use(
body: &FunctionBody, body: &FunctionBody,
cfg: &CFGInfo,
block: Block,
u: Value, u: Value,
live_values: &mut HashSet<Value>, live_values: &mut HashSet<Value>,
live_locals: &mut HashSet<Local>, live_locals: &mut HashSet<Local>,
@ -145,32 +147,56 @@ impl<'a> Context<'a> {
unreachable!(); unreachable!();
} }
&ValueDef::PickOutput(value, idx, _) => { &ValueDef::PickOutput(value, idx, _) => {
handle_use(body, value, live_values, live_locals, results, affinities); handle_use(
body,
cfg,
block,
value,
live_values,
live_locals,
results,
affinities,
);
results.values[u] = smallvec![results.values[value][idx]]; results.values[u] = smallvec![results.values[value][idx]];
} }
&ValueDef::BlockParam(..) | &ValueDef::Operator(..) => { &ValueDef::BlockParam(..) | &ValueDef::Operator(..) => {
// Uses from dominating blocks may be live
// over a loop backedge, so for simplicity,
// let's not reuse any locals for uses of
// non-local defs.
let can_reuse = cfg.def_block[u] == block;
let locals = def let locals = def
.tys() .tys()
.iter() .iter()
.map(|&ty| { .map(|&ty| {
// Try to find a local of the right type that is not live. let reused = if can_reuse {
let affinities = affinities.get(&u).map(|v| &v[..]).unwrap_or(&[]); // Try to find a local of the right type that is not live.
let local = affinities let affinities =
.iter() affinities.get(&u).map(|v| &v[..]).unwrap_or(&[]);
.filter_map(|&aff_val| { let mut try_list = affinities
let local = *results.values[aff_val].get(0)?; .iter()
Some((local, results.locals[local])) .filter_map(|&aff_val| {
}) let local = *results.values[aff_val].get(0)?;
.chain(results.locals.entries().map(|(local, &ty)| (local, ty))) Some((local, results.locals[local]))
.filter_map(|(local, local_ty)| { })
if local_ty == ty && live_locals.insert(local) { .chain(
Some(local) results
} else { .locals
None .entries()
} .map(|(local, &ty)| (local, ty)),
}) );
.next();
local.unwrap_or_else(|| { try_list
.find(|&(local, local_ty)| {
local_ty == ty && live_locals.insert(local)
})
.map(|(local, _)| local)
} else {
None
};
reused.unwrap_or_else(|| {
let local = results.locals.push(ty); let local = results.locals.push(ty);
live_locals.insert(local); live_locals.insert(local);
local local
@ -205,6 +231,8 @@ impl<'a> Context<'a> {
self.body.blocks[block].terminator.visit_uses(|u| { self.body.blocks[block].terminator.visit_uses(|u| {
handle_use( handle_use(
self.body, self.body,
self.cfg,
block,
u, u,
&mut live_values, &mut live_values,
&mut live_locals, &mut live_locals,
@ -226,6 +254,8 @@ impl<'a> Context<'a> {
if !self.trees.owner.contains_key(&u) { if !self.trees.owner.contains_key(&u) {
handle_use( handle_use(
self.body, self.body,
self.cfg,
block,
u, u,
&mut live_values, &mut live_values,
&mut live_locals, &mut live_locals,

View file

@ -4,7 +4,7 @@
// LLVM exception. // LLVM exception.
use crate::entity::{EntityRef, PerEntity}; use crate::entity::{EntityRef, PerEntity};
use crate::ir::{Block, FunctionBody, Terminator}; use crate::ir::{Block, FunctionBody, Terminator, Value, ValueDef};
use smallvec::SmallVec; use smallvec::SmallVec;
pub mod domtree; pub mod domtree;
@ -28,6 +28,8 @@ pub struct CFGInfo {
pub domtree: PerEntity<Block, Block>, pub domtree: PerEntity<Block, Block>,
/// Domtree children. /// Domtree children.
pub domtree_children: PerEntity<Block, DomtreeChildren>, pub domtree_children: PerEntity<Block, DomtreeChildren>,
/// Defining block for a given value.
pub def_block: PerEntity<Value, Block>,
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
@ -91,6 +93,21 @@ impl CFGInfo {
} }
} }
let mut def_block: PerEntity<Value, Block> = PerEntity::default();
for (block, block_def) in f.blocks.entries() {
for &value in &block_def.insts {
def_block[value] = block;
}
}
for value in f.values.iter() {
let orig_value = f.resolve_alias(value);
let underlying_value = match &f.values[orig_value] {
&ValueDef::PickOutput(value, ..) => value,
_ => orig_value,
};
def_block[value] = def_block[underlying_value];
}
CFGInfo { CFGInfo {
entry: f.entry, entry: f.entry,
block_preds, block_preds,
@ -100,6 +117,7 @@ impl CFGInfo {
postorder_pos, postorder_pos,
domtree, domtree,
domtree_children, domtree_children,
def_block,
} }
} }