https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/216404
>From 77105ec5c27e155a36aabcdb999079516d5de48f Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Fri, 14 Aug 2026 21:08:52 +0200 Subject: [PATCH 1/2] [RISCV] make `_Complex {integer}` consistent with GCC Complex integers should not be passed via FPRs. --- clang/lib/CodeGen/Targets/RISCV.cpp | 6 ++++++ clang/test/CodeGen/RISCV/riscv32-abi.c | 23 +++++++++-------------- clang/test/CodeGen/RISCV/riscv64-abi.c | 23 +++++++++-------------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index ce2352ca76284..4bac5711a2dd6 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -225,6 +225,12 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, if (Field1Ty) return false; QualType EltTy = CTy->getElementType(); + // Only floating-point complex types (e.g. _Complex float/double) are + // eligible to be passed in floating-point argument registers. Complex + // integer types (a GNU extension) should be treated like a normal + // aggregate and packed into GPRs instead. + if (!EltTy->isRealFloatingType()) + return false; if (getContext().getTypeSize(EltTy) > FLen) return false; Field1Ty = CGT.ConvertType(EltTy); diff --git a/clang/test/CodeGen/RISCV/riscv32-abi.c b/clang/test/CodeGen/RISCV/riscv32-abi.c index e9f7e6c26a0dc..9fa34a9a75cf2 100644 --- a/clang/test/CodeGen/RISCV/riscv32-abi.c +++ b/clang/test/CodeGen/RISCV/riscv32-abi.c @@ -1888,6 +1888,9 @@ struct float16complex_s f_ret_float16complex_s(void) { return (struct float16complex_s){1.0}; } +// Complex integer values or structs containing a single complex +// integer value should be passed as if it were an int+int struct. + // CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex(i64 %x.coerce) // ILP32-ILP32F-ILP32D-LABEL: define dso_local i16 @f_ucharcomplex // ILP32-ILP32F-ILP32D-SAME: (i16 noundef [[X_COERCE:%.*]]) #[[ATTR0]] { @@ -1906,13 +1909,9 @@ struct ucharcomplex_s { unsigned char __complex__ c; }; // CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex_s(i64 %x.coerce) -// ILP32-LABEL: define dso_local i16 @f_ucharcomplex_s -// ILP32-SAME: (i16 [[X_COERCE:%.*]]) #[[ATTR0]] { -// ILP32: entry: -// -// ILP32F-ILP32D-LABEL: define dso_local { i8, i8 } @f_ucharcomplex_s -// ILP32F-ILP32D-SAME: (i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] { -// ILP32F-ILP32D: entry: +// ILP32-ILP32F-ILP32D-LABEL: define dso_local i16 @f_ucharcomplex_s +// ILP32-ILP32F-ILP32D-SAME: (i16 [[X_COERCE:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D: entry: // struct ucharcomplex_s f_ucharcomplex_s(struct ucharcomplex_s x) { return x; @@ -1922,13 +1921,9 @@ struct ushortcomplex_s { unsigned short __complex__ c; }; // CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex_s(i64 %x.coerce) -// ILP32-LABEL: define dso_local i32 @f_ushortcomplex_s -// ILP32-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] { -// ILP32: entry: -// -// ILP32F-ILP32D-LABEL: define dso_local { i16, i16 } @f_ushortcomplex_s -// ILP32F-ILP32D-SAME: (i16 [[TMP0:%.*]], i16 [[TMP1:%.*]]) #[[ATTR0]] { -// ILP32F-ILP32D: entry: +// ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ushortcomplex_s +// ILP32-ILP32F-ILP32D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D: entry: // struct ushortcomplex_s f_ushortcomplex_s(struct ushortcomplex_s x) { return x; diff --git a/clang/test/CodeGen/RISCV/riscv64-abi.c b/clang/test/CodeGen/RISCV/riscv64-abi.c index ac5524720ee31..4a2f89e9ec6b1 100644 --- a/clang/test/CodeGen/RISCV/riscv64-abi.c +++ b/clang/test/CodeGen/RISCV/riscv64-abi.c @@ -709,6 +709,9 @@ struct floatcomplex_s f_ret_floatcomplex_s(void) { return (struct floatcomplex_s){1.0}; } +// Complex integer values or structs containing a single complex +// integer value should be passed as if it were an int+int struct. + // CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex(i64 %x.coerce) // LP64-LP64F-LP64D-LABEL: define dso_local i16 @f_ucharcomplex // LP64-LP64F-LP64D-SAME: (i16 noundef [[X_COERCE:%.*]]) #[[ATTR0]] { @@ -727,13 +730,9 @@ struct ucharcomplex_s { unsigned char __complex__ c; }; // CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex_s(i64 %x.coerce) -// LP64-LABEL: define dso_local i16 @f_ucharcomplex_s -// LP64-SAME: (i16 [[X_COERCE:%.*]]) #[[ATTR0]] { -// LP64: entry: -// -// LP64F-LP64D-LABEL: define dso_local { i8, i8 } @f_ucharcomplex_s -// LP64F-LP64D-SAME: (i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) #[[ATTR0]] { -// LP64F-LP64D: entry: +// LP64-LP64F-LP64D-LABEL: define dso_local i16 @f_ucharcomplex_s +// LP64-LP64F-LP64D-SAME: (i16 [[X_COERCE:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D: entry: // struct ucharcomplex_s f_ucharcomplex_s(struct ucharcomplex_s x) { return x; @@ -743,13 +742,9 @@ struct ushortcomplex_s { unsigned short __complex__ c; }; // CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex_s(i64 %x.coerce) -// LP64-LABEL: define dso_local i32 @f_ushortcomplex_s -// LP64-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] { -// LP64: entry: -// -// LP64F-LP64D-LABEL: define dso_local { i16, i16 } @f_ushortcomplex_s -// LP64F-LP64D-SAME: (i16 [[TMP0:%.*]], i16 [[TMP1:%.*]]) #[[ATTR0]] { -// LP64F-LP64D: entry: +// LP64-LP64F-LP64D-LABEL: define dso_local i32 @f_ushortcomplex_s +// LP64-LP64F-LP64D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D: entry: // struct ushortcomplex_s f_ushortcomplex_s(struct ushortcomplex_s x) { return x; >From 6fc1907c1d893f8f5303a09a01ee8626c5247446 Mon Sep 17 00:00:00 2001 From: Folkert de Vries <[email protected]> Date: Sat, 15 Aug 2026 00:01:57 +0200 Subject: [PATCH 2/2] remove ignored check lines --- clang/test/CodeGen/RISCV/riscv32-abi.c | 4 ---- clang/test/CodeGen/RISCV/riscv64-abi.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/clang/test/CodeGen/RISCV/riscv32-abi.c b/clang/test/CodeGen/RISCV/riscv32-abi.c index 9fa34a9a75cf2..fe4cb21146ee8 100644 --- a/clang/test/CodeGen/RISCV/riscv32-abi.c +++ b/clang/test/CodeGen/RISCV/riscv32-abi.c @@ -1891,14 +1891,12 @@ struct float16complex_s f_ret_float16complex_s(void) { // Complex integer values or structs containing a single complex // integer value should be passed as if it were an int+int struct. -// CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex(i64 %x.coerce) // ILP32-ILP32F-ILP32D-LABEL: define dso_local i16 @f_ucharcomplex // ILP32-ILP32F-ILP32D-SAME: (i16 noundef [[X_COERCE:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // unsigned char __complex__ f_ucharcomplex(unsigned char __complex__ x) { return x; } -// CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex(i64 %x.coerce) // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ushortcomplex // ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: @@ -1908,7 +1906,6 @@ unsigned short __complex__ f_ushortcomplex(unsigned short __complex__ x) { retur struct ucharcomplex_s { unsigned char __complex__ c; }; -// CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex_s(i64 %x.coerce) // ILP32-ILP32F-ILP32D-LABEL: define dso_local i16 @f_ucharcomplex_s // ILP32-ILP32F-ILP32D-SAME: (i16 [[X_COERCE:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: @@ -1920,7 +1917,6 @@ struct ucharcomplex_s f_ucharcomplex_s(struct ucharcomplex_s x) { struct ushortcomplex_s { unsigned short __complex__ c; }; -// CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex_s(i64 %x.coerce) // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_ushortcomplex_s // ILP32-ILP32F-ILP32D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: diff --git a/clang/test/CodeGen/RISCV/riscv64-abi.c b/clang/test/CodeGen/RISCV/riscv64-abi.c index 4a2f89e9ec6b1..88a64f41f71b9 100644 --- a/clang/test/CodeGen/RISCV/riscv64-abi.c +++ b/clang/test/CodeGen/RISCV/riscv64-abi.c @@ -712,14 +712,12 @@ struct floatcomplex_s f_ret_floatcomplex_s(void) { // Complex integer values or structs containing a single complex // integer value should be passed as if it were an int+int struct. -// CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex(i64 %x.coerce) // LP64-LP64F-LP64D-LABEL: define dso_local i16 @f_ucharcomplex // LP64-LP64F-LP64D-SAME: (i16 noundef [[X_COERCE:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // unsigned char __complex__ f_ucharcomplex(unsigned char __complex__ x) { return x; } -// CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex(i64 %x.coerce) // LP64-LP64F-LP64D-LABEL: define dso_local i32 @f_ushortcomplex // LP64-LP64F-LP64D-SAME: (i32 noundef [[X_COERCE:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: @@ -729,7 +727,6 @@ unsigned short __complex__ f_ushortcomplex(unsigned short __complex__ x) { retur struct ucharcomplex_s { unsigned char __complex__ c; }; -// CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex_s(i64 %x.coerce) // LP64-LP64F-LP64D-LABEL: define dso_local i16 @f_ucharcomplex_s // LP64-LP64F-LP64D-SAME: (i16 [[X_COERCE:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: @@ -741,7 +738,6 @@ struct ucharcomplex_s f_ucharcomplex_s(struct ucharcomplex_s x) { struct ushortcomplex_s { unsigned short __complex__ c; }; -// CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex_s(i64 %x.coerce) // LP64-LP64F-LP64D-LABEL: define dso_local i32 @f_ushortcomplex_s // LP64-LP64F-LP64D-SAME: (i32 [[X_COERCE:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
