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

Function duplicate_end_returns

crates/codegen/src/ir.rs:2845–2912  ·  view source on GitHub ↗

Duplicate `LOAD_CONST None + RETURN_VALUE` for blocks that fall through to the final return block.

(blocks: &mut [Block])

Source from the content-addressed store, hash-verified

2843/// Duplicate `LOAD_CONST None + RETURN_VALUE` for blocks that fall through
2844/// to the final return block.
2845fn duplicate_end_returns(blocks: &mut [Block]) {
2846 // Walk the block chain and keep the last non-empty block.
2847 let mut last_block = BlockIdx::NULL;
2848 let mut current = BlockIdx(0);
2849 while current != BlockIdx::NULL {
2850 if !blocks[current.idx()].instructions.is_empty() {
2851 last_block = current;
2852 }
2853 current = blocks[current.idx()].next;
2854 }
2855 if last_block == BlockIdx::NULL {
2856 return;
2857 }
2858
2859 let last_insts = &blocks[last_block.idx()].instructions;
2860 // Only apply when the last block is EXACTLY a return-None epilogue
2861 let is_return_block = last_insts.len() == 2
2862 && matches!(
2863 last_insts[0].instr,
2864 AnyInstruction::Real(Instruction::LoadConst { .. })
2865 )
2866 && matches!(
2867 last_insts[1].instr,
2868 AnyInstruction::Real(Instruction::ReturnValue)
2869 );
2870 if !is_return_block {
2871 return;
2872 }
2873
2874 // Get the return instructions to clone
2875 let return_insts: Vec<InstructionInfo> = last_insts[last_insts.len() - 2..].to_vec();
2876
2877 // Find non-cold blocks that fall through to the last block
2878 let mut blocks_to_fix = Vec::new();
2879 current = BlockIdx(0);
2880 while current != BlockIdx::NULL {
2881 let block = &blocks[current.idx()];
2882 let next = next_nonempty_block(blocks, block.next);
2883 if current != last_block && next == last_block && !block.cold && !block.except_handler {
2884 let last_ins = block.instructions.last();
2885 let has_fallthrough = last_ins
2886 .map(|ins| !ins.instr.is_scope_exit() && !ins.instr.is_unconditional_jump())
2887 .unwrap_or(true);
2888 // Don't duplicate if block already ends with the same return pattern
2889 let already_has_return = block.instructions.len() >= 2 && {
2890 let n = block.instructions.len();
2891 matches!(
2892 block.instructions[n - 2].instr,
2893 AnyInstruction::Real(Instruction::LoadConst { .. })
2894 ) && matches!(
2895 block.instructions[n - 1].instr,
2896 AnyInstruction::Real(Instruction::ReturnValue)
2897 )
2898 };
2899 if has_fallthrough && !already_has_return {
2900 blocks_to_fix.push(current);
2901 }
2902 }

Callers 1

finalize_codeMethod · 0.85

Calls 12

BlockIdxClass · 0.85
newFunction · 0.85
next_nonempty_blockFunction · 0.85
idxMethod · 0.80
to_vecMethod · 0.80
is_scope_exitMethod · 0.80
is_unconditional_jumpMethod · 0.80
is_emptyMethod · 0.45
lenMethod · 0.45
lastMethod · 0.45
mapMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected