diff --git a/cranelift/codegen/meta/src/cdsl/cpu_modes.rs b/cranelift/codegen/meta/src/cdsl/cpu_modes.rs new file mode 100644 index 0000000000..5e0e5b4762 --- /dev/null +++ b/cranelift/codegen/meta/src/cdsl/cpu_modes.rs @@ -0,0 +1,84 @@ +use crate::cdsl::types::LaneType; +use crate::cdsl::xform::{TransformGroup, TransformGroupIndex, TransformGroups}; + +use std::collections::{HashMap, HashSet}; +use std::iter::FromIterator; + +pub struct CpuMode { + _name: &'static str, + default_legalize: Option, + monomorphic_legalize: Option, + typed_legalize: HashMap, +} + +impl CpuMode { + pub fn new(name: &'static str) -> Self { + Self { + _name: name, + default_legalize: None, + monomorphic_legalize: None, + typed_legalize: HashMap::new(), + } + } + pub fn legalize_monomorphic(&mut self, group: &TransformGroup) { + assert!(self.monomorphic_legalize.is_none()); + self.monomorphic_legalize = Some(group.id); + } + pub fn legalize_default(&mut self, group: &TransformGroup) { + assert!(self.default_legalize.is_none()); + self.default_legalize = Some(group.id); + } + pub fn legalize_type(&mut self, lane_type: impl Into, group: &TransformGroup) { + assert!(self + .typed_legalize + .insert(lane_type.into().to_string(), group.id) + .is_none()); + } + + /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the + /// transitive set of TransformGroup this TargetIsa uses. + pub fn transitive_transform_groups( + &self, + all_groups: &TransformGroups, + ) -> Vec { + let mut roots = Vec::new(); + if let Some(i) = &self.default_legalize { + roots.push(*i); + } + if let Some(i) = &self.monomorphic_legalize { + roots.push(*i); + } + roots.extend(self.typed_legalize.values().cloned()); + + let mut set = HashSet::new(); + for root in roots { + set.insert(root); + let mut base = root; + // Follow the chain of chain_with. + while let Some(chain_with) = &all_groups.get(base).chain_with { + set.insert(*chain_with); + base = *chain_with; + } + } + + let mut ret = Vec::from_iter(set); + ret.sort(); + ret + } + + /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the directly + /// reachable set of TransformGroup this TargetIsa uses. + pub fn direct_transform_groups(&self) -> Vec { + let mut set = HashSet::new(); + if let Some(i) = &self.default_legalize { + set.insert(*i); + } + if let Some(i) = &self.monomorphic_legalize { + set.insert(*i); + } + set.extend(self.typed_legalize.values().cloned()); + let mut ret = Vec::from_iter(set); + ret.sort(); + ret + } +} diff --git a/cranelift/codegen/meta/src/cdsl/isa.rs b/cranelift/codegen/meta/src/cdsl/isa.rs index 1091f6db80..b8cfa17465 100644 --- a/cranelift/codegen/meta/src/cdsl/isa.rs +++ b/cranelift/codegen/meta/src/cdsl/isa.rs @@ -1,12 +1,18 @@ +use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::inst::InstructionGroup; use crate::cdsl::regs::IsaRegs; use crate::cdsl::settings::SettingGroup; +use crate::cdsl::xform::{TransformGroupIndex, TransformGroups}; + +use std::collections::HashSet; +use std::iter::FromIterator; pub struct TargetIsa { pub name: &'static str, pub instructions: InstructionGroup, pub settings: SettingGroup, pub regs: IsaRegs, + pub cpu_modes: Vec, } impl TargetIsa { @@ -15,12 +21,41 @@ impl TargetIsa { instructions: InstructionGroup, settings: SettingGroup, regs: IsaRegs, + cpu_modes: Vec, ) -> Self { Self { name, instructions, settings, regs, + cpu_modes, } } + + /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the + /// transitive set of TransformGroup this TargetIsa uses. + pub fn transitive_transform_groups( + &self, + all_groups: &TransformGroups, + ) -> Vec { + let mut set = HashSet::new(); + for cpu_mode in &self.cpu_modes { + set.extend(cpu_mode.transitive_transform_groups(all_groups)); + } + let mut vec = Vec::from_iter(set); + vec.sort(); + vec + } + + /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the directly + /// reachable set of TransformGroup this TargetIsa uses. + pub fn direct_transform_groups(&self) -> Vec { + let mut set = HashSet::new(); + for cpu_mode in &self.cpu_modes { + set.extend(cpu_mode.direct_transform_groups()); + } + let mut vec = Vec::from_iter(set); + vec.sort(); + vec + } } diff --git a/cranelift/codegen/meta/src/cdsl/mod.rs b/cranelift/codegen/meta/src/cdsl/mod.rs index a6c8be95fe..516b04d0b2 100644 --- a/cranelift/codegen/meta/src/cdsl/mod.rs +++ b/cranelift/codegen/meta/src/cdsl/mod.rs @@ -5,6 +5,7 @@ #[macro_use] pub mod ast; +pub mod cpu_modes; pub mod formats; pub mod inst; pub mod isa; diff --git a/cranelift/codegen/meta/src/isa/arm32/mod.rs b/cranelift/codegen/meta/src/isa/arm32/mod.rs index 8c32cdcdcd..15a9190924 100644 --- a/cranelift/codegen/meta/src/isa/arm32/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm32/mod.rs @@ -1,7 +1,9 @@ +use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::inst::InstructionGroup; use crate::cdsl::isa::TargetIsa; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder}; + use crate::shared::Definitions as SharedDefinitions; fn define_settings(_shared: &SettingGroup) -> SettingGroup { @@ -52,5 +54,16 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroup::new("arm32", "arm32 specific instruction set"); - TargetIsa::new("arm32", inst_group, settings, regs) + // CPU modes for 32-bit ARM and Thumb2. + let mut a32 = CpuMode::new("A32"); + let mut t32 = CpuMode::new("T32"); + + // TODO refine these. + let narrow = shared_defs.transform_groups.by_name("narrow"); + a32.legalize_default(narrow); + t32.legalize_default(narrow); + + let cpu_modes = vec![a32, t32]; + + TargetIsa::new("arm32", inst_group, settings, regs, cpu_modes) } diff --git a/cranelift/codegen/meta/src/isa/arm64/mod.rs b/cranelift/codegen/meta/src/isa/arm64/mod.rs index 46baac90e6..4aaeb2c336 100644 --- a/cranelift/codegen/meta/src/isa/arm64/mod.rs +++ b/cranelift/codegen/meta/src/isa/arm64/mod.rs @@ -1,7 +1,9 @@ +use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::inst::InstructionGroup; use crate::cdsl::isa::TargetIsa; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{SettingGroup, SettingGroupBuilder}; + use crate::shared::Definitions as SharedDefinitions; fn define_settings(_shared: &SettingGroup) -> SettingGroup { @@ -48,5 +50,13 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroup::new("arm64", "arm64 specific instruction set"); - TargetIsa::new("arm64", inst_group, settings, regs) + let mut a64 = CpuMode::new("A64"); + + // TODO refine these. + let narrow = shared_defs.transform_groups.by_name("narrow"); + a64.legalize_default(narrow); + + let cpu_modes = vec![a64]; + + TargetIsa::new("arm64", inst_group, settings, regs, cpu_modes) } diff --git a/cranelift/codegen/meta/src/isa/riscv/mod.rs b/cranelift/codegen/meta/src/isa/riscv/mod.rs index 9d5a78a5a0..4e947d3184 100644 --- a/cranelift/codegen/meta/src/isa/riscv/mod.rs +++ b/cranelift/codegen/meta/src/isa/riscv/mod.rs @@ -1,7 +1,11 @@ +use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::inst::InstructionGroup; use crate::cdsl::isa::TargetIsa; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder}; + +use crate::shared::types::Float::{F32, F64}; +use crate::shared::types::Int::{I32, I64}; use crate::shared::Definitions as SharedDefinitions; fn define_settings(shared: &SettingGroup) -> SettingGroup { @@ -84,5 +88,26 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let inst_group = InstructionGroup::new("riscv", "riscv specific instruction set"); - TargetIsa::new("riscv", inst_group, settings, regs) + // CPU modes for 32-bit and 64-bit operation. + let mut rv_32 = CpuMode::new("RV32"); + let mut rv_64 = CpuMode::new("RV64"); + + let expand = shared_defs.transform_groups.by_name("expand"); + let narrow = shared_defs.transform_groups.by_name("narrow"); + rv_32.legalize_monomorphic(expand); + rv_32.legalize_default(narrow); + rv_32.legalize_type(I32, expand); + rv_32.legalize_type(F32, expand); + rv_32.legalize_type(F64, expand); + + rv_64.legalize_monomorphic(expand); + rv_64.legalize_default(narrow); + rv_64.legalize_type(I32, expand); + rv_64.legalize_type(I64, expand); + rv_64.legalize_type(F32, expand); + rv_64.legalize_type(F64, expand); + + let cpu_modes = vec![rv_32, rv_64]; + + TargetIsa::new("riscv", inst_group, settings, regs, cpu_modes) } diff --git a/cranelift/codegen/meta/src/isa/x86/mod.rs b/cranelift/codegen/meta/src/isa/x86/mod.rs index 6c5fe4d097..8080ea5d43 100644 --- a/cranelift/codegen/meta/src/isa/x86/mod.rs +++ b/cranelift/codegen/meta/src/isa/x86/mod.rs @@ -1,11 +1,16 @@ -mod instructions; - +use crate::cdsl::cpu_modes::CpuMode; use crate::cdsl::isa::TargetIsa; use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder}; use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder}; +use crate::shared::types::Bool::B1; +use crate::shared::types::Float::{F32, F64}; +use crate::shared::types::Int::{I16, I32, I64, I8}; use crate::shared::Definitions as SharedDefinitions; +mod instructions; +mod legalize; + fn define_settings(_shared: &SettingGroup) -> SettingGroup { let mut settings = SettingGroupBuilder::new("x86"); @@ -118,6 +123,37 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa { let regs = define_registers(); let inst_group = instructions::define(&shared_defs.format_registry); + legalize::define(shared_defs, &inst_group); - TargetIsa::new("x86", inst_group, settings, regs) + // CPU modes for 32-bit and 64-bit operations. + let mut x86_64 = CpuMode::new("I64"); + let mut x86_32 = CpuMode::new("I32"); + + let expand_flags = shared_defs.transform_groups.by_name("expand_flags"); + let narrow = shared_defs.transform_groups.by_name("narrow"); + let widen = shared_defs.transform_groups.by_name("widen"); + let x86_expand = shared_defs.transform_groups.by_name("x86_expand"); + + x86_32.legalize_monomorphic(expand_flags); + x86_32.legalize_default(narrow); + x86_32.legalize_type(B1, expand_flags); + x86_32.legalize_type(I8, widen); + x86_32.legalize_type(I16, widen); + x86_32.legalize_type(I32, x86_expand); + x86_32.legalize_type(F32, x86_expand); + x86_32.legalize_type(F64, x86_expand); + + x86_64.legalize_monomorphic(expand_flags); + x86_64.legalize_default(narrow); + x86_64.legalize_type(B1, expand_flags); + x86_64.legalize_type(I8, widen); + x86_64.legalize_type(I16, widen); + x86_64.legalize_type(I32, x86_expand); + x86_64.legalize_type(I64, x86_expand); + x86_64.legalize_type(F32, x86_expand); + x86_64.legalize_type(F64, x86_expand); + + let cpu_modes = vec![x86_64, x86_32]; + + TargetIsa::new("x86", inst_group, settings, regs, cpu_modes) }