Add DerivedFunction for splitting lane widths and doubling the number of lanes
Certain operations (e.g. x86_packss) will have operands with types like `NxM` but will return results with types like `(N/2)x(M*2)` (halve the lane width, double the number of lanes; maintain the same number of vector bits). This is equivalent to applying two `DerivedFunction`s to the type: `DerivedFunction::HalfWidth` then `DerivedFunction::DoubleVector`. Since there is no easy way to apply multiple `DerivedFunction`s (e.g. most of the logic is one-level deep, 1d5a678124/cranelift/codegen/meta/src/gen_inst.rs (L618-L621)), I added `DerivedFunction::SplitLanes` to do the necessary type conversion.
This commit is contained in:
@@ -193,6 +193,24 @@ impl TypeVar {
|
||||
"can't double 256 lanes"
|
||||
);
|
||||
}
|
||||
DerivedFunc::SplitLanes => {
|
||||
assert!(
|
||||
ts.ints.is_empty() || *ts.ints.iter().min().unwrap() > 8,
|
||||
"can't halve all integer types"
|
||||
);
|
||||
assert!(
|
||||
ts.floats.is_empty() || *ts.floats.iter().min().unwrap() > 32,
|
||||
"can't halve all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.is_empty() || *ts.bools.iter().min().unwrap() > 8,
|
||||
"can't halve all boolean types"
|
||||
);
|
||||
assert!(
|
||||
*ts.lanes.iter().max().unwrap() < MAX_LANES,
|
||||
"can't double 256 lanes"
|
||||
);
|
||||
}
|
||||
DerivedFunc::LaneOf | DerivedFunc::AsBool => { /* no particular assertions */ }
|
||||
}
|
||||
|
||||
@@ -227,6 +245,9 @@ impl TypeVar {
|
||||
pub fn double_vector(&self) -> TypeVar {
|
||||
self.derived(DerivedFunc::DoubleVector)
|
||||
}
|
||||
pub fn split_lanes(&self) -> TypeVar {
|
||||
self.derived(DerivedFunc::SplitLanes)
|
||||
}
|
||||
|
||||
/// Constrain the range of types this variable can assume to a subset of those in the typeset
|
||||
/// ts.
|
||||
@@ -333,6 +354,7 @@ pub(crate) enum DerivedFunc {
|
||||
DoubleWidth,
|
||||
HalfVector,
|
||||
DoubleVector,
|
||||
SplitLanes,
|
||||
}
|
||||
|
||||
impl DerivedFunc {
|
||||
@@ -344,6 +366,7 @@ impl DerivedFunc {
|
||||
DerivedFunc::DoubleWidth => "double_width",
|
||||
DerivedFunc::HalfVector => "half_vector",
|
||||
DerivedFunc::DoubleVector => "double_vector",
|
||||
DerivedFunc::SplitLanes => "split_lanes",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +461,7 @@ impl TypeSet {
|
||||
DerivedFunc::DoubleWidth => self.double_width(),
|
||||
DerivedFunc::HalfVector => self.half_vector(),
|
||||
DerivedFunc::DoubleVector => self.double_vector(),
|
||||
DerivedFunc::SplitLanes => self.half_width().double_vector(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,6 +601,7 @@ impl TypeSet {
|
||||
DerivedFunc::DoubleWidth => self.half_width(),
|
||||
DerivedFunc::HalfVector => self.double_vector(),
|
||||
DerivedFunc::DoubleVector => self.half_vector(),
|
||||
DerivedFunc::SplitLanes => self.half_vector().double_width(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -518,6 +518,9 @@ enum OperandConstraint {
|
||||
|
||||
/// This operand is `ctrlType.double_vector()`.
|
||||
DoubleVector,
|
||||
|
||||
/// This operand is `ctrlType.split_lanes()`.
|
||||
SplitLanes,
|
||||
}
|
||||
|
||||
impl OperandConstraint {
|
||||
@@ -544,6 +547,11 @@ impl OperandConstraint {
|
||||
.expect("invalid type for half_vector"),
|
||||
),
|
||||
DoubleVector => Bound(ctrl_type.by(2).expect("invalid type for double_vector")),
|
||||
SplitLanes => Bound(
|
||||
ctrl_type
|
||||
.split_lanes()
|
||||
.expect("invalid type for split_lanes"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +279,16 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Split the lane width in half and double the number of lanes to maintain the same bit-width.
|
||||
///
|
||||
/// If this is a scalar type of n bits, it produces a SIMD vector type of (n/2)x2.
|
||||
pub fn split_lanes(self) -> Option<Self> {
|
||||
match self.half_width() {
|
||||
Some(half_width) => half_width.by(2),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Index of this type, for use with hash tables etc.
|
||||
pub fn index(self) -> usize {
|
||||
usize::from(self.0)
|
||||
|
||||
Reference in New Issue
Block a user