Author: hev Date: 2026-08-13T20:31:41+08:00 New Revision: 70998dbeda3a9f29b38af26e5256feeeeb20acea
URL: https://github.com/llvm/llvm-project/commit/70998dbeda3a9f29b38af26e5256feeeeb20acea DIFF: https://github.com/llvm/llvm-project/commit/70998dbeda3a9f29b38af26e5256feeeeb20acea.diff LOG: [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 Added: Modified: clang/lib/CodeGen/Targets/LoongArch.cpp clang/test/CodeGen/LoongArch/abi-lp64d.c Removed: ################################################################################ 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. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
