diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1205,10 +1205,6 @@ 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(SrcTy)->getElementType(); DstElementTy = cast(DstTy)->getElementType(); SrcElementType = SrcType->castAs()->getElementType(); @@ -1228,8 +1224,15 @@ InputSigned = true; } - if (isa(DstElementTy)) - return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); + bool OutputSigned = DstElementType->isSignedIntegerOrEnumerationType(); + if (DstElementType->isBooleanType() && Opts.TreatBooleanAsSigned) { + OutputSigned = true; + } + + if (isa(DstElementTy)) { + return Builder.CreateIntCast(Src, DstTy, InputSigned && OutputSigned, + "conv"); + } if (InputSigned) return Builder.CreateSIToFP(Src, DstTy, "conv"); return Builder.CreateUIToFP(Src, DstTy, "conv"); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2648,6 +2648,13 @@ return; } + if (DestType->getAs() || + SrcExpr.get()->getType()->getAs()) { + if (Self.CheckMatrixCast(OpRange, DestType, SrcExpr.get()->getType(), Kind)) + SrcExpr = ExprError(); + return; + } + // AltiVec vector initialization with a single literal. if (const VectorType *vecTy = DestType->getAs()) if (vecTy->getVectorKind() == VectorType::AltiVecVector diff --git a/clang/test/CodeGen/matrix-cast.c b/clang/test/CodeGen/matrix-cast.c --- a/clang/test/CodeGen/matrix-cast.c +++ b/clang/test/CodeGen/matrix-cast.c @@ -22,7 +22,7 @@ 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: [[CONV:%.*]] = zext <25 x i8> [[C]] to <25 x i32> // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 // CHECK-NEXT: ret void @@ -52,7 +52,7 @@ 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: [[CONV:%.*]] = sitofp <25 x i32> [[I]] to <25 x float> // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* {{.*}}, align 4 // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenCXX/matrix-casts.cpp b/clang/test/CodeGenCXX/matrix-casts.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/matrix-casts.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++11 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +template + +using matrix_4_4 = X __attribute__((matrix_type(4, 4))); + +template + +using matrix_5_5 = Y __attribute__((matrix_type(5, 5))); + +// CHECK-LABEL: define{{.*}} void @_Z19CastCharMatrixToIntv +void CastCharMatrixToInt() { + // 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: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* [[CONV1]], align 4 + + matrix_5_5 c; + matrix_5_5 i; + i = (matrix_5_5)c; +} + +// CHECK-LABEL: define{{.*}} void @_Z27CastCharMatrixToUnsignedIntv +void CastCharMatrixToUnsignedInt() { + // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 + // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i8> [[C]] to <25 x i32> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 c; + matrix_5_5 u; + u = (matrix_5_5)c; +} + +// CHECK-LABEL: define{{.*}} void @_Z32CastUnsignedLongIntMatrixToShortv +void CastUnsignedLongIntMatrixToShort() { + // CHECK: [[U:%.*]] = load <25 x i64>, <25 x i64>* {{.*}}, align 8 + // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> {{.*}} to <25 x i16> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 u; + matrix_5_5 s; + s = (matrix_5_5)u; +} + +// CHECK-LABEL: define{{.*}} void @_Z20CastIntMatrixToShortv() +void CastIntMatrixToShort() { + // 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: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 i; + matrix_5_5 s; + s = (matrix_5_5)i; +} + +// CHECK-LABEL: define{{.*}} void @_Z20CastIntMatrixToFloatv() +void CastIntMatrixToFloat() { + // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV]] = sitofp <25 x i32> {{.*}} to <25 x float> + // CHECK-NEXT: [[CONV1]] = bitcast [25 x float]* {{.*}} to <25 x float>* + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 i; + matrix_5_5 f; + f = (matrix_5_5)i; +} + +// CHECK-LABEL: define{{.*}} void @_Z21CastDoubleMatrixToIntv() +void CastDoubleMatrixToInt() { + // 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: [[CONV1:%.*]] = bitcast [25 x i32]* %i to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + matrix_5_5 d; + matrix_5_5 i; + i = (matrix_5_5)d; +} + +// CHECK-LABEL: define{{.*}} void @_Z33CastFloatMatrixToUnsignedShortIntv() +void CastFloatMatrixToUnsignedShortInt() { + // 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: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 f; + matrix_5_5 i; + i = (matrix_5_5)f; +} + +// CHECK-LABEL: define{{.*}} void @_Z23CastDoubleMatrixToFloatv() +void CastDoubleMatrixToFloat() { + // 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: [[CONV1:%.*]] = bitcast [25 x float]* {{.*}} to <25 x float>* + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 d; + matrix_5_5 f; + f = (matrix_5_5)d; +} + +// CHECK-LABEL: define{{.*}} void @_Z33CastUnsignedShortIntToUnsignedIntv() +void CastUnsignedShortIntToUnsignedInt() { + // 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: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 s; + matrix_5_5 i; + i = (matrix_5_5)s; +} + +void CastUnsignedLongIntToUnsignedShortInt() { + // 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: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 l; + matrix_5_5 s; + s = (matrix_5_5)l; +} \ No newline at end of file diff --git a/clang/test/SemaCXX/matrix-casts.cpp b/clang/test/SemaCXX/matrix-casts.cpp --- a/clang/test/SemaCXX/matrix-casts.cpp +++ b/clang/test/SemaCXX/matrix-casts.cpp @@ -14,7 +14,6 @@ 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 m1; matrix_4_4 m2; matrix_4_4 m3; @@ -23,45 +22,46 @@ vec v; test_struct *s; - (matrix_4_4)m1; // expected-error {{C-style cast from 'matrix_4_4' (aka 'char __attribute__((matrix_type(4, \ -4)))') to 'matrix_4_4' (aka 'int __attribute__((matrix_type(4, 4)))') is not allowed}} - (matrix_4_4)m2; // expected-error {{C-style cast from 'matrix_4_4' (aka 'int __attribute__((matrix_type(4, \ -4)))') to 'matrix_4_4' (aka 'short __attribute__((matrix_type(4, 4)))') is not allowed}} - (matrix_5_5)m3; // expected-error {{C-style cast from 'matrix_4_4' (aka 'short __attribute__((matrix_type(4, \ -4)))') to 'matrix_5_5' (aka 'int __attribute__((matrix_type(5, 5)))') is not allowed}} + m2 = (matrix_4_4)m1; + m2 = m1; // expected-error {{assigning to 'matrix_4_4' from incompatible type 'matrix_4_4'}} + m3 = (matrix_4_4)m2; + (matrix_5_5)m3; // expected-error {{conversion between matrix types 'matrix_5_5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and 'matrix_4_4' (aka 'short __attribute__((matrix_type(4, 4)))') of different size is not\ + allowed}} - (int)m3; // expected-error {{C-style cast from 'matrix_4_4' (aka 'short __attribute__((matrix_type(4, \ -4)))') to 'int'}} - (matrix_4_4)i; // expected-error {{C-style cast from 'int' to 'matrix_4_4' (aka 'int __attribute__((\ -matrix_type(4, 4)))') is not allowed}} + (int)m3; // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'short __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}} + (matrix_4_4)i; // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'int __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}} - (vec) m2; // expected-error {{C-style cast from 'matrix_4_4' (aka 'int __attribute__((matrix_type(4, 4)))') \ -to 'vec' (vector of 1 'int' value) is not allowed}} - (matrix_4_4)v; // expected-error {{C-style cast from 'vec' (vector of 1 'int' value) to 'matrix_4_4' \ -(aka 'char __attribute__((matrix_type(4, 4)))') is not allowed}} + (vec) m2; // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'int __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) is not allowed}} + (matrix_4_4)v; // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'char __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) is not allowed}} - (test_struct *)m1; // expected-error {{cannot cast from type 'matrix_4_4' (aka 'char __attribute__\ -((matrix_type(4, 4)))') to pointer type 'test_struct *}}' - (matrix_5_5)s; // expected-error {{C-style cast from 'test_struct *' to 'matrix_5_5' (aka 'float __attribute__\ -((matrix_type(5, 5)))') is not allowed}}' + (test_struct *)m1; // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'char __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'test_struct *' is not allowed}}' + (matrix_5_5)s; // expected-error {{conversion between matrix type 'matrix_5_5' (aka 'float __attribute__\ +((matrix_type(5, 5)))') and incompatible type 'test_struct *' is not allowed}}' } void f2() { - // TODO: Update this test once the support of C-style casts for C++ is implemented. matrix_4_4 m1; - matrix_5_5 m2; - matrix_5_5 m3; - matrix_4_4 m4; + matrix_4_4 m2; + matrix_5_5 m3; + matrix_5_5 m4; + matrix_4_4 m5; + matrix_5_5 m6; float f; - (matrix_4_4)m1; // expected-error {{C-style cast from 'matrix_4_4' (aka 'float __attribute__\ -((matrix_type(4, 4)))') to 'matrix_4_4' (aka 'double __attribute__((matrix_type(4, 4)))') is not allowed}} - (matrix_5_5)m2; // expected-error {{C-style cast from 'matrix_5_5' (aka 'double __attribute__\ -((matrix_type(5, 5)))') to 'matrix_5_5' (aka 'float __attribute__((matrix_type(5, 5)))') is not allowed}} - (matrix_5_5)m3; // expected-error {{C-style cast from 'matrix_5_5' (aka 'int __attribute__\ -((matrix_type(5, 5)))') to 'matrix_5_5' (aka 'unsigned int __attribute__((matrix_type(5, 5)))') \ -is not allowed}} - (matrix_4_4)m4; // expected-error {{C-style cast from 'matrix_4_4' (aka 'unsigned int \ -__attribute__((matrix_type(4, 4)))') to 'matrix_4_4' (aka 'int __attribute__((matrix_type(4, 4)))') is not \ -allowed}} + m2 = (matrix_4_4)m1; + (matrix_5_5)m1; // expected-error {{conversion between matrix types 'matrix_5_5' (aka 'double __\ +attribute__((matrix_type(5, 5)))') and 'matrix_4_4' (aka 'float __attribute__((matrix_type(4, 4)))') of different\ + size is not allowed}} + m4 = (matrix_5_5)m3; + m5 = (matrix_5_5)m4; // expected-error {{assigning to 'matrix_4_4' (aka 'unsigned int \ +__attribute__((matrix_type(4, 4)))') from incompatible type 'matrix_5_5' (aka 'unsigned int __attribute__\ +((matrix_type(5, 5)))')}} + m6 = (matrix_5_5)m4; + m4 = (matrix_5_5)m6; }