Skip to content
Merged
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
59 changes: 59 additions & 0 deletions cranelift/codegen/src/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,65 @@ impl DataFlowGraph {
resolve_aliases(&self.values, value)
}

/// Replace all uses of value aliases with their resolved values, and delete
/// the aliases.
pub fn resolve_all_aliases(&mut self) {
let invalid_value = ValueDataPacked::from(ValueData::Alias {
ty: types::INVALID,
original: Value::reserved_value(),
});

// Rewrite each chain of aliases. Update every alias along the chain
// into an alias directly to the final value. Due to updating every
// alias that it looks at, this loop runs in time linear in the number
// of values.
for mut src in self.values.keys() {
let value_data = self.values[src];
if value_data == invalid_value {
continue;
}
if let ValueData::Alias { mut original, .. } = value_data.into() {
// We don't use the type after this, we just need some place to
// store the resolved aliases temporarily.
let resolved = ValueDataPacked::from(ValueData::Alias {
ty: types::INVALID,
original: resolve_aliases(&self.values, original),
});
// Walk the chain again, splatting the new alias everywhere.
// resolve_aliases panics if there's an alias cycle, so we don't
// need to guard against cycles here.
loop {
self.values[src] = resolved;
src = original;
if let ValueData::Alias { original: next, .. } = self.values[src].into() {
original = next;
} else {
break;
}
}
}
}

// Now aliases don't point to other aliases, so we can replace any use
// of an alias with the final value in constant time.
for inst in self.insts.0.values_mut() {
inst.map_values(&mut self.value_lists, &mut self.jump_tables, |arg| {
if let ValueData::Alias { original, .. } = self.values[arg].into() {
original
} else {
arg
}
});
}

// Delete all aliases now that there are no uses left.
for value in self.values.values_mut() {
if let ValueData::Alias { .. } = ValueData::from(*value) {
*value = invalid_value;
}
}
}

/// Resolve all aliases among inst's arguments.
///
/// For each argument of inst which is defined by an alias, replace the
Expand Down
10 changes: 1 addition & 9 deletions cranelift/src/bugpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,18 +822,10 @@ fn inst_count(func: &Function) -> usize {
.sum()
}

fn resolve_aliases(func: &mut Function) {
for block in func.stencil.layout.blocks() {
for inst in func.stencil.layout.block_insts(block) {
func.stencil.dfg.resolve_aliases_in_arguments(inst);
}
}
}

/// Resolve aliases only if function still crashes after this.
fn try_resolve_aliases(context: &mut CrashCheckContext, func: &mut Function) {
let mut func_with_resolved_aliases = func.clone();
resolve_aliases(&mut func_with_resolved_aliases);
func_with_resolved_aliases.dfg.resolve_all_aliases();
if let CheckResult::Crash(_) = context.check_for_crash(&func_with_resolved_aliases) {
*func = func_with_resolved_aliases;
}
Expand Down
19 changes: 0 additions & 19 deletions cranelift/tests/bugpoint_test_expected.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,11 @@ block0:
v0 = iconst.i64 0
v105 = iconst.i64 0
v829 = iconst.i64 0
v935 -> v829
v962 -> v829
v992 -> v829
v1036 -> v829
v1049 -> v829
v842 = iconst.i64 0
v976 -> v842
v989 -> v842
v1038 -> v842
v1061 -> v842
v883 = iconst.i64 0
v934 -> v883
v961 -> v883
v991 -> v883
v1005 -> v883
v1048 -> v883
v951 = iconst.i64 0
v988 -> v951
v987 = iconst.i64 0
v1052 = iconst.i16 0
v960 -> v1052
v990 -> v1052
v1051 -> v1052
v1055 -> v1052
call fn0(v0, v105, v1052, v883, v829, v987, v951, v842) ; v0 = 0, v105 = 0, v1052 = 0, v883 = 0, v829 = 0, v987 = 0, v951 = 0, v842 = 0
trap user0
}