https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/232079
>From c5b6fb7af2c1b1510fb6573d785ffdc1f37a8150 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Fri, 16 Oct 2026 18:39:26 +0200 Subject: [PATCH 1/2] [CIR] Implement support for MatrixSingleSubscript expr --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 41 ++++++++++++++++++ clang/include/clang/CIR/LoweringHelpers.h | 2 +- clang/lib/CIR/CodeGen/CIRGenBuilder.h | 6 +++ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 11 ++--- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 5 ++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 42 +++++++++++++++++-- clang/lib/CIR/Lowering/LoweringHelpers.cpp | 18 +++++--- .../CodeGenHLSL/matrix-element-expr-load.hlsl | 1 - .../CodeGenHLSL/matrix-single-subscript.hlsl | 34 +++++++++++++++ 9 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 63d50761806a67..7538dcdc271825 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -6681,6 +6681,47 @@ def CIR_MatrixExtractOp : CIR_Op<"matrix.extract", [ }]; } +//===----------------------------------------------------------------------===// +// MatrixExtractRowOp +//===----------------------------------------------------------------------===// + +def CIR_MatrixExtractRowOp : CIR_Op<"matrix.extract_row", [ + Pure, + TypesMatchWith< + "type of 'result' matches vector type with same element type of 'matrix' " + "and size equals to num columns", + "matrix", "result", + "cir::VectorType::get(" + "mlir::cast<cir::MatrixType>($_self).getElementType()," + "mlir::cast<cir::MatrixType>($_self).getNumColumns()" + ")"> +]> { + let summary = "Extract a row from a matrix object"; + let description = [{ + The `cir.matrix.extract_row` operation extracts a row from from a matrix + object using a row index. + + ``` + %rowIdx = cir.const #cir.int<1> : !u64i + %row = cir.matrix.extract_row %matrix[%rowIdx : !u64i] + : !cir.matrix<3 x 3 x !cir.float> + ``` + }]; + + let arguments = (ins + CIR_MatrixType:$matrix, + CIR_AnyFundamentalIntType:$rowIdx + ); + + let results = (outs CIR_AnyVectorType:$result); + + let assemblyFormat = [{ + $matrix + `[` $rowIdx `:` type($rowIdx) `]` + attr-dict `:` qualified(type($matrix)) + }]; +} + //===----------------------------------------------------------------------===// // MatrixInsertOp //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/LoweringHelpers.h b/clang/include/clang/CIR/LoweringHelpers.h index bfd1182aa64891..cda497ce7aff06 100644 --- a/clang/include/clang/CIR/LoweringHelpers.h +++ b/clang/include/clang/CIR/LoweringHelpers.h @@ -79,7 +79,7 @@ mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs); mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, - mlir::Type type); + mlir::Type type, bool isForHLSL = false); /// The type of a load/store's *value*, as opposed to convertTypeForMemory's /// type of the memory it lives in. The two are effectively identical except diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 4c0b90efec5c68..b9cc67e394accf 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -834,6 +834,12 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return cir::MatrixExtractOp::create(*this, loc, matrix, rowIdx, columnIdx); } + cir::MatrixExtractRowOp createMatrixExtractRow(mlir::Location loc, + mlir::Value matrix, + mlir::Value rowIdx) { + return cir::MatrixExtractRowOp::create(*this, loc, matrix, rowIdx); + } + cir::MatrixInsertOp createMatrixInsert(mlir::Location loc, mlir::Value value, mlir::Value matrix, mlir::Value rowIdx, mlir::Value columnIdx) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 2082963025238c..10aa03c3cc3c87 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -320,15 +320,16 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { mlir::Value columnIdx = cgf.emitScalarExpr(e->getColumnIdx()); mlir::Value matrix = Visit(e->getBase()); mlir::Location loc = cgf.getLoc(e->getSourceRange()); - if (cgf.cgm.getCodeGenOpts().OptimizationLevel > 0) - assert(!cir::MissingFeatures::emitMatrixIndexAssumption()); + assert(!cir::MissingFeatures::emitMatrixIndexAssumption()); return builder.createMatrixExtract(loc, matrix, rowIdx, columnIdx); } mlir::Value VisitMatrixSingleSubscriptExpr(MatrixSingleSubscriptExpr *e) { - cgf.cgm.errorNYI(e->getSourceRange(), - "ScalarExprEmitter: matrix singel subscript"); - return {}; + mlir::Value rowIdx = cgf.emitScalarExpr(e->getRowIdx()); + assert(!cir::MissingFeatures::emitMatrixIndexAssumption()); + mlir::Value matrix = Visit(e->getBase()); + mlir::Location loc = cgf.getLoc(e->getSourceRange()); + return builder.createMatrixExtractRow(loc, matrix, rowIdx); } mlir::Value VisitCastExpr(CastExpr *e); diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index e1da57c9a38db7..6e564288447676 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -8,6 +8,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/GlobalDecl.h" +#include "clang/AST/MatrixUtils.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" @@ -698,7 +699,9 @@ mlir::Type CIRGenTypes::convertType(QualType type) { mlir::Type CIRGenTypes::convertTypeForMem(clang::QualType qualType, bool forBitField) { if (astContext.getLangOpts().HLSL && qualType->isConstantMatrixType()) { - cgm.errorNYI("convertTypeForMem: HLSL & ConstantMatrixType"); + if (isMatrixRowMajor(astContext.getLangOpts(), qualType)) { + cgm.errorNYI("convertTypeForMem: HLSL & Matrix row major"); + } } mlir::Type convertedType = convertType(qualType); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index e433e6b9147f76..8664a47ba1ae7e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2318,19 +2318,26 @@ mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite( mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite( cir::AllocaOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { + mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>(); + mlir::Attribute langOpts = + module->getAttr(cir::CIRDialect::getLoweringLangOptionsAttrName()); + auto loweringLangOps = + dyn_cast_if_present<cir::LoweringLangOptionsAttr>(langOpts); + bool isForHLSL = loweringLangOps ? loweringLangOps.getHlsl() : false; + mlir::Value size = op.isDynamic() ? adaptor.getDynAllocSize() : mlir::LLVM::ConstantOp::create( rewriter, op.getLoc(), typeConverter->convertType(rewriter.getI32Type()), 1); - mlir::Type elementTy = - convertTypeForMemory(*getTypeConverter(), dataLayout, op.getAllocaType()); + mlir::Type elementTy = convertTypeForMemory(*getTypeConverter(), dataLayout, + op.getAllocaType(), isForHLSL); if (!elementTy) return op.emitError() << "NYI: lowering alloca of a type with no memory representation"; - mlir::Type resultTy = - convertTypeForMemory(*getTypeConverter(), dataLayout, op.getType()); + mlir::Type resultTy = convertTypeForMemory(*getTypeConverter(), dataLayout, + op.getType(), isForHLSL); assert(!cir::MissingFeatures::addressSpace()); assert(!cir::MissingFeatures::opAllocaAnnotations()); @@ -5564,6 +5571,33 @@ mlir::LogicalResult CIRToLLVMMatrixExtractOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMMatrixExtractRowOpLowering::matchAndRewrite( + cir::MatrixExtractRowOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + cir::MatrixType matrixTy = op.getMatrix().getType(); + mlir::Type elementType = + typeConverter->convertType(matrixTy.getElementType()); + mlir::Type resultTy = + mlir::VectorType::get(matrixTy.getNumColumns(), elementType); + mlir::Value rowVec = + mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), resultTy); + + for (unsigned col = 0; col != matrixTy.getNumColumns(); ++col) { + mlir::Value columnIdx = mlir::LLVM::ConstantOp::create( + rewriter, op.getLoc(), rewriter.getI32Type(), + rewriter.getIntegerAttr(rewriter.getI32Type(), col)); + mlir::Value flatIndex = computeMatrixFlatIndex( + rewriter, op.getLoc(), matrixTy, adaptor.getRowIdx(), columnIdx); + + auto element = mlir::LLVM::ExtractElementOp::create( + rewriter, op->getLoc(), elementType, adaptor.getMatrix(), flatIndex); + rowVec = mlir::LLVM::InsertElementOp::create(rewriter, op->getLoc(), rowVec, + element, columnIdx); + } + rewriter.replaceOp(op, rowVec); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMMatrixInsertOpLowering::matchAndRewrite( cir::MatrixInsertOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp b/clang/lib/CIR/Lowering/LoweringHelpers.cpp index 41ba493d3482a4..cce8cfe013c611 100644 --- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp +++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp @@ -73,7 +73,7 @@ mlir::Attribute getBitIntStorageAttr(mlir::ConversionPatternRewriter &rewriter, mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, - mlir::Type type) { + mlir::Type type, bool isForHLSL) { // TODO(cir): Handle other types similarly to clang's codegen // convertTypeForMemory if (mlir::isa<cir::BoolType>(type)) { @@ -82,10 +82,18 @@ mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, } if (auto matrixTy = mlir::dyn_cast<cir::MatrixType>(type)) { - if (mlir::isa<cir::BoolType>(matrixTy.getElementType())) { - assert(!cir::MissingFeatures::hlsl()); - llvm_unreachable( - "convertTypeForMemory: Matrix with bool as element type"); + if (isForHLSL) { + if (mlir::isa<cir::BoolType>(matrixTy.getElementType())) { + assert(!cir::MissingFeatures::hlsl()); + llvm_unreachable( + "convertTypeForMemory: HLSL -> Matrix with bool as element type"); + } + + unsigned vecLen = matrixTy.getNumRows(); + unsigned arrayLen = matrixTy.getNumColumns(); + mlir::Type elementType = converter.convertType(matrixTy.getElementType()); + auto vecTy = mlir::VectorType::get(vecLen, elementType); + return mlir::LLVM::LLVMArrayType::get(vecTy, arrayLen); } uint64_t size = matrixTy.getNumRows() * matrixTy.getNumColumns(); diff --git a/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl b/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl index 76a9d0da14dbfb..3b291041004045 100644 --- a/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl +++ b/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl @@ -2,7 +2,6 @@ // RUN: -fclangir -emit-cir -disable-llvm-passes -verify float test_zero_indexed(float2x2 M) { - // expected-error@*:* {{ClangIR code gen Not Yet Implemented: convertTypeForMem: HLSL & ConstantMatrixType}} // expected-error@+1 {{ClangIR code gen Not Yet Implemented: ScalarExprEmitter: matrix element}} return M._m00; } diff --git a/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl b/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl new file mode 100644 index 00000000000000..4e93ed849668d2 --- /dev/null +++ b/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -x hlsl -triple spirv-unknown-vulkan-library -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x hlsl -triple spirv-unknown-vulkan-library -fclangir -emit-llvm %s -o %t.cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.cir.ll %s +// RUN: %clang_cc1 -x hlsl -triple spirv-unknown-vulkan-library -emit-llvm -disable-llvm-passes %s -o %t.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + +typedef float matrix3x3 __attribute__((matrix_type(3, 3))); +typedef float vector3 __attribute__((ext_vector_type(3))); + +void matrix_single_subscript() { + matrix3x3 matrix; + vector3 vec = matrix[1]; +} + +// CIR: %[[MATRIX_ADDR:.*]] = cir.alloca "matrix" {{.*}} : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> +// CIR: %[[VEC_ADDR:.*]] = cir.alloca "vec" {{.*}} init : !cir.ptr<!cir.vector<3 x !cir.float>> +// CIR: %[[VEC_ADDR_AS:.*]] = cir.cast address_space %[[VEC_ADDR]] : !cir.ptr<!cir.vector<3 x !cir.float>> -> !cir.ptr<!cir.vector<3 x !cir.float>> +// CIR: %[[MATRIX_ADDR_AS:.*]] = cir.cast address_space %[[MATRIX_ADDR]] : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> -> !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> +// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i +// CIR: %[[TMP_MATRIX:.*]] = cir.load {{.*}} %[[MATRIX_ADDR_AS]] : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>>, !cir.matrix<3 x 3 x !cir.float> +// CIR: %[[VEC:.*]] = cir.matrix.extract_row %[[TMP_MATRIX]][%[[CONST_1]] : !s32i] : !cir.matrix<3 x 3 x !cir.float> +// CIR: cir.store {{.*}} %[[VEC]], %[[VEC_ADDR_AS]] : !cir.vector<3 x !cir.float>, !cir.ptr<!cir.vector<3 x !cir.float>> + +// LLVM: %[[MATRIX_ADDR:.*]] = alloca [3 x <3 x float>], align 4 +// LLVM: %[[VEC_ADDR:.*]] = alloca <3 x float>, align 4 +// LLVM: %[[TMP_MATRIX:.*]] = load <9 x float>, ptr %[[MATRIX_ADDR]], align 4 +// LLVM: %[[EXTRACT_1:.*]] = extractelement <9 x float> %[[TMP_MATRIX]], i64 1 +// LLVM: %[[INSERT_ROW_0:.*]] = insertelement <3 x float> {{.*}}, float %[[EXTRACT_1]], i32 0 +// LLVM: %[[EXTRACT_4:.*]] = extractelement <9 x float> %[[TMP_MATRIX]], i64 4 +// LLVM: %[[INSERT_ROW_1:.*]] = insertelement <3 x float> %[[INSERT_ROW_0]], float %[[EXTRACT_4]], i32 1 +// LLVM: %[[EXTRACT_7:.*]] = extractelement <9 x float> %[[TMP_MATRIX]], i64 7 +// LLVM: %[[INSERT_ROW_2:.*]] = insertelement <3 x float> %[[INSERT_ROW_1]], float %[[EXTRACT_7]], i32 2 +// LLVM: store <3 x float> %[[INSERT_ROW_2]], ptr %[[VEC_ADDR]], align 4 >From 3b3b658f44c2454bb6bb9c2049b29761cc496ab4 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Sat, 17 Oct 2026 16:18:02 +0200 Subject: [PATCH 2/2] Address code review comments --- clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 7 +++++++ clang/lib/CIR/Lowering/LoweringHelpers.cpp | 6 ------ clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl | 6 ++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 8664a47ba1ae7e..07ecf4a39e4e04 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2323,7 +2323,14 @@ mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite( module->getAttr(cir::CIRDialect::getLoweringLangOptionsAttrName()); auto loweringLangOps = dyn_cast_if_present<cir::LoweringLangOptionsAttr>(langOpts); + bool isForHLSL = loweringLangOps ? loweringLangOps.getHlsl() : false; + if (isForHLSL && mlir::isa<cir::MatrixType>(op.getAllocaType()) && + mlir::isa<cir::BoolType>( + cast<cir::MatrixType>(op.getAllocaType()).getElementType())) { + return op.emitError() + << "NYI: Builtin matrix type with bool element type for HLSL"; + } mlir::Value size = op.isDynamic() diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp b/clang/lib/CIR/Lowering/LoweringHelpers.cpp index cce8cfe013c611..dec0928dfcf4bf 100644 --- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp +++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp @@ -83,12 +83,6 @@ mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, if (auto matrixTy = mlir::dyn_cast<cir::MatrixType>(type)) { if (isForHLSL) { - if (mlir::isa<cir::BoolType>(matrixTy.getElementType())) { - assert(!cir::MissingFeatures::hlsl()); - llvm_unreachable( - "convertTypeForMemory: HLSL -> Matrix with bool as element type"); - } - unsigned vecLen = matrixTy.getNumRows(); unsigned arrayLen = matrixTy.getNumColumns(); mlir::Type elementType = converter.convertType(matrixTy.getElementType()); diff --git a/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl b/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl index 4e93ed849668d2..670e9ab957e6b9 100644 --- a/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl +++ b/clang/test/CIR/CodeGenHLSL/matrix-single-subscript.hlsl @@ -15,12 +15,10 @@ void matrix_single_subscript() { // CIR: %[[MATRIX_ADDR:.*]] = cir.alloca "matrix" {{.*}} : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> // CIR: %[[VEC_ADDR:.*]] = cir.alloca "vec" {{.*}} init : !cir.ptr<!cir.vector<3 x !cir.float>> -// CIR: %[[VEC_ADDR_AS:.*]] = cir.cast address_space %[[VEC_ADDR]] : !cir.ptr<!cir.vector<3 x !cir.float>> -> !cir.ptr<!cir.vector<3 x !cir.float>> -// CIR: %[[MATRIX_ADDR_AS:.*]] = cir.cast address_space %[[MATRIX_ADDR]] : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> -> !cir.ptr<!cir.matrix<3 x 3 x !cir.float>> // CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i -// CIR: %[[TMP_MATRIX:.*]] = cir.load {{.*}} %[[MATRIX_ADDR_AS]] : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>>, !cir.matrix<3 x 3 x !cir.float> +// CIR: %[[TMP_MATRIX:.*]] = cir.load {{.*}} %[[MATRIX_ADDR]] : !cir.ptr<!cir.matrix<3 x 3 x !cir.float>>, !cir.matrix<3 x 3 x !cir.float> // CIR: %[[VEC:.*]] = cir.matrix.extract_row %[[TMP_MATRIX]][%[[CONST_1]] : !s32i] : !cir.matrix<3 x 3 x !cir.float> -// CIR: cir.store {{.*}} %[[VEC]], %[[VEC_ADDR_AS]] : !cir.vector<3 x !cir.float>, !cir.ptr<!cir.vector<3 x !cir.float>> +// CIR: cir.store {{.*}} %[[VEC]], %[[VEC_ADDR]] : !cir.vector<3 x !cir.float>, !cir.ptr<!cir.vector<3 x !cir.float>> // LLVM: %[[MATRIX_ADDR:.*]] = alloca [3 x <3 x float>], align 4 // LLVM: %[[VEC_ADDR:.*]] = alloca <3 x float>, align 4 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
