summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp3
-rw-r--r--clang/test/CodeGen/riscv64-lp64-abi.c21
-rw-r--r--clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c29
3 files changed, 52 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 682ef18da73..e2380f5581c 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -9613,7 +9613,8 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
uint64_t Size = getContext().getTypeSize(Ty);
// Pass floating point values via FPRs if possible.
- if (IsFixed && Ty->isFloatingType() && FLen >= Size && ArgFPRsLeft) {
+ if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
+ FLen >= Size && ArgFPRsLeft) {
ArgFPRsLeft--;
return ABIArgInfo::getDirect();
}
diff --git a/clang/test/CodeGen/riscv64-lp64-abi.c b/clang/test/CodeGen/riscv64-lp64-abi.c
index bae5470c377..a89e75e58a4 100644
--- a/clang/test/CodeGen/riscv64-lp64-abi.c
+++ b/clang/test/CodeGen/riscv64-lp64-abi.c
@@ -30,3 +30,24 @@ struct large f_scalar_stack_2(double a, __int128_t b, long double c, v32i8 d,
uint8_t e, int8_t f, uint8_t g) {
return (struct large){a, e, f, g};
}
+
+// Complex floating-point values or structs containing a single complex
+// floating-point value should be passed in a GPR.
+
+// CHECK: define void @f_floatcomplex(i64 %a.coerce)
+void f_floatcomplex(float __complex__ a) {}
+
+// CHECK: define i64 @f_ret_floatcomplex()
+float __complex__ f_ret_floatcomplex() {
+ return 1.0;
+}
+
+struct floatcomplex_s { float __complex__ c; };
+
+// CHECK: define void @f_floatcomplex_s_arg(i64 %a.coerce)
+void f_floatcomplex_s_arg(struct floatcomplex_s a) {}
+
+// CHECK: define i64 @f_ret_floatcomplex_s()
+struct floatcomplex_s f_ret_floatcomplex_s() {
+ return (struct floatcomplex_s){1.0};
+}
diff --git a/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c
index 9a44928cac8..7a25cef6cad 100644
--- a/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c
+++ b/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c
@@ -165,6 +165,35 @@ struct floatcomplex_s f_ret_floatcomplex_s() {
return (struct floatcomplex_s){1.0};
}
+// Complex floating-point values or structs containing a single complex
+// floating-point value should be passed in GPRs if no two FPRs is available.
+
+// 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)
+void f_floatcomplex_insufficient_fprs1(float __complex__ a, float __complex__ b,
+ float __complex__ c, float __complex__ d,
+ float __complex__ e) {}
+
+
+// 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)
+void f_floatcomplex_s_arg_insufficient_fprs1(struct floatcomplex_s a,
+ struct floatcomplex_s b,
+ struct floatcomplex_s c,
+ struct floatcomplex_s d,
+ struct floatcomplex_s e) {}
+
+// 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)
+void f_floatcomplex_insufficient_fprs2(float a,
+ float __complex__ b, float __complex__ c,
+ float __complex__ d, float __complex__ e) {}
+
+
+// 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)
+void f_floatcomplex_s_arg_insufficient_fprs2(float a,
+ struct floatcomplex_s b,
+ struct floatcomplex_s c,
+ struct floatcomplex_s d,
+ struct floatcomplex_s e) {}
+
// Test single or two-element structs that need flattening. e.g. those
// containing nested structs, floats in small arrays, zero-length structs etc.
OpenPOWER on IntegriCloud