Skip to content

Commit 02c5ebc

Browse files
committed
Revert "Sink outgoing block param copies where possible"
This reverts commit 78478ea. Sinking copies that way can be unsound if the outgoing assignment has already been reused by the time execution enters the successor block. The sinking itself can still be done with a more careful check, but it would likely be rather convoluted and I don't want to risk introducing more bugs for such little gain (at least for now). I'm leaving in the verifier changes and cross-block copy refactor because they're still net positive changes in their own right.
1 parent 848ad82 commit 02c5ebc

File tree

6 files changed

+4770
-4809
lines changed

6 files changed

+4770
-4809
lines changed

crates/codegen/src/regalloc/reify.rs

Lines changed: 14 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use alloc::vec::Vec;
55
use cranelift_entity::{packed_option::ReservedValue, EntityRef, PrimaryMap, SecondaryMap};
66
use entity_set::DenseEntitySet;
77
use fx_utils::FxHashMap;
8-
use itertools::Itertools;
98
use log::trace;
109
use smallvec::SmallVec;
1110

@@ -490,21 +489,9 @@ impl<M: MachineRegalloc> RegAllocContext<'_, M> {
490489
) {
491490
trace!("collecting block param copies");
492491

493-
struct BlockParamOut {
494-
block: Block,
495-
vreg: VirtReg,
496-
assignment: CopySourceAssignment,
497-
}
498-
499-
let mut outs = SmallVec::<[BlockParamOut; 4]>::new();
500-
501492
for incoming in block_param_ins {
502493
trace!(" -> {} ({})", incoming.vreg, incoming.block);
503-
504494
let class = self.lir.vreg_class(incoming.vreg);
505-
506-
// Start by collecting sources for this value from all predecessors.
507-
outs.clear();
508495
for &pred in self.cfg_ctx.cfg.block_preds(incoming.block) {
509496
trace!(" {pred}");
510497
let (from_vreg, from_assignment) = *block_param_outs
@@ -513,72 +500,27 @@ impl<M: MachineRegalloc> RegAllocContext<'_, M> {
513500
to_vreg: incoming.vreg,
514501
})
515502
.expect("block param source not recorded for predecessor");
516-
outs.push(BlockParamOut {
517-
block: pred,
518-
vreg: from_vreg,
519-
assignment: from_assignment,
520-
});
521-
}
522-
523-
// Now that we know all outputs from predecessors feeding into this block param, place
524-
// the copies moving them to the correct assignment.
525-
526-
if let Ok(out_assignment) = outs
527-
.iter()
528-
.map(|source| source.assignment)
529-
.all_equal_value()
530-
{
531-
// If the sources all have the same assignment, we can sink the copy into the
532-
// receiving block instead of performing it in every predecessor individually.
533503

504+
// We always insert copies for block params in the predecessor because we know we
505+
// are its unique successor.
506+
let pred_terminator = self.lir.block_terminator(pred);
534507
record_parallel_copy(
535508
copies,
536-
self.lir.block_instrs(incoming.block).start,
537-
ParallelCopyPhase::Before,
509+
pred_terminator,
510+
ParallelCopyPhase::PreCopy,
538511
class,
539-
out_assignment,
512+
from_assignment,
540513
incoming.assignment,
541514
);
542515

543-
// Record a "ghost copy" in each of the predecessors indicating that the source
544-
// belongs to the destination vreg upon exit.
545-
if let Some(out_op_assignment) = out_assignment.as_operand() {
546-
for out in &outs {
547-
assignment.block_exit_ghost_copies.push(BlockExitGhostCopy {
548-
block: out.block,
549-
assignment: out_op_assignment,
550-
from_vreg: out.vreg,
551-
to_vreg: incoming.vreg,
552-
});
553-
}
554-
}
555-
} else {
556-
// Assignments in predecessors weren't identical: perform the copies in each of them
557-
// instead. This is legal because each of those predecessors have only the receiving
558-
// block as a successor.
559-
560-
for out in &outs {
561-
// We always insert copies for block params in the predecessor because we know
562-
// we are its unique successor.
563-
let pred_terminator = self.lir.block_terminator(out.block);
564-
record_parallel_copy(
565-
copies,
566-
pred_terminator,
567-
ParallelCopyPhase::PreCopy,
568-
class,
569-
out.assignment,
570-
incoming.assignment,
571-
);
572-
573-
// Record a ghost copy indicating that the new assignment now belongs to the
574-
// destination vreg and not the source vreg.
575-
assignment.block_exit_ghost_copies.push(BlockExitGhostCopy {
576-
block: out.block,
577-
assignment: incoming.assignment,
578-
from_vreg: out.vreg,
579-
to_vreg: incoming.vreg,
580-
});
581-
}
516+
// Record a "ghost copy" indicating that the new assignment now belongs to the
517+
// destination vreg and not the source vreg.
518+
assignment.block_exit_ghost_copies.push(BlockExitGhostCopy {
519+
block: pred,
520+
assignment: incoming.assignment,
521+
from_vreg,
522+
to_vreg: incoming.vreg,
523+
});
582524
}
583525
}
584526

0 commit comments

Comments
 (0)