wuzish created this revision.
wuzish added reviewers: hfinkel, nemanjai, Douglasgido, hubert.reinterpretcast, 
fpichet.

There are 2 function variations with altivec type parameter. When we call them 
with argument of generic gcc vector type we would prefer to choose the 
variation with implicit argument conversion of compatible vector type.

  typedef float __v4sf __attribute__((__vector_size__(16)));
  void f(vector float);
  void f(vector signed int);
  
  int main {
     __v4sf a;
     f(a);
  }

Here, we'd like to choose f(vector float) but not report an ambiguous call 
error.


Repository:
  rC Clang

https://reviews.llvm.org/D53417

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/Sema/altivec-generic-overload.c

Index: clang/test/Sema/altivec-generic-overload.c
===================================================================
--- /dev/null
+++ clang/test/Sema/altivec-generic-overload.c
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 %s -triple=powerpc64le-unknown-linux -target-feature +altivec -target-feature +vsx -verify -verify-ignore-unexpected=note -pedantic -fsyntax-only
+
+typedef signed char __v4sc __attribute__((__vector_size__(16)));
+typedef unsigned char __v4uc __attribute__((__vector_size__(16)));
+typedef signed short __v4ss __attribute__((__vector_size__(16)));
+typedef unsigned short __v4us __attribute__((__vector_size__(16)));
+typedef signed int __v4si __attribute__((__vector_size__(16)));
+typedef unsigned int __v4ui __attribute__((__vector_size__(16)));
+typedef signed long long __v4sll __attribute__((__vector_size__(16)));
+typedef unsigned long long __v4ull __attribute__((__vector_size__(16)));
+typedef signed __int128 __v4slll __attribute__((__vector_size__(16)));
+typedef unsigned __int128 __v4ulll __attribute__((__vector_size__(16)));
+typedef float __v4f __attribute__((__vector_size__(16)));
+typedef double __v4d __attribute__((__vector_size__(16)));
+
+void __attribute__((__overloadable__)) convert1(vector signed char);
+void __attribute__((__overloadable__)) convert1(vector unsigned char);
+void __attribute__((__overloadable__)) convert1(vector signed short);
+void __attribute__((__overloadable__)) convert1(vector unsigned short);
+void __attribute__((__overloadable__)) convert1(vector signed int);
+void __attribute__((__overloadable__)) convert1(vector unsigned int);
+void __attribute__((__overloadable__)) convert1(vector signed long long);
+void __attribute__((__overloadable__)) convert1(vector unsigned long long);
+void __attribute__((__overloadable__)) convert1(vector signed __int128);
+void __attribute__((__overloadable__)) convert1(vector unsigned __int128);
+void __attribute__((__overloadable__)) convert1(vector float);
+void __attribute__((__overloadable__)) convert1(vector double);
+void __attribute__((__overloadable__)) convert1(vector bool int);
+void __attribute__((__overloadable__)) convert1(vector pixel short);
+void __attribute__((__overloadable__)) convert2(__v4sc);
+void __attribute__((__overloadable__)) convert2(__v4uc);
+void __attribute__((__overloadable__)) convert2(__v4ss);
+void __attribute__((__overloadable__)) convert2(__v4us);
+void __attribute__((__overloadable__)) convert2(__v4si);
+void __attribute__((__overloadable__)) convert2(__v4ui);
+void __attribute__((__overloadable__)) convert2(__v4sll);
+void __attribute__((__overloadable__)) convert2(__v4ull);
+void __attribute__((__overloadable__)) convert2(__v4slll);
+void __attribute__((__overloadable__)) convert2(__v4ulll);
+void __attribute__((__overloadable__)) convert2(__v4f);
+void __attribute__((__overloadable__)) convert2(__v4d);
+
+void test()
+{
+  __v4sc gv1;
+  __v4uc gv2;
+  __v4ss gv3;
+  __v4us gv4;
+  __v4si gv5;
+  __v4ui gv6;
+  __v4sll gv7;
+  __v4ull gv8;
+  __v4slll gv9;
+  __v4ulll gv10;
+  __v4f gv11;
+  __v4d  gv12;
+
+  vector signed char av1;
+  vector unsigned char av2;
+  vector signed short av3;
+  vector unsigned short av4;
+  vector signed int av5;
+  vector unsigned int av6;
+  vector signed long long av7;
+  vector unsigned long long av8;
+  vector signed __int128 av9;
+  vector unsigned __int128 av10;
+  vector float av11;
+  vector double av12;
+  vector bool int av13;
+  vector pixel short av14;
+
+  convert1(gv1);
+  convert1(gv2);
+  convert1(gv3);
+  convert1(gv4);
+  convert1(gv5);
+  convert1(gv6);
+  convert1(gv7);
+  convert1(gv8);
+  convert1(gv9);
+  convert1(gv10);
+  convert1(gv11);
+  convert1(gv12);
+
+  convert2(av1);
+  convert2(av2);
+  convert2(av3);
+  convert2(av4);
+  convert2(av5);
+  convert2(av6);
+  convert2(av7);
+  convert2(av8);
+  convert2(av9);
+  convert2(av10);
+  convert2(av11);
+  convert2(av12);
+  convert2(av13); // expected-error {{call to 'convert2' is ambiguous}}
+  convert2(av14); // expected-error {{call to 'convert2' is ambiguous}}
+
+}
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -3900,6 +3900,46 @@
           S.Context.getTypeSize(SCS1.getToType(2)))
     return ImplicitConversionSequence::Better;
 
+  // For now only conversions with VectorType::AltiVecVector kind
+  // prefer to choose a compatible vector conversion
+  // FIXME: Can remove this constraint and extend to other vector kind?
+  auto IsPreferCompatibleConversionVectorKind = [](QualType FromType,
+                                                   QualType ToType) {
+    assert(FromType->isVectorType() && "FromType should be a vector type");
+    assert(ToType->isVectorType() && "ToType should be a vector type");
+
+    if (FromType->getAs<VectorType>()->getVectorKind() ==
+            VectorType::AltiVecVector ||
+        ToType->getAs<VectorType>()->getVectorKind() ==
+            VectorType::AltiVecVector)
+      return true;
+
+    return false;
+  };
+
+  // Prefer a compatible vector conversion to lax vector conversion
+  // For example:
+  //
+  // typedef float __v4sf __attribute__((__vector_size__(16)));
+  // void f(vector float);
+  // void f(vector signed int);
+  // int main {
+  //   __v4sf a;
+  //   f(a);
+  // }
+  // Here, we'd like to choose f(vector float) but not
+  // report an ambiguous call error
+  if (SCS1.Second == ICK_Vector_Conversion &&
+      SCS2.Second == ICK_Vector_Conversion &&
+      IsPreferCompatibleConversionVectorKind(SCS1.getFromType(),
+                                             SCS1.getToType(2))) {
+    if (S.Context.areCompatibleVectorTypes(SCS1.getFromType(),
+                                           SCS1.getToType(2)) &&
+        !S.Context.areCompatibleVectorTypes(SCS2.getFromType(),
+                                            SCS2.getToType(2)))
+      return ImplicitConversionSequence::Better;
+  }
+
   return ImplicitConversionSequence::Indistinguishable;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to