Constant folding: fold LOAD_CONST/LOAD_SMALL_INT + BUILD_TUPLE into LOAD_CONST tuple fold_tuple_of_constants
(&mut self)
| 938 | /// Constant folding: fold LOAD_CONST/LOAD_SMALL_INT + BUILD_TUPLE into LOAD_CONST tuple |
| 939 | /// fold_tuple_of_constants |
| 940 | fn fold_tuple_constants(&mut self) { |
| 941 | for block in &mut self.blocks { |
| 942 | let mut i = 0; |
| 943 | while i < block.instructions.len() { |
| 944 | let instr = &block.instructions[i]; |
| 945 | // Look for BUILD_TUPLE |
| 946 | let Some(Instruction::BuildTuple { .. }) = instr.instr.real() else { |
| 947 | i += 1; |
| 948 | continue; |
| 949 | }; |
| 950 | |
| 951 | let tuple_size = u32::from(instr.arg) as usize; |
| 952 | if tuple_size == 0 { |
| 953 | // BUILD_TUPLE 0 → LOAD_CONST () |
| 954 | let (const_idx, _) = self.metadata.consts.insert_full(ConstantData::Tuple { |
| 955 | elements: Vec::new(), |
| 956 | }); |
| 957 | block.instructions[i].instr = Instruction::LoadConst { |
| 958 | consti: Arg::marker(), |
| 959 | } |
| 960 | .into(); |
| 961 | block.instructions[i].arg = OpArg::new(const_idx as u32); |
| 962 | i += 1; |
| 963 | continue; |
| 964 | } |
| 965 | if i < tuple_size { |
| 966 | i += 1; |
| 967 | continue; |
| 968 | } |
| 969 | |
| 970 | // Check if all preceding instructions are constant-loading |
| 971 | let start_idx = i - tuple_size; |
| 972 | let mut elements = Vec::with_capacity(tuple_size); |
| 973 | let mut all_const = true; |
| 974 | |
| 975 | for j in start_idx..i { |
| 976 | let load_instr = &block.instructions[j]; |
| 977 | match load_instr.instr.real() { |
| 978 | Some(Instruction::LoadConst { .. }) => { |
| 979 | let const_idx = u32::from(load_instr.arg) as usize; |
| 980 | if let Some(constant) = |
| 981 | self.metadata.consts.get_index(const_idx).cloned() |
| 982 | { |
| 983 | elements.push(constant); |
| 984 | } else { |
| 985 | all_const = false; |
| 986 | break; |
| 987 | } |
| 988 | } |
| 989 | Some(Instruction::LoadSmallInt { .. }) => { |
| 990 | // arg is the i32 value stored as u32 (two's complement) |
| 991 | let value = u32::from(load_instr.arg) as i32; |
| 992 | elements.push(ConstantData::Integer { |
| 993 | value: BigInt::from(value), |
| 994 | }); |
| 995 | } |
| 996 | _ => { |
| 997 | all_const = false; |