[clang] b4f2f7b - [clang][AArch64][SVE] Implicit conversions for vector-scalar operations

David Truby via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 13 03:22:19 PDT 2022


Author: David Truby
Date: 2022-06-13T10:22:10Z
New Revision: b4f2f7bebd29f7cedd3ce93c1925e8029b8e2b05

URL: https://github.com/llvm/llvm-project/commit/b4f2f7bebd29f7cedd3ce93c1925e8029b8e2b05
DIFF: https://github.com/llvm/llvm-project/commit/b4f2f7bebd29f7cedd3ce93c1925e8029b8e2b05.diff

LOG: [clang][AArch64][SVE] Implicit conversions for vector-scalar operations

This patch allows the same implicit conversions for vector-scalar
operations in SVE that are allowed for NEON.

Depends on D126377

Reviewed By: c-rhodes

Differential Revision: https://reviews.llvm.org/D126380

Added: 
    

Modified: 
    clang/lib/Sema/SemaChecking.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
    clang/test/Sema/aarch64-sve-vector-arith-ops.c
    clang/test/Sema/sizeless-1.c
    clang/test/SemaCXX/sizeless-1.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 57a034d3c61e9..9cb031b87f3a8 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -13574,6 +13574,29 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
   const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
   const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
 
+  // Strip SVE vector types
+  if (SourceBT && SourceBT->isVLSTBuiltinType()) {
+    // Need the original target type for vector type checks
+    const Type *OriginalTarget = S.Context.getCanonicalType(T).getTypePtr();
+    // Handle conversion from scalable to fixed when msve-vector-bits is
+    // specified
+    if (S.Context.areCompatibleSveTypes(QualType(OriginalTarget, 0),
+                                        QualType(Source, 0)) ||
+        S.Context.areLaxCompatibleSveTypes(QualType(OriginalTarget, 0),
+                                           QualType(Source, 0)))
+      return;
+
+    // If the vector cast is cast between two vectors of the same size, it is
+    // a bitcast, not a conversion.
+    if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target))
+      return;
+
+    Source = SourceBT->getSveEltType(S.Context).getTypePtr();
+  }
+
+  if (TargetBT && TargetBT->isVLSTBuiltinType())
+    Target = TargetBT->getSveEltType(S.Context).getTypePtr();
+
   // If the source is floating point...
   if (SourceBT && SourceBT->isFloatingPoint()) {
     // ...and the target is floating point...

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e44172c399639..7e6618bd2d11d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10261,12 +10261,18 @@ static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar,
                                         ExprResult *Vector) {
   QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType();
   QualType VectorTy = Vector->get()->getType().getUnqualifiedType();
-  const auto *VT = VectorTy->castAs<VectorType>();
-
-  assert(!isa<ExtVectorType>(VT) &&
-         "ExtVectorTypes should not be handled here!");
-
-  QualType VectorEltTy = VT->getElementType();
+  QualType VectorEltTy;
+
+  if (const auto *VT = VectorTy->getAs<VectorType>()) {
+    assert(!isa<ExtVectorType>(VT) &&
+           "ExtVectorTypes should not be handled here!");
+    VectorEltTy = VT->getElementType();
+  } else if (VectorTy->isVLSTBuiltinType()) {
+    VectorEltTy =
+        VectorTy->castAs<BuiltinType>()->getSveEltType(S.getASTContext());
+  } else {
+    llvm_unreachable("Only Fixed-Length and SVE Vector types are handled here");
+  }
 
   // Reject cases where the vector element type or the scalar element type are
   // not integral or floating point types.
@@ -10593,24 +10599,14 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
   if (Context.hasSameType(LHSType, RHSType))
     return LHSType;
 
-  auto tryScalableVectorConvert = [this](ExprResult *Src, QualType SrcType,
-                                         QualType DestType) {
-    const QualType DestBaseType = DestType->getSveEltType(Context);
-    if (DestBaseType->getUnqualifiedDesugaredType() ==
-        SrcType->getUnqualifiedDesugaredType()) {
-      unsigned DiagID = diag::err_typecheck_invalid_operands;
-      if (!tryVectorConvertAndSplat(*this, Src, SrcType, DestBaseType, DestType,
-                                    DiagID))
-        return DestType;
-    }
-    return QualType();
-  };
-
   if (LHSType->isVLSTBuiltinType() && !RHSType->isVLSTBuiltinType()) {
-    auto DestType = tryScalableVectorConvert(&RHS, RHSType, LHSType);
-    if (DestType == QualType())
-      return InvalidOperands(Loc, LHS, RHS);
-    return DestType;
+    if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS))
+      return LHSType;
+  }
+  if (RHSType->isVLSTBuiltinType() && !LHSType->isVLSTBuiltinType()) {
+    if (LHS.get()->isLValue() ||
+        !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS))
+      return RHSType;
   }
 
   if ((!LHSType->isVLSTBuiltinType() && !LHSType->isRealType()) ||

diff  --git a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
index f14e7d1e84262..c57c476032025 100644
--- a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
+++ b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
@@ -328,6 +328,132 @@ svfloat64_t add_scalar_f64(svfloat64_t a, double b) {
   return a + b;
 }
 
+// CHECK-LABEL: @add_i8_i_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 16 x i8> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 16 x i8> [[ADD]]
+//
+svint8_t add_i8_i_lit(svint8_t a) {
+  return a + 0;
+}
+
+// CHECK-LABEL: @add_i8_il_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 16 x i8> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 16 x i8> [[ADD]]
+//
+svint8_t add_i8_il_lit(svint8_t a) {
+  return a + 0l;
+}
+
+// CHECK-LABEL: @add_i8_ill_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 16 x i8> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 16 x i8> [[ADD]]
+//
+svint8_t add_i8_ill_lit(svint8_t a) {
+  return a + 0ll;
+}
+
+// CHECK-LABEL: @add_i8_u_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 16 x i8> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 16 x i8> [[ADD]]
+//
+svint8_t add_i8_u_lit(svint8_t a) {
+  return a + 0u;
+}
+
+// CHECK-LABEL: @add_i8_ul_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 16 x i8> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 16 x i8> [[ADD]]
+//
+svint8_t add_i8_ul_lit(svint8_t a) {
+  return a + 0ul;
+}
+
+// CHECK-LABEL: @add_i8_ull_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 16 x i8> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 16 x i8> [[ADD]]
+//
+svint8_t add_i8_ull_lit(svint8_t a) {
+  return a + 0ull;
+}
+
+// CHECK-LABEL: @add_f64_i_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_i_lit(svfloat64_t a) {
+  return a + 0;
+}
+
+// CHECK-LABEL: @add_f64_il_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_il_lit(svfloat64_t a) {
+  return a + 0l;
+}
+
+// CHECK-LABEL: @add_f64_ill_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_ill_lit(svfloat64_t a) {
+  return a + 0ll;
+}
+
+// CHECK-LABEL: @add_f64_u_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_u_lit(svfloat64_t a) {
+  return a + 0u;
+}
+
+// CHECK-LABEL: @add_f64_ul_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_ul_lit(svfloat64_t a) {
+  return a + 0ul;
+}
+
+// CHECK-LABEL: @add_f64_ull_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_ull_lit(svfloat64_t a) {
+  return a + 0ull;
+}
+
+// CHECK-LABEL: @add_f64_f_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_f_lit(svfloat64_t a) {
+  return a + 0.f;
+}
+
+// CHECK-LABEL: @add_f64_d_lit(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = fadd <vscale x 2 x double> [[A:%.*]], zeroinitializer
+// CHECK-NEXT:    ret <vscale x 2 x double> [[ADD]]
+//
+svfloat64_t add_f64_d_lit(svfloat64_t a) {
+  return a + 0.;
+}
+
 // SUBTRACTION
 
 // CHECK-LABEL: @sub_i8(

