Skip to content

Commit 0e5e8a6

Browse files
committed
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, https://github.com/bytecodealliance/wasmtime/blob/1d5a678124e0f035f7614cafe43066c834a5113b/cranelift/codegen/meta/src/gen_inst.rs#L618-L621), I added `DerivedFunction::MergeLanes` to do the necessary type conversion.
1 parent 12a31c8 commit 0e5e8a6

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

cranelift/codegen/meta/src/cdsl/typevar.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,24 @@ impl TypeVar {
211211
"can't double 256 lanes"
212212
);
213213
}
214+
DerivedFunc::MergeLanes => {
215+
assert!(
216+
ts.ints.is_empty() || *ts.ints.iter().max().unwrap() < MAX_BITS,
217+
"can't double all integer types"
218+
);
219+
assert!(
220+
ts.floats.is_empty() || *ts.floats.iter().max().unwrap() < MAX_FLOAT_BITS,
221+
"can't double all float types"
222+
);
223+
assert!(
224+
ts.bools.is_empty() || *ts.bools.iter().max().unwrap() < MAX_BITS,
225+
"can't double all boolean types"
226+
);
227+
assert!(
228+
*ts.lanes.iter().min().unwrap() > 1,
229+
"can't halve a scalar type"
230+
);
231+
}
214232
DerivedFunc::LaneOf | DerivedFunc::AsBool => { /* no particular assertions */ }
215233
}
216234

@@ -248,6 +266,9 @@ impl TypeVar {
248266
pub fn split_lanes(&self) -> TypeVar {
249267
self.derived(DerivedFunc::SplitLanes)
250268
}
269+
pub fn merge_lanes(&self) -> TypeVar {
270+
self.derived(DerivedFunc::MergeLanes)
271+
}
251272

252273
/// Constrain the range of types this variable can assume to a subset of those in the typeset
253274
/// ts.
@@ -355,6 +376,7 @@ pub(crate) enum DerivedFunc {
355376
HalfVector,
356377
DoubleVector,
357378
SplitLanes,
379+
MergeLanes,
358380
}
359381

360382
impl DerivedFunc {
@@ -367,6 +389,7 @@ impl DerivedFunc {
367389
DerivedFunc::HalfVector => "half_vector",
368390
DerivedFunc::DoubleVector => "double_vector",
369391
DerivedFunc::SplitLanes => "split_lanes",
392+
DerivedFunc::MergeLanes => "merge_lanes",
370393
}
371394
}
372395

@@ -377,6 +400,8 @@ impl DerivedFunc {
377400
DerivedFunc::DoubleWidth => Some(DerivedFunc::HalfWidth),
378401
DerivedFunc::HalfVector => Some(DerivedFunc::DoubleVector),
379402
DerivedFunc::DoubleVector => Some(DerivedFunc::HalfVector),
403+
DerivedFunc::MergeLanes => Some(DerivedFunc::SplitLanes),
404+
DerivedFunc::SplitLanes => Some(DerivedFunc::MergeLanes),
380405
_ => None,
381406
}
382407
}
@@ -462,6 +487,7 @@ impl TypeSet {
462487
DerivedFunc::HalfVector => self.half_vector(),
463488
DerivedFunc::DoubleVector => self.double_vector(),
464489
DerivedFunc::SplitLanes => self.half_width().double_vector(),
490+
DerivedFunc::MergeLanes => self.double_width().half_vector(),
465491
}
466492
}
467493

@@ -601,7 +627,8 @@ impl TypeSet {
601627
DerivedFunc::DoubleWidth => self.half_width(),
602628
DerivedFunc::HalfVector => self.double_vector(),
603629
DerivedFunc::DoubleVector => self.half_vector(),
604-
DerivedFunc::SplitLanes => self.half_vector().double_width(),
630+
DerivedFunc::SplitLanes => self.double_width().half_vector(),
631+
DerivedFunc::MergeLanes => self.half_width().double_vector(),
605632
}
606633
}
607634

cranelift/codegen/src/ir/instructions.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ enum OperandConstraint {
584584

585585
/// This operand is `ctrlType.split_lanes()`.
586586
SplitLanes,
587+
588+
/// This operand is `ctrlType.merge_lanes()`.
589+
MergeLanes,
587590
}
588591

589592
impl OperandConstraint {
@@ -615,6 +618,11 @@ impl OperandConstraint {
615618
.split_lanes()
616619
.expect("invalid type for split_lanes"),
617620
),
621+
MergeLanes => Bound(
622+
ctrl_type
623+
.merge_lanes()
624+
.expect("invalid type for merge_lanes"),
625+
),
618626
}
619627
}
620628
}

cranelift/codegen/src/ir/types.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,25 @@ impl Type {
284284

285285
/// Split the lane width in half and double the number of lanes to maintain the same bit-width.
286286
///
287-
/// If this is a scalar type of n bits, it produces a SIMD vector type of (n/2)x2.
287+
/// If this is a scalar type of `n` bits, it produces a SIMD vector type of `(n/2)x2`.
288288
pub fn split_lanes(self) -> Option<Self> {
289289
match self.half_width() {
290290
Some(half_width) => half_width.by(2),
291291
None => None,
292292
}
293293
}
294294

295+
/// Merge lanes to half the number of lanes and double the lane width to maintain the same
296+
/// bit-width.
297+
///
298+
/// If this is a scalar type, it will return `None`.
299+
pub fn merge_lanes(self) -> Option<Self> {
300+
match self.double_width() {
301+
Some(double_width) => double_width.half_vector(),
302+
None => None,
303+
}
304+
}
305+
295306
/// Index of this type, for use with hash tables etc.
296307
pub fn index(self) -> usize {
297308
usize::from(self.0)

0 commit comments

Comments
 (0)