[PATCH] D69590: [RISCV] Fix ILP32D lowering for double+double/double+int return types
James Clarke via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 29 15:36:26 PDT 2019
jrtc27 created this revision.
jrtc27 added a reviewer: asb.
Herald added subscribers: cfe-commits, sameer.abuasal, pzheng, s.egerton, lenary, Jim, benna, psnobl, jocewei, PkmX, rkruppe, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, shiva0217, kito-cheng, niosHD, sabuasal, apazos, simoncook, johnrusso, rbar.
Herald added a project: clang.
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.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D69590
Files:
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/riscv32-ilp32d-abi.c
Index: clang/test/CodeGen/riscv32-ilp32d-abi.c
===================================================================
--- clang/test/CodeGen/riscv32-ilp32d-abi.c
+++ clang/test/CodeGen/riscv32-ilp32d-abi.c
@@ -280,3 +280,27 @@
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 include 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;
+}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -9291,11 +9291,21 @@
FI.getReturnInfo() = classifyReturnType(RetTy);
// IsRetIndirect is true if classifyArgumentType indicated the value should
- // be passed indirect or if the type size is greater than 2*xlen. e.g. fp128
- // is passed direct in LLVM IR, relying on the backend lowering code to
- // rewrite the argument list and pass indirectly on RV32.
- bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect ||
- getContext().getTypeSize(RetTy) > (2 * XLen);
+ // be passed indirect, or if the type size is a scalar greater than 2*XLen
+ // and not a complex type with elements <= FLen. e.g. fp128 is passed direct
+ // in LLVM IR, relying on the backend lowering code to rewrite the argument
+ // list and pass indirectly on RV32.
+ bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
+ if (!IsRetIndirect && RetTy->isScalarType() &&
+ getContext().getTypeSize(RetTy) > (2 * XLen)) {
+ if (RetTy->isComplexType() && FLen) {
+ QualType EltTy = RetTy->getAs<ComplexType>()->getElementType();
+ IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
+ } else {
+ // This is a normal scalar > 2*XLen, such as fp128 on RV32.
+ IsRetIndirect = true;
+ }
+ }
// We must track the number of GPRs used in order to conform to the RISC-V
// ABI, as integer scalars passed in registers should have signext/zeroext
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69590.226981.patch
Type: text/x-patch
Size: 3378 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191029/41056e9a/attachment-0001.bin>
More information about the cfe-commits
mailing list