[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-21 Thread Erich Keane via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL308769: Complex Long Double classification In RegCall 
calling convention (authored by erichkeane).

Changed prior to commit:
  https://reviews.llvm.org/D35259?vs=107667=107696#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D35259

Files:
  cfe/trunk/lib/CodeGen/TargetInfo.cpp
  cfe/trunk/test/CodeGenCXX/regcall.cpp


Index: cfe/trunk/test/CodeGenCXX/regcall.cpp
===
--- cfe/trunk/test/CodeGenCXX/regcall.cpp
+++ cfe/trunk/test/CodeGenCXX/regcall.cpp
@@ -73,8 +73,8 @@
 // CHECK-WIN64-DAG: define x86_regcallcc zeroext i1 
@"\01??8@Yw_NAEBVtest_class@@0@Z"
 // CHECK-WIN32-DAG: define x86_regcallcc zeroext i1 
@"\01??8@Yw_NABVtest_class@@0@Z"
 
-test_class __regcall operator""_test_class (unsigned long long) { ++x; return 
test_class{};} 
-// CHECK-LIN64-DAG: define x86_regcallcc %class.test_class 
@_Zli11_test_classy(i64)
+test_class __regcall operator""_test_class (unsigned long long) { ++x; return 
test_class{};}
+// CHECK-LIN64-DAG: define x86_regcallcc void 
@_Zli11_test_classy(%class.test_class* noalias sret %agg.result, i64)
 // CHECK-LIN32-DAG: define x86_regcallcc void 
@_Zli11_test_classy(%class.test_class* inreg noalias sret %agg.result, i64)
 // CHECK-WIN64-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
 // CHECK-WIN32-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall foo(long double _Complex f) {
+  return f;
+}
+// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval 
align 16 %f)
+// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* 
byval align 4 %f)
+// CHECK-WIN64-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
Index: cfe/trunk/lib/CodeGen/TargetInfo.cpp
===
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp
@@ -882,8 +882,14 @@
 /// X86_VectorCall calling convention. Shared between x86_32 and x86_64.
 static bool isX86VectorTypeForVectorCall(ASTContext , QualType Ty) {
   if (const BuiltinType *BT = Ty->getAs()) {
-if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half)
+if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) {
+  if (BT->getKind() == BuiltinType::LongDouble) {
+if (().getLongDoubleFormat() ==
+::APFloat::x87DoubleExtended())
+  return false;
+  }
   return true;
+}
   } else if (const VectorType *VT = Ty->getAs()) {
 // vectorcall can pass XMM, YMM, and ZMM vectors. We don't pass SSE1 MMX
 // registers specially.
@@ -3515,18 +3521,27 @@
   unsigned FreeSSERegs = IsRegCall ? 16 : 8;
   unsigned NeededInt, NeededSSE;
 
-  if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
-  !FI.getReturnType()->getTypePtr()->isUnionType()) {
-FI.getReturnInfo() =
-classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
-if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
-  FreeIntRegs -= NeededInt;
-  FreeSSERegs -= NeededSSE;
-} else {
-  FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
-}
-  } else if (!getCXXABI().classifyReturnType(FI))
-FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  if (!getCXXABI().classifyReturnType(FI)) {
+if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
+!FI.getReturnType()->getTypePtr()->isUnionType()) {
+  FI.getReturnInfo() =
+  classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
+  if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
+FreeIntRegs -= NeededInt;
+FreeSSERegs -= NeededSSE;
+  } else {
+FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+  }
+} else if (IsRegCall && FI.getReturnType()->getAs()) {
+  // Complex Long Double Type is passed in Memory when Regcall
+  // calling convention is used.
+  const ComplexType *CT = FI.getReturnType()->getAs();
+  if (getContext().getCanonicalType(CT->getElementType()) ==
+  getContext().LongDoubleTy)
+FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+} else
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  }
 
   // If the return value is indirect, then the hidden argument is consuming one
   // integer register.


Index: cfe/trunk/test/CodeGenCXX/regcall.cpp

[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-21 Thread Reid Kleckner via Phabricator via cfe-commits
rnk accepted this revision.
rnk added a comment.
This revision is now accepted and ready to land.

lgtm


https://reviews.llvm.org/D35259



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


[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-21 Thread Elizabeth Andrews via Phabricator via cfe-commits
eandrews updated this revision to Diff 107667.
eandrews added a comment.

Regcall-specific checks for Lin64 now occur only if CXXABI returns false. An 
existing test has also been modified to verify behavior with non trivial 
destructors.


https://reviews.llvm.org/D35259

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGenCXX/regcall.cpp


Index: test/CodeGenCXX/regcall.cpp
===
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -73,8 +73,8 @@
 // CHECK-WIN64-DAG: define x86_regcallcc zeroext i1 
@"\01??8@Yw_NAEBVtest_class@@0@Z"
 // CHECK-WIN32-DAG: define x86_regcallcc zeroext i1 
@"\01??8@Yw_NABVtest_class@@0@Z"
 
-test_class __regcall operator""_test_class (unsigned long long) { ++x; return 
test_class{};} 
-// CHECK-LIN64-DAG: define x86_regcallcc %class.test_class 
@_Zli11_test_classy(i64)
+test_class __regcall operator""_test_class (unsigned long long) { ++x; return 
test_class{};}
+// CHECK-LIN64-DAG: define x86_regcallcc void 
@_Zli11_test_classy(%class.test_class* noalias sret %agg.result, i64)
 // CHECK-LIN32-DAG: define x86_regcallcc void 
@_Zli11_test_classy(%class.test_class* inreg noalias sret %agg.result, i64)
 // CHECK-WIN64-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
 // CHECK-WIN32-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z"
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall foo(long double _Complex f) {
+  return f;
+}
+// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval 
align 16 %f)
+// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* 
byval align 4 %f)
+// CHECK-WIN64-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -882,8 +882,14 @@
 /// X86_VectorCall calling convention. Shared between x86_32 and x86_64.
 static bool isX86VectorTypeForVectorCall(ASTContext , QualType Ty) {
   if (const BuiltinType *BT = Ty->getAs()) {
-if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half)
+if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) {
+  if (BT->getKind() == BuiltinType::LongDouble) {
+if (().getLongDoubleFormat() ==
+::APFloat::x87DoubleExtended())
+  return false;
+  }
   return true;
+}
   } else if (const VectorType *VT = Ty->getAs()) {
 // vectorcall can pass XMM, YMM, and ZMM vectors. We don't pass SSE1 MMX
 // registers specially.
@@ -3505,18 +3511,27 @@
   unsigned FreeSSERegs = IsRegCall ? 16 : 8;
   unsigned NeededInt, NeededSSE;
 
-  if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
-  !FI.getReturnType()->getTypePtr()->isUnionType()) {
-FI.getReturnInfo() =
-classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
-if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
-  FreeIntRegs -= NeededInt;
-  FreeSSERegs -= NeededSSE;
-} else {
-  FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
-}
-  } else if (!getCXXABI().classifyReturnType(FI))
-FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  if (!getCXXABI().classifyReturnType(FI)) {
+if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
+!FI.getReturnType()->getTypePtr()->isUnionType()) {
+  FI.getReturnInfo() =
+  classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
+  if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
+FreeIntRegs -= NeededInt;
+FreeSSERegs -= NeededSSE;
+  } else {
+FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+  }
+} else if (IsRegCall && FI.getReturnType()->getAs()) {
+  // Complex Long Double Type is passed in Memory when Regcall
+  // calling convention is used.
+  const ComplexType *CT = FI.getReturnType()->getAs();
+  if (getContext().getCanonicalType(CT->getElementType()) ==
+  getContext().LongDoubleTy)
+FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+} else
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  }
 
   // If the return value is indirect, then the hidden argument is consuming one
   // integer register.


Index: test/CodeGenCXX/regcall.cpp
===
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -73,8 +73,8 @@
 // CHECK-WIN64-DAG: define 

[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-19 Thread Reid Kleckner via Phabricator via cfe-commits
rnk added inline comments.



Comment at: lib/CodeGen/TargetInfo.cpp:3516
+  // calling convention is used.
   if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
   !FI.getReturnType()->getTypePtr()->isUnionType()) {

This is incorrect. We should consult the CXXABI first, and then only do these 
regcall-specific things if it returns false. Consider adding this test case to 
find the bug:
```
struct NonTrivial {
  int x, y;
  ~NonTrivial();
};
NonTrivial __regcall f() { return NonTrivial(); }
```

This should not return in registers, but it does today.



Comment at: lib/CodeGen/TargetInfo.cpp:3526
 }
