https://github.com/farzonl created 
https://github.com/llvm/llvm-project/pull/216791

fixes #216786

This change add matric cmp support similar to that done for vector types.

>From 37e996a38e057bcff37d8f96226e9bde3665b199 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <[email protected]>
Date: Mon, 17 Aug 2026 13:38:45 -0400
Subject: [PATCH] [HLSL][Matrix] Add comparison operator support

fixes #216786

This change add matric cmp support similar to that done for vector
types.
---
 clang/include/clang/Sema/Sema.h               |  3 +
 clang/lib/AST/Type.cpp                        |  2 +
 clang/lib/CodeGen/CGExprScalar.cpp            |  3 +
 clang/lib/Sema/SemaExpr.cpp                   | 33 ++++++++
 .../MatrixComparisonOperators.hlsl            | 83 +++++++++++++++++++
 .../Operators/matrix-comparisons.hlsl         | 54 ++++++++++++
 6 files changed, 178 insertions(+)
 create mode 100644 
clang/test/CodeGenHLSL/BasicFeatures/MatrixComparisonOperators.hlsl
 create mode 100644 clang/test/SemaHLSL/Operators/matrix-comparisons.hlsl

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d931e70cb2342..32949ca1d6998 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7886,6 +7886,9 @@ class Sema final : public SemaBase {
   QualType CheckSizelessVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
                                               SourceLocation Loc,
                                               BinaryOperatorKind Opc);
+  QualType CheckMatrixCompareOperands(ExprResult &LHS, ExprResult &RHS,
+                                      SourceLocation Loc,
+                                      BinaryOperatorKind Opc);
   QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
                                       SourceLocation Loc,
                                       BinaryOperatorKind Opc);
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 5069b587c1f8b..8b10b0347329e 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2340,6 +2340,8 @@ bool Type::isSignedIntegerOrEnumerationType() const {
 bool Type::hasSignedIntegerRepresentation() const {
   if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isSignedIntegerOrEnumerationType();
+  if (const auto *MT = dyn_cast<MatrixType>(CanonicalType))
+    return MT->getElementType()->isSignedIntegerOrEnumerationType();
 
   if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
     switch (BT->getKind()) {
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 67014904ffb37..342e3113b1121 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -5368,6 +5368,9 @@ Value *ScalarExprEmitter::EmitCompare(const 
BinaryOperator *E,
     if (LHSTy->isVectorType() || LHSTy->isSveVLSBuiltinType())
       return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext");
 
+    if (LHSTy->isMatrixType())
+      return Result;
+
   } else {
     // Complex Comparison: can only be an equality comparison.
     CodeGenFunction::ComplexPairTy LHS, RHS;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0908841dca8bf..021024a6bfd93 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12963,6 +12963,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, 
ExprResult &RHS,
     CheckPtrComparisonWithNullChar(RHS, LHS);
   }
 
+  if (getLangOpts().HLSL && (LHS.get()->getType()->isConstantMatrixType() ||
+                             RHS.get()->getType()->isConstantMatrixType()))
+    return CheckMatrixCompareOperands(LHS, RHS, Loc, Opc);
+
   // Handle vector comparisons separately.
   if (LHS.get()->getType()->isVectorType() ||
       RHS.get()->getType()->isVectorType())
@@ -13538,6 +13542,35 @@ QualType Sema::CheckVectorCompareOperands(ExprResult 
&LHS, ExprResult &RHS,
   return GetSignedVectorType(vType);
 }
 
+QualType Sema::CheckMatrixCompareOperands(ExprResult &LHS, ExprResult &RHS,
+                                          SourceLocation Loc,
+                                          BinaryOperatorKind Opc) {
+  assert(getLangOpts().HLSL && "matrix comparisons are only supported in 
HLSL");
+  assert(Opc != BO_Cmp && "three-way comparisons are not supported in HLSL");
+
+  QualType MatrixTy =
+      CheckMatrixElementwiseOperands(LHS, RHS, Loc, /*IsCompAssign=*/false);
+  if (MatrixTy.isNull())
+    return QualType();
+
+  if (!LHS.get()->getType()->isMatrixType()) {
+    LHS = prepareMatrixSplat(MatrixTy, LHS.get());
+    if (LHS.isInvalid())
+      return QualType();
+    LHS = ImpCastExprToType(LHS.get(), MatrixTy, CK_HLSLAggregateSplatCast);
+  }
+  if (!RHS.get()->getType()->isMatrixType()) {
+    RHS = prepareMatrixSplat(MatrixTy, RHS.get());
+    if (RHS.isInvalid())
+      return QualType();
+    RHS = ImpCastExprToType(RHS.get(), MatrixTy, CK_HLSLAggregateSplatCast);
+  }
+
+  const auto *MT = MatrixTy->castAs<ConstantMatrixType>();
+  return Context.getConstantMatrixType(Context.BoolTy, MT->getNumRows(),
+                                       MT->getNumColumns());
+}
+
 QualType Sema::CheckSizelessVectorCompareOperands(ExprResult &LHS,
                                                   ExprResult &RHS,
                                                   SourceLocation Loc,
diff --git 
a/clang/test/CodeGenHLSL/BasicFeatures/MatrixComparisonOperators.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixComparisonOperators.hlsl
new file mode 100644
index 0000000000000..94ea87166d3b0
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixComparisonOperators.hlsl
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple 
dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | 
FileCheck %s
+
+// ==================================================================
+// Float Matrix vs Float Matrix
+// ==================================================================
+
+// CHECK-LABEL: define {{.*}}test_float_lt
+// CHECK: fcmp {{.*}}olt <4 x float>
+bool2x2 test_float_lt(float2x2 A, float2x2 B) {
+  return A < B;
+}
+
+// CHECK-LABEL: define {{.*}}test_float_gt
+// CHECK: fcmp {{.*}}ogt <9 x float>
+bool3x3 test_float_gt(float3x3 A, float3x3 B) {
+  return A > B;
+}
+
+// CHECK-LABEL: define {{.*}}test_float_le
+// CHECK: fcmp {{.*}}ole <16 x float>
+bool4x4 test_float_le(float4x4 A, float4x4 B) {
+  return A <= B;
+}
+
+// CHECK-LABEL: define {{.*}}test_float_ge
+// CHECK: fcmp {{.*}}oge <6 x float>
+bool2x3 test_float_ge(float2x3 A, float2x3 B) {
+  return A >= B;
+}
+
+// CHECK-LABEL: define {{.*}}test_float_eq
+// CHECK: fcmp {{.*}}oeq <4 x float>
+bool2x2 test_float_eq(float2x2 A, float2x2 B) {
+  return A == B;
+}
+
+// CHECK-LABEL: define {{.*}}test_float_neq
+// CHECK: fcmp {{.*}}une <4 x float>
+bool2x2 test_float_neq(float2x2 A, float2x2 B) {
+  return A != B;
+}
+
+// ==================================================================
+// Integer Matrix vs Integer Matrix
+// ==================================================================
+
+// CHECK-LABEL: define {{.*}}test_int_lt
+// CHECK: icmp slt <4 x i32>
+bool2x2 test_int_lt(int2x2 A, int2x2 B) {
+  return A < B;
+}
+
+// CHECK-LABEL: define {{.*}}test_int_ge
+// CHECK: icmp sge <4 x i32>
+bool2x2 test_int_ge(int2x2 A, int2x2 B) {
+  return A >= B;
+}
+
+// CHECK-LABEL: define {{.*}}test_int_eq
+// CHECK: icmp eq <4 x i32>
+bool2x2 test_int_eq(int2x2 A, int2x2 B) {
+  return A == B;
+}
+
+// ==================================================================
+// Matrix vs Scalar (Broadcast)
+// ==================================================================
+
+// CHECK-LABEL: define {{.*}}test_scalar_lt
+// CHECK: [[SPLAT:%.*]] = insertelement <4 x float> poison, float {{%.*}}, i64 0
+// CHECK: [[B_MAT:%.*]] = shufflevector <4 x float> [[SPLAT]], <4 x float> 
poison, <4 x i32> zeroinitializer
+// CHECK: fcmp {{.*}}olt <4 x float> {{%.*}}, [[B_MAT]]
+bool2x2 test_scalar_lt(float2x2 A, float B) {
+  return A < B;
+}
+
+// CHECK-LABEL: define {{.*}}test_scalar_neq
+// CHECK: [[SPLAT:%.*]] = insertelement <4 x float> poison, float {{%.*}}, i64 0
+// CHECK: [[B_MAT:%.*]] = shufflevector <4 x float> [[SPLAT]], <4 x float> 
poison, <4 x i32> zeroinitializer
+// CHECK: fcmp {{.*}}une <4 x float> {{%.*}}, [[B_MAT]]
+bool2x2 test_scalar_neq(float2x2 A, float B) {
+  return A != B;
+}
diff --git a/clang/test/SemaHLSL/Operators/matrix-comparisons.hlsl 
b/clang/test/SemaHLSL/Operators/matrix-comparisons.hlsl
new file mode 100644
index 0000000000000..e2e67bce4fd52
--- /dev/null
+++ b/clang/test/SemaHLSL/Operators/matrix-comparisons.hlsl
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.3-library -Wno-implicit-int-float-conversion %s -ast-dump 
-ast-dump-filter=test | FileCheck %s
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.3-library -Wno-implicit-int-float-conversion %s -DERRORS 
-verify
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_matrix_matrix 'bool2x2 (float2x2, 
float2x2)'
+// CHECK: BinaryOperator {{.*}} 'matrix<bool, 2, 2>' '<'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue 
ParmVar {{.*}} 'a'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue 
ParmVar {{.*}} 'b'
+bool2x2 test_matrix_matrix(float2x2 a, float2x2 b) {
+  return a < b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_matrix_scalar 'bool2x2 (float2x2, 
int)'
+// CHECK: BinaryOperator {{.*}} 'matrix<bool, 2, 2>' '=='
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue 
ParmVar {{.*}} 'a'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' 
<HLSLAggregateSplatCast>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'b'
+bool2x2 test_matrix_scalar(float2x2 a, int b) {
+  return a == b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_scalar_matrix 'bool2x2 (int, 
float2x2)'
+// CHECK: BinaryOperator {{.*}} 'matrix<bool, 2, 2>' '>='
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' 
<HLSLAggregateSplatCast>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'a'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float2x2':'matrix<float, 2, 2>' lvalue 
ParmVar {{.*}} 'b'
+bool2x2 test_scalar_matrix(int a, float2x2 b) {
+  return a >= b;
+}
+
+#ifdef ERRORS
+
+bool2x2 test_dimension_mismatch(float2x2 a, float3x3 b) {
+  return a != b; // expected-error {{invalid operands to binary expression 
('float2x2' (aka 'matrix<float, 2, 2>') and 'float3x3' (aka 'matrix<float, 3, 
3>'))}}
+}
+
+bool2x2 test_element_mismatch(float2x2 a, int2x2 b) {
+  return a < b; // expected-error {{invalid operands to binary expression 
('float2x2' (aka 'matrix<float, 2, 2>') and 'int2x2' (aka 'matrix<int, 2, 
2>'))}}
+}
+
+struct Unsupported {};
+
+bool2x2 test_unsupported_operand(float2x2 a, Unsupported b) {
+  return a > b; // expected-error {{invalid operands to binary expression 
('float2x2' (aka 'matrix<float, 2, 2>') and 'Unsupported')}} expected-error 
{{cannot initialize a value of type 'float' with an rvalue of type 
'Unsupported'}}
+}
+
+#endif

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

Reply via email to