https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/201727

>From c1843c3c465b7ff3e93b290216f1948c36b827a2 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Wed, 3 Jun 2026 16:31:07 -0700
Subject: [PATCH 1/2] [CIR] Update CIR unary operations

This creates a floating-point-specific FNegOp and updates the type
constraints on the existing unary operations to match the types that
are actually produced by the Clang AST.

This change also moves complex types out of the unary operations.
A ComplexConjOp is added to handle what was previously being incorrectly
referred to as "not", while inc, dec, and minus are just expanded to
their component representation during codegen. We may want to consider
adding operations like cir.complex.add later, but for now I'm just
removing this type from the unary ops. I'm doing this for two reasons:
(1) the old use was inconsistent with how we handle other arithmetic
operations on complex types, and (2) I will soon need to attach
FP-specific attributes to add and subtract of complex types (and so also
inc and dec).

Assisted-by: Cursor / claude-opus-4.8
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      |  13 +++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  76 ++++++++++--
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         |  16 +--
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |   2 +-
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  |   8 +-
 clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp   |  40 ++++++-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  24 ++--
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       |  39 ++++---
 .../Dialect/Transforms/CIRCanonicalize.cpp    |   3 +-
 .../Dialect/Transforms/LoweringPrepare.cpp    |  47 +++-----
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  52 +++------
 clang/test/CIR/CodeGen/complex-builtins.cpp   |   2 +-
 clang/test/CIR/CodeGen/complex-unary.cpp      | 110 ++++++++++++------
 .../test/CIR/CodeGen/long-double-inc-dec.cpp  |  20 ++--
 clang/test/CIR/CodeGen/unary.cpp              |  33 +++---
 .../test/CIR/CodeGenOpenACC/atomic-update.cpp |   3 +-
 clang/test/CIR/IR/unary.cir                   |  23 ++++
 clang/test/CIR/Transforms/canonicalize.cir    |  42 ++-----
 clang/test/CodeGen/AArch64/neon/fullfp16.c    |   4 +-
 19 files changed, 341 insertions(+), 216 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index a841190c53c0d..2816bca88b1c4 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -224,6 +224,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::ComplexImagOp::create(*this, loc, resultType, operand);
   }
 
+  mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand) {
+    return cir::ComplexConjOp::create(*this, loc, operand.getType(), operand);
+  }
+
   cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
                          bool isVolatile = false, uint64_t alignment = 0) {
     mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
@@ -737,6 +741,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::FRemOp::create(*this, loc, lhs, rhs);
   }
 
+  mlir::Value createFNeg(mlir::Location loc, mlir::Value operand) {
+    assert(cir::isFPOrVectorOfFPType(operand.getType()) &&
+           "expected floating-point or vector-of-float type");
+    assert(!cir::MissingFeatures::metaDataNode());
+    assert(!cir::MissingFeatures::fpConstraints());
+    assert(!cir::MissingFeatures::fastMathFlags());
+    return cir::FNegOp::create(*this, loc, operand);
+  }
+
   mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
     return cir::XorOp::create(*this, loc, lhs, rhs);
   }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 975be5aac87a7..29644fa35aa74 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1868,8 +1868,9 @@ class CIR_UnaryOpWithOverflowFlag<string mnemonic, Type 
type,
 // IncOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_IncOp : CIR_UnaryOpWithOverflowFlag<"inc", CIR_AnyType> {
-  let summary = "Increment by one";
+def CIR_IncOp
+    : CIR_UnaryOpWithOverflowFlag<"inc", CIR_AnyIntOrVecOfIntType> {
+  let summary = "Increment an integer by one";
   let description = [{
     The `cir.inc` operation increments the operand by one. The operand and
     result must have the same type.
@@ -1892,8 +1893,9 @@ def CIR_IncOp : CIR_UnaryOpWithOverflowFlag<"inc", 
CIR_AnyType> {
 // DecOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_DecOp : CIR_UnaryOpWithOverflowFlag<"dec", CIR_AnyType> {
-  let summary = "Decrement by one";
+def CIR_DecOp
+    : CIR_UnaryOpWithOverflowFlag<"dec", CIR_AnyIntOrVecOfIntType> {
+  let summary = "Decrement an integer by one";
   let description = [{
     The `cir.dec` operation decrements the operand by one. The operand and
     result must have the same type.
@@ -1916,8 +1918,9 @@ def CIR_DecOp : CIR_UnaryOpWithOverflowFlag<"dec", 
CIR_AnyType> {
 // MinusOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_MinusOp : CIR_UnaryOpWithOverflowFlag<"minus", CIR_AnyType> {
-  let summary = "Unary minus (negation)";
+def CIR_MinusOp
+    : CIR_UnaryOpWithOverflowFlag<"minus", CIR_AnyIntOrVecOfIntType> {
+  let summary = "Integer unary minus (negation)";
   let description = [{
     The `cir.minus` operation negates the operand. The operand and result
     must have the same type.
@@ -1931,7 +1934,6 @@ def CIR_MinusOp : CIR_UnaryOpWithOverflowFlag<"minus", 
CIR_AnyType> {
     ```
     %1 = cir.minus %0 : !s32i
     %3 = cir.minus nsw %2 : !s32i
-    %5 = cir.minus %4 : !cir.float
     ```
   }];
 
@@ -1942,7 +1944,7 @@ def CIR_MinusOp : CIR_UnaryOpWithOverflowFlag<"minus", 
CIR_AnyType> {
 // NotOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_NotOp : CIR_UnaryOp<"not", CIR_AnyType, [Involution]> {
+def CIR_NotOp : CIR_UnaryOp<"not", CIR_AnyBitwiseType, [Involution]> {
   let summary = "Bitwise NOT / logical NOT";
   let description = [{
     The `cir.not` operation performs a bitwise NOT on integer types or a
@@ -1960,6 +1962,30 @@ def CIR_NotOp : CIR_UnaryOp<"not", CIR_AnyType, 
[Involution]> {
   let hasFolder = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// FNegOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FNegOp : CIR_UnaryOp<"fneg", CIR_AnyFloatOrVecOfFloatType> {
+  let summary = "Floating-point negation";
+  let description = [{
+    The `cir.fneg` operation negates the operand. The operand and result must
+    have the same type.
+
+    Example:
+
+    ```
+    %1 = cir.fneg %0 : !cir.float
+    %3 = cir.fneg %2 : !cir.double
+    %5 = cir.fneg %4 : !cir.vector<4 x !cir.float>
+    ```
+  }];
+
+  let hasFolder = 1;
+
+  let llvmOp = "FNegOp";
+}
+
 
//===----------------------------------------------------------------------===//
 // BrCondOp
 
//===----------------------------------------------------------------------===//
@@ -2436,7 +2462,7 @@ def CIR_AddOp
   let description = [{
     The `cir.add` operation performs addition on integer operands. Both
     operands and the result must have the same integer or vector-of-integer
-    type. Floating-point addition is performed by `cir.fadd`.
+    type.
 
     The optional `nsw` (no signed wrap) and `nuw` (no unsigned wrap) unit
     attributes indicate that the result is poison if signed or unsigned
@@ -2466,7 +2492,7 @@ def CIR_SubOp
   let description = [{
     The `cir.sub` operation performs subtraction on integer operands. Both
     operands and the result must have the same integer or vector-of-integer
-    type. Floating-point subtraction is performed by `cir.fsub`.
+    type.
 
     The optional `nsw` (no signed wrap) and `nuw` (no unsigned wrap) unit
     attributes indicate that the result is poison if signed or unsigned
@@ -2494,7 +2520,7 @@ def CIR_MulOp : CIR_BinaryOp<"mul", 
CIR_AnyIntOrVecOfIntType> {
   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. Floating-point multiplication is performed by `cir.fmul`.
+    type.
 
     The optional `nsw` (no signed wrap) and `nuw` (no unsigned wrap) unit
     attributes indicate that the result is poison if signed or unsigned
@@ -6062,6 +6088,34 @@ def CIR_ComplexDivOp : 
CIR_ComplexRangeBinOp<"complex.div"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// ComplexConjOp
+//===----------------------------------------------------------------------===//
+
+def CIR_ComplexConjOp
+    : CIR_Op<"complex.conj", [Pure, SameOperandsAndResultType]> {
+  let summary = "Complex conjugate";
+  let description = [{
+    The `cir.complex.conj` operation takes a complex number and returns its
+    complex conjugate, which is formed by negating the imaginary part.
+
+    Example:
+
+    ```
+    %1 = cir.complex.conj %0 : !cir.complex<!cir.float>
+    ```
+  }];
+
+  let arguments = (ins CIR_ComplexType:$operand);
+  let results = (outs CIR_ComplexType:$result);
+
+  let assemblyFormat = [{
+    $operand `:` qualified(type($operand)) attr-dict
+  }];
+
+  let hasLLVMLowering = false;
+}
+
 
//===----------------------------------------------------------------------===//
 // Bit Manipulation Operations
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 9e88e3588d84a..d9fa5e23f40ae 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -467,29 +467,19 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
   
//===--------------------------------------------------------------------===//
   // UnaryOp creation helpers
   
//===--------------------------------------------------------------------===//
-  mlir::Value createNeg(mlir::Value value, bool nsw = false) {
+  mlir::Value createNeg(mlir::Location loc, mlir::Value value,
+                        bool nsw = false) {
 
     if (auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) {
       // Source is a unsigned integer: first cast it to signed.
       if (intTy.isUnsigned())
         value = createIntCast(value, getSIntNTy(intTy.getWidth()));
-      return createMinus(value.getLoc(), value, nsw);
+      return createMinus(loc, value, nsw);
     }
 
     llvm_unreachable("negation for the given type is NYI");
   }
 
-  mlir::Value createFNeg(mlir::Value value) {
-    assert(mlir::isa<cir::FPTypeInterface>(value.getType()) &&
-           "Non-fp input type!");
-
-    assert(!cir::MissingFeatures::metaDataNode());
-    assert(!cir::MissingFeatures::fpConstraints());
-    assert(!cir::MissingFeatures::fastMathFlags());
-
-    return createMinus(value.getLoc(), value);
-  }
-
   
//===--------------------------------------------------------------------===//
   // CastOp creation helpers
   
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 1bb3c729e6279..e6de3954a8c69 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1171,7 +1171,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BIconjf:
   case Builtin::BIconjl: {
     mlir::Value complex = emitComplexExpr(e->getArg(0));
-    mlir::Value conj = builder.createNot(complex);
+    mlir::Value conj = builder.createComplexConj(loc, complex);
     return RValue::getComplex(conj);
   }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 81f66727b251c..01c5511980980 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -2442,10 +2442,10 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
                      getContext().BuiltinInfo.getName(builtinID));
     return mlir::Value{};
   case NEON::BI__builtin_neon_vnegd_s64: {
-    return builder.createNeg(ops[0]);
+    return builder.createNeg(loc, ops[0]);
   }
   case NEON::BI__builtin_neon_vnegh_f16: {
-    return builder.createFNeg(ops[0]);
+    return builder.createFNeg(loc, ops[0]);
   }
   case NEON::BI__builtin_neon_vtstd_s64:
   case NEON::BI__builtin_neon_vtstd_u64:
@@ -2517,7 +2517,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vfmsh_f16:
     // NEON intrinsic puts accumulator first, unlike the LLVM fma.
     std::rotate(ops.begin(), ops.begin() + 1, ops.end());
-    ops[0] = builder.createFNeg(ops[0]);
+    ops[0] = builder.createFNeg(loc, ops[0]);
     return emitCallMaybeConstrainedBuiltin(builder, loc, "fma",
                                            convertType(expr->getType()), ops);
   case NEON::BI__builtin_neon_vaddd_s64:
@@ -2569,7 +2569,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
     cir::IntType int64Type = builtinID == NEON::BI__builtin_neon_vrsrad_n_u64
                                  ? builder.getUInt64Ty()
                                  : builder.getSInt64Ty();
-    ops[2] = builder.createNeg(ops[2]);
+    ops[2] = builder.createNeg(loc, ops[2]);
     const StringRef intrName = builtinID == NEON::BI__builtin_neon_vrsrad_n_u64
                                    ? "aarch64.neon.urshl"
                                    : "aarch64.neon.srshl";
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 34e239b0997a0..fb8ace089a4c5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -595,12 +595,28 @@ mlir::Value ComplexExprEmitter::VisitUnaryMinus(const 
UnaryOperator *e,
     op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
   else
     op = Visit(e->getSubExpr());
-  return builder.createMinus(cgf.getLoc(e->getExprLoc()), op);
+
+  // Negate each component of the complex value.
+  mlir::Location loc = cgf.getLoc(e->getExprLoc());
+  mlir::Value real = builder.createComplexReal(loc, op);
+  mlir::Value imag = builder.createComplexImag(loc, op);
+
+  mlir::Value resultReal;
+  mlir::Value resultImag;
+  if (cir::isFPOrVectorOfFPType(real.getType())) {
+    resultReal = builder.createFNeg(loc, real);
+    resultImag = builder.createFNeg(loc, imag);
+  } else {
+    resultReal = builder.createMinus(loc, real);
+    resultImag = builder.createMinus(loc, imag);
+  }
+
+  return builder.createComplexCreate(loc, resultReal, resultImag);
 }
 
 mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) {
   mlir::Value op = Visit(e->getSubExpr());
-  return builder.createNot(op);
+  return builder.createComplexConj(cgf.getLoc(e->getExprLoc()), op);
 }
 
 mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
@@ -1108,8 +1124,24 @@ mlir::Value 
CIRGenFunction::emitComplexPrePostIncDec(const UnaryOperator *e,
                                                      LValue lv) {
   mlir::Value inVal = emitLoadOfComplex(lv, e->getExprLoc());
   mlir::Location loc = getLoc(e->getExprLoc());
-  mlir::Value incVal = e->isIncrementOp() ? builder.createInc(loc, inVal)
-                                          : builder.createDec(loc, inVal);
+
+  // Increment/decrement only the real component of the complex value.
+  mlir::Value real = builder.createComplexReal(loc, inVal);
+  mlir::Value imag = builder.createComplexImag(loc, inVal);
+
+  mlir::Value resultReal;
+  if (cir::isFPOrVectorOfFPType(real.getType())) {
+    auto fpType = mlir::cast<cir::FPTypeInterface>(real.getType());
+    mlir::Value amount = builder.getConstFP(
+        loc, real.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
+    resultReal = e->isIncrementOp() ? builder.createFAdd(loc, real, amount)
+                                    : builder.createFSub(loc, real, amount);
+  } else {
+    resultReal = e->isIncrementOp() ? builder.createInc(loc, real)
+                                    : builder.createDec(loc, real);
+  }
+
+  mlir::Value incVal = builder.createComplexCreate(loc, resultReal, imag);
 
   // Store the updated result through the lvalue.
   emitStoreOfComplex(loc, incVal, lv, /*isInit=*/false);
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 5f2626da19a34..875dd70ecf266 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -678,7 +678,7 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
         mlir::Location loc = cgf.getLoc(e->getSourceRange());
         mlir::Value numElts = cgf.getVLASize(vla).numElts;
         if (!e->isIncrementOp())
-          numElts = cgf.getBuilder().createNeg(numElts, /*nsw=*/true);
+          numElts = cgf.getBuilder().createNeg(loc, numElts, /*nsw=*/true);
         assert(!cir::MissingFeatures::sanitizers());
         value = cgf.getBuilder().createPtrStride(loc, value, numElts);
       } else {
@@ -704,9 +704,13 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
 
       if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
               value.getType())) {
-        // Create the inc/dec operation.
-        // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
-        value = emitIncOrDec(e, value);
+        mlir::Location loc = cgf.getLoc(e->getExprLoc());
+        auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
+        mlir::Value amount = builder.getConstFP(
+            loc, value.getType(),
+            llvm::APFloat(fpType.getFloatSemantics(), 1));
+        value = e->isIncrementOp() ? builder.createFAdd(loc, value, amount)
+                                   : builder.createFSub(loc, value, amount);
       } else {
         cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");
         return {};
@@ -795,6 +799,11 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
     else
       operand = Visit(e->getSubExpr());
 
+    mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
+
+    if (cir::isFPOrVectorOfFPType(operand.getType()))
+      return builder.createOrFold<cir::FNegOp>(loc, operand);
+
     // TODO(cir): We might have to change this to support overflow trapping.
     //            Classic codegen routes unary minus through emitSub to ensure
     //            that the overflow behavior is handled correctly.
@@ -802,10 +811,7 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
                cgf.getLangOpts().getSignedOverflowBehavior() !=
                    LangOptions::SOB_Defined;
 
-    // NOTE: LLVM codegen will lower this directly to either a FNeg
-    // or a Sub instruction.  In CIR this will be handled later in LowerToLLVM.
-    return builder.createOrFold<cir::MinusOp>(
-        cgf.getLoc(e->getSourceRange().getBegin()), operand, nsw);
+    return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
   }
 
   mlir::Value emitIncOrDec(const UnaryOperator *e, mlir::Value input,
@@ -1903,7 +1909,7 @@ static mlir::Value emitPointerArithmetic(CIRGenFunction 
&cgf,
 
   // If this is subtraction, negate the index.
   if (isSubtraction)
-    index = cgf.getBuilder().createNeg(index);
+    index = cgf.getBuilder().createNeg(cgf.getLoc(op.e->getExprLoc()), index);
 
   assert(!cir::MissingFeatures::sanitizers());
 
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 371806a216dcc..39807d1dee89a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -3011,23 +3011,32 @@ OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
   if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
     return adaptor.getInput();
 
-  // Avoid materializing a duplicate constant for bool minus (identity).
-  if (auto srcConst = getInput().getDefiningOp<cir::ConstantOp>())
-    if (mlir::isa<cir::BoolType>(srcConst.getType()))
-      return srcConst.getResult();
+  // Fold with constant inputs. Floating-point negation is handled by
+  // cir::FNegOp.
+  if (auto intAttr = mlir::dyn_cast_if_present<cir::IntAttr>(
+          adaptor.getInput())) {
+    APInt val = intAttr.getValue();
+    val.negate();
+    return cir::IntAttr::get(getType(), val);
+  }
+
+  return {};
+}
+
+//===----------------------------------------------------------------------===//
+// FNegOp
+//===----------------------------------------------------------------------===//
+
+OpFoldResult cir::FNegOp::fold(FoldAdaptor adaptor) {
+  if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
+    return adaptor.getInput();
 
   // Fold with constant inputs.
-  if (mlir::Attribute attr = adaptor.getInput()) {
-    if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
-      APInt val = intAttr.getValue();
-      val.negate();
-      return cir::IntAttr::get(getType(), val);
-    }
-    if (auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
-      APFloat val = fpAttr.getValue();
-      val.changeSign();
-      return cir::FPAttr::get(getType(), val);
-    }
+  if (auto fpAttr = mlir::dyn_cast_if_present<cir::FPAttr>(
+          adaptor.getInput())) {
+    APFloat val = fpAttr.getValue();
+    val.changeSign();
+    return cir::FPAttr::get(getType(), val);
   }
 
   return {};
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp 
b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
index da08f21977066..da1984d29a797 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
@@ -71,7 +71,8 @@ void CIRCanonicalizePass::runOnOperation() {
     // Many operations are here to perform a manual `fold` in
     // applyOpPatternsGreedily.
     if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, IncOp, DecOp,
-            MinusOp, NotOp, AddOp, MulOp, AndOp, OrOp, XorOp, MaxOp, MinOp,
+            MinusOp, FNegOp, NotOp, AddOp, MulOp, AndOp, OrOp, XorOp, MaxOp,
+            MinOp,
             ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,
             VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,
             VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitFfsOp, 
BitParityOp,
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 14458d5b62d67..ae7a26c04036b 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -87,9 +87,9 @@ struct LoweringPreparePass
 
   void runOnOp(mlir::Operation *op);
   void lowerCastOp(cir::CastOp op);
+  void lowerComplexConjOp(cir::ComplexConjOp op);
   void lowerComplexDivOp(cir::ComplexDivOp op);
   void lowerComplexMulOp(cir::ComplexMulOp op);
-  void lowerUnaryOp(cir::UnaryOpInterface op);
   void lowerGetGlobalOp(cir::GetGlobalOp op);
   void lowerGlobalOp(cir::GlobalOp op);
   void lowerThreeWayCmpOp(cir::CmpThreeWayOp op);
@@ -1028,35 +1028,22 @@ void 
LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
   op.erase();
 }
 
-void LoweringPreparePass::lowerUnaryOp(cir::UnaryOpInterface op) {
-  if (!mlir::isa<cir::ComplexType>(op.getResult().getType()))
-    return;
-
-  mlir::Location loc = op->getLoc();
+void LoweringPreparePass::lowerComplexConjOp(cir::ComplexConjOp op) {
+  mlir::Location loc = op.getLoc();
   CIRBaseBuilderTy builder(getContext());
   builder.setInsertionPointAfter(op);
 
-  mlir::Value operand = op.getInput();
+  mlir::Value operand = op.getOperand();
   mlir::Value operandReal = builder.createComplexReal(loc, operand);
   mlir::Value operandImag = builder.createComplexImag(loc, operand);
 
-  mlir::Value resultReal = operandReal;
-  mlir::Value resultImag = operandImag;
-
-  llvm::TypeSwitch<mlir::Operation *>(op)
-      .Case<cir::IncOp>(
-          [&](auto) { resultReal = builder.createInc(loc, operandReal); })
-      .Case<cir::DecOp>(
-          [&](auto) { resultReal = builder.createDec(loc, operandReal); })
-      .Case<cir::MinusOp>([&](auto) {
-        resultReal = builder.createMinus(loc, operandReal);
-        resultImag = builder.createMinus(loc, operandImag);
-      })
-      .Case<cir::NotOp>(
-          [&](auto) { resultImag = builder.createMinus(loc, operandImag); })
-      .Default([](auto) { llvm_unreachable("unhandled unary complex op"); });
-
-  mlir::Value result = builder.createComplexCreate(loc, resultReal, 
resultImag);
+  // The complex conjugate is formed by negating the imaginary component.
+  const bool isFP = cir::isFPOrVectorOfFPType(operandReal.getType());
+  mlir::Value resultImag = isFP ? builder.createFNeg(loc, operandImag)
+                                : builder.createMinus(loc, operandImag);
+
+  mlir::Value result =
+      builder.createComplexCreate(loc, operandReal, resultImag);
   op->replaceAllUsesWith(mlir::ValueRange{result});
   op->erase();
 }
@@ -2270,6 +2257,8 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) {
     lowerArrayDtor(arrayDtor);
   } else if (auto cast = mlir::dyn_cast<cir::CastOp>(op)) {
     lowerCastOp(cast);
+  } else if (auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
+    lowerComplexConjOp(complexConj);
   } else if (auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
     lowerComplexDivOp(complexDiv);
   } else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
@@ -2281,8 +2270,6 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) {
       cudaDeviceVars.emplace_back(glob, regAttr);
   } else if (auto getGlob = mlir::dyn_cast<cir::GetGlobalOp>(op)) {
     lowerGetGlobalOp(getGlob);
-  } else if (auto unaryOp = mlir::dyn_cast<cir::UnaryOpInterface>(op)) {
-    lowerUnaryOp(unaryOp);
   } else if (auto callOp = dyn_cast<cir::CallOp>(op)) {
     lowerTrivialCopyCall(callOp);
   } else if (auto storeOp = dyn_cast<cir::StoreOp>(op)) {
@@ -2903,10 +2890,10 @@ void LoweringPreparePass::runOnOperation() {
 
   op->walk([&](mlir::Operation *op) {
     if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
-                  cir::ComplexMulOp, cir::ComplexDivOp, cir::DynamicCastOp,
-                  cir::FuncOp, cir::CallOp, cir::GetGlobalOp, cir::GlobalOp,
-                  cir::StoreOp, cir::CmpThreeWayOp, cir::IncOp, cir::DecOp,
-                  cir::MinusOp, cir::NotOp, cir::LocalInitOp>(op))
+                  cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
+                  cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
+                  cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
+                  cir::CmpThreeWayOp, cir::LocalInitOp>(op))
       opsToTransform.push_back(op);
   });
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index eb9587cc1bf83..f9c0939b29538 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2589,40 +2589,27 @@ static mlir::LLVM::IntegerOverflowFlags nswFlag(bool 
nsw) {
 template <typename CIROp, typename LLVMIntOp>
 static mlir::LogicalResult
 lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor,
-              mlir::ConversionPatternRewriter &rewriter, double fpConstant) {
+              mlir::ConversionPatternRewriter &rewriter) {
   mlir::Type elementType = elementTypeIfVector(op.getType());
   mlir::Type llvmType = adaptor.getInput().getType();
   mlir::Location loc = op.getLoc();
 
-  if (mlir::isa<cir::IntType>(elementType)) {
-    auto maybeNSW = nswFlag(op.getNoSignedWrap());
-    auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
-    rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one,
-                                           maybeNSW);
-    return mlir::success();
-  }
-  if (mlir::isa<cir::FPTypeInterface>(elementType)) {
-    auto fpConst = mlir::LLVM::ConstantOp::create(
-        rewriter, loc, rewriter.getFloatAttr(llvmType, fpConstant));
-    rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, fpConst,
-                                                    adaptor.getInput());
-    return mlir::success();
-  }
-  return op.emitError() << "Unsupported type for IncOp/DecOp";
+  auto maybeNSW = nswFlag(op.getNoSignedWrap());
+  auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
+  rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, 
maybeNSW);
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
     cir::IncOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  return lowerIncDecOp<cir::IncOp, mlir::LLVM::AddOp>(op, adaptor, rewriter,
-                                                      1.0);
+  return lowerIncDecOp<cir::IncOp, mlir::LLVM::AddOp>(op, adaptor, rewriter);
 }
 
 mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
     cir::DecOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  return lowerIncDecOp<cir::DecOp, mlir::LLVM::SubOp>(op, adaptor, rewriter,
-                                                      -1.0);
+  return lowerIncDecOp<cir::DecOp, mlir::LLVM::SubOp>(op, adaptor, rewriter);
 }
 
 mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
@@ -2633,22 +2620,15 @@ mlir::LogicalResult 
CIRToLLVMMinusOpLowering::matchAndRewrite(
   mlir::Type llvmType = adaptor.getInput().getType();
   mlir::Location loc = op.getLoc();
 
-  if (mlir::isa<cir::IntType>(elementType)) {
-    auto maybeNSW = nswFlag(op.getNoSignedWrap());
-    mlir::Value zero;
-    if (isVector)
-      zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
-    else
-      zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
-    rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, 
adaptor.getInput(),
-                                                   maybeNSW);
-    return mlir::success();
-  }
-  if (mlir::isa<cir::FPTypeInterface>(elementType)) {
-    rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, adaptor.getInput());
-    return mlir::success();
-  }
-  return op.emitError() << "Unsupported type for unary minus";
+  auto maybeNSW = nswFlag(op.getNoSignedWrap());
+  mlir::Value zero;
+  if (isVector)
+    zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
+  else
+    zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
+  rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
+                                                 maybeNSW);
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
diff --git a/clang/test/CIR/CodeGen/complex-builtins.cpp 
b/clang/test/CIR/CodeGen/complex-builtins.cpp
index 9a6ca7562ecf7..8d9e32b055601 100644
--- a/clang/test/CIR/CodeGen/complex-builtins.cpp
+++ b/clang/test/CIR/CodeGen/complex-builtins.cpp
@@ -94,7 +94,7 @@ void foo4() {
 // CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> 
!cir.float
 // CIR: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> 
!cir.float
-// CIR: %[[IMAG_MINUS:.*]] = cir.minus %[[IMAG]] : !cir.float
+// CIR: %[[IMAG_MINUS:.*]] = cir.fneg %[[IMAG]] : !cir.float
 // CIR: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : 
!cir.float -> !cir.complex<!cir.float>
 // CIR: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp 
b/clang/test/CIR/CodeGen/complex-unary.cpp
index 753b322c6597a..15052e686a9a5 100644
--- a/clang/test/CIR/CodeGen/complex-unary.cpp
+++ b/clang/test/CIR/CodeGen/complex-unary.cpp
@@ -13,8 +13,8 @@ void foo() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
-// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.not %[[TMP]] : !cir.complex<!s32i>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[B_ADDR]] : 
!cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+// CIR-BEFORE: %[[COMPLEX_CONJ:.*]] = cir.complex.conj %[[TMP]] : 
!cir.complex<!s32i>
+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_CONJ]], %[[B_ADDR]] : 
!cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["a"]
 // CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
@@ -55,15 +55,15 @@ void foo2() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.not %[[TMP]] : 
!cir.complex<!cir.float>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: %[[COMPLEX_CONJ:.*]] = cir.complex.conj %[[TMP]] : 
!cir.complex<!cir.float>
+// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_CONJ]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.minus %[[IMAG]] : !cir.float
+// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.fneg %[[IMAG]] : !cir.float
 // CIR-AFTER: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], 
%[[IMAG_MINUS]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[RESULT_VAL]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
@@ -97,8 +97,12 @@ void foo3() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[COMPLEX_INC:.*]] = cir.inc %[[TMP]] : 
!cir.complex<!cir.float>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-BEFORE: %[[REAL_INC:.*]] = cir.fadd %[[REAL]], %[[ONE]] : !cir.float
+// CIR-BEFORE: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 // CIR-BEFORE: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
@@ -106,7 +110,8 @@ void foo3() {
 // CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[REAL_INC:.*]] = cir.inc %[[REAL]] : !cir.float
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-AFTER: %[[REAL_INC:.*]] = cir.fadd %[[REAL]], %[[ONE]] : !cir.float
 // CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
@@ -116,7 +121,7 @@ void foo3() {
 // LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
 // LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
 // LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1
-// LLVM: %[[REAL_INC:.*]] = fadd float 1.000000e+00, %[[REAL]]
+// LLVM: %[[REAL_INC:.*]] = fadd float %[[REAL]], 1.000000e+00
 // LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float 
%[[REAL_INC]], 0
 // LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], 
float %[[IMAG]], 1
 // LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4
@@ -146,16 +151,21 @@ void foo4() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[COMPLEX_INC:.*]] = cir.inc %[[TMP]] : 
!cir.complex<!cir.float>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-BEFORE: %[[REAL_INC:.*]] = cir.fadd %[[REAL]], %[[ONE]] : !cir.float
+// CIR-BEFORE: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[REAL_INC:.*]] = cir.inc %[[REAL]] : !cir.float
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-AFTER: %[[REAL_INC:.*]] = cir.fadd %[[REAL]], %[[ONE]] : !cir.float
 // CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
@@ -165,7 +175,7 @@ void foo4() {
 // LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
 // LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
 // LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1
-// LLVM: %[[REAL_INC:.*]] = fadd float 1.000000e+00, %[[REAL]]
+// LLVM: %[[REAL_INC:.*]] = fadd float %[[REAL]], 1.000000e+00
 // LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float 
%[[REAL_INC]], 0
 // LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], 
float %[[IMAG]], 1
 // LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4
@@ -195,8 +205,12 @@ void foo5() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[COMPLEX_DEC:.*]] = cir.dec %[[TMP]] : 
!cir.complex<!cir.float>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-BEFORE: %[[REAL_DEC:.*]] = cir.fsub %[[REAL]], %[[ONE]] : !cir.float
+// CIR-BEFORE: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 // CIR-BEFORE: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
@@ -204,7 +218,8 @@ void foo5() {
 // CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[REAL_DEC:.*]] = cir.dec %[[REAL]] : !cir.float
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-AFTER: %[[REAL_DEC:.*]] = cir.fsub %[[REAL]], %[[ONE]] : !cir.float
 // CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
@@ -214,7 +229,7 @@ void foo5() {
 // LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
 // LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
 // LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1
-// LLVM: %[[REAL_DEC:.*]] = fadd float -1.000000e+00, %[[REAL]]
+// LLVM: %[[REAL_DEC:.*]] = fsub float %[[REAL]], 1.000000e+00
 // LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float 
%[[REAL_DEC]], 0
 // LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], 
float %[[IMAG]], 1
 // LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4
@@ -244,16 +259,21 @@ void foo6() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[COMPLEX_DEC:.*]] = cir.dec %[[TMP]] : 
!cir.complex<!cir.float>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-BEFORE: %[[REAL_DEC:.*]] = cir.fsub %[[REAL]], %[[ONE]] : !cir.float
+// CIR-BEFORE: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[REAL_DEC:.*]] = cir.dec %[[REAL]] : !cir.float
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-AFTER: %[[REAL_DEC:.*]] = cir.fsub %[[REAL]], %[[ONE]] : !cir.float
 // CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], 
%[[IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
@@ -263,7 +283,7 @@ void foo6() {
 // LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
 // LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
 // LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1
-// LLVM: %[[REAL_DEC:.*]] = fadd float -1.000000e+00, %[[REAL]]
+// LLVM: %[[REAL_DEC:.*]] = fsub float %[[REAL]], 1.000000e+00
 // LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float 
%[[REAL_DEC]], 0
 // LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], 
float %[[IMAG]], 1
 // LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4
@@ -324,16 +344,20 @@ void foo8() {
 // CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[COMPLEX_MINUS:.*]] = cir.minus %[[TMP]] : 
!cir.complex<!cir.float>
-// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_MINUS]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR-BEFORE: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[REAL_MINUS:.*]] = cir.fneg %[[REAL]] : !cir.float
+// CIR-BEFORE: %[[IMAG_MINUS:.*]] = cir.fneg %[[IMAG]] : !cir.float
+// CIR-BEFORE: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_MINUS]], 
%[[IMAG_MINUS]] : !cir.float -> !cir.complex<!cir.float>
+// CIR-BEFORE: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
 // CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[REAL_MINUS:.*]] = cir.minus %[[REAL]] : !cir.float
-// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.minus %[[IMAG]] : !cir.float
+// CIR-AFTER: %[[REAL_MINUS:.*]] = cir.fneg %[[REAL]] : !cir.float
+// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.fneg %[[IMAG]] : !cir.float
 // CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_MINUS]], 
%[[IMAG_MINUS]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
@@ -426,7 +450,11 @@ void foo10() {
 // CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.f16>, 
!cir.ptr<!cir.complex<!cir.f16>>, ["b", init]
 // CIR-BEFORE: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.f16>>, !cir.complex<!cir.f16>
 // CIR-BEFORE: %[[A_COMPLEX_F32:.*]] = cir.cast float_complex %[[TMP_A]] : 
!cir.complex<!cir.f16> -> !cir.complex<!cir.float>
-// CIR-BEFORE: %[[RESULT:.*]] = cir.minus %[[A_COMPLEX_F32]] : 
!cir.complex<!cir.float>
+// CIR-BEFORE: %[[REAL:.*]] = cir.complex.real %[[A_COMPLEX_F32]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[IMAG:.*]] = cir.complex.imag %[[A_COMPLEX_F32]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[REAL_MINUS:.*]] = cir.fneg %[[REAL]] : !cir.float
+// CIR-BEFORE: %[[IMAG_MINUS:.*]] = cir.fneg %[[IMAG]] : !cir.float
+// CIR-BEFORE: %[[RESULT:.*]] = cir.complex.create %[[REAL_MINUS]], 
%[[IMAG_MINUS]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-BEFORE: %[[A_COMPLEX_F16:.*]] = cir.cast float_complex %[[RESULT]] : 
!cir.complex<!cir.float> -> !cir.complex<!cir.f16>
 // CIR-BEFORE: cir.store{{.*}} %[[A_COMPLEX_F16]], %[[B_ADDR]] : 
!cir.complex<!cir.f16>, !cir.ptr<!cir.complex<!cir.f16>>
 
@@ -440,8 +468,8 @@ void foo10() {
 // CIR-AFTER: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], 
%[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_COMPLEX_F32]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[A_IMAG_F32:.*]] = cir.complex.imag %[[A_COMPLEX_F32]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[RESULT_REAL_F32:.*]] = cir.minus %[[A_REAL_F32]] : !cir.float
-// CIR-AFTER: %[[RESULT_IMAG_F32:.*]] = cir.minus %[[A_IMAG_F32]] : !cir.float
+// CIR-AFTER: %[[RESULT_REAL_F32:.*]] = cir.fneg %[[A_REAL_F32]] : !cir.float
+// CIR-AFTER: %[[RESULT_IMAG_F32:.*]] = cir.fneg %[[A_IMAG_F32]] : !cir.float
 // CIR-AFTER: %[[RESULT_COMPLEX_F32:.*]] = cir.complex.create 
%[[RESULT_REAL_F32]], %[[RESULT_IMAG_F32]] : !cir.float -> 
!cir.complex<!cir.float>
 // CIR-AFTER: %[[RESULT_REAL_F32:.*]] = cir.complex.real 
%[[RESULT_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[RESULT_IMAG_F32:.*]] = cir.complex.imag 
%[[RESULT_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float
@@ -494,14 +522,19 @@ void complex_unary_inc_lvalue() {
 
 // CIR-BEFORE: %[[A_ADDR]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[RESULT:.*]] = cir.inc %[[TMP_A]] : !cir.complex<!cir.float>
+// CIR-BEFORE: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-BEFORE: %[[RESULT_REAL:.*]] = cir.fadd %[[A_REAL]], %[[ONE]] : 
!cir.float
+// CIR-BEFORE: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], 
%[[A_IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-BEFORE: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-AFTER: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[RESULT_REAL:.*]] = cir.inc %2 : !cir.float
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-AFTER: %[[RESULT_REAL:.*]] = cir.fadd %[[A_REAL]], %[[ONE]] : !cir.float
 // CIR-AFTER: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], 
%[[A_IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
@@ -509,7 +542,7 @@ void complex_unary_inc_lvalue() {
 // LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
 // LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
 // LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
-// LLVM: %[[RESULT_REAL:.*]] = fadd float 1.000000e+00, %[[A_REAL]]
+// LLVM: %[[RESULT_REAL:.*]] = fadd float %[[A_REAL]], 1.000000e+00
 // LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float 
%[[RESULT_REAL]], 0
 // LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float 
%[[A_IMAG]], 1
 // LLVM: store { float, float } %[[RESULT]], ptr %[[A_ADDR]], align 4
@@ -532,14 +565,19 @@ void complex_unary_dec_lvalue() {
 
 // CIR-BEFORE: %[[A_ADDR]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-BEFORE: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR-BEFORE: %[[RESULT:.*]] = cir.dec %[[TMP_A]] : !cir.complex<!cir.float>
+// CIR-BEFORE: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-BEFORE: %[[RESULT_REAL:.*]] = cir.fsub %[[A_REAL]], %[[ONE]] : 
!cir.float
+// CIR-BEFORE: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], 
%[[A_IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-BEFORE: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a"]
 // CIR-AFTER: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR-AFTER: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR-AFTER: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : 
!cir.complex<!cir.float> -> !cir.float
-// CIR-AFTER: %[[RESULT_REAL:.*]] = cir.dec %2 : !cir.float
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR-AFTER: %[[RESULT_REAL:.*]] = cir.fsub %[[A_REAL]], %[[ONE]] : !cir.float
 // CIR-AFTER: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], 
%[[A_IMAG]] : !cir.float -> !cir.complex<!cir.float>
 // CIR-AFTER: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
@@ -547,7 +585,7 @@ void complex_unary_dec_lvalue() {
 // LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
 // LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
 // LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
-// LLVM: %[[RESULT_REAL:.*]] = fadd float -1.000000e+00, %[[A_REAL]]
+// LLVM: %[[RESULT_REAL:.*]] = fsub float %[[A_REAL]], 1.000000e+00
 // LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float 
%[[RESULT_REAL]], 0
 // LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float 
%[[A_IMAG]], 1
 // LLVM: store { float, float } %[[RESULT]], ptr %[[A_ADDR]], align 4
diff --git a/clang/test/CIR/CodeGen/long-double-inc-dec.cpp 
b/clang/test/CIR/CodeGen/long-double-inc-dec.cpp
index 02a6c10c010b2..57461320a7375 100644
--- a/clang/test/CIR/CodeGen/long-double-inc-dec.cpp
+++ b/clang/test/CIR/CodeGen/long-double-inc-dec.cpp
@@ -30,14 +30,15 @@ extern "C" long double do_pre_inc(long double d) {
 
   return ++d;
   // CIR: %[[ARG_LOAD:.*]]  = cir.load {{.*}}%[[ARG_ALLOCA]] : 
!cir.ptr<!cir.long_double<![[LDTY]]>>, !cir.long_double<![[LDTY]]>
-  // CIR: %[[ARG_INC:.*]] = cir.inc %[[ARG_LOAD]]
+  // CIR: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<![[LDTY]]>
+  // CIR: %[[ARG_INC:.*]] = cir.fadd %[[ARG_LOAD]], %[[ONE]]
   // CIR: cir.store{{.*}} %[[ARG_INC]], %[[ARG_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: cir.store %[[ARG_INC]], %[[RET_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: %[[LOAD_RET:.*]] = cir.load %[[RET_ALLOCA]]
   // CIR: cir.return %[[LOAD_RET]] : !cir.long_double<![[LDTY]]>
   //
   // LLVM: %[[ARG_LOAD:.*]] = load [[LDTY]], ptr %[[ARG_ALLOCA]]
-  // LLVMCIR: %[[ARG_INC:.*]] = fadd [[LDTY]] 1.000000e+00, %[[ARG_LOAD]]
+  // LLVMCIR: %[[ARG_INC:.*]] = fadd [[LDTY]] %[[ARG_LOAD]], 1.000000e+00
   // OGCG: %[[ARG_INC:.*]] = fadd [[LDTY]] %[[ARG_LOAD]], 1.000000e+00
   // LLVM: store [[LDTY]] %[[ARG_INC]], ptr %[[ARG_ALLOCA]]
   // LLVMCIR: store [[LDTY]] %[[ARG_INC]], ptr %[[RET_ALLOCA]]
@@ -56,14 +57,15 @@ extern "C" long double do_post_inc(long double d) {
 
   return d++;
   // CIR: %[[ARG_LOAD:.*]]  = cir.load {{.*}}%[[ARG_ALLOCA]] : 
!cir.ptr<!cir.long_double<![[LDTY]]>>, !cir.long_double<![[LDTY]]>
-  // CIR: %[[ARG_INC:.*]] = cir.inc %[[ARG_LOAD]]
+  // CIR: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<![[LDTY]]>
+  // CIR: %[[ARG_INC:.*]] = cir.fadd %[[ARG_LOAD]], %[[ONE]]
   // CIR: cir.store{{.*}} %[[ARG_INC]], %[[ARG_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: cir.store %[[ARG_LOAD]], %[[RET_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: %[[LOAD_RET:.*]] = cir.load %[[RET_ALLOCA]]
   // CIR: cir.return %[[LOAD_RET]] : !cir.long_double<![[LDTY]]>
   //
   // LLVM: %[[ARG_LOAD:.*]] = load [[LDTY]], ptr %[[ARG_ALLOCA]]
-  // LLVMCIR: %[[ARG_INC:.*]] = fadd [[LDTY]] 1.000000e+00, %[[ARG_LOAD]]
+  // LLVMCIR: %[[ARG_INC:.*]] = fadd [[LDTY]] %[[ARG_LOAD]], 1.000000e+00
   // OGCG: %[[ARG_INC:.*]] = fadd [[LDTY]] %[[ARG_LOAD]], 1.000000e+00
   // LLVM: store [[LDTY]] %[[ARG_INC]], ptr %[[ARG_ALLOCA]]
   // LLVMCIR: store [[LDTY]] %[[ARG_LOAD]], ptr %[[RET_ALLOCA]]
@@ -83,14 +85,15 @@ extern "C" long double do_pre_dec(long double d) {
 
   return --d;
   // CIR: %[[ARG_LOAD:.*]]  = cir.load {{.*}}%[[ARG_ALLOCA]] : 
!cir.ptr<!cir.long_double<![[LDTY]]>>, !cir.long_double<![[LDTY]]>
-  // CIR: %[[ARG_DEC:.*]] = cir.dec %[[ARG_LOAD]]
+  // CIR: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<![[LDTY]]>
+  // CIR: %[[ARG_DEC:.*]] = cir.fsub %[[ARG_LOAD]], %[[ONE]]
   // CIR: cir.store{{.*}} %[[ARG_DEC]], %[[ARG_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: cir.store %[[ARG_DEC]], %[[RET_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: %[[LOAD_RET:.*]] = cir.load %[[RET_ALLOCA]]
   // CIR: cir.return %[[LOAD_RET]] : !cir.long_double<![[LDTY]]>
   //
   // LLVM: %[[ARG_LOAD:.*]] = load [[LDTY]], ptr %[[ARG_ALLOCA]]
-  // LLVMCIR: %[[ARG_DEC:.*]] = fadd [[LDTY]] -1.000000e+00, %[[ARG_LOAD]]
+  // LLVMCIR: %[[ARG_DEC:.*]] = fsub [[LDTY]] %[[ARG_LOAD]], 1.000000e+00
   // OGCG: %[[ARG_DEC:.*]] = fadd [[LDTY]] %[[ARG_LOAD]], -1.000000e+00
   // LLVM: store [[LDTY]] %[[ARG_DEC]], ptr %[[ARG_ALLOCA]]
   // LLVMCIR: store [[LDTY]] %[[ARG_DEC]], ptr %[[RET_ALLOCA]]
@@ -109,14 +112,15 @@ extern "C" long double do_post_dec(long double d) {
 
   return d--;
   // CIR: %[[ARG_LOAD:.*]]  = cir.load {{.*}}%[[ARG_ALLOCA]] : 
!cir.ptr<!cir.long_double<![[LDTY]]>>, !cir.long_double<![[LDTY]]>
-  // CIR: %[[ARG_DEC:.*]] = cir.dec %[[ARG_LOAD]]
+  // CIR: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<![[LDTY]]>
+  // CIR: %[[ARG_DEC:.*]] = cir.fsub %[[ARG_LOAD]], %[[ONE]]
   // CIR: cir.store{{.*}} %[[ARG_DEC]], %[[ARG_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: cir.store %[[ARG_LOAD]], %[[RET_ALLOCA]] : 
!cir.long_double<![[LDTY]]>, !cir.ptr<!cir.long_double<![[LDTY]]>>
   // CIR: %[[LOAD_RET:.*]] = cir.load %[[RET_ALLOCA]]
   // CIR: cir.return %[[LOAD_RET]] : !cir.long_double<![[LDTY]]>
   //
   // LLVM: %[[ARG_LOAD:.*]] = load [[LDTY]], ptr %[[ARG_ALLOCA]]
-  // LLVMCIR: %[[ARG_DEC:.*]] = fadd [[LDTY]] -1.000000e+00, %[[ARG_LOAD]]
+  // LLVMCIR: %[[ARG_DEC:.*]] = fsub [[LDTY]] %[[ARG_LOAD]], 1.000000e+00
   // OGCG: %[[ARG_DEC:.*]] = fadd [[LDTY]] %[[ARG_LOAD]], -1.000000e+00
   // LLVM: store [[LDTY]] %[[ARG_DEC]], ptr %[[ARG_ALLOCA]]
   // LLVMCIR: store [[LDTY]] %[[ARG_LOAD]], ptr %[[RET_ALLOCA]]
diff --git a/clang/test/CIR/CodeGen/unary.cpp b/clang/test/CIR/CodeGen/unary.cpp
index 2af96583fe34b..0346729170a55 100644
--- a/clang/test/CIR/CodeGen/unary.cpp
+++ b/clang/test/CIR/CodeGen/unary.cpp
@@ -250,7 +250,7 @@ float fpMinus() {
 // CHECK: cir.func{{.*}} @_Z7fpMinusv() -> (!cir.float{{.*}})
 // CHECK:   %[[A:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a", 
init]
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[A]]
-// CHECK:   %[[OUTPUT:.*]] = cir.minus %[[INPUT]]
+// CHECK:   %[[OUTPUT:.*]] = cir.fneg %[[INPUT]]
 
 // LLVM: define{{.*}} float @_Z7fpMinusv()
 // LLVM:   %[[RV:.*]] = alloca float, i64 1, align 4
@@ -275,14 +275,15 @@ float fpPreInc() {
 // CHECK:   %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
 // CHECK:   cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[A]]
-// CHECK:   %[[INCREMENTED:.*]] = cir.inc %[[INPUT]]
+// CHECK:   %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[INCREMENTED:.*]] = cir.fadd %[[INPUT]], %[[ONE]]
 
 // LLVM: define{{.*}} float @_Z8fpPreIncv()
 // LLVM:   %[[RV:.*]] = alloca float, i64 1, align 4
 // LLVM:   %[[A:.*]] = alloca float, i64 1, align 4
 // LLVM:   store float 1.000000e+00, ptr %[[A]], align 4
 // LLVM:   %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4
-// LLVM:   %[[RESULT:.*]] = fadd float 1.000000e+00, %[[A_LOAD]]
+// LLVM:   %[[RESULT:.*]] = fadd float %[[A_LOAD]], 1.000000e+00
 
 // OGCG: define{{.*}} float @_Z8fpPreIncv()
 // OGCG:   %[[A:.*]] = alloca float, align 4
@@ -300,14 +301,15 @@ float fpPreDec() {
 // CHECK:   %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
 // CHECK:   cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[A]]
-// CHECK:   %[[DECREMENTED:.*]] = cir.dec %[[INPUT]]
+// CHECK:   %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[DECREMENTED:.*]] = cir.fsub %[[INPUT]], %[[ONE]]
 
 // LLVM: define{{.*}} float @_Z8fpPreDecv()
 // LLVM:   %[[RV:.*]] = alloca float, i64 1, align 4
 // LLVM:   %[[A:.*]] = alloca float, i64 1, align 4
 // LLVM:   store float 1.000000e+00, ptr %[[A]], align 4
 // LLVM:   %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4
-// LLVM:   %[[RESULT:.*]] = fadd float -1.000000e+00, %[[A_LOAD]]
+// LLVM:   %[[RESULT:.*]] = fsub float %[[A_LOAD]], 1.000000e+00
 
 // OGCG: define{{.*}} float @_Z8fpPreDecv()
 // OGCG:   %[[A:.*]] = alloca float, align 4
@@ -325,14 +327,15 @@ float fpPostInc() {
 // CHECK:   %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
 // CHECK:   cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[A]]
-// CHECK:   %[[INCREMENTED:.*]] = cir.inc %[[INPUT]]
+// CHECK:   %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[INCREMENTED:.*]] = cir.fadd %[[INPUT]], %[[ONE]]
 
 // LLVM: define{{.*}} float @_Z9fpPostIncv()
 // LLVM:   %[[RV:.*]] = alloca float, i64 1, align 4
 // LLVM:   %[[A:.*]] = alloca float, i64 1, align 4
 // LLVM:   store float 1.000000e+00, ptr %[[A]], align 4
 // LLVM:   %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4
-// LLVM:   %[[RESULT:.*]] = fadd float 1.000000e+00, %[[A_LOAD]]
+// LLVM:   %[[RESULT:.*]] = fadd float %[[A_LOAD]], 1.000000e+00
 
 // OGCG: define{{.*}} float @_Z9fpPostIncv()
 // OGCG:   %[[A:.*]] = alloca float, align 4
@@ -350,14 +353,15 @@ float fpPostDec() {
 // CHECK:   %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
 // CHECK:   cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[A]]
-// CHECK:   %[[DECREMENTED:.*]] = cir.dec %[[INPUT]]
+// CHECK:   %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[DECREMENTED:.*]] = cir.fsub %[[INPUT]], %[[ONE]]
 
 // LLVM: define{{.*}} float @_Z9fpPostDecv()
 // LLVM:   %[[RV:.*]] = alloca float, i64 1, align 4
 // LLVM:   %[[A:.*]] = alloca float, i64 1, align 4
 // LLVM:   store float 1.000000e+00, ptr %[[A]], align 4
 // LLVM:   %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4
-// LLVM:   %[[RESULT:.*]] = fadd float -1.000000e+00, %[[A_LOAD]]
+// LLVM:   %[[RESULT:.*]] = fsub float %[[A_LOAD]], 1.000000e+00
 
 // OGCG: define{{.*}} float @_Z9fpPostDecv()
 // OGCG:   %[[A:.*]] = alloca float, align 4
@@ -378,7 +382,8 @@ float fpPostInc2() {
 // CHECK:   %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
 // CHECK:   cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float
 // CHECK:   %[[ATOB:.*]] = cir.load{{.*}} %[[A]]
-// CHECK:   %[[INCREMENTED:.*]] = cir.inc %[[ATOB]]
+// CHECK:   %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[INCREMENTED:.*]] = cir.fadd %[[ATOB]], %[[ONE]]
 // CHECK:   cir.store{{.*}} %[[INCREMENTED]], %[[A]]
 // CHECK:   cir.store{{.*}} %[[ATOB]], %[[B]]
 // CHECK:   %[[B_TO_OUTPUT:.*]] = cir.load{{.*}} %[[B]]
@@ -389,7 +394,7 @@ float fpPostInc2() {
 // LLVM:   %[[B:.*]] = alloca float, i64 1, align 4
 // LLVM:   store float 1.000000e+00, ptr %[[A]], align 4
 // LLVM:   %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4
-// LLVM:   %[[A_INC:.*]] = fadd float 1.000000e+00, %[[A_LOAD]]
+// LLVM:   %[[A_INC:.*]] = fadd float %[[A_LOAD]], 1.000000e+00
 // LLVM:   store float %[[A_INC]], ptr %[[A]], align 4
 // LLVM:   store float %[[A_LOAD]], ptr %[[B]], align 4
 // LLVM:   %[[B_TO_OUTPUT:.*]] = load float, ptr %[[B]], align 4
@@ -448,7 +453,7 @@ _Float16 fp16UMinus(_Float16 f) {
 // CHECK: cir.func{{.*}} @_Z10fp16UMinusDF16_({{.*}}) -> (!cir.f16{{.*}})
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[F:.*]]
 // CHECK:   %[[PROMOTED:.*]] = cir.cast floating %[[INPUT]] : !cir.f16 -> 
!cir.float
-// CHECK:   %[[RESULT:.*]] = cir.minus %[[PROMOTED]]
+// CHECK:   %[[RESULT:.*]] = cir.fneg %[[PROMOTED]]
 // CHECK:   %[[UNPROMOTED:.*]] = cir.cast floating %[[RESULT]] : !cir.float -> 
!cir.f16
 
 // LLVM: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}})
@@ -592,8 +597,8 @@ void f16NestedUMinus() {
 // CHECK:  %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", 
init]
 // CHECK:  %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.f16>, 
!cir.f16
 // CHECK:  %[[A_F32:.*]] = cir.cast floating %[[TMP_A]] : !cir.f16 -> 
!cir.float
-// CHECK:  %[[A_MINUS:.*]] = cir.minus %[[A_F32]] : !cir.float
-// CHECK:  %[[RESULT_F32:.*]] = cir.minus %[[A_MINUS]] : !cir.float
+// CHECK:  %[[A_MINUS:.*]] = cir.fneg %[[A_F32]] : !cir.float
+// CHECK:  %[[RESULT_F32:.*]] = cir.fneg %[[A_MINUS]] : !cir.float
 // CHECK:  %[[RESULT:.*]] = cir.cast floating %[[RESULT_F32]] : !cir.float -> 
!cir.f16
 // CHECK:  cir.store{{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.f16, 
!cir.ptr<!cir.f16>
 
diff --git a/clang/test/CIR/CodeGenOpenACC/atomic-update.cpp 
b/clang/test/CIR/CodeGenOpenACC/atomic-update.cpp
index f1f11259c65c2..751e0f0ea605e 100644
--- a/clang/test/CIR/CodeGenOpenACC/atomic-update.cpp
+++ b/clang/test/CIR/CodeGenOpenACC/atomic-update.cpp
@@ -52,7 +52,8 @@ void use(int x, unsigned int y, float f, HasOps ops) {
   // CHECK-NEXT: cir.store %[[RECIPE_ARG]], %[[TEMP_ALLOCA]] : !cir.float, 
!cir.ptr<!cir.float>
   //
   // CHECK-NEXT: %[[TEMP_LOAD:.*]] = cir.load{{.*}} %[[TEMP_ALLOCA]] : 
!cir.ptr<!cir.float>, !cir.float
-  // CHECK-NEXT: %[[INC:.*]] = cir.dec %[[TEMP_LOAD]] : !cir.float
+  // CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+  // CHECK-NEXT: %[[INC:.*]] = cir.fsub %[[TEMP_LOAD]], %[[ONE]] : !cir.float
   // CHECK-NEXT: cir.store {{.*}}%[[INC]], %[[TEMP_ALLOCA]] : !cir.float, 
!cir.ptr<!cir.float>
   // 
   // CHECK-NEXT: %[[TEMP_LOAD:.*]] = cir.load{{.*}} %[[TEMP_ALLOCA]] : 
!cir.ptr<!cir.float>, !cir.float
diff --git a/clang/test/CIR/IR/unary.cir b/clang/test/CIR/IR/unary.cir
index 1ef1606807935..d9657cf91a04e 100644
--- a/clang/test/CIR/IR/unary.cir
+++ b/clang/test/CIR/IR/unary.cir
@@ -4,6 +4,7 @@
 !s64i = !cir.int<s, 64>
 !u32i = !cir.int<u, 32>
 !u64i = !cir.int<u, 64>
+!cir_vec = !cir.vector<4 x !cir.float>
 
 module {
   cir.func @test_unary_unsigned() {
@@ -42,5 +43,27 @@ module {
 // CHECK:   %4 = cir.inc nsw %1 : !s32i
 // CHECK:   %5 = cir.dec nsw %1 : !s32i
 // CHECK:   cir.return
+// CHECK: }
+
+  cir.func @test_unary_fneg() {
+    %0 = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] {alignment = 4 : 
i64}
+    %1 = cir.load %0 : !cir.ptr<!cir.float>, !cir.float
+    %2 = cir.fneg %1 : !cir.float
+    cir.return
+  }
+// CHECK: cir.func{{.*}} @test_unary_fneg() {
+// CHECK:   %0 = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] {alignment 
= 4 : i64}
+// CHECK:   %1 = cir.load %0 : !cir.ptr<!cir.float>, !cir.float
+// CHECK:   %2 = cir.fneg %1 : !cir.float
+// CHECK:   cir.return
+// CHECK: }
+
+  cir.func @test_unary_fneg_vec(%arg0 : !cir_vec) {
+    %0 = cir.fneg %arg0 : !cir_vec
+    cir.return
+  }
+// CHECK: cir.func{{.*}} @test_unary_fneg_vec(%arg0: !cir.vector<4 x 
!cir.float>) {
+// CHECK:   %0 = cir.fneg %arg0 : !cir.vector<4 x !cir.float>
+// CHECK:   cir.return
 // CHECK: }
 }
diff --git a/clang/test/CIR/Transforms/canonicalize.cir 
b/clang/test/CIR/Transforms/canonicalize.cir
index 26493f7a37e39..a2e68064d9ce3 100644
--- a/clang/test/CIR/Transforms/canonicalize.cir
+++ b/clang/test/CIR/Transforms/canonicalize.cir
@@ -117,24 +117,6 @@ module {
   // CHECK-NEXT:   %[[CONST:.*]] = cir.const #cir.int<4294967294> : !u32i
   // CHECK-NEXT:   cir.return %[[CONST]] : !u32i
 
-  cir.func @unary_minus_true() -> !cir.bool {
-    %0 = cir.const #true
-    %1 = cir.minus %0 : !cir.bool
-    cir.return %1 : !cir.bool
-  }
-  // CHECK:      cir.func{{.*}} @unary_minus_true() -> !cir.bool
-  // CHECK-NEXT:   %[[CONST:.*]] = cir.const #true
-  // CHECK-NEXT:   cir.return %[[CONST]] : !cir.bool
-
-  cir.func @unary_minus_false() -> !cir.bool {
-    %0 = cir.const #false
-    %1 = cir.minus %0 : !cir.bool
-    cir.return %1 : !cir.bool
-  }
-  // CHECK:      cir.func{{.*}} @unary_minus_false() -> !cir.bool
-  // CHECK-NEXT:   %[[CONST:.*]] = cir.const #false
-  // CHECK-NEXT:   cir.return %[[CONST]] : !cir.bool
-
   cir.func @unary_minus_int() -> !s32i {
     %0 = cir.const #cir.int<1> : !s32i
     %1 = cir.minus %0 : !s32i
@@ -153,39 +135,39 @@ module {
   // CHECK-NEXT:   %[[CONST:.*]] = cir.const #cir.int<4294967295> : !u32i
   // CHECK-NEXT:   cir.return %[[CONST]] : !u32i
 
-  cir.func @unary_minus_float() -> !cir.float {
+  cir.func @unary_fneg_float() -> !cir.float {
     %0 = cir.const #cir.fp<1.100000e+00> : !cir.float
-    %1 = cir.minus %0 : !cir.float
+    %1 = cir.fneg %0 : !cir.float
     cir.return %1 : !cir.float
   }
-  // CHECK:      cir.func{{.*}} @unary_minus_float() -> !cir.float
+  // CHECK:      cir.func{{.*}} @unary_fneg_float() -> !cir.float
   // CHECK-NEXT:   %[[CONST:.*]] = cir.const #cir.fp<-1.100000e+00> : 
!cir.float
   // CHECK-NEXT:   cir.return %[[CONST]] : !cir.float
 
-  cir.func @unary_minus_double() -> !cir.double {
+  cir.func @unary_fneg_double() -> !cir.double {
     %0 = cir.const #cir.fp<1.100000e+00> : !cir.double
-    %1 = cir.minus %0 : !cir.double
+    %1 = cir.fneg %0 : !cir.double
     cir.return %1 : !cir.double
   }
-  // CHECK:      cir.func{{.*}} @unary_minus_double() -> !cir.double
+  // CHECK:      cir.func{{.*}} @unary_fneg_double() -> !cir.double
   // CHECK-NEXT:   %[[CONST:.*]] = cir.const #cir.fp<-1.100000e+00> : 
!cir.double
   // CHECK-NEXT:   cir.return %[[CONST]] : !cir.double
 
-  cir.func @unary_minus_nan() -> !cir.float {
+  cir.func @unary_fneg_nan() -> !cir.float {
     %0 = cir.const #cir.fp<0x7F800000> : !cir.float
-    %1 = cir.minus %0 : !cir.float
+    %1 = cir.fneg %0 : !cir.float
     cir.return %1 : !cir.float
   }
-  // CHECK:      cir.func{{.*}} @unary_minus_nan() -> !cir.float
+  // CHECK:      cir.func{{.*}} @unary_fneg_nan() -> !cir.float
   // CHECK-NEXT:   %[[CONST:.*]] = cir.const #cir.fp<0xFF800000> : !cir.float
   // CHECK-NEXT:   cir.return %[[CONST]] : !cir.float
 
-  cir.func @unary_minus_neg_nan() -> !cir.float {
+  cir.func @unary_fneg_neg_nan() -> !cir.float {
     %0 = cir.const #cir.fp<0xFF800000> : !cir.float
-    %1 = cir.minus %0 : !cir.float
+    %1 = cir.fneg %0 : !cir.float
     cir.return %1 : !cir.float
   }
-  // CHECK:      cir.func{{.*}} @unary_minus_neg_nan() -> !cir.float
+  // CHECK:      cir.func{{.*}} @unary_fneg_neg_nan() -> !cir.float
   // CHECK-NEXT:   %[[CONST:.*]] = cir.const #cir.fp<0x7F800000> : !cir.float
   // CHECK-NEXT:   cir.return %[[CONST]] : !cir.float
 
diff --git a/clang/test/CodeGen/AArch64/neon/fullfp16.c 
b/clang/test/CodeGen/AArch64/neon/fullfp16.c
index fd73aa56a7751..ba65f76e924c4 100644
--- a/clang/test/CodeGen/AArch64/neon/fullfp16.c
+++ b/clang/test/CodeGen/AArch64/neon/fullfp16.c
@@ -179,7 +179,7 @@ float16_t test_vrsqrtsh_f16(float16_t a, float16_t b) {
 //===------------------------------------------------------===//
 // ALL-LABEL: @test_vnegh_f16
 float16_t test_vnegh_f16(float16_t a) {
-// CIR: cir.minus {{.*}} : !cir.f16
+// CIR: cir.fneg {{.*}} : !cir.f16
 
 // LLVM-SAME: half{{.*}} [[A:%.*]])
 // LLVM: [[NEG:%.*]] = fneg half [[A:%.*]]
@@ -202,7 +202,7 @@ float16_t test_vfmah_f16(float16_t a, float16_t b, 
float16_t c) {
 
 // ALL-LABEL: test_vfmsh_f16
 float16_t test_vfmsh_f16(float16_t a, float16_t b, float16_t c) {
-// CIR: [[SUB:%.*]] = cir.minus %{{.*}} : !cir.f16
+// CIR: [[SUB:%.*]] = cir.fneg %{{.*}} : !cir.f16
 // CIR: cir.call_llvm_intrinsic "fma" [[SUB]], {{.*}} : (!cir.f16, !cir.f16, 
!cir.f16) -> !cir.f16
 
 // LLVM-SAME: half{{.*}} [[A:%.*]], half{{.*}} [[B:%.*]], half{{.*}} [[C:%.*]])

>From e7a4a8a85be3be91ee9a7ba4f243bf2fad7f556d Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Thu, 4 Jun 2026 17:46:43 -0700
Subject: [PATCH 2/2] Fix formatting

---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp           | 3 +--
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp              | 8 ++++----
 clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp | 3 +--
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 875dd70ecf266..d8b7fa062b845 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -707,8 +707,7 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
         mlir::Location loc = cgf.getLoc(e->getExprLoc());
         auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
         mlir::Value amount = builder.getConstFP(
-            loc, value.getType(),
-            llvm::APFloat(fpType.getFloatSemantics(), 1));
+            loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 
1));
         value = e->isIncrementOp() ? builder.createFAdd(loc, value, amount)
                                    : builder.createFSub(loc, value, amount);
       } else {
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 39807d1dee89a..5b0e8d13e3822 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -3013,8 +3013,8 @@ OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
 
   // Fold with constant inputs. Floating-point negation is handled by
   // cir::FNegOp.
-  if (auto intAttr = mlir::dyn_cast_if_present<cir::IntAttr>(
-          adaptor.getInput())) {
+  if (auto intAttr =
+          mlir::dyn_cast_if_present<cir::IntAttr>(adaptor.getInput())) {
     APInt val = intAttr.getValue();
     val.negate();
     return cir::IntAttr::get(getType(), val);
@@ -3032,8 +3032,8 @@ OpFoldResult cir::FNegOp::fold(FoldAdaptor adaptor) {
     return adaptor.getInput();
 
   // Fold with constant inputs.
-  if (auto fpAttr = mlir::dyn_cast_if_present<cir::FPAttr>(
-          adaptor.getInput())) {
+  if (auto fpAttr =
+          mlir::dyn_cast_if_present<cir::FPAttr>(adaptor.getInput())) {
     APFloat val = fpAttr.getValue();
     val.changeSign();
     return cir::FPAttr::get(getType(), val);
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp 
b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
index da1984d29a797..a88b0accef57c 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
@@ -72,8 +72,7 @@ void CIRCanonicalizePass::runOnOperation() {
     // applyOpPatternsGreedily.
     if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, IncOp, DecOp,
             MinusOp, FNegOp, NotOp, AddOp, MulOp, AndOp, OrOp, XorOp, MaxOp,
-            MinOp,
-            ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,
+            MinOp, ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,
             VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,
             VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitFfsOp, 
BitParityOp,
             BitPopcountOp, BitReverseOp, ByteSwapOp, RotateOp, ConstantOp,

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

Reply via email to