Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,19 +348,14 @@ pub struct EntityOrientedDenseMap<K: EntityOrientedMapKey<V>, V> {
// since the ideal state is one chunk per map, the slow case might never be hit,
// unless one `EntityOrientedDenseMap` is used with more than one `EntityDefs`,
// which could still maybe be implemented more efficiently than `FxHashMap`.
#[derive(Clone)]
#[derive(Clone, Default)]
enum SmallFxHashMap<K, V> {
#[default]
Empty,
One(K, V),
More(FxHashMap<K, V>),
}

impl<K, V> Default for SmallFxHashMap<K, V> {
fn default() -> Self {
Self::Empty
}
}

impl<K: Copy + Eq + Hash, V: Default> SmallFxHashMap<K, V> {
fn get_mut_or_insert_default(&mut self, k: K) -> &mut V {
// HACK(eddyb) to avoid borrowing issues, this is done in two stages:
Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
clippy::dbg_macro,
clippy::debug_assert_with_mut_call,
clippy::doc_markdown,
clippy::empty_enum,
clippy::empty_enums,
clippy::enum_glob_use,
clippy::exit,
clippy::expl_impl_clone_on_copy,
Expand Down Expand Up @@ -121,7 +121,6 @@
clippy::string_add_assign,
clippy::string_add,
clippy::string_lit_as_bytes,
clippy::string_to_string,
clippy::todo,
clippy::trait_duplication_in_bounds,
clippy::unimplemented,
Expand Down
60 changes: 54 additions & 6 deletions src/spv/lift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,22 +863,70 @@ impl<'a> FuncLifting<'a> {
// HACK(eddyb) this takes advantage of `blocks` being an `IndexMap`,
// to iterate at the same time as mutating other entries.
for block_idx in (0..blocks.len()).rev() {
let BlockLifting { terminator: original_terminator, .. } = &blocks[block_idx];
// HACK(eddyb) elide empty cases of an `if`-`else`/`switch`, as
// SPIR-V allows their targets to just be the whole merge block
// (the same one that `OpSelectionMerge` describes).
let block = &blocks[block_idx];
if let (cfg::ControlInstKind::SelectBranch(_), Some(Merge::Selection(merge_point))) =
(&*block.terminator.kind, block.terminator.merge)
{
for target_idx in 0..block.terminator.targets.len() {
let block = &blocks[block_idx];
let target = block.terminator.targets[target_idx];
if !block
.terminator
.target_phi_values
.get(&target)
.copied()
.unwrap_or_default()
.is_empty()
{
continue;
}

let target_is_trivial_branch = {
let BlockLifting {
phis,
insts,
terminator:
Terminator { attrs, kind, inputs, targets, target_phi_values, merge },
} = &blocks[&target];

(phis.is_empty()
&& insts.iter().all(|insts| insts.is_empty())
&& *attrs == AttrSet::default()
&& matches!(**kind, cfg::ControlInstKind::Branch)
&& inputs.is_empty()
&& targets.len() == 1
&& target_phi_values.is_empty()
&& merge.is_none())
.then(|| targets[0])
};
if let Some(target_of_target) = target_is_trivial_branch
&& target_of_target == merge_point
{
blocks[block_idx].terminator.targets[target_idx] = target_of_target;
*use_counts.get_mut(&target).unwrap() -= 1;
*use_counts.get_mut(&target_of_target).unwrap() += 1;
}
}
}

let block = &blocks[block_idx];
let is_trivial_branch = {
let Terminator { attrs, kind, inputs, targets, target_phi_values, merge } =
original_terminator;
&block.terminator;

*attrs == AttrSet::default()
(*attrs == AttrSet::default()
&& matches!(**kind, cfg::ControlInstKind::Branch)
&& inputs.is_empty()
&& targets.len() == 1
&& target_phi_values.is_empty()
&& merge.is_none()
&& merge.is_none())
.then(|| targets[0])
};

if is_trivial_branch {
let target = original_terminator.targets[0];
if let Some(target) = is_trivial_branch {
let target_use_count = use_counts.get_mut(&target).unwrap();

if *target_use_count == 1 {
Expand Down
Loading