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

Reply via email to