Add DerivedFunction for doubling lane widths and halving the number of lanes (i.e. merging)
Certain operations (e.g. widening) will have operands with types like `NxM` but will return results with types like `(N*2)x(M/2)` (double the lane width, halve the number of lanes; maintain the same number of vector bits). This is equivalent to applying two `DerivedFunction`s to the type: `DerivedFunction::DoubleWidth` then `DerivedFunction::HalfVector`. 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::MergeLanes` to do the necessary type conversion.
This commit is contained in:
@@ -584,6 +584,9 @@ enum OperandConstraint {
|
||||
|
||||
/// This operand is `ctrlType.split_lanes()`.
|
||||
SplitLanes,
|
||||
|
||||
/// This operand is `ctrlType.merge_lanes()`.
|
||||
MergeLanes,
|
||||
}
|
||||
|
||||
impl OperandConstraint {
|
||||
@@ -615,6 +618,11 @@ impl OperandConstraint {
|
||||
.split_lanes()
|
||||
.expect("invalid type for split_lanes"),
|
||||
),
|
||||
MergeLanes => Bound(
|
||||
ctrl_type
|
||||
.merge_lanes()
|
||||
.expect("invalid type for merge_lanes"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ 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.
|
||||
/// 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),
|
||||
@@ -292,6 +292,17 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge lanes to half the number of lanes and double the lane width to maintain the same
|
||||
/// bit-width.
|
||||
///
|
||||
/// If this is a scalar type, it will return `None`.
|
||||
pub fn merge_lanes(self) -> Option<Self> {
|
||||
match self.double_width() {
|
||||
Some(double_width) => double_width.half_vector(),
|
||||
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