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

Andrew Jeffery via cfe-commits cfe-commits at lists.llvm.org
Sun Jul 23 18:54:05 PDT 2017


Hi Hal,

On Sat, 2017-07-22 at 23:26 -0500, Hal Finkel wrote:
> On 07/19/2017 10:26 AM, Adrian Prantl wrote:
> > > > > > On Jun 21, 2017, at 11:32 PM, Andrew Jeffery <andrew at aj.id.au> wrote:
> > > 
> > > 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.
> > 
> > You could also write all in one file and use invoke FileCheck with --check-prefix=CHECK-PPC64 to have a second set of CHECK-lines in the same input file.
> > 
> > -- adrian
> > > > > > Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
> > > ---
> > > 
> > > Hello,
> > > 
> > > The only change in v3 is rebasing it on top upstream HEAD, fixing a conflict in
> > > one of the lit REQUIRES lines.
> > > 
> > > Ulrich, Hal, Bill: I've Cc'ed you as you were fingered by the blame output. As
> > > some background I sent the patch several months ago but it hasn't got much
> > > traction aside from a LGTM from Adrian (thanks!). I'm hoping it gets a bit more
> > > attention as without it we get build failures for Swift on POWER, which is
> > > in-turn blocking some CI efforts.
> > > 
> > > Cheers,
> > > 
> > > Andrew
> > > 
> > > 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 e23a93e..54b5911 100644
> > > --- a/lib/Basic/Targets.cpp
> > > +++ b/lib/Basic/Targets.cpp
> > > @@ -1753,6 +1753,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 8d00e05..a82cd24 100644
> > > --- a/lib/CodeGen/TargetInfo.cpp
> > > +++ b/lib/CodeGen/TargetInfo.cpp
> > > @@ -4179,7 +4179,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,
> > > @@ -4223,7 +4223,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;
> > > @@ -4266,6 +4266,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);
> 
> I don't know much about Swift; the code changes seem reasonable. One 
> question I have is: from where does this number 4 come? Is there some 
> corresponding patch to Swift that this matches?

As far as I'm aware a patch to Swift is not necessary, rather 4 comes
from Ulrich's '[PowerPC] Support multiple return values with fast isel'
patch[1] which allows up to 4 values to be returned in registers.

To give some confidence, with this patch Swift builds and the tests
pass for PPC64 on PPC64. Looking at the other implementations of
shouldPassIndirectlyForSwift() none of them seem to have behaviour
dependent on asReturnValue, however must say I'm not certain about the
false (argument) case. Maybe Ulrich can provide some insight?

Thanks for taking a look.

Andrew

[1] https://github.com/apple/swift-llvm/commit/d7ad443387b829b4f401a6750a6e8bfb7c4ca31a

> 
>   -Hal
> 
> > > +  }
> > > +
> > > +  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 0000000..fa00484
> > > --- /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 0000000..b94932b
> > > --- /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 92ba37c..21f182d 100644
> > > --- a/test/CodeGen/64bit-swiftcall.c
> > > +++ b/test/CodeGen/64bit-swiftcall.c
> > > @@ -2,8 +2,9 @@
> > > // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s --check-prefix=X86-64
> > > // RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
> > > // RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM64
> > > +// 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))
> > > @@ -69,8 +70,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)));
> > > @@ -371,94 +370,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
> > > 
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170724/6ba44477/attachment-0001.sig>


More information about the cfe-commits mailing list