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 that the vector type should be initialized from a scalar + // by splatting the value rather than populating a single element. + // This is the case for AltiVecVector types as well as with + // AltiVecPixel and AltiVecBool when -faltivec-src-compat=xl is specified. + bool ShouldSplatAltivecScalarInCast(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,19 @@ } } +bool Sema::ShouldSplatAltivecScalarInCast(const VectorType *VecTy) { + bool SrcCompatXL = this->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 +2691,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(vecTy) && + (SrcExpr.get()->getType()->isIntegerType() || + SrcExpr.get()->getType()->isFloatingType())) { Kind = CK_VectorSplat; SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); return; @@ -2963,8 +2976,8 @@ } if (const VectorType *DestVecTy = DestType->getAs()) { - if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && - (SrcType->isIntegerType() || SrcType->isFloatingType())) { + if (Self.ShouldSplatAltivecScalarInCast(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(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-no-parentheses.c b/clang/test/CodeGen/vector-bool-pixel-altivec-init-no-parentheses.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/vector-bool-pixel-altivec-init-no-parentheses.c @@ -0,0 +1,88 @@ +// 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-ERR +// 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-ERR +// 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-ERR +// 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-ERR +// 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_no_parentheses() { + // vector bool char initialization + vbi8_1 = (vector bool char)'a'; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned char' + // XL: + char c = 'c'; + vbi8_2 = (vector bool char)c; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned char' + // XL: [[INS_ELT:%.*]] = insertelement <16 x i8> + // XL: [[SHUFF:%.*]] = shufflevector <16 x i8> [[INS_ELT]], <16 x i8> poison, <16 x i32> zeroinitializer + // XL: store <16 x i8> [[SHUFF]] + + // vector bool short initialization + vbi16_1 = (vector bool short)5; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned short' + // XL: + short si16 = 55; + vbi16_2 = (vector bool short)si16; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned short' + // XL: [[INS_ELT:%.*]] = insertelement <8 x i16> + // XL: [[SHUFF:%.*]] = shufflevector <8 x i16> [[INS_ELT]], <8 x i16> poison, <8 x i32> zeroinitializer + // XL: store <8 x i16> [[SHUFF]] + + // vector bool int initialization + vbi32_1 = (vector bool int)9; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned int' + // XL: + int si32 = 99; + vbi32_2 = (vector bool int)si32; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned int' + // XL: [[INS_ELT:%.*]] = insertelement <4 x i32> + // XL: [[SHUFF:%.*]] = shufflevector <4 x i32> [[INS_ELT]], <4 x i32> poison, <4 x i32> zeroinitializer + // XL: store <4 x i32> [[SHUFF]] + + // vector bool long long initialization + vbi64_1 = (vector bool long long)13; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned long long' + // XL: + long long si64 = 1313; + vbi64_2 = (vector bool long long)si64; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned long long' + // XL: [[INS_ELT:%.*]] = insertelement <2 x i64> + // XL: [[SHUFF:%.*]] = shufflevector <2 x i64> [[INS_ELT]], <2 x i64> poison, <2 x i32> zeroinitializer + // XL: store <2 x i64> [[SHUFF]] + + // vector pixel initialization + p1 = (vector pixel)1; + // MIXED-ERR: error: invalid conversion between vector type '__vector __pixel ' + // XL: +} 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,92 @@ +// 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: [[INS:%.*]] = insertelement <16 x i8> + // MIXED: store <16 x i8> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <16 x i8> + // XL: [[SHUFF:%.*]] = shufflevector <16 x i8> [[INS_ELT]], <16 x i8> poison, <16 x i32> zeroinitializer + // XL: store <16 x i8> [[SHUFF]] + + // vector bool short initialization + vbi16_1 = (vector bool short)(5); + // MIXED: + // XL: + short si16 = 55; + vbi16_2 = (vector bool short)(si16); + // MIXED: [[INS:%.*]] = insertelement <8 x i16> + // MIXED: store <8 x i16> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <8 x i16> + // XL: [[SHUFF:%.*]] = shufflevector <8 x i16> [[INS_ELT]], <8 x i16> poison, <8 x i32> zeroinitializer + // XL: store <8 x i16> [[SHUFF]] + + // vector bool int initialization + vbi32_1 = (vector bool int)(9); + // MIXED: + // XL: + int si32 = 99; + vbi32_2 = (vector bool int)(si32); + // MIXED: [[INS:%.*]] = insertelement <4 x i32> + // MIXED: store <4 x i32> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <4 x i32> + // XL: [[SHUFF:%.*]] = shufflevector <4 x i32> [[INS_ELT]], <4 x i32> poison, <4 x i32> zeroinitializer + // XL: store <4 x i32> [[SHUFF]] + + // 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: [[INS:%.*]] = insertelement <2 x i64> + // MIXED: store <2 x i64> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <2 x i64> + // XL: [[SHUFF:%.*]] = shufflevector <2 x i64> [[INS_ELT]], <2 x i64> poison, <2 x i32> zeroinitializer + // XL: store <2 x i64> [[SHUFF]] + + // vector pixel initialization + p1 = (vector pixel)(1); + // MIXED: + // XL: +}