[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-28 Thread Nemanja Ivanovic via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
nemanjai marked an inline comment as done.
Closed by commit rG9021ce9576e4: [Clang] Enable KF and KC mode for [_Complex] 
__float128 (authored by nemanjai).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Sema/attr-mode.c

Index: clang/test/Sema/attr-mode.c
===
--- clang/test/Sema/attr-mode.c
+++ clang/test/Sema/attr-mode.c
@@ -4,6 +4,8 @@
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_64BIT_PPC64 -fsyntax-only \
 // RUN:   -verify %s
+// RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_F128_PPC64 -fsyntax-only \
+// RUN:   -verify -target-feature +float128 %s
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnux32 -DTEST_64BIT_X86 -fsyntax-only \
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple mips-linux-gnu -DTEST_MIPS_32 -fsyntax-only \
@@ -90,6 +92,15 @@
 void f_ft128_complex_arg(_Complex long double *x);
 void test_TFtype(f128ibm *a) { f_ft128_arg (a); }
 void test_TCtype(c128ibm *a) { f_ft128_complex_arg (a); }
+#elif TEST_F128_PPC64
+typedef int invalid_7 __attribute((mode(KF))); // expected-error{{type of machine mode does not match type of base type}}
+typedef int invalid_8 __attribute((mode(KI))); // expected-error{{unknown machine mode}}
+typedef _Complex float cf128 __attribute__((mode(KC)));
+typedef float f128 __attribute__((mode(KF)));
+void f_f128_arg(__float128 *x);
+void f_f128_complex_arg(_Complex __float128 *x);
+void test_KFtype(f128 *a) { f_f128_arg(a); }
+void test_KCtype(cf128 *a) { f_f128_complex_arg(a); }
 #elif TEST_MIPS_32
 typedef unsigned int gcc_unwind_word __attribute__((mode(unwind_word)));
 int foo[sizeof(gcc_unwind_word) == 4 ? 1 : -1];
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3942,7 +3942,8 @@
 /// parseModeAttrArg - Parses attribute mode string and returns parsed type
 /// attribute.
 static void parseModeAttrArg(Sema , StringRef Str, unsigned ,
- bool , bool ) {
+ bool , bool ,
+ bool ) {
   IntegerMode = true;
   ComplexMode = false;
   switch (Str.size()) {
@@ -3963,7 +3964,12 @@
 case 'X':
   DestWidth = 96;
   break;
+case 'K': // KFmode - IEEE quad precision (__float128)
+  ExplicitIEEE = true;
+  DestWidth = Str[1] == 'I' ? 0 : 128;
+  break;
 case 'T':
+  ExplicitIEEE = false;
   DestWidth = 128;
   break;
 }
@@ -4024,6 +4030,7 @@
   unsigned DestWidth = 0;
   bool IntegerMode = true;
   bool ComplexMode = false;
+  bool ExplicitIEEE = false;
   llvm::APInt VectorSize(64, 0);
   if (Str.size() >= 4 && Str[0] == 'V') {
 // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
@@ -4036,7 +4043,7 @@
 !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
 VectorSize.isPowerOf2()) {
   parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
-   IntegerMode, ComplexMode);
+   IntegerMode, ComplexMode, ExplicitIEEE);
   // Avoid duplicate warning from template instantiation.
   if (!InInstantiation)
 Diag(AttrLoc, diag::warn_vector_mode_deprecated);
@@ -4046,7 +4053,8 @@
   }
 
   if (!VectorSize)
-parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode,
+ ExplicitIEEE);
 
   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
   // and friends, at least with glibc.
@@ -4112,7 +4120,7 @@
 NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
   OldElemTy->isSignedIntegerType());
   else
-NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
+NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE);
 
   if (NewElemTy.isNull()) {
 Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
Index: clang/lib/Basic/TargetInfo.cpp
===
--- clang/lib/Basic/TargetInfo.cpp
+++ clang/lib/Basic/TargetInfo.cpp
@@ -265,7 +265,8 @@
   return NoInt;
 }
 
-TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
+TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth,
+bool ExplicitIEEE) const {
   if (getFloatWidth() == BitWidth)
 return Float;
   if (getDoubleWidth() == BitWidth)
@@ 

[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-28 Thread John McCall via Phabricator via cfe-commits
rjmccall accepted this revision.
rjmccall added a comment.
This revision is now accepted and ready to land.

Thanks


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-28 Thread Nemanja Ivanovic via Phabricator via cfe-commits
nemanjai marked 3 inline comments as done.
nemanjai added inline comments.



Comment at: clang/lib/Sema/SemaDeclAttr.cpp:3970
+  DestWidth = 128;
+  break;
 case 'T':

rjmccall wrote:
> rjmccall wrote:
> > Are there interactions with the other mode specifiers?  For example, should 
> > this be allowed with integer modes?  If so, I think this needs more tests.
> I shouldn't have said "if so" — *either way*, this needs more tests.
Very good point. Thank you. Added.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-28 Thread Nemanja Ivanovic via Phabricator via cfe-commits
nemanjai updated this revision to Diff 266820.
nemanjai added a comment.

Handled invalid uses of `KI` as there is no corresponding integer mode and 
added testing for it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Sema/attr-mode.c

Index: clang/test/Sema/attr-mode.c
===
--- clang/test/Sema/attr-mode.c
+++ clang/test/Sema/attr-mode.c
@@ -4,6 +4,8 @@
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_64BIT_PPC64 -fsyntax-only \
 // RUN:   -verify %s
+// RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_F128_PPC64 -fsyntax-only \
+// RUN:   -verify -target-feature +float128 %s
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnux32 -DTEST_64BIT_X86 -fsyntax-only \
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple mips-linux-gnu -DTEST_MIPS_32 -fsyntax-only \
@@ -90,6 +92,15 @@
 void f_ft128_complex_arg(_Complex long double *x);
 void test_TFtype(f128ibm *a) { f_ft128_arg (a); }
 void test_TCtype(c128ibm *a) { f_ft128_complex_arg (a); }
+#elif TEST_F128_PPC64
+typedef int invalid_7 __attribute((mode(KF))); // expected-error{{type of machine mode does not match type of base type}}
+typedef int invalid_8 __attribute((mode(KI))); // expected-error{{unknown machine mode}}
+typedef _Complex float cf128 __attribute__((mode(KC)));
+typedef float f128 __attribute__((mode(KF)));
+void f_f128_arg(__float128 *x);
+void f_f128_complex_arg(_Complex __float128 *x);
+void test_KFtype(f128 *a) { f_f128_arg(a); }
+void test_KCtype(cf128 *a) { f_f128_complex_arg(a); }
 #elif TEST_MIPS_32
 typedef unsigned int gcc_unwind_word __attribute__((mode(unwind_word)));
 int foo[sizeof(gcc_unwind_word) == 4 ? 1 : -1];
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3942,7 +3942,8 @@
 /// parseModeAttrArg - Parses attribute mode string and returns parsed type
 /// attribute.
 static void parseModeAttrArg(Sema , StringRef Str, unsigned ,
- bool , bool ) {
+ bool , bool ,
+ bool ) {
   IntegerMode = true;
   ComplexMode = false;
   switch (Str.size()) {
@@ -3963,7 +3964,12 @@
 case 'X':
   DestWidth = 96;
   break;
+case 'K': // KFmode - IEEE quad precision (__float128)
+  ExplicitIEEE = true;
+  DestWidth = Str[1] == 'I' ? 0 : 128;
+  break;
 case 'T':
+  ExplicitIEEE = false;
   DestWidth = 128;
   break;
 }
@@ -4024,6 +4030,7 @@
   unsigned DestWidth = 0;
   bool IntegerMode = true;
   bool ComplexMode = false;
+  bool ExplicitIEEE = false;
   llvm::APInt VectorSize(64, 0);
   if (Str.size() >= 4 && Str[0] == 'V') {
 // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
@@ -4036,7 +4043,7 @@
 !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
 VectorSize.isPowerOf2()) {
   parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
-   IntegerMode, ComplexMode);
+   IntegerMode, ComplexMode, ExplicitIEEE);
   // Avoid duplicate warning from template instantiation.
   if (!InInstantiation)
 Diag(AttrLoc, diag::warn_vector_mode_deprecated);
@@ -4046,7 +4053,8 @@
   }
 
   if (!VectorSize)
-parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode,
+ ExplicitIEEE);
 
   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
   // and friends, at least with glibc.
