Compare commits

..

3 Commits

Author SHA1 Message Date
T0b1
3f93c5f698 changes 2023-04-15 05:04:07 +02:00
T0b1
afb8d61c87 changes 2023-04-15 05:00:52 +02:00
T0b1
a31407c991 maybe better blockorder impl 2023-04-15 04:18:14 +02:00
12 changed files with 80 additions and 118 deletions

25
Cargo.lock generated
View File

@@ -607,7 +607,7 @@ dependencies = [
"cranelift-isle",
"criterion",
"gimli",
"hashbrown 0.13.2",
"hashbrown 0.13.1",
"log",
"regalloc2",
"serde",
@@ -677,7 +677,7 @@ name = "cranelift-frontend"
version = "0.96.0"
dependencies = [
"cranelift-codegen",
"hashbrown 0.13.2",
"hashbrown 0.13.1",
"log",
"similar",
"smallvec",
@@ -747,7 +747,7 @@ dependencies = [
"anyhow",
"cranelift-codegen",
"cranelift-control",
"hashbrown 0.13.2",
"hashbrown 0.13.1",
]
[[package]]
@@ -837,7 +837,7 @@ dependencies = [
"cranelift-codegen",
"cranelift-entity",
"cranelift-frontend",
"hashbrown 0.13.2",
"hashbrown 0.13.1",
"itertools",
"log",
"serde",
@@ -1498,9 +1498,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.13.2"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
dependencies = [
"ahash",
]
@@ -2049,7 +2049,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"crc32fast",
"hashbrown 0.13.2",
"hashbrown 0.13.1",
"indexmap",
"memchr",
]
@@ -2578,10 +2578,11 @@ dependencies = [
[[package]]
name = "regalloc2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80535183cae11b149d618fbd3c37e38d7cda589d82d7769e196ca9a9042d7621"
dependencies = [
"hashbrown 0.13.2",
"fxhash",
"log",
"rustc-hash",
"serde",
"slice-group-by",
"smallvec",
@@ -2673,12 +2674,6 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.36.8"

View File

@@ -84,9 +84,6 @@ anyhow = { workspace = true }
[profile.release.build-override]
opt-level = 0
[profile.release]
debug = true
[workspace]
resolver = '2'
members = [

View File

@@ -27,7 +27,7 @@ serde = { version = "1.0.94", features = ["derive"], optional = true }
bincode = { version = "1.2.1", optional = true }
gimli = { workspace = true, features = ["write"], optional = true }
smallvec = { workspace = true }
regalloc2 = { path = "../../../regalloc2/", features = ["checker", "trace-log"] }
regalloc2 = { version = "0.6.1", features = ["checker"] }
souper-ir = { version = "2.1.0", optional = true }
sha2 = { version = "0.10.2", optional = true }
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.

View File

@@ -230,7 +230,6 @@ pub fn create_reg_env(flags: &settings::Flags) -> MachineEnv {
],
],
fixed_stack_slots: vec![],
scratch_by_class: [None, None],
};
if !flags.enable_pinned_reg() {

View File

@@ -182,7 +182,6 @@ pub fn crate_reg_eviroment(_flags: &settings::Flags) -> MachineEnv {
preferred_regs_by_class,
non_preferred_regs_by_class,
fixed_stack_slots: vec![],
scratch_by_class: [None, None],
}
}

View File

@@ -151,7 +151,6 @@ pub fn create_machine_env(_flags: &settings::Flags) -> MachineEnv {
],
],
fixed_stack_slots: vec![],
scratch_by_class: [None, None],
}
}

View File

@@ -203,7 +203,6 @@ pub(crate) fn create_reg_env_systemv(flags: &settings::Flags) -> MachineEnv {
vec![],
],
fixed_stack_slots: vec![],
scratch_by_class: [None, None]
};
debug_assert_eq!(r15(), pinned_reg());

View File

@@ -81,15 +81,6 @@ pub struct BlockLoweringOrder {
/// Ranges in `lowered_succ_indices` giving the successor lists for each lowered
/// block. Indexed by lowering-order index (`BlockIndex`).
lowered_succ_ranges: Vec<(Option<Inst>, std::ops::Range<usize>)>,
/// Cold blocks. These blocks are not reordered in the
/// `lowered_order` above; the lowered order must respect RPO
/// (uses after defs) in order for lowering to be
/// correct. Instead, this set is used to provide `is_cold()`,
/// which is used by VCode emission to sink the blocks at the last
/// moment (when we actually emit bytes into the MachBuffer).
cold_blocks: FxHashSet<BlockIndex>,
/// Lowered blocks that are indirect branch targets.
indirect_branch_targets: FxHashSet<BlockIndex>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -98,6 +89,15 @@ pub enum LoweredBlock {
Orig {
/// Original CLIF block.
block: Block,
/// Cold block. These blocks are not reordered in the
/// `lowered_order` above; the lowered order must respect RPO
/// (uses after defs) in order for lowering to be
/// correct. Instead, this bool is used to provide `is_cold()`,
/// which is used by VCode emission to sink the blocks at the last
/// moment (when we actually emit bytes into the MachBuffer).
cold: bool,
/// Target of indirect branch
indirect_branch_target: bool,
},
/// Critical edge between two CLIF blocks.
@@ -112,6 +112,11 @@ pub enum LoweredBlock {
/// indexing order as `inst_predicates::visit_block_succs`. This is used to distinguish
/// multiple edges between the same CLIF blocks.
succ_idx: u32,
/// See [LoweredBlock::orig]
cold: bool,
/// See [LoweredBlock::orig]
indirect_branch_target: bool,
},
}
@@ -119,7 +124,7 @@ impl LoweredBlock {
/// Unwrap an `Orig` block.
pub fn orig_block(&self) -> Option<Block> {
match self {
&LoweredBlock::Orig { block } => Some(block),
&LoweredBlock::Orig { block, .. } => Some(block),
&LoweredBlock::CriticalEdge { .. } => None,
}
}
@@ -141,6 +146,20 @@ impl LoweredBlock {
&LoweredBlock::Orig { .. } => None,
}
}
pub fn is_cold(&self) -> bool {
match self {
&LoweredBlock::CriticalEdge { cold, .. } => cold,
&LoweredBlock::Orig { cold, .. } => cold
}
}
pub fn is_indirect_branch_target(&self) -> bool {
match self {
&LoweredBlock::CriticalEdge { indirect_branch_target, .. } => indirect_branch_target,
&LoweredBlock::Orig { indirect_branch_target, .. } => indirect_branch_target
}
}
}
impl BlockLoweringOrder {
@@ -165,7 +184,7 @@ impl BlockLoweringOrder {
visit_block_succs(f, block, |_, succ, from_table| {
block_out_count[block] += 1;
block_in_count[succ] += 1;
block_succs.push(LoweredBlock::Orig { block: succ });
block_succs.push(LoweredBlock::Orig { block: succ, cold: f.layout.is_cold(succ), indirect_branch_target: false });
if from_table {
indirect_branch_target_clif_blocks.insert(succ);
@@ -192,7 +211,7 @@ impl BlockLoweringOrder {
let mut lowered_order = Vec::new();
for &block in domtree.cfg_postorder().iter().rev() {
let lb = LoweredBlock::Orig { block };
let lb = LoweredBlock::Orig { block, cold: f.layout.is_cold(block), indirect_branch_target: indirect_branch_target_clif_blocks.contains(&block) };
let bindex = BlockIndex::new(lowered_order.len());
lb_to_bindex.insert(lb.clone(), bindex);
lowered_order.push(lb);
@@ -208,6 +227,10 @@ impl BlockLoweringOrder {
pred: block,
succ,
succ_idx: succ_ix as u32,
// Edges inherit indirect branch and cold block metadata from their
// successor.
cold: f.layout.is_cold(succ),
indirect_branch_target: indirect_branch_target_clif_blocks.contains(&succ)
};
let bindex = BlockIndex::new(lowered_order.len());
lb_to_bindex.insert(*lb, bindex);
@@ -221,8 +244,6 @@ impl BlockLoweringOrder {
// during the creation of `lowering_order`, as we need `lb_to_bindex` to be fully populated
// first.
let mut lowered_succ_indices = Vec::new();
let mut cold_blocks = FxHashSet::default();
let mut indirect_branch_targets = FxHashSet::default();
let lowered_succ_ranges =
Vec::from_iter(lowered_order.iter().enumerate().map(|(ix, lb)| {
let bindex = BlockIndex::new(ix);
@@ -230,18 +251,24 @@ impl BlockLoweringOrder {
let opt_inst = match lb {
// Block successors are pulled directly over, as they'll have been mutated when
// determining the block order already.
&LoweredBlock::Orig { block } => {
&LoweredBlock::Orig { block, .. } => {
let range = block_succ_range[block].clone();
lowered_succ_indices
.extend(block_succs[range].iter().map(|lb| lb_to_bindex[lb]));
if f.layout.is_cold(block) {
cold_blocks.insert(bindex);
}
if indirect_branch_target_clif_blocks.contains(&block) {
indirect_branch_targets.insert(bindex);
}
.extend(block_succs[range].iter().map(|lb| {
match lb {
LoweredBlock::Orig { block, cold, .. } => {
match lb_to_bindex.get(&LoweredBlock::Orig { block: *block, cold: *cold, indirect_branch_target: indirect_branch_target_clif_blocks.contains(block) } ) {
Some(idx) => *idx,
None => {
panic!("Trying to hashlookup {:?} in HashMap: {:?}", lb, lb_to_bindex);
}
}
},
LoweredBlock::CriticalEdge { .. } => {
lb_to_bindex[&lb]
}
}
}));
let last = f.layout.last_inst(block).unwrap();
let opcode = f.dfg.insts[last].opcode();
@@ -253,21 +280,10 @@ impl BlockLoweringOrder {
// Critical edges won't have successor information in block_succ_range, but
// they only have a single known successor to record anyway.
&LoweredBlock::CriticalEdge { succ, .. } => {
let succ_index = lb_to_bindex[&LoweredBlock::Orig { block: succ }];
&LoweredBlock::CriticalEdge { succ, cold, indirect_branch_target, .. } => {
let succ_index = lb_to_bindex[&LoweredBlock::Orig { block: succ, cold, indirect_branch_target }];
lowered_succ_indices.push(succ_index);
// Edges inherit indirect branch and cold block metadata from their
// successor.
if f.layout.is_cold(succ) {
cold_blocks.insert(bindex);
}
if indirect_branch_target_clif_blocks.contains(&succ) {
indirect_branch_targets.insert(bindex);
}
None
}
};
@@ -278,9 +294,7 @@ impl BlockLoweringOrder {
let result = BlockLoweringOrder {
lowered_order,
lowered_succ_indices,
lowered_succ_ranges,
cold_blocks,
indirect_branch_targets,
lowered_succ_ranges
};
trace!("BlockLoweringOrder: {:#?}", result);
@@ -300,13 +314,13 @@ impl BlockLoweringOrder {
/// Determine whether the given lowered-block index is cold.
pub fn is_cold(&self, block: BlockIndex) -> bool {
self.cold_blocks.contains(&block)
self.lowered_order[block.index()].is_cold()
}
/// Determine whether the given lowered block index is an indirect branch
/// target.
pub fn is_indirect_branch_target(&self, block: BlockIndex) -> bool {
self.indirect_branch_targets.contains(&block)
self.lowered_order[block.index()].is_indirect_branch_target()
}
}

View File

@@ -51,7 +51,6 @@ pub fn compile<B: LowerBackend + TargetIsa>(
let _tt = timing::regalloc();
let mut options = RegallocOptions::default();
options.verbose_log = b.flags().regalloc_verbose_logs();
options.fast_alloc = true;
if cfg!(debug_assertions) {
options.validate_ssa = true;

View File

@@ -771,7 +771,6 @@ impl<I: VCodeInst> VCode<I> {
{
// To write into disasm string.
use core::fmt::Write;
let want_disasm = true;
let _tt = timing::vcode_emit();
let mut buffer = MachBuffer::new();
@@ -909,7 +908,6 @@ impl<I: VCodeInst> VCode<I> {
for inst_or_edit in regalloc.block_insts_and_edits(&self, block) {
match inst_or_edit {
InstOrEdit::Inst(iix) => {
trace!("Emitting inst {}", iix.index());
if !self.debug_value_labels.is_empty() {
// If we need to produce debug info,
// record the offset of each instruction
@@ -935,7 +933,7 @@ impl<I: VCodeInst> VCode<I> {
// and they come out the other end, if
// still needed (not elided), as
// regalloc-inserted moves.
//continue;
continue;
}
// Update the srcloc at this point in the buffer.
@@ -1011,7 +1009,6 @@ impl<I: VCodeInst> VCode<I> {
// immediately emit it.
match (from.as_reg(), to.as_reg()) {
(Some(from), Some(to)) => {
trace!("Emitting move from {} to {}", from, to);
// Reg-to-reg move.
let from_rreg = Reg::from(from);
let to_rreg = Writable::from_reg(Reg::from(to));
@@ -1021,7 +1018,6 @@ impl<I: VCodeInst> VCode<I> {
do_emit(&mv, &[], &mut disasm, &mut buffer, &mut state);
}
(Some(from), None) => {
trace!("Emitting move from {} to slot {}", from, to.as_stack().unwrap().index());
// Spill from register to spillslot.
let to = to.as_stack().unwrap();
let from_rreg = RealReg::from(from);
@@ -1029,7 +1025,6 @@ impl<I: VCodeInst> VCode<I> {
do_emit(&spill, &[], &mut disasm, &mut buffer, &mut state);
}
(None, Some(to)) => {
trace!("Emitting move from slot {} to {}", from.as_stack().unwrap().index(), to);
// Load from spillslot to register.
let from = from.as_stack().unwrap();
let to_rreg = Writable::from_reg(RealReg::from(to));
@@ -1105,10 +1100,6 @@ impl<I: VCodeInst> VCode<I> {
self.compute_value_labels_ranges(regalloc, &inst_offsets[..], func_body_len);
let frame_size = self.abi.frame_size();
if want_disasm {
trace!("Disassembly:\n{}", disasm);
}
EmitResult {
buffer,
bb_offsets,
@@ -1291,6 +1282,14 @@ impl<I: VCodeInst> RegallocFunction for VCode<I> {
self.insts[insn.index()].is_safepoint()
}
fn is_move(&self, insn: InsnIndex) -> Option<(Operand, Operand)> {
let (a, b) = self.is_move.get(&insn)?;
Some((
self.assert_operand_not_vreg_alias(*a),
self.assert_operand_not_vreg_alias(*b),
))
}
fn inst_operands(&self, insn: InsnIndex) -> &[Operand] {
let (start, end) = self.operand_ranges[insn.index()];
let ret = &self.operands[start as usize..end as usize];
@@ -1350,39 +1349,12 @@ impl<I: VCodeInst> fmt::Debug for VCode<I> {
for block in 0..self.num_blocks() {
let block = BlockIndex::new(block);
write!(f, "Block {}(", block.index())?;
{
let mut first = true;
for vreg in self.block_params(block) {
if !first {
write!(f, ", ")?;
} else {
first = false;
}
write!(f, "{}", vreg)?;
}
}
writeln!(f, "):")?;
writeln!(f, "Block {}:", block.index())?;
if let Some(bb) = self.bindex_to_bb(block) {
writeln!(f, " (original IR block: {})", bb)?;
}
for (i, succ) in self.succs(block).iter().enumerate() {
let last_inst = self.block_insns(block).last();
if self.is_branch(last_inst) {
write!(f, " (successor: Block {}(", succ.index())?;
let mut first = true;
for vreg in self.branch_blockparams(block, last_inst, i) {
if !first {
write!(f, ", ")?;
} else {
first = false;
}
write!(f, "{}", vreg)?;
}
writeln!(f, "))")?;
} else {
write!(f, " (successor: Block {})", succ.index())?;
}
for succ in self.succs(block) {
writeln!(f, " (successor: Block {})", succ.index())?;
}
let (start, end) = self.block_ranges[block.index()];
writeln!(

View File

@@ -17,7 +17,6 @@ use std::cmp::max;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use thiserror::Error;
use log::trace;
const TESTFILE_NAMESPACE: u32 = 0;
@@ -192,7 +191,6 @@ impl TestFileCompiler {
// First, rename the function
let func_original_name = func.name;
func.name = UserFuncName::User(defined_func.new_name.clone());
trace!("Rename func from '{}' to '{}'", func_original_name, func.name);
// Rename any functions that it references
// Do this in stages to appease the borrow checker
@@ -235,10 +233,6 @@ impl TestFileCompiler {
.get(&func.name)
.ok_or(anyhow!("Undeclared function {} found!", &func.name))?;
if log::log_enabled!(log::Level::Trace) {
self.ctx.set_disasm(true);
}
self.ctx.func = self.apply_func_rename(func, defined_func)?;
self.module.define_function_with_control_plane(
defined_func.func_id,
@@ -283,11 +277,6 @@ impl TestFileCompiler {
// available).
self.module.finalize_definitions()?;
for (name, func) in self.defined_functions.iter() {
let ptr = self.module.get_finalized_function(func.func_id);
trace!("Function '{}' at {:#X}", name, ptr as u64);
}
Ok(CompiledTestFile {
module: Some(self.module),
defined_functions: self.defined_functions,

View File

@@ -17,7 +17,7 @@ target-lexicon = { workspace = true, features = ["std"] }
# In the next iteration we'll factor out the common bits so that they can be consumed
# by Cranelift and Winch.
cranelift-codegen = { workspace = true }
regalloc2 = { path = "../../../regalloc2" }
regalloc2 = "0.6.0"
gimli = { workspace = true }
[features]