diff  --git a/clang/test/Sema/aarch64-sve-vector-arith-ops.c b/clang/test/Sema/aarch64-sve-vector-arith-ops.c
index e81bc39fff359..c8147d287f647 100644
--- a/clang/test/Sema/aarch64-sve-vector-arith-ops.c
+++ b/clang/test/Sema/aarch64-sve-vector-arith-ops.c
@@ -701,3 +701,11 @@ void mod(svint8_t i8, svint16_t i16, svint32_t i32, svint64_t i64,
   (void)(s % f16); // expected-error{{invalid operands to binary expression}}
   (void)(s % f32); // expected-error{{invalid operands to binary expression}}
 }
+
+svint8_t svi8(svint8_t a) {
+  return a + 256; // expected-error{{cannot convert between scalar type 'int' and vector type 'svint8_t' (aka '__SVInt8_t') as implicit conversion would cause truncation}}
+}
+
+svint8_t svi8_128(svint8_t a) {
+  return a + 128; // expected-warning{{implicit conversion from 'int' to 'svint8_t' (aka '__SVInt8_t') changes value from 128 to -128}}
+}

diff  --git a/clang/test/Sema/sizeless-1.c b/clang/test/Sema/sizeless-1.c
index 2ee1ca9e87165..d50d1c629d13d 100644
--- a/clang/test/Sema/sizeless-1.c
+++ b/clang/test/Sema/sizeless-1.c
@@ -201,23 +201,6 @@ void func(int sel) {
   local_int8 &&init_int8;  // expected-error {{invalid operands to binary expression}}
   local_int8 || init_int8; // expected-error {{invalid operands to binary expression}}
 
-  local_int8 + 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 - 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 * 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 / 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 % 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 & 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 | 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 ^ 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 < 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 <= 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 == 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 != 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 >= 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 > 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 && 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 || 0; // expected-error {{invalid operands to binary expression}}
-
   if (local_int8) { // expected-error {{statement requires expression of scalar type}}
   }
   while (local_int8) { // expected-error {{statement requires expression of scalar type}}

diff  --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp
index 1e6987955cc7a..e0ca847bcdb29 100644
--- a/clang/test/SemaCXX/sizeless-1.cpp
+++ b/clang/test/SemaCXX/sizeless-1.cpp
@@ -213,23 +213,6 @@ void func(int sel) {
   local_int8 &&init_int8;  // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}}
   local_int8 || init_int8; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}}
 
-  local_int8 + 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 - 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 * 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 / 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 % 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 & 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 | 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 ^ 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 < 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 <= 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 == 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 != 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 >= 0; // expected-error {{invalid operands to binary expression}}
-  local_int8 > 0;  // expected-error {{invalid operands to binary expression}}
-  local_int8 && 0; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}}
-  local_int8 || 0; // expected-error {{invalid operands to binary expression}} expected-error {{not contextually convertible}}
-
   if (local_int8) { // expected-error {{not contextually convertible to 'bool'}}
   }
   while (local_int8) { // expected-error {{not contextually convertible to 'bool'}}


        


More information about the cfe-commits mailing list