Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -8513,6 +8513,10 @@ bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind); + /// \brief Prepare `SplattedExpr` for a vector splat operation, adding + /// implicit casts if necessary. + ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr); + // CheckExtVectorCast - check type constraints for extended vectors. // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size, Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -1150,7 +1150,7 @@ static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info); static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); -static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); +static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); @@ -1575,7 +1575,7 @@ static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, QualType DestType, QualType SrcType, - APSInt &Value) { + const APSInt &Value) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. @@ -5619,7 +5619,7 @@ return VectorExprEvaluator(Info, Result).Visit(E); } -bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { +bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { const VectorType *VTy = E->getType()->castAs(); unsigned NElts = VTy->getNumElements(); @@ -5632,13 +5632,13 @@ if (SETy->isIntegerType()) { APSInt IntResult; if (!EvaluateInteger(SE, IntResult, Info)) - return false; - Val = APValue(IntResult); + return false; + Val = APValue(std::move(IntResult)); } else if (SETy->isRealFloatingType()) { - APFloat F(0.0); - if (!EvaluateFloat(SE, F, Info)) - return false; - Val = APValue(F); + APFloat FloatResult(0.0); + if (!EvaluateFloat(SE, FloatResult, Info)) + return false; + Val = APValue(std::move(FloatResult)); } else { return Error(E); } Index: lib/CodeGen/CGExprConstant.cpp =================================================================== --- lib/CodeGen/CGExprConstant.cpp +++ lib/CodeGen/CGExprConstant.cpp @@ -1350,15 +1350,17 @@ return llvm::ConstantStruct::get(STy, Complex); } case APValue::Vector: { - SmallVector Inits; unsigned NumElts = Value.getVectorLength(); + SmallVector Inits(NumElts); - for (unsigned i = 0; i != NumElts; ++i) { - const APValue &Elt = Value.getVectorElt(i); + for (unsigned I = 0; I != NumElts; ++I) { + const APValue &Elt = Value.getVectorElt(I); if (Elt.isInt()) - Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt())); + Inits[I] = llvm::ConstantInt::get(VMContext, Elt.getInt()); + else if (Elt.isFloat()) + Inits[I] = llvm::ConstantFP::get(VMContext, Elt.getFloat()); else - Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat())); + llvm_unreachable("unsupported vector element type"); } return llvm::ConstantVector::get(Inits); } Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -2101,6 +2101,7 @@ && (SrcExpr.get()->getType()->isIntegerType() || SrcExpr.get()->getType()->isFloatingType())) { Kind = CK_VectorSplat; + SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); return; } @@ -2335,6 +2336,7 @@ if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && (SrcType->isIntegerType() || SrcType->isFloatingType())) { Kind = CK_VectorSplat; + SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { SrcExpr = ExprError(); } Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -5563,6 +5563,19 @@ return false; } +ExprResult Sema::prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr) { + QualType DestElemTy = VectorTy->castAs()->getElementType(); + + if (DestElemTy == SplattedExpr->getType()) + return SplattedExpr; + + ExprResult CastExprRes = SplattedExpr; + CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + return ImpCastExprToType(CastExprRes.get(), DestElemTy, CK); +} + ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr, CastKind &Kind) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); @@ -5593,15 +5606,8 @@ diag::err_invalid_conversion_between_vector_and_scalar) << DestTy << SrcTy << R; - QualType DestElemTy = DestTy->getAs()->getElementType(); - ExprResult CastExprRes = CastExpr; - CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); - if (CastExprRes.isInvalid()) - return ExprError(); - CastExpr = ImpCastExprToType(CastExprRes.get(), DestElemTy, CK).get(); - Kind = CK_VectorSplat; - return CastExpr; + return prepareVectorSplat(DestTy, CastExpr); } ExprResult @@ -6942,13 +6948,9 @@ if (RHSType->isExtVectorType()) return Incompatible; if (RHSType->isArithmeticType()) { - // CK_VectorSplat does T -> vector T, so first cast to the - // element type. - QualType elType = cast(LHSType)->getElementType(); - if (elType != RHSType && ConvertRHS) { - Kind = PrepareScalarCast(RHS, elType); - RHS = ImpCastExprToType(RHS.get(), elType, Kind); - } + // CK_VectorSplat does T -> vector T, so first cast to the element type. + if (ConvertRHS) + RHS = prepareVectorSplat(LHSType, RHS.get()); Kind = CK_VectorSplat; return Compatible; } @@ -8165,7 +8167,7 @@ if (RHS.isInvalid()) return QualType(); QualType LHSType = LHS.get()->getType(); - const VectorType *LHSVecTy = LHSType->getAs(); + const VectorType *LHSVecTy = LHSType->castAs(); QualType LHSEleType = LHSVecTy->getElementType(); // Note that RHS might not be a vector. Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -3352,15 +3352,9 @@ case ICK_Vector_Splat: // Vector splat from any arithmetic type to a vector. - // Cast to the element type. { - QualType elType = ToType->getAs()->getElementType(); - if (elType != From->getType()) { - ExprResult E = From; - From = ImpCastExprToType(From, elType, - PrepareScalarCast(E, elType)).get(); - } - From = ImpCastExprToType(From, ToType, CK_VectorSplat, + Expr *Elem = prepareVectorSplat(ToType, From).get(); + From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_RValue, /*BasePath=*/nullptr, CCK).get(); } break; Index: test/CodeGenCXX/builtins-systemz-zvector.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/builtins-systemz-zvector.cpp @@ -0,0 +1,50 @@ +// REQUIRES: systemz-registered-target +// RUN: %clang_cc1 -target-cpu z13 -triple s390x-linux-gnu \ +// RUN: -fzvector -fno-lax-vector-conversions -std=c++11 \ +// RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s + +bool gb; + +// There was an issue where we weren't properly converting constexprs to +// vectors with elements of the appropriate width. (e.g. +// (vector signed short)0 would be lowered as [4 x i32] in some cases) + +// CHECK-LABEL: @_Z8testIntsDv4_i +void testInts(vector int VI) { + constexpr vector int CI1 = (vector int)0LL; + // CHECK: icmp + gb = (VI == CI1)[0]; + + // Likewise for float inits. + constexpr vector int CI2 = (vector int)char(0); + // CHECK: icmp + gb = (VI == CI2)[0]; + + constexpr vector int CF1 = (vector int)0.0; + // CHECK: icmp + gb = (VI == CF1)[0]; + + constexpr vector int CF2 = (vector int)0.0f; + // CHECK: icmp + gb = (VI == CF2)[0]; +} + +// CHECK-LABEL: @_Z10testFloatsDv2_d +void testFloats(vector double VD) { + constexpr vector double CI1 = (vector double)0LL; + // CHECK: fcmp + gb = (VD == CI1)[0]; + + // Likewise for float inits. + constexpr vector double CI2 = (vector double)char(0); + // CHECK: fcmp + gb = (VD == CI2)[0]; + + constexpr vector double CF1 = (vector double)0.0; + // CHECK: fcmp + gb = (VD == CF1)[0]; + + constexpr vector double CF2 = (vector double)0.0f; + // CHECK: fcmp + gb = (VD == CF2)[0]; +}