[clang] 3323a62 - [Matrix] Add __builtin_matrix_transpose to Clang.
Florian Hahn via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 9 02:15:38 PDT 2020
Author: Florian Hahn
Date: 2020-06-09T10:14:37+01:00
New Revision: 3323a628ec821b8b75d3b60bf1510931f97d3883
URL: https://github.com/llvm/llvm-project/commit/3323a628ec821b8b75d3b60bf1510931f97d3883
DIFF: https://github.com/llvm/llvm-project/commit/3323a628ec821b8b75d3b60bf1510931f97d3883.diff
LOG: [Matrix] Add __builtin_matrix_transpose to Clang.
This patch add __builtin_matrix_transpose to Clang, as described in
clang/docs/MatrixTypes.rst.
Reviewers: rjmccall, jfb, rsmith, Bigcheese
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D72778
Added:
clang/test/CodeGen/matrix-type-builtins.c
clang/test/CodeGenCXX/matrix-type-builtins.cpp
clang/test/CodeGenObjC/matrix-type-builtins.m
clang/test/Sema/matrix-type-builtins.c
clang/test/SemaCXX/matrix-type-builtins.cpp
clang/test/SemaObjC/matrix-type-builtins.m
Modified:
clang/include/clang/Basic/Builtins.def
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/Sema/SemaChecking.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 4c43d63ffec4..4deca85bb867 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -577,6 +577,8 @@ BUILTIN(__builtin_alloca, "v*z" , "Fn")
BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
+BUILTIN(__builtin_matrix_transpose, "v.", "nFt")
+
// "Overloaded" Atomic operator builtins. These are overloaded to support data
// types of i8, i16, i32, i64, and i128. The front-end sees calls to the
// non-suffixed version of these (which has a bogus type) and transforms them to
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cce6dcc54c2f..84bcf66a148e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10779,6 +10779,9 @@ def warn_import_on_definition : Warning<
"import %select{module|name}0 cannot be applied to a function with a definition">,
InGroup<IgnoredAttributes>;
+def err_builtin_matrix_arg: Error<
+ "%select{first|second}0 argument must be a matrix">;
+
def err_preserve_field_info_not_field : Error<
"__builtin_preserve_field_info argument %0 not a field access">;
def err_preserve_field_info_not_const: Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 8df78a5a7aca..33be6c68b11a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12120,6 +12120,11 @@ class Sema final {
int ArgNum, unsigned ExpectedFieldNum,
bool AllowName);
bool SemaBuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ // Matrix builtin handling.
+ ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
+ ExprResult CallResult);
+
public:
enum FormatStringType {
FST_Scanf,
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c580720379b5..bfc78ce94892 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -44,6 +44,7 @@
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/IntrinsicsX86.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/MatrixBuilder.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
@@ -2375,6 +2376,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
}
+ case Builtin::BI__builtin_matrix_transpose: {
+ const auto *MatrixTy = E->getArg(0)->getType()->getAs<ConstantMatrixType>();
+ Value *MatValue = EmitScalarExpr(E->getArg(0));
+ MatrixBuilder<CGBuilderTy> MB(Builder);
+ Value *Result = MB.CreateMatrixTranspose(MatValue, MatrixTy->getNumRows(),
+ MatrixTy->getNumColumns());
+ return RValue::get(Result);
+ }
+
case Builtin::BIfinite:
case Builtin::BI__finite:
case Builtin::BIfinitef:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 86b18e26eb8d..0e451d6e5867 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1896,7 +1896,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
return ExprError();
break;
case Builtin::BI__builtin_frame_address:
- case Builtin::BI__builtin_return_address:
+ case Builtin::BI__builtin_return_address: {
if (SemaBuiltinConstantArgRange(TheCall, 0, 0, 0xFFFF))
return ExprError();
@@ -1913,6 +1913,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
break;
}
+ case Builtin::BI__builtin_matrix_transpose:
+ return SemaBuiltinMatrixTranspose(TheCall, TheCallResult);
+ }
+
// Since the target specific builtins for each arch overlap, only check those
// of the arch we are compiling for.
if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) {
@@ -15033,3 +15037,32 @@ void Sema::CheckAddressOfPackedMember(Expr *rhs) {
rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1,
_2, _3, _4));
}
+
+ExprResult Sema::SemaBuiltinMatrixTranspose(CallExpr *TheCall,
+ ExprResult CallResult) {
+ if (checkArgCount(*this, TheCall, 1))
+ return ExprError();
+
+ ExprResult MatrixArg = DefaultLvalueConversion(TheCall->getArg(0));
+ if (MatrixArg.isInvalid())
+ return MatrixArg;
+ Expr *Matrix = MatrixArg.get();
+
+ auto *MType = Matrix->getType()->getAs<ConstantMatrixType>();
+ if (!MType) {
+ Diag(Matrix->getBeginLoc(), diag::err_builtin_matrix_arg) << 0;
+ return ExprError();
+ }
+
+ // Create returned matrix type by swapping rows and columns of the argument
+ // matrix type.
+ QualType ResultType = Context.getConstantMatrixType(
+ MType->getElementType(), MType->getNumColumns(), MType->getNumRows());
+
+ // Change the return type to the type of the returned matrix.
+ TheCall->setType(ResultType);
+
+ // Update call argument to use the possibly converted matrix argument.
+ TheCall->setArg(0, Matrix);
+ return CallResult;
+}
diff --git a/clang/test/CodeGen/matrix-type-builtins.c b/clang/test/CodeGen/matrix-type-builtins.c
new file mode 100644
index 000000000000..5bd7239333ce
--- /dev/null
+++ b/clang/test/CodeGen/matrix-type-builtins.c
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+// Tests for the matrix type builtins.
+
+typedef double dx5x5_t __attribute__((matrix_type(5, 5)));
+typedef float fx2x3_t __attribute__((matrix_type(2, 3)));
+typedef float fx3x2_t __attribute__((matrix_type(3, 2)));
+typedef int ix20x4_t __attribute__((matrix_type(20, 4)));
+typedef int ix4x20_t __attribute__((matrix_type(4, 20)));
+typedef unsigned ux1x6_t __attribute__((matrix_type(1, 6)));
+typedef unsigned ux6x1_t __attribute__((matrix_type(6, 1)));
+
+void transpose_double_5x5(dx5x5_t *a) {
+ // CHECK-LABEL: define void @transpose_double_5x5(
+ // CHECK: [[A:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
+ // CHECK-NEXT: [[TRANS:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[A]], i32 5, i32 5)
+ // CHECK-NEXT: [[AT_ADDR:%.*]] = bitcast [25 x double]* %a_t to <25 x double>*
+ // CHECK-NEXT: store <25 x double> [[TRANS]], <25 x double>* [[AT_ADDR]], align 8
+ dx5x5_t a_t = __builtin_matrix_transpose(*a);
+}
+
+void transpose_float_3x2(fx3x2_t *a) {
+ // CHECK-LABEL: define void @transpose_float_3x2(
+ // CHECK: [[A:%.*]] = load <6 x float>, <6 x float>* {{.*}}, align 4
+ // CHECK-NEXT: [[TRANS:%.*]] = call <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> [[A]], i32 3, i32 2)
+ // CHECK-NEXT: [[AT_ADDR:%.*]] = bitcast [6 x float]* %a_t to <6 x float>*
+ // CHECK-NEXT: store <6 x float> [[TRANS]], <6 x float>* [[AT_ADDR]], align 4
+
+ fx2x3_t a_t = __builtin_matrix_transpose(*a);
+}
+
+void transpose_int_20x4(ix20x4_t *a) {
+ // CHECK-LABEL: define void @transpose_int_20x4(
+ // CHECK: [[A:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[TRANS:%.*]] = call <80 x i32> @llvm.matrix.transpose.v80i32(<80 x i32> [[A]], i32 20, i32 4)
+ // CHECK-NEXT: [[AT_ADDR:%.*]] = bitcast [80 x i32]* %a_t to <80 x i32>*
+ // CHECK-NEXT: store <80 x i32> [[TRANS]], <80 x i32>* [[AT_ADDR]], align 4
+
+ ix4x20_t a_t = __builtin_matrix_transpose(*a);
+}
+
+struct Foo {
+ ux1x6_t in;
+ ux6x1_t out;
+};
+
+void transpose_struct_member(struct Foo *F) {
+ // CHECK-LABEL: define void @transpose_struct_member(
+ // CHECK: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6)
+ // CHECK-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8
+ // CHECK-NEXT: [[OUT_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 1
+ // CHECK-NEXT: [[OUT_PTR_C:%.*]] = bitcast [6 x i32]* [[OUT_PTR]] to <6 x i32>*
+ // CHECK-NEXT: store <6 x i32> [[M_T]], <6 x i32>* [[OUT_PTR_C]], align 4
+
+ F->out = __builtin_matrix_transpose(F->in);
+}
+
+void transpose_transpose_struct_member(struct Foo *F) {
+ // CHECK-LABEL: define void @transpose_transpose_struct_member(
+ // CHECK: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6)
+ // CHECK-NEXT: [[M_T2:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M_T]], i32 6, i32 1)
+ // CHECK-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8
+ // CHECK-NEXT: [[IN_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 0
+ // CHECK-NEXT: [[IN_PTR_C:%.*]] = bitcast [6 x i32]* [[IN_PTR]] to <6 x i32>*
+ // CHECK-NEXT: store <6 x i32> [[M_T2]], <6 x i32>* [[IN_PTR_C]], align 4
+
+ F->in = __builtin_matrix_transpose(__builtin_matrix_transpose(F->in));
+}
+
+dx5x5_t get_matrix();
+
+void transpose_rvalue() {
+ // CHECK-LABEL: define void @transpose_rvalue()
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 8
+ // CHECK-NEXT: [[CALL:%.*]] = call <25 x double> (...) @get_matrix()
+ // CHECK-NEXT: [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[CALL]], i32 5, i32 5)
+ // CHECK-NEXT: [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>*
+ // CHECK-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8
+
+ dx5x5_t m_t = __builtin_matrix_transpose(get_matrix());
+}
+
+const dx5x5_t global_matrix;
+
+void transpose_global() {
+ // CHECK-LABEL: define void @transpose_global()
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 8
+ // CHECK-NEXT: [[GLOBAL_MATRIX:%.*]] = load <25 x double>, <25 x double>* bitcast ([25 x double]* @global_matrix to <25 x double>*), align 8
+ // CHECK-NEXT: [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[GLOBAL_MATRIX]], i32 5, i32 5)
+ // CHECK-NEXT: [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>*
+ // CHECK-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8
+
+ dx5x5_t m_t = __builtin_matrix_transpose(global_matrix);
+}
diff --git a/clang/test/CodeGenCXX/matrix-type-builtins.cpp b/clang/test/CodeGenCXX/matrix-type-builtins.cpp
new file mode 100644
index 000000000000..b2b9f7be33f9
--- /dev/null
+++ b/clang/test/CodeGenCXX/matrix-type-builtins.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - -std=c++17 | FileCheck %s
+
+// Tests for the matrix type builtins.
+
+template <typename EltTy, unsigned Rows, unsigned Columns>
+using matrix_t = EltTy __attribute__((matrix_type(Rows, Columns)));
+
+template <typename EltTy, unsigned Rows, unsigned Columns>
+struct MyMatrix {
+ matrix_t<EltTy, Rows, Columns> value;
+};
+
+template <typename T, unsigned R, unsigned C>
+MyMatrix<T, C, R> transpose(const MyMatrix<T, R, C> &M) {
+ MyMatrix<T, C, R> Res;
+ Res.value = __builtin_matrix_transpose(M.value);
+ return Res;
+}
+
+void test_transpose_template1() {
+ // CHECK-LABEL: define void @_Z24test_transpose_template1v()
+ // CHECK: call void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.0* sret align 4 %M1_t, %struct.MyMatrix* nonnull align 4 dereferenceable(160) %M1)
+
+ // CHECK-LABEL: define linkonce_odr void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
+ // CHECK: [[M:%.*]] = load <40 x i32>, <40 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[M_T:%.*]] = call <40 x i32> @llvm.matrix.transpose.v40i32(<40 x i32> [[M]], i32 4, i32 10)
+
+ MyMatrix<int, 4, 10> M1;
+ MyMatrix<int, 10, 4> M1_t = transpose(M1);
+}
+
+void test_transpose_template2(MyMatrix<double, 7, 6> &M) {
+ // CHECK-LABEL: define void @_Z24test_transpose_template2R8MyMatrixIdLj7ELj6EE(
+ // CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.2* sret align 8 %ref.tmp1, %struct.MyMatrix.1* nonnull align 8 dereferenceable(336) %0)
+ // CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.1* sret align 8 %ref.tmp, %struct.MyMatrix.2* nonnull align 8 dereferenceable(336) %ref.tmp1)
+ // CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.2* sret align 8 %M2_t, %struct.MyMatrix.1* nonnull align 8 dereferenceable(336) %ref.tmp)
+
+ // CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
+ // CHECK: [[M:%.*]] = load <42 x double>, <42 x double>* {{.*}}, align 8
+ // CHECK-NEXT: [[M_T:%.*]] = call <42 x double> @llvm.matrix.transpose.v42f64(<42 x double> [[M]], i32 7, i32 6)
+ // CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.2, %struct.MyMatrix.2* %agg.result, i32 0, i32 0
+ // CHECK-NEXT: [[RES_ADDR_C:%.*]] = bitcast [42 x double]* [[RES_ADDR]] to <42 x double>*
+ // CHECK-NEXT: store <42 x double> [[M_T]], <42 x double>* [[RES_ADDR_C]], align 8
+
+ // CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
+ // CHECK: [[M:%.*]] = load <42 x double>, <42 x double>* {{.*}}, align 8
+ // CHECK-NEXT: [[M_T:%.*]] = call <42 x double> @llvm.matrix.transpose.v42f64(<42 x double> [[M]], i32 6, i32 7)
+ // CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.1, %struct.MyMatrix.1* %agg.result, i32 0, i32 0
+ // CHECK-NEXT: [[RES_ADDR_C:%.*]] = bitcast [42 x double]* [[RES_ADDR]] to <42 x double>*
+ // CHECK-NEXT: store <42 x double> [[M_T]], <42 x double>* [[RES_ADDR_C]], align 8
+
+ MyMatrix<double, 6, 7> M2_t = transpose(transpose(transpose(M)));
+}
+
+matrix_t<float, 3, 3> get_matrix();
+
+void test_transpose_rvalue() {
+ // CHECK-LABEL: define void @_Z21test_transpose_rvaluev()
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: [[M_T_ADDR:%.*]] = alloca [9 x float], align 4
+ // CHECK-NEXT: [[CALL_RES:%.*]] = call <9 x float> @_Z10get_matrixv()
+ // CHECK-NEXT: [[ADD:%.*]] = fadd <9 x float> [[CALL_RES]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>
+ // CHECK-NEXT: [[M_T:%.*]] = call <9 x float> @llvm.matrix.transpose.v9f32(<9 x float> [[ADD]], i32 3, i32 3)
+ // CHECK-NEXT: [[M_T_ADDR_CAST:%.*]] = bitcast [9 x float]* [[M_T_ADDR]] to <9 x float>*
+ // CHECK-NEXT: store <9 x float> [[M_T]], <9 x float>* [[M_T_ADDR_CAST]], align 4
+ matrix_t<float, 3, 3> m_t = __builtin_matrix_transpose(get_matrix() + 2.0);
+}
+
+void test_transpose_const(const matrix_t<float, 3, 3> &m) {
+ // CHECK-LABEL: define void @_Z20test_transpose_constRKU11matrix_typeLm3ELm3Ef(
+ // CHECK: [[MATRIX:%.*]] = load <9 x float>, <9 x float>* {{.*}}, align 4
+ // CHECK-NEXT: [[M_T:%.*]] = call <9 x float> @llvm.matrix.transpose.v9f32(<9 x float> [[MATRIX]], i32 3, i32 3)
+ // CHECK-NEXT: [[M_T_ADDR:%.*]] = bitcast [9 x float]* %m_t to <9 x float>*
+ // CHECK-NEXT: store <9 x float> [[M_T]], <9 x float>* [[M_T_ADDR]], align 4
+ matrix_t<float, 3, 3> m_t = __builtin_matrix_transpose(m);
+}
+
+// TODO: Enable once initialization support is defined and implemented for
+// matrix types.
+// void test_lvalue_conversion() {
+// constexpr double4x4 m = {};
+// [] { return __builtin_matrix_transpose(m); }
+//}
diff --git a/clang/test/CodeGenObjC/matrix-type-builtins.m b/clang/test/CodeGenObjC/matrix-type-builtins.m
new file mode 100644
index 000000000000..37f24ff6b68e
--- /dev/null
+++ b/clang/test/CodeGenObjC/matrix-type-builtins.m
@@ -0,0 +1,42 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fenable-matrix -emit-llvm -disable-llvm-optzns -o - %s | FileCheck %s
+
+// Check that we correctly deal with placeholder expressions.
+
+typedef double double4x2 __attribute__((matrix_type(4, 2)));
+typedef double double2x4 __attribute__((matrix_type(2, 4)));
+
+__attribute__((objc_root_class))
+ at interface DoubleMatrixValue
+ at property double4x2 value;
+ at end
+
+void test_transpose_placeholder_get(DoubleMatrixValue *m, double2x4 *r) {
+ // CHECK-LABEL: define void @test_transpose_placeholder_get(
+ // CHECK: [[MATRIX:%.*]] = call <8 x double> bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to <8 x double> (i8*, i8*)*)(
+ // CHECK-NEXT: [[MT:%.*]] = call <8 x double> @llvm.matrix.transpose.v8f64(<8 x double> %call, i32 4, i32 2)
+ // CHECK-NEXT: [[R_ADDR:%.*]] = load [8 x double]*, [8 x double]** %r.addr, align 8
+ // CHECK-NEXT: [[R_ADDR_C:%.*]] = bitcast [8 x double]* [[R_ADDR]] to <8 x double>*
+ // CHECK-NEXT: store <8 x double> [[MT]], <8 x double>* [[R_ADDR_C]], align 8
+ // CHECK-NEXT: ret void
+
+ *r = __builtin_matrix_transpose(m.value);
+}
+
+typedef unsigned u3x4 __attribute__((matrix_type(3, 4)));
+typedef unsigned u4x3 __attribute__((matrix_type(4, 3)));
+
+__attribute__((objc_root_class))
+ at interface UnsignedMatrixValue
+ at property u3x4 value;
+ at end
+
+void test_transpose_placeholder_set(UnsignedMatrixValue *m, u4x3 *r) {
+ // CHECK-LABEL: define void @test_transpose_placeholder_set(
+ // CHECK: [[MATRIX:%.*]] = load <12 x i32>, <12 x i32>* {{.*}}, align 4
+ // CHECK-NEXT: [[MT:%.*]] = call <12 x i32> @llvm.matrix.transpose.v12i32(<12 x i32> [[MATRIX]], i32 4, i32 3)
+ // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, <12 x i32>)*)(i8* {{.*}}, i8* {{.*}}, <12 x i32> [[MT]])
+ // CHECK-NEXT: ret void
+
+ m.value = __builtin_matrix_transpose(*r);
+}
diff --git a/clang/test/Sema/matrix-type-builtins.c b/clang/test/Sema/matrix-type-builtins.c
new file mode 100644
index 000000000000..ac23e562be03
--- /dev/null
+++ b/clang/test/Sema/matrix-type-builtins.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -fenable-matrix -pedantic -verify -triple=x86_64-apple-darwin9
+
+typedef float sx5x10_t __attribute__((matrix_type(5, 10)));
+typedef int ix3x2_t __attribute__((matrix_type(3, 2)));
+typedef double dx3x3 __attribute__((matrix_type(3, 3)));
+typedef unsigned ix3x3 __attribute__((matrix_type(3, 3)));
+
+void transpose(sx5x10_t a, ix3x2_t b, dx3x3 c, int *d, int e) {
+ a = __builtin_matrix_transpose(b);
+ // expected-error at -1 {{assigning to 'sx5x10_t' (aka 'float __attribute__((matrix_type(5, 10)))') from incompatible type 'int __attribute__((matrix_type(2, 3)))'}}
+ b = __builtin_matrix_transpose(b);
+ // expected-error at -1 {{assigning to 'ix3x2_t' (aka 'int __attribute__((matrix_type(3, 2)))') from incompatible type 'int __attribute__((matrix_type(2, 3)))'}}
+ __builtin_matrix_transpose(d);
+ // expected-error at -1 {{first argument must be a matrix}}
+ __builtin_matrix_transpose(e);
+ // expected-error at -1 {{first argument must be a matrix}}
+ __builtin_matrix_transpose("test");
+ // expected-error at -1 {{first argument must be a matrix}}
+
+ ix3x3 m = __builtin_matrix_transpose(c);
+ // expected-error at -1 {{initializing 'ix3x3' (aka 'unsigned int __attribute__((matrix_type(3, 3)))') with an expression of incompatible type 'double __attribute__((matrix_type(3, 3)))'}}
+}
diff --git a/clang/test/SemaCXX/matrix-type-builtins.cpp b/clang/test/SemaCXX/matrix-type-builtins.cpp
new file mode 100644
index 000000000000..b4311b357fa6
--- /dev/null
+++ b/clang/test/SemaCXX/matrix-type-builtins.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 %s -fenable-matrix -pedantic -std=c++11 -verify -triple=x86_64-apple-darwin9
+
+template <typename EltTy, unsigned Rows, unsigned Columns>
+struct MyMatrix {
+ using matrix_t = EltTy __attribute__((matrix_type(Rows, Columns)));
+
+ matrix_t value;
+};
+
+template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1>
+typename MyMatrix<EltTy1, R1, C1>::matrix_t transpose(MyMatrix<EltTy0, R0, C0> &A) {
+ char *v1 = __builtin_matrix_transpose(A.value);
+ // expected-error at -1 {{cannot initialize a variable of type 'char *' with an rvalue of type 'unsigned int __attribute__((matrix_type(3, 2)))'}}
+ // expected-error at -2 {{cannot initialize a variable of type 'char *' with an rvalue of type 'unsigned int __attribute__((matrix_type(3, 3)))'}}
+ // expected-error at -3 {{cannot initialize a variable of type 'char *' with an rvalue of type 'unsigned int __attribute__((matrix_type(3, 3)))'}}
+
+ __builtin_matrix_transpose(A);
+ // expected-error at -1 {{first argument must be a matrix}}
+ // expected-error at -2 {{first argument must be a matrix}}
+ // expected-error at -3 {{first argument must be a matrix}}
+
+ return __builtin_matrix_transpose(A.value);
+ // expected-error at -1 {{cannot initialize return object of type 'typename MyMatrix<unsigned int, 2U, 3U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 3)))') with an rvalue of type 'unsigned int __attribute__((matrix_type(3, 2)))'}}
+ // expected-error at -2 {{cannot initialize return object of type 'typename MyMatrix<unsigned int, 2U, 3U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 3)))') with an rvalue of type 'unsigned int __attribute__((matrix_type(3, 3)))'}}
+ // expected-error at -3 {{cannot initialize return object of type 'typename MyMatrix<float, 3U, 3U>::matrix_t' (aka 'float __attribute__((matrix_type(3, 3)))') with an rvalue of type 'unsigned int __attribute__((matrix_type(3, 3)))'}}
+}
+
+void test_transpose_template(unsigned *Ptr1, float *Ptr2) {
+ MyMatrix<unsigned, 2, 3> Mat1;
+ MyMatrix<unsigned, 3, 3> Mat2;
+ Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
+ Mat1.value = transpose<unsigned, 2, 3, unsigned, 2, 3>(Mat1);
+ // expected-note at -1 {{in instantiation of function template specialization 'transpose<unsigned int, 2, 3, unsigned int, 2, 3>' requested here}}
+
+ Mat1.value = transpose<unsigned, 3, 3, unsigned, 2, 3>(Mat2);
+ // expected-note at -1 {{in instantiation of function template specialization 'transpose<unsigned int, 3, 3, unsigned int, 2, 3>' requested here}}
+
+ MyMatrix<float, 3, 3> Mat3;
+ Mat3.value = transpose<unsigned, 3, 3, float, 3, 3>(Mat2);
+ // expected-note at -1 {{in instantiation of function template specialization 'transpose<unsigned int, 3, 3, float, 3, 3>' requested here}}
+}
diff --git a/clang/test/SemaObjC/matrix-type-builtins.m b/clang/test/SemaObjC/matrix-type-builtins.m
new file mode 100644
index 000000000000..bac7008f74e2
--- /dev/null
+++ b/clang/test/SemaObjC/matrix-type-builtins.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fenable-matrix %s
+
+typedef double double4x4 __attribute__((matrix_type(4, 4)));
+typedef unsigned u4x4 __attribute__((matrix_type(4, 4)));
+
+__attribute__((objc_root_class))
+ at interface MatrixValue
+ at property double4x4 value;
+ at end
+
+void test_element_type_mismatch(u4x4 m, MatrixValue *mv) {
+ m = __builtin_matrix_transpose(mv.value);
+ // expected-error at -1 {{assigning to 'u4x4' (aka 'unsigned int __attribute__((matrix_type(4, 4)))') from incompatible type 'double __attribute__((matrix_type(4, 4)))'}}
+}
+
+typedef double double3x3 __attribute__((matrix_type(3, 3)));
+
+double test_dimension_mismatch(double3x3 m, MatrixValue *mv) {
+ m = __builtin_matrix_transpose(mv.value);
+ // expected-error at -1 {{assigning to 'double3x3' (aka 'double __attribute__((matrix_type(3, 3)))') from incompatible type 'double __attribute__((matrix_type(4, 4)))'}}
+}
More information about the cfe-commits
mailing list