[clang] [CIR] Implement matrix scalar division support (PR #230808)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 10 08:54:57 PDT 2026
https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/230808
Implement division op support between matrix and scalar types.
Issue https://github.com/llvm/llvm-project/issues/221772
>From 7946a686914dd3861feaa4b119f77f90e53a633b Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sat, 10 Oct 2026 16:07:36 +0200
Subject: [PATCH] [CIR] Implement matrix scalar division support
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 10 ++--
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 18 +++++--
clang/test/CIR/CodeGen/matrix.cpp | 57 ++++++++++++++++++++
3 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6a7d8ca8f7fc9..b912e066fd398 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2897,12 +2897,12 @@ def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyIntOrVecOfIntType> {
// DivOp
//===----------------------------------------------------------------------===//
-def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyIntOrVecOfIntType> {
+def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyIntOrVecOrMatrixOfIntType> {
let summary = "Integer division";
let description = [{
The `cir.div` operation performs division on integer operands. Both
operands and the result must have the same integer or vector-of-integer
- type.
+ or matrix-of-integer type.
Example:
@@ -2910,6 +2910,7 @@ def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyIntOrVecOfIntType> {
%0 = cir.div %a, %b : !s32i
%1 = cir.div %a, %b : !u32i
%2 = cir.div %va, %vb : !cir.vector<4 x !s32i>
+ %3 = cir.div %ma, %mb : !cir.matrix<3 x 3 x !s32i>
```
}];
}
@@ -3038,12 +3039,12 @@ def CIR_FMulOp : CIR_FPBinaryOp<"fmul"> {
// FDivOp
//===----------------------------------------------------------------------===//
-def CIR_FDivOp : CIR_FPBinaryOp<"fdiv"> {
+def CIR_FDivOp : CIR_FPBinaryOp<"fdiv", [], CIR_AnyFloatOrVecOrMatrixOfFloatType> {
let summary = "Floating-point division";
let description = [{
The `cir.fdiv` operation performs floating-point division on its operands.
Both operands and the result must have the same floating-point scalar or
- vector-of-float type.
+ ector-of-float or matrix-of-float type.
Example:
@@ -3051,6 +3052,7 @@ def CIR_FDivOp : CIR_FPBinaryOp<"fdiv"> {
%0 = cir.fdiv %a, %b : !cir.float
%1 = cir.fdiv %a, %b : !cir.double
%2 = cir.fdiv %va, %vb : !cir.vector<4 x !cir.float>
+ %3 = cir.fdiv %ma, %mb : !cir.matrix<3 x 3 x !cir.float>
```
}];
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 5209ca959de1e..eaca5b7c1fad8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2280,9 +2280,21 @@ mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {
}
if (ops.fullType->isConstantMatrixType()) {
- assert(!cir::MissingFeatures::matrixType());
- cgf.cgm.errorNYI("ScalarExprEmitter::emitDiv: matrix types");
- return {};
+ auto *bo = cast<BinaryOperator>(ops.e);
+ (void)bo;
+ assert(
+ isa<ConstantMatrixType>(bo->getLHS()->getType().getCanonicalType()) &&
+ "first operand must be a matrix");
+ assert(bo->getRHS()->getType().getCanonicalType()->isArithmeticType() &&
+ "second operand must be an arithmetic type");
+
+ auto [lhs, rhs] =
+ builder.splatMatrixOpOperandsIfNecessary(loc, ops.lhs, ops.rhs);
+
+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
+ if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
+ return builder.createFDiv(loc, lhs, rhs);
+ return builder.createDiv(loc, lhs, rhs);
}
if (ops.isFixedPointOp())
diff --git a/clang/test/CIR/CodeGen/matrix.cpp b/clang/test/CIR/CodeGen/matrix.cpp
index 19d87a8829aab..4b485ca0cb822 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_div() {
+ 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.fdiv %[[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:.*]] = fdiv <9 x float> %[[TMP_MATRIX]], %[[SPLAT_SCALAR]]
+// LLVM: store <9 x float> %[[RESULT]], ptr %[[RESULT_ADDR]], align 4
+
+void int_matrix_scalar_div() {
+ 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.div %[[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:.*]] = sdiv <9 x i32> %[[TMP_MATRIX]], %[[SPLAT_SCALAR]]
+// LLVM: store <9 x i32> %[[RESULT]], ptr %[[RESULT_ADDR]], align 4
More information about the cfe-commits
mailing list