https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/216034
Backport 70998dbeda3a9f29b38af26e5256feeeeb20acea Requested by: @heiher >From 33a5142252b5b6a406fce96e112d0c8d226fd674 Mon Sep 17 00:00:00 2001 From: hev <[email protected]> Date: Thu, 13 Aug 2026 20:31:41 +0800 Subject: [PATCH] [clang][LoongArch] Match GCC ABI handling of integer complex types (#215222) GNU integer complex types such as `_Complex unsigned char` and `_Complex unsigned short` were incorrectly recognized as eligible floating-point ABI aggregates by `detectFARsEligibleStructHelper`. When used as a member of a structure, this caused the real and imaginary parts to be expanded into separate general-purpose argument registers. Integer complex types are not floating-point complex types and should be handled as ordinary aggregates. Restrict the complex-type expansion path to elements with real floating-point types, allowing small integer complex aggregates to be packed into a single general-purpose register, consistent with GCC. Fixes #214810 (cherry picked from commit 70998dbeda3a9f29b38af26e5256feeeeb20acea) --- clang/lib/CodeGen/Targets/LoongArch.cpp | 6 +++++ clang/test/CodeGen/LoongArch/abi-lp64d.c | 28 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 878723d67f081..ca080b22fcabd 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -135,6 +135,12 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( 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 GARs instead. + if (!EltTy->isRealFloatingType()) + return false; if (getContext().getTypeSize(EltTy) > FRLen) return false; Field1Ty = CGT.ConvertType(EltTy); diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d.c b/clang/test/CodeGen/LoongArch/abi-lp64d.c index 9f64cfd662e5f..6bee262f30fa2 100644 --- a/clang/test/CodeGen/LoongArch/abi-lp64d.c +++ b/clang/test/CodeGen/LoongArch/abi-lp64d.c @@ -501,6 +501,34 @@ struct doublecomplex_s f_doublecomplex_s(struct doublecomplex_s x) { return x; } +/// A complex integer, or a structure containing just one complex integer +/// (a GNU extension), is not eligible to be passed in floating-point +/// registers; it is passed as though it were an aggregate of the same +/// size, i.e. packed into a single GAR when its size does not exceed +/// GRLen. + +// CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex(i64 %x.coerce) +unsigned char __complex__ f_ucharcomplex(unsigned char __complex__ x) { return x; } + +// CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex(i64 %x.coerce) +unsigned short __complex__ f_ushortcomplex(unsigned short __complex__ x) { return x; } + +struct ucharcomplex_s { + unsigned char __complex__ c; +}; +// CHECK-LABEL: define{{.*}} i64 @f_ucharcomplex_s(i64 %x.coerce) +struct ucharcomplex_s f_ucharcomplex_s(struct ucharcomplex_s x) { + return x; +} + +struct ushortcomplex_s { + unsigned short __complex__ c; +}; +// CHECK-LABEL: define{{.*}} i64 @f_ushortcomplex_s(i64 %x.coerce) +struct ushortcomplex_s f_ushortcomplex_s(struct ushortcomplex_s x) { + return x; +} + /// Part 5: Variadic arguments. /// Variadic arguments are passed in GARs in the same manner as named arguments. _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
