[PATCH v2] [PPC64]: Add support for Swift calling convention

Andrew Jeffery via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 26 21:22:23 PDT 2017


For the tests I've extracted the int5 and int8 cases to cater for
different alignments for different platform ABIs. For Linux on POWER the
5 and 8 element vectors must be naturally aligned with respect to the
total "soft" vector size, despite being represented as an aggregate.
Specifically, the patch caters for the following differences in
supporting powerpc64le-unknown-linux:

   $ diff -u test/CodeGen/64bit-swiftcall.c test/CodeGen/ppc64-swiftcall.c
   --- test/CodeGen/64bit-swiftcall.c	2017-04-20 17:14:59.797963820 +0930
   +++ test/CodeGen/ppc64-swiftcall.c	2017-04-20 17:15:11.621965118 +0930
   @@ -1,7 +1,6 @@
   -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
   -// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
   +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -emit-llvm -o - %s | FileCheck %s

   -// REQUIRES: aarch64-registered-target,x86-registered-target
   +// REQUIRES: powerpc-registered-target

    #define SWIFTCALL __attribute__((swiftcall))
    #define OUT __attribute__((swift_indirect_result))
   @@ -370,8 +369,8 @@

    TEST(int8)
    // CHECK-LABEL: define {{.*}} @return_int8()
   -// CHECK:   [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 16
   +// CHECK:   [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32
    // CHECK:   [[VAR:%.*]] = alloca [[REC]], align
    // CHECK:   store
    // CHECK:   load
    // CHECK:   store
   @@ -414,8 +413,8 @@

    TEST(int5)
    // CHECK-LABEL: define {{.*}} @return_int5()
   -// CHECK:   [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 16
   +// CHECK:   [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32
    // CHECK:   [[VAR:%.*]] = alloca [[REC]], align
    // CHECK:   store
    // CHECK:   load
    // CHECK:   store

Despite some duplication, the advantage of this approach over using
pattern matching for alignment in 64bit-swiftcall.c is that we ensure
each platform is using the expected alignment but without duplicating
the entirety of 64bit-swiftcall.c.

Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
---
 lib/Basic/Targets.cpp                             |  11 ++
 lib/CodeGen/TargetInfo.cpp                        |  14 ++-
 test/CodeGen/64bit-swiftcall-extvec-agg-align16.c | 117 ++++++++++++++++++++++
 test/CodeGen/64bit-swiftcall-extvec-agg-align32.c | 116 +++++++++++++++++++++
 test/CodeGen/64bit-swiftcall.c                    |  93 +----------------
 5 files changed, 258 insertions(+), 93 deletions(-)
 create mode 100644 test/CodeGen/64bit-swiftcall-extvec-agg-align16.c
 create mode 100644 test/CodeGen/64bit-swiftcall-extvec-agg-align32.c

diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index aab3160af0f9..e32ad0b2dc39 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -1708,6 +1708,17 @@ public:
     }
     return false;
   }
