From: Daniel Dunbar Date: Wed, 1 Apr 2009 06:13:08 +0000 (+0000) Subject: x86-32 Darwin ABI: Handle direct return of vectors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=360431660b2245a109f5c6870729126dbcdea254;p=clang x86-32 Darwin ABI: Handle direct return of vectors. - Current return-arguments-32 status is: 8 out of 1000 failures (-7) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68192 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 291e476f0b..58e448949e 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -278,6 +278,28 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, ASTContext &Context) const { if (RetTy->isVoidType()) { return ABIArgInfo::getIgnore(); + } else if (const VectorType *VT = RetTy->getAsVectorType()) { + // On Darwin, some vectors are returned in registers. + if (IsDarwin) { + uint64_t Size = Context.getTypeSize(RetTy); + + // 128-bit vectors are a special case; they are returned in + // registers and we need to make sure to pick a type the LLVM + // backend will like. + if (Size == 128) + return ABIArgInfo::getCoerce(llvm::VectorType::get(llvm::Type::Int64Ty, + 2)); + + // Always return in register if it fits in a general purpose + // register, or if it is 64 bits and has a single element. + if ((Size == 8 || Size == 16 || Size == 32) || + (Size == 64 && VT->getNumElements() == 1)) + return ABIArgInfo::getCoerce(llvm::IntegerType::get(Size)); + + return ABIArgInfo::getIndirect(0); + } + + return ABIArgInfo::getDirect(); } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) { // Outside of Darwin, structs and unions are always indirect. if (!IsDarwin && !RetTy->isAnyComplexType()) diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c index 9334895186..58637d5253 100644 --- a/test/CodeGen/x86_32-arguments.c +++ b/test/CodeGen/x86_32-arguments.c @@ -71,5 +71,19 @@ struct s10 { float f; } f10(void) {} -// RUN: true +// Small vectors and 1 x {i64,double} are returned in registers... + +// RUN: grep 'i32 @f11()' %t && +// RUN: grep -F 'void @f12(<2 x i32>* noalias sret %agg.result)' %t && +// RUN: grep 'i64 @f13()' %t && +// RUN: grep 'i64 @f14()' %t && +typedef short T11 __attribute__ ((vector_size (4))); +T11 f11(void) {} +typedef int T12 __attribute__ ((vector_size (8))); +T12 f12(void) {} +typedef long long T13 __attribute__ ((vector_size (8))); +T13 f13(void) {} +typedef double T14 __attribute__ ((vector_size (8))); +T14 f14(void) {} +// RUN: true