From aa78811fb26e3dfa9ad6270d0456b9d4647d87b0 Mon Sep 17 00:00:00 2001 From: teapotd Date: Fri, 17 Apr 2020 18:27:32 +0200 Subject: [PATCH] [bugpoint] Remove block params --- cranelift/src/bugpoint.rs | 118 ++++++++++++++++---- cranelift/tests/bugpoint_test_expected.clif | 45 ++------ 2 files changed, 109 insertions(+), 54 deletions(-) diff --git a/cranelift/src/bugpoint.rs b/cranelift/src/bugpoint.rs index 6848a053b2..fdb93125d5 100644 --- a/cranelift/src/bugpoint.rs +++ b/cranelift/src/bugpoint.rs @@ -146,22 +146,6 @@ impl ReplaceInstWithConst { 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 { @@ -189,7 +173,7 @@ impl Mutator for ReplaceInstWithConst { if num_results == 1 { 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 ( func, format!("Replace inst {} with {}.", prev_inst, new_inst_name), @@ -212,7 +196,7 @@ impl Mutator for ReplaceInstWithConst { for r in results { let ty = pos.func.dfg.value_type(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); } @@ -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. struct RemoveUnusedEntities { 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( func: &Function, block: &mut Block, @@ -722,8 +799,9 @@ fn reduce( 1 => Box::new(ReplaceInstWithConst::new(&func)), 2 => Box::new(ReplaceInstWithTrap::new(&func)), 3 => Box::new(RemoveBlock::new(&func)), - 4 => Box::new(RemoveUnusedEntities::new()), - 5 => Box::new(MergeBlocks::new(&func)), + 4 => Box::new(ReplaceBlockParamWithConst::new(&func)), + 5 => Box::new(RemoveUnusedEntities::new()), + 6 => Box::new(MergeBlocks::new(&func)), _ => break, }; diff --git a/cranelift/tests/bugpoint_test_expected.clif b/cranelift/tests/bugpoint_test_expected.clif index b2ca38a064..86a7405feb 100644 --- a/cranelift/tests/bugpoint_test_expected.clif +++ b/cranelift/tests/bugpoint_test_expected.clif @@ -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 fn0 = u0:95 sig0 -block0(v0: i64, v1: i64, v2: i64): - v113 -> v1 - v124 -> v1 - v136 -> v1 - v148 -> v1 - v160 -> v1 - v185 -> v1 - v222 -> v1 - v237 -> v1 - v241 -> v1 - v256 -> v1 - v262 -> v1 +block0: + v0 = iconst.i64 0 v105 = iconst.i64 0 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: v829 = iconst.i64 0 v935 -> v829 @@ -73,4 +42,12 @@ block117: v987 = iconst.i64 0 call fn0(v0, v105, v1052, v883, v829, v987, v951, v842) trap user0 + +block120: + v1052 = iconst.i16 0 + v960 -> v1052 + v990 -> v1052 + v1051 -> v1052 + v1055 -> v1052 + trap user0 }