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

Reply via email to