Add a TargetIsa::allocatable_registers() method.
This gives the target ISA a chance to reserve registers like the stack pointer or hard-wired 0 registers like %x0 on RISC-V.
This commit is contained in:
@@ -6,7 +6,8 @@ isa riscv
|
|||||||
function add(i32, i32) {
|
function add(i32, i32) {
|
||||||
ebb0(v1: i32, v2: i32):
|
ebb0(v1: i32, v2: i32):
|
||||||
v3 = iadd v1, v2
|
v3 = iadd v1, v2
|
||||||
; check: [R#0c,%x0]
|
; TODO: This shouldn't clobber the link register.
|
||||||
|
; check: [R#0c,%x1]
|
||||||
; sameln: iadd
|
; sameln: iadd
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use ir;
|
use ir;
|
||||||
use isa::RegClass;
|
use isa::RegClass;
|
||||||
|
use regalloc::AllocatableSet;
|
||||||
use settings as shared_settings;
|
use settings as shared_settings;
|
||||||
use super::registers::{S, D, Q, GPR};
|
use super::registers::{S, D, Q, GPR};
|
||||||
|
|
||||||
@@ -25,3 +26,8 @@ pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the set of allocatable registers for `func`.
|
||||||
|
pub fn allocatable_registers(_func: &ir::Function) -> AllocatableSet {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encodin
|
|||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
|
use regalloc;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Isa {
|
struct Isa {
|
||||||
@@ -86,6 +87,10 @@ impl TargetIsa for Isa {
|
|||||||
abi::regclass_for_abi_type(ty)
|
abi::regclass_for_abi_type(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn allocatable_registers(&self, func: &ir::Function) -> regalloc::AllocatableSet {
|
||||||
|
abi::allocatable_registers(func)
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use ir;
|
use ir;
|
||||||
use isa::RegClass;
|
use isa::RegClass;
|
||||||
|
use regalloc::AllocatableSet;
|
||||||
use settings as shared_settings;
|
use settings as shared_settings;
|
||||||
use super::registers::{GPR, FPR};
|
use super::registers::{GPR, FPR};
|
||||||
|
|
||||||
@@ -16,3 +17,8 @@ pub fn legalize_signature(_sig: &mut ir::Signature,
|
|||||||
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
|
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
|
||||||
if ty.is_int() { GPR } else { FPR }
|
if ty.is_int() { GPR } else { FPR }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the set of allocatable registers for `func`.
|
||||||
|
pub fn allocatable_registers(_func: &ir::Function) -> AllocatableSet {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use isa::enc_tables::{lookup_enclist, general_encoding};
|
|||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
|
use regalloc;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Isa {
|
struct Isa {
|
||||||
@@ -79,6 +80,10 @@ impl TargetIsa for Isa {
|
|||||||
abi::regclass_for_abi_type(ty)
|
abi::regclass_for_abi_type(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn allocatable_registers(&self, func: &ir::Function) -> regalloc::AllocatableSet {
|
||||||
|
abi::allocatable_registers(func)
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use ir;
|
use ir;
|
||||||
use isa::RegClass;
|
use isa::RegClass;
|
||||||
|
use regalloc::AllocatableSet;
|
||||||
use settings as shared_settings;
|
use settings as shared_settings;
|
||||||
use super::registers::{GPR, FPR};
|
use super::registers::{GPR, FPR};
|
||||||
|
|
||||||
@@ -16,3 +17,8 @@ pub fn legalize_signature(_sig: &mut ir::Signature,
|
|||||||
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
|
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
|
||||||
if ty.is_int() { GPR } else { FPR }
|
if ty.is_int() { GPR } else { FPR }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the set of allocatable registers for `func`.
|
||||||
|
pub fn allocatable_registers(_func: &ir::Function) -> AllocatableSet {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encodin
|
|||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
|
use regalloc;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Isa {
|
struct Isa {
|
||||||
@@ -86,6 +87,10 @@ impl TargetIsa for Isa {
|
|||||||
abi::regclass_for_abi_type(ty)
|
abi::regclass_for_abi_type(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn allocatable_registers(&self, func: &ir::Function) -> regalloc::AllocatableSet {
|
||||||
|
abi::allocatable_registers(func)
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ pub use isa::registers::{RegInfo, RegUnit, RegClass, RegClassIndex};
|
|||||||
|
|
||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use settings;
|
use settings;
|
||||||
use ir::{Function, Inst, InstructionData, DataFlowGraph, Signature, Type};
|
use ir;
|
||||||
|
use regalloc;
|
||||||
|
|
||||||
pub mod riscv;
|
pub mod riscv;
|
||||||
pub mod intel;
|
pub mod intel;
|
||||||
@@ -142,9 +143,9 @@ pub trait TargetIsa {
|
|||||||
///
|
///
|
||||||
/// This is also the main entry point for determining if an instruction is legal.
|
/// This is also the main entry point for determining if an instruction is legal.
|
||||||
fn encode(&self,
|
fn encode(&self,
|
||||||
dfg: &DataFlowGraph,
|
dfg: &ir::DataFlowGraph,
|
||||||
inst: &InstructionData,
|
inst: &ir::InstructionData,
|
||||||
ctrl_typevar: Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize>;
|
-> Result<Encoding, Legalize>;
|
||||||
|
|
||||||
/// Get a data structure describing the instruction encodings in this ISA.
|
/// Get a data structure describing the instruction encodings in this ISA.
|
||||||
@@ -183,7 +184,7 @@ pub trait TargetIsa {
|
|||||||
/// Arguments and return values for the caller's frame pointer and other callee-saved registers
|
/// Arguments and return values for the caller's frame pointer and other callee-saved registers
|
||||||
/// should not be added by this function. These arguments are not added until after register
|
/// should not be added by this function. These arguments are not added until after register
|
||||||
/// allocation.
|
/// allocation.
|
||||||
fn legalize_signature(&self, sig: &mut Signature, current: bool);
|
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool);
|
||||||
|
|
||||||
/// Get the register class that should be used to represent an ABI argument or return value of
|
/// Get the register class that should be used to represent an ABI argument or return value of
|
||||||
/// type `ty`. This should be the top-level register class that contains the argument
|
/// type `ty`. This should be the top-level register class that contains the argument
|
||||||
@@ -191,13 +192,19 @@ pub trait TargetIsa {
|
|||||||
///
|
///
|
||||||
/// This function can assume that it will only be asked to provide register classes for types
|
/// This function can assume that it will only be asked to provide register classes for types
|
||||||
/// that `legalize_signature()` produces in `ArgumentLoc::Reg` entries.
|
/// that `legalize_signature()` produces in `ArgumentLoc::Reg` entries.
|
||||||
fn regclass_for_abi_type(&self, ty: Type) -> RegClass;
|
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass;
|
||||||
|
|
||||||
|
/// Get the set of allocatable registers that can be used when compiling `func`.
|
||||||
|
///
|
||||||
|
/// This set excludes reserved registers like the stack pointer and other special-purpose
|
||||||
|
/// registers.
|
||||||
|
fn allocatable_registers(&self, func: &ir::Function) -> regalloc::AllocatableSet;
|
||||||
|
|
||||||
/// Emit binary machine code for a single instruction into the `sink` trait object.
|
/// Emit binary machine code for a single instruction into the `sink` trait object.
|
||||||
///
|
///
|
||||||
/// Note that this will call `put*` methods on the trait object via its vtable which is not the
|
/// Note that this will call `put*` methods on the trait object via its vtable which is not the
|
||||||
/// fastest way of emitting code.
|
/// fastest way of emitting code.
|
||||||
fn emit_inst(&self, func: &Function, inst: Inst, sink: &mut CodeSink);
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink);
|
||||||
|
|
||||||
/// Get a static array of names associated with relocations in this ISA.
|
/// Get a static array of names associated with relocations in this ISA.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
//! This doesn't support the soft-float ABI at the moment.
|
//! This doesn't support the soft-float ABI at the moment.
|
||||||
|
|
||||||
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
|
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
|
||||||
use ir::{Signature, Type, ArgumentType, ArgumentLoc, ArgumentExtension, ArgumentPurpose};
|
use ir::{self, Type, ArgumentType, ArgumentLoc, ArgumentExtension, ArgumentPurpose};
|
||||||
use isa::RegClass;
|
use isa::RegClass;
|
||||||
|
use regalloc::AllocatableSet;
|
||||||
use settings as shared_settings;
|
use settings as shared_settings;
|
||||||
use super::registers::{GPR, FPR};
|
use super::registers::{GPR, FPR};
|
||||||
use super::settings;
|
use super::settings;
|
||||||
@@ -84,7 +85,7 @@ impl ArgAssigner for Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Legalize `sig` for RISC-V.
|
/// Legalize `sig` for RISC-V.
|
||||||
pub fn legalize_signature(sig: &mut Signature,
|
pub fn legalize_signature(sig: &mut ir::Signature,
|
||||||
flags: &shared_settings::Flags,
|
flags: &shared_settings::Flags,
|
||||||
isa_flags: &settings::Flags,
|
isa_flags: &settings::Flags,
|
||||||
current: bool) {
|
current: bool) {
|
||||||
@@ -114,3 +115,22 @@ pub fn legalize_signature(sig: &mut Signature,
|
|||||||
pub fn regclass_for_abi_type(ty: Type) -> RegClass {
|
pub fn regclass_for_abi_type(ty: Type) -> RegClass {
|
||||||
if ty.is_float() { FPR } else { GPR }
|
if ty.is_float() { FPR } else { GPR }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn allocatable_registers(_func: &ir::Function, isa_flags: &settings::Flags) -> AllocatableSet {
|
||||||
|
let mut regs = AllocatableSet::new();
|
||||||
|
regs.take(GPR, GPR.unit(0)); // Hard-wired 0.
|
||||||
|
// %x1 is the link register which is available for allocation.
|
||||||
|
regs.take(GPR, GPR.unit(2)); // Stack pointer.
|
||||||
|
regs.take(GPR, GPR.unit(3)); // Global pointer.
|
||||||
|
regs.take(GPR, GPR.unit(4)); // Thread pointer.
|
||||||
|
// TODO: %x8 is the frame pointer. Reserve it?
|
||||||
|
|
||||||
|
// Remove %x16 and up for RV32E.
|
||||||
|
if isa_flags.enable_e() {
|
||||||
|
for u in 16..32 {
|
||||||
|
regs.take(GPR, GPR.unit(u));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regs
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ use binemit::CodeSink;
|
|||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
||||||
use ir::{Function, Inst, InstructionData, DataFlowGraph, Signature, Type};
|
use ir;
|
||||||
|
use regalloc;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Isa {
|
struct Isa {
|
||||||
@@ -61,9 +62,9 @@ impl TargetIsa for Isa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn encode(&self,
|
||||||
_dfg: &DataFlowGraph,
|
_dfg: &ir::DataFlowGraph,
|
||||||
inst: &InstructionData,
|
inst: &ir::InstructionData,
|
||||||
ctrl_typevar: Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize> {
|
-> Result<Encoding, Legalize> {
|
||||||
lookup_enclist(ctrl_typevar,
|
lookup_enclist(ctrl_typevar,
|
||||||
inst.opcode(),
|
inst.opcode(),
|
||||||
@@ -78,15 +79,19 @@ impl TargetIsa for Isa {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn legalize_signature(&self, sig: &mut Signature, current: bool) {
|
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) {
|
||||||
abi::legalize_signature(sig, &self.shared_flags, &self.isa_flags, current)
|
abi::legalize_signature(sig, &self.shared_flags, &self.isa_flags, current)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regclass_for_abi_type(&self, ty: Type) -> RegClass {
|
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
|
||||||
abi::regclass_for_abi_type(ty)
|
abi::regclass_for_abi_type(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_inst(&self, func: &Function, inst: Inst, sink: &mut CodeSink) {
|
fn allocatable_registers(&self, func: &ir::Function) -> regalloc::AllocatableSet {
|
||||||
|
abi::allocatable_registers(func, &self.isa_flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_inst(&self, func: &ir::Function, inst: ir::Inst, sink: &mut CodeSink) {
|
||||||
binemit::emit_inst(func, inst, sink)
|
binemit::emit_inst(func, inst, sink)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,8 +101,7 @@ impl Coloring {
|
|||||||
encinfo: isa.encoding_info(),
|
encinfo: isa.encoding_info(),
|
||||||
domtree: domtree,
|
domtree: domtree,
|
||||||
liveness: liveness,
|
liveness: liveness,
|
||||||
// TODO: Ask the target ISA about reserved registers etc.
|
usable_regs: isa.allocatable_registers(func),
|
||||||
usable_regs: AllocatableSet::new(),
|
|
||||||
};
|
};
|
||||||
ctx.run(self, func, tracker)
|
ctx.run(self, func, tracker)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ pub mod coloring;
|
|||||||
mod affinity;
|
mod affinity;
|
||||||
mod context;
|
mod context;
|
||||||
|
|
||||||
|
pub use self::allocatable_set::AllocatableSet;
|
||||||
pub use self::context::Context;
|
pub use self::context::Context;
|
||||||
|
|||||||
Reference in New Issue
Block a user