Author: Phoebe Wang Date: 2026-06-24T10:17:54+08:00 New Revision: ca368598052824548c753faf227bcf1dfc443cfd
URL: https://github.com/llvm/llvm-project/commit/ca368598052824548c753faf227bcf1dfc443cfd DIFF: https://github.com/llvm/llvm-project/commit/ca368598052824548c753faf227bcf1dfc443cfd.diff LOG: [clang] Exclude EmptyRecord when calculating larger CXX records (#205040) To match with GCC: https://godbolt.org/z/KPKGhhenK Fixes: #203760 Assisted-by: Claude Sonnet 4.6 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/CodeGen/Targets/X86.cpp clang/test/CodeGen/X86/avx-cxx-record.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0ff8e8f5afd3c..8bb17755b28f5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -113,6 +113,8 @@ ABI Changes in This Version compilers. On most targets this is not a breaking change because ``fastcc`` and the platform C calling convention agree for ``void(ptr)``. It is an ABI break on i686, MIPS O32, PowerPC64 ELFv1, and Lanai. +- Fixed incorrect struct return when single large vector (256/512-bit) used on + x86-64 targets. (#GH203760) The bug was introduced since Clang 21. (#GH120670) AST Dumping Potentially Breaking Changes ---------------------------------------- diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index dbe4d656aabc5..abf903647336d 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2085,6 +2085,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, Lo = merge(Lo, FieldLo); Hi = merge(Hi, FieldHi); if (returnCXXRecordGreaterThan128InMem() && + !isEmptyRecord(getContext(), I.getType(), true) && (Size > 128 && (Size != getContext().getTypeSize(I.getType()) || Size > getNativeVectorSizeForAVXABI(AVXLevel)))) { // The only case a 256(or 512)-bit wide vector could be used to return diff --git a/clang/test/CodeGen/X86/avx-cxx-record.cpp b/clang/test/CodeGen/X86/avx-cxx-record.cpp index b20bcdd616a43..e64cef32e78ec 100644 --- a/clang/test/CodeGen/X86/avx-cxx-record.cpp +++ b/clang/test/CodeGen/X86/avx-cxx-record.cpp @@ -46,3 +46,21 @@ YMM2 bar() { ((YMM1<1>*)&result)->x = UInt64x4{5, 6, 7, 8}; return result; } + +// Test that empty base classes do not prevent structs with a single wide +// vector member from being passed/returned in registers (issue #203760). +struct EmptyBase {}; + +struct YMMWithEmptyBase : EmptyBase { + UInt64x4 x; +}; + +// A struct with a single 256-bit vector and an empty base should use registers, +// matching the behavior with no base class. +// CHECK: define{{.*}} <4 x i64> @_Z18ymm_empty_base_retv() +// CLANG-20: define{{.*}} <4 x i64> @_Z18ymm_empty_base_retv() +YMMWithEmptyBase ymm_empty_base_ret() { return {}; } + +// CHECK: define{{.*}} i64 @_Z19ymm_empty_base_pass16YMMWithEmptyBase(<4 x i64> +// CLANG-20: define{{.*}} i64 @_Z19ymm_empty_base_pass16YMMWithEmptyBase(<4 x i64> +unsigned long long ymm_empty_base_pass(YMMWithEmptyBase x) { return x.x[0]; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
