From: Stephen Canon Date: Thu, 3 Apr 2014 10:33:25 +0000 (+0000) Subject: Improved semantics for implicit scalar -> extvector conversions. X-Git-Tag: llvmorg-3.5.0-rc1~7642 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3ba640d7aef9fb3f9be143853a48d44053f0b5f3;p=platform%2Fupstream%2Fllvm.git Improved semantics for implicit scalar -> extvector conversions. llvm-svn: 205521 --- diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 41c7613c74a4..27cc8a37a5b1 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5780,6 +5780,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, Source = cast(Source)->getElementType().getTypePtr(); Target = cast(Target)->getElementType().getTypePtr(); } + if (auto VecTy = dyn_cast(Target)) + Target = VecTy->getElementType().getTypePtr(); // Strip complex types. if (isa(Source)) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f0e0485e2317..7894682efcfc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6696,35 +6696,40 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, return QualType(); } -/// Try to convert a value of non-vector type to a vector type by -/// promoting (and only promoting) the type to the element type of the -/// vector and then performing a vector splat. +/// Try to convert a value of non-vector type to a vector type by converting +/// the type to the element type of the vector and then performing a splat. +/// If the language is OpenCL, we only use conversions that promote scalar +/// rank; for C, Obj-C, and C++ we allow any real scalar conversion except +/// for float->int. /// /// \param scalar - if non-null, actually perform the conversions /// \return true if the operation fails (but without diagnosing the failure) -static bool tryVectorPromoteAndSplat(Sema &S, ExprResult *scalar, +static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar, QualType scalarTy, QualType vectorEltTy, QualType vectorTy) { // The conversion to apply to the scalar before splatting it, // if necessary. CastKind scalarCast = CK_Invalid; - + if (vectorEltTy->isIntegralType(S.Context)) { - if (!scalarTy->isIntegralType(S.Context)) return true; - int order = S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy); - if (order < 0) return true; - if (order > 0) scalarCast = CK_IntegralCast; + if (!scalarTy->isIntegralType(S.Context)) + return true; + if (S.getLangOpts().OpenCL && + S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0) + return true; + scalarCast = CK_IntegralCast; } else if (vectorEltTy->isRealFloatingType()) { if (scalarTy->isRealFloatingType()) { - int order = S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy); - if (order < 0) return true; - if (order > 0) scalarCast = CK_FloatingCast; - } else if (scalarTy->isIntegralType(S.Context)) { + if (S.getLangOpts().OpenCL && + S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy) < 0) + return true; + scalarCast = CK_FloatingCast; + } + else if (scalarTy->isIntegralType(S.Context)) scalarCast = CK_IntegralToFloating; - } else { + else return true; - } } else { return true; } @@ -6732,7 +6737,7 @@ static bool tryVectorPromoteAndSplat(Sema &S, ExprResult *scalar, // Adjust scalar if desired. if (scalar) { if (scalarCast != CK_Invalid) - *scalar = S.ImpCastExprToType(scalar->take(), vectorEltTy, scalarCast); + *scalar = S.ImpCastExprToType(scalar->take(), vectorEltTy, scalarCast); *scalar = S.ImpCastExprToType(scalar->take(), vectorTy, CK_VectorSplat); } return false; @@ -6775,6 +6780,19 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return RHSType; } + // If there's an ext-vector type and a scalar, try to convert the scalar to + // the vector element type and splat. + if (!RHSVecType && isa(LHSVecType)) { + if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, + LHSVecType->getElementType(), LHSType)) + return LHSType; + } + if (!LHSVecType && isa(RHSVecType)) { + if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? 0 : &LHS), LHSType, + RHSVecType->getElementType(), RHSType)) + return RHSType; + } + // If we're allowing lax vector conversions, only the total (data) size // needs to be the same. // FIXME: Should we really be allowing this? @@ -6785,19 +6803,6 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return resultType; } - // If there's an ext-vector type and a scalar, try to promote (and - // only promote) and splat the scalar to the vector type. - if (!RHSVecType && isa(LHSVecType)) { - if (!tryVectorPromoteAndSplat(*this, &RHS, RHSType, - LHSVecType->getElementType(), LHSType)) - return LHSType; - } - if (!LHSVecType && isa(RHSVecType)) { - if (!tryVectorPromoteAndSplat(*this, (IsCompAssign ? 0 : &LHS), LHSType, - RHSVecType->getElementType(), RHSType)) - return RHSType; - } - // Okay, the expression is invalid. // If there's a non-vector, non-real operand, diagnose that. diff --git a/clang/test/Sema/ext_vector_casts.c b/clang/test/Sema/ext_vector_casts.c index 5ad24faaaed1..d60bc3c65c8c 100644 --- a/clang/test/Sema/ext_vector_casts.c +++ b/clang/test/Sema/ext_vector_casts.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -fsyntax-only -verify -fno-lax-vector-conversions %s +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -fsyntax-only -verify -fno-lax-vector-conversions -Wconversion %s typedef __attribute__(( ext_vector_type(2) )) float float2; typedef __attribute__(( ext_vector_type(3) )) float float3; @@ -38,9 +38,8 @@ static void test() { ivec4 = (int4)ptr; // expected-error {{invalid conversion between vector type 'int4' and scalar type 'int *'}} vec4 = (float4)vec2; // expected-error {{invalid conversion between ext-vector type 'float4' and 'float2'}} - - ish8 += 5; // expected-error {{can't convert between vector values of different size ('short8' and 'int')}} - ish8 += (short)5; + + ish8 += 5; ivec4 *= 5; vec4 /= 5.2f; vec4 %= 4; // expected-error {{invalid operands to binary expression ('float4' and 'int')}} @@ -89,3 +88,37 @@ extern float32x4_t vabsq_f32(float32x4_t __a); C3DVector3 Func(const C3DVector3 a) { return (C3DVector3)vabsq_f32((float32x4_t)a); // expected-error {{invalid conversion between ext-vector type 'float32x4_t' and 'C3DVector3'}} } + +// rdar://16350802 +typedef double double2 __attribute__ ((ext_vector_type(2))); + +static void splats(int i, long l, __uint128_t t, float f, double d) { + short8 vs = 0; + int4 vi = i; + ulong2 vl = (unsigned long)l; + float2 vf = f; + double2 vd = d; + + vs = 65536 + vs; // expected-warning {{implicit conversion from 'int' to 'short8' changes value from 65536 to 0}} + vs = vs + i; // expected-warning {{implicit conversion loses integer precision}} + vs = vs + 1; + vs = vs + 1.f; // expected-error {{can't convert between vector values of different size}} + + vi = l + vi; // expected-warning {{implicit conversion loses integer precision}} + vi = 1 + vi; + vi = vi + 2.0; // expected-error {{can't convert between vector values of different size}} + vi = vi + 0xffffffff; // expected-warning {{implicit conversion changes signedness}} + + vl = l + vl; // expected-warning {{implicit conversion changes signedness}} + vl = vl + t; // expected-warning {{implicit conversion loses integer precision}} + + vf = 1 + vf; + vf = l + vf; + vf = 2.0 + vf; + vf = d + vf; // expected-warning {{implicit conversion loses floating-point precision}} + vf = vf + 0xffffffff; + vf = vf + 2.1; // expected-warning {{implicit conversion loses floating-point precision}} + + vd = l + vd; + vd = vd + t; +}