forked from OSchip/llvm-project
[Matrix] Implement C-style explicit type conversions for matrix types.
This implements C-style type conversions for matrix types, as specified in clang/docs/MatrixTypes.rst. Fixes PR47141. Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D99037
This commit is contained in:
parent
471ae42c04
commit
71ab6c98a0
|
@ -181,6 +181,9 @@ CAST_OPERATION(PointerToBoolean)
|
|||
/// (void) malloc(2048)
|
||||
CAST_OPERATION(ToVoid)
|
||||
|
||||
/// CK_MatrixCast - A cast between matrix types of the same dimensions.
|
||||
CAST_OPERATION(MatrixCast)
|
||||
|
||||
/// CK_VectorSplat - A conversion from an arithmetic type to a
|
||||
/// vector of that element type. Fills all elements ("splats") with
|
||||
/// the source value.
|
||||
|
|
|
@ -518,7 +518,7 @@ protected:
|
|||
|
||||
unsigned : NumExprBits;
|
||||
|
||||
unsigned Kind : 6;
|
||||
unsigned Kind : 7;
|
||||
unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr.
|
||||
|
||||
/// True if the call expression has some floating-point features.
|
||||
|
|
|
@ -8580,6 +8580,12 @@ let CategoryName = "Inline Assembly Issue" in {
|
|||
|
||||
let CategoryName = "Semantic Issue" in {
|
||||
|
||||
def err_invalid_conversion_between_matrixes : Error<
|
||||
"conversion between matrix types%diff{ $ and $|}0,1 of different size is not allowed">;
|
||||
|
||||
def err_invalid_conversion_between_matrix_and_type : Error<
|
||||
"conversion between matrix type %0 and incompatible type %1 is not allowed">;
|
||||
|
||||
def err_invalid_conversion_between_vectors : Error<
|
||||
"invalid conversion between vector type%diff{ $ and $|}0,1 of different "
|
||||
"size">;
|
||||
|
|
|
@ -11660,6 +11660,8 @@ public:
|
|||
|
||||
bool isValidSveBitcast(QualType srcType, QualType destType);
|
||||
|
||||
bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
|
||||
|
||||
bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
|
||||
bool isLaxVectorConversion(QualType srcType, QualType destType);
|
||||
|
||||
|
@ -11718,6 +11720,13 @@ public:
|
|||
ExprResult checkUnknownAnyArg(SourceLocation callLoc,
|
||||
Expr *result, QualType ¶mType);
|
||||
|
||||
// CheckMatrixCast - Check type constraints for matrix casts.
|
||||
// We allow casting between matrixes of the same dimensions i.e. when they
|
||||
// have the same number of rows and column. Returns true if the cast is
|
||||
// invalid.
|
||||
bool CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy,
|
||||
CastKind &Kind);
|
||||
|
||||
// CheckVectorCast - check type constraints for vectors.
|
||||
// Since vectors are an extension, there are no C standard reference for this.
|
||||
// We allow casting between vectors and integer datatypes of the same size.
|
||||
|
|
|
@ -1708,6 +1708,7 @@ bool CastExpr::CastConsistency() const {
|
|||
case CK_FixedPointCast:
|
||||
case CK_FixedPointToIntegral:
|
||||
case CK_IntegralToFixedPoint:
|
||||
case CK_MatrixCast:
|
||||
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
|
||||
goto CheckNoBasePath;
|
||||
|
||||
|
|
|
@ -13183,6 +13183,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
|
|||
case CK_FixedPointToFloating:
|
||||
case CK_FixedPointCast:
|
||||
case CK_IntegralToFixedPoint:
|
||||
case CK_MatrixCast:
|
||||
llvm_unreachable("invalid cast kind for integral value");
|
||||
|
||||
case CK_BitCast:
|
||||
|
@ -13923,6 +13924,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
|
|||
case CK_FixedPointToBoolean:
|
||||
case CK_FixedPointToIntegral:
|
||||
case CK_IntegralToFixedPoint:
|
||||
case CK_MatrixCast:
|
||||
llvm_unreachable("invalid cast kind for complex value");
|
||||
|
||||
case CK_LValueToRValue:
|
||||
|
|
|
@ -4645,6 +4645,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
|||
case CK_FixedPointToBoolean:
|
||||
case CK_FixedPointToIntegral:
|
||||
case CK_IntegralToFixedPoint:
|
||||
case CK_MatrixCast:
|
||||
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
|
||||
|
||||
case CK_Dependent:
|
||||
|
|
|
@ -901,6 +901,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
|||
case CK_CopyAndAutoreleaseBlockObject:
|
||||
case CK_BuiltinFnToFnPtr:
|
||||
case CK_ZeroToOCLOpaqueType:
|
||||
case CK_MatrixCast:
|
||||
|
||||
case CK_IntToOCLSampler:
|
||||
case CK_FloatingToFixedPoint:
|
||||
|
@ -1422,6 +1423,7 @@ static bool castPreservesZero(const CastExpr *CE) {
|
|||
case CK_PointerToIntegral:
|
||||
// Language extensions.
|
||||
case CK_VectorSplat:
|
||||
case CK_MatrixCast:
|
||||
case CK_NonAtomicToAtomic:
|
||||
case CK_AtomicToNonAtomic:
|
||||
return true;
|
||||
|
|
|
@ -533,6 +533,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
|
|||
case CK_FixedPointToBoolean:
|
||||
case CK_FixedPointToIntegral:
|
||||
case CK_IntegralToFixedPoint:
|
||||
case CK_MatrixCast:
|
||||
llvm_unreachable("invalid cast kind for complex value");
|
||||
|
||||
case CK_FloatingRealToComplex:
|
||||
|
|
|
@ -1170,6 +1170,7 @@ public:
|
|||
case CK_FixedPointToIntegral:
|
||||
case CK_IntegralToFixedPoint:
|
||||
case CK_ZeroToOCLOpaqueType:
|
||||
case CK_MatrixCast:
|
||||
return nullptr;
|
||||
}
|
||||
llvm_unreachable("Invalid CastKind");
|
||||
|
|
|
@ -1198,27 +1198,50 @@ Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
|
|||
QualType DstType, llvm::Type *SrcTy,
|
||||
llvm::Type *DstTy,
|
||||
ScalarConversionOpts Opts) {
|
||||
if (isa<llvm::IntegerType>(SrcTy)) {
|
||||
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
|
||||
if (SrcType->isBooleanType() && Opts.TreatBooleanAsSigned) {
|
||||
// The Element types determine the type of cast to perform.
|
||||
llvm::Type *SrcElementTy;
|
||||
llvm::Type *DstElementTy;
|
||||
QualType SrcElementType;
|
||||
QualType DstElementType;
|
||||
if (SrcType->isMatrixType() && DstType->isMatrixType()) {
|
||||
// Allow bitcast between matrixes of the same size.
|
||||
if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits())
|
||||
return Builder.CreateBitCast(Src, DstTy, "conv");
|
||||
|
||||
SrcElementTy = cast<llvm::VectorType>(SrcTy)->getElementType();
|
||||
DstElementTy = cast<llvm::VectorType>(DstTy)->getElementType();
|
||||
SrcElementType = SrcType->castAs<MatrixType>()->getElementType();
|
||||
DstElementType = DstType->castAs<MatrixType>()->getElementType();
|
||||
} else {
|
||||
assert(!SrcType->isMatrixType() && !DstType->isMatrixType() &&
|
||||
"cannot cast between matrix and non-matrix types");
|
||||
SrcElementTy = SrcTy;
|
||||
DstElementTy = DstTy;
|
||||
SrcElementType = SrcType;
|
||||
DstElementType = DstType;
|
||||
}
|
||||
|
||||
if (isa<llvm::IntegerType>(SrcElementTy)) {
|
||||
bool InputSigned = SrcElementType->isSignedIntegerOrEnumerationType();
|
||||
if (SrcElementType->isBooleanType() && Opts.TreatBooleanAsSigned) {
|
||||
InputSigned = true;
|
||||
}
|
||||
|
||||
if (isa<llvm::IntegerType>(DstTy))
|
||||
if (isa<llvm::IntegerType>(DstElementTy))
|
||||
return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
|
||||
if (InputSigned)
|
||||
return Builder.CreateSIToFP(Src, DstTy, "conv");
|
||||
return Builder.CreateUIToFP(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
if (isa<llvm::IntegerType>(DstTy)) {
|
||||
assert(SrcTy->isFloatingPointTy() && "Unknown real conversion");
|
||||
if (DstType->isSignedIntegerOrEnumerationType())
|
||||
if (isa<llvm::IntegerType>(DstElementTy)) {
|
||||
assert(SrcElementTy->isFloatingPointTy() && "Unknown real conversion");
|
||||
if (DstElementType->isSignedIntegerOrEnumerationType())
|
||||
return Builder.CreateFPToSI(Src, DstTy, "conv");
|
||||
return Builder.CreateFPToUI(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
if (DstTy->getTypeID() < SrcTy->getTypeID())
|
||||
if (DstElementTy->getTypeID() < SrcElementTy->getTypeID())
|
||||
return Builder.CreateFPTrunc(Src, DstTy, "conv");
|
||||
return Builder.CreateFPExt(Src, DstTy, "conv");
|
||||
}
|
||||
|
@ -1350,6 +1373,9 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
|||
return Builder.CreateVectorSplat(NumElements, Src, "splat");
|
||||
}
|
||||
|
||||
if (SrcType->isMatrixType() && DstType->isMatrixType())
|
||||
return EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
|
||||
|
||||
if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) {
|
||||
// Allow bitcast from vector to integer/fp of the same size.
|
||||
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
|
||||
|
@ -2238,6 +2264,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
|
|||
CGF.EmitIgnoredExpr(E);
|
||||
return nullptr;
|
||||
}
|
||||
case CK_MatrixCast: {
|
||||
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
|
||||
CE->getExprLoc());
|
||||
}
|
||||
case CK_VectorSplat: {
|
||||
llvm::Type *DstTy = ConvertType(DestTy);
|
||||
Value *Elt = Visit(const_cast<Expr*>(E));
|
||||
|
|
|
@ -1080,6 +1080,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
|
|||
case CK_BuiltinFnToFnPtr:
|
||||
case CK_ZeroToOCLOpaqueType:
|
||||
case CK_IntToOCLSampler:
|
||||
case CK_MatrixCast:
|
||||
return false;
|
||||
|
||||
case CK_BooleanToSignedIntegral:
|
||||
|
|
|
@ -2859,7 +2859,8 @@ void CastOperation::CheckCStyleCast() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!DestType->isScalarType() && !DestType->isVectorType()) {
|
||||
if (!DestType->isScalarType() && !DestType->isVectorType() &&
|
||||
!DestType->isMatrixType()) {
|
||||
const RecordType *DestRecordTy = DestType->getAs<RecordType>();
|
||||
|
||||
if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){
|
||||
|
@ -2910,10 +2911,11 @@ void CastOperation::CheckCStyleCast() {
|
|||
return;
|
||||
}
|
||||
|
||||
// The type we're casting to is known to be a scalar or vector.
|
||||
// The type we're casting to is known to be a scalar, a vector, or a matrix.
|
||||
|
||||
// Require the operand to be a scalar or vector.
|
||||
if (!SrcType->isScalarType() && !SrcType->isVectorType()) {
|
||||
// Require the operand to be a scalar, a vector, or a matrix.
|
||||
if (!SrcType->isScalarType() && !SrcType->isVectorType() &&
|
||||
!SrcType->isMatrixType()) {
|
||||
Self.Diag(SrcExpr.get()->getExprLoc(),
|
||||
diag::err_typecheck_expect_scalar_operand)
|
||||
<< SrcType << SrcExpr.get()->getSourceRange();
|
||||
|
@ -2926,6 +2928,12 @@ void CastOperation::CheckCStyleCast() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (DestType->getAs<MatrixType>() || SrcType->getAs<MatrixType>()) {
|
||||
if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind))
|
||||
SrcExpr = ExprError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) {
|
||||
if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
|
||||
(SrcType->isIntegerType() || SrcType->isFloatingType())) {
|
||||
|
|
|
@ -7345,6 +7345,19 @@ bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) {
|
|||
ValidScalableConversion(destTy, srcTy);
|
||||
}
|
||||
|
||||
/// Are the two types matrix types and do they have the same dimensions i.e.
|
||||
/// do they have the same number of rows and the same number of columns?
|
||||
bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) {
|
||||
if (!destTy->isMatrixType() || !srcTy->isMatrixType())
|
||||
return false;
|
||||
|
||||
const ConstantMatrixType *matSrcType = srcTy->getAs<ConstantMatrixType>();
|
||||
const ConstantMatrixType *matDestType = destTy->getAs<ConstantMatrixType>();
|
||||
|
||||
return matSrcType->getNumRows() == matDestType->getNumRows() &&
|
||||
matSrcType->getNumColumns() == matDestType->getNumColumns();
|
||||
}
|
||||
|
||||
/// Are the two types lax-compatible vector types? That is, given
|
||||
/// that one of them is a vector, do they have equal storage sizes,
|
||||
/// where the storage size is the number of elements times the element
|
||||
|
@ -7407,6 +7420,27 @@ bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
|
|||
return areLaxCompatibleVectorTypes(srcTy, destTy);
|
||||
}
|
||||
|
||||
bool Sema::CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy,
|
||||
CastKind &Kind) {
|
||||
if (SrcTy->isMatrixType() && DestTy->isMatrixType()) {
|
||||
if (!areMatrixTypesOfTheSameDimension(SrcTy, DestTy)) {
|
||||
return Diag(R.getBegin(), diag::err_invalid_conversion_between_matrixes)
|
||||
<< DestTy << SrcTy << R;
|
||||
}
|
||||
} else if (SrcTy->isMatrixType()) {
|
||||
return Diag(R.getBegin(),
|
||||
diag::err_invalid_conversion_between_matrix_and_type)
|
||||
<< SrcTy << DestTy << R;
|
||||
} else if (DestTy->isMatrixType()) {
|
||||
return Diag(R.getBegin(),
|
||||
diag::err_invalid_conversion_between_matrix_and_type)
|
||||
<< DestTy << SrcTy << R;
|
||||
}
|
||||
|
||||
Kind = CK_MatrixCast;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
|
||||
CastKind &Kind) {
|
||||
assert(VectorTy->isVectorType() && "Not a vector type!");
|
||||
|
|
|
@ -543,6 +543,10 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred);
|
||||
continue;
|
||||
}
|
||||
case CK_MatrixCast: {
|
||||
// TODO: Handle MatrixCast here.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
// RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
|
||||
|
||||
typedef char cx5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef int ix5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef short sx5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef float fx5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef double dx5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef unsigned short unsigned_short_int_5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef unsigned int unsigned_int_5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef unsigned long unsigned_long_int_5x5 __attribute__((matrix_type(5, 5)));
|
||||
|
||||
void cast_char_matrix_to_int(cx5x5 c, ix5x5 i) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_char_matrix_to_int(<25 x i8> %c, <25 x i32> %i)
|
||||
// CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1
|
||||
// CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32>
|
||||
// CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
i = (ix5x5)c;
|
||||
}
|
||||
|
||||
void cast_char_matrix_to_unsigned_int(cx5x5 c, unsigned_int_5x5 u) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_char_matrix_to_unsigned_int(<25 x i8> %c, <25 x i32> %u)
|
||||
// CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1
|
||||
// CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32>
|
||||
// CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
u = (unsigned_int_5x5)c;
|
||||
}
|
||||
|
||||
void cast_unsigned_long_int_matrix_to_short(unsigned_long_int_5x5 u, sx5x5 s) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_unsigned_long_int_matrix_to_short(<25 x i64> %u, <25 x i16> %s)
|
||||
// CHECK: [[U:%.*]] = load <25 x i64>, <25 x i64>* {{.*}}, align 8
|
||||
// CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> [[U]] to <25 x i16>
|
||||
// CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* {{.*}}, align 2
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
s = (sx5x5)u;
|
||||
}
|
||||
|
||||
void cast_int_matrix_to_short(ix5x5 i, sx5x5 s) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_int_matrix_to_short(<25 x i32> %i, <25 x i16> %s)
|
||||
// CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
|
||||
// CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i32> [[I]] to <25 x i16>
|
||||
// CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* {{.*}}, align 2
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
s = (sx5x5)i;
|
||||
}
|
||||
|
||||
void cast_int_matrix_to_float(ix5x5 i, fx5x5 f) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_int_matrix_to_float(<25 x i32> %i, <25 x float> %f)
|
||||
// CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
|
||||
// CHECK-NEXT: [[CONV:%.*]] = bitcast <25 x i32> [[I]] to <25 x float>
|
||||
// CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* {{.*}}, align 4
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
f = (fx5x5)i;
|
||||
}
|
||||
|
||||
void cast_double_matrix_to_int(dx5x5 d, ix5x5 i) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_double_matrix_to_int(<25 x double> %d, <25 x i32> %i)
|
||||
// CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
|
||||
// CHECK-NEXT: [[CONV:%.*]] = fptosi <25 x double> [[D]] to <25 x i32>
|
||||
// CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
i = (ix5x5)d;
|
||||
}
|
||||
|
||||
void cast_float_matrix_to_unsigned_short_int(fx5x5 f, unsigned_short_int_5x5 i) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_float_matrix_to_unsigned_short_int(<25 x float> %f, <25 x i16> %i)
|
||||
// CHECK: [[F:%.*]] = load <25 x float>, <25 x float>* {{.*}}, align 4
|
||||
// CHECK-NEXT: [[CONV:%.*]] = fptoui <25 x float> [[F]] to <25 x i16>
|
||||
// CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* %1, align 2
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
i = (unsigned_short_int_5x5)f;
|
||||
}
|
||||
|
||||
void cast_double_matrix_to_float(dx5x5 d, fx5x5 f) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_double_matrix_to_float(<25 x double> %d, <25 x float> %f)
|
||||
// CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
|
||||
// CHECK-NEXT: [[CONV:%.*]] = fptrunc <25 x double> [[D]] to <25 x float>
|
||||
// CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* {{.*}}, align 4
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
f = (fx5x5)d;
|
||||
}
|
||||
|
||||
void cast_unsigned_short_int_to_unsigned_int(unsigned_short_int_5x5 s, unsigned_int_5x5 i) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_unsigned_short_int_to_unsigned_int(<25 x i16> %s, <25 x i32> %i)
|
||||
// CHECK: [[S:%.*]] = load <25 x i16>, <25 x i16>* {{.*}}, align 2
|
||||
// CHECK-NEXT: [[CONV:%.*]] = zext <25 x i16> [[S]] to <25 x i32>
|
||||
// CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
i = (unsigned_int_5x5)s;
|
||||
}
|
||||
|
||||
void cast_unsigned_long_int_to_unsigned_short_int(unsigned_long_int_5x5 l, unsigned_short_int_5x5 s) {
|
||||
// CHECK-LABEL: define{{.*}} void @cast_unsigned_long_int_to_unsigned_short_int(<25 x i64> %l, <25 x i16> %s)
|
||||
// CHECK: [[L:%.*]] = load <25 x i64>, <25 x i64>* %0, align 8
|
||||
// CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> [[L]] to <25 x i16>
|
||||
// CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* {{.*}}, align 2
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
s = (unsigned_short_int_5x5)l;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// RUN: %clang_cc1 -fenable-matrix -fsyntax-only %s -verify
|
||||
|
||||
typedef char cx4x4 __attribute__((matrix_type(4, 4)));
|
||||
typedef int ix4x4 __attribute__((matrix_type(4, 4)));
|
||||
typedef short sx4x4 __attribute__((matrix_type(4, 4)));
|
||||
typedef int ix5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef float fx5x5 __attribute__((matrix_type(5, 5)));
|
||||
typedef int vec __attribute__((vector_size(4)));
|
||||
typedef struct test_struct {
|
||||
} test_struct;
|
||||
|
||||
void f1() {
|
||||
cx4x4 m1;
|
||||
ix4x4 m2;
|
||||
sx4x4 m3;
|
||||
ix5x5 m4;
|
||||
fx5x5 m5;
|
||||
int i;
|
||||
vec v;
|
||||
test_struct *s;
|
||||
|
||||
m2 = (ix4x4)m1;
|
||||
m3 = (sx4x4)m2;
|
||||
m4 = (ix5x5)m3; // expected-error {{conversion between matrix types 'ix5x5' (aka 'int __attribute__\
|
||||
((matrix_type(5, 5)))') and 'sx4x4' (aka 'short __attribute__((matrix_type(4, 4)))') of different size \
|
||||
is not allowed}}
|
||||
m5 = (ix5x5)m4; // expected-error {{assigning to 'fx5x5' (aka \
|
||||
'float __attribute__((matrix_type(5, 5)))') from incompatible type 'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))')}}
|
||||
i = (int)m4; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\
|
||||
((matrix_type(5, 5)))') and incompatible type 'int' is not allowed}}
|
||||
m4 = (ix5x5)i; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\
|
||||
((matrix_type(5, 5)))') and incompatible type 'int' is not allowed}}
|
||||
v = (vec)m4; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\
|
||||
((matrix_type(5, 5)))') and incompatible type 'vec' (vector of 1 'int' value) is not allowed}}
|
||||
m4 = (ix5x5)v; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\
|
||||
((matrix_type(5, 5)))') and incompatible type 'vec' (vector of 1 'int' value) is not allowed}}
|
||||
s = (test_struct *)m3; // expected-error {{conversion between matrix type 'sx4x4' (aka 'short \
|
||||
__attribute__((matrix_type(4, 4)))') and incompatible type 'test_struct *' (aka 'struct test_struct *') is not allowed}}
|
||||
m3 = (sx4x4)s; // expected-error {{conversion between matrix type 'sx4x4' (aka 'short \
|
||||
__attribute__((matrix_type(4, 4)))') and incompatible type 'test_struct *' (aka 'struct test_struct *') is not allowed}}
|
||||
|
||||
m4 = (ix5x5)m5;
|
||||
}
|
||||
|
||||
typedef float float2_8x8 __attribute__((matrix_type(8, 8)));
|
||||
typedef double double_10x10 __attribute__((matrix_type(10, 10)));
|
||||
typedef double double_8x8 __attribute__((matrix_type(8, 8)));
|
||||
typedef signed int signed_int_12x12 __attribute__((matrix_type(12, 12)));
|
||||
typedef unsigned int unsigned_int_12x12 __attribute__((matrix_type(12, 12)));
|
||||
typedef unsigned int unsigned_int_10x10 __attribute__((matrix_type(10, 10)));
|
||||
|
||||
void f2() {
|
||||
float2_8x8 m1;
|
||||
double_10x10 m2;
|
||||
double_8x8 m3;
|
||||
signed_int_12x12 m4;
|
||||
unsigned_int_12x12 m5;
|
||||
unsigned_int_10x10 m6;
|
||||
float f;
|
||||
|
||||
m2 = (double_10x10)m1; // expected-error {{conversion between matrix types 'double_10x10' \
|
||||
(aka 'double __attribute__((matrix_type(10, 10)))') and 'float2_8x8' (aka 'float __attribute__\
|
||||
((matrix_type(8, 8)))') of different size is not allowed}}
|
||||
m3 = (double_8x8)m1;
|
||||
|
||||
m5 = (unsigned_int_12x12)m4;
|
||||
m4 = (signed_int_12x12)m5;
|
||||
m6 = (unsigned_int_10x10)m4; // expected-error {{conversion between matrix types 'unsigned_int_10x10' \
|
||||
(aka 'unsigned int __attribute__((matrix_type(10, 10)))') and 'signed_int_12x12' (aka 'int __attribute__\
|
||||
((matrix_type(12, 12)))') of different size is not allowed}}
|
||||
f = (float)m4; // expected-error {{conversion between matrix type 'signed_int_12x12' \
|
||||
(aka 'int __attribute__((matrix_type(12, 12)))') and incompatible type 'float' is not allowed}}
|
||||
m4 = (signed_int_12x12)f; // expected-error {{conversion between matrix type 'signed_int_12x12' \
|
||||
(aka 'int __attribute__((matrix_type(12, 12)))') and incompatible type 'float' is not allowed}}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fenable-matrix -fsyntax-only -verify %s
|
||||
|
||||
template <typename X>
|
||||
|
||||
using matrix_4_4 = X __attribute__((matrix_type(4, 4)));
|
||||
|
||||
template <typename Y>
|
||||
|
||||
using matrix_5_5 = Y __attribute__((matrix_type(5, 5)));
|
||||
|
||||
typedef struct test_struct {
|
||||
} test_struct;
|
||||
|
||||
typedef int vec __attribute__((vector_size(4)));
|
||||
|
||||
void f1() {
|
||||
// TODO: Update this test once the support of C-style casts for C++ is implemented.
|
||||
matrix_4_4<char> m1;
|
||||
matrix_4_4<int> m2;
|
||||
matrix_4_4<short> m3;
|
||||
matrix_5_5<int> m4;
|
||||
int i;
|
||||
vec v;
|
||||
test_struct *s;
|
||||
|
||||
(matrix_4_4<int>)m1; // expected-error {{C-style cast from 'matrix_4_4<char>' (aka 'char __attribute__((matrix_type(4, \
|
||||
4)))') to 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') is not allowed}}
|
||||
(matrix_4_4<short>)m2; // expected-error {{C-style cast from 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, \
|
||||
4)))') to 'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, 4)))') is not allowed}}
|
||||
(matrix_5_5<int>)m3; // expected-error {{C-style cast from 'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, \
|
||||
4)))') to 'matrix_5_5<int>' (aka 'int __attribute__((matrix_type(5, 5)))') is not allowed}}
|
||||
|
||||
(int)m3; // expected-error {{C-style cast from 'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, \
|
||||
4)))') to 'int'}}
|
||||
(matrix_4_4<int>)i; // expected-error {{C-style cast from 'int' to 'matrix_4_4<int>' (aka 'int __attribute__((\
|
||||
matrix_type(4, 4)))') is not allowed}}
|
||||
|
||||
(vec) m2; // expected-error {{C-style cast from 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') \
|
||||
to 'vec' (vector of 1 'int' value) is not allowed}}
|
||||
(matrix_4_4<char>)v; // expected-error {{C-style cast from 'vec' (vector of 1 'int' value) to 'matrix_4_4<char>' \
|
||||
(aka 'char __attribute__((matrix_type(4, 4)))') is not allowed}}
|
||||
|
||||
(test_struct *)m1; // expected-error {{cannot cast from type 'matrix_4_4<char>' (aka 'char __attribute__\
|
||||
((matrix_type(4, 4)))') to pointer type 'test_struct *}}'
|
||||
(matrix_5_5<float>)s; // expected-error {{C-style cast from 'test_struct *' to 'matrix_5_5<float>' (aka 'float __attribute__\
|
||||
((matrix_type(5, 5)))') is not allowed}}'
|
||||
}
|
||||
|
||||
void f2() {
|
||||
// TODO: Update this test once the support of C-style casts for C++ is implemented.
|
||||
matrix_4_4<float> m1;
|
||||
matrix_5_5<double> m2;
|
||||
matrix_5_5<signed int> m3;
|
||||
matrix_4_4<unsigned int> m4;
|
||||
float f;
|
||||
|
||||
(matrix_4_4<double>)m1; // expected-error {{C-style cast from 'matrix_4_4<float>' (aka 'float __attribute__\
|
||||
((matrix_type(4, 4)))') to 'matrix_4_4<double>' (aka 'double __attribute__((matrix_type(4, 4)))') is not allowed}}
|
||||
(matrix_5_5<float>)m2; // expected-error {{C-style cast from 'matrix_5_5<double>' (aka 'double __attribute__\
|
||||
((matrix_type(5, 5)))') to 'matrix_5_5<float>' (aka 'float __attribute__((matrix_type(5, 5)))') is not allowed}}
|
||||
(matrix_5_5<unsigned int>)m3; // expected-error {{C-style cast from 'matrix_5_5<int>' (aka 'int __attribute__\
|
||||
((matrix_type(5, 5)))') to 'matrix_5_5<unsigned int>' (aka 'unsigned int __attribute__((matrix_type(5, 5)))') \
|
||||
is not allowed}}
|
||||
(matrix_4_4<int>)m4; // expected-error {{C-style cast from 'matrix_4_4<unsigned int>' (aka 'unsigned int \
|
||||
__attribute__((matrix_type(4, 4)))') to 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') is not \
|
||||
allowed}}
|
||||
}
|
Loading…
Reference in New Issue