cubecl-cpp 0.11.0-pre.4

CPP transpiler for CubeCL
Documentation
use cubecl_core::{
    frontend::cast_value,
    ir::{ContextExt, dialect::plane::*, types::scalar::BoolType},
    prelude::*,
};
use pliron::{
    builtin::types::{IntegerType, Signedness},
    derive::op_interface_impl,
    value::Value,
};

use crate::{
    cuda::{cuda_op_with_out, ptx::InlinePtxOp},
    ptx_block,
    shared::{CompilationOptions, elect, lowering::LowerOp},
    target::Cuda,
};

cuda_op_with_out!(BroadcastOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    let lane = op.lane(ctx).0;
    format!("__shfl_sync(__activemask(), {val}, {lane})")
});

cuda_op_with_out!(ShuffleOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    let lane = op.lane(ctx).name(ctx);
    format!("__shfl_sync(__activemask(), {val}, {lane})")
});

cuda_op_with_out!(ShuffleXorOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    let mask = op.mask(ctx).name(ctx);
    format!("__shfl_xor_sync(__activemask(), {val}, {mask})")
});

cuda_op_with_out!(ShuffleUpOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    let delta = op.delta(ctx).name(ctx);
    format!("__shfl_up_sync(__activemask(), {val}, {delta})")
});

cuda_op_with_out!(ShuffleDownOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    let delta = op.delta(ctx).name(ctx);
    format!("__shfl_down_sync(__activemask(), {val}, {delta})")
});

cuda_op_with_out!(AllOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    format!("__all_sync(__activemask(), {val})")
});

cuda_op_with_out!(AnyOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    format!("__any_sync(__activemask(), {val})")
});

cuda_op_with_out!(BallotOp, |op, ctx| {
    let val = op.input(ctx).name(ctx);
    format!("{{__ballot_sync(__activemask(), {val}), 0, 0, 0}}")
});

#[op_interface_impl]
impl LowerOp<Cuda> for ElectOp {
    fn lower(&self, scope: &cubecl_core::ir::Scope) -> Vec<Value> {
        let ctx = scope.ctx_mut();
        let opts = ctx.aux_ty::<CompilationOptions>();
        let native_elect = opts.supports_features.elect_sync;
        if native_elect {
            let u32 = IntegerType::get(ctx, 32, Signedness::Unsigned).to_handle();
            let ptx = ptx_block! {
                ".reg .pred %%px;"
                ".reg .b32 %mask;"
                "activemask.b32 %mask;"
                "elect.sync _|%%px, %mask;"
                "selp.b32 $0, 1, 0, %%px;"
            };
            let op = InlinePtxOp::new_volatile(ctx, Some(u32), ptx, vec![]);
            scope.register(&op);
            let cast = cast_value(scope, op.result(ctx).unwrap(), BoolType::get(ctx).into());
            vec![cast]
        } else {
            vec![elect::expand::<u32>(scope).read_value(scope)]
        }
    }
}