Skip to content

Commit

Permalink
[RFC] Dynamic Vector Support (#4200)
Browse files Browse the repository at this point in the history
Introduce a new concept in the IR that allows a producer to create
dynamic vector types. An IR function can now contain global value(s)
that represent a dynamic scaling factor, for a given fixed-width
vector type. A dynamic type is then created by 'multiplying' the
corresponding global value with a fixed-width type. These new types
can be used just like the existing types and the type system has a
set of hard-coded dynamic types, such as I32X4XN, which the user
defined types map onto. The dynamic types are also used explicitly
to create dynamic stack slots, which have no set size like their
existing counterparts. New IR instructions are added to access these
new stack entities.

Currently, during codegen, the dynamic scaling factor has to be
lowered to a constant so the dynamic slots do eventually have a
compile-time known size, as do spill slots.

The current lowering for aarch64 just targets Neon, using a dynamic
scale of 1.

Copyright (c) 2022, Arm Limited.
  • Loading branch information
sparker-arm authored Jul 7, 2022
1 parent 9ae060a commit 9c43749
Show file tree
Hide file tree
Showing 69 changed files with 2,422 additions and 294 deletions.
2 changes: 2 additions & 0 deletions cranelift/codegen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,9 @@ fn get_isle_compilations(
inputs: vec![
prelude_isle.clone(),
src_isa_aarch64.join("inst.isle"),
src_isa_aarch64.join("inst_neon.isle"),
src_isa_aarch64.join("lower.isle"),
src_isa_aarch64.join("lower_dynamic_neon.isle"),
],
untracked_inputs: vec![clif_isle.clone()],
},
Expand Down
90 changes: 90 additions & 0 deletions cranelift/codegen/meta/src/cdsl/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub(crate) enum ValueType {
Reference(ReferenceType),
Special(SpecialType),
Vector(VectorType),
DynamicVector(DynamicVectorType),
}

impl ValueType {
Expand All @@ -44,6 +45,7 @@ impl ValueType {
ValueType::Reference(r) => r.doc(),
ValueType::Special(s) => s.doc(),
ValueType::Vector(ref v) => v.doc(),
ValueType::DynamicVector(ref v) => v.doc(),
}
}

Expand All @@ -54,6 +56,7 @@ impl ValueType {
ValueType::Reference(r) => r.lane_bits(),
ValueType::Special(s) => s.lane_bits(),
ValueType::Vector(ref v) => v.lane_bits(),
ValueType::DynamicVector(ref v) => v.lane_bits(),
}
}

Expand All @@ -77,6 +80,7 @@ impl ValueType {
ValueType::Reference(r) => r.number(),
ValueType::Special(s) => s.number(),
ValueType::Vector(ref v) => v.number(),
ValueType::DynamicVector(ref v) => v.number(),
}
}

Expand All @@ -98,6 +102,7 @@ impl fmt::Display for ValueType {
ValueType::Reference(r) => r.fmt(f),
ValueType::Special(s) => s.fmt(f),
ValueType::Vector(ref v) => v.fmt(f),
ValueType::DynamicVector(ref v) => v.fmt(f),
}
}
}
Expand Down Expand Up @@ -130,6 +135,13 @@ impl From<VectorType> for ValueType {
}
}

/// Create a ValueType from a given dynamic vector type.
impl From<DynamicVectorType> for ValueType {
fn from(vector: DynamicVectorType) -> Self {
ValueType::DynamicVector(vector)
}
}

/// A concrete scalar type that can appear as a vector lane too.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum LaneType {
Expand Down Expand Up @@ -230,6 +242,10 @@ impl LaneType {
ValueType::Vector(VectorType::new(self, lanes.into()))
}
}

pub fn to_dynamic(self, lanes: u16) -> ValueType {
ValueType::DynamicVector(DynamicVectorType::new(self, lanes.into()))
}
}

impl fmt::Display for LaneType {
Expand Down Expand Up @@ -380,6 +396,80 @@ impl fmt::Debug for VectorType {
}
}

/// A concrete dynamic SIMD vector type.
///
/// A vector type has a lane type which is an instance of `LaneType`,
/// and a positive number of lanes.
#[derive(Clone, PartialEq, Eq, Hash)]
pub(crate) struct DynamicVectorType {
base: LaneType,
unscaled_lanes: u64,
}

impl DynamicVectorType {
/// Initialize a new type with `base` lane type and a minimum number of lanes.
pub fn new(base: LaneType, unscaled_lanes: u64) -> Self {
Self {
base,
unscaled_lanes,
}
}

/// Return a string containing the documentation comment for this vector type.
pub fn doc(&self) -> String {
format!(
"A dynamically-scaled SIMD vector with a minimum of {} lanes containing `{}` bits each.",
self.unscaled_lanes,
self.base
)
}

/// Return the number of bits in a lane.
pub fn lane_bits(&self) -> u64 {
self.base.lane_bits()
}

/// Return the number of lanes.
pub fn minimum_lane_count(&self) -> u64 {
self.unscaled_lanes
}

/// Return the lane type.
pub fn lane_type(&self) -> LaneType {
self.base
}

/// Find the unique number associated with this vector type.
///
/// Dynamic vector types are encoded in the same manner as `VectorType`,
/// with lane type in the low 4 bits and the log2(lane_count). We add the
/// `VECTOR_BASE` to move these numbers into the range beyond the fixed
/// SIMD types.
pub fn number(&self) -> u16 {
let base_num = u32::from(self.base.number());
let lanes_log_2: u32 = 63 - self.minimum_lane_count().leading_zeros();
let num = 0x80 + (lanes_log_2 << 4) + base_num;
num as u16
}
}

impl fmt::Display for DynamicVectorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}x{}xN", self.base, self.minimum_lane_count())
}
}

impl fmt::Debug for DynamicVectorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"DynamicVectorType(base={}, lanes={})",
self.base,
self.minimum_lane_count(),
)
}
}

/// A concrete scalar type that is neither a vector nor a lane type.
///
/// Special types cannot be used to form vectors.
Expand Down
Loading

0 comments on commit 9c43749

Please sign in to comment.