llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

<details>
<summary>Changes</summary>

Implement multiplication op support between matrix and scalar types.

Issue https://github.com/llvm/llvm-project/issues/221772

---
Full diff: https://github.com/llvm/llvm-project/pull/230815.diff


3 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+8-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+12-3) 
- (modified) clang/test/CIR/CodeGen/matrix.cpp (+57) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6a7d8ca8f7fc9..b116f58813f58 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2859,12 +2859,12 @@ def CIR_SubOp
 // MulOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyIntOrVecOfIntType> {
+def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyIntOrVecOrMatrixOfIntType> {
   let summary = "Integer multiplication";
   let description = [{
     The `cir.mul` operation performs multiplication on integer operands. Both
     operands and the result must have the same integer or vector-of-integer
-    type.
+    or matrix-of-integer type.
 
     The optional `nsw` (no signed wrap) and `nuw` (no unsigned wrap) unit
     attributes indicate that the result is poison if signed or unsigned
@@ -2877,11 +2877,13 @@ def CIR_MulOp : CIR_BinaryOp<"mul", 
CIR_AnyIntOrVecOfIntType> {
     %1 = cir.mul nsw %a, %b : !s32i
     %2 = cir.mul nuw %a, %b : !u32i
     %3 = cir.mul %va, %vb : !cir.vector<4 x !s32i>
+    %4 = cir.mul %ma, %mb : !cir.matrix<3 x 3 x !s32i>
     ```
   }];
 
   let arguments = (ins
-    CIR_AnyIntOrVecOfIntType:$lhs, CIR_AnyIntOrVecOfIntType:$rhs,
+    CIR_AnyIntOrVecOrMatrixOfIntType:$lhs,
+    CIR_AnyIntOrVecOrMatrixOfIntType:$rhs,
     UnitProp:$no_signed_wrap,
     UnitProp:$no_unsigned_wrap
   );
@@ -2997,7 +2999,7 @@ def CIR_FSubOp : CIR_FPBinaryOp<"fsub"> {
   let description = [{
     The `cir.fsub` operation performs floating-point subtraction on its
     operands. Both operands and the result must have the same floating-point
-    scalar or vector-of-float type.
+    scalar or vector-of-float or matrix-of-float type..
 
     Example:
 
@@ -3005,6 +3007,7 @@ def CIR_FSubOp : CIR_FPBinaryOp<"fsub"> {
     %0 = cir.fsub %a, %b : !cir.float
     %1 = cir.fsub %a, %b : !cir.double
     %2 = cir.fsub %va, %vb : !cir.vector<4 x !cir.float>
+    %3 = cir.fsub %ma, %mb : !cir.matrix<3 x 3 x !cir.float>
     ```
   }];
 
@@ -3015,7 +3018,7 @@ def CIR_FSubOp : CIR_FPBinaryOp<"fsub"> {
 // FMulOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_FMulOp : CIR_FPBinaryOp<"fmul"> {
+def CIR_FMulOp : CIR_FPBinaryOp<"fmul", [], 
CIR_AnyFloatOrVecOrMatrixOfFloatType> {
   let summary = "Floating-point multiplication";
   let description = [{
     The `cir.fmul` operation performs floating-point multiplication on its
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 5209ca959de1e..da248331ea9b6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2252,9 +2252,18 @@ mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo 
&ops) {
     }
   }
   if (ops.fullType->isConstantMatrixType()) {
-    assert(!cir::MissingFeatures::matrixType());
-    cgf.cgm.errorNYI("ScalarExprEmitter::emitMul: matrix types");
-    return {};
+    if (isa<cir::MatrixType>(ops.lhs.getType()) &&
+        isa<cir::MatrixType>(ops.rhs.getType())) {
+      cgf.cgm.errorNYI("ScalarExprEmitter::emitMul: matrix matrix 
multiplication");
+      return {};
+    }
+
+    CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
+    auto [lhs, rhs] =
+        builder.splatMatrixOpOperandsIfNecessary(loc, ops.lhs, ops.rhs);
+    if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
+      return builder.createFMul(loc, lhs, rhs);
+    return builder.createMul(loc, lhs, rhs);
   }
   if (ops.compType->isUnsignedIntegerType() &&
       cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
diff --git a/clang/test/CIR/CodeGen/matrix.cpp 
b/clang/test/CIR/CodeGen/matrix.cpp
index 19d87a8829aab..b5a4dfe3e5391 100644
--- a/clang/test/CIR/CodeGen/matrix.cpp
+++ b/clang/test/CIR/CodeGen/matrix.cpp
@@ -8,6 +8,7 @@
 typedef float matrix3x3 __attribute__((matrix_type(3, 3)));
 typedef float matrix3x2 __attribute__((matrix_type(3, 2)));
 typedef float matrix2x3 __attribute__((matrix_type(2, 3)));
+typedef int matrixi3x3 __attribute__((matrix_type(3, 3)));
 
 matrix3x3 a;
 
@@ -213,3 +214,59 @@ void matrix_subscript_expr_non_const_indices() {
 
 // LLVM: %[[ELEM:.*]] = extractelement <9 x float> %[[TMP_MATRIX]], i64 
%[[FLAT_IDX]]
 // LLVM: store float %[[ELEM]], ptr %[[B_ADDR]], align 4
+
+void fp_matrix_scalar_mul() {
+  matrix3x3 matrix;
+  float scalar = 3.0f;
+  matrix3x3 result = matrix * scalar;
+}
+
+// CIR: %[[MATRIX_ADDR:.*]] = cir.alloca "matrix" {{.*}} : 
!cir.ptr<!cir.matrix<3 x 3 x !cir.float>>
+// CIR: %[[SCALAR_ADDR:.*]] = cir.alloca "scalar" {{.*}} init : 
!cir.ptr<!cir.float>
+// CIR: %[[RESULT_ADDR:.*]] = cir.alloca "result" {{.*}} init : 
!cir.ptr<!cir.matrix<3 x 3 x !cir.float>>
+// CIR: %[[CONST_3:.*]] = cir.const #cir.fp<3.000000e+00> : !cir.float
+// CIR: cir.store {{.*}} %[[CONST_3]], %[[SCALAR_ADDR]] : !cir.float, 
!cir.ptr<!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: %[[TMP_SCALAR:.*]] = cir.load {{.*}} %[[SCALAR_ADDR]] : 
!cir.ptr<!cir.float>, !cir.float
+// CIR: %[[SPLAT_SCALAR:.*]] = cir.vec.splat %[[TMP_SCALAR]] : !cir.float, 
!cir.matrix<3 x 3 x !cir.float>
+// CIR: %[[RESULT:.*]] = cir.fmul %[[TMP_MATRIX]], %[[SPLAT_SCALAR]] : 
!cir.matrix<3 x 3 x !cir.float>
+// CIR: cir.store {{.*}} %[[RESULT]], %[[RESULT_ADDR]] : !cir.matrix<3 x 3 x 
!cir.float>, !cir.ptr<!cir.matrix<3 x 3 x !cir.float>>
+
+// LLVM: %[[MATRIX_ADDR:.*]] = alloca [9 x float], align 4
+// LLVM: %[[SCALAR_ADDR:.*]] = alloca float, align 4
+// LLVM: %[[RESULT_ADDR:.*]] = alloca [9 x float], align 4
+// LLVM: store float 3.000000e+00, ptr %[[SCALAR_ADDR]], align 4
+// LLVM: %[[TMP_MATRIX:.*]] = load <9 x float>, ptr %[[MATRIX_ADDR]], align 4
+// LLVM: %[[TMP_SCALAR:.*]] = load float, ptr %[[SCALAR_ADDR]], align 4
+// LLVM: %[[SPLAT_SCALAR_INSERT:.*]] = insertelement <9 x float> poison, float 
%[[TMP_SCALAR]], i64 0
+// LLVM: %[[SPLAT_SCALAR:.*]] = shufflevector <9 x float> 
%[[SPLAT_SCALAR_INSERT]], <9 x float> poison, <9 x i32> zeroinitializer
+// LLVM: %[[RESULT:.*]] = fmul  <9 x float> %[[TMP_MATRIX]], %[[SPLAT_SCALAR]]
+// LLVM: store <9 x float> %[[RESULT]], ptr %[[RESULT_ADDR]], align 4
+
+void int_matrix_scalar_mul() {
+  matrixi3x3 matrix;
+  int scalar = 3;
+  matrixi3x3 result = matrix * scalar;
+}
+
+// CIR: %[[MATRIX_ADDR:.*]] = cir.alloca "matrix" {{.*}} : 
!cir.ptr<!cir.matrix<3 x 3 x !s32i>>
+// CIR: %[[SCALAR_ADDR:.*]] = cir.alloca "scalar" {{.*}} init : !cir.ptr<!s32i>
+// CIR: %[[RESULT_ADDR:.*]] = cir.alloca "result" {{.*}} init : 
!cir.ptr<!cir.matrix<3 x 3 x !s32i>>
+// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i
+// CIR: cir.store {{.*}} %[[CONST_3]], %[[SCALAR_ADDR]] : !s32i, 
!cir.ptr<!s32i>
+// CIR: %[[TMP_MATRIX:.*]] = cir.load {{.*}} %[[MATRIX_ADDR]] : 
!cir.ptr<!cir.matrix<3 x 3 x !s32i>>, !cir.matrix<3 x 3 x !s32i>
+// CIR: %[[TMP_SCALAR:.*]] = cir.load {{.*}} %[[SCALAR_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR: %[[SPLAT_SCALAR:.*]] = cir.vec.splat %[[TMP_SCALAR]] : !s32i, 
!cir.matrix<3 x 3 x !s32i>
+// CIR: %[[RESULT:.*]] = cir.mul %[[TMP_MATRIX]], %[[SPLAT_SCALAR]] : 
!cir.matrix<3 x 3 x !s32i>
+// CIR: cir.store {{.*}} %[[RESULT]], %[[RESULT_ADDR]] : !cir.matrix<3 x 3 x 
!s32i>, !cir.ptr<!cir.matrix<3 x 3 x !s32i>>
+
+// LLVM: %[[MATRIX_ADDR:.*]] = alloca [9 x i32], align 4
+// LLVM: %[[SCALAR_ADDR:.*]] = alloca i32, align 4
+// LLVM: %[[RESULT_ADDR:.*]] = alloca [9 x i32], align 4
+// LLVM: store i32 3, ptr %[[SCALAR_ADDR]], align 4
+// LLVM: %[[TMP_MATRIX:.*]] = load <9 x i32>, ptr %[[MATRIX_ADDR]], align 4
+// LLVM: %[[TMP_SCALAR:.*]] = load i32, ptr %[[SCALAR_ADDR]], align 4
+// LLVM: %[[SPLAT_SCALAR_INSERT:.*]] = insertelement <9 x i32> poison, i32 
%[[TMP_SCALAR]], i64 0
+// LLVM: %[[SPLAT_SCALAR:.*]] = shufflevector <9 x i32> 
%[[SPLAT_SCALAR_INSERT]], <9 x i32> poison, <9 x i32> zeroinitializer
+// LLVM: %[[RESULT:.*]] = mul <9 x i32> %[[TMP_MATRIX]], %[[SPLAT_SCALAR]]
+// LLVM: store <9 x i32> %[[RESULT]], ptr %[[RESULT_ADDR]], align 4

``````````

</details>


https://github.com/llvm/llvm-project/pull/230815
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to