forked from OSchip/llvm-project
[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
This commit is contained in:
parent
988682a389
commit
b4f2f7bebd
|
@ -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...
|
||||
|
|
|
@ -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>();
|
||||
QualType VectorEltTy;
|
||||
|
||||
assert(!isa<ExtVectorType>(VT) &&
|
||||
"ExtVectorTypes should not be handled here!");
|
||||
|
||||
QualType VectorEltTy = VT->getElementType();
|
||||
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()) ||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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'}}
|
||||
|
|
Loading…
Reference in New Issue