MCPcopy Index your code
hub / github.com/RustPython/RustPython / fold_binop_constants

Method fold_binop_constants

crates/codegen/src/ir.rs:710–769  ·  view source on GitHub ↗

Constant folding: fold LOAD_CONST/LOAD_SMALL_INT + LOAD_CONST/LOAD_SMALL_INT + BINARY_OP into a single LOAD_CONST when the result is computable at compile time. = fold_binops_on_constants in CPython flowgraph.c

(&mut self)

Source from the content-addressed store, hash-verified

708 /// into a single LOAD_CONST when the result is computable at compile time.
709 /// = fold_binops_on_constants in CPython flowgraph.c
710 fn fold_binop_constants(&mut self) {
711 use oparg::BinaryOperator as BinOp;
712
713 for block in &mut self.blocks {
714 let mut i = 0;
715 while i + 2 < block.instructions.len() {
716 // Check pattern: LOAD_CONST/LOAD_SMALL_INT, LOAD_CONST/LOAD_SMALL_INT, BINARY_OP
717 let Some(Instruction::BinaryOp { .. }) = block.instructions[i + 2].instr.real()
718 else {
719 i += 1;
720 continue;
721 };
722
723 let op_raw = u32::from(block.instructions[i + 2].arg);
724 let Ok(op) = BinOp::try_from(op_raw) else {
725 i += 1;
726 continue;
727 };
728
729 let left = Self::get_const_value_from(&self.metadata, &block.instructions[i]);
730 let right = Self::get_const_value_from(&self.metadata, &block.instructions[i + 1]);
731
732 let (Some(left_val), Some(right_val)) = (left, right) else {
733 i += 1;
734 continue;
735 };
736
737 let result = Self::eval_binop(&left_val, &right_val, op);
738
739 if let Some(result_const) = result {
740 // Check result size limit (CPython limits to 4096 bytes)
741 if Self::const_too_big(&result_const) {
742 i += 1;
743 continue;
744 }
745 let (const_idx, _) = self.metadata.consts.insert_full(result_const);
746 // Replace first instruction with LOAD_CONST result
747 block.instructions[i].instr = Instruction::LoadConst {
748 consti: Arg::marker(),
749 }
750 .into();
751 block.instructions[i].arg = OpArg::new(const_idx as u32);
752 // NOP out the second and third instructions
753 let loc = block.instructions[i].location;
754 let end_loc = block.instructions[i].end_location;
755 block.instructions[i + 1].instr = Instruction::Nop.into();
756 block.instructions[i + 1].location = loc;
757 block.instructions[i + 1].end_location = end_loc;
758 block.instructions[i + 2].instr = Instruction::Nop.into();
759 block.instructions[i + 2].location = loc;
760 block.instructions[i + 2].end_location = end_loc;
761 // Don't advance - check if the result can be folded again
762 // (e.g., 2 ** 31 - 1)
763 i = i.saturating_sub(1); // re-check with previous instruction
764 } else {
765 i += 1;
766 }
767 }

Callers 1

finalize_codeMethod · 0.80

Calls 3

newFunction · 0.85
lenMethod · 0.45
realMethod · 0.45

Tested by

no test coverage detected