diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -13563,6 +13563,29 @@ const BuiltinType *SourceBT = dyn_cast(Source); const BuiltinType *TargetBT = dyn_cast(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 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10261,12 +10261,18 @@ ExprResult *Vector) { QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType(); QualType VectorTy = Vector->get()->getType().getUnqualifiedType(); - const auto *VT = VectorTy->castAs(); - - assert(!isa(VT) && - "ExtVectorTypes should not be handled here!"); - - QualType VectorEltTy = VT->getElementType(); + QualType VectorEltTy; + + if (const auto *VT = VectorTy->getAs()) { + assert(!isa(VT) && + "ExtVectorTypes should not be handled here!"); + VectorEltTy = VT->getElementType(); + } else if (VectorTy->isVLSTBuiltinType()) { + VectorEltTy = + VectorTy->castAs()->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 @@ 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 --- a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c +++ b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c @@ -328,6 +328,132 @@ return a + b; } +// CHECK-LABEL: @add_i8_i_lit( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 [[A:%.*]], zeroinitializer +// CHECK-NEXT: ret [[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 --- 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)(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 --- a/clang/test/Sema/sizeless-1.c +++ b/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}} diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp --- a/clang/test/SemaCXX/sizeless-1.cpp +++ b/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'}}