SaurabhJha created this revision.
SaurabhJha added a reviewer: fhahn.
Herald added a subscriber: tschuett.
SaurabhJha requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

[Matrix] Implement explicit type conversions for MatrixType.
Bugzilla ticket is here: https://bugs.llvm.org/show_bug.cgi?id=47141


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99037

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/matrix-cast.c
  clang/test/SemaCXX/matrix-casts.cpp

Index: clang/test/SemaCXX/matrix-casts.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/matrix-casts.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++11 -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;
+
+  (void)reinterpret_cast<ix4x4>(m1);
+  (void)(ix4x4) m1;
+  (void)reinterpret_cast<sx4x4>(m2);
+  (void)(sx4x4) m1;
+  (void)reinterpret_cast<ix5x5>(m3); // expected-error {{reinterpret_cast from matrix 'sx4x4' (aka 'short __attribute__((matrix_type(4, 4)))') to matrix 'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))') of different size}}
+  (void)(ix5x5) m3;                  // expected-error {{-style cast from matrix 'sx4x4' (aka 'short __attribute__((matrix_type(4, 4)))') to matrix 'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))') of different size}}
+}
+
+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_8x8 m2;
+  signed_int_12x12 m3;
+  unsigned_int_12x12 m4;
+
+  (void)reinterpret_cast<double_10x10>(m1); // expected-error {{reinterpret_cast from matrix 'float2_8x8' (aka 'float __attribute__((matrix_type(8, 8)))') to matrix 'double_10x10' (aka 'double __attribute__((matrix_type(10, 10)))') of different size}}
+  (void)(double_10x10) m1;                  // expected-error {{C-style cast from matrix 'float2_8x8' (aka 'float __attribute__((matrix_type(8, 8)))') to matrix 'double_10x10' (aka 'double __attribute__((matrix_type(10, 10)))') of different size}}
+  (void)reinterpret_cast<float2_8x8>(m2);
+  (void)(float2_8x8) m2;
+  (void)reinterpret_cast<unsigned_int_12x12>(m3);
+  (void)(unsigned_int_12x12) m3;
+  (void)reinterpret_cast<signed_int_12x12>(m4);
+  (void)(signed_int_12x12) m4;
+  (void)reinterpret_cast<unsigned_int_10x10>(m3); // expected-error {{reinterpret_cast from matrix 'signed_int_12x12' (aka 'int __attribute__((matrix_type(12, 12)))') to matrix 'unsigned_int_10x10' (aka 'unsigned int __attribute__((matrix_type(10, 10)))') of different size}}
+  (void)(unsigned_int_10x10) m3;                  // expected-error {{C-style cast from matrix 'signed_int_12x12' (aka 'int __attribute__((matrix_type(12, 12)))') to matrix 'unsigned_int_10x10' (aka 'unsigned int __attribute__((matrix_type(10, 10)))') of different size}}
+}
\ No newline at end of file
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/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7306,6 +7306,32 @@
          ValidScalableConversion(destTy, srcTy);
 }
 
+/// Are the two types compatible matrix types?  That is, are they both matrices
+/// and do they both have the same dimensions i.e. do they have the same number
+/// of rows and the same number of columns?
+///
+/// This will also return false if elements types of either of the matrices
+/// is not a scalar type.
+bool Sema::areCompatibleMatrixTypes(QualType srcTy, QualType destTy) {
+  assert(destTy->isMatrixType() && srcTy->isMatrixType());
+
+  const ConstantMatrixType *matSrcType = srcTy->getAs<ConstantMatrixType>();
+  const ConstantMatrixType *matDestType = destTy->getAs<ConstantMatrixType>();
+
+  if (matSrcType->getNumRows() != matDestType->getNumRows() ||
+      matSrcType->getNumColumns() != matDestType->getNumColumns()) {
+    return false;
+  }
+
+  QualType elemSrcType = matSrcType->getElementType();
+  QualType elemDestType = matDestType->getElementType();
+
+  if (!elemSrcType->isScalarType() || !elemDestType->isScalarType()) {
+    return false;
+  }
+  return true;
+}
+
 /// 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
@@ -7368,6 +7394,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 (!areCompatibleMatrixTypes(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_BitCast;
+  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
@@ -2214,6 +2214,27 @@
     return TC_Success;
   }
 
+  // Allow reinterpret_casts between matrices of same dimensions.
+  bool destIsMatrix = DestType->isMatrixType();
+  bool srcIsMatrix = SrcType->isMatrixType();
+  if (srcIsMatrix || destIsMatrix) {
+    if (srcIsMatrix && destIsMatrix) {
+      if (Self.areCompatibleMatrixTypes(SrcType, DestType)) {
+        Kind = CK_BitCast;
+        return TC_Success;
+      } else {
+        msg = diag::err_bad_cxx_cast_matrix_to_matrix_different_size;
+        return TC_Failed;
+      }
+    } else if (!destIsMatrix) {
+      msg = diag::err_bad_cxx_cast_matrix_to_scalar;
+      return TC_Failed;
+    } else if (!srcIsMatrix) {
+      msg = diag::err_bad_cxx_cast_scalar_to_matrix;
+      return TC_Failed;
+    }
+  }
+
   // Allow reinterpret_casts between vectors of the same size and
   // between vectors and integers of the same size.
   bool destIsVector = DestType->isVectorType();
@@ -2765,7 +2786,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)){
@@ -2816,10 +2838,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()) {
+  // 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();
@@ -2832,6 +2855,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/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -11603,6 +11603,8 @@
 
   bool isValidSveBitcast(QualType srcType, QualType destType);
 
+  bool areCompatibleMatrixTypes(QualType srcType, QualType destType);
+
   bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
   bool isLaxVectorConversion(QualType srcType, QualType destType);
 
@@ -11661,6 +11663,13 @@
   ExprResult checkUnknownAnyArg(SourceLocation callLoc,
                                 Expr *result, QualType &paramType);
 
+  // CheckMatrixCast - check type constraints for matrices.
+  // We allow casting in between matrices of the same dimensions i.e. when
+  // they have the same number of rows and columns.
+  // 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
@@ -7137,6 +7137,15 @@
   InGroup<CXX98CompatPedantic>, DefaultIgnore;
 def err_bad_reinterpret_cast_small_int : Error<
   "cast from pointer to smaller type %2 loses information">;
+def err_bad_cxx_cast_matrix_to_matrix_different_size : Error<
+  "%select{||reinterpret_cast||C-style cast||}0 from matrix %1 "
+  "to matrix %2 of different size">;
+def err_bad_cxx_cast_scalar_to_matrix : Error<
+  "%select{||reinterpret_cast||C-style cast||}0 from scalar %1 "
+  "to matrix %2">;
+def err_bad_cxx_cast_matrix_to_scalar : Error<
+  "%select{||reinterpret_cast||C-style cast||}0 from matrix %1 "
+  "to scalar %2">;
 def err_bad_cxx_cast_vector_to_scalar_different_size : Error<
   "%select{||reinterpret_cast||C-style cast||}0 from vector %1 "
   "to scalar %2 of different size">;
@@ -8568,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">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to