Skip to content

Commit 5aeca3b

Browse files
committed
[CFE][X86] Enable complex _Float16 support
Support complex _Float16 on X86 in C/C++ following the latest X86 psABI. (https://gitlab.com/x86-psABIs) Reviewed By: LuoYuanke Differential Revision: https://reviews.llvm.org/D105331
1 parent 59dfde7 commit 5aeca3b

File tree

5 files changed

+152
-4
lines changed

5 files changed

+152
-4
lines changed

clang/lib/CodeGen/TargetInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,14 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
15241524
if (isEmptyRecord(getContext(), RetTy, true))
15251525
return ABIArgInfo::getIgnore();
15261526

1527+
// Return complex of _Float16 as <2 x half> so the backend will use xmm0.
1528+
if (const ComplexType *CT = RetTy->getAs<ComplexType>()) {
1529+
QualType ET = getContext().getCanonicalType(CT->getElementType());
1530+
if (ET->isFloat16Type())
1531+
return ABIArgInfo::getDirect(llvm::FixedVectorType::get(
1532+
llvm::Type::getHalfTy(getVMContext()), 2));
1533+
}
1534+
15271535
// Small structures which are register sized are generally returned
15281536
// in a register.
15291537
if (shouldReturnTypeInRegister(RetTy, getContext())) {

clang/lib/Sema/DeclSpec.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,8 +1300,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
13001300
if (!S.getLangOpts().CPlusPlus)
13011301
S.Diag(TSTLoc, diag::ext_integer_complex);
13021302
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double &&
1303-
TypeSpecType != TST_float128) {
1304-
// FIXME: _Float16, __fp16?
1303+
TypeSpecType != TST_float128 && TypeSpecType != TST_float16) {
1304+
// FIXME: __fp16?
13051305
S.Diag(TSCLoc, diag::err_invalid_complex_spec)
13061306
<< getSpecifierName((TST)TypeSpecType, Policy);
13071307
TypeSpecComplex = TSC_unspecified;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -target-feature +avx512fp16 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
2+
3+
// Return value should be passed in <2 x half> so the backend will use xmm0
4+
_Complex _Float16 f16(_Complex _Float16 A, _Complex _Float16 B) {
5+
// CHECK-LABEL: define{{.*}}<2 x half> @f16({ half, half }* byval({ half, half }) align 4 %{{.*}}, { half, half }* byval({ half, half }) align 4 %{{.*}})
6+
return A + B;
7+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// RUN: %clang_cc1 %s -O0 -fno-experimental-new-pass-manager -emit-llvm -triple x86_64-unknown-unknown -target-feature +avx512fp16 -o - | FileCheck %s --check-prefix=X86
2+
3+
_Float16 _Complex add_half_rr(_Float16 a, _Float16 b) {
4+
// X86-LABEL: @add_half_rr(
5+
// X86: fadd
6+
// X86-NOT: fadd
7+
// X86: ret
8+
return a + b;
9+
}
10+
_Float16 _Complex add_half_cr(_Float16 _Complex a, _Float16 b) {
11+
// X86-LABEL: @add_half_cr(
12+
// X86: fadd
13+
// X86-NOT: fadd
14+
// X86: ret
15+
return a + b;
16+
}
17+
_Float16 _Complex add_half_rc(_Float16 a, _Float16 _Complex b) {
18+
// X86-LABEL: @add_half_rc(
19+
// X86: fadd
20+
// X86-NOT: fadd
21+
// X86: ret
22+
return a + b;
23+
}
24+
_Float16 _Complex add_half_cc(_Float16 _Complex a, _Float16 _Complex b) {
25+
// X86-LABEL: @add_half_cc(
26+
// X86: fadd
27+
// X86: fadd
28+
// X86-NOT: fadd
29+
// X86: ret
30+
return a + b;
31+
}
32+
33+
_Float16 _Complex sub_half_rr(_Float16 a, _Float16 b) {
34+
// X86-LABEL: @sub_half_rr(
35+
// X86: fsub
36+
// X86-NOT: fsub
37+
// X86: ret
38+
return a - b;
39+
}
40+
_Float16 _Complex sub_half_cr(_Float16 _Complex a, _Float16 b) {
41+
// X86-LABEL: @sub_half_cr(
42+
// X86: fsub
43+
// X86-NOT: fsub
44+
// X86: ret
45+
return a - b;
46+
}
47+
_Float16 _Complex sub_half_rc(_Float16 a, _Float16 _Complex b) {
48+
// X86-LABEL: @sub_half_rc(
49+
// X86: fsub
50+
// X86: fneg
51+
// X86-NOT: fsub
52+
// X86: ret
53+
return a - b;
54+
}
55+
_Float16 _Complex sub_half_cc(_Float16 _Complex a, _Float16 _Complex b) {
56+
// X86-LABEL: @sub_half_cc(
57+
// X86: fsub
58+
// X86: fsub
59+
// X86-NOT: fsub
60+
// X86: ret
61+
return a - b;
62+
}
63+
64+
_Float16 _Complex mul_half_rr(_Float16 a, _Float16 b) {
65+
// X86-LABEL: @mul_half_rr(
66+
// X86: fmul
67+
// X86-NOT: fmul
68+
// X86: ret
69+
return a * b;
70+
}
71+
_Float16 _Complex mul_half_cr(_Float16 _Complex a, _Float16 b) {
72+
// X86-LABEL: @mul_half_cr(
73+
// X86: fmul
74+
// X86: fmul
75+
// X86-NOT: fmul
76+
// X86: ret
77+
return a * b;
78+
}
79+
_Float16 _Complex mul_half_rc(_Float16 a, _Float16 _Complex b) {
80+
// X86-LABEL: @mul_half_rc(
81+
// X86: fmul
82+
// X86: fmul
83+
// X86-NOT: fmul
84+
// X86: ret
85+
return a * b;
86+
}
87+
_Float16 _Complex mul_half_cc(_Float16 _Complex a, _Float16 _Complex b) {
88+
// X86-LABEL: @mul_half_cc(
89+
// X86: %[[AC:[^ ]+]] = fmul
90+
// X86: %[[BD:[^ ]+]] = fmul
91+
// X86: %[[AD:[^ ]+]] = fmul
92+
// X86: %[[BC:[^ ]+]] = fmul
93+
// X86: %[[RR:[^ ]+]] = fsub half %[[AC]], %[[BD]]
94+
// X86: %[[RI:[^ ]+]] = fadd half
95+
// X86-DAG: %[[AD]]
96+
// X86-DAG: ,
97+
// X86-DAG: %[[BC]]
98+
// X86: fcmp uno half %[[RR]]
99+
// X86: fcmp uno half %[[RI]]
100+
// X86: call {{.*}} @__mulhc3(
101+
// X86: ret
102+
return a * b;
103+
}
104+
105+
_Float16 _Complex div_half_rr(_Float16 a, _Float16 b) {
106+
// X86-LABEL: @div_half_rr(
107+
// X86: fdiv
108+
// X86-NOT: fdiv
109+
// X86: ret
110+
return a / b;
111+
}
112+
_Float16 _Complex div_half_cr(_Float16 _Complex a, _Float16 b) {
113+
// X86-LABEL: @div_half_cr(
114+
// X86: fdiv
115+
// X86: fdiv
116+
// X86-NOT: fdiv
117+
// X86: ret
118+
return a / b;
119+
}
120+
_Float16 _Complex div_half_rc(_Float16 a, _Float16 _Complex b) {
121+
// X86-LABEL: @div_half_rc(
122+
// X86-NOT: fdiv
123+
// X86: call {{.*}} @__divhc3(
124+
// X86: ret
125+
return a / b;
126+
}
127+
_Float16 _Complex div_half_cc(_Float16 _Complex a, _Float16 _Complex b) {
128+
// X86-LABEL: @div_half_cc(
129+
// X86-NOT: fdiv
130+
// X86: call {{.*}} @__divhc3(
131+
// X86: ret
132+
return a / b;
133+
}

clang/test/Sema/Float16.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc -target-feature +avx512fp16 %s -DHAVE
23
// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE
34
// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE
45
// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE
@@ -9,8 +10,7 @@
910
_Float16 f;
1011

1112
#ifdef HAVE
12-
// FIXME: Should this be valid?
13-
_Complex _Float16 a; // expected-error {{'_Complex _Float16' is invalid}}
13+
_Complex _Float16 a;
1414
void builtin_complex() {
1515
_Float16 a = 0;
1616
(void)__builtin_complex(a, a); // expected-error {{'_Complex _Float16' is invalid}}

0 commit comments

Comments
 (0)