Skip to main content

cubecl_core/frontend/
plane.rs

1use cubecl_ir::ExpandValue;
2use half::{bf16, f16};
3
4use super::{CubePrimitive, Vector};
5use crate::prelude::*;
6use crate::{
7    ir::{Scope, attributes::IndexAttr, dialect::plane::*},
8    unexpanded,
9};
10
11pub trait PlaneNumeric {
12    fn __expand_native_sum(scope: &Scope, value: ExpandValue) -> ExpandValue;
13    fn __expand_native_inclusive_sum(scope: &Scope, value: ExpandValue) -> ExpandValue;
14    fn __expand_native_exclusive_sum(scope: &Scope, value: ExpandValue) -> ExpandValue;
15
16    fn __expand_native_prod(scope: &Scope, value: ExpandValue) -> ExpandValue;
17    fn __expand_native_inclusive_prod(scope: &Scope, value: ExpandValue) -> ExpandValue;
18    fn __expand_native_exclusive_prod(scope: &Scope, value: ExpandValue) -> ExpandValue;
19
20    fn __expand_native_plane_min(scope: &Scope, value: ExpandValue) -> ExpandValue;
21    fn __expand_native_plane_max(scope: &Scope, value: ExpandValue) -> ExpandValue;
22}
23
24macro_rules! plane_numeric {
25    ($($ty: ty),*; $sum: ty, $inc_sum: ty, $exc_sum: ty, $prod: ty, $inc_prod: ty, $exc_prod: ty, $min: ty, $max: ty) => {
26        $(impl PlaneNumeric for $ty {
27            fn __expand_native_sum(scope: &Scope, value: ExpandValue) -> ExpandValue {
28                unary_expand(scope, value, <$sum>::new)
29            }
30            fn __expand_native_inclusive_sum(scope: &Scope, value: ExpandValue) -> ExpandValue {
31                unary_expand(scope, value, <$inc_sum>::new)
32            }
33            fn __expand_native_exclusive_sum(scope: &Scope, value: ExpandValue) -> ExpandValue {
34                unary_expand(scope, value, <$exc_sum>::new)
35            }
36
37            fn __expand_native_prod(scope: &Scope, value: ExpandValue) -> ExpandValue {
38                unary_expand(scope, value, <$prod>::new)
39            }
40            fn __expand_native_inclusive_prod(scope: &Scope, value: ExpandValue) -> ExpandValue {
41                unary_expand(scope, value, <$inc_prod>::new)
42            }
43            fn __expand_native_exclusive_prod(scope: &Scope, value: ExpandValue) -> ExpandValue {
44                unary_expand(scope, value, <$exc_prod>::new)
45            }
46
47            fn __expand_native_plane_min(scope: &Scope, value: ExpandValue) -> ExpandValue {
48                unary_expand(scope, value, <$min>::new)
49            }
50            fn __expand_native_plane_max(scope: &Scope, value: ExpandValue) -> ExpandValue {
51                unary_expand(scope, value, <$max>::new)
52            }
53        })*
54    };
55}
56
57plane_numeric!(i8, i16, i32, i64, isize; ISumOp, InclusiveISumOp, ExclusiveISumOp, IProdOp, InclusiveIProdOp, ExclusiveIProdOp, SMinOp, SMaxOp);
58plane_numeric!(u8, u16, u32, u64, usize; ISumOp, InclusiveISumOp, ExclusiveISumOp, IProdOp, InclusiveIProdOp, ExclusiveIProdOp, UMinOp, UMaxOp);
59plane_numeric!(f16, bf16, f32, flex32, tf32, f64; FSumOp, InclusiveFSumOp, ExclusiveFSumOp, FProdOp, InclusiveFProdOp, ExclusiveFProdOp, FMinOp, FMaxOp);
60
61/// Returns true if the cube unit has the lowest `plane_unit_id` among active unit in the plane
62pub fn plane_elect() -> bool {
63    unexpanded!()
64}
65
66/// Module containing the expand function for [`plane_elect()`].
67pub mod plane_elect {
68    use super::*;
69
70    /// Expand method of [`plane_elect()`].
71    pub fn expand(scope: &Scope) -> NativeExpand<bool> {
72        let op = ElectOp::new(scope.ctx_mut());
73        scope.register_with_result(&op).into()
74    }
75}
76
77/// Broadcasts the value from the specified plane unit at the given index
78/// to all active units within that plane. Requires a constant index. For non-constant indices,
79/// use [`plane_shuffle()`].
80#[allow(unused_variables)]
81pub fn plane_broadcast<E: CubePrimitive>(value: E, index: u32) -> E {
82    unexpanded!()
83}
84
85/// Module containing the expand function for [`plane_broadcast()`].
86pub mod plane_broadcast {
87    use super::*;
88
89    /// Expand method of [`plane_broadcast()`].
90    pub fn expand<E: CubePrimitive>(
91        scope: &Scope,
92        value: NativeExpand<E>,
93        id: u32,
94    ) -> NativeExpand<E> {
95        let value = value.read_value(scope);
96        let op = BroadcastOp::new(scope.ctx_mut(), value, IndexAttr::new(id as usize));
97        scope.register_with_result(&op).into()
98    }
99}
100
101/// Perform an arbitrary lane shuffle operation across the plane.
102/// Each unit reads the value from the specified source lane.
103///
104/// # Example
105/// `plane_shuffle(value, 0)` - all lanes read from lane 0 (same as broadcast)
106/// `plane_shuffle(value, lane_id ^ 1)` - butterfly pattern (same as `shuffle_xor`)
107#[allow(unused_variables)]
108pub fn plane_shuffle<E: CubePrimitive>(value: E, src_lane: u32) -> E {
109    unexpanded!()
110}
111
112/// Module containing the expand function for [`plane_shuffle()`].
113pub mod plane_shuffle {
114    use super::*;
115
116    /// Expand method of [`plane_shuffle()`].
117    pub fn expand<E: CubePrimitive>(
118        scope: &Scope,
119        value: NativeExpand<E>,
120        src_lane: NativeExpand<u32>,
121    ) -> NativeExpand<E> {
122        let value = value.read_value(scope);
123        let src_lane = src_lane.read_value(scope);
124        let op = ShuffleOp::new(scope.ctx_mut(), value, src_lane);
125        scope.register_with_result(&op).into()
126    }
127}
128
129/// Perform a shuffle XOR operation across the plane.
130/// Each unit exchanges its value with another unit at an index determined by XOR with the mask.
131/// This is useful for butterfly reduction patterns.
132///
133/// # Example
134/// For a 32-lane warp with mask=1:
135/// - Lane 0 gets value from lane 1, lane 1 gets value from lane 0
136/// - Lane 2 gets value from lane 3, lane 3 gets value from lane 2
137/// - etc.
138#[allow(unused_variables)]
139pub fn plane_shuffle_xor<E: CubePrimitive>(value: E, mask: u32) -> E {
140    unexpanded!()
141}
142
143/// Module containing the expand function for [`plane_shuffle_xor()`].
144pub mod plane_shuffle_xor {
145    use super::*;
146
147    /// Expand method of [`plane_shuffle_xor()`].
148    pub fn expand<E: CubePrimitive>(
149        scope: &Scope,
150        value: NativeExpand<E>,
151        mask: NativeExpand<u32>,
152    ) -> NativeExpand<E> {
153        let value = value.read_value(scope);
154        let mask = mask.read_value(scope);
155        let op = ShuffleXorOp::new(scope.ctx_mut(), value, mask);
156        scope.register_with_result(&op).into()
157    }
158}
159
160/// Perform a shuffle up operation across the plane.
161/// Each unit reads the value from a unit with a lower lane ID (`current_id` - delta).
162/// Units with `lane_id` < delta will read from themselves (no change).
163///
164/// # Example
165/// For delta=1: `[a, b, c, d] -> [a, a, b, c]`
166#[allow(unused_variables)]
167pub fn plane_shuffle_up<E: CubePrimitive>(value: E, delta: u32) -> E {
168    unexpanded!()
169}
170
171/// Module containing the expand function for [`plane_shuffle_up()`].
172pub mod plane_shuffle_up {
173    use super::*;
174
175    /// Expand method of [`plane_shuffle_up()`].
176    pub fn expand<E: CubePrimitive>(
177        scope: &Scope,
178        value: NativeExpand<E>,
179        delta: NativeExpand<u32>,
180    ) -> NativeExpand<E> {
181        let value = value.read_value(scope);
182        let delta = delta.read_value(scope);
183        let op = ShuffleUpOp::new(scope.ctx_mut(), value, delta);
184        scope.register_with_result(&op).into()
185    }
186}
187
188/// Perform a shuffle down operation across the plane.
189/// Each unit reads the value from a unit with a higher lane ID (`current_id` + delta).
190/// Units at the end will read from themselves if (`lane_id` + delta >= `plane_dim`).
191///
192/// # Example
193/// For delta=1: `[a, b, c, d] -> [b, c, d, d]`
194#[allow(unused_variables)]
195pub fn plane_shuffle_down<E: CubePrimitive>(value: E, delta: u32) -> E {
196    unexpanded!()
197}
198
199/// Module containing the expand function for [`plane_shuffle_down()`].
200pub mod plane_shuffle_down {
201    use super::*;
202
203    /// Expand method of [`plane_shuffle_down()`].
204    pub fn expand<E: CubePrimitive>(
205        scope: &Scope,
206        value: NativeExpand<E>,
207        delta: NativeExpand<u32>,
208    ) -> NativeExpand<E> {
209        let value = value.read_value(scope);
210        let delta = delta.read_value(scope);
211        let op = ShuffleDownOp::new(scope.ctx_mut(), value, delta);
212        scope.register_with_result(&op).into()
213    }
214}
215
216/// Perform a reduce sum operation across all units in a plane.
217#[allow(unused_variables)]
218pub fn plane_sum<E: CubePrimitive<Scalar: PlaneNumeric>>(value: E) -> E {
219    unexpanded!()
220}
221
222/// Module containing the expand function for [`plane_sum()`].
223pub mod plane_sum {
224    use super::*;
225
226    /// Expand method of [`plane_sum()`].
227    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
228        scope: &Scope,
229        elem: NativeExpand<E>,
230    ) -> NativeExpand<E> {
231        E::Scalar::__expand_native_sum(scope, elem.into()).into()
232    }
233}
234
235/// Perform an inclusive sum operation across all units in a plane.
236/// This sums all values to the "left" of the unit, including this unit's value.
237/// Also known as "prefix sum" or "inclusive scan".
238///
239/// # Example
240/// `inclusive_sum([1, 2, 3, 4, 5]) == [1, 3, 6, 10, 15]`
241#[allow(unused_variables)]
242pub fn plane_inclusive_sum<E: CubePrimitive<Scalar: PlaneNumeric>>(value: E) -> E {
243    unexpanded!()
244}
245
246/// Module containing the expand function for [`plane_inclusive_sum()`].
247pub mod plane_inclusive_sum {
248    use super::*;
249
250    /// Expand method of [`plane_inclusive_sum()`].
251    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
252        scope: &Scope,
253        elem: NativeExpand<E>,
254    ) -> NativeExpand<E> {
255        E::Scalar::__expand_native_inclusive_sum(scope, elem.into()).into()
256    }
257}
258
259/// Perform an exclusive sum operation across all units in a plane.
260/// This sums all values to the "left" of the unit, excluding this unit's value. The 0th unit will
261/// be set to `E::zero()`.
262/// Also known as "exclusive prefix sum" or "exclusive scan".
263///
264/// # Example
265/// `exclusive_sum([1, 2, 3, 4, 5]) == [0, 1, 3, 6, 10]`
266#[allow(unused_variables)]
267pub fn plane_exclusive_sum<E: CubePrimitive<Scalar: PlaneNumeric>>(value: E) -> E {
268    unexpanded!()
269}
270
271/// Module containing the expand function for [`plane_exclusive_sum()`].
272pub mod plane_exclusive_sum {
273    use super::*;
274
275    /// Expand method of [`plane_exclusive_sum()`].
276    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
277        scope: &Scope,
278        elem: NativeExpand<E>,
279    ) -> NativeExpand<E> {
280        E::Scalar::__expand_native_exclusive_sum(scope, elem.into()).into()
281    }
282}
283
284/// Perform a reduce prod operation across all units in a plane.
285pub fn plane_prod<E: CubePrimitive<Scalar: PlaneNumeric>>(_elem: E) -> E {
286    unexpanded!()
287}
288
289/// Module containing the expand function for [`plane_prod()`].
290pub mod plane_prod {
291    use super::*;
292
293    /// Expand method of [`plane_prod()`].
294    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
295        scope: &Scope,
296        elem: NativeExpand<E>,
297    ) -> NativeExpand<E> {
298        E::Scalar::__expand_native_prod(scope, elem.into()).into()
299    }
300}
301
302/// Perform an inclusive product operation across all units in a plane.
303/// This multiplies all values to the "left" of the unit, including this unit's value.
304/// Also known as "prefix product" or "inclusive scan".
305///
306/// # Example
307/// `exclusive_prod([1, 2, 3, 4, 5]) == [1, 2, 6, 24, 120]`
308#[allow(unused_variables)]
309pub fn plane_inclusive_prod<E: CubePrimitive<Scalar: PlaneNumeric>>(value: E) -> E {
310    unexpanded!()
311}
312
313/// Module containing the expand function for [`plane_inclusive_prod()`].
314pub mod plane_inclusive_prod {
315    use super::*;
316
317    /// Expand method of [`plane_inclusive_prod()`].
318    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
319        scope: &Scope,
320        elem: NativeExpand<E>,
321    ) -> NativeExpand<E> {
322        E::Scalar::__expand_native_inclusive_prod(scope, elem.into()).into()
323    }
324}
325
326/// Perform an exclusive product operation across all units in a plane.
327/// This multiplies all values to the "left" of the unit, excluding this unit's value. The 0th unit
328/// will be set to `E::one()`.
329/// Also known as "exclusive prefix product" or "exclusive scan".
330///
331/// # Example
332/// `exclusive_prod([1, 2, 3, 4, 5]) == [1, 1, 2, 6, 24]`
333#[allow(unused_variables)]
334pub fn plane_exclusive_prod<E: CubePrimitive<Scalar: PlaneNumeric>>(value: E) -> E {
335    unexpanded!()
336}
337
338/// Module containing the expand function for [`plane_exclusive_prod()`].
339pub mod plane_exclusive_prod {
340    use super::*;
341
342    /// Expand method of [`plane_exclusive_prod()`].
343    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
344        scope: &Scope,
345        elem: NativeExpand<E>,
346    ) -> NativeExpand<E> {
347        E::Scalar::__expand_native_exclusive_prod(scope, elem.into()).into()
348    }
349}
350
351/// Perform a reduce max operation across all units in a plane.
352pub fn plane_max<E: CubePrimitive<Scalar: PlaneNumeric>>(_elem: E) -> E {
353    unexpanded!()
354}
355
356/// Module containing the expand function for [`plane_max()`].
357pub mod plane_max {
358    use super::*;
359
360    /// Expand method of [`plane_max()`].
361    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
362        scope: &Scope,
363        elem: NativeExpand<E>,
364    ) -> NativeExpand<E> {
365        E::Scalar::__expand_native_plane_max(scope, elem.into()).into()
366    }
367}
368
369/// Perform a reduce min operation across all units in a plane.
370pub fn plane_min<E: CubePrimitive<Scalar: PlaneNumeric>>(_elem: E) -> E {
371    unexpanded!()
372}
373
374/// Module containing the expand function for [`plane_min()`].
375pub mod plane_min {
376    use super::*;
377
378    /// Expand method of [`plane_min()`].
379    pub fn expand<E: CubePrimitive<Scalar: PlaneNumeric>>(
380        scope: &Scope,
381        elem: NativeExpand<E>,
382    ) -> NativeExpand<E> {
383        E::Scalar::__expand_native_plane_min(scope, elem.into()).into()
384    }
385}
386
387/// Perform a reduce all operation across all units in a plane.
388pub fn plane_all(_elem: bool) -> bool {
389    unexpanded!()
390}
391
392/// Module containing the expand function for [`plane_all()`].
393pub mod plane_all {
394    use super::*;
395
396    /// Expand method of [`plane_all()`].
397    pub fn expand(scope: &Scope, elem: NativeExpand<bool>) -> NativeExpand<bool> {
398        let value = elem.read_value(scope);
399        let op = AllOp::new(scope.ctx_mut(), value);
400        scope.register_with_result(&op).into()
401    }
402}
403
404/// Perform a reduce any operation across all units in a plane.
405pub fn plane_any(_elem: bool) -> bool {
406    unexpanded!()
407}
408
409/// Module containing the expand function for [`plane_any()`].
410pub mod plane_any {
411    use super::*;
412
413    /// Expand method of [`plane_any()`].
414    pub fn expand(scope: &Scope, elem: NativeExpand<bool>) -> NativeExpand<bool> {
415        let value = elem.read_value(scope);
416        let op = AnyOp::new(scope.ctx_mut(), value);
417        scope.register_with_result(&op).into()
418    }
419}
420
421/// Perform a ballot operation across all units in a plane.
422/// Returns a set of 32-bit bitfields as a [`Vector`], with each element containing the value from 32
423/// invocations.
424/// Note that vector size will always be set to 4 even for `PLANE_DIM <= 64`, because we can't
425/// retrieve the actual plane size at expand time. Use the runtime`PLANE_DIM` to index appropriately.
426pub fn plane_ballot(_elem: bool) -> Vector<u32, Const<4>> {
427    unexpanded!()
428}
429
430/// Module containing the expand function for [`plane_ballot()`].
431pub mod plane_ballot {
432    use super::*;
433
434    /// Expand method of [`plane_ballot()`].
435    pub fn expand(scope: &Scope, elem: NativeExpand<bool>) -> NativeExpand<Vector<u32, Const<4>>> {
436        let value = elem.read_value(scope);
437        let op = BallotOp::new(scope.ctx_mut(), value);
438        scope.register_with_result(&op).into()
439    }
440}