Switch Cranelift over to regalloc2. (#3989)
This PR switches Cranelift over to the new register allocator, regalloc2. See [this document](https://gist.github.com/cfallin/08553421a91f150254fe878f67301801) for a summary of the design changes. This switchover has implications for core VCode/MachInst types and the lowering pass. Overall, this change brings improvements to both compile time and speed of generated code (runtime), as reported in #3942: ``` Benchmark Compilation (wallclock) Execution (wallclock) blake3-scalar 25% faster 28% faster blake3-simd no diff no diff meshoptimizer 19% faster 17% faster pulldown-cmark 17% faster no diff bz2 15% faster no diff SpiderMonkey, 21% faster 2% faster fib(30) clang.wasm 42% faster N/A ```
This commit is contained in:
@@ -6,10 +6,7 @@
|
||||
use crate::ir::types::*;
|
||||
use crate::ir::Type;
|
||||
use crate::isa::aarch64::inst::*;
|
||||
use crate::machinst::{ty_bits, MachLabel};
|
||||
|
||||
use regalloc::{PrettyPrint, RealRegUniverse, Reg, Writable};
|
||||
|
||||
use crate::machinst::{ty_bits, MachLabel, PrettyPrint, Reg, Writable};
|
||||
use core::convert::Into;
|
||||
use std::string::String;
|
||||
|
||||
@@ -222,6 +219,29 @@ impl AMode {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
// This should match `memarg_operands()`.
|
||||
match self {
|
||||
&AMode::Unscaled(reg, imm9) => AMode::Unscaled(allocs.next(reg), imm9),
|
||||
&AMode::UnsignedOffset(r, uimm12) => AMode::UnsignedOffset(allocs.next(r), uimm12),
|
||||
&AMode::RegReg(r1, r2) => AMode::RegReg(allocs.next(r1), allocs.next(r2)),
|
||||
&AMode::RegScaled(r1, r2, ty) => AMode::RegScaled(allocs.next(r1), allocs.next(r2), ty),
|
||||
&AMode::RegScaledExtended(r1, r2, ty, ext) => {
|
||||
AMode::RegScaledExtended(allocs.next(r1), allocs.next(r2), ty, ext)
|
||||
}
|
||||
&AMode::RegExtended(r1, r2, ext) => {
|
||||
AMode::RegExtended(allocs.next(r1), allocs.next(r2), ext)
|
||||
}
|
||||
&AMode::PreIndexed(reg, simm9) => AMode::PreIndexed(allocs.next_writable(reg), simm9),
|
||||
&AMode::PostIndexed(reg, simm9) => AMode::PostIndexed(allocs.next_writable(reg), simm9),
|
||||
&AMode::RegOffset(r, off, ty) => AMode::RegOffset(allocs.next(r), off, ty),
|
||||
&AMode::FPOffset(..)
|
||||
| &AMode::SPOffset(..)
|
||||
| &AMode::NominalSPOffset(..)
|
||||
| AMode::Label(..) => self.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A memory argument to a load/store-pair.
|
||||
@@ -232,6 +252,23 @@ pub enum PairAMode {
|
||||
PostIndexed(Writable<Reg>, SImm7Scaled),
|
||||
}
|
||||
|
||||
impl PairAMode {
|
||||
pub fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
// Should match `pairmemarg_operands()`.
|
||||
match self {
|
||||
&PairAMode::SignedOffset(reg, simm7scaled) => {
|
||||
PairAMode::SignedOffset(allocs.next(reg), simm7scaled)
|
||||
}
|
||||
&PairAMode::PreIndexed(reg, simm7scaled) => {
|
||||
PairAMode::PreIndexed(allocs.next_writable(reg), simm7scaled)
|
||||
}
|
||||
&PairAMode::PostIndexed(reg, simm7scaled) => {
|
||||
PairAMode::PostIndexed(allocs.next_writable(reg), simm7scaled)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Instruction sub-components (conditions, branches and branch targets):
|
||||
// definitions
|
||||
@@ -362,19 +399,19 @@ impl BranchTarget {
|
||||
}
|
||||
|
||||
impl PrettyPrint for ShiftOpAndAmt {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
format!("{:?} {}", self.op(), self.amt().value())
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for ExtendOp {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for MemLabel {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
match self {
|
||||
&MemLabel::PCRel(off) => format!("pc+{}", off),
|
||||
}
|
||||
@@ -393,33 +430,36 @@ fn shift_for_type(ty: Type) -> usize {
|
||||
}
|
||||
|
||||
impl PrettyPrint for AMode {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, allocs: &mut AllocationConsumer<'_>) -> String {
|
||||
match self {
|
||||
&AMode::Unscaled(reg, simm9) => {
|
||||
let reg = pretty_print_reg(reg, allocs);
|
||||
if simm9.value != 0 {
|
||||
format!("[{}, {}]", reg.show_rru(mb_rru), simm9.show_rru(mb_rru))
|
||||
let simm9 = simm9.pretty_print(8, allocs);
|
||||
format!("[{}, {}]", reg, simm9)
|
||||
} else {
|
||||
format!("[{}]", reg.show_rru(mb_rru))
|
||||
format!("[{}]", reg)
|
||||
}
|
||||
}
|
||||
&AMode::UnsignedOffset(reg, uimm12) => {
|
||||
let reg = pretty_print_reg(reg, allocs);
|
||||
if uimm12.value != 0 {
|
||||
format!("[{}, {}]", reg.show_rru(mb_rru), uimm12.show_rru(mb_rru))
|
||||
let uimm12 = uimm12.pretty_print(8, allocs);
|
||||
format!("[{}, {}]", reg, uimm12)
|
||||
} else {
|
||||
format!("[{}]", reg.show_rru(mb_rru))
|
||||
format!("[{}]", reg)
|
||||
}
|
||||
}
|
||||
&AMode::RegReg(r1, r2) => {
|
||||
format!("[{}, {}]", r1.show_rru(mb_rru), r2.show_rru(mb_rru),)
|
||||
let r1 = pretty_print_reg(r1, allocs);
|
||||
let r2 = pretty_print_reg(r2, allocs);
|
||||
format!("[{}, {}]", r1, r2)
|
||||
}
|
||||
&AMode::RegScaled(r1, r2, ty) => {
|
||||
let r1 = pretty_print_reg(r1, allocs);
|
||||
let r2 = pretty_print_reg(r2, allocs);
|
||||
let shift = shift_for_type(ty);
|
||||
format!(
|
||||
"[{}, {}, LSL #{}]",
|
||||
r1.show_rru(mb_rru),
|
||||
r2.show_rru(mb_rru),
|
||||
shift,
|
||||
)
|
||||
format!("[{}, {}, LSL #{}]", r1, r2, shift)
|
||||
}
|
||||
&AMode::RegScaledExtended(r1, r2, ty, op) => {
|
||||
let shift = shift_for_type(ty);
|
||||
@@ -427,39 +467,32 @@ impl PrettyPrint for AMode {
|
||||
ExtendOp::SXTW | ExtendOp::UXTW => OperandSize::Size32,
|
||||
_ => OperandSize::Size64,
|
||||
};
|
||||
let op = op.show_rru(mb_rru);
|
||||
format!(
|
||||
"[{}, {}, {} #{}]",
|
||||
r1.show_rru(mb_rru),
|
||||
show_ireg_sized(r2, mb_rru, size),
|
||||
op,
|
||||
shift
|
||||
)
|
||||
let r1 = pretty_print_reg(r1, allocs);
|
||||
let r2 = pretty_print_ireg(r2, size, allocs);
|
||||
let op = op.pretty_print(0, allocs);
|
||||
format!("[{}, {}, {} #{}]", r1, r2, op, shift)
|
||||
}
|
||||
&AMode::RegExtended(r1, r2, op) => {
|
||||
let size = match op {
|
||||
ExtendOp::SXTW | ExtendOp::UXTW => OperandSize::Size32,
|
||||
_ => OperandSize::Size64,
|
||||
};
|
||||
let op = op.show_rru(mb_rru);
|
||||
format!(
|
||||
"[{}, {}, {}]",
|
||||
r1.show_rru(mb_rru),
|
||||
show_ireg_sized(r2, mb_rru, size),
|
||||
op,
|
||||
)
|
||||
let r1 = pretty_print_reg(r1, allocs);
|
||||
let r2 = pretty_print_ireg(r2, size, allocs);
|
||||
let op = op.pretty_print(0, allocs);
|
||||
format!("[{}, {}, {}]", r1, r2, op)
|
||||
}
|
||||
&AMode::Label(ref label) => label.pretty_print(0, allocs),
|
||||
&AMode::PreIndexed(r, simm9) => {
|
||||
let r = pretty_print_reg(r.to_reg(), allocs);
|
||||
let simm9 = simm9.pretty_print(8, allocs);
|
||||
format!("[{}, {}]!", r, simm9)
|
||||
}
|
||||
&AMode::PostIndexed(r, simm9) => {
|
||||
let r = pretty_print_reg(r.to_reg(), allocs);
|
||||
let simm9 = simm9.pretty_print(8, allocs);
|
||||
format!("[{}], {}", r, simm9)
|
||||
}
|
||||
&AMode::Label(ref label) => label.show_rru(mb_rru),
|
||||
&AMode::PreIndexed(r, simm9) => format!(
|
||||
"[{}, {}]!",
|
||||
r.to_reg().show_rru(mb_rru),
|
||||
simm9.show_rru(mb_rru)
|
||||
),
|
||||
&AMode::PostIndexed(r, simm9) => format!(
|
||||
"[{}], {}",
|
||||
r.to_reg().show_rru(mb_rru),
|
||||
simm9.show_rru(mb_rru)
|
||||
),
|
||||
// Eliminated by `mem_finalize()`.
|
||||
&AMode::SPOffset(..)
|
||||
| &AMode::FPOffset(..)
|
||||
@@ -472,31 +505,33 @@ impl PrettyPrint for AMode {
|
||||
}
|
||||
|
||||
impl PrettyPrint for PairAMode {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, allocs: &mut AllocationConsumer<'_>) -> String {
|
||||
match self {
|
||||
&PairAMode::SignedOffset(reg, simm7) => {
|
||||
let reg = pretty_print_reg(reg, allocs);
|
||||
if simm7.value != 0 {
|
||||
format!("[{}, {}]", reg.show_rru(mb_rru), simm7.show_rru(mb_rru))
|
||||
let simm7 = simm7.pretty_print(8, allocs);
|
||||
format!("[{}, {}]", reg, simm7)
|
||||
} else {
|
||||
format!("[{}]", reg.show_rru(mb_rru))
|
||||
format!("[{}]", reg)
|
||||
}
|
||||
}
|
||||
&PairAMode::PreIndexed(reg, simm7) => format!(
|
||||
"[{}, {}]!",
|
||||
reg.to_reg().show_rru(mb_rru),
|
||||
simm7.show_rru(mb_rru)
|
||||
),
|
||||
&PairAMode::PostIndexed(reg, simm7) => format!(
|
||||
"[{}], {}",
|
||||
reg.to_reg().show_rru(mb_rru),
|
||||
simm7.show_rru(mb_rru)
|
||||
),
|
||||
&PairAMode::PreIndexed(reg, simm7) => {
|
||||
let reg = pretty_print_reg(reg.to_reg(), allocs);
|
||||
let simm7 = simm7.pretty_print(8, allocs);
|
||||
format!("[{}, {}]!", reg, simm7)
|
||||
}
|
||||
&PairAMode::PostIndexed(reg, simm7) => {
|
||||
let reg = pretty_print_reg(reg.to_reg(), allocs);
|
||||
let simm7 = simm7.pretty_print(8, allocs);
|
||||
format!("[{}], {}", reg, simm7)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for Cond {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
let mut s = format!("{:?}", self);
|
||||
s.make_ascii_lowercase();
|
||||
s
|
||||
@@ -504,7 +539,7 @@ impl PrettyPrint for Cond {
|
||||
}
|
||||
|
||||
impl PrettyPrint for BranchTarget {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
match self {
|
||||
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
||||
&BranchTarget::ResolvedOffset(off) => format!("{}", off),
|
||||
|
||||
Reference in New Issue
Block a user