DavidTruby created this revision.
Herald added subscribers: ctetreau, psnobl, kristof.beyls, tschuett.
Herald added a reviewer: efriedma.
Herald added a project: All.
DavidTruby requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
This patch allows the same implicit conversions for vector-scalar
operations in SVE that are allowed for NEON.
Depends on D126377 <https://reviews.llvm.org/D126377>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D126380
Files:
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-scalar-ops.c
clang/test/Sema/sizeless-1.c
clang/test/SemaCXX/sizeless-1.cpp
Index: clang/test/SemaCXX/sizeless-1.cpp
===================================================================
--- clang/test/SemaCXX/sizeless-1.cpp
+++ clang/test/SemaCXX/sizeless-1.cpp
@@ -213,23 +213,6 @@
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'}}
Index: clang/test/Sema/sizeless-1.c
===================================================================
--- clang/test/Sema/sizeless-1.c
+++ clang/test/Sema/sizeless-1.c
@@ -201,23 +201,6 @@
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}}
Index: clang/test/Sema/aarch64-sve-vector-scalar-ops.c
===================================================================
--- /dev/null
+++ clang/test/Sema/aarch64-sve-vector-scalar-ops.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -verify -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +neon -fallow-half-arguments-and-returns -fsyntax-only %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_neon.h>
+#include <arm_sve.h>
+
+struct T {
+ int x;
+};
+
+void add_nonscalar(svint32_t i32, struct T a32, svbool_t b) {
+ (void)(i32 + a32); // expected-error{{cannot convert between vector and non-scalar values ('svint32_t' (aka '__SVInt32_t') and 'struct T')}}
+}
+
+void add_bool(svbool_t b) {
+ (void)(b + b); // expected-error{{invalid operands to binary expression ('svbool_t' (aka '__SVBool_t') and 'svbool_t')}}
+}
+
+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}}
+}
Index: clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
===================================================================
--- clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
+++ clang/test/CodeGen/aarch64-sve-vector-arith-ops.c
@@ -328,6 +328,132 @@
return a + b;
}
+// CHECK-LABEL: @add_i8_ilit(
+// 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_ilit(svint8_t a) {
+ return a + 0;
+}
+
+// CHECK-LABEL: @add_i8_illit(
+// 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_illit(svint8_t a) {
+ return a + 0l;
+}
+
+// CHECK-LABEL: @add_i8_illlit(
+// 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_illlit(svint8_t a) {
+ return a + 0ll;
+}
+
+// CHECK-LABEL: @add_i8_ulit(
+// 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_ulit(svint8_t a) {
+ return a + 0u;
+}
+
+// CHECK-LABEL: @add_i8_ullit(
+// 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_ullit(svint8_t a) {
+ return a + 0ul;
+}
+
+// CHECK-LABEL: @add_i8_ulllit(
+// 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_ulllit(svint8_t a) {
+ return a + 0ull;
+}
+
+// CHECK-LABEL: @add_f64_ilit(
+// 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_ilit(svfloat64_t a) {
+ return a + 0;
+}
+
+// CHECK-LABEL: @add_f64_illit(
+// 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_illit(svfloat64_t a) {
+ return a + 0l;
+}
+
+// CHECK-LABEL: @add_f64_illlit(
+// 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_illlit(svfloat64_t a) {
+ return a + 0ll;
+}
+
+// CHECK-LABEL: @add_f64_ulit(
+// 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_ulit(svfloat64_t a) {
+ return a + 0u;
+}
+
+// CHECK-LABEL: @add_f64_ullit(
+// 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_ullit(svfloat64_t a) {
+ return a + 0ul;
+}
+
+// CHECK-LABEL: @add_f64_ulllit(
+// 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_ulllit(svfloat64_t a) {
+ return a + 0ull;
+}
+
+// CHECK-LABEL: @add_f64_flit(
+// 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_flit(svfloat64_t a) {
+ return a + 0.f;
+}
+
+// CHECK-LABEL: @add_f64_dlit(
+// 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_dlit(svfloat64_t a) {
+ return a + 0.;
+}
+
// SUBTRACTION
// CHECK-LABEL: @sub_i8(
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -10257,12 +10257,21 @@
ExprResult *Vector) {
QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType();
QualType VectorTy = Vector->get()->getType().getUnqualifiedType();
- const auto *VT = VectorTy->castAs<VectorType>();
+ const auto *VT = VectorTy->getAs<VectorType>();
- assert(!isa<ExtVectorType>(VT) &&
- "ExtVectorTypes should not be handled here!");
+ assert(!VT || !isa<ExtVectorType>(VT) &&
+ "ExtVectorTypes should not be handled here!");
- QualType VectorEltTy = VT->getElementType();
+ QualType VectorEltTy;
+
+ if (VT) {
+ VectorEltTy = VT->getElementType();
+ } else if (VectorTy->isVLSTBuiltinType()) {
+ const auto *BuiltinTy = VectorTy->castAs<BuiltinType>();
+ VectorEltTy = BuiltinTy->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.
@@ -10589,24 +10598,14 @@
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()) ||
@@ -10617,7 +10616,7 @@
return QualType();
}
- if (LHSBuiltinTy && RHSBuiltinTy &&
+ if (LHSType->isVLSTBuiltinType() && RHSType->isVLSTBuiltinType() &&
Context.getBuiltinVectorTypeInfo(LHSBuiltinTy).EC !=
Context.getBuiltinVectorTypeInfo(RHSBuiltinTy).EC) {
Diag(Loc, diag::err_typecheck_vector_lengths_not_equal)
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -13576,6 +13576,35 @@
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 (!Target->isVLSTBuiltinType() && !isa<VectorType>(OriginalTarget)) {
+ if (S.SourceMgr.isInSystemMacro(CC))
+ return;
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
+ }
+
+ // 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...
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits