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

>From 8d328786bdfc80f348fd6c4159ac54c343a28ae9 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Tue, 15 Jul 2025 16:16:34 +0200
Subject: [PATCH 1/2] [CIR] Upstream unary not for ComplexType

---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      | 21 +++++++
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         | 16 ------
 clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp   |  6 ++
 .../Dialect/Transforms/LoweringPrepare.cpp    | 57 ++++++++++++++++++-
 clang/test/CIR/CodeGen/complex-unary.cpp      | 48 ++++++++++++++++
 5 files changed, 131 insertions(+), 17 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/complex-unary.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 277c278fd38b7..25baf278bba38 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -129,6 +129,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
   cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
 
+  mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
+                                  mlir::Value imag) {
+    auto resultComplexTy = cir::ComplexType::get(real.getType());
+    return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);
+  }
+
+  mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
+    auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
+    return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), 
operand);
+  }
+
+  mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
+    auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
+    return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), 
operand);
+  }
+
   mlir::Value createNot(mlir::Value value) {
     return create<cir::UnaryOp>(value.getLoc(), value.getType(),
                                 cir::UnaryOpKind::Not, value);
@@ -169,6 +185,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return create<cir::ContinueOp>(loc);
   }
 
+  mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,
+                            mlir::Value operand) {
+    return create<cir::UnaryOp>(loc, kind, operand);
+  }
+
   mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
     return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
   }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 5bd53ebc52ab5..f855bdad2d7c3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -348,22 +348,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
     return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align);
   }
 
-  mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
-                                  mlir::Value imag) {
-    auto resultComplexTy = cir::ComplexType::get(real.getType());
-    return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);
-  }
-
-  mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
-    auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
-    return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), 
operand);
-  }
-
-  mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
-    auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
-    return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), 
operand);
-  }
-
   /// Create a cir.complex.real_ptr operation that derives a pointer to the 
real
   /// part of the complex value pointed to by the specified pointer value.
   mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 3273d9000771a..6663f5ea1e758 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -57,6 +57,7 @@ class ComplexExprEmitter : public 
StmtVisitor<ComplexExprEmitter, mlir::Value> {
   mlir::Value
   VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);
   mlir::Value VisitUnaryDeref(const Expr *e);
+  mlir::Value VisitUnaryNot(const UnaryOperator *e);
 
   struct BinOpInfo {
     mlir::Location loc;
@@ -338,6 +339,11 @@ mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr 
*e) {
   return emitLoadOfLValue(e);
 }
 
+mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
+  mlir::Value op = Visit(e->getSubExpr());
+  return builder.createNot(op);
+}
+
 mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
                                              QualType promotionTy) {
   e = e->IgnoreParens();
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 5493b86a0a321..788817006baa5 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -8,7 +8,9 @@
 
 #include "PassDetail.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
 #include "clang/CIR/Dialect/Passes.h"
 
 #include <memory>
@@ -22,15 +24,68 @@ struct LoweringPreparePass : public 
LoweringPrepareBase<LoweringPreparePass> {
   void runOnOperation() override;
 
   void runOnOp(Operation *op);
+  void lowerUnaryOp(UnaryOp op);
 };
 
 } // namespace
 
-void LoweringPreparePass::runOnOp(Operation *op) {}
+void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {
+  mlir::Type ty = op.getType();
+  if (!mlir::isa<cir::ComplexType>(ty))
+    return;
+
+  mlir::Location loc = op.getLoc();
+  cir::UnaryOpKind opKind = op.getKind();
+
+  CIRBaseBuilderTy builder(getContext());
+  builder.setInsertionPointAfter(op);
+
+  mlir::Value operand = op.getInput();
+  mlir::Value operandReal = builder.createComplexReal(loc, operand);
+  mlir::Value operandImag = builder.createComplexImag(loc, operand);
+
+  mlir::Value resultReal;
+  mlir::Value resultImag;
+
+  switch (opKind) {
+  case cir::UnaryOpKind::Inc:
+  case cir::UnaryOpKind::Dec:
+    llvm_unreachable("Complex unary Inc/Dec NYI");
+    break;
+
+  case cir::UnaryOpKind::Plus:
+  case cir::UnaryOpKind::Minus:
+    llvm_unreachable("Complex unary Plus/Minus NYI");
+    break;
+
+  case cir::UnaryOpKind::Not:
+    resultReal = operandReal;
+    resultImag =
+        builder.createUnaryOp(loc, cir::UnaryOpKind::Minus, operandImag);
+    break;
+  }
+
+  auto result = builder.createComplexCreate(loc, resultReal, resultImag);
+  op.replaceAllUsesWith(result);
+  op.erase();
+}
+
+void LoweringPreparePass::runOnOp(Operation *op) {
+  if (auto unary = dyn_cast<UnaryOp>(op)) {
+    lowerUnaryOp(unary);
+  }
+}
 
 void LoweringPreparePass::runOnOperation() {
+  mlir::Operation *op = getOperation();
+
   llvm::SmallVector<Operation *> opsToTransform;
 
+  op->walk([&](Operation *op) {
+    if (isa<UnaryOp>(op))
+      opsToTransform.push_back(op);
+  });
+
   for (auto *o : opsToTransform)
     runOnOp(o);
 }
diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp 
b/clang/test/CIR/CodeGen/complex-unary.cpp
new file mode 100644
index 0000000000000..463c4dde47ed6
--- /dev/null
+++ b/clang/test/CIR/CodeGen/complex-unary.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir 
--mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck 
--check-prefix=CIR-BEFORE %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir 
--mlir-print-ir-after=cir-lowering-prepare -o %t.cir %s 2>&1 | FileCheck 
--check-prefixes=CIR-AFTER %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+void foo() {
+  int _Complex a;
+  int _Complex b = ~a;
+}
+
+// CIR-BEFORE: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["a"]
+// CIR-BEFORE: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.unary(not, %[[TMP]]) : 
!cir.complex<!s32i>, !cir.complex<!s32i>
+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[RESULT]] : 
!cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+
+// CIR-AFTER: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["a"]
+// CIR-AFTER: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!s32i> 
-> !s32i
+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!s32i> 
-> !s32i
+// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !s32i, !s32i
+// CIR-AFTER: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], 
%[[IMAG_MINUS]] : !s32i -> !cir.complex<!s32i>
+// CIR-AFTER: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : 
!cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[COMPLEX:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[COMPLEX]], align 4
+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP]], 0
+// LLVM: %[[IMAG:.*]] = extractvalue { i32, i32 } %[[TMP]], 1
+// LLVM: %[[IMAG_MINUS:.*]] = sub i32 0, %[[IMAG]]
+// LLVM: %[[RESULT_TMP:.*]] = insertvalue { i32, i32 } {{.*}}, i32 %[[REAL]], 0
+// LLVM: %[[RESULT_VAL:.*]] = insertvalue { i32, i32 } %[[RESULT_TMP]], i32 
%[[IMAG_MINUS]], 1
+// LLVM: store { i32, i32 } %[[RESULT_VAL]], ptr %[[RESULT]], align 4
+
+// OGCG: %[[COMPLEX:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX]], 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]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[A_IMAG_MINUS:.*]] = sub i32 0, %[[A_IMAG]]
+// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, 
ptr %[[RESULT]], i32 0, i32 0
+// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, 
ptr %[[RESULT]], i32 0, i32 1
+// OGCG: store i32 %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4
+// OGCG: store i32 %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4

>From 9edd9e0e7494b92ab8cf0fcd16cf5bc14156f055 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Tue, 15 Jul 2025 17:02:37 +0200
Subject: [PATCH 2/2] Address code review comments

---
 .../Dialect/Transforms/LoweringPrepare.cpp    | 21 +++++++++----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 788817006baa5..c708cf9d9fa61 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -23,13 +23,13 @@ struct LoweringPreparePass : public 
LoweringPrepareBase<LoweringPreparePass> {
   LoweringPreparePass() = default;
   void runOnOperation() override;
 
-  void runOnOp(Operation *op);
-  void lowerUnaryOp(UnaryOp op);
+  void runOnOp(mlir::Operation *op);
+  void lowerUnaryOp(cir::UnaryOp op);
 };
 
 } // namespace
 
-void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {
+void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
   mlir::Type ty = op.getType();
   if (!mlir::isa<cir::ComplexType>(ty))
     return;
@@ -65,28 +65,27 @@ void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {
     break;
   }
 
-  auto result = builder.createComplexCreate(loc, resultReal, resultImag);
+  mlir::Value result = builder.createComplexCreate(loc, resultReal, 
resultImag);
   op.replaceAllUsesWith(result);
   op.erase();
 }
 
-void LoweringPreparePass::runOnOp(Operation *op) {
-  if (auto unary = dyn_cast<UnaryOp>(op)) {
+void LoweringPreparePass::runOnOp(mlir::Operation *op) {
+  if (auto unary = dyn_cast<cir::UnaryOp>(op))
     lowerUnaryOp(unary);
-  }
 }
 
 void LoweringPreparePass::runOnOperation() {
   mlir::Operation *op = getOperation();
 
-  llvm::SmallVector<Operation *> opsToTransform;
+  llvm::SmallVector<mlir::Operation *> opsToTransform;
 
-  op->walk([&](Operation *op) {
-    if (isa<UnaryOp>(op))
+  op->walk([&](mlir::Operation *op) {
+    if (mlir::isa<cir::UnaryOp>(op))
       opsToTransform.push_back(op);
   });
 
-  for (auto *o : opsToTransform)
+  for (mlir::Operation *o : opsToTransform)
     runOnOp(o);
 }
 

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

Reply via email to