Helper to simulate block execution for dataflow analysis OR transformation When used for analysis, it just calculates the output state. When used for transformation, it produces new instructions.
(
info: &BasicBlockInfo,
initial_state: &ConstantMap,
transform: bool, // If true, generate new instructions; otherwise, just calculate state
_data_types: &HashMap<String, DataType>, /
| 138 | |
| 139 | let mut simplified_algebraically = false; |
| 140 | |
| 141 | if is_zero(&new_op2) { |
| 142 | // a + 0 = a |
| 143 | optimised_instruction = Instruction::Move { |
| 144 | dest: dest.clone(), |
| 145 | src: new_op1.clone(), |
| 146 | }; |
| 147 | update_state_based_on_operand( |
| 148 | &mut current_state, |
| 149 | dest, |
| 150 | &new_op1, |
| 151 | initial_state, |
| 152 | ); |
| 153 | simplified_algebraically = true; |
| 154 | } else if is_zero(&new_op1) { |
| 155 | // 0 + a = a |
| 156 | optimised_instruction = Instruction::Move { |
| 157 | dest: dest.clone(), |
| 158 | src: new_op2.clone(), |
| 159 | }; |
| 160 | update_state_based_on_operand( |
| 161 | &mut current_state, |
| 162 | dest, |
| 163 | &new_op2, |
| 164 | initial_state, |
| 165 | ); |
| 166 | simplified_algebraically = true; |
| 167 | } |
| 168 | |
| 169 | if !simplified_algebraically && let (Some(c1), Some(c2)) = (const1, const2) { |
| 170 | if let Some(result_const) = interpret::add_constants(c1, c2) { |
| 171 | current_state.insert(dest.clone(), result_const.clone()); |
| 172 | // If transforming, replace Add with Move constant |
| 173 | if transform { |
| 174 | optimised_instruction = Instruction::Move { |
| 175 | dest: dest.clone(), |
| 176 | src: Operand::Constant(result_const), |
| 177 | }; |
| 178 | } else { |
| 179 | keep_original_instruction = false; |
| 180 | } |
| 181 | } else { |
| 182 | // Calculation failed -> result not constant |
| 183 | current_state.remove(dest); |
| 184 | } |
| 185 | } else if !simplified_algebraically { |
| 186 | // Operands not both constant, and no simplification -> result is not constant |
| 187 | current_state.remove(dest); |
| 188 | } |
| 189 | // If simplified_algebraically, state already updated, instruction is Move |
| 190 | } |
| 191 | |
| 192 | Instruction::Sub { dest, op1, op2 } => { |
| 193 | let const1 = lookup_const(op1, ¤t_state); |
| 194 | let const2 = lookup_const(op2, ¤t_state); |
| 195 | let new_op1 = const1.clone().map_or(op1.clone(), Operand::Constant); |
| 196 | let new_op2 = const2.clone().map_or(op2.clone(), Operand::Constant); |
| 197 |
no test coverage detected