https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/221773
Implement the basic support for the built-in matrix type Issue #221772 >From a71a96ea9f3c454997850a28ea874f0c3f8d6c88 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Sun, 6 Sep 2026 19:56:44 +0200 Subject: [PATCH] [CIR] Support builtin matrix type --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 2 + .../CIR/Dialect/IR/CIRTypeConstraints.td | 10 ++++ .../include/clang/CIR/Dialect/IR/CIRTypes.td | 53 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 13 +++-- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 +- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 30 +++++++++++ clang/lib/CIR/Lowering/LoweringHelpers.cpp | 11 ++++ clang/test/CIR/CodeGen/matrix.cpp | 20 +++++++ .../CodeGenHLSL/matrix-element-expr-load.hlsl | 4 +- clang/test/CIR/IR/invalid-matrix.cir | 32 +++++++++++ 10 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 clang/test/CIR/CodeGen/matrix.cpp create mode 100644 clang/test/CIR/IR/invalid-matrix.cir diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index b5920492f1800..ac2c29a1b0843 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -131,6 +131,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return cir::ZeroAttr::get(arrTy); if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty)) return cir::ZeroAttr::get(vecTy); + if (auto matrixTy = mlir::dyn_cast<cir::MatrixType>(ty)) + return cir::ZeroAttr::get(matrixTy); if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty)) return getConstNullPtrAttr(ptrTy); if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td index afdd732a5867f..fc0bb623425b9 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td @@ -366,6 +366,16 @@ def CIR_AnyBitwiseType : AnyTypeOf<[CIR_AnyIntType, CIR_AnyBoolType, CIR_VectorOfIntOrBoolType], "integer, boolean, or vector of bool or integer">; +//===----------------------------------------------------------------------===// +// Matrix Type predicates +//===----------------------------------------------------------------------===// + +def CIR_MatrixElementType + : AnyTypeOf<[CIR_AnyBoolType, CIR_AnyIntOrFloatType, CIR_AnyPtrType], + "any cir boolean, integer, floating point or pointer type"> { + let cppFunctionName = "isValidMatrixTypeElementType"; +} + //===----------------------------------------------------------------------===// // Data member type predicates //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index d0bcb885bc634..ccb42455376ba 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -529,6 +529,59 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [ let hasCustomAssemblyFormat = 1; } +//===----------------------------------------------------------------------===// +// MatrixType +//===----------------------------------------------------------------------===// + +def CIR_MatrixType : CIR_Type<"Matrix", "matrix", [ + DeclareTypeInterfaceMethods<DataLayoutTypeInterface>, +]> { + let summary = "CIR matrix type"; + let description = [{ + The `!cir.matrix` type represents a fixed-size 2-dimensional matrices. + It takes three parameters: the element type, the number of rows + and columns. + + Syntax: + + ``` + matrix-type ::= !cir.vector<row x colum x element-type> + size ::= (decimal-literal | `[` decimal-literal `]`) + element-type ::= float-type | integer-type | pointer-type + ``` + + The `element-type` must be a scalar CIR type. Zero-sized matrices are not + allowed. The `row` and `column` count must be a positive integer. + + Examples: + + ``` + !cir.matrix<3 x 3 x !cir.int<u, 8>> + !cir.matrix<2 x 4 x !cir.float> + ``` + }]; + + let parameters = (ins + CIR_MatrixElementType:$element_type, + "uint64_t":$row_num, + "uint64_t":$column_num + ); + + let builders = [ + TypeBuilderWithInferredContext<(ins + "mlir::Type":$element_type, "uint64_t":$row_num, "uint64_t":$column_num + ), [{ + return $_get(element_type.getContext(), element_type, row_num, column_num); + }]>, + ]; + + let assemblyFormat = [{ + `<` $row_num `x` $column_num `x` $element_type `>` + }]; + + let genVerifyDecl = 1; +} + //===----------------------------------------------------------------------===// // FuncType //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index f2cb875e908a7..99645ce8665b5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -606,6 +606,14 @@ mlir::Type CIRGenTypes::convertType(QualType type) { break; } + case Type::ConstantMatrix: { + const ConstantMatrixType *mt = cast<ConstantMatrixType>(ty); + const mlir::Type elemTy = convertType(mt->getElementType()); + resultType = + cir::MatrixType::get(elemTy, mt->getNumRows(), mt->getNumColumns()); + break; + } + case Type::Enum: { const auto *ed = ty->castAsEnumDecl(); if (auto integerType = ed->getIntegerType(); !integerType.isNull()) @@ -689,11 +697,6 @@ mlir::Type CIRGenTypes::convertType(QualType type) { mlir::Type CIRGenTypes::convertTypeForMem(clang::QualType qualType, bool forBitField) { - if (qualType->isConstantMatrixType()) { - cgm.errorNYI("Matrix type conversion"); - return cgm.sInt32Ty; - } - mlir::Type convertedType = convertType(qualType); assert(!forBitField && "Bit fields NYI"); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 606b4fd9d3fa6..825d739597e2c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -587,8 +587,8 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, } if (isa<cir::ZeroAttr>(attrType)) { - if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>( - opType)) + if (isa<cir::RecordType, cir::ArrayType, cir::MatrixType, cir::VectorType, + cir::ComplexType>(opType)) return success(); return op->emitOpError( "zero expects struct, array, vector, or complex type"); diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index e4093000e8507..aedb26659e72e 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -1583,6 +1583,36 @@ void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) const { odsPrinter << ">"; } +//===----------------------------------------------------------------------===// +// MatrixType Definitions +//===----------------------------------------------------------------------===// + +llvm::TypeSize cir::MatrixType::getTypeSizeInBits( + const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + return llvm::TypeSize::getFixed( + getRowNum() * getColumnNum() * + dataLayout.getTypeSizeInBits(getElementType())); +} + +uint64_t +cir::MatrixType::getABIAlignment(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + // This hook answers in bytes, not bits. + return llvm::PowerOf2Ceil( + llvm::divideCeil(dataLayout.getTypeSizeInBits(*this), 8u)); +} + +mlir::LogicalResult cir::MatrixType::verify( + llvm::function_ref<mlir::InFlightDiagnostic()> emitError, + mlir::Type elementType, uint64_t row, uint64_t column) { + if (row == 0) + return emitError() << "the number of matrix rows must be non-zero"; + if (column == 0) + return emitError() << "the number of matrix columns must be non-zero"; + return success(); +} + //===----------------------------------------------------------------------===// // AddressSpace definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp b/clang/lib/CIR/Lowering/LoweringHelpers.cpp index 1dad8beaa4bce..7f15dff597299 100644 --- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp +++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp @@ -46,6 +46,17 @@ mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, dataLayout.getTypeSizeInBits(type)); } + if (auto matrixTy = mlir::dyn_cast<cir::MatrixType>(type)) { + if (mlir::isa<cir::BoolType>(matrixTy.getElementType())) { + llvm_unreachable( + "convertTypeForMemory: Matrix with bool as element type"); + } + + uint64_t size = matrixTy.getRowNum() * matrixTy.getColumnNum(); + mlir::Type elementType = converter.convertType(matrixTy.getElementType()); + return mlir::LLVM::LLVMArrayType::get(elementType, size); + } + if (auto vecTy = mlir::dyn_cast<cir::VectorType>(type)) { if (mlir::isa<cir::BoolType>(vecTy.getElementType())) { assert(!cir::MissingFeatures::hlsl()); diff --git a/clang/test/CIR/CodeGen/matrix.cpp b/clang/test/CIR/CodeGen/matrix.cpp new file mode 100644 index 0000000000000..89c4c55149c6b --- /dev/null +++ b/clang/test/CIR/CodeGen/matrix.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fenable-matrix -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fenable-matrix -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fenable-matrix -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM + +typedef float matrix3x3 __attribute__((matrix_type(3, 3))); + +matrix3x3 a; + +// CIR: cir.global external @a = #cir.zero : !cir.matrix<3 x 3 x !cir.float> +// LLVM: @a = global [9 x float] zeroinitializer, align 4 + +void local_matrix() { + matrix3x3 a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> +// LLVM: %[[A_ADDR:.*]] = alloca [9 x float], align 4 diff --git a/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl b/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl index abec530f474f5..8f9d5fd45a922 100644 --- a/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl +++ b/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl @@ -1,8 +1,6 @@ -// RUN: %clang_cc1 -x hlsl -finclude-default-header -triple spirv-unknown-vulkan-library %s \ +// RUN: not %clang_cc1 -x hlsl -finclude-default-header -triple spirv-unknown-vulkan-library %s \ // RUN: -fclangir -emit-cir -disable-llvm-passes -verify -// expected-error@*:* {{ClangIR code gen Not Yet Implemented: processing of type: ConstantMatrix}} -// expected-error@*:* {{ClangIR code gen Not Yet Implemented: Matrix type conversion}} float test_zero_indexed(float2x2 M) { // expected-error@+1 {{ClangIR code gen Not Yet Implemented: ScalarExprEmitter: matrix element}} return M._m00; diff --git a/clang/test/CIR/IR/invalid-matrix.cir b/clang/test/CIR/IR/invalid-matrix.cir new file mode 100644 index 0000000000000..f8bb3c5d3ba73 --- /dev/null +++ b/clang/test/CIR/IR/invalid-matrix.cir @@ -0,0 +1,32 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!s32i = !cir.int<s, 32> + +module { + +// expected-error @below {{failed to verify 'element_type'}} +cir.global external @vec_b = #cir.zero : !cir.matrix<4 x 4 x !cir.array<!s32i x 10>> + +} + +// ----- + +!s32i = !cir.int<s, 32> + +cir.func @invalid_row_number() { + // expected-error@+1 {{the number of matrix rows must be non-zero}} + %3 = cir.alloca !cir.matrix<0 x 4 x !s32i>, !cir.ptr<!cir.matrix<0 x 4 x !s32i>> + cir.return + +} + +// ----- + +!s32i = !cir.int<s, 32> + +cir.func @invalid_column_number() { + // expected-error@+1 {{the number of matrix columns must be non-zero}} + %3 = cir.alloca !cir.matrix<4 x 0 x !s32i>, !cir.ptr<!cir.matrix<4 x 0 x !s32i>> + cir.return + +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
