SaurabhJha updated this revision to Diff 334942.
SaurabhJha added a comment.
Updating D99037 <https://reviews.llvm.org/D99037>: [Matrix] Implement explicit
type conversions for matrix types
Latest update includes code gen for c style casts along with some lit tests
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D99037/new/
https://reviews.llvm.org/D99037
Files:
clang/include/clang/AST/OperationKinds.def
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprAgg.cpp
clang/lib/CodeGen/CGExprComplex.cpp
clang/lib/CodeGen/CGExprConstant.cpp
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/Edit/RewriteObjCFoundationAPI.cpp
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
clang/test/CodeGen/matrix-cast.c
clang/test/Sema/matrix-cast.c
Index: clang/test/Sema/matrix-cast.c
===================================================================
--- /dev/null
+++ clang/test/Sema/matrix-cast.c
@@ -0,0 +1,51 @@
+// 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)));
+
+void f1() {
+ cx4x4 m1;
+ ix4x4 m2;
+ sx4x4 m3;
+ ix5x5 m4;
+ fx5x5 m5;
+
+ m2 = (ix4x4)m1;
+ m3 = (sx4x4)m2;
+ m4 = (ix5x5)m3; // expected-error {{invalid conversion between matrix type \
+'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))') and 'sx4x4' \
+(aka 'short __attribute__((matrix_type(4, 4)))') of different size}}
+ 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)))')}}
+ 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;
+
+ m2 = (double_10x10)m1; // expected-error {{invalid conversion between matrix type \
+'double_10x10' (aka 'double __attribute__((matrix_type(10, 10)))') and 'float2_8x8' \
+(aka 'float __attribute__((matrix_type(8, 8)))') of different size}}
+ m3 = (double_8x8)m1;
+
+ m5 = (unsigned_int_12x12)m4;
+ m4 = (signed_int_12x12)m5;
+ m6 = (unsigned_int_10x10)m4; // expected-error {{invalid conversion between matrix type \
+'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}}
+}
\ No newline at end of file
Index: clang/test/CodeGen/matrix-cast.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/matrix-cast.c
@@ -0,0 +1,74 @@
+// 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 int ix5x5 __attribute__((matrix_type(5, 5)));
+typedef float fx5x5 __attribute__((matrix_type(5, 5)));
+typedef double dx5x5 __attribute__((matrix_type(5, 5)));
+typedef signed int signed_int_5x5 __attribute__((matrix_type(5, 5)));
+typedef unsigned int unsigned_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: [[C1:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1
+ // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i8> [[C1]] 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_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: [[I1:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i32> [[I1]] 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: [[I1:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[CONV:%.*]] = bitcast <25 x i32> [[I1]] 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_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: [[D1:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
+ // CHECK-NEXT: [[CONV:%.*]] = fptrunc <25 x double> [[D1]] 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_int_to_signed_int(unsigned_int_5x5 u, signed_int_5x5 s) {
+ // CHECK-LABEL: define{{.*}} void @cast_unsigned_int_to_signed_int(<25 x i32> %u, <25 x i32> %s)
+ // CHECK: [[U:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[U1:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: store <25 x i32> [[U1]], <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: ret void
+
+ s = (signed_int_5x5)u;
+}
+
+void cast_signed_int_to_unsigned_int(signed_int_5x5 s, unsigned_int_5x5 u) {
+ // CHECK-LABEL: define{{.*}} void @cast_signed_int_to_unsigned_int(<25 x i32> %s, <25 x i32> %u)
+ // CHECK: [[S:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[S1:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: store <25 x i32> [[S1]], <25 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: ret void
+
+ u = (unsigned_int_5x5)s;
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -543,6 +543,9 @@
state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred);
continue;
}
+ case CK_MatrixCast: {
+ // TODO: Handle MatrixCast here.
+ }
}
}
}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7312,6 +7312,19 @@
ValidScalableConversion(destTy, srcTy);
}
+/// Are the two types matrix types and do they have the same dimensions i.e.
+/// and do they both 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) {
+ assert(destTy->isMatrixType() && srcTy->isMatrixType());
+
+ 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
@@ -7374,6 +7387,25 @@
return areLaxCompatibleVectorTypes(srcTy, destTy);
}
+bool Sema::CheckMatrixCast(SourceRange R, QualType DestMatrixTy, QualType SrcTy,
+ CastKind &Kind) {
+ assert(DestMatrixTy->isMatrixType() && "Not a matrix type!");
+
+ if (SrcTy->isMatrixType()) {
+ if (!areMatrixTypesOfTheSameDimension(SrcTy, DestMatrixTy)) {
+ return Diag(R.getBegin(), diag::err_invalid_conversion_between_matrices)
+ << DestMatrixTy << SrcTy << R;
+ }
+ } else {
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_matrix_and_scalar)
+ << DestMatrixTy << 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!");
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2859,7 +2859,8 @@
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 @@
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()) {
+ 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,13 @@
return;
}
+ if (const MatrixType *DestMatTy = DestType->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())) {
Index: clang/lib/Edit/RewriteObjCFoundationAPI.cpp
===================================================================
--- clang/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ clang/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1080,6 +1080,7 @@
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLOpaqueType:
case CK_IntToOCLSampler:
+ case CK_MatrixCast:
return false;
case CK_BooleanToSignedIntegral:
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -41,6 +41,7 @@
#include "llvm/IR/MatrixBuilder.h"
#include "llvm/IR/Module.h"
#include <cstdarg>
+#include <iostream>
using namespace clang;
using namespace CodeGen;
@@ -2230,6 +2231,14 @@
CGF.EmitIgnoredExpr(E);
return nullptr;
}
+ case CK_MatrixCast: {
+ Value *Src = Visit(const_cast<Expr*>(E));
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = ConvertType(DestTy);
+ bool src_ty_is_matrix = SrcTy->isVectorTy();
+ bool dst_ty_is_matrix = DstTy->isVectorTy();
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc());
+ }
case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy);
Value *Elt = Visit(const_cast<Expr*>(E));
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1170,6 +1170,7 @@
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
case CK_ZeroToOCLOpaqueType:
+ case CK_MatrixCast:
return nullptr;
}
llvm_unreachable("Invalid CastKind");
Index: clang/lib/CodeGen/CGExprComplex.cpp
===================================================================
--- clang/lib/CodeGen/CGExprComplex.cpp
+++ clang/lib/CodeGen/CGExprComplex.cpp
@@ -533,6 +533,7 @@
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
Index: clang/lib/CodeGen/CGExprAgg.cpp
===================================================================
--- clang/lib/CodeGen/CGExprAgg.cpp
+++ clang/lib/CodeGen/CGExprAgg.cpp
@@ -901,6 +901,7 @@
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLOpaqueType:
+ case CK_MatrixCast:
case CK_IntToOCLSampler:
case CK_FloatingToFixedPoint:
@@ -1422,6 +1423,7 @@
case CK_PointerToIntegral:
// Language extensions.
case CK_VectorSplat:
+ case CK_MatrixCast:
case CK_NonAtomicToAtomic:
case CK_AtomicToNonAtomic:
return true;
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -4645,6 +4645,7 @@
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
case CK_Dependent:
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -13183,6 +13183,7 @@
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 @@
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -1708,6 +1708,7 @@
case CK_FixedPointCast:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -11648,6 +11648,8 @@
bool isValidSveBitcast(QualType srcType, QualType destType);
+ bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
+
bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
bool isLaxVectorConversion(QualType srcType, QualType destType);
@@ -11706,6 +11708,13 @@
ExprResult checkUnknownAnyArg(SourceLocation callLoc,
Expr *result, QualType ¶mType);
+ // CheckMatrixCast - Check type constraints for matrices.
+ // We allow casting between matrices 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 MatrixTy, QualType Tr,
+ 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.
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8577,6 +8577,13 @@
let CategoryName = "Semantic Issue" in {
+def err_invalid_conversion_between_matrices : Error<
+ "invalid conversion between matrix type%diff{ $ and $|}0,1 of different "
+ "size">;
+
+def err_invalid_conversion_between_matrix_and_scalar : Error<
+ "invalid conversion between matrix type %0 and scalar type%1">;
+
def err_invalid_conversion_between_vectors : Error<
"invalid conversion between vector type%diff{ $ and $|}0,1 of different "
"size">;
Index: clang/include/clang/AST/OperationKinds.def
===================================================================
--- clang/include/clang/AST/OperationKinds.def
+++ clang/include/clang/AST/OperationKinds.def
@@ -181,6 +181,9 @@
/// (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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits