flowgraph.c inline_small_or_no_lineno_blocks
(blocks: &mut [Block])
| 2568 | |
| 2569 | /// flowgraph.c inline_small_or_no_lineno_blocks |
| 2570 | fn inline_small_or_no_lineno_blocks(blocks: &mut [Block]) { |
| 2571 | const MAX_COPY_SIZE: usize = 4; |
| 2572 | |
| 2573 | let block_exits_scope = |block: &Block| { |
| 2574 | block |
| 2575 | .instructions |
| 2576 | .last() |
| 2577 | .is_some_and(|ins| ins.instr.is_scope_exit()) |
| 2578 | }; |
| 2579 | let block_has_no_lineno = |block: &Block| { |
| 2580 | block |
| 2581 | .instructions |
| 2582 | .iter() |
| 2583 | .all(|ins| !instruction_has_lineno(ins)) |
| 2584 | }; |
| 2585 | |
| 2586 | loop { |
| 2587 | let mut changes = false; |
| 2588 | let mut current = BlockIdx(0); |
| 2589 | while current != BlockIdx::NULL { |
| 2590 | let next = blocks[current.idx()].next; |
| 2591 | let Some(last) = blocks[current.idx()].instructions.last().copied() else { |
| 2592 | current = next; |
| 2593 | continue; |
| 2594 | }; |
| 2595 | if !last.instr.is_unconditional_jump() || last.target == BlockIdx::NULL { |
| 2596 | current = next; |
| 2597 | continue; |
| 2598 | } |
| 2599 | |
| 2600 | let target = last.target; |
| 2601 | let small_exit_block = block_exits_scope(&blocks[target.idx()]) |
| 2602 | && blocks[target.idx()].instructions.len() <= MAX_COPY_SIZE; |
| 2603 | let no_lineno_no_fallthrough = block_has_no_lineno(&blocks[target.idx()]) |
| 2604 | && !block_has_fallthrough(&blocks[target.idx()]); |
| 2605 | |
| 2606 | if small_exit_block || no_lineno_no_fallthrough { |
| 2607 | if let Some(last_instr) = blocks[current.idx()].instructions.last_mut() { |
| 2608 | last_instr.instr = Instruction::Nop.into(); |
| 2609 | last_instr.arg = OpArg::new(0); |
| 2610 | last_instr.target = BlockIdx::NULL; |
| 2611 | } |
| 2612 | let appended = blocks[target.idx()].instructions.clone(); |
| 2613 | blocks[current.idx()].instructions.extend(appended); |
| 2614 | changes = true; |
| 2615 | } |
| 2616 | |
| 2617 | current = next; |
| 2618 | } |
| 2619 | |
| 2620 | if !changes { |
| 2621 | break; |
| 2622 | } |
| 2623 | } |
| 2624 | } |
| 2625 | |
| 2626 | /// Follow chain of empty blocks to find first non-empty block. |
| 2627 | fn next_nonempty_block(blocks: &[Block], mut idx: BlockIdx) -> BlockIdx { |
no test coverage detected