diff --git a/cranelift/src/bugpoint.rs b/cranelift/src/bugpoint.rs index fdb93125d5..28e0f704a8 100644 --- a/cranelift/src/bugpoint.rs +++ b/cranelift/src/bugpoint.rs @@ -258,6 +258,58 @@ impl Mutator for ReplaceInstWithTrap { } } +/// Try to move instructions to entry block. +struct MoveInstToEntryBlock { + block: Block, + inst: Inst, +} + +impl MoveInstToEntryBlock { + fn new(func: &Function) -> Self { + let first_block = func.layout.entry_block().unwrap(); + let first_inst = func.layout.first_inst(first_block).unwrap(); + Self { + block: first_block, + inst: first_inst, + } + } +} + +impl Mutator for MoveInstToEntryBlock { + fn name(&self) -> &'static str { + "move inst to entry block" + } + + fn mutation_count(&self, func: &Function) -> usize { + inst_count(func) + } + + fn mutate(&mut self, mut func: Function) -> Option<(Function, String, ProgressStatus)> { + next_inst_ret_prev(&func, &mut self.block, &mut self.inst).map(|(prev_block, prev_inst)| { + // Don't move instructions that are already in entry block + // and instructions that end blocks. + let first_block = func.layout.entry_block().unwrap(); + if first_block == prev_block || self.block != prev_block { + return ( + func, + format!("did nothing for {}", prev_inst), + ProgressStatus::Skip, + ); + } + + let last_inst_of_first_block = func.layout.last_inst(first_block).unwrap(); + func.layout.remove_inst(prev_inst); + func.layout.insert_inst(prev_inst, last_inst_of_first_block); + + ( + func, + format!("Move inst {} to entry block", prev_inst), + ProgressStatus::ExpandedOrShrinked, + ) + }) + } +} + /// Try to remove a block. struct RemoveBlock { block: Block, @@ -798,10 +850,11 @@ fn reduce( 0 => Box::new(RemoveInst::new(&func)), 1 => Box::new(ReplaceInstWithConst::new(&func)), 2 => Box::new(ReplaceInstWithTrap::new(&func)), - 3 => Box::new(RemoveBlock::new(&func)), - 4 => Box::new(ReplaceBlockParamWithConst::new(&func)), - 5 => Box::new(RemoveUnusedEntities::new()), - 6 => Box::new(MergeBlocks::new(&func)), + 3 => Box::new(MoveInstToEntryBlock::new(&func)), + 4 => Box::new(RemoveBlock::new(&func)), + 5 => Box::new(ReplaceBlockParamWithConst::new(&func)), + 6 => Box::new(RemoveUnusedEntities::new()), + 7 => Box::new(MergeBlocks::new(&func)), _ => break, }; diff --git a/cranelift/tests/bugpoint_test_expected.clif b/cranelift/tests/bugpoint_test_expected.clif index 86a7405feb..308863d9f7 100644 --- a/cranelift/tests/bugpoint_test_expected.clif +++ b/cranelift/tests/bugpoint_test_expected.clif @@ -5,49 +5,31 @@ function u0:0() system_v { block0: v0 = iconst.i64 0 v105 = iconst.i64 0 - trap user0 - -block101: v829 = iconst.i64 0 v935 -> v829 v962 -> v829 v992 -> v829 v1036 -> v829 v1049 -> v829 - trap user0 - -block102: v842 = iconst.i64 0 v976 -> v842 v989 -> v842 v1038 -> v842 v1061 -> v842 - trap user0 - -block105: v883 = iconst.i64 0 v934 -> v883 v961 -> v883 v991 -> v883 v1005 -> v883 v1048 -> v883 - trap user0 - -block114: v951 = iconst.i64 0 v988 -> v951 - trap user0 - -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 + call fn0(v0, v105, v1052, v883, v829, v987, v951, v842) trap user0 }