diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6090,6 +6090,12 @@ void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, bool IsDereference, SourceRange Range); + // Checks if we have a valid AltiVec vector type, and splats the + // value into the vector accordingly. If a 'vector bool' or + // 'vector pixel' type is used with the -faltivec-src-compat=xl + // option, these types also splat the scalar value. + bool ShouldSplatAltivecScalarInCast(Sema &Self, const VectorType *VecTy); + /// ActOnCXXNamedCast - Parse /// {dynamic,static,reinterpret,const,addrspace}_cast's. ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2624,6 +2624,23 @@ } } +// Checks if we have a valid AltiVec vector type, and splats the value into +// the vector accordingly. If a 'vector bool' or 'vector pixel' type is used +// with the -faltivec-src-compat=xl option, these types also splat the scalar +// value into the respective vector (whereas normally they are not). +bool Sema::ShouldSplatAltivecScalarInCast(Sema &Self, const VectorType *VecTy) { + bool SrcCompatXL = Self.getLangOpts().getAltivecSrcCompat() == + LangOptions::AltivecSrcCompatKind::XL; + VectorType::VectorKind VKind = VecTy->getVectorKind(); + + if ((VKind == VectorType::AltiVecVector) || + (SrcCompatXL && ((VKind == VectorType::AltiVecBool) || + (VKind == VectorType::AltiVecPixel)))) { + return true; + } + return false; +} + void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, bool ListInitialization) { assert(Self.getLangOpts().CPlusPlus); @@ -2678,9 +2695,9 @@ // AltiVec vector initialization with a single literal. if (const VectorType *vecTy = DestType->getAs()) - if (vecTy->getVectorKind() == VectorType::AltiVecVector - && (SrcExpr.get()->getType()->isIntegerType() - || SrcExpr.get()->getType()->isFloatingType())) { + if (Self.ShouldSplatAltivecScalarInCast(Self, vecTy) && + (SrcExpr.get()->getType()->isIntegerType() || + SrcExpr.get()->getType()->isFloatingType())) { Kind = CK_VectorSplat; SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); return; @@ -2963,8 +2980,8 @@ } if (const VectorType *DestVecTy = DestType->getAs()) { - if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && - (SrcType->isIntegerType() || SrcType->isFloatingType())) { + if (Self.ShouldSplatAltivecScalarInCast(Self, DestVecTy) && + (SrcType->isIntegerType() || SrcType->isFloatingType())) { Kind = CK_VectorSplat; SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7707,7 +7707,7 @@ // initializers must be one or must match the size of the vector. // If a single value is specified in the initializer then it will be // replicated to all the components of the vector - if (VTy->getVectorKind() == VectorType::AltiVecVector) { + if (ShouldSplatAltivecScalarInCast(*this, VTy)) { // The number of initializers must be one or must match the size of the // vector. If a single value is specified in the initializer then it will // be replicated to all the components of the vector diff --git a/clang/test/CodeGen/vector-bool-pixel-altivec-init.c b/clang/test/CodeGen/vector-bool-pixel-altivec-init.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/vector-bool-pixel-altivec-init.c @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL + +// Vector bool type +vector bool char vbi8_1; +vector bool char vbi8_2; + +vector bool short vbi16_1; +vector bool short vbi16_2; + +vector bool int vbi32_1; +vector bool int vbi32_2; + +vector bool long long vbi64_1; +vector bool long long vbi64_2; + +// Vector pixel type +vector pixel p1; + +//////////////////////////////////////////////////////////////////////////////// +void test_vector_bool_pixel_init() { + // vector bool char initialization + vbi8_1 = (vector bool char)('a'); + // MIXED: + // XL: + char c = 'c'; + vbi8_2 = (vector bool char)(c); + // MIXED: insertelement <16 x i8> + // XL: %splat.splatinsert = insertelement <16 x i8> + // XL-NEXT: %splat.splat = shufflevector <16 x i8> %splat.splatinsert + + // vector bool short initialization + vbi16_1 = (vector bool short)(5); + // MIXED: + // XL: + short si16 = 55; + vbi16_2 = (vector bool short)(si16); + // MIXED: insertelement <8 x i16> + // XL: %splat.splatinsert1 = insertelement <8 x i16> + // XL-NEXT: %splat.splat2 = shufflevector <8 x i16> %splat.splatinsert1 + + // vector bool int initialization + vbi32_1 = (vector bool int)(9); + // MIXED: + // XL: + int si32 = 99; + vbi32_2 = (vector bool int)(si32); + // MIXED: insertelement <4 x i32> + // XL: %splat.splatinsert3 = insertelement <4 x i32> + // XL-NEXT: %splat.splat4 = shufflevector <4 x i32> %splat.splatinsert3 + + // vector bool long long initialization + vbi64_1 = (vector bool long long)(13); + // MIXED: + // XL: + long long si64 = 1313; + vbi64_2 = (vector bool long long)(si64); + // MIXED: insertelement <2 x i64> + // XL: %splat.splatinsert5 = insertelement <2 x i64> + // XL-NEXT: %splat.splat6 = shufflevector <2 x i64> %splat.splatinsert5 + + // vector pixel initialization + p1 = (vector pixel)(1); + // MIXED: + // XL: +} + diff --git a/clang/test/CodeGen/vector-bool-pixel-altivec-init2.c b/clang/test/CodeGen/vector-bool-pixel-altivec-init2.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/vector-bool-pixel-altivec-init2.c @@ -0,0 +1,85 @@ +// RUN: not %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED +// RUN: not %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: not %clang -mcpu=pwr8 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED +// RUN: not %clang -mcpu=pwr9 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL + +// Vector bool type +vector bool char vbi8_1; +vector bool char vbi8_2; + +vector bool short vbi16_1; +vector bool short vbi16_2; + +vector bool int vbi32_1; +vector bool int vbi32_2; + +vector bool long long vbi64_1; +vector bool long long vbi64_2; + +// Vector pixel type +vector pixel p1; + +//////////////////////////////////////////////////////////////////////////////// +void test_vector_bool_pixel_init() { + // vector bool char initialization + vbi8_1 = (vector bool char)'a'; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned char' + // XL: + char c = 'c'; + vbi8_2 = (vector bool char)c; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned char' + // XL: %splat.splatinsert = insertelement <16 x i8> + // XL-NEXT: %splat.splat = shufflevector <16 x i8> %splat.splatinsert + + // vector bool short initialization + vbi16_1 = (vector bool short)5; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned short' + // XL: + short si16 = 55; + vbi16_2 = (vector bool short)si16; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned short' + // XL: %splat.splatinsert1 = insertelement <8 x i16> + // XL-NEXT: %splat.splat2 = shufflevector <8 x i16> %splat.splatinsert1 + + // vector bool int initialization + vbi32_1 = (vector bool int)9; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned int' + // XL: + int si32 = 99; + vbi32_2 = (vector bool int)si32; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned int' + // XL: %splat.splatinsert3 = insertelement <4 x i32> + // XL-NEXT: %splat.splat4 = shufflevector <4 x i32> %splat.splatinsert3 + + // vector bool long long initialization + vbi64_1 = (vector bool long long)13; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned long long' + // XL: + long long si64 = 1313; + vbi64_2 = (vector bool long long)si64; + // MIXED: error: invalid conversion between vector type '__vector __bool unsigned long long' + // XL: %splat.splatinsert5 = insertelement <2 x i64> + // XL-NEXT: %splat.splat6 = shufflevector <2 x i64> %splat.splatinsert5 + + // vector pixel initialization + p1 = (vector pixel)1; + // MIXED: error: invalid conversion between vector type '__vector __pixel ' + // XL: +} + diff --git a/clang/test/CodeGen/vector-scalar-altivec-init.c b/clang/test/CodeGen/vector-scalar-altivec-init.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/vector-scalar-altivec-init.c @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s + +vector char vi8_1; +vector char vi8_2; +vector unsigned char vui8_1; +vector unsigned char vui8_2; + +vector short vi16_1; +vector short vi16_2; +vector unsigned short vui16_1; +vector unsigned short vui16_2; + +vector int vi32_1; +vector int vi32_2; +vector unsigned int vui32_1; +vector unsigned int vui32_2; + +vector long long vi64_1; +vector long long vi64_2; +vector unsigned long long vui64_1; +vector unsigned long long vui64_2; + +vector float f1; +vector float f2; +vector double d1; +vector double d2; + +//////////////////////////////////////////////////////////////////////////////// +void test_vector_scalar_init() { + // vector char initialization + vi8_1 = (vector char)('A'); + // CHECK: + char two = '2'; + vi8_2 = (vector char)(two); + // CHECK: %splat.splatinsert = insertelement <16 x i8> + // CHECK: %splat.splat = shufflevector <16 x i8> + + vui8_1 = (vector unsigned char)('B'); + // CHECK: + unsigned char three = '3'; + vui8_2 = (vector unsigned char)(three); + // CHECK: %splat.splatinsert1 = insertelement <16 x i8> + // CHECK: %splat.splat2 = shufflevector <16 x i8> + + // vector short initialization + vi16_1 = (vector short)(5); + // CHECK: + short six = 6; + vi16_2 = (vector short)(six); + // CHECK: %splat.splatinsert3 = insertelement <8 x i16> + // CHECK: %splat.splat4 = shufflevector <8 x i16> + + vui16_1 = (vector unsigned short)(7); + // CHECK: + unsigned short eight = 8; + vui16_2 = (vector unsigned short)(eight); + // CHECK: %splat.splatinsert5 = insertelement <8 x i16> + // CHECK: %splat.splat6 = shufflevector <8 x i16> + + // vector int initialization + vi32_1 = (vector int)(9); + // CHECK: + int ten = 10; + vi32_2 = (vector int)(ten); + // CHECK: %splat.splatinsert7 = insertelement <4 x i32> + // CHECK: %splat.splat8 = shufflevector <4 x i32> + + vui32_1 = (vector unsigned int)(11); + // CHECK: + unsigned int twelve = 12; + vui32_2 = (vector unsigned int)(twelve); + // CHECK: %splat.splatinsert9 = insertelement <4 x i32> + // CHECK: %splat.splat10 = shufflevector <4 x i32> + + // vector long long initialization + vi64_1 = (vector long long)(143); + // CHECK: + long long thousand = 1000; + vi64_1 = (vector long long)(thousand); + // CHECK: %splat.splatinsert11 = insertelement <2 x i64> + // CHECK: %splat.splat12 = shufflevector <2 x i64> + + vui64_1 = (vector unsigned long long)(99); + // CHECK: + unsigned long long twothousand = 2000; + vui64_1 = (vector unsigned long long)(twothousand); + // CHECK: %splat.splatinsert13 = insertelement <2 x i64> + // CHECK: %splat.splat14 = shufflevector <2 x i64> + + // vector float, double initialization + f1 = (vector float)(17.5); + // CHECK: + float f_temp = 20.2; + f2 = (vector float)(f_temp); + // CHECK: %splat.splatinsert15 = insertelement <4 x float> + // CHECK: %splat.splat16 = shufflevector <4 x float> + + d1 = (vector double)(8.7); + // CHECK: + double d_temp = 87.87; + d2 = (vector double)(d_temp); + // CHECK: %splat.splatinsert17 = insertelement <2 x double> + // CHECK: %splat.splat18 = shufflevector <2 x double> +} diff --git a/clang/test/CodeGen/vector-scalar-altivec-init2.c b/clang/test/CodeGen/vector-scalar-altivec-init2.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/vector-scalar-altivec-init2.c @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s + +vector char vi8_1; +vector char vi8_2; +vector unsigned char vui8_1; +vector unsigned char vui8_2; + +vector short vi16_1; +vector short vi16_2; +vector unsigned short vui16_1; +vector unsigned short vui16_2; + +vector int vi32_1; +vector int vi32_2; +vector unsigned int vui32_1; +vector unsigned int vui32_2; + +vector long long vi64_1; +vector long long vi64_2; +vector unsigned long long vui64_1; +vector unsigned long long vui64_2; + +vector float f1; +vector float f2; +vector double d1; +vector double d2; + +//////////////////////////////////////////////////////////////////////////////// +void test_vector_scalar_init() { + // vector char initialization + vi8_1 = (vector char)'A'; + // CHECK: + char two = '2'; + vi8_2 = (vector char)two; + // CHECK: %splat.splatinsert = insertelement <16 x i8> + // CHECK: %splat.splat = shufflevector <16 x i8> + + vui8_1 = (vector unsigned char)'B'; + // CHECK: + unsigned char three = '3'; + vui8_2 = (vector unsigned char)three; + // CHECK: %splat.splatinsert1 = insertelement <16 x i8> + // CHECK: %splat.splat2 = shufflevector <16 x i8> + + // vector short initialization + vi16_1 = (vector short)5; + // CHECK: + short six = 6; + vi16_2 = (vector short)six; + // CHECK: %splat.splatinsert3 = insertelement <8 x i16> + // CHECK: %splat.splat4 = shufflevector <8 x i16> + + vui16_1 = (vector unsigned short)7; + // CHECK: + unsigned short eight = 8; + vui16_2 = (vector unsigned short)eight; + // CHECK: %splat.splatinsert5 = insertelement <8 x i16> + // CHECK: %splat.splat6 = shufflevector <8 x i16> + + // vector int initialization + vi32_1 = (vector int)9; + // CHECK: + int ten = 10; + vi32_2 = (vector int)ten; + // CHECK: %splat.splatinsert7 = insertelement <4 x i32> + // CHECK: %splat.splat8 = shufflevector <4 x i32> + + vui32_1 = (vector unsigned int)11; + // CHECK: + unsigned int twelve = 12; + vui32_2 = (vector unsigned int)twelve; + // CHECK: %splat.splatinsert9 = insertelement <4 x i32> + // CHECK: %splat.splat10 = shufflevector <4 x i32> + + // vector long long initialization + vi64_1 = (vector long long)143; + // CHECK: + long long thousand = 1000; + vi64_1 = (vector long long)thousand; + // CHECK: %splat.splatinsert11 = insertelement <2 x i64> + // CHECK: %splat.splat12 = shufflevector <2 x i64> + + vui64_1 = (vector unsigned long long)99; + // CHECK: + unsigned long long twothousand = 2000; + vui64_1 = (vector unsigned long long)twothousand; + // CHECK: %splat.splatinsert13 = insertelement <2 x i64> + // CHECK: %splat.splat14 = shufflevector <2 x i64> + + // vector float, double initialization + f1 = (vector float)17.5; + // CHECK: + float f_temp = 20.2; + f2 = (vector float)f_temp; + // CHECK: %splat.splatinsert15 = insertelement <4 x float> + // CHECK: %splat.splat16 = shufflevector <4 x float> + + d1 = (vector double)8.7; + // CHECK: + double d_temp = 87.87; + d2 = (vector double)d_temp; + // CHECK: %splat.splatinsert17 = insertelement <2 x double> + // CHECK: %splat.splat18 = shufflevector <2 x double> +}