Skip to content

Commit 76f120b

Browse files
elliotttfitzgen
andauthored
Remove safepoint support (#183)
As we have switched to modeling safepoints in clif directly, it's not longer necessary to track them in RA2. This PR is the first cut at removing safepoints from RA2. Co-authored-by: Nick Fitzgerald <[email protected]> --------- Co-authored-by: Nick Fitzgerald <[email protected]>
1 parent 4c98571 commit 76f120b

File tree

10 files changed

+14
-358
lines changed

10 files changed

+14
-358
lines changed

doc/DESIGN.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -667,12 +667,6 @@ If the requirement indicates that no register is needed (`Unknown` or
667667
bundle already exists for this bundle's spillset, then we move all the
668668
liveranges over to the spill bundle, as described above.
669669

670-
If the requirement indicates that the stack is needed explicitly
671-
(e.g., for a safepoint), we set our spillset as "required" (this will
672-
cause it to allocate a spillslot) and return; because the bundle has
673-
no other allocation set, it will look to the spillset's spillslot by
674-
default.
675-
676670
If the requirement indicates a conflict, we immediately split and
677671
requeue the split pieces. This split is performed at the point at
678672
which the conflict is first introduced, i.e. just before the first use

src/checker.rs

Lines changed: 8 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -518,30 +518,6 @@ impl CheckerState {
518518
self.check_val(inst, *op, *alloc, val, allocs, checker)?;
519519
}
520520
}
521-
&CheckerInst::Safepoint { inst, ref allocs } => {
522-
for &alloc in allocs {
523-
let val = self.get_value(&alloc).unwrap_or(&default_val);
524-
trace!(
525-
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
526-
checkinst,
527-
alloc,
528-
val
529-
);
530-
531-
let reffy = val
532-
.vregs()
533-
.expect("checker value should not be Universe set")
534-
.iter()
535-
.any(|vreg| checker.reftyped_vregs.contains(vreg));
536-
if !reffy {
537-
return Err(CheckerError::NonRefValuesInStackmap {
538-
inst,
539-
alloc,
540-
vregs: val.vregs().unwrap().clone(),
541-
});
542-
}
543-
}
544-
}
545521
&CheckerInst::Move { into, from } => {
546522
// Ensure that the allocator never returns stack-to-stack moves.
547523
let is_stack = |alloc: Allocation| {
@@ -565,7 +541,7 @@ impl CheckerState {
565541
}
566542

567543
/// Update according to instruction.
568-
fn update<'a, F: Function>(&mut self, checkinst: &CheckerInst, checker: &Checker<'a, F>) {
544+
fn update(&mut self, checkinst: &CheckerInst) {
569545
self.become_defined();
570546

571547
match checkinst {
@@ -645,23 +621,6 @@ impl CheckerState {
645621
self.remove_value(&Allocation::reg(*clobber));
646622
}
647623
}
648-
&CheckerInst::Safepoint { ref allocs, .. } => {
649-
for (alloc, value) in self.get_mappings_mut() {
650-
if alloc.is_reg() {
651-
continue;
652-
}
653-
if !allocs.contains(&alloc) {
654-
// Remove all reftyped vregs as labels.
655-
let new_vregs = value
656-
.vregs()
657-
.unwrap()
658-
.difference(&checker.reftyped_vregs)
659-
.cloned()
660-
.collect();
661-
*value = CheckerValue::VRegs(new_vregs);
662-
}
663-
}
664-
}
665624
}
666625
}
667626

@@ -749,10 +708,6 @@ pub(crate) enum CheckerInst {
749708
allocs: Vec<Allocation>,
750709
clobbers: Vec<PReg>,
751710
},
752-
753-
/// A safepoint, with the given Allocations specified as containing
754-
/// reftyped values. All other reftyped values become invalid.
755-
Safepoint { inst: Inst, allocs: Vec<Allocation> },
756711
}
757712

758713
#[derive(Debug)]
@@ -761,7 +716,6 @@ pub struct Checker<'a, F: Function> {
761716
bb_in: FxHashMap<Block, CheckerState>,
762717
bb_insts: FxHashMap<Block, Vec<CheckerInst>>,
763718
edge_insts: FxHashMap<(Block, Block), Vec<CheckerInst>>,
764-
reftyped_vregs: FxHashSet<VReg>,
765719
machine_env: &'a MachineEnv,
766720
stack_pregs: PRegSet,
767721
}
@@ -775,7 +729,6 @@ impl<'a, F: Function> Checker<'a, F> {
775729
let mut bb_in = FxHashMap::default();
776730
let mut bb_insts = FxHashMap::default();
777731
let mut edge_insts = FxHashMap::default();
778-
let mut reftyped_vregs = FxHashSet::default();
779732

780733
for block in 0..f.num_blocks() {
781734
let block = Block::new(block);
@@ -786,10 +739,6 @@ impl<'a, F: Function> Checker<'a, F> {
786739
}
787740
}
788741

789-
for &vreg in f.reftype_vregs() {
790-
reftyped_vregs.insert(vreg);
791-
}
792-
793742
bb_in.insert(f.entry_block(), CheckerState::default());
794743

795744
let mut stack_pregs = PRegSet::empty();
@@ -802,7 +751,6 @@ impl<'a, F: Function> Checker<'a, F> {
802751
bb_in,
803752
bb_insts,
804753
edge_insts,
805-
reftyped_vregs,
806754
machine_env,
807755
stack_pregs,
808756
}
@@ -812,15 +760,6 @@ impl<'a, F: Function> Checker<'a, F> {
812760
/// and allocation results.
813761
pub fn prepare(&mut self, out: &Output) {
814762
trace!("checker: out = {:?}", out);
815-
// Preprocess safepoint stack-maps into per-inst vecs.
816-
let mut safepoint_slots: FxHashMap<Inst, Vec<Allocation>> = FxHashMap::default();
817-
for &(progpoint, slot) in &out.safepoint_slots {
818-
safepoint_slots
819-
.entry(progpoint.inst())
820-
.or_insert_with(|| vec![])
821-
.push(slot);
822-
}
823-
824763
let mut last_inst = None;
825764
for block in 0..self.f.num_blocks() {
826765
let block = Block::new(block);
@@ -829,7 +768,7 @@ impl<'a, F: Function> Checker<'a, F> {
829768
InstOrEdit::Inst(inst) => {
830769
debug_assert!(last_inst.is_none() || inst > last_inst.unwrap());
831770
last_inst = Some(inst);
832-
self.handle_inst(block, inst, &mut safepoint_slots, out);
771+
self.handle_inst(block, inst, out);
833772
}
834773
InstOrEdit::Edit(edit) => self.handle_edit(block, edit),
835774
}
@@ -838,21 +777,7 @@ impl<'a, F: Function> Checker<'a, F> {
838777
}
839778

840779
/// For each original instruction, create an `Op`.
841-
fn handle_inst(
842-
&mut self,
843-
block: Block,
844-
inst: Inst,
845-
safepoint_slots: &mut FxHashMap<Inst, Vec<Allocation>>,
846-
out: &Output,
847-
) {
848-
// If this is a safepoint, then check the spillslots at this point.
849-
if self.f.requires_refs_on_stack(inst) {
850-
let allocs = safepoint_slots.remove(&inst).unwrap_or_else(|| vec![]);
851-
852-
let checkinst = CheckerInst::Safepoint { inst, allocs };
853-
self.bb_insts.get_mut(&block).unwrap().push(checkinst);
854-
}
855-
780+
fn handle_inst(&mut self, block: Block, inst: Inst, out: &Output) {
856781
// Skip normal checks if this is a branch: the blockparams do
857782
// not exist in post-regalloc code, and the edge-moves have to
858783
// be inserted before the branch rather than after.
@@ -931,14 +856,14 @@ impl<'a, F: Function> Checker<'a, F> {
931856
let mut state = self.bb_in.get(&block).cloned().unwrap();
932857
trace!("analyze: block {} has state {:?}", block.index(), state);
933858
for inst in self.bb_insts.get(&block).unwrap() {
934-
state.update(inst, self);
859+
state.update(inst);
935860
trace!("analyze: inst {:?} -> state {:?}", inst, state);
936861
}
937862

938863
for &succ in self.f.block_succs(block) {
939864
let mut new_state = state.clone();
940865
for edge_inst in self.edge_insts.get(&(block, succ)).unwrap() {
941-
new_state.update(edge_inst, self);
866+
new_state.update(edge_inst);
942867
trace!(
943868
"analyze: succ {:?}: inst {:?} -> state {:?}",
944869
succ,
@@ -987,7 +912,7 @@ impl<'a, F: Function> Checker<'a, F> {
987912
trace!("Checker error: {:?}", e);
988913
errors.push(e);
989914
}
990-
state.update(inst, self);
915+
state.update(inst);
991916
if let Err(e) = state.check(InstPosition::After, inst, self) {
992917
trace!("Checker error: {:?}", e);
993918
errors.push(e);
@@ -1021,9 +946,6 @@ impl<'a, F: Function> Checker<'a, F> {
1021946
trace!(" {{ {} }}", s.join(", "))
1022947
}
1023948
}
1024-
for vreg in self.f.reftype_vregs() {
1025-
trace!(" REF: {}", vreg);
1026-
}
1027949
for bb in 0..self.f.num_blocks() {
1028950
let bb = Block::new(bb);
1029951
trace!("block{}:", bb.index());
@@ -1049,18 +971,11 @@ impl<'a, F: Function> Checker<'a, F> {
1049971
&CheckerInst::Move { from, into } => {
1050972
trace!(" {} -> {}", from, into);
1051973
}
1052-
&CheckerInst::Safepoint { ref allocs, .. } => {
1053-
let mut slotargs = vec![];
1054-
for &slot in allocs {
1055-
slotargs.push(format!("{}", slot));
1056-
}
1057-
trace!(" safepoint: {}", slotargs.join(", "));
1058-
}
1059974
&CheckerInst::ParallelMove { .. } => {
1060975
panic!("unexpected parallel_move in body (non-edge)")
1061976
}
1062977
}
1063-
state.update(inst, &self);
978+
state.update(inst);
1064979
print_state(&state);
1065980
}
1066981

@@ -1078,7 +993,7 @@ impl<'a, F: Function> Checker<'a, F> {
1078993
}
1079994
_ => panic!("unexpected edge_inst: not a parallel move"),
1080995
}
1081-
state.update(edge_inst, &self);
996+
state.update(edge_inst);
1082997
print_state(&state);
1083998
}
1084999
}

src/fuzzing/func.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ pub struct InstData {
2626
op: InstOpcode,
2727
operands: Vec<Operand>,
2828
clobbers: Vec<PReg>,
29-
is_safepoint: bool,
3029
}
3130

3231
impl InstData {
@@ -35,15 +34,13 @@ impl InstData {
3534
op: InstOpcode::Branch,
3635
operands: vec![],
3736
clobbers: vec![],
38-
is_safepoint: false,
3937
}
4038
}
4139
pub fn ret() -> InstData {
4240
InstData {
4341
op: InstOpcode::Ret,
4442
operands: vec![],
4543
clobbers: vec![],
46-
is_safepoint: false,
4744
}
4845
}
4946
}
@@ -103,14 +100,6 @@ impl Function for Func {
103100
&self.block_params_out[block.index()][succ][..]
104101
}
105102

106-
fn requires_refs_on_stack(&self, insn: Inst) -> bool {
107-
self.insts[insn.index()].is_safepoint
108-
}
109-
110-
fn reftype_vregs(&self) -> &[VReg] {
111-
&self.reftype_vregs[..]
112-
}
113-
114103
fn debug_value_labels(&self) -> &[(VReg, Inst, Inst, u32)] {
115104
&self.debug_value_labels[..]
116105
}
@@ -515,19 +504,12 @@ impl Func {
515504
)));
516505
}
517506

518-
let is_safepoint = opts.reftypes
519-
&& operands
520-
.iter()
521-
.all(|op| !builder.f.reftype_vregs.contains(&op.vreg()))
522-
&& bool::arbitrary(u)?;
523-
524507
builder.add_inst(
525508
Block::new(block),
526509
InstData {
527510
op: InstOpcode::Op,
528511
operands,
529512
clobbers,
530-
is_safepoint,
531513
},
532514
);
533515
avail.push(vreg);
@@ -583,9 +565,6 @@ impl Func {
583565
impl core::fmt::Debug for Func {
584566
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
585567
write!(f, "{{\n")?;
586-
for vreg in self.reftype_vregs() {
587-
write!(f, " REF: {}\n", vreg)?;
588-
}
589568
for (i, blockrange) in self.blocks.iter().enumerate() {
590569
let succs = self.block_succs[i]
591570
.iter()
@@ -620,9 +599,6 @@ impl core::fmt::Debug for Func {
620599
i, params_in, succs, preds
621600
)?;
622601
for inst in blockrange.iter() {
623-
if self.requires_refs_on_stack(inst) {
624-
write!(f, " -- SAFEPOINT --\n")?;
625-
}
626602
write!(
627603
f,
628604
" inst{}: {:?} ops:{:?} clobber:{:?}\n",

src/ion/data_structures.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@ use crate::cfg::CFGInfo;
1717
use crate::index::ContainerComparator;
1818
use crate::indexset::IndexSet;
1919
use crate::{
20-
define_index, Allocation, Block, Edit, Function, FxHashSet, Inst, MachineEnv, Operand, PReg,
20+
define_index, Allocation, Block, Edit, Function, FxHashSet, MachineEnv, Operand, PReg,
2121
ProgPoint, RegClass, VReg,
2222
};
2323
use alloc::collections::BTreeMap;
2424
use alloc::string::String;
2525
use alloc::vec::Vec;
2626
use core::cmp::Ordering;
2727
use core::fmt::Debug;
28-
use hashbrown::{HashMap, HashSet};
2928
use smallvec::{smallvec, SmallVec};
3029

3130
/// A range from `from` (inclusive) to `to` (exclusive).
@@ -195,8 +194,6 @@ impl Use {
195194
}
196195
}
197196

198-
pub const SLOT_NONE: u8 = u8::MAX;
199-
200197
#[derive(Clone, Debug)]
201198
pub struct LiveBundle {
202199
pub ranges: LiveRangeList,
@@ -315,7 +312,6 @@ pub(crate) const MAX_SPLITS_PER_SPILLSET: u8 = 2;
315312
pub struct VRegData {
316313
pub ranges: LiveRangeList,
317314
pub blockparam: Block,
318-
pub is_ref: bool,
319315
// We don't initially know the RegClass until we observe a use of the VReg.
320316
pub class: Option<RegClass>,
321317
}
@@ -460,8 +456,6 @@ pub struct Env<'a, F: Function> {
460456
pub vregs: VRegs,
461457
pub pregs: Vec<PRegData>,
462458
pub allocation_queue: PrioQueue,
463-
pub safepoints: Vec<Inst>, // Sorted list of safepoint insts.
464-
pub safepoints_per_vreg: HashMap<usize, HashSet<Inst>>,
465459

466460
pub spilled_bundles: Vec<LiveBundleIndex>,
467461
pub spillslots: Vec<SpillSlotData>,
@@ -484,7 +478,6 @@ pub struct Env<'a, F: Function> {
484478
pub allocs: Vec<Allocation>,
485479
pub inst_alloc_offsets: Vec<u32>,
486480
pub num_spillslots: u32,
487-
pub safepoint_slots: Vec<(ProgPoint, Allocation)>,
488481
pub debug_locations: Vec<(u32, ProgPoint, ProgPoint, Allocation)>,
489482

490483
pub allocated_bundle_count: usize,

0 commit comments

Comments
 (0)