Generates a single instruction in the given block.
(&mut self, block: Block, is_first_inst: bool, is_ret: bool)
| 740 | |
| 741 | /// Generates a single instruction in the given block. |
| 742 | fn gen_inst(&mut self, block: Block, is_first_inst: bool, is_ret: bool) -> Result<InstData> { |
| 743 | // These are temporary for the scope of this instruction. |
| 744 | self.early_fixed.clear(); |
| 745 | self.late_fixed.clear(); |
| 746 | self.reuse_operands.clear(); |
| 747 | |
| 748 | let mut inst = InstData { |
| 749 | operands: vec![], |
| 750 | clobbers: vec![], |
| 751 | block, |
| 752 | terminator_kind: None, |
| 753 | is_pure: self.u.arbitrary()?, |
| 754 | }; |
| 755 | |
| 756 | // Add operands which define values. |
| 757 | let mut defined_values = vec![]; |
| 758 | for _ in 0..self.u.int_in_range(self.config.defs_per_inst.clone())? { |
| 759 | if inst.operands.len() >= MAX_INST_OPERANDS { |
| 760 | break; |
| 761 | } |
| 762 | |
| 763 | // Generate a value that was previously used, otherwise generate a |
| 764 | // new dead value. |
| 765 | let value = if self.u.arbitrary()? && !self.defs_by_blocks[block].is_empty() { |
| 766 | self.defs_by_blocks[block].pop().unwrap() |
| 767 | } else { |
| 768 | let bank = RegBank::new(self.u.choose_index(self.reginfo.num_banks())?); |
| 769 | self.new_value(bank)? |
| 770 | }; |
| 771 | let op = self.gen_def( |
| 772 | block, |
| 773 | value, |
| 774 | is_ret, |
| 775 | inst.operands.len(), |
| 776 | &mut defined_values, |
| 777 | )?; |
| 778 | inst.operands.push(op); |
| 779 | } |
| 780 | |
| 781 | let can_generate_uses = !is_first_inst || self.domtree.immediate_dominator(block).is_some(); |
| 782 | if can_generate_uses { |
| 783 | for value in defined_values { |
| 784 | if !self.u.arbitrary()? { |
| 785 | self.add_indirect_remat(value, block, is_first_inst)?; |
| 786 | } |
| 787 | } |
| 788 | } |
| 789 | |
| 790 | // Add operands which use values, unless we are the first instruction of |
| 791 | // a block without a real dominator. In such blocks there is nowhere to |
| 792 | // synthesize a new dominating definition if no reusable value exists. |
| 793 | if can_generate_uses { |
| 794 | for _ in 0..self.u.int_in_range(self.config.uses_per_inst.clone())? { |
| 795 | if inst.operands.len() >= MAX_INST_OPERANDS { |
| 796 | break; |
| 797 | } |
| 798 | let op_idx = inst.operands.len(); |
| 799 | let op = self.gen_use(block, is_first_inst, true, |this| { |
no test coverage detected