summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGCall.cpp22
-rw-r--r--clang/test/CodeGen/x86_32-arguments.c16
2 files changed, 37 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 291e476f0bd..58e448949e7 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/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/clang/test/CodeGen/x86_32-arguments.c b/clang/test/CodeGen/x86_32-arguments.c
index 93348951862..58637d52532 100644
--- a/clang/test/CodeGen/x86_32-arguments.c
+++ b/clang/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
OpenPOWER on IntegriCloud