Skip to content
Snippets Groups Projects
Commit b8689ee7 authored by Bruno Cardoso Lopes's avatar Bruno Cardoso Lopes
Browse files

[SemaExpr] Support assignments from vector to scalars with same size

Before r266366, clang used to support constructs like:

  typedef __attribute__((vector_size(8))) double float64x1_t;
  typedef __attribute__((vector_size(16))) double float64x2_t;
  float64x1_t vget_low_f64(float64x2_t __p0);

  double y = 3.0 + vget_low_f64(v);

But it would reject:

  double y = vget_low_f64(v) + 3.0;

It also always rejected assignments:

  double y = vget_low_f64(v);

This patch: (a) revivies the behavior of `3.0 + vget_low_f64(v)` prior to
r266366, (b) add support for `vget_low_f64(v) + 3.0` and (c) add support for
assignments.

These vector semantics have never really been tied up but it seems
odd that we used to support some binop froms but do not support
assignment. If we did support scalar for the purposes of arithmetic, we
should probably be able to reinterpret as scalar for the purposes of
assignment too.

Differential Revision: http://reviews.llvm.org/D21700

rdar://problem/26093791

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274646 91177308-0d34-0410-b5e6-96231b3b80d8
parent a30322e8
No related branches found
No related tags found
No related merge requests found
...@@ -7394,6 +7394,22 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, ...@@ -7394,6 +7394,22 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return IncompatibleVectors; return IncompatibleVectors;
} }
} }
// When the RHS comes from another lax conversion (e.g. binops between
// scalars and vectors) the result is canonicalized as a vector. When the
// LHS is also a vector, the lax is allowed by the condition above. Handle
// the case where LHS is a scalar.
if (LHSType->isScalarType()) {
const VectorType *VecType = RHSType->getAs<VectorType>();
if (VecType && VecType->getNumElements() == 1 &&
isLaxVectorConversion(RHSType, LHSType)) {
ExprResult *VecExpr = &RHS;
*VecExpr = ImpCastExprToType(VecExpr->get(), LHSType, CK_BitCast);
Kind = CK_BitCast;
return Compatible;
}
}
return Incompatible; return Incompatible;
} }
   
......
...@@ -45,15 +45,23 @@ void f3(t3 Y) { ...@@ -45,15 +45,23 @@ void f3(t3 Y) {
} }
typedef float float2 __attribute__ ((vector_size (8))); typedef float float2 __attribute__ ((vector_size (8)));
typedef __attribute__((vector_size(8))) double float64x1_t;
typedef __attribute__((vector_size(16))) double float64x2_t;
float64x1_t vget_low_f64(float64x2_t __p0);
void f4() { void f4() {
float2 f2; float2 f2;
double d; double d, a, b, c;
float64x2_t v = {0.0, 1.0};
f2 += d; f2 += d;
// We used to allow the next statement, but we've always rejected the next two a = 3.0 + vget_low_f64(v);
// statements b = vget_low_f64(v) + 3.0;
c = vget_low_f64(v);
// LAX conversions within compound assignments are not supported.
// FIXME: This diagnostic is inaccurate. // FIXME: This diagnostic is inaccurate.
d += f2; // expected-error {{cannot convert between vector values of different size}} d += f2; // expected-error {{cannot convert between vector values of different size}}
c -= vget_low_f64(v); // expected-error {{cannot convert between vector values of different size}}
// LAX conversions between scalar and vector types require same size and one element sized vectors.
d = f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}} d = f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}}
d = d + f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}} d = d + f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}}
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment