Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -3900,6 +3900,31 @@ S.Context.getTypeSize(SCS1.getToType(2))) return ImplicitConversionSequence::Better; + // Prefer a compatible vector conversion over a 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) and not + // report an ambiguous call error + if (SCS1.Second == ICK_Vector_Conversion && + SCS2.Second == ICK_Vector_Conversion) { + bool SCS1IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes( + SCS1.getFromType(), SCS1.getToType(2)); + bool SCS2IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes( + SCS2.getFromType(), SCS2.getToType(2)); + + if (SCS1IsCompatibleVectorConversion != SCS2IsCompatibleVectorConversion) + return SCS1IsCompatibleVectorConversion + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + return ImplicitConversionSequence::Indistinguishable; } Index: clang/test/CodeGen/altivec-generic-overload.c =================================================================== --- /dev/null +++ clang/test/CodeGen/altivec-generic-overload.c @@ -0,0 +1,122 @@ +// RUN: %clang_cc1 %s -triple=powerpc64le-unknown-linux -target-feature +altivec -target-feature +vsx -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK + +typedef signed char __v16sc __attribute__((__vector_size__(16))); +typedef unsigned char __v16uc __attribute__((__vector_size__(16))); +typedef signed short __v8ss __attribute__((__vector_size__(16))); +typedef unsigned short __v8us __attribute__((__vector_size__(16))); +typedef signed int __v4si __attribute__((__vector_size__(16))); +typedef unsigned int __v4ui __attribute__((__vector_size__(16))); +typedef signed long long __v2sll __attribute__((__vector_size__(16))); +typedef unsigned long long __v2ull __attribute__((__vector_size__(16))); +typedef signed __int128 __v1slll __attribute__((__vector_size__(16))); +typedef unsigned __int128 __v1ulll __attribute__((__vector_size__(16))); +typedef float __v4f __attribute__((__vector_size__(16))); +typedef double __v2d __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(__v16sc); +void __attribute__((__overloadable__)) convert2(__v16uc); +void __attribute__((__overloadable__)) convert2(__v8ss); +void __attribute__((__overloadable__)) convert2(__v8us); +void __attribute__((__overloadable__)) convert2(__v4si); +void __attribute__((__overloadable__)) convert2(__v4ui); +void __attribute__((__overloadable__)) convert2(__v2sll); +void __attribute__((__overloadable__)) convert2(__v2ull); +void __attribute__((__overloadable__)) convert2(__v1slll); +void __attribute__((__overloadable__)) convert2(__v1ulll); +void __attribute__((__overloadable__)) convert2(__v4f); +void __attribute__((__overloadable__)) convert2(__v2d); + +void test() +{ + __v16sc gv1; + __v16uc gv2; + __v8ss gv3; + __v8us gv4; + __v4si gv5; + __v4ui gv6; + __v2sll gv7; + __v2ull gv8; + __v1slll gv9; + __v1ulll gv10; + __v4f gv11; + __v2d 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); + // CHECK: call void @_Z8convert1Dv16_a(<16 x i8> %{{[0-9]+}}) + convert1(gv2); + // CHECK: call void @_Z8convert1Dv16_h(<16 x i8> %{{[0-9]+}}) + convert1(gv3); + // CHECK: call void @_Z8convert1Dv8_s(<8 x i16> %{{[0-9]+}}) + convert1(gv4); + // CHECK: call void @_Z8convert1Dv8_t(<8 x i16> %{{[0-9]+}}) + convert1(gv5); + // CHECK: call void @_Z8convert1Dv4_i(<4 x i32> %{{[0-9]+}}) + convert1(gv6); + // CHECK: call void @_Z8convert1Dv4_j(<4 x i32> %{{[0-9]+}}) + convert1(gv7); + // CHECK: call void @_Z8convert1Dv2_x(<2 x i64> %{{[0-9]+}}) + convert1(gv8); + // CHECK: call void @_Z8convert1Dv2_y(<2 x i64> %{{[0-9]+}}) + convert1(gv9); + // CHECK: call void @_Z8convert1Dv1_n(<1 x i128> %{{[0-9]+}}) + convert1(gv10); + // CHECK: call void @_Z8convert1Dv1_o(<1 x i128> %{{[0-9]+}}) + convert1(gv11); + // CHECK: call void @_Z8convert1Dv4_f(<4 x float> %{{[0-9]+}}) + convert1(gv12); + // CHECK: call void @_Z8convert1Dv2_d(<2 x double> %{{[0-9]+}}) + + convert2(av1); + // CHECK: call void @_Z8convert2Dv16_a(<16 x i8> %{{[0-9]+}}) + convert2(av2); + // CHECK: call void @_Z8convert2Dv16_h(<16 x i8> %{{[0-9]+}}) + convert2(av3); + // CHECK: call void @_Z8convert2Dv8_s(<8 x i16> %{{[0-9]+}}) + convert2(av4); + // CHECK: call void @_Z8convert2Dv8_t(<8 x i16> %{{[0-9]+}}) + convert2(av5); + // CHECK: call void @_Z8convert2Dv4_i(<4 x i32> %{{[0-9]+}}) + convert2(av6); + // CHECK: call void @_Z8convert2Dv4_j(<4 x i32> %{{[0-9]+}}) + convert2(av7); + // CHECK: call void @_Z8convert2Dv2_x(<2 x i64> %{{[0-9]+}}) + convert2(av8); + // CHECK: call void @_Z8convert2Dv2_y(<2 x i64> %{{[0-9]+}}) + convert2(av9); + // CHECK: call void @_Z8convert2Dv1_n(<1 x i128> %{{[0-9]+}}) + convert2(av10); + // CHECK: call void @_Z8convert2Dv1_o(<1 x i128> %{{[0-9]+}}) + convert2(av11); + // CHECK: call void @_Z8convert2Dv4_f(<4 x float> %{{[0-9]+}}) + convert2(av12); + // CHECK: call void @_Z8convert2Dv2_d(<2 x double> %{{[0-9]+}}) +} 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 __v16sc __attribute__((__vector_size__(16))); +typedef unsigned char __v16uc __attribute__((__vector_size__(16))); +typedef signed short __v8ss __attribute__((__vector_size__(16))); +typedef unsigned short __v8us __attribute__((__vector_size__(16))); +typedef signed int __v4si __attribute__((__vector_size__(16))); +typedef unsigned int __v4ui __attribute__((__vector_size__(16))); +typedef signed long long __v2sll __attribute__((__vector_size__(16))); +typedef unsigned long long __v2ull __attribute__((__vector_size__(16))); +typedef signed __int128 __v1slll __attribute__((__vector_size__(16))); +typedef unsigned __int128 __v1ulll __attribute__((__vector_size__(16))); +typedef float __v4f __attribute__((__vector_size__(16))); +typedef double __v2d __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(__v16sc); +void __attribute__((__overloadable__)) convert2(__v16uc); +void __attribute__((__overloadable__)) convert2(__v8ss); +void __attribute__((__overloadable__)) convert2(__v8us); +void __attribute__((__overloadable__)) convert2(__v4si); +void __attribute__((__overloadable__)) convert2(__v4ui); +void __attribute__((__overloadable__)) convert2(__v2sll); +void __attribute__((__overloadable__)) convert2(__v2ull); +void __attribute__((__overloadable__)) convert2(__v1slll); +void __attribute__((__overloadable__)) convert2(__v1ulll); +void __attribute__((__overloadable__)) convert2(__v4f); +void __attribute__((__overloadable__)) convert2(__v2d); + +void test() +{ + __v16sc gv1; + __v16uc gv2; + __v8ss gv3; + __v8us gv4; + __v4si gv5; + __v4ui gv6; + __v2sll gv7; + __v2ull gv8; + __v1slll gv9; + __v1ulll gv10; + __v4f gv11; + __v2d 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/test/SemaCXX/vector.cpp =================================================================== --- clang/test/SemaCXX/vector.cpp +++ clang/test/SemaCXX/vector.cpp @@ -17,14 +17,14 @@ f0(ll16e); } -int &f1(char16); // expected-note 2{{candidate function}} -float &f1(longlong16); // expected-note 2{{candidate function}} +int &f1(char16); +float &f1(longlong16); void f1_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { int &ir1 = f1(c16); float &fr1 = f1(ll16); - f1(c16e); // expected-error{{call to 'f1' is ambiguous}} - f1(ll16e); // expected-error{{call to 'f1' is ambiguous}} + f1(c16e); + f1(ll16e); } void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' (vector of 2 'long long' values) to 'char16_e' (vector of 16 'char' values) for 1st argument}} \