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:
Andrew Brown
2020-03-25 10:15:06 -07:00
parent f5fc09f64a
commit 341dc45cea
3 changed files with 43 additions and 0 deletions

View File

@@ -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"),
),
}
}
}

View File

@@ -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)