summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorJames Clarke <jrtc27@jrtc27.com>2020-01-14 11:17:19 +0000
committerJames Clarke <jrtc27@jrtc27.com>2020-01-14 11:17:19 +0000
commit3d6c492d7a9830a1a39b85dfa215743581d52715 (patch)
treed386e32b723c8cefa62ae4233b7a0ea147b6e7dc /clang/test
parent4624a1e8ac8a3f69cc887403b976f538f587744a (diff)
downloadbcm5719-llvm-3d6c492d7a9830a1a39b85dfa215743581d52715.tar.gz
bcm5719-llvm-3d6c492d7a9830a1a39b85dfa215743581d52715.zip
[RISCV] Fix ILP32D lowering for double+double/double+int return types
Summary: Previously, since these aggregates are > 2*XLen, Clang would think they were being returned indirectly and thus would decrease the number of available GPRs available by 1. For long argument lists this could lead to a struct argument incorrectly being passed indirectly. Reviewers: asb, lenary Reviewed By: asb, lenary Subscribers: luismarques, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, lenary, s.egerton, pzheng, sameer.abuasal, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D69590
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGen/riscv32-ilp32d-abi.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/clang/test/CodeGen/riscv32-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32d-abi.c
index 078fcb6b5ab..b5b451cee15 100644
--- a/clang/test/CodeGen/riscv32-ilp32d-abi.c
+++ b/clang/test/CodeGen/riscv32-ilp32d-abi.c
@@ -280,3 +280,27 @@ void f_double_u_arg(union double_u a) {}
union double_u f_ret_double_u() {
return (union double_u){1.0};
}
+
+// Test that we don't incorrectly think double+int/double+double structs will
+// be returned indirectly and thus have an off-by-one error for the number of
+// GPRs available (this is an edge case when structs > 2*XLEN are still
+// returned in registers). This includes complex doubles, which are treated as
+// double+double structs by the ABI.
+
+// CHECK: define { double, i32 } @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, double %0, i32 %1)
+struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(
+ int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
+ return (struct double_int32_s){1.0, 2};
+}
+
+// CHECK: define { double, double } @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, double %0, i32 %1)
+struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs(
+ int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
+ return (struct double_double_s){1.0, 2.0};
+}
+
+// CHECK: define { double, double } @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, double %0, i32 %1)
+double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(
+ int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
+ return 1.0;
+}
OpenPOWER on IntegriCloud