Skip to content

Commit 90366de

Browse files
committed
[CIR] Add support for float16 and bfloat
This patch adds two new CIR floating-point types, namely `!cir.f16` and `!cir.bf16`, to represent the float16 format and bfloat format, respectively. CIRGen, LLVMIR lowering, and MLIR lowering for the two new types are also included in this patch. This patch converts the clang extension type `_Float16` to `!cir.f16`, and converts the clang extension type `__bf16` type to `!cir.bf16`. The type conversion for clang extension type `__fp16` is not included in this patch since it requires additional work during CIRGen.
1 parent 981c976 commit 90366de

File tree

11 files changed

+439
-76
lines changed

11 files changed

+439
-76
lines changed

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

+16-1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,20 @@ def CIR_Double : CIR_FloatType<"Double", "double"> {
150150
}];
151151
}
152152

153+
def CIR_FP16 : CIR_FloatType<"FP16", "f16"> {
154+
let summary = "CIR type that represents IEEE-754 binary16 format";
155+
let description = [{
156+
Floating-point type that represents the IEEE-754 binary16 format.
157+
}];
158+
}
159+
160+
def CIR_BFloat16 : CIR_FloatType<"BF16", "bf16"> {
161+
let summary = "CIR type that represents";
162+
let description = [{
163+
Floating-point type that represents the bfloat16 format.
164+
}];
165+
}
166+
153167
def CIR_FP80 : CIR_FloatType<"FP80", "f80"> {
154168
let summary = "CIR type that represents x87 80-bit floating-point format";
155169
let description = [{
@@ -179,7 +193,8 @@ def CIR_LongDouble : CIR_FloatType<"LongDouble", "long_double"> {
179193

180194
// Constraints
181195

182-
def CIR_AnyFloat: AnyTypeOf<[CIR_Single, CIR_Double, CIR_LongDouble]>;
196+
def CIR_AnyFloat: AnyTypeOf<[CIR_Single, CIR_Double, CIR_FP16, CIR_BFloat16,
197+
CIR_FP80, CIR_LongDouble]>;
183198
def CIR_AnyIntOrFloat: AnyTypeOf<[CIR_AnyFloat, CIR_IntType]>;
184199

185200
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenModule.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,11 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
131131
// Initialize CIR pointer types cache.
132132
VoidPtrTy = ::mlir::cir::PointerType::get(builder.getContext(), VoidTy);
133133

134-
// TODO: HalfTy
135-
// TODO: BFloatTy
134+
FP16Ty = ::mlir::cir::FP16Type::get(builder.getContext());
135+
BFloat16Ty = ::mlir::cir::BF16Type::get(builder.getContext());
136136
FloatTy = ::mlir::cir::SingleType::get(builder.getContext());
137137
DoubleTy = ::mlir::cir::DoubleType::get(builder.getContext());
138138
FP80Ty = ::mlir::cir::FP80Type::get(builder.getContext());
139-
// TODO(cir): perhaps we should abstract long double variations into a custom
140-
// cir.long_double type. Said type would also hold the semantics for lowering.
141139

142140
// TODO: PointerWidthInBits
143141
PointerAlignInBytes =

clang/lib/CIR/CodeGen/CIRGenTypeCache.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,9 @@ struct CIRGenTypeCache {
3434
mlir::cir::IntType SInt8Ty, SInt16Ty, SInt32Ty, SInt64Ty;
3535
// usigned char, unsigned, unsigned short, unsigned long
3636
mlir::cir::IntType UInt8Ty, UInt16Ty, UInt32Ty, UInt64Ty;
37-
/// half, bfloat, float, double
38-
// mlir::Type HalfTy, BFloatTy;
39-
// TODO(cir): perhaps we should abstract long double variations into a custom
40-
// cir.long_double type. Said type would also hold the semantics for lowering.
37+
/// half, bfloat, float, double, fp80
38+
mlir::cir::FP16Type FP16Ty;
39+
mlir::cir::BF16Type BFloat16Ty;
4140
mlir::cir::SingleType FloatTy;
4241
mlir::cir::DoubleType DoubleTy;
4342
mlir::cir::FP80Type FP80Ty;

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -464,14 +464,14 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) {
464464
break;
465465

466466
case BuiltinType::Float16:
467-
ResultType = Builder.getF16Type();
467+
ResultType = CGM.FP16Ty;
468468
break;
469469
case BuiltinType::Half:
470470
// Should be the same as above?
471471
assert(0 && "not implemented");
472472
break;
473473
case BuiltinType::BFloat16:
474-
ResultType = Builder.getBF16Type();
474+
ResultType = CGM.BFloat16Ty;
475475
break;
476476
case BuiltinType::Float:
477477
ResultType = CGM.FloatTy;

clang/lib/CIR/Dialect/IR/CIRTypes.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,48 @@ DoubleType::getPreferredAlignment(const ::mlir::DataLayout &dataLayout,
692692
return (uint64_t)(getWidth() / 8);
693693
}
694694

695+
const llvm::fltSemantics &FP16Type::getFloatSemantics() const {
696+
return llvm::APFloat::IEEEhalf();
697+
}
698+
699+
llvm::TypeSize
700+
FP16Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
701+
mlir::DataLayoutEntryListRef params) const {
702+
return llvm::TypeSize::getFixed(getWidth());
703+
}
704+
705+
uint64_t FP16Type::getABIAlignment(const mlir::DataLayout &dataLayout,
706+
mlir::DataLayoutEntryListRef params) const {
707+
return (uint64_t)(getWidth() / 8);
708+
}
709+
710+
uint64_t
711+
FP16Type::getPreferredAlignment(const ::mlir::DataLayout &dataLayout,
712+
::mlir::DataLayoutEntryListRef params) const {
713+
return (uint64_t)(getWidth() / 8);
714+
}
715+
716+
const llvm::fltSemantics &BF16Type::getFloatSemantics() const {
717+
return llvm::APFloat::BFloat();
718+
}
719+
720+
llvm::TypeSize
721+
BF16Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
722+
mlir::DataLayoutEntryListRef params) const {
723+
return llvm::TypeSize::getFixed(getWidth());
724+
}
725+
726+
uint64_t BF16Type::getABIAlignment(const mlir::DataLayout &dataLayout,
727+
mlir::DataLayoutEntryListRef params) const {
728+
return (uint64_t)(getWidth() / 8);
729+
}
730+
731+
uint64_t
732+
BF16Type::getPreferredAlignment(const ::mlir::DataLayout &dataLayout,
733+
::mlir::DataLayoutEntryListRef params) const {
734+
return (uint64_t)(getWidth() / 8);
735+
}
736+
695737
const llvm::fltSemantics &FP80Type::getFloatSemantics() const {
696738
return llvm::APFloat::x87DoubleExtended();
697739
}

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,12 @@ void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
30493049
converter.addConversion([&](mlir::cir::DoubleType type) -> mlir::Type {
30503050
return mlir::FloatType::getF64(type.getContext());
30513051
});
3052+
converter.addConversion([&](mlir::cir::FP16Type type) -> mlir::Type {
3053+
return mlir::FloatType::getF16(type.getContext());
3054+
});
3055+
converter.addConversion([&](mlir::cir::BF16Type type) -> mlir::Type {
3056+
return mlir::FloatType::getBF16(type.getContext());
3057+
});
30523058
converter.addConversion([&](mlir::cir::FP80Type type) -> mlir::Type {
30533059
return mlir::FloatType::getF80(type.getContext());
30543060
});

clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,12 @@ static mlir::TypeConverter prepareTypeConverter() {
883883
converter.addConversion([&](mlir::cir::DoubleType type) -> mlir::Type {
884884
return mlir::FloatType::getF64(type.getContext());
885885
});
886+
converter.addConversion([&](mlir::cir::FP16Type type) -> mlir::Type {
887+
return mlir::FloatType::getF16(type.getContext());
888+
});
889+
converter.addConversion([&](mlir::cir::BF16Type type) -> mlir::Type {
890+
return mlir::FloatType::getBF16(type.getContext());
891+
});
886892
converter.addConversion([&](mlir::cir::FP80Type type) -> mlir::Type {
887893
return mlir::FloatType::getF80(type.getContext());
888894
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
4+
__bf16 add1(__bf16 a, __bf16 b) {
5+
return a + b;
6+
}
7+
8+
// CHECK: cir.func @add1(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
9+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
10+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
11+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#A]], %[[#B]]) : !cir.bf16
12+
// CHECK: }
13+
14+
__bf16 add2(__bf16 a, __bf16 b, __bf16 c) {
15+
return a + b + c;
16+
}
17+
18+
// CHECK: cir.func @add2(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
19+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
20+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
21+
// CHECK-NEXT: %[[#A_B:]] = cir.binop(add, %[[#A]], %[[#B]]) : !cir.bf16
22+
// CHECK-NEXT: %[[#C:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
23+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#A_B]], %[[#C]]) : !cir.bf16
24+
// CHECK: }
25+
26+
__bf16 div(__bf16 a, __bf16 b) {
27+
return a / b;
28+
}
29+
30+
// CHECK: cir.func @div(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
31+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
32+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
33+
// CHECK-NEXT: %{{.+}} = cir.binop(div, %[[#A]], %[[#B]]) : !cir.bf16
34+
// CHECK: }
35+
36+
__bf16 mul(__bf16 a, __bf16 b) {
37+
return a * b;
38+
}
39+
40+
// CHECK: cir.func @mul(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
41+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
42+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
43+
// CHECK-NEXT: %{{.+}} = cir.binop(mul, %[[#A]], %[[#B]]) : !cir.bf16
44+
// CHECK: }
45+
46+
__bf16 add_and_mul1(__bf16 a, __bf16 b, __bf16 c, __bf16 d) {
47+
return a * b + c * d;
48+
}
49+
50+
// CHECK: cir.func @add_and_mul1(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}}])) -> !cir.bf16
51+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
52+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
53+
// CHECK-NEXT: %[[#A_B:]] = cir.binop(mul, %[[#A]], %[[#B]]) : !cir.bf16
54+
// CHECK-NEXT: %[[#C:]] = cir.load %2 : !cir.ptr<!cir.bf16>, !cir.bf16
55+
// CHECK-NEXT: %[[#D:]] = cir.load %3 : !cir.ptr<!cir.bf16>, !cir.bf16
56+
// CHECK-NEXT: %[[#C_D:]] = cir.binop(mul, %[[#C]], %[[#D]]) : !cir.bf16
57+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#A_B]], %[[#C_D]]) : !cir.bf16
58+
// CHECK: }
59+
60+
__bf16 add_and_mul2(__bf16 a, __bf16 b, __bf16 c) {
61+
return (a - 6 * b) + c;
62+
}
63+
64+
// CHECK: cir.func @add_and_mul2(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
65+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
66+
// CHECK-NEXT: %[[#SIX:]] = cir.const #cir.int<6> : !s32i
67+
// CHECK-NEXT: %[[#SIX_FP:]] = cir.cast(int_to_float, %[[#SIX]] : !s32i), !cir.bf16
68+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
69+
// CHECK-NEXT: %[[#SIX_B:]] = cir.binop(mul, %[[#SIX_FP]], %[[#B]]) : !cir.bf16
70+
// CHECK-NEXT: %[[#ADD_LHS:]] = cir.binop(sub, %[[#A]], %[[#SIX_B]]) : !cir.bf16
71+
// CHECK-NEXT: %[[#C:]] = cir.load %2 : !cir.ptr<!cir.bf16>, !cir.bf16
72+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#ADD_LHS]], %[[#C]]) : !cir.bf16
73+
// CHECK: }
74+
75+
__bf16 addcompound(__bf16 a, __bf16 c) {
76+
c += a;
77+
return c;
78+
}
79+
80+
// CHECK: cir.func @addcompound(%{{.+}}: !cir.bf16 loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
81+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
82+
// CHECK-NEXT: %[[#C_OLD:]] = cir.load %[[#C_PTR:]] : !cir.ptr<!cir.bf16>, !cir.bf16
83+
// CHECK-NEXT: %[[#C_NEW:]] = cir.binop(add, %[[#C_OLD]], %[[#A]]) : !cir.bf16
84+
// CHECK-NEXT: cir.store %[[#C_NEW]], %[[#C_PTR]] : !cir.bf16, !cir.ptr<!cir.bf16>
85+
// CHECK: }
86+
87+
__bf16 mulcompound_int__bf16(int a, __bf16 c) {
88+
a *= c;
89+
return c;
90+
}
91+
92+
// CHECK: cir.func @mulcompound_int__bf16(%{{.+}}: !s32i loc({{.+}}), %{{.+}}: !cir.bf16 loc({{.+}})) -> !cir.bf16
93+
// CHECK: %[[#C:]] = cir.load %{{.+}} : !cir.ptr<!cir.bf16>, !cir.bf16
94+
// CHECK-NEXT: %[[#A_OLD:]] = cir.load %[[#A_PTR:]] : !cir.ptr<!s32i>, !s32i
95+
// CHECK-NEXT: %[[#A_FP:]] = cir.cast(int_to_float, %[[#A_OLD]] : !s32i), !cir.bf16
96+
// CHECK-NEXT: %[[#A_NEW_FP:]] = cir.binop(mul, %[[#A_FP]], %[[#C]]) : !cir.bf16
97+
// CHECK-NEXT: %[[#A_NEW:]] = cir.cast(float_to_int, %[[#A_NEW_FP]] : !cir.bf16), !s32i
98+
// CHECK-NEXT: cir.store %[[#A_NEW]], %[[#A_PTR]] : !s32i, !cir.ptr<!s32i>
99+
// CHECK: }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
4+
_Float16 add1(_Float16 a, _Float16 b) {
5+
return a + b;
6+
}
7+
8+
// CHECK: cir.func @add1(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
9+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
10+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
11+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#A]], %[[#B]]) : !cir.f16
12+
// CHECK: }
13+
14+
_Float16 add2(_Float16 a, _Float16 b, _Float16 c) {
15+
return a + b + c;
16+
}
17+
18+
// CHECK: cir.func @add2(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
19+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
20+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
21+
// CHECK-NEXT: %[[#A_B:]] = cir.binop(add, %[[#A]], %[[#B]]) : !cir.f16
22+
// CHECK-NEXT: %[[#C:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
23+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#A_B]], %[[#C]]) : !cir.f16
24+
// CHECK: }
25+
26+
_Float16 div(_Float16 a, _Float16 b) {
27+
return a / b;
28+
}
29+
30+
// CHECK: cir.func @div(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
31+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
32+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
33+
// CHECK-NEXT: %{{.+}} = cir.binop(div, %[[#A]], %[[#B]]) : !cir.f16
34+
// CHECK: }
35+
36+
_Float16 mul(_Float16 a, _Float16 b) {
37+
return a * b;
38+
}
39+
40+
// CHECK: cir.func @mul(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
41+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
42+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
43+
// CHECK-NEXT: %{{.+}} = cir.binop(mul, %[[#A]], %[[#B]]) : !cir.f16
44+
// CHECK: }
45+
46+
_Float16 add_and_mul1(_Float16 a, _Float16 b, _Float16 c, _Float16 d) {
47+
return a * b + c * d;
48+
}
49+
50+
// CHECK: cir.func @add_and_mul1(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}}])) -> !cir.f16
51+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
52+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
53+
// CHECK-NEXT: %[[#A_B:]] = cir.binop(mul, %[[#A]], %[[#B]]) : !cir.f16
54+
// CHECK-NEXT: %[[#C:]] = cir.load %2 : !cir.ptr<!cir.f16>, !cir.f16
55+
// CHECK-NEXT: %[[#D:]] = cir.load %3 : !cir.ptr<!cir.f16>, !cir.f16
56+
// CHECK-NEXT: %[[#C_D:]] = cir.binop(mul, %[[#C]], %[[#D]]) : !cir.f16
57+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#A_B]], %[[#C_D]]) : !cir.f16
58+
// CHECK: }
59+
60+
_Float16 add_and_mul2(_Float16 a, _Float16 b, _Float16 c) {
61+
return (a - 6 * b) + c;
62+
}
63+
64+
// CHECK: cir.func @add_and_mul2(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
65+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
66+
// CHECK-NEXT: %[[#SIX:]] = cir.const #cir.int<6> : !s32i
67+
// CHECK-NEXT: %[[#SIX_FP:]] = cir.cast(int_to_float, %[[#SIX]] : !s32i), !cir.f16
68+
// CHECK-NEXT: %[[#B:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
69+
// CHECK-NEXT: %[[#SIX_B:]] = cir.binop(mul, %[[#SIX_FP]], %[[#B]]) : !cir.f16
70+
// CHECK-NEXT: %[[#ADD_LHS:]] = cir.binop(sub, %[[#A]], %[[#SIX_B]]) : !cir.f16
71+
// CHECK-NEXT: %[[#C:]] = cir.load %2 : !cir.ptr<!cir.f16>, !cir.f16
72+
// CHECK-NEXT: %{{.+}} = cir.binop(add, %[[#ADD_LHS]], %[[#C]]) : !cir.f16
73+
// CHECK: }
74+
75+
_Float16 addcompound(_Float16 a, _Float16 c) {
76+
c += a;
77+
return c;
78+
}
79+
80+
// CHECK: cir.func @addcompound(%{{.+}}: !cir.f16 loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
81+
// CHECK: %[[#A:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
82+
// CHECK-NEXT: %[[#C_OLD:]] = cir.load %[[#C_PTR:]] : !cir.ptr<!cir.f16>, !cir.f16
83+
// CHECK-NEXT: %[[#C_NEW:]] = cir.binop(add, %[[#C_OLD]], %[[#A]]) : !cir.f16
84+
// CHECK-NEXT: cir.store %[[#C_NEW]], %[[#C_PTR]] : !cir.f16, !cir.ptr<!cir.f16>
85+
// CHECK: }
86+
87+
_Float16 mulcompound_int_float16(int a, _Float16 c) {
88+
a *= c;
89+
return c;
90+
}
91+
92+
// CHECK: cir.func @mulcompound_int_float16(%{{.+}}: !s32i loc({{.+}}), %{{.+}}: !cir.f16 loc({{.+}})) -> !cir.f16
93+
// CHECK: %[[#C:]] = cir.load %{{.+}} : !cir.ptr<!cir.f16>, !cir.f16
94+
// CHECK-NEXT: %[[#A_OLD:]] = cir.load %[[#A_PTR:]] : !cir.ptr<!s32i>, !s32i
95+
// CHECK-NEXT: %[[#A_FP:]] = cir.cast(int_to_float, %[[#A_OLD]] : !s32i), !cir.f16
96+
// CHECK-NEXT: %[[#A_NEW_FP:]] = cir.binop(mul, %[[#A_FP]], %[[#C]]) : !cir.f16
97+
// CHECK-NEXT: %[[#A_NEW:]] = cir.cast(float_to_int, %[[#A_NEW_FP]] : !cir.f16), !s32i
98+
// CHECK-NEXT: cir.store %[[#A_NEW]], %[[#A_PTR]] : !s32i, !cir.ptr<!s32i>
99+
// CHECK: }

0 commit comments

Comments
 (0)