WIP.
This commit is contained in:
parent
a676310629
commit
5859930639
|
@ -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| {
|
||||||
|
let reused = if can_reuse {
|
||||||
// Try to find a local of the right type that is not live.
|
// Try to find a local of the right type that is not live.
|
||||||
let affinities = affinities.get(&u).map(|v| &v[..]).unwrap_or(&[]);
|
let affinities =
|
||||||
let local = affinities
|
affinities.get(&u).map(|v| &v[..]).unwrap_or(&[]);
|
||||||
|
let mut try_list = affinities
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|&aff_val| {
|
.filter_map(|&aff_val| {
|
||||||
let local = *results.values[aff_val].get(0)?;
|
let local = *results.values[aff_val].get(0)?;
|
||||||
Some((local, results.locals[local]))
|
Some((local, results.locals[local]))
|
||||||
})
|
})
|
||||||
.chain(results.locals.entries().map(|(local, &ty)| (local, ty)))
|
.chain(
|
||||||
.filter_map(|(local, local_ty)| {
|
results
|
||||||
if local_ty == ty && live_locals.insert(local) {
|
.locals
|
||||||
Some(local)
|
.entries()
|
||||||
|
.map(|(local, &ty)| (local, ty)),
|
||||||
|
);
|
||||||
|
|
||||||
|
try_list
|
||||||
|
.find(|&(local, local_ty)| {
|
||||||
|
local_ty == ty && live_locals.insert(local)
|
||||||
|
})
|
||||||
|
.map(|(local, _)| local)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
};
|
||||||
})
|
|
||||||
.next();
|
reused.unwrap_or_else(|| {
|
||||||
local.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,
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue