r212734 - [PowerPC] ABI support for non-Altivec vector types

Ulrich Weigand ulrich.weigand at de.ibm.com
Thu Jul 10 09:39:01 PDT 2014


Author: uweigand
Date: Thu Jul 10 11:39:01 2014
New Revision: 212734

URL: http://llvm.org/viewvc/llvm-project?rev=212734&view=rev
Log:
[PowerPC] ABI support for non-Altivec vector types

This patch adds support for passing arguments of non-Altivec vector type
(i.e. defined via attribute ((vector_size (...)))) on powerpc64-linux.

While such types are not mentioned in the formal ABI document, this
patch implements a calling convention compatible with GCC:

- Vectors of size < 16 bytes are passed in a GPR
- Vectors of size > 16 bytes are passed via reference

Note that vector types with a number of elements that is not a power
of 2 are not supported by GCC, so there is no pre-existing ABI to
follow.  We choose to pass those (of size < 16) as if widened to the
next power of two, so they might end up in a vector register or
in a GPR.  (Sizes > 16 are always passed via reference as well.)

Reviewed by Hal Finkel.


Added:
    cfe/trunk/test/CodeGen/ppc64-vector.c
Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=212734&r1=212733&r2=212734&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Thu Jul 10 11:39:01 2014
@@ -2923,7 +2923,8 @@ public:
       const Type *T = isSingleElementStruct(I.type, getContext());
       if (T) {
         const BuiltinType *BT = T->getAs<BuiltinType>();
-        if (T->isVectorType() || (BT && BT->isFloatingPoint())) {
+        if ((T->isVectorType() && getContext().getTypeSize(T) == 128) ||
+            (BT && BT->isFloatingPoint())) {
           QualType QT(T, 0);
           I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT));
           continue;
@@ -2997,6 +2998,18 @@ PPC64_SVR4_ABIInfo::classifyArgumentType
   if (Ty->isAnyComplexType())
     return ABIArgInfo::getDirect();
 
+  // Non-Altivec vector types are passed in GPRs (smaller than 16 bytes)
+  // or via reference (larger than 16 bytes).
+  if (Ty->isVectorType()) {
+    uint64_t Size = getContext().getTypeSize(Ty);
+    if (Size > 128)
+      return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+    else if (Size < 128) {
+      llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
+      return ABIArgInfo::getDirect(CoerceTy);
+    }
+  }
+
   if (isAggregateTypeForABI(Ty)) {
     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
       return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
@@ -3016,6 +3029,18 @@ PPC64_SVR4_ABIInfo::classifyReturnType(Q
   if (RetTy->isAnyComplexType())
     return ABIArgInfo::getDirect();
 
+  // Non-Altivec vector types are returned in GPRs (smaller than 16 bytes)
+  // or via reference (larger than 16 bytes).
+  if (RetTy->isVectorType()) {
+    uint64_t Size = getContext().getTypeSize(RetTy);
+    if (Size > 128)
+      return ABIArgInfo::getIndirect(0);
+    else if (Size < 128) {
+      llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
+      return ABIArgInfo::getDirect(CoerceTy);
+    }
+  }
+
   if (isAggregateTypeForABI(RetTy))
     return ABIArgInfo::getIndirect(0);
 

Added: cfe/trunk/test/CodeGen/ppc64-vector.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ppc64-vector.c?rev=212734&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/ppc64-vector.c (added)
+++ cfe/trunk/test/CodeGen/ppc64-vector.c Thu Jul 10 11:39:01 2014
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -faltivec -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+typedef short v2i16 __attribute__((vector_size (4)));
+typedef short v3i16 __attribute__((vector_size (6)));
+typedef short v4i16 __attribute__((vector_size (8)));
+typedef short v6i16 __attribute__((vector_size (12)));
+typedef short v8i16 __attribute__((vector_size (16)));
+typedef short v16i16 __attribute__((vector_size (32)));
+
+struct v16i16 { v16i16 x; };
+
+// CHECK: define i32 @test_v2i16(i32 %x.coerce)
+v2i16 test_v2i16(v2i16 x)
+{
+  return x;
+}
+
+// CHECK: define i64 @test_v3i16(i64 %x.coerce)
+v3i16 test_v3i16(v3i16 x)
+{
+  return x;
+}
+
+// CHECK: define i64 @test_v4i16(i64 %x.coerce)
+v4i16 test_v4i16(v4i16 x)
+{
+  return x;
+}
+
+// CHECK: define <6 x i16> @test_v6i16(<6 x i16> %x)
+v6i16 test_v6i16(v6i16 x)
+{
+  return x;
+}
+
+// CHECK: define <8 x i16> @test_v8i16(<8 x i16> %x)
+v8i16 test_v8i16(v8i16 x)
+{
+  return x;
+}
+
+// CHECK: define void @test_v16i16(<16 x i16>* noalias sret %agg.result, <16 x i16>*)
+v16i16 test_v16i16(v16i16 x)
+{
+  return x;
+}
+
+// CHECK: define void @test_struct_v16i16(%struct.v16i16* noalias sret %agg.result, %struct.v16i16* byval %x)
+struct v16i16 test_struct_v16i16(struct v16i16 x)
+{
+  return x;
+}





More information about the cfe-commits mailing list