diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index b2663714340b939..5647963e884b7d8 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -3542,8 +3542,8 @@ bool Compiler::VisitConvertVectorExpr(const ConvertVectorExpr *E) { QualType ElemType = VT->getElementType(); PrimType ElemT = classifyPrim(ElemType); const Expr *Src = E->getSrcExpr(); - PrimType SrcElemT = - classifyPrim(Src->getType()->castAs()->getElementType()); + QualType SrcType = Src->getType(); + PrimType SrcElemT = classifyVectorElementType(SrcType); unsigned SrcOffset = this->allocateLocalPrimitive(Src, PT_Ptr, true, false); if (!this->visit(Src)) @@ -3556,9 +3556,15 @@ bool Compiler::VisitConvertVectorExpr(const ConvertVectorExpr *E) { return false; if (!this->emitArrayElemPop(SrcElemT, I, E)) return false; + + // Cast to the desired result element type. if (SrcElemT != ElemT) { if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E)) return false; + } else if (ElemType->isFloatingType() && SrcType != ElemType) { + const auto *TargetSemantics = &Ctx.getFloatSemantics(ElemType); + if (!this->emitCastFP(TargetSemantics, getRoundingMode(E), E)) + return false; } if (!this->emitInitElem(ElemT, I, E)) return false; diff --git a/clang/test/AST/ByteCode/vectors.cpp b/clang/test/AST/ByteCode/vectors.cpp index 7662abeeb7f5965..a0aace44f3c981e 100644 --- a/clang/test/AST/ByteCode/vectors.cpp +++ b/clang/test/AST/ByteCode/vectors.cpp @@ -125,3 +125,21 @@ constexpr int a2() { } static_assert(a2() == 0); + +namespace { + /// convertvector expr with a per-element floating-point cast + + typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); + typedef double __m128d __attribute__((__vector_size__(16), __aligned__(16))); + typedef float __v4sf __attribute__((__vector_size__(16))); + typedef double __v2df __attribute__((__vector_size__(16))); + + static inline constexpr __m128d + _mm_cvtps_pd(__m128 __a) { + return __builtin_convertvector(__builtin_shufflevector(__a, __a, 0, 1), __v2df); + } + + constexpr __m128 kf1 {-1.0f,+2.0f,-3.0f,+4.0f}; + constexpr __m128d v_mm_cvtps_pd = _mm_cvtps_pd(kf1); + static_assert(v_mm_cvtps_pd[0] == -1.0 && v_mm_cvtps_pd[1] == +2.0); +}