[bugpoint] Remove block params

This commit is contained in:
teapotd
2020-04-17 18:27:32 +02:00
committed by Andrew Brown
parent 346a3b8a90
commit aa78811fb2
2 changed files with 109 additions and 54 deletions

View File

@@ -146,22 +146,6 @@ impl ReplaceInstWithConst {
inst: first_inst, inst: first_inst,
} }
} }
fn const_for_type<'f, T: InstBuilder<'f>>(builder: T, ty: ir::Type) -> &'static str {
// Try to keep the result type consistent, and default to an integer type
// otherwise: this will cover all the cases for f32/f64 and integer types, or
// create verifier errors otherwise.
if ty == F32 {
builder.f32const(0.0);
"f32const"
} else if ty == F64 {
builder.f64const(0.0);
"f64const"
} else {
builder.iconst(ty, 0);
"iconst"
}
}
} }
impl Mutator for ReplaceInstWithConst { impl Mutator for ReplaceInstWithConst {
@@ -189,7 +173,7 @@ impl Mutator for ReplaceInstWithConst {
if num_results == 1 { if num_results == 1 {
let ty = func.dfg.value_type(func.dfg.first_result(prev_inst)); let ty = func.dfg.value_type(func.dfg.first_result(prev_inst));
let new_inst_name = Self::const_for_type(func.dfg.replace(prev_inst), ty); let new_inst_name = const_for_type(func.dfg.replace(prev_inst), ty);
return ( return (
func, func,
format!("Replace inst {} with {}.", prev_inst, new_inst_name), format!("Replace inst {} with {}.", prev_inst, new_inst_name),
@@ -212,7 +196,7 @@ impl Mutator for ReplaceInstWithConst {
for r in results { for r in results {
let ty = pos.func.dfg.value_type(r); let ty = pos.func.dfg.value_type(r);
let builder = pos.ins().with_results([Some(r)]); let builder = pos.ins().with_results([Some(r)]);
let new_inst_name = Self::const_for_type(builder, ty); let new_inst_name = const_for_type(builder, ty);
inst_names.push(new_inst_name); inst_names.push(new_inst_name);
} }
@@ -312,6 +296,80 @@ impl Mutator for RemoveBlock {
} }
} }
/// Try to replace the block params with constants.
struct ReplaceBlockParamWithConst {
block: Block,
params_remaining: usize,
}
impl ReplaceBlockParamWithConst {
fn new(func: &Function) -> Self {
let first_block = func.layout.entry_block().unwrap();
Self {
block: first_block,
params_remaining: func.dfg.num_block_params(first_block),
}
}
}
impl Mutator for ReplaceBlockParamWithConst {
fn name(&self) -> &'static str {
"replace block parameter with const"
}
fn mutation_count(&self, func: &Function) -> usize {
func.layout
.blocks()
.map(|block| func.dfg.num_block_params(block))
.sum()
}
fn mutate(&mut self, mut func: Function) -> Option<(Function, String, ProgressStatus)> {
while self.params_remaining == 0 {
self.block = func.layout.next_block(self.block)?;
self.params_remaining = func.dfg.num_block_params(self.block);
}
self.params_remaining -= 1;
let param_index = self.params_remaining;
let param = func.dfg.block_params(self.block)[param_index];
let param_type = func.dfg.value_type(param);
func.dfg.remove_block_param(param);
let first_inst = func.layout.first_inst(self.block).unwrap();
let mut pos = FuncCursor::new(&mut func).at_inst(first_inst);
let builder = pos.ins().with_results([Some(param)]);
let new_inst_name = const_for_type(builder, param_type);
let mut cfg = ControlFlowGraph::new();
cfg.compute(&func);
// Remove parameters in branching instructions that point to this block
for pred in cfg.pred_iter(self.block) {
let inst = &mut func.dfg[pred.inst];
let num_fixed_args = inst.opcode().constraints().num_fixed_value_arguments();
let mut values = inst.take_value_list().unwrap();
values.remove(num_fixed_args + param_index, &mut func.dfg.value_lists);
func.dfg[pred.inst].put_value_list(values);
}
if Some(self.block) == func.layout.entry_block() {
// Entry block params must match function params
func.signature.params.remove(param_index);
}
Some((
func,
format!(
"Replaced param {} of {} by {}",
param, self.block, new_inst_name
),
ProgressStatus::ExpandedOrShrinked,
))
}
}
/// Try to remove unused entities. /// Try to remove unused entities.
struct RemoveUnusedEntities { struct RemoveUnusedEntities {
kind: u32, kind: u32,
@@ -652,6 +710,25 @@ impl Mutator for MergeBlocks {
} }
} }
fn const_for_type<'f, T: InstBuilder<'f>>(builder: T, ty: ir::Type) -> &'static str {
// Try to keep the result type consistent, and default to an integer type
// otherwise: this will cover all the cases for f32/f64, integer and boolean types,
// or create verifier errors otherwise.
if ty == F32 {
builder.f32const(0.0);
"f32const"
} else if ty == F64 {
builder.f64const(0.0);
"f64const"
} else if ty.is_bool() {
builder.bconst(ty, false);
"bconst"
} else {
builder.iconst(ty, 0);
"iconst"
}
}
fn next_inst_ret_prev( fn next_inst_ret_prev(
func: &Function, func: &Function,
block: &mut Block, block: &mut Block,
@@ -722,8 +799,9 @@ fn reduce(
1 => Box::new(ReplaceInstWithConst::new(&func)), 1 => Box::new(ReplaceInstWithConst::new(&func)),
2 => Box::new(ReplaceInstWithTrap::new(&func)), 2 => Box::new(ReplaceInstWithTrap::new(&func)),
3 => Box::new(RemoveBlock::new(&func)), 3 => Box::new(RemoveBlock::new(&func)),
4 => Box::new(RemoveUnusedEntities::new()), 4 => Box::new(ReplaceBlockParamWithConst::new(&func)),
5 => Box::new(MergeBlocks::new(&func)), 5 => Box::new(RemoveUnusedEntities::new()),
6 => Box::new(MergeBlocks::new(&func)),
_ => break, _ => break,
}; };

View File

@@ -1,43 +1,12 @@
function u0:0(i64, i64, i64) system_v { function u0:0() system_v {
sig0 = (i64, i64, i16, i64, i64, i64, i64, i64) system_v sig0 = (i64, i64, i16, i64, i64, i64, i64, i64) system_v
fn0 = u0:95 sig0 fn0 = u0:95 sig0
block0(v0: i64, v1: i64, v2: i64): block0:
v113 -> v1 v0 = iconst.i64 0
v124 -> v1
v136 -> v1
v148 -> v1
v160 -> v1
v185 -> v1
v222 -> v1
v237 -> v1
v241 -> v1
v256 -> v1
v262 -> v1
v105 = iconst.i64 0 v105 = iconst.i64 0
trap user0 trap user0
block99(v804: i64, v1035: i64, v1037: i64, v1039: i64, v1044: i64, v1052: i16, v1057: i64):
v817 -> v1035
v830 -> v1037
v844 -> v1039
v857 -> v1039
v939 -> v1039
v1042 -> v1039
v1050 -> v1039
v908 -> v1044
v917 -> v1044
v921 -> v1044
v1043 -> v1044
v960 -> v1052
v990 -> v1052
v1051 -> v1052
v1055 -> v1052
v963 -> v1057
v1056 -> v1057
v1060 -> v1057
trap user0
block101: block101:
v829 = iconst.i64 0 v829 = iconst.i64 0
v935 -> v829 v935 -> v829
@@ -73,4 +42,12 @@ block117:
v987 = iconst.i64 0 v987 = iconst.i64 0
call fn0(v0, v105, v1052, v883, v829, v987, v951, v842) call fn0(v0, v105, v1052, v883, v829, v987, v951, v842)
trap user0 trap user0
block120:
v1052 = iconst.i16 0
v960 -> v1052
v990 -> v1052
v1051 -> v1052
v1055 -> v1052
trap user0
} }