llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: mike-goutokuji (mike-goutokuji) <details> <summary>Changes</summary> - Fix Clang returning vectorcall HVA/HFA types via `sret` when they are not C++14 aggregates (e.g. they have base classes, protected members, or user-provided constructors). - MSVC returns these types in XMM registers on x86/x64 vectorcall; Clang was incorrectly treating them as indirect returns after applying the usual MSVC C++14 aggregate rules in `MicrosoftCXXABI::classifyReturnType`. - Allow direct register returns for `__vectorcall` functions when the return type is a homogeneous aggregate and can still be passed in registers. This is analogous to the AArch64 HVA return handling added for #<!-- -->62223, but on x86 vectorcall the same relaxation also applies to HFAs. Fixes #<!-- -->63417 --- Full diff: https://github.com/llvm/llvm-project/pull/203925.diff 3 Files Affected: - (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+11) - (modified) clang/test/CodeGenCXX/homogeneous-aggregates.cpp (+22) - (added) clang/test/CodeGenCXX/microsoft-abi-vectorcall-hva.cpp (+30) ``````````diff diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 40c7c00d85395..b24595036a930 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1192,6 +1192,17 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { bool isTrivialForABI = RD->canPassInRegisters() && isTrivialForMSVC(RD, FI.getReturnType(), CGM); + // On x86 and x64, vectorcall returns HVAs and HFAs in registers even if they + // are not C++14 aggregates (e.g. they have base classes), as long as they can + // still be passed in registers and qualify as homogeneous aggregates. + if (!isTrivialForABI && RD->canPassInRegisters() && + FI.getCallingConvention() == llvm::CallingConv::X86_VectorCall) { + const Type *Base = nullptr; + uint64_t NumElts = 0; + if (CGM.getABIInfo().isHomogeneousAggregate(FI.getReturnType(), Base, NumElts)) + isTrivialForABI = true; + } + // MSVC always returns structs indirectly from C++ instance methods. bool isIndirectReturn = !isTrivialForABI || FI.isInstanceMethod(); diff --git a/clang/test/CodeGenCXX/homogeneous-aggregates.cpp b/clang/test/CodeGenCXX/homogeneous-aggregates.cpp index 278c19b384c92..6365472fc4b3e 100644 --- a/clang/test/CodeGenCXX/homogeneous-aggregates.cpp +++ b/clang/test/CodeGenCXX/homogeneous-aggregates.cpp @@ -302,3 +302,25 @@ struct test2 : base2 { test2(double); protected: double v2;}; test2 f(test2 *x) { return *x; } // WOA64: define dso_local void @"?f@pr62223@@YA?AUtest2@1@PEAU21@@Z"(ptr dead_on_unwind inreg noalias writable sret(%"struct.pr62223::test2") align 8 %{{.*}}, ptr noundef %{{.*}}) } + +namespace pr113104 { +// On x86/x64 vectorcall, both HVAs and HFAs are returned in registers even when +// they are not C++14 aggregates (unlike WOA64, where only HVAs get this +// treatment — see pr62223 above). +struct HFA { + float a; + float b; +}; + +using HVA = float __attribute__((__vector_size__(16), __aligned__(16))); + +struct base_hfa { HFA v1; }; +struct test_hfa : base_hfa { test_hfa(double); protected: HFA v2; }; +test_hfa CC f(test_hfa *x) { return *x; } +// X64: define dso_local x86_vectorcallcc %"struct.pr113104::test_hfa" @"\01_ZN8pr1131041fEPNS_8test_hfaE@@8"(ptr noundef %x) + +struct base_hva { HVA v1; }; +struct test_hva : base_hva { test_hva(double); protected: HVA v2; }; +test_hva CC f(test_hva *x) { return *x; } +// X64: define dso_local x86_vectorcallcc %"struct.pr113104::test_hva" @"\01_ZN8pr1131041fEPNS_8test_hvaE@@8"(ptr noundef %x) +} diff --git a/clang/test/CodeGenCXX/microsoft-abi-vectorcall-hva.cpp b/clang/test/CodeGenCXX/microsoft-abi-vectorcall-hva.cpp new file mode 100644 index 0000000000000..7739813088111 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-vectorcall-hva.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -o - %s | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm -o - %s | FileCheck %s --check-prefix=X64 + +typedef float __m128 __attribute__((__vector_size__(16))); + +// HVA with base class +struct base_hva { __m128 v; }; +struct test_hva : base_hva { test_hva(double); protected: __m128 v2; }; + +// HFA with base class +struct base_hfa { double v; }; +struct test_hfa : base_hfa { test_hfa(double); protected: double v2; }; + +// 1. Vectorcall returns should be direct (not sret) +test_hva __vectorcall ret_hva_vectorcall(test_hva *x) { return *x; } +// X86-LABEL: define dso_local x86_vectorcallcc %struct.test_hva @"?ret_hva_vectorcall@@YQ?AUtest_hva@@PAU1@@Z"(ptr inreg noundef %x) +// X64-LABEL: define dso_local x86_vectorcallcc %struct.test_hva @"?ret_hva_vectorcall@@YQ?AUtest_hva@@PEAU1@@Z"(ptr noundef %x) + +test_hfa __vectorcall ret_hfa_vectorcall(test_hfa *x) { return *x; } +// X86-LABEL: define dso_local x86_vectorcallcc %struct.test_hfa @"?ret_hfa_vectorcall@@YQ?AUtest_hfa@@PAU1@@Z"(ptr inreg noundef %x) +// X64-LABEL: define dso_local x86_vectorcallcc %struct.test_hfa @"?ret_hfa_vectorcall@@YQ?AUtest_hfa@@PEAU1@@Z"(ptr noundef %x) + +// 2. Cdecl returns should be indirect (sret) because they are not aggregates +test_hva __cdecl ret_hva_cdecl(test_hva *x) { return *x; } +// X86-LABEL: define dso_local void @"?ret_hva_cdecl@@YA?AUtest_hva@@PAU1@@Z"(ptr dead_on_unwind noalias writable sret(%struct.test_hva) align 16 %agg.result, ptr noundef %x) +// X64-LABEL: define dso_local void @"?ret_hva_cdecl@@YA?AUtest_hva@@PEAU1@@Z"(ptr dead_on_unwind noalias writable sret(%struct.test_hva) align 16 %agg.result, ptr noundef %x) + +test_hfa __cdecl ret_hfa_cdecl(test_hfa *x) { return *x; } +// X86-LABEL: define dso_local void @"?ret_hfa_cdecl@@YA?AUtest_hfa@@PAU1@@Z"(ptr dead_on_unwind noalias writable sret(%struct.test_hfa) align 8 %agg.result, ptr noundef %x) +// X64-LABEL: define dso_local void @"?ret_hfa_cdecl@@YA?AUtest_hfa@@PEAU1@@Z"(ptr dead_on_unwind noalias writable sret(%struct.test_hfa) align 8 %agg.result, ptr noundef %x) `````````` </details> https://github.com/llvm/llvm-project/pull/203925 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
