cubecl_cpp/shared/
convert.rs1use cubecl_core::ir::{
5 NamedRewrite,
6 dialect::{OperationPtrExt, general::CastOp},
7 interfaces::ValueExt,
8 prelude::{Context, MatchRewriter, Operation, Ptr, Result},
9 rewrite::MatchRewritePass,
10 types::scalar::Float32Type,
11 verify_op_succ,
12};
13use pliron::{
14 builtin::{
15 op_interfaces::OneResultInterface,
16 types::{IntegerType, Signedness},
17 },
18 derive::op_interface,
19 irbuild::match_rewrite::MatchRewrite,
20 op::Op,
21 r#type::{TypeHandle, Typed},
22 value::Value,
23};
24
25#[op_interface]
26pub trait HalfPromotedOp: OneResultInterface {
27 verify_op_succ!();
28}
29
30#[op_interface]
31pub trait IntPromotedOp: OneResultInterface {
32 verify_op_succ!();
33}
34
35macro_rules! no_half {
36 ($ty: ty) => {
37 #[pliron::derive::op_interface_impl]
38 impl $crate::shared::convert::HalfPromotedOp for $ty {}
39 };
40}
41
42pub(crate) use no_half;
43
44macro_rules! promotes_int {
45 ($ty: ty) => {
46 #[pliron::derive::op_interface_impl]
47 impl $crate::shared::convert::IntPromotedOp for $ty {}
48 };
49}
50pub(crate) use promotes_int;
51
52use crate::shared::ty::TypedExtCPP;
53
54pub type PromoteUnsupportedTypesPass = MatchRewritePass<PromoteUnsupportedTypes>;
55
56#[derive(Default, NamedRewrite)]
57pub struct PromoteUnsupportedTypes;
58
59impl MatchRewrite for PromoteUnsupportedTypes {
60 fn r#match(&mut self, ctx: &Context, op: Ptr<Operation>) -> bool {
61 let promote_half = op.impls::<dyn HalfPromotedOp>(ctx) && op.result(ctx).is_half(ctx);
62 let promote_int = op.impls::<dyn IntPromotedOp>(ctx) && op.result(ctx).is_small_int(ctx);
63 promote_half || promote_int
64 }
65
66 fn rewrite(
67 &mut self,
68 ctx: &mut Context,
69 _rewriter: &mut MatchRewriter,
70 op: Ptr<Operation>,
71 ) -> Result<()> {
72 if op.impls::<dyn HalfPromotedOp>(ctx) && op.result(ctx).is_half(ctx) {
73 let f32 = Float32Type::get(ctx).to_handle();
74 promote(ctx, op, |ctx, value| value.is_half(ctx), f32);
75 }
76 if op.impls::<dyn IntPromotedOp>(ctx) && op.result(ctx).is_small_signed_int(ctx) {
77 let i32 = IntegerType::get(ctx, 32, Signedness::Signed).to_handle();
78 promote(ctx, op, |ctx, value| value.is_small_int(ctx), i32);
79 }
80 if op.impls::<dyn IntPromotedOp>(ctx) && op.result(ctx).is_small_unsigned_int(ctx) {
81 let u32 = IntegerType::get(ctx, 32, Signedness::Unsigned).to_handle();
82 promote(ctx, op, |ctx, value| value.is_small_int(ctx), u32);
83 }
84
85 Ok(())
86 }
87}
88
89fn promote(
90 ctx: &mut Context,
91 op: Ptr<Operation>,
92 pred: impl Fn(&Context, Value) -> bool,
93 promoted_type: TypeHandle,
94) {
95 let res = op.result(ctx);
96 let res_ty = res.get_type(ctx);
97
98 for r#use in op.operands_as_uses(ctx) {
99 let value = r#use.get_def(ctx);
100 if pred(ctx, value) {
101 let cast = CastOp::new(ctx, promoted_type, value);
102 cast.get_operation().insert_before(ctx, op);
103 value.replace_use_with(ctx, r#use, &cast.get_result(ctx));
104 }
105 }
106
107 res.set_type(ctx, promoted_type);
108 let cast_res = CastOp::new(ctx, res_ty, res);
109 let new_res = cast_res.get_result(ctx);
110 cast_res.get_operation().insert_after(ctx, op);
111 res.replace_all_uses_except_with(ctx, cast_res.input_as_use(ctx), &new_res);
112}