@@ -4112,7 +4120,7 @@
 NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
   OldElemTy->isSignedIntegerType());
   else
-NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
+NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE);
 
   if (NewElemTy.isNull()) {
 Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
Index: clang/lib/Basic/TargetInfo.cpp
===
--- clang/lib/Basic/TargetInfo.cpp
+++ clang/lib/Basic/TargetInfo.cpp
@@ -265,7 +265,8 @@
   return NoInt;
 }
 
-TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
+TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth,
+bool ExplicitIEEE) const {
   if (getFloatWidth() == BitWidth)
 return Float;
   if (getDoubleWidth() == BitWidth)
@@ -277,6 +278,10 @@
   return LongDouble;
 break;
  

[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-26 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/Sema/SemaDeclAttr.cpp:3970
+  DestWidth = 128;
+  break;
 case 'T':

Are there interactions with the other mode specifiers?  For example, should 
this be allowed with integer modes?  If so, I think this needs more tests.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-26 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/Sema/SemaDeclAttr.cpp:3970
+  DestWidth = 128;
+  break;
 case 'T':

rjmccall wrote:
> Are there interactions with the other mode specifiers?  For example, should 
> this be allowed with integer modes?  If so, I think this needs more tests.
I shouldn't have said "if so" — *either way*, this needs more tests.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-25 Thread Nemanja Ivanovic via Phabricator via cfe-commits
nemanjai updated this revision to Diff 266092.
nemanjai added a comment.

Remove handling for explicit `_Complex __float128`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Sema/attr-mode.c

Index: clang/test/Sema/attr-mode.c
===
--- clang/test/Sema/attr-mode.c
+++ clang/test/Sema/attr-mode.c
@@ -4,6 +4,8 @@
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_64BIT_PPC64 -fsyntax-only \
 // RUN:   -verify %s
+// RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_F128_PPC64 -fsyntax-only \
+// RUN:   -verify -target-feature +float128 %s
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnux32 -DTEST_64BIT_X86 -fsyntax-only \
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple mips-linux-gnu -DTEST_MIPS_32 -fsyntax-only \
@@ -90,6 +92,13 @@
 void f_ft128_complex_arg(_Complex long double *x);
 void test_TFtype(f128ibm *a) { f_ft128_arg (a); }
 void test_TCtype(c128ibm *a) { f_ft128_complex_arg (a); }
+#elif TEST_F128_PPC64
+typedef _Complex float cf128 __attribute__ ((mode (KC)));
+typedef float f128 __attribute__ ((mode (KF)));
+void f_f128_arg(__float128 *x);
+void f_f128_complex_arg(_Complex __float128 *x);
+void test_KFtype(f128 *a) { f_f128_arg (a); }
+void test_KCtype(cf128 *a) { f_f128_complex_arg (a); }
 #elif TEST_MIPS_32
 typedef unsigned int gcc_unwind_word __attribute__((mode(unwind_word)));
 int foo[sizeof(gcc_unwind_word) == 4 ? 1 : -1];
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3942,7 +3942,8 @@
 /// parseModeAttrArg - Parses attribute mode string and returns parsed type
 /// attribute.
 static void parseModeAttrArg(Sema , StringRef Str, unsigned ,
- bool , bool ) {
+ bool , bool ,
+ bool ) {
   IntegerMode = true;
   ComplexMode = false;
   switch (Str.size()) {
@@ -3963,7 +3964,12 @@
 case 'X':
   DestWidth = 96;
   break;
+case 'K': // KFmode - IEEE quad precision (__float128)
+  ExplicitIEEE = true;
+  DestWidth = 128;
+  break;
 case 'T':
+  ExplicitIEEE = false;
   DestWidth = 128;
   break;
 }
@@ -4024,6 +4030,7 @@
   unsigned DestWidth = 0;
   bool IntegerMode = true;
   bool ComplexMode = false;
+  bool ExplicitIEEE = false;
   llvm::APInt VectorSize(64, 0);
   if (Str.size() >= 4 && Str[0] == 'V') {
 // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
@@ -4036,7 +4043,7 @@
 !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
 VectorSize.isPowerOf2()) {
   parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
-   IntegerMode, ComplexMode);
+   IntegerMode, ComplexMode, ExplicitIEEE);
   // Avoid duplicate warning from template instantiation.
   if (!InInstantiation)
 Diag(AttrLoc, diag::warn_vector_mode_deprecated);
@@ -4046,7 +4053,8 @@
   }
 
   if (!VectorSize)
-parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode,
+ ExplicitIEEE);
 
   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
   // and friends, at least with glibc.
@@ -4112,7 +4120,7 @@
 NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
   OldElemTy->isSignedIntegerType());
   else
-NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
+NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE);
 
   if (NewElemTy.isNull()) {
 Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
Index: clang/lib/Basic/TargetInfo.cpp
===
--- clang/lib/Basic/TargetInfo.cpp
+++ clang/lib/Basic/TargetInfo.cpp
@@ -265,7 +265,8 @@
   return NoInt;
 }
 
-TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
+TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth,
+bool ExplicitIEEE) const {
   if (getFloatWidth() == BitWidth)
 return Float;
   if (getDoubleWidth() == BitWidth)
@@ -277,6 +278,10 @@
   return LongDouble;
 break;
   case 128:
+// The caller explicitly asked for an IEEE compliant type but we still
+// have to check if the target supports it.
+if (ExplicitIEEE)
+  return hasFloat128Type() ? Float128 : NoFloat;
 if (() == ::APFloat::PPCDoubleDouble() ||
 () 

[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-25 Thread Nemanja Ivanovic via Phabricator via cfe-commits
nemanjai added a comment.

The support for `_Complex __float128` in https://reviews.llvm.org/D80533
I will repurpose leave only the addition of the `KF/KC` modes in this patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-22 Thread John McCall via Phabricator via cfe-commits
rjmccall added a comment.

Would you mind separating these two patches?  They don't seem have any 
interdependencies.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80374/new/

https://reviews.llvm.org/D80374



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80374: [Clang] Enable KF and KC mode for [_Complex] __float128

2020-05-21 Thread Nemanja Ivanovic via Phabricator via cfe-commits
nemanjai created this revision.
nemanjai added reviewers: rjmccall, rsmith, PowerPC, hfinkel.
Herald added subscribers: dexonsmith, kbarton.
Herald added a reviewer: aaron.ballman.
Herald added a project: clang.

The headers provided with recent GNU toolchains for PPC have code that includes 
typedefs such as:
`typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__KC__)))`

Also, when I added `__float128`, I neglected to add support for `_Complex 
__float128` altogether. This patch fixes those oversights and allows clang to 
compile something like:

  #include 
  _Complex __float128 testkf(_Complex __float128 a, _Complex __float128 b) {
return a + b;
  }

with `-mfloat128` which it currently fails to compile due to the two reasons 
listed above.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80374

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Sema/DeclSpec.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/ppc64-complex-parms.c
  clang/test/CodeGen/ppc64-complex-return.c
  clang/test/Sema/attr-mode.c

Index: clang/test/Sema/attr-mode.c
===
--- clang/test/Sema/attr-mode.c
+++ clang/test/Sema/attr-mode.c
@@ -4,6 +4,8 @@
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_64BIT_PPC64 -fsyntax-only \
 // RUN:   -verify %s
+// RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_F128_PPC64 -fsyntax-only \
+// RUN:   -verify -target-feature +float128 %s
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnux32 -DTEST_64BIT_X86 -fsyntax-only \
 // RUN:   -verify %s
 // RUN: %clang_cc1 -triple mips-linux-gnu -DTEST_MIPS_32 -fsyntax-only \
@@ -90,6 +92,13 @@
 void f_ft128_complex_arg(_Complex long double *x);
 void test_TFtype(f128ibm *a) { f_ft128_arg (a); }
 void test_TCtype(c128ibm *a) { f_ft128_complex_arg (a); }
+#elif TEST_F128_PPC64
+typedef _Complex float cf128 __attribute__ ((mode (KC)));
+typedef float f128 __attribute__ ((mode (KF)));
+void f_f128_arg(__float128 *x);
+void f_f128_complex_arg(_Complex __float128 *x);
+void test_KFtype(f128 *a) { f_f128_arg (a); }
+void test_KCtype(cf128 *a) { f_f128_complex_arg (a); }
 #elif TEST_MIPS_32
 typedef unsigned int gcc_unwind_word __attribute__((mode(unwind_word)));
 int foo[sizeof(gcc_unwind_word) == 4 ? 1 : -1];
Index: clang/test/CodeGen/ppc64-complex-return.c
===
--- clang/test/CodeGen/ppc64-complex-return.c
+++ clang/test/CodeGen/ppc64-complex-return.c
@@ -1,9 +1,20 @@
 // REQUIRES: powerpc-registered-target
 // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -target-feature +float128 -DTEST_F128 -triple \
+// RUN:   powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s \
+// RUN:   --check-prefix CHECK-F128
 
 float crealf(_Complex float);
 double creal(_Complex double);
 long double creall(_Complex long double);
+#ifdef TEST_F128
+__float128 crealf128(_Complex __float128);
+_Complex __float128 foo_f128(_Complex __float128 x) {
+  return x;
+}
+
+// CHECK-F128: define { fp128, fp128 } @foo_f128(fp128 {{[%A-Za-z0-9.]+}}, fp128 {{[%A-Za-z0-9.]+}}) [[NUW:#[0-9]+]] {
+#endif
 
 _Complex float foo_float(_Complex float x) {
   return x;
@@ -80,6 +91,17 @@
 // CHECK: extractvalue { ppc_fp128, ppc_fp128 } [[VAR3]], 0
 // CHECK: extractvalue { ppc_fp128, ppc_fp128 } [[VAR3]], 1
 
+#ifdef TEST_F128
+__float128 bar_f128(void) {
+  return crealf128(foo_f128(2.0Q - 2.5Qi));
+}
+
+// CHECK-F128: define fp128 @bar_f128() [[NUW]] {
+// CHECK-F128: [[VAR3:[%A-Za-z0-9.]+]] = call { fp128, fp128 } @foo_f128
+// CHECK-F128: extractvalue { fp128, fp128 } [[VAR3]], 0
+// CHECK-F128: extractvalue { fp128, fp128 } [[VAR3]], 1
+#endif
+
 int bar_int(void) {
   return __real__(foo_int(2 - 3i));
 }
Index: clang/test/CodeGen/ppc64-complex-parms.c
===
--- clang/test/CodeGen/ppc64-complex-parms.c
+++ clang/test/CodeGen/ppc64-complex-parms.c
@@ -1,8 +1,20 @@
+// REQUIRES: powerpc-registered-target
 // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -target-feature +float128 -DTEST_F128 -triple \
+// RUN:   powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s \
+// RUN:   --check-prefix CHECK-F128
 
 float crealf(_Complex float);
 double creal(_Complex double);
 long double creall(_Complex long double);
+#ifdef TEST_F128
+__float128 crealf128(_Complex __float128);
+__float128 foo_f128(_Complex __float128 x) {
+  return crealf128(x);
+}
+// CHECK-F128: define fp128 @foo_f128(fp128 {{[%A-Za-z0-9.]+}}, fp128 {{[%A-Za-z0-9.]+}})
+#endif
+
 
 float foo_float(_Complex float x) {
   return crealf(x);
Index: clang/lib/Sema/SemaDeclAttr.cpp