+
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+    switch (CC) {
+    case CC_C:
+    case CC_Swift:
+        return CCCR_OK;
+    default:
+        break;
+    }
+    return CCCR_Warning;
+  }
 };
 
 class DarwinPPC32TargetInfo : public DarwinTargetInfo<PPC32TargetInfo> {
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index d2fc3888ef29..6193f6c4ac29 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -4175,7 +4175,7 @@ PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
 
 namespace {
 /// PPC64_SVR4_ABIInfo - The 64-bit PowerPC ELF (SVR4) ABI information.
-class PPC64_SVR4_ABIInfo : public ABIInfo {
+class PPC64_SVR4_ABIInfo : public SwiftABIInfo {
 public:
   enum ABIKind {
     ELFv1 = 0,
@@ -4219,7 +4219,7 @@ private:
 public:
   PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind, bool HasQPX,
                      bool SoftFloatABI)
-      : ABIInfo(CGT), Kind(Kind), HasQPX(HasQPX),
+      : SwiftABIInfo(CGT), Kind(Kind), HasQPX(HasQPX),
         IsSoftFloatABI(SoftFloatABI) {}
 
   bool isPromotableTypeForABI(QualType Ty) const;
@@ -4262,6 +4262,16 @@ public:
 
   Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
                     QualType Ty) const override;
+
+  bool shouldPassIndirectlyForSwift(CharUnits totalSize,
+                                    ArrayRef<llvm::Type*> scalars,
+                                    bool asReturnValue) const override {
+    return occupiesMoreThan(CGT, scalars, /*total*/ 4);
+  }
+
+  bool isSwiftErrorInRegister() const override {
+    return true;
+  }
 };
 
 class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
diff --git a/test/CodeGen/64bit-swiftcall-extvec-agg-align16.c b/test/CodeGen/64bit-swiftcall-extvec-agg-align16.c
new file mode 100644
index 000000000000..fa00484fc185
--- /dev/null
+++ b/test/CodeGen/64bit-swiftcall-extvec-agg-align16.c
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
+
+// REQUIRES: aarch64-registered-target,x86-registered-target
+
+#define SWIFTCALL __attribute__((swiftcall))
+
+/*****************************************************************************/
+/********************************** LOWERING *********************************/
+/*****************************************************************************/
+
+typedef int int5 __attribute__((ext_vector_type(5)));
+typedef int int8 __attribute__((ext_vector_type(8)));
+
+#define TEST(TYPE)                       \
+  SWIFTCALL TYPE return_##TYPE(void) {   \
+    TYPE result = {};                    \
+    return result;                       \
+  }                                      \
+  SWIFTCALL void take_##TYPE(TYPE v) {   \
+  }                                      \
+  void test_##TYPE() {                   \
+    take_##TYPE(return_##TYPE());        \
+  }
+
+
+/*****************************************************************************/
+/****************************** VECTOR LEGALIZATION **************************/
+/*****************************************************************************/
+
+TEST(int8)
+// CHECK-LABEL: define {{.*}} @return_int8()
+// CHECK:   [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 16
+// CHECK:   [[VAR:%.*]] = alloca [[REC]], align
+// CHECK:   store
+// CHECK:   load
+// CHECK:   store
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK:   [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1
+// CHECK:   ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>)
+// CHECK:   [[V:%.*]] = alloca [[REC]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   store <4 x i32> %0, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   store <4 x i32> %1, <4 x i32>* [[T0]], align
+// CHECK:   ret void
+// CHECK-LABEL: define void @test_int8()
+// CHECK:   [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK:   [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK:   [[CALL:%.*]] = call [[SWIFTCC:swiftcc]] [[UAGG]] @return_int8()
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK:   [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK:   store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]])
+// CHECK:   ret void
+
+TEST(int5)
+// CHECK-LABEL: define {{.*}} @return_int5()
+// CHECK:   [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 16
+// CHECK:   [[VAR:%.*]] = alloca [[REC]], align
+// CHECK:   store
+// CHECK:   load
+// CHECK:   store
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK:   [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK:   [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
+// CHECK:   ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32)
+// CHECK:   [[V:%.*]] = alloca [[REC]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   store <4 x i32> %0, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   store i32 %1, i32* [[T0]], align
+// CHECK:   ret void
+// CHECK-LABEL: define void @test_int5()
+// CHECK:   [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK:   [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK:   [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK:   store i32 [[T1]], i32* [[T0]], align
+// CHECK:   [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK:   store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK:   call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]])
+// CHECK:   ret void
diff --git a/test/CodeGen/64bit-swiftcall-extvec-agg-align32.c b/test/CodeGen/64bit-swiftcall-extvec-agg-align32.c
new file mode 100644
index 000000000000..b94932b1f8c7
--- /dev/null
+++ b/test/CodeGen/64bit-swiftcall-extvec-agg-align32.c
@@ -0,0 +1,116 @@
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -emit-llvm -o - %s | FileCheck %s
+
+// REQUIRES: powerpc-registered-target
+
+#define SWIFTCALL __attribute__((swiftcall))
+
+/*****************************************************************************/
+/********************************** LOWERING *********************************/
+/*****************************************************************************/
+
+typedef int int5 __attribute__((ext_vector_type(5)));
+typedef int int8 __attribute__((ext_vector_type(8)));
+
+#define TEST(TYPE)                       \
+  SWIFTCALL TYPE return_##TYPE(void) {   \
+    TYPE result = {};                    \
+    return result;                       \
+  }                                      \
+  SWIFTCALL void take_##TYPE(TYPE v) {   \
+  }                                      \
+  void test_##TYPE() {                   \
+    take_##TYPE(return_##TYPE());        \
+  }
+
+
+/*****************************************************************************/
+/****************************** VECTOR LEGALIZATION **************************/
+/*****************************************************************************/
+
+TEST(int8)
+// CHECK-LABEL: define {{.*}} @return_int8()
+// CHECK:   [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32
+// CHECK:   [[VAR:%.*]] = alloca [[REC]], align
+// CHECK:   store
+// CHECK:   load
+// CHECK:   store
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK:   [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1
+// CHECK:   ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>)
+// CHECK:   [[V:%.*]] = alloca [[REC]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   store <4 x i32> %0, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   store <4 x i32> %1, <4 x i32>* [[T0]], align
+// CHECK:   ret void
+// CHECK-LABEL: define void @test_int8()
+// CHECK:   [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK:   [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK:   [[CALL:%.*]] = call [[SWIFTCC:swiftcc]] [[UAGG]] @return_int8()
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK:   [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK:   store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]])
+// CHECK:   ret void
+
+TEST(int5)
+// CHECK-LABEL: define {{.*}} @return_int5()
+// CHECK:   [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32
+// CHECK:   [[VAR:%.*]] = alloca [[REC]], align
+// CHECK:   store
+// CHECK:   load
+// CHECK:   store
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK:   [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK:   [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
+// CHECK:   ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32)
+// CHECK:   [[V:%.*]] = alloca [[REC]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   store <4 x i32> %0, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   store i32 %1, i32* [[T0]], align
+// CHECK:   ret void
+// CHECK-LABEL: define void @test_int5()
+// CHECK:   [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK:   [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK:   [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK:   store i32 [[T1]], i32* [[T0]], align
+// CHECK:   [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK:   store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK:   [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK:   call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]])
+// CHECK:   ret void
diff --git a/test/CodeGen/64bit-swiftcall.c b/test/CodeGen/64bit-swiftcall.c
index c1f098172371..4ee06b58ea42 100644
--- a/test/CodeGen/64bit-swiftcall.c
+++ b/test/CodeGen/64bit-swiftcall.c
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -emit-llvm -o - %s | FileCheck %s
 
-// REQUIRES: aarch64-registered-target,x86-registered-target
+// REQUIRES: aarch64-registered-target,x86-registered-target,powerpc-registered-target
 
 #define SWIFTCALL __attribute__((swiftcall))
 #define OUT __attribute__((swift_indirect_result))
@@ -66,8 +67,6 @@ typedef double double2 __attribute__((ext_vector_type(2)));
 typedef double double4 __attribute__((ext_vector_type(4)));
 typedef int int3 __attribute__((ext_vector_type(3)));
 typedef int int4 __attribute__((ext_vector_type(4)));
-typedef int int5 __attribute__((ext_vector_type(5)));
-typedef int int8 __attribute__((ext_vector_type(8)));
 typedef char char16 __attribute__((ext_vector_type(16)));
 typedef short short8 __attribute__((ext_vector_type(8)));
 typedef long long long2 __attribute__((ext_vector_type(2)));
@@ -368,94 +367,6 @@ TEST(int4)
 // CHECK-LABEL: define {{.*}} <4 x i32> @return_int4()
 // CHECK-LABEL: define {{.*}} @take_int4(<4 x i32>
 
-TEST(int8)
-// CHECK-LABEL: define {{.*}} @return_int8()
-// CHECK:   [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 16
-// CHECK:   [[VAR:%.*]] = alloca [[REC]], align
-// CHECK:   store
-// CHECK:   load
-// CHECK:   store
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0
-// CHECK:   [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1
-// CHECK:   ret [[UAGG]] [[T1]]
-// CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>)
-// CHECK:   [[V:%.*]] = alloca [[REC]], align
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   store <4 x i32> %0, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   store <4 x i32> %1, <4 x i32>* [[T0]], align
-// CHECK:   ret void
-// CHECK-LABEL: define void @test_int8()
-// CHECK:   [[TMP1:%.*]] = alloca [[REC]], align
-// CHECK:   [[TMP2:%.*]] = alloca [[REC]], align
-// CHECK:   [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8()
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
-// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
-// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
-// CHECK:   [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
-// CHECK:   store [[REC]] [[V]], [[REC]]* [[TMP2]], align
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
-// CHECK:   call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]])
-// CHECK:   ret void
-
-TEST(int5)
-// CHECK-LABEL: define {{.*}} @return_int5()
-// CHECK:   [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 16
-// CHECK:   [[VAR:%.*]] = alloca [[REC]], align
-// CHECK:   store
-// CHECK:   load
-// CHECK:   store
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   [[SECOND:%.*]] = load i32, i32* [[T0]], align
-// CHECK:   [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0
-// CHECK:   [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
-// CHECK:   ret [[UAGG]] [[T1]]
-// CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32)
-// CHECK:   [[V:%.*]] = alloca [[REC]], align
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   store <4 x i32> %0, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   store i32 %1, i32* [[T0]], align
-// CHECK:   ret void
-// CHECK-LABEL: define void @test_int5()
-// CHECK:   [[TMP1:%.*]] = alloca [[REC]], align
-// CHECK:   [[TMP2:%.*]] = alloca [[REC]], align
-// CHECK:   [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
-// CHECK:   store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
-// CHECK:   store i32 [[T1]], i32* [[T0]], align
-// CHECK:   [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
-// CHECK:   store [[REC]] [[V]], [[REC]]* [[TMP2]], align
-// CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK:   [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
-// CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK:   [[SECOND:%.*]] = load i32, i32* [[T0]], align
-// CHECK:   call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]])
-// CHECK:   ret void
-
 typedef struct {
   int x;
   int3 v __attribute__((packed));
-- 
2.9.3



More information about the cfe-commits mailing list