Skip to content

Commit 71c14cd

Browse files
tclin914tstellar
authored andcommitted
[RISCV] Fix passing two floating-point values in complex separately by two GPRs on RV64
Summary: This patch fixed the error of counting the remaining FPRs. Complex floating-point values should be passed by two FPRs for the hard-float ABI. If no two FPRs are available, it should be passed via a 64-bit GPR (fp+fp). `ArgFPRsLeft` is only decreased one while the type is complex floating-point. It causes two floating-point values in the complex are passed separately by two GPRs. Reviewers: asb, luismarques, lenary Reviewed By: asb Subscribers: rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, s.egerton, pzheng, sameer.abuasal, apazos, evandro, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D79770 (cherry picked from commit 7ee479a)
1 parent f8e49af commit 71c14cd

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

clang/lib/CodeGen/TargetInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9613,7 +9613,8 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
96139613
uint64_t Size = getContext().getTypeSize(Ty);
96149614

96159615
// Pass floating point values via FPRs if possible.
9616-
if (IsFixed && Ty->isFloatingType() && FLen >= Size && ArgFPRsLeft) {
9616+
if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
9617+
FLen >= Size && ArgFPRsLeft) {
96179618
ArgFPRsLeft--;
96189619
return ABIArgInfo::getDirect();
96199620
}

clang/test/CodeGen/riscv64-lp64-abi.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,24 @@ struct large f_scalar_stack_2(double a, __int128_t b, long double c, v32i8 d,
3030
uint8_t e, int8_t f, uint8_t g) {
3131
return (struct large){a, e, f, g};
3232
}
33+
34+
// Complex floating-point values or structs containing a single complex
35+
// floating-point value should be passed in a GPR.
36+
37+
// CHECK: define void @f_floatcomplex(i64 %a.coerce)
38+
void f_floatcomplex(float __complex__ a) {}
39+
40+
// CHECK: define i64 @f_ret_floatcomplex()
41+
float __complex__ f_ret_floatcomplex() {
42+
return 1.0;
43+
}
44+
45+
struct floatcomplex_s { float __complex__ c; };
46+
47+
// CHECK: define void @f_floatcomplex_s_arg(i64 %a.coerce)
48+
void f_floatcomplex_s_arg(struct floatcomplex_s a) {}
49+
50+
// CHECK: define i64 @f_ret_floatcomplex_s()
51+
struct floatcomplex_s f_ret_floatcomplex_s() {
52+
return (struct floatcomplex_s){1.0};
53+
}

clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,35 @@ struct floatcomplex_s f_ret_floatcomplex_s() {
165165
return (struct floatcomplex_s){1.0};
166166
}
167167

168+
// Complex floating-point values or structs containing a single complex
169+
// floating-point value should be passed in GPRs if no two FPRs is available.
170+
171+
// CHECK: define void @f_floatcomplex_insufficient_fprs1(float %a.coerce0, float %a.coerce1, float %b.coerce0, float %b.coerce1, float %c.coerce0, float %c.coerce1, float %d.coerce0, float %d.coerce1, i64 %e.coerce)
172+
void f_floatcomplex_insufficient_fprs1(float __complex__ a, float __complex__ b,
173+
float __complex__ c, float __complex__ d,
174+
float __complex__ e) {}
175+
176+
177+
// CHECK: define void @f_floatcomplex_s_arg_insufficient_fprs1(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i64 %e.coerce)
178+
void f_floatcomplex_s_arg_insufficient_fprs1(struct floatcomplex_s a,
179+
struct floatcomplex_s b,
180+
struct floatcomplex_s c,
181+
struct floatcomplex_s d,
182+
struct floatcomplex_s e) {}
183+
184+
// CHECK: define void @f_floatcomplex_insufficient_fprs2(float %a, float %b.coerce0, float %b.coerce1, float %c.coerce0, float %c.coerce1, float %d.coerce0, float %d.coerce1, i64 %e.coerce)
185+
void f_floatcomplex_insufficient_fprs2(float a,
186+
float __complex__ b, float __complex__ c,
187+
float __complex__ d, float __complex__ e) {}
188+
189+
190+
// CHECK: define void @f_floatcomplex_s_arg_insufficient_fprs2(float %a, float %0, float %1, float %2, float %3, float %4, float %5, i64 %e.coerce)
191+
void f_floatcomplex_s_arg_insufficient_fprs2(float a,
192+
struct floatcomplex_s b,
193+
struct floatcomplex_s c,
194+
struct floatcomplex_s d,
195+
struct floatcomplex_s e) {}
196+
168197
// Test single or two-element structs that need flattening. e.g. those
169198
// containing nested structs, floats in small arrays, zero-length structs etc.
170199

0 commit comments

Comments
 (0)