+  } else if (IsRegCall && FI.getReturnType()->getAs()) {
+const ComplexType *CT = FI.getReturnType()->getAs();

This isn't necessarily a bug, but please always do C++ ABI classifications 
first so it's easy to spot the bug above.


https://reviews.llvm.org/D35259



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


[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-19 Thread Elizabeth Andrews via Phabricator via cfe-commits
eandrews updated this revision to Diff 107343.
eandrews added a comment.

As per revision comments, I moved the condition for extended precision floating 
type to isX86VectorTypeForVectorCall. This update will now alter behavior for 
complex long double type under vectorcall calling convention as well. 
Returns/parameters will be passed in memory.


https://reviews.llvm.org/D35259

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGenCXX/regcall.cpp


Index: test/CodeGenCXX/regcall.cpp
===
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall foo(long double _Complex f) {
+  return f;
+}
+// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval 
align 16 %f)
+// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* 
byval align 4 %f)
+// CHECK-WIN64-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -882,8 +882,14 @@
 /// X86_VectorCall calling convention. Shared between x86_32 and x86_64.
 static bool isX86VectorTypeForVectorCall(ASTContext , QualType Ty) {
   if (const BuiltinType *BT = Ty->getAs()) {
-if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half)
+if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) {
+  if (BT->getKind() == BuiltinType::LongDouble) {
+if (().getLongDoubleFormat() ==
+::APFloat::x87DoubleExtended())
+  return false;
+  }
   return true;
+}
   } else if (const VectorType *VT = Ty->getAs()) {
 // vectorcall can pass XMM, YMM, and ZMM vectors. We don't pass SSE1 MMX
 // registers specially.
@@ -3505,6 +3511,8 @@
   unsigned FreeSSERegs = IsRegCall ? 16 : 8;
   unsigned NeededInt, NeededSSE;
 
+  // Complex Long Double Type is passed in Memory when Regcall
+  // calling convention is used.
   if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
   !FI.getReturnType()->getTypePtr()->isUnionType()) {
 FI.getReturnInfo() =
@@ -3515,6 +3523,11 @@
 } else {
   FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
 }
+  } else if (IsRegCall && FI.getReturnType()->getAs()) {
+const ComplexType *CT = FI.getReturnType()->getAs();
+if (getContext().getCanonicalType(CT->getElementType()) ==
+getContext().LongDoubleTy)
+  FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
   } else if (!getCXXABI().classifyReturnType(FI))
 FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
 


Index: test/CodeGenCXX/regcall.cpp
===
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall foo(long double _Complex f) {
+  return f;
+}
+// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 16 %f)
+// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %f)
+// CHECK-WIN64-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -882,8 +882,14 @@
 /// X86_VectorCall calling convention. Shared between x86_32 and x86_64.
 static bool isX86VectorTypeForVectorCall(ASTContext , QualType Ty) {
   if (const BuiltinType *BT = Ty->getAs()) {
-if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half)
+if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) {
+  if (BT->getKind() == BuiltinType::LongDouble) {
+if (().getLongDoubleFormat() ==
+::APFloat::x87DoubleExtended())
+  return false;
+  }
   return true;
+}
   } else if (const VectorType *VT = Ty->getAs()) {
 // vectorcall can pass XMM, YMM, and ZMM vectors. We don't pass SSE1 MMX
 // registers specially.
@@ -3505,6 +3511,8 @@
   unsigned FreeSSERegs = IsRegCall ? 16 : 8;
   unsigned NeededInt, 

[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-11 Thread Elizabeth Andrews via Phabricator via cfe-commits
eandrews added a comment.

In https://reviews.llvm.org/D35259#805415, @erichkeane wrote:

> In https://reviews.llvm.org/D35259#805409, @rnk wrote:
>
> > In https://reviews.llvm.org/D35259#805284, @erichkeane wrote:
> >
> > > Oren discovered this miss to the original implementation.  I'd reviewed 
> > > this internally quite a bit.
> > >
> > > The reason for the Win32ABI test is that MSVC 'long double' is actually 
> > > small enough for SSE registers in this case.  I DO now (looking again, 
> > > sorry Elizabeth) wonder if there is a better way to exclude 
> > > extended-length LongDouble type?  Could we us the 'length' of it instead? 
> > > @rnk : opinion?
> >
> >
> > Yeah, you can ask clang::TargetInfo for the format of most basic FP types. 
> > The code to do that looks like:
> >
> >   () == ::APFloat::x87DoubleExtended()
> >   
> >
> > Any reason you can't just add that condition to 
> > isX86VectorTypeForVectorCall? I assume we don't want to pass x86_fp80s in 
> > SSE registers for vectorcall either, right? That would eliminate the need 
> > for the isRegCallReturnableHA helper and the IsWin32StructABI parameter, 
> > which is a poorly named variable.
>
>
> It actually WOULD make sense to apply this to vectorcall as well, wouldn't 
> it?  I presumed we didnt want to change its behavior, however vectorcall is 
> MSVC-only (other than us), so the long-double issue isn't a thing over 
> there.@eandrews?


I can apply this condition to isX86VectorTypeForVectorCall like Reid suggested. 
The only reason I did not do that originally was because I wasn't sure how to 
differentiate between the calling conventions without changing function 
declaration. If I don't need to explicitly differentiate between RegCall and 
VectorCall and can  use the 'length' instead, I think this works better. Like 
Reid mentioned, it would eliminate the need for isRegCallReturnableHA and 
IsWin32StructABI.


https://reviews.llvm.org/D35259



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


[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-11 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added a comment.

In https://reviews.llvm.org/D35259#805409, @rnk wrote:

> In https://reviews.llvm.org/D35259#805284, @erichkeane wrote:
>
> > Oren discovered this miss to the original implementation.  I'd reviewed 
> > this internally quite a bit.
> >
> > The reason for the Win32ABI test is that MSVC 'long double' is actually 
> > small enough for SSE registers in this case.  I DO now (looking again, 
> > sorry Elizabeth) wonder if there is a better way to exclude extended-length 
> > LongDouble type?  Could we us the 'length' of it instead? @rnk : opinion?
>
>
> Yeah, you can ask clang::TargetInfo for the format of most basic FP types. 
> The code to do that looks like:
>
>   () == ::APFloat::x87DoubleExtended()
>   
>
> Any reason you can't just add that condition to isX86VectorTypeForVectorCall? 
> I assume we don't want to pass x86_fp80s in SSE registers for vectorcall 
> either, right? That would eliminate the need for the isRegCallReturnableHA 
> helper and the IsWin32StructABI parameter, which is a poorly named variable.


It actually WOULD make sense to apply this to vectorcall as well, wouldn't it?  
I presumed we didnt want to change its behavior, however vectorcall is 
MSVC-only (other than us), so the long-double issue isn't a thing over 
there.@eandrews?


https://reviews.llvm.org/D35259



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


[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-11 Thread Reid Kleckner via Phabricator via cfe-commits
rnk added a comment.

In https://reviews.llvm.org/D35259#805284, @erichkeane wrote:

> Oren discovered this miss to the original implementation.  I'd reviewed this 
> internally quite a bit.
>
> The reason for the Win32ABI test is that MSVC 'long double' is actually small 
> enough for SSE registers in this case.  I DO now (looking again, sorry 
> Elizabeth) wonder if there is a better way to exclude extended-length 
> LongDouble type?  Could we us the 'length' of it instead? @rnk : opinion?


Yeah, you can ask clang::TargetInfo for the format of most basic FP types. The 
code to do that looks like:

  () == ::APFloat::x87DoubleExtended()

Any reason you can't just add that condition to isX86VectorTypeForVectorCall? I 
assume we don't want to pass x86_fp80s in SSE registers for vectorcall either, 
right? That would eliminate the need for the isRegCallReturnableHA helper and 
the IsWin32StructABI parameter, which is a poorly named variable.


https://reviews.llvm.org/D35259



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


[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-11 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added a comment.

Oren discovered this miss to the original implementation.  I'd reviewed this 
internally quite a bit.

The reason for the Win32ABI test is that MSVC 'long double' is actually small 
enough for SSE registers in this case.  I DO now (looking again, sorry 
Elizabeth) wonder if there is a better way to exclude extended-length 
LongDouble type?  Could we us the 'length' of it instead? @rnk : opinion?


https://reviews.llvm.org/D35259



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


[PATCH] D35259: Complex Long Double classification In RegCall calling convention

2017-07-11 Thread Elizabeth Andrews via Phabricator via cfe-commits
eandrews created this revision.

This change is part of the RegCall calling convention support for LLVM. 
Existing RegCall implementation was extended to include correct handling of 
Complex Long Double type. Complex long double types should be returned/passed 
in memory and not register stack. This patch implements this behavior.


https://reviews.llvm.org/D35259

Files:
  lib/CodeGen/ABIInfo.h
  lib/CodeGen/TargetInfo.cpp
  test/CodeGenCXX/regcall.cpp


Index: test/CodeGenCXX/regcall.cpp
===
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall foo(long double _Complex f) {
+  return f;
+}
+// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval 
align 16 %f)
+// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ 
x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* 
byval align 4 %f)
+// CHECK-WIN64-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define x86_regcallcc { double, double } 
@"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -1289,9 +1289,11 @@
 
   const Type *Base = nullptr;
   uint64_t NumElts = 0;
-  if ((State.CC == llvm::CallingConv::X86_VectorCall ||
-   State.CC == llvm::CallingConv::X86_RegCall) &&
-  isHomogeneousAggregate(RetTy, Base, NumElts)) {
+  if ((State.CC == llvm::CallingConv::X86_VectorCall &&
+   isHomogeneousAggregate(RetTy, Base, NumElts)) ||
+  (State.CC == llvm::CallingConv::X86_RegCall &&
+   isRegcallReturnableHomogeneousAggregate(RetTy, Base, NumElts,
+   IsWin32StructABI))) {
 // The LLVM struct type for such an aggregate should lower properly.
 return ABIArgInfo::getDirect();
   }
@@ -1558,8 +1560,8 @@
   const Type *Base = nullptr;
   uint64_t NumElts = 0;
   if (State.CC == llvm::CallingConv::X86_RegCall &&
-  isHomogeneousAggregate(Ty, Base, NumElts)) {
-
+  isRegcallReturnableHomogeneousAggregate(Ty, Base, NumElts,
+  IsWin32StructABI)) {
 if (State.FreeSSERegs >= NumElts) {
   State.FreeSSERegs -= NumElts;
   if (Ty->isBuiltinType() || Ty->isVectorType())
@@ -3495,6 +3497,11 @@
 } else {
   FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
 }
+  } else if (IsRegCall && FI.getReturnType()->getAs()) {
+const ComplexType *CT = FI.getReturnType()->getAs();
+if (getContext().getCanonicalType(CT->getElementType()) ==
+getContext().LongDoubleTy)
+  FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
   } else if (!getCXXABI().classifyReturnType(FI))
 FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
 
@@ -4385,6 +4392,24 @@
   return CharUnits::fromQuantity(8);
 }
 
+/// isRegcallReturnableHomogeneousAggregate - Return true if a type is an ELFv2
+/// homogeneous aggregate that can be returned in stack for regcall.
+bool ABIInfo::isRegcallReturnableHomogeneousAggregate(
+QualType Ty, const Type *, uint64_t ,
+bool IsWin32StructABI) const {
+  if (isHomogeneousAggregate(Ty, Base, Members)) {
+if (const ComplexType *CT = Ty->getAs()) {
+  if (!IsWin32StructABI) {
+QualType ET = getContext().getCanonicalType(CT->getElementType());
+if (ET == getContext().LongDoubleTy)
+  return false;
+  }
+}
+return true;
+  }
+  return false;
+}
+
 /// isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous
 /// aggregate.  Base is set to the base element type, and Members is set
 /// to the number of base elements.
Index: lib/CodeGen/ABIInfo.h
===
--- lib/CodeGen/ABIInfo.h
+++ lib/CodeGen/ABIInfo.h
@@ -111,6 +111,10 @@
 bool isHomogeneousAggregate(QualType Ty, const Type *,
 uint64_t ) const;
 
+bool isRegcallReturnableHomogeneousAggregate(QualType Ty, const Type 
*,
+ uint64_t ,
+ bool IsWin32StructABI) const;
+
 /// A convenience method to return an indirect ABIArgInfo with an
 /// expected alignment equal to the ABI alignment of the given type.
 CodeGen::ABIArgInfo


Index: test/CodeGenCXX/regcall.cpp
===
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall