https://github.com/AmrDeveloper updated 
https://github.com/llvm/llvm-project/pull/146129

>From 964a930b9f96423d04155b9972bfd8540c59d911 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Fri, 27 Jun 2025 20:10:48 +0200
Subject: [PATCH 1/4] [CIR] Implement NotEqualOp for ComplexType

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 25 +++++++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  5 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 38 ++++++++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   | 10 +++
 clang/test/CIR/CodeGen/complex.cpp            | 72 +++++++++++++++++++
 5 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4daff74cbae5a..b58ebd2dfe509 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2481,6 +2481,31 @@ def ComplexEqualOp : CIR_Op<"complex.eq", [Pure, 
SameTypeOperands]> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// ComplexNotEqualOp
+//===----------------------------------------------------------------------===//
+
+def ComplexNotEqualOp : CIR_Op<"complex.neq", [Pure, SameTypeOperands]> {
+
+  let summary = "Computes whether two complex values are not equal";
+  let description = [{
+   The `complex.equal` op takes two complex numbers and returns whether
+   they are not equal.
+
+    ```mlir
+    %r = cir.complex.neq %a, %b : !cir.complex<!cir.float>
+    ```
+  }];
+
+  let results = (outs CIR_BoolType:$result);
+  let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs);
+
+  let assemblyFormat = [{
+    $lhs `,` $rhs
+    `:` qualified(type($lhs)) attr-dict
+  }];
+}
+
 
//===----------------------------------------------------------------------===//
 // Assume Operations
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 955bb5ffc4395..0ba653add826f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -905,9 +905,8 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
         result =
             builder.create<cir::ComplexEqualOp>(loc, boInfo.lhs, boInfo.rhs);
       } else {
-        assert(!cir::MissingFeatures::complexType());
-        cgf.cgm.errorNYI(loc, "complex not equal");
-        result = builder.getBool(false, loc);
+        result =
+            builder.create<cir::ComplexNotEqualOp>(loc, boInfo.lhs, 
boInfo.rhs);
       }
     }
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 1034b8780c03c..598283eeaf518 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1903,6 +1903,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMComplexCreateOpLowering,
                CIRToLLVMComplexEqualOpLowering,
                CIRToLLVMComplexImagOpLowering,
+               CIRToLLVMComplexNotEqualOpLowering,
                CIRToLLVMComplexRealOpLowering,
                CIRToLLVMConstantOpLowering,
                CIRToLLVMExpectOpLowering,
@@ -2282,6 +2283,43 @@ mlir::LogicalResult 
CIRToLLVMComplexEqualOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMComplexNotEqualOpLowering::matchAndRewrite(
+    cir::ComplexNotEqualOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Value lhs = adaptor.getLhs();
+  mlir::Value rhs = adaptor.getRhs();
+
+  auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
+  mlir::Type complexElemTy =
+      getTypeConverter()->convertType(complexType.getElementType());
+
+  mlir::Location loc = op.getLoc();
+  auto lhsReal =
+      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
+  auto lhsImag =
+      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
+  auto rhsReal =
+      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
+  auto rhsImag =
+      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
+
+  if (complexElemTy.isInteger()) {
+    auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
+        loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
+    auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
+        loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
+    rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp);
+    return mlir::success();
+  }
+
+  auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
+      loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
+  auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
+      loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
+  rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp);
+  return mlir::success();
+}
+
 std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
   return std::make_unique<ConvertCIRToLLVMPass>();
 }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index 25cf218cf8b6c..5cd1d09b88c00 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -473,6 +473,16 @@ class CIRToLLVMComplexEqualOpLowering
                   mlir::ConversionPatternRewriter &) const override;
 };
 
+class CIRToLLVMComplexNotEqualOpLowering
+    : public mlir::OpConversionPattern<cir::ComplexNotEqualOp> {
+public:
+  using mlir::OpConversionPattern<cir::ComplexNotEqualOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(cir::ComplexNotEqualOp op, OpAdaptor,
+                  mlir::ConversionPatternRewriter &) const override;
+};
+
 } // namespace direct
 } // namespace cir
 
diff --git a/clang/test/CIR/CodeGen/complex.cpp 
b/clang/test/CIR/CodeGen/complex.cpp
index 1e9ce0e29fd46..b8a0b99c10f0b 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -442,3 +442,75 @@ bool foo19(double _Complex a, double _Complex b) {
 // OGCG: %[[CMP_IMAG:.*]] = fcmp oeq double %[[A_IMAG]], %[[B_IMAG]]
 // OGCG: %[[RESULT:.*]] = and i1 %[[CMP_REAL]], %[[CMP_IMAG]]
 
+
+bool foo20(int _Complex a, int _Complex b) {
+  return a != b;
+}
+
+// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : 
!cir.complex<!s32i>
+
+// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4
+// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4
+// LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 0
+// LLVM: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 1
+// LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 0
+// LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 1
+// LLVM: %[[CMP_REAL:.*]] = icmp ne i32 %[[A_REAL]], %[[B_REAL]]
+// LLVM: %[[CMP_IMAG:.*]] = icmp ne i32 %[[A_IMAG]], %[[B_IMAG]]
+// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]
+
+// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_A]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_A]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_B]], i32 0, i32 0
+// OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_B]], i32 0, i32 1
+// OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4
+// OGCG: %[[CMP_REAL:.*]] = icmp ne i32 %[[A_REAL]], %[[B_REAL]]
+// OGCG: %[[CMP_IMAG:.*]] = icmp ne i32 %[[A_IMAG]], %[[B_IMAG]]
+// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]
+
+bool foo21(double _Complex a, double _Complex b) {
+  return a != b;
+}
+
+// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
+// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
+// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : 
!cir.complex<!cir.double>
+
+// LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8
+// LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8
+// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 0
+// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 1
+// LLVM: %[[B_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 0
+// LLVM: %[[B_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 1
+// LLVM: %[[CMP_REAL:.*]] = fcmp une double %[[A_REAL]], %[[B_REAL]]
+// LLVM: %[[CMP_IMAG:.*]] = fcmp une double %[[A_IMAG]], %[[B_IMAG]]
+// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]
+
+// OGCG: %[[COMPLEX_A:.*]] = alloca { double, double }, align 8
+// OGCG: %[[COMPLEX_B:.*]] = alloca { double, double }, align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_A]], i32 0, i32 0
+// OGCG: store double {{.*}}, ptr %[[A_REAL_PTR]], align 8
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_A]], i32 0, i32 1
+// OGCG: store double {{.*}}, ptr %[[A_IMAG_PTR]], align 8
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_B]], i32 0, i32 0
+// OGCG: store double {{.*}}, ptr %[[B_REAL_PTR]], align 8
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_B]], i32 0, i32 1
+// OGCG: store double {{.*}}, ptr %[[B_IMAG_PTR]], align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_A]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_A]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_B]], i32 0, i32 0
+// OGCG: %[[B_REAL:.*]] = load double, ptr %[[B_REAL_PTR]], align 8
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, 
ptr %[[COMPLEX_B]], i32 0, i32 1
+// OGCG: %[[B_IMAG:.*]] = load double, ptr %[[B_IMAG_PTR]], align 8
+// OGCG: %[[CMP_REAL:.*]] = fcmp une double %[[A_REAL]], %[[B_REAL]]
+// OGCG: %[[CMP_IMAG:.*]] = fcmp une double %[[A_IMAG]], %[[B_IMAG]]
+// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]]

>From f6097ef2cf5a8c7fa289ef7a08996786c1ea29a1 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Fri, 27 Jun 2025 20:51:02 +0200
Subject: [PATCH 2/4] Fix op description

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index b58ebd2dfe509..553d7bcc161c5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2464,7 +2464,7 @@ def ComplexEqualOp : CIR_Op<"complex.eq", [Pure, 
SameTypeOperands]> {
 
   let summary = "Computes whether two complex values are equal";
   let description = [{
-   The `complex.equal` op takes two complex numbers and returns whether
+   The `cir.complex.eq` op takes two complex numbers and returns whether
    they are equal.
 
     ```mlir
@@ -2489,7 +2489,7 @@ def ComplexNotEqualOp : CIR_Op<"complex.neq", [Pure, 
SameTypeOperands]> {
 
   let summary = "Computes whether two complex values are not equal";
   let description = [{
-   The `complex.equal` op takes two complex numbers and returns whether
+   The `cir.complex.neq` op takes two complex numbers and returns whether
    they are not equal.
 
     ```mlir

>From e8486dbe675b48bfa64d5e14f061ca1b49972121 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Sat, 28 Jun 2025 09:22:59 +0200
Subject: [PATCH 3/4] Replace ComplexEqual and ComplexNotEqual by CmpOp

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  50 ------
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  10 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 147 ++++++++----------
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  20 ---
 clang/test/CIR/CodeGen/complex.cpp            |   9 +-
 5 files changed, 73 insertions(+), 163 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 553d7bcc161c5..7e45fa464f9d4 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2456,56 +2456,6 @@ def ComplexImagOp : CIR_Op<"complex.imag", [Pure]> {
   let hasFolder = 1;
 }
 
-//===----------------------------------------------------------------------===//
-// ComplexEqualOp
-//===----------------------------------------------------------------------===//
-
-def ComplexEqualOp : CIR_Op<"complex.eq", [Pure, SameTypeOperands]> {
-
-  let summary = "Computes whether two complex values are equal";
-  let description = [{
-   The `cir.complex.eq` op takes two complex numbers and returns whether
-   they are equal.
-
-    ```mlir
-    %r = cir.complex.eq %a, %b : !cir.complex<!cir.float>
-    ```
-  }];
-
-  let results = (outs CIR_BoolType:$result);
-  let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs);
-
-  let assemblyFormat = [{
-    $lhs `,` $rhs
-    `:` qualified(type($lhs)) attr-dict
-  }];
-}
-
-//===----------------------------------------------------------------------===//
-// ComplexNotEqualOp
-//===----------------------------------------------------------------------===//
-
-def ComplexNotEqualOp : CIR_Op<"complex.neq", [Pure, SameTypeOperands]> {
-
-  let summary = "Computes whether two complex values are not equal";
-  let description = [{
-   The `cir.complex.neq` op takes two complex numbers and returns whether
-   they are not equal.
-
-    ```mlir
-    %r = cir.complex.neq %a, %b : !cir.complex<!cir.float>
-    ```
-  }];
-
-  let results = (outs CIR_BoolType:$result);
-  let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs);
-
-  let assemblyFormat = [{
-    $lhs `,` $rhs
-    `:` qualified(type($lhs)) attr-dict
-  }];
-}
-
 
//===----------------------------------------------------------------------===//
 // Assume Operations
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 0ba653add826f..02f62b863a190 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -901,13 +901,9 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
       assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
 
       BinOpInfo boInfo = emitBinOps(e);
-      if (e->getOpcode() == BO_EQ) {
-        result =
-            builder.create<cir::ComplexEqualOp>(loc, boInfo.lhs, boInfo.rhs);
-      } else {
-        result =
-            builder.create<cir::ComplexNotEqualOp>(loc, boInfo.lhs, 
boInfo.rhs);
-      }
+      cir::CmpOpKind opKind =
+          e->getOpcode() == BO_EQ ? cir::CmpOpKind::eq : cir::CmpOpKind::ne;
+      result = builder.create<cir::CmpOp>(loc, opKind, boInfo.lhs, boInfo.rhs);
     }
 
     return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 598283eeaf518..bdc7492d48211 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1586,7 +1586,6 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
   assert(!cir::MissingFeatures::dataMemberType());
   assert(!cir::MissingFeatures::methodType());
 
-  // Lower to LLVM comparison op.
   if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
     bool isSigned = mlir::isa<cir::IntType>(type)
                         ? mlir::cast<cir::IntType>(type).isSigned()
@@ -1595,22 +1594,82 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
         convertCmpKindToICmpPredicate(cmpOp.getKind(), isSigned);
     rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
         cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
-  } else if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
+    return mlir::success();
+  }
+
+  if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
     mlir::LLVM::ICmpPredicate kind =
         convertCmpKindToICmpPredicate(cmpOp.getKind(),
                                       /* isSigned=*/false);
     rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
         cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
-  } else if (mlir::isa<cir::FPTypeInterface>(type)) {
+    return mlir::success();
+  }
+
+  if (mlir::isa<cir::FPTypeInterface>(type)) {
     mlir::LLVM::FCmpPredicate kind =
         convertCmpKindToFCmpPredicate(cmpOp.getKind());
     rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
         cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
-  } else {
-    return cmpOp.emitError() << "unsupported type for CmpOp: " << type;
+    return mlir::success();
   }
 
-  return mlir::success();
+  if (mlir::isa<cir::ComplexType>(type)) {
+    mlir::Value lhs = adaptor.getLhs();
+    mlir::Value rhs = adaptor.getRhs();
+    mlir::Location loc = cmpOp.getLoc();
+
+    auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
+    mlir::Type complexElemTy =
+        getTypeConverter()->convertType(complexType.getElementType());
+
+    auto lhsReal =
+        rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 
0);
+    auto lhsImag =
+        rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 
1);
+    auto rhsReal =
+        rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 
0);
+    auto rhsImag =
+        rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 
1);
+
+    if (cmpOp.getKind() == cir::CmpOpKind::eq) {
+      if (complexElemTy.isInteger()) {
+        auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
+            loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
+        auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
+            loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
+        rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, 
imagCmp);
+        return mlir::success();
+      }
+
+      auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
+          loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
+      auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
+          loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
+      rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
+      return mlir::success();
+    }
+
+    if (cmpOp.getKind() == cir::CmpOpKind::ne) {
+      if (complexElemTy.isInteger()) {
+        auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
+            loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
+        auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
+            loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
+        rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
+        return mlir::success();
+      }
+
+      auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
+          loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
+      auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
+          loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
+      rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
+      return mlir::success();
+    }
+  }
+
+  return cmpOp.emitError() << "unsupported type for CmpOp: " << type;
 }
 
 mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
@@ -1901,9 +1960,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMCallOpLowering,
                CIRToLLVMCmpOpLowering,
                CIRToLLVMComplexCreateOpLowering,
-               CIRToLLVMComplexEqualOpLowering,
                CIRToLLVMComplexImagOpLowering,
-               CIRToLLVMComplexNotEqualOpLowering,
                CIRToLLVMComplexRealOpLowering,
                CIRToLLVMConstantOpLowering,
                CIRToLLVMExpectOpLowering,
@@ -2246,80 +2303,6 @@ mlir::LogicalResult 
CIRToLLVMComplexImagOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
-mlir::LogicalResult CIRToLLVMComplexEqualOpLowering::matchAndRewrite(
-    cir::ComplexEqualOp op, OpAdaptor adaptor,
-    mlir::ConversionPatternRewriter &rewriter) const {
-  mlir::Value lhs = adaptor.getLhs();
-  mlir::Value rhs = adaptor.getRhs();
-
-  auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
-  mlir::Type complexElemTy =
-      getTypeConverter()->convertType(complexType.getElementType());
-
-  mlir::Location loc = op.getLoc();
-  auto lhsReal =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
-  auto lhsImag =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
-  auto rhsReal =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
-  auto rhsImag =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
-
-  if (complexElemTy.isInteger()) {
-    auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
-        loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
-    auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
-        loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
-    rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, realCmp, imagCmp);
-    return mlir::success();
-  }
-
-  auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
-      loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
-  auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
-      loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
-  rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, realCmp, imagCmp);
-  return mlir::success();
-}
-
-mlir::LogicalResult CIRToLLVMComplexNotEqualOpLowering::matchAndRewrite(
-    cir::ComplexNotEqualOp op, OpAdaptor adaptor,
-    mlir::ConversionPatternRewriter &rewriter) const {
-  mlir::Value lhs = adaptor.getLhs();
-  mlir::Value rhs = adaptor.getRhs();
-
-  auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
-  mlir::Type complexElemTy =
-      getTypeConverter()->convertType(complexType.getElementType());
-
-  mlir::Location loc = op.getLoc();
-  auto lhsReal =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
-  auto lhsImag =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
-  auto rhsReal =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
-  auto rhsImag =
-      rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
-
-  if (complexElemTy.isInteger()) {
-    auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
-        loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
-    auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
-        loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
-    rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp);
-    return mlir::success();
-  }
-
-  auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
-      loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
-  auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
-      loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
-  rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp);
-  return mlir::success();
-}
-
 std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
   return std::make_unique<ConvertCIRToLLVMPass>();
 }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index 5cd1d09b88c00..8502cb1ae5d9f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -463,26 +463,6 @@ class CIRToLLVMComplexImagOpLowering
                   mlir::ConversionPatternRewriter &) const override;
 };
 
-class CIRToLLVMComplexEqualOpLowering
-    : public mlir::OpConversionPattern<cir::ComplexEqualOp> {
-public:
-  using mlir::OpConversionPattern<cir::ComplexEqualOp>::OpConversionPattern;
-
-  mlir::LogicalResult
-  matchAndRewrite(cir::ComplexEqualOp op, OpAdaptor,
-                  mlir::ConversionPatternRewriter &) const override;
-};
-
-class CIRToLLVMComplexNotEqualOpLowering
-    : public mlir::OpConversionPattern<cir::ComplexNotEqualOp> {
-public:
-  using mlir::OpConversionPattern<cir::ComplexNotEqualOp>::OpConversionPattern;
-
-  mlir::LogicalResult
-  matchAndRewrite(cir::ComplexNotEqualOp op, OpAdaptor,
-                  mlir::ConversionPatternRewriter &) const override;
-};
-
 } // namespace direct
 } // namespace cir
 
diff --git a/clang/test/CIR/CodeGen/complex.cpp 
b/clang/test/CIR/CodeGen/complex.cpp
index b8a0b99c10f0b..dbeeb75d85b89 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -376,7 +376,7 @@ bool foo18(int _Complex a, int _Complex b) {
 
 // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
 // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
-// CIR: %[[RESULT:.*]] = cir.complex.eq %[[COMPLEX_A]], %[[COMPLEX_B]] : 
!cir.complex<!s32i>
+// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[COMPLEX_B]]) : 
!cir.complex<!s32i>, !cir.bool
 
 // LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4
 // LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4
@@ -408,7 +408,8 @@ bool foo19(double _Complex a, double _Complex b) {
 
 // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
 // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
-// CIR: %[[RESULT:.*]] = cir.complex.eq %[[COMPLEX_A]], %[[COMPLEX_B]] : 
!cir.complex<!cir.double>
+// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[COMPLEX_B]]) : 
!cir.complex<!cir.double>, !cir.bool
+
 
 // LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8
 // LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8
@@ -449,7 +450,7 @@ bool foo20(int _Complex a, int _Complex b) {
 
 // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
 // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
-// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : 
!cir.complex<!s32i>
+// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[COMPLEX_B]]) : 
!cir.complex<!s32i>, !cir.bool
 
 // LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4
 // LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4
@@ -481,7 +482,7 @@ bool foo21(double _Complex a, double _Complex b) {
 
 // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
 // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
-// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : 
!cir.complex<!cir.double>
+// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[COMPLEX_B]]) : 
!cir.complex<!cir.double>, !cir.bool
 
 // LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8
 // LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8

>From 187fd85eabbb8435a9fa32738ba61acca8f565aa Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Sat, 28 Jun 2025 10:55:15 +0200
Subject: [PATCH 4/4] Remove unneeded check

---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 02f62b863a190..fe7db4e80ed26 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -901,9 +901,7 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
       assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
 
       BinOpInfo boInfo = emitBinOps(e);
-      cir::CmpOpKind opKind =
-          e->getOpcode() == BO_EQ ? cir::CmpOpKind::eq : cir::CmpOpKind::ne;
-      result = builder.create<cir::CmpOp>(loc, opKind, boInfo.lhs, boInfo.rhs);
+      result = builder.create<cir::CmpOp>(loc, kind, boInfo.lhs, boInfo.rhs);
     }
 
     return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to