sdardis created this revision. sdardis added subscribers: rnk, bruno, ahatanak, cfe-commits. Herald added a reviewer: vkalintiris.
This patch teaches clang to perform implicit scalar to vector conversions when one of the operands to a binary vector expression is a scalar like GCC. The scalar is implicitly casted to the vector elements type and splatted to produce a vector of the same type. https://reviews.llvm.org/D25866 Files: lib/Sema/SemaExpr.cpp test/Sema/vector-cast.c test/Sema/vector-scalar-implict-conv.c test/Sema/zvector.c
Index: test/Sema/zvector.c =================================================================== --- test/Sema/zvector.c +++ test/Sema/zvector.c @@ -326,14 +326,14 @@ bc = bc + sc2; // expected-error {{incompatible type}} bc = sc + bc2; // expected-error {{incompatible type}} - sc = sc + sc_scalar; // expected-error {{cannot convert}} - sc = sc + uc_scalar; // expected-error {{cannot convert}} - sc = sc_scalar + sc; // expected-error {{cannot convert}} - sc = uc_scalar + sc; // expected-error {{cannot convert}} - uc = uc + sc_scalar; // expected-error {{cannot convert}} - uc = uc + uc_scalar; // expected-error {{cannot convert}} - uc = sc_scalar + uc; // expected-error {{cannot convert}} - uc = uc_scalar + uc; // expected-error {{cannot convert}} + sc = sc + sc_scalar; + sc = sc + uc_scalar; // expected-error {{implicit conversion changes signedness: 'unsigned char' to '__vector signed char' (vector of 16 'signed char' values)}} + sc = sc_scalar + sc; + sc = uc_scalar + sc; // expected-error {{implicit conversion changes signedness: 'unsigned char' to '__vector signed char' (vector of 16 'signed char' values)}} + uc = uc + sc_scalar; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc = uc + uc_scalar; + uc = sc_scalar + uc; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc = uc_scalar + uc; ss = ss + ss2; us = us + us2; @@ -368,10 +368,10 @@ sc += sl2; // expected-error {{cannot convert}} sc += fd2; // expected-error {{cannot convert}} - sc += sc_scalar; // expected-error {{cannot convert}} - sc += uc_scalar; // expected-error {{cannot convert}} - uc += sc_scalar; // expected-error {{cannot convert}} - uc += uc_scalar; // expected-error {{cannot convert}} + sc += sc_scalar; + sc += uc_scalar; // expected-error {{implicit conversion changes signedness: 'unsigned char' to '__vector signed char' (vector of 16 'signed char' values)}} + uc += sc_scalar; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc += uc_scalar; ss += ss2; us += us2; Index: test/Sema/vector-scalar-implict-conv.c =================================================================== --- /dev/null +++ test/Sema/vector-scalar-implict-conv.c @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Weverything + +typedef long long v2i64 __attribute__((vector_size(16))); +typedef long long v2i64 __attribute__((vector_size(16))); + +typedef int v2i32 __attribute__((vector_size(8))); +typedef int v2i32 __attribute__((vector_size(8))); + +typedef unsigned long long v2u64 __attribute__((vector_size(16))); +typedef unsigned long long v2u64 __attribute__((vector_size(16))); + +typedef float v4f32 __attribute__((vector_size(16))); +typedef double v4f64 __attribute__((vector_size(32))); + +void test (void); + +void test (void){ + + v2i64 v2i64_a = (v2i64) {0, 1}; + v2i64 v2i64_r; + + v2i32 v2i32_a = (v2i32) {0 , 1}; + + v2u64 v2u64_a = (v2u64) {0, 1}; + + v4f32 v4f32_a = (v4f32) {0.1f, 0.2f, 0.3f, 0.4f}; + + v4f64 v4f64_r = v4f32_a; // expected-error {{initializing 'v4f64' (vector of 4 'double' values) with an expression of incompatible type 'v4f32' (vector of 4 'float' values)}} + + v4f64_r = v4f32_a; + + // FIXME: this should warn about truncation. + v4f32_a = v4f64_r; + + v2i64_r = v2i32_a; // expected-error {{assigning to 'v2i64' (vector of 2 'long long' values) from incompatible type 'v2i32' (vector of 2 'int' values)}} + + v2i64_r = v2u64_a; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'v2u64' (vector of 2 'unsigned long long' values)}} + + v2i64_r = v2i64_a + 1; + v2i64_r = v2i64_a - 1; + v2i64_r = v2i64_a * 1; + v2i64_r = v2i64_a / 1; + v2i64_r = v2i64_a % 1; + + v2i64_a += 1; + v2i64_a -= 1; + v2i64_a *= 1; + v2i64_a /= 1; + v2i64_a %= 1; + + v2i64_r = v2i64_a == 1; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + v2i64_r = v2i64_a != 1; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + + v2i64_r = v2i64_a < 1; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + + v2i64_r = v2i64_a > 1; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + + v2i64_r = v2i64_a <= 1; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + + v2i64_r = v2i64_a >= 1; // expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + + + v2i64_r = v2i64_a & 1; + v2i64_r = v2i64_a | 1; + v2i64_r = v2i64_a ^ 1; + + v2i64_a &= 1; + v2i64_a |= 1; + v2i64_a ^= 1; + + v2i64_r = v2i64_a && 1; // expected-warning {{implicit conversion turns vector to scalar: 'v2i64' (vector of 2 'long long' values) to '_Bool'}} expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + v2i64_r = v2i64_a || 1; // expected-warning {{implicit conversion turns vector to scalar: 'v2i64' (vector of 2 'long long' values) to '_Bool'}} expected-warning {{incompatible vector types assigning to 'v2i64' (vector of 2 'long long' values) from 'long __attribute__((ext_vector_type(2)))' (vector of 2 'long' values)}} + + + v2i64_r = v2i64_a << 1; + v2i64_r = v2i64_a >> 1; + + v2i64_a <<= 1; + v2i64_a >>= 1; + +} Index: test/Sema/vector-cast.c =================================================================== --- test/Sema/vector-cast.c +++ test/Sema/vector-cast.c @@ -53,9 +53,9 @@ float2 f2; double d, a, b, c; float64x2_t v = {0.0, 1.0}; - // FIXME: These diagnostics are inaccurate: should complain that 'double' to vector 'float2' involves truncation - f2 += d; // expected-error {{cannot convert between vector values of different size ('float2' (vector of 2 'float' values) and 'double')}} - d += f2; // expected-error {{cannot convert between vector values of different size}} + // FIXME: This lacks a diagnostic: should complain that 'double' to vector 'float2' involves truncation + f2 += d; + d += f2; // expected-error {{assigning to 'double' from incompatible type 'float2' (vector of 2 'float' values)}} a = 3.0 + vget_low_f64(v); b = vget_low_f64(v) + 3.0; c = vget_low_f64(v); Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -8039,15 +8039,14 @@ } } - // If there's an ext-vector type and a scalar, try to convert the scalar to + // If there's an vector type and a scalar, try to convert the scalar to // the vector element type and splat. - // FIXME: this should also work for regular vector types as supported in GCC. - if (!RHSVecType && isa<ExtVectorType>(LHSVecType)) { + if (!RHSVecType && isa<VectorType>(LHSVecType)) { if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, LHSVecType->getElementType(), LHSType)) return LHSType; } - if (!LHSVecType && isa<ExtVectorType>(RHSVecType)) { + if (!LHSVecType && isa<VectorType>(RHSVecType)) { if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), LHSType, RHSVecType->getElementType(), RHSType))
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits