llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> Implement support for the MatrixElementExpr that performs extract to return element, the other version that returns row will be implemented in a follow-up --- Full diff: https://github.com/llvm/llvm-project/pull/235497.diff 5 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+65-2) - (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+1-4) - (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+1-3) - (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+1) - (modified) clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl (+25-5) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 2637266cf3feed..7eea04459de2f5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -860,7 +860,8 @@ RValue CIRGenFunction::emitLoadOfExtVectorElementLValue(LValue lv) { // HLSL allows treating scalars as one-element vectors. Converting the scalar // IR value to a vector here allows the rest of codegen to behave as normal. - if (getLangOpts().HLSL && !mlir::isa<cir::VectorType>(vec.getType())) { + if (getLangOpts().HLSL && (!mlir::isa<cir::VectorType>(vec.getType()) && + !mlir::isa<cir::MatrixType>(vec.getType()))) { cgm.errorNYI(loc, "emitLoadOfExtVectorElementLValue: HLSL"); return {}; } @@ -874,7 +875,15 @@ RValue CIRGenFunction::emitLoadOfExtVectorElementLValue(LValue lv) { int64_t indexValue = getAccessedFieldNo(0, elts); cir::ConstantOp index = builder.getConstInt(loc, builder.getSInt64Ty(), indexValue); - return RValue::get(cir::VecExtractOp::create(builder, loc, vec, index)); + if (mlir::isa<cir::VectorType>(vec.getType())) { + return RValue::get(cir::VecExtractOp::create(builder, loc, vec, index)); + } + + cir::ConstantOp columnIdx = + builder.getConstInt(loc, builder.getSInt64Ty(), 0); + mlir::Value element = + cir::MatrixExtractOp::create(builder, loc, vec, index, columnIdx); + return RValue::get(element); } // Always use shuffle vector to try to retain the original program structure @@ -1657,6 +1666,60 @@ LValue CIRGenFunction::emitExtVectorElementExpr(const ExtVectorElementExpr *e) { base.getBaseInfo()); } +LValue CIRGenFunction::emitMatrixElementExpr(const MatrixElementExpr *e) { + LValue base; + if (e->getBase()->isGLValue()) + base = emitLValue(e->getBase()); + else { + cgm.errorNYI(e->getSourceRange(), "emitMatrixElementExpr base not GLValue"); + return {}; + } + + QualType resultType = + e->getType().withCVRQualifiers(base.getQuals().getCVRQualifiers()); + + // Encode the element access list into a vector of unsigned indices. + // getEncodedElementAccess returns row-major linearized indices. + SmallVector<uint32_t, 4> indices; + e->getEncodedElementAccess(indices); + + // getEncodedElementAccess returns row-major linearized indices + // If the matrix memory layout is column-major, convert indices + // to column-major indices. + bool isRowMajor = isMatrixRowMajor(getLangOpts(), e->getBase()->getType()); + if (!isRowMajor) { + const auto *matrixTy = + e->getBase()->getType()->castAs<ConstantMatrixType>(); + unsigned numCols = matrixTy->getNumColumns(); + for (uint32_t &idx : indices) { + // Decompose row-major index: Row = Idx / NumCols, Col = Idx % NumCols + unsigned row = idx / numCols; + unsigned column = idx % numCols; + // Re-linearize as column-major + idx = matrixTy->getColumnMajorFlattenedIndex(row, column); + } + } + + if (base.isSimple()) { + Address matrixAddr = base.getAddress(); + if (getLangOpts().HLSL && + e->getBase()->getType().getAddressSpace() == LangAS::hlsl_constant) { + cgm.errorNYI( + e->getSourceRange(), + "emitMatrixElementExpr simple & HLSL address space hlsl_constant"); + return {}; + } + + SmallVector<int64_t> attrElts(indices.begin(), indices.end()); + mlir::ArrayAttr elts = builder.getI64ArrayAttr(attrElts); + return LValue::makeExtVectorElt(matrixAddr, elts, resultType, + base.getBaseInfo()); + } + + cgm.errorNYI(e->getSourceRange(), "emitMatrixElementExpr not simple"); + return {}; +} + LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name) { cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e, name); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 8e6ded0527cc90..90796feb5e6f6a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -408,10 +408,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { mlir::Value VisitExtVectorElementExpr(Expr *e) { return emitLoadOfLValue(e); } - mlir::Value VisitMatrixElementExpr(Expr *e) { - cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: matrix element"); - return {}; - } + mlir::Value VisitMatrixElementExpr(Expr *e) { return emitLoadOfLValue(e); } mlir::Value VisitMemberExpr(MemberExpr *e); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 409a94b9acff8f..4fa4585b08d1ef 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -1336,9 +1336,7 @@ LValue CIRGenFunction::emitLValue(const Expr *e) { case Expr::ExtVectorElementExprClass: return emitExtVectorElementExpr(cast<ExtVectorElementExpr>(e)); case Expr::MatrixElementExprClass: - getCIRGenModule().errorNYI(e->getSourceRange(), - "emitLValue: MatrixElementExpr"); - return LValue(); + return emitMatrixElementExpr(cast<MatrixElementExpr>(e)); case Expr::CXXThisExprClass: return makeAddrLValue(loadCXXThisAddress(), e->getType()); case Expr::MemberExprClass: diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 396c10ec9001a5..df01669410bf3a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -2470,6 +2470,7 @@ class CIRGenFunction : public CIRGenTypeCache { LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e); + LValue emitMatrixElementExpr(const MatrixElementExpr *e); LValue emitMemberExpr(const MemberExpr *e); /// Emit a musttail call for a thunk with a potentially different ABI. diff --git a/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl b/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl index 3b291041004045..840b891fa0dad1 100644 --- a/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl +++ b/clang/test/CIR/CodeGenHLSL/matrix-element-expr-load.hlsl @@ -1,7 +1,27 @@ -// RUN: %clang_cc1 -x hlsl -finclude-default-header -triple spirv-unknown-vulkan-library %s \ -// RUN: -fclangir -emit-cir -disable-llvm-passes -verify +// 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 -float test_zero_indexed(float2x2 M) { - // expected-error@+1 {{ClangIR code gen Not Yet Implemented: ScalarExprEmitter: matrix element}} - return M._m00; +typedef int matrix4x4 __attribute__((matrix_type(4, 4))); + +void matrix_element_expr() { + matrix4x4 matrix; + int element = matrix._11; } + +// CIR: %[[MATRIX_ADDR:.*]] = cir.alloca "matrix" {{.*}} : !cir.ptr<!cir.matrix<4 x 4 x !s32i>> +// CIR: %[[ELEMENT_ADDR:.*]] = cir.alloca "element" {{.*}} init : !cir.ptr<!s32i> +// CIR: %[[TMP_MATRIX:.*]] = cir.load {{.*}} %[[MATRIX_ADDR]] : !cir.ptr<!cir.matrix<4 x 4 x !s32i>>, !cir.matrix<4 x 4 x !s32i> +// CIR: %[[ROW_IDX:.*]] = cir.const #cir.int<0> : !s64i +// CIR: %[[COLUMN_IDX:.*]] = cir.const #cir.int<0> : !s64i +// CIR: %[[EXTREACT:.*]] = cir.matrix.extract %[[TMP_MATRIX]][%[[ROW_IDX]] : !s64i] [%[[COLUMN_IDX]] : !s64i] : !cir.matrix<4 x 4 x !s32i> +// CIR: cir.store {{.*}} %[[EXTREACT]], %[[ELEMENT_ADDR]] : !s32i, !cir.ptr<!s32i> + +// LLVM: %[[MATRIX_ADDR:.*]] = alloca [4 x <4 x i32>], align 4 +// LLVM: %[[ELEMENT_ADDR:.*]] = alloca i32, align 4 +// LLVM: %[[TMP_MATRIX:.*]] = load <16 x i32>, ptr %[[MATRIX_ADDR]], align 4 +// LLVM: %[[EXTRACT:.*]] = extractelement <16 x i32> %[[TMP_MATRIX]], i64 0 +// LLVM: store i32 %[[EXTRACT]], ptr %[[ELEMENT_ADDR]], align 4 `````````` </details> https://github.com/llvm/llvm-project/pull/235497 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
