https://github.com/AmrDeveloper created 
https://github.com/llvm/llvm-project/pull/226725

Split the Complex binary operations into float and int versions and remove the 
unnecessary range kind from div and mul int ops

>From ff5ec3416adc35a3c7b088930819d877880a7bb3 Mon Sep 17 00:00:00 2001
From: Amr Hesham <[email protected]>
Date: Sat, 26 Sep 2026 19:07:14 +0200
Subject: [PATCH] [CIR] Split ComplexBinOps for float and int

---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      |  34 +++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 106 +++++++--
 .../CIR/Dialect/IR/CIRTypeConstraints.td      |  13 ++
 clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp   |  12 +-
 .../Dialect/Transforms/LoweringPrepare.cpp    | 212 +++++++++++-------
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 174 ++++++++++----
 .../CodeGen/complex-compound-assignment.cpp   |   6 +-
 clang/test/CIR/CodeGen/complex-mul-div.cpp    |  48 ++--
 clang/test/CIR/CodeGen/complex-plus-minus.cpp |  12 +-
 clang/test/CIR/CodeGen/complex.cpp            |   4 +-
 10 files changed, 428 insertions(+), 193 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 36d583cfe9fbe..820e504a9c636 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -328,6 +328,40 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::ComplexImagOp::create(*this, loc, resultType, operand);
   }
 
+  mlir::Value createComplexAdd(mlir::Location loc, mlir::Value lhs,
+                               mlir::Value rhs) {
+    auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
+    if (cir::isAnyFloatingPointType(complexTy.getElementType()))
+      return cir::ComplexFAddOp::create(*this, loc, lhs, rhs);
+    return cir::ComplexAddOp::create(*this, loc, lhs, rhs);
+  }
+
+  mlir::Value createComplexSub(mlir::Location loc, mlir::Value lhs,
+                               mlir::Value rhs) {
+    auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
+    if (cir::isAnyFloatingPointType(complexTy.getElementType()))
+      return cir::ComplexFSubOp::create(*this, loc, lhs, rhs);
+    return cir::ComplexSubOp::create(*this, loc, lhs, rhs);
+  }
+
+  mlir::Value createComplexMul(mlir::Location loc, mlir::Value lhs,
+                               mlir::Value rhs,
+                               cir::ComplexRangeKind rangeKind) {
+    auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
+    if (cir::isAnyFloatingPointType(complexTy.getElementType()))
+      return cir::ComplexFMulOp::create(*this, loc, lhs, rhs, rangeKind);
+    return cir::ComplexMulOp::create(*this, loc, lhs, rhs);
+  }
+
+  mlir::Value createComplexDiv(mlir::Location loc, mlir::Value lhs,
+                               mlir::Value rhs,
+                               cir::ComplexRangeKind rangeKind) {
+    auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
+    if (cir::isAnyFloatingPointType(complexTy.getElementType()))
+      return cir::ComplexFDivOp::create(*this, loc, lhs, rhs, rangeKind);
+    return cir::ComplexDivOp::create(*this, loc, lhs, rhs);
+  }
+
   mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand) {
     return cir::ComplexConjOp::create(*this, loc, operand.getType(), operand);
   }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4996037ea5f56..6ad827cd66e89 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6623,13 +6623,13 @@ def CIR_ComplexImagPtrOp : 
CIR_ComplexPartPtrOp<"complex.imag_ptr"> {
 }
 
 
//===----------------------------------------------------------------------===//
-// ComplexAddOp and ComplexSubOp
+// Complex binary operations
 
//===----------------------------------------------------------------------===//
 
 class CIR_ComplexBinOp<string mnemonic>
     : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
-  let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs);
-  let results = (outs CIR_ComplexType:$result);
+  let arguments = (ins CIR_ComplexOfIntType:$lhs, CIR_ComplexOfIntType:$rhs);
+  let results = (outs CIR_ComplexOfIntType:$result);
 
   let assemblyFormat = [{
     $lhs `,` $rhs `:` qualified(type($result)) attr-dict
@@ -6645,7 +6645,7 @@ def CIR_ComplexAddOp : CIR_ComplexBinOp<"complex.add"> {
     Example:
 
     ```
-    %2 = cir.complex.add %0, %1 : !cir.complex<!cir.float>
+    %2 = cir.complex.add %0, %1 : !cir.complex<s32i>
     ```
   }];
 }
@@ -6659,13 +6659,83 @@ def CIR_ComplexSubOp : CIR_ComplexBinOp<"complex.sub"> {
     Example:
 
     ```
-    %2 = cir.complex.sub %0, %1 : !cir.complex<!cir.float>
+    %2 = cir.complex.sub %0, %1 : !cir.complex<s32i>
+    ```
+  }];
+}
+
+def CIR_ComplexMulOp : CIR_ComplexBinOp<"complex.mul"> {
+  let summary = "Complex subtraction";
+  let description = [{
+    The `cir.complex.mul` operation takes two complex numbers and returns
+    their product.
+
+    Example:
+
+    ```
+    %2 = cir.complex.mul %0, %1 : !cir.complex<s32i>
+    ```
+  }];
+
+  let hasLLVMLowering = false;
+}
+
+def CIR_ComplexDivOp : CIR_ComplexBinOp<"complex.div"> {
+  let summary = "Complex subtraction";
+  let description = [{
+    The `cir.complex.div` operation takes two complex numbers and returns
+    their quotient.
+
+    Example:
+
+    ```
+    %2 = cir.complex.div %0, %1 : !cir.complex<s32i>
+    ```
+  }];
+
+  let hasLLVMLowering = false;
+}
+
+class CIR_ComplexFPBinOp<string mnemonic>
+    : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
+  let arguments = (ins CIR_ComplexOfFloatType:$lhs, 
CIR_ComplexOfFloatType:$rhs);
+  let results = (outs CIR_ComplexOfFloatType:$result);
+
+  let assemblyFormat = [{
+    $lhs `,` $rhs `:` qualified(type($result)) attr-dict
+  }];
+}
+
+def CIR_ComplexFAddOp : CIR_ComplexFPBinOp<"complex.fadd"> {
+  let summary = "Complex addition";
+  let description = [{
+    The `cir.complex.fadd` operation takes two complex numbers and returns
+    their sum.
+
+    Example:
+
+    ```
+    %2 = cir.complex.fadd %0, %1 : !cir.complex<!cir.float>
+    ```
+  }];
+}
+
+def CIR_ComplexFSubOp : CIR_ComplexFPBinOp<"complex.fsub"> {
+  let summary = "Complex subtraction";
+  let description = [{
+    The `cir.complex.fsub` operation takes two complex numbers and returns
+    their difference.
+
+    Example:
+
+    ```
+    %2 = cir.complex.fsub %0, %1 : !cir.complex<!cir.float>
     ```
   }];
 }
 
 
//===----------------------------------------------------------------------===//
-// ComplexMulOp and ComplexDivOp
+// Complex binary operations with range
 
//===----------------------------------------------------------------------===//
 
 def CIR_ComplexRangeKind : CIR_I32Enum<
@@ -6682,12 +6752,12 @@ def CIR_ComplexRangeKindAttr
 class CIR_ComplexRangeBinOp<string mnemonic>
     : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
   let arguments = (ins
-    CIR_ComplexType:$lhs,
-    CIR_ComplexType:$rhs,
+    CIR_ComplexOfFloatType:$lhs,
+    CIR_ComplexOfFloatType:$rhs,
     CIR_ComplexRangeKindAttr:$range
   );
 
-  let results = (outs CIR_ComplexType:$result);
+  let results = (outs CIR_ComplexOfFloatType:$result);
 
   let assemblyFormat = [{
     $lhs `,` $rhs `range` `(` enum($range) `)` `:` qualified(type($result))
@@ -6697,16 +6767,15 @@ class CIR_ComplexRangeBinOp<string mnemonic>
   let hasLLVMLowering = false;
 }
 
-def CIR_ComplexMulOp : CIR_ComplexRangeBinOp<"complex.mul"> {
+def CIR_ComplexFMulOp : CIR_ComplexRangeBinOp<"complex.fmul"> {
   let summary = "Complex multiplication";
   let description = [{
     The `cir.complex.mul` operation takes two complex numbers and returns
     their product.
 
-    For complex types with floating-point components, the `range` attribute
-    specifies the algorithm to be used when the operation is lowered to
-    the LLVM dialect. For multiplication, 'improved', 'promoted', and 'basic'
-    are all handled equivalently, producing the algebraic formula with no
+    The `range` attribute specifies the algorithm to be used when the 
operation 
+    is lowered to the LLVM dialect. For multiplication, 'improved', 'promoted',
+    and 'basic' are all handled equivalently, producing the algebraic formula 
with no
     special handling for NaN value. If 'full' is used, a runtime-library
     function is called if one of the intermediate calculations produced
     a NaN value.
@@ -6720,16 +6789,15 @@ def CIR_ComplexMulOp : 
CIR_ComplexRangeBinOp<"complex.mul"> {
   }];
 }
 
-def CIR_ComplexDivOp : CIR_ComplexRangeBinOp<"complex.div"> {
+def CIR_ComplexFDivOp : CIR_ComplexRangeBinOp<"complex.fdiv"> {
   let summary = "Complex division";
   let description = [{
     The `cir.complex.div` operation takes two complex numbers and returns
     their quotient.
 
-    For complex types with floating-point components, the `range` attribute
-    specifies the algorithm to be used when the operation is lowered to
-    the LLVM dialect. For division, 'improved' produces Smith's algorithms for
-    Complex division with no additional handling for NaN values. If 'promoted'
+    The `range` attribute specifies the algorithm to be used when the 
operation 
+    is lowered to the LLVM dialect. For division, 'improved' produces Smith's 
algorithms
+    for Complex division with no additional handling for NaN values. If 
'promoted'
     is used, the values are promoted to a higher precision type, if possible,
     and the calculation is performed using the algebraic formula, with
     no additional handling for NaN values. We fall back on Smith's algorithm
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index c6afa74ba051f..a3de83f6cab63 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -202,6 +202,19 @@ def CIR_AnyIntOrBoolOrFloatType
 
 def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">;
 
+class CIR_ComplexElementTypePred<Pred pred> : SubstLeaves<"$_self",
+    "::mlir::cast<::cir::ComplexType>($_self).getElementType()", pred>;
+
+class CIR_ComplexTypeOf<list<Type> types, string summary = "">
+    : CIR_ConfinedType<CIR_AnyComplexType,
+        [Or<!foreach(type, types, 
CIR_ComplexElementTypePred<type.predicate>)>],
+        !if(!empty(summary),
+            "complex of " # CIR_TypeSummaries<types>.value,
+            summary)>;
+
+def CIR_ComplexOfIntType : CIR_ComplexTypeOf<[CIR_AnyIntType]>;
+def CIR_ComplexOfFloatType : CIR_ComplexTypeOf<[CIR_AnyFloatType]>;
+
 def CIR_AnyComplexOrIntOrBoolOrFloatType
     : AnyTypeOf<[CIR_AnyComplexType, CIR_AnyIntOrBoolOrFloatType],
                 "complex, integer, boolean or floating point type"> {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 91535c57132bd..7dd24a6d076e8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -623,7 +623,7 @@ mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo 
&op) {
 
   if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
       mlir::isa<cir::ComplexType>(op.rhs.getType()))
-    return cir::ComplexAddOp::create(builder, op.loc, op.lhs, op.rhs);
+    return builder.createComplexAdd(op.loc, op.lhs, op.rhs);
 
   auto createAdd = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
     return cir::isFPOrVectorOfFPType(a.getType())
@@ -651,7 +651,7 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo 
&op) {
 
   if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
       mlir::isa<cir::ComplexType>(op.rhs.getType()))
-    return cir::ComplexSubOp::create(builder, op.loc, op.lhs, op.rhs);
+    return builder.createComplexSub(op.loc, op.lhs, op.rhs);
 
   auto createSub = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
     return cir::isFPOrVectorOfFPType(a.getType())
@@ -704,8 +704,7 @@ mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo 
&op) {
       mlir::isa<cir::ComplexType>(op.rhs.getType())) {
     cir::ComplexRangeKind rangeKind =
         getComplexRangeAttr(op.fpFeatures.getComplexRange());
-    return cir::ComplexMulOp::create(builder, op.loc, op.lhs, op.rhs,
-                                     rangeKind);
+    return builder.createComplexMul(op.loc, op.lhs, op.rhs, rangeKind);
   }
 
   auto createMul = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
@@ -742,8 +741,7 @@ mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo 
&op) {
       mlir::isa<cir::ComplexType>(op.rhs.getType())) {
     cir::ComplexRangeKind rangeKind =
         getComplexRangeAttr(op.fpFeatures.getComplexRange());
-    return cir::ComplexDivOp::create(builder, op.loc, op.lhs, op.rhs,
-                                     rangeKind);
+    return builder.createComplexDiv(op.loc, op.lhs, op.rhs, rangeKind);
   }
 
   // The C99 standard (G.5.1) defines division of a complex value by a real
@@ -763,7 +761,7 @@ mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo 
&op) {
   mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue);
   cir::ComplexRangeKind rangeKind =
       getComplexRangeAttr(op.fpFeatures.getComplexRange());
-  return cir::ComplexDivOp::create(builder, op.loc, lhs, op.rhs, rangeKind);
+  return builder.createComplexDiv(op.loc, lhs, op.rhs, rangeKind);
 }
 
 mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result,
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 9a3c9c9745eaa..7d30c71bb10ac 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -89,6 +89,8 @@ struct LoweringPreparePass
   void lowerComplexConjOp(cir::ComplexConjOp op);
   void lowerComplexDivOp(cir::ComplexDivOp op);
   void lowerComplexMulOp(cir::ComplexMulOp op);
+  void lowerComplexFDivOp(cir::ComplexFDivOp op);
+  void lowerComplexFMulOp(cir::ComplexFMulOp op);
   void lowerGetGlobalOp(cir::GetGlobalOp op);
   void lowerGlobalOp(cir::GlobalOp op);
   void lowerThreeWayCmpOp(cir::CmpThreeWayOp op);
@@ -941,61 +943,81 @@ static mlir::Type 
higherPrecisionElementTypeForComplexArithmetic(
   return {};
 }
 
-static mlir::Value
-lowerComplexDiv(LoweringPreparePass &pass, CIRBaseBuilderTy &builder,
-                mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal,
-                mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag,
-                mlir::MLIRContext &mlirCx,
-                const clang::TargetInfo &targetInfo) {
+static mlir::Value lowerComplexFDiv(LoweringPreparePass &pass,
+                                    CIRBaseBuilderTy &builder,
+                                    mlir::Location loc, cir::ComplexFDivOp op,
+                                    mlir::Value lhsReal, mlir::Value lhsImag,
+                                    mlir::Value rhsReal, mlir::Value rhsImag,
+                                    mlir::MLIRContext &mlirCx,
+                                    const clang::TargetInfo &targetInfo) {
   cir::ComplexType complexTy = op.getType();
-  if (mlir::isa<cir::FPTypeInterface>(complexTy.getElementType())) {
-    cir::ComplexRangeKind range = op.getRange();
-    if (range == cir::ComplexRangeKind::Improved)
+  cir::ComplexRangeKind range = op.getRange();
+  switch (range) {
+  case ComplexRangeKind::Full: {
+    return buildComplexBinOpLibCall(pass, builder, &getComplexDivLibCallName,
+                                    loc, complexTy, lhsReal, lhsImag, rhsReal,
+                                    rhsImag);
+  }
+  case ComplexRangeKind::Improved: {
+    return buildRangeReductionComplexDiv(builder, loc, lhsReal, lhsImag,
+                                         rhsReal, rhsImag);
+  }
+  case ComplexRangeKind::Promoted: {
+    mlir::Type originalElementType = complexTy.getElementType();
+    mlir::Type higherPrecisionElementType =
+        higherPrecisionElementTypeForComplexArithmetic(
+            mlirCx, targetInfo, pass.getLangOpts(), builder,
+            originalElementType);
+
+    if (!higherPrecisionElementType)
       return buildRangeReductionComplexDiv(builder, loc, lhsReal, lhsImag,
                                            rhsReal, rhsImag);
 
-    if (range == cir::ComplexRangeKind::Full)
-      return buildComplexBinOpLibCall(pass, builder, &getComplexDivLibCallName,
-                                      loc, complexTy, lhsReal, lhsImag, 
rhsReal,
-                                      rhsImag);
-
-    if (range == cir::ComplexRangeKind::Promoted) {
-      mlir::Type originalElementType = complexTy.getElementType();
-      mlir::Type higherPrecisionElementType =
-          higherPrecisionElementTypeForComplexArithmetic(
-              mlirCx, targetInfo, pass.getLangOpts(), builder,
-              originalElementType);
-
-      if (!higherPrecisionElementType)
-        return buildRangeReductionComplexDiv(builder, loc, lhsReal, lhsImag,
-                                             rhsReal, rhsImag);
-
-      cir::CastKind floatingCastKind = cir::CastKind::floating;
-      lhsReal = builder.createCast(floatingCastKind, lhsReal,
-                                   higherPrecisionElementType);
-      lhsImag = builder.createCast(floatingCastKind, lhsImag,
-                                   higherPrecisionElementType);
-      rhsReal = builder.createCast(floatingCastKind, rhsReal,
-                                   higherPrecisionElementType);
-      rhsImag = builder.createCast(floatingCastKind, rhsImag,
-                                   higherPrecisionElementType);
-
-      mlir::Value algebraicResult = buildAlgebraicComplexDiv(
-          builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
-
-      mlir::Value resultReal = builder.createComplexReal(loc, algebraicResult);
-      mlir::Value resultImag = builder.createComplexImag(loc, algebraicResult);
-
-      mlir::Value finalReal =
-          builder.createCast(floatingCastKind, resultReal, 
originalElementType);
-      mlir::Value finalImag =
-          builder.createCast(floatingCastKind, resultImag, 
originalElementType);
-      return builder.createComplexCreate(loc, finalReal, finalImag);
-    }
+    cir::CastKind floatingCastKind = cir::CastKind::floating;
+    lhsReal = builder.createCast(floatingCastKind, lhsReal,
+                                 higherPrecisionElementType);
+    lhsImag = builder.createCast(floatingCastKind, lhsImag,
+                                 higherPrecisionElementType);
+    rhsReal = builder.createCast(floatingCastKind, rhsReal,
+                                 higherPrecisionElementType);
+    rhsImag = builder.createCast(floatingCastKind, rhsImag,
+                                 higherPrecisionElementType);
+
+    mlir::Value algebraicResult = buildAlgebraicComplexDiv(
+        builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
+
+    mlir::Value resultReal = builder.createComplexReal(loc, algebraicResult);
+    mlir::Value resultImag = builder.createComplexImag(loc, algebraicResult);
+
+    mlir::Value finalReal =
+        builder.createCast(floatingCastKind, resultReal, originalElementType);
+    mlir::Value finalImag =
+        builder.createCast(floatingCastKind, resultImag, originalElementType);
+    return builder.createComplexCreate(loc, finalReal, finalImag);
   }
+  case ComplexRangeKind::Basic: {
+    return buildAlgebraicComplexDiv(builder, loc, lhsReal, lhsImag, rhsReal,
+                                    rhsImag);
+  }
+  }
+}
+
+void LoweringPreparePass::lowerComplexFDivOp(cir::ComplexFDivOp op) {
+  cir::CIRBaseBuilderTy builder(getContext());
+  builder.setInsertionPointAfter(op);
+  mlir::Location loc = op.getLoc();
+  mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
+  mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
+  mlir::Value lhsReal = builder.createComplexReal(loc, lhs);
+  mlir::Value lhsImag = builder.createComplexImag(loc, lhs);
+  mlir::Value rhsReal = builder.createComplexReal(loc, rhs);
+  mlir::Value rhsImag = builder.createComplexImag(loc, rhs);
 
-  return buildAlgebraicComplexDiv(builder, loc, lhsReal, lhsImag, rhsReal,
-                                  rhsImag);
+  mlir::Value loweredResult =
+      lowerComplexFDiv(*this, builder, loc, op, lhsReal, lhsImag, rhsReal,
+                       rhsImag, getContext(), getTargetInfo());
+  op.replaceAllUsesWith(loweredResult);
+  op.erase();
 }
 
 void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) {
@@ -1009,9 +1031,8 @@ void 
LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) {
   mlir::Value rhsReal = builder.createComplexReal(loc, rhs);
   mlir::Value rhsImag = builder.createComplexImag(loc, rhs);
 
-  mlir::Value loweredResult =
-      lowerComplexDiv(*this, builder, loc, op, lhsReal, lhsImag, rhsReal,
-                      rhsImag, getContext(), getTargetInfo());
+  mlir::Value loweredResult = buildAlgebraicComplexDiv(
+      builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
   op.replaceAllUsesWith(loweredResult);
   op.erase();
 }
@@ -1036,36 +1057,26 @@ getComplexMulLibCallName(llvm::APFloat::Semantics 
semantics) {
   }
 }
 
-static mlir::Value lowerComplexMul(LoweringPreparePass &pass,
-                                   CIRBaseBuilderTy &builder,
-                                   mlir::Location loc, cir::ComplexMulOp op,
-                                   mlir::Value lhsReal, mlir::Value lhsImag,
-                                   mlir::Value rhsReal, mlir::Value rhsImag) {
+static mlir::Value lowerComplexFMul(LoweringPreparePass &pass,
+                                    CIRBaseBuilderTy &builder,
+                                    mlir::Location loc, cir::ComplexFMulOp op,
+                                    mlir::Value lhsReal, mlir::Value lhsImag,
+                                    mlir::Value rhsReal, mlir::Value rhsImag) {
   // (a+bi) * (c+di) = (ac-bd) + (ad+bc)i
-  bool isFP = cir::isFPOrVectorOfFPType(lhsReal.getType());
-  auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
-    return isFP ? builder.createFMul(l, x, y) : builder.createMul(l, x, y);
-  };
-  auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
-    return isFP ? builder.createFAdd(l, x, y) : builder.createAdd(l, x, y);
-  };
-  auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
-    return isFP ? builder.createFSub(l, x, y) : builder.createSub(l, x, y);
-  };
-
-  mlir::Value resultRealLhs = mul(loc, lhsReal, rhsReal); // ac
-  mlir::Value resultRealRhs = mul(loc, lhsImag, rhsImag); // bd
-  mlir::Value resultImagLhs = mul(loc, lhsReal, rhsImag); // ad
-  mlir::Value resultImagRhs = mul(loc, lhsImag, rhsReal); // bc
-  mlir::Value resultReal = sub(loc, resultRealLhs, resultRealRhs);
-  mlir::Value resultImag = add(loc, resultImagLhs, resultImagRhs);
+  mlir::Value resultRealLhs = builder.createFMul(loc, lhsReal, rhsReal); // ac
+  mlir::Value resultRealRhs = builder.createFMul(loc, lhsImag, rhsImag); // bd
+  mlir::Value resultImagLhs = builder.createFMul(loc, lhsReal, rhsImag); // ad
+  mlir::Value resultImagRhs = builder.createFMul(loc, lhsImag, rhsReal); // bc
+  mlir::Value resultReal =
+      builder.createFSub(loc, resultRealLhs, resultRealRhs);
+  mlir::Value resultImag =
+      builder.createFAdd(loc, resultImagLhs, resultImagRhs);
   mlir::Value algebraicResult =
       builder.createComplexCreate(loc, resultReal, resultImag);
 
   cir::ComplexType complexTy = op.getType();
   cir::ComplexRangeKind rangeKind = op.getRange();
-  if (mlir::isa<cir::IntType>(complexTy.getElementType()) ||
-      rangeKind == cir::ComplexRangeKind::Basic ||
+  if (rangeKind == cir::ComplexRangeKind::Basic ||
       rangeKind == cir::ComplexRangeKind::Improved ||
       rangeKind == cir::ComplexRangeKind::Promoted)
     return algebraicResult;
@@ -1094,6 +1105,24 @@ static mlir::Value lowerComplexMul(LoweringPreparePass 
&pass,
       .getResult();
 }
 
+void LoweringPreparePass::lowerComplexFMulOp(cir::ComplexFMulOp op) {
+  cir::CIRBaseBuilderTy builder(getContext());
+  builder.setInsertionPointAfter(op);
+  mlir::Location loc = op.getLoc();
+  mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
+  mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
+
+  // (a+bi) * (c+di) = (ac-bd) + (ad+bc)i
+  mlir::Value lhsReal = builder.createComplexReal(loc, lhs);
+  mlir::Value lhsImag = builder.createComplexImag(loc, lhs);
+  mlir::Value rhsReal = builder.createComplexReal(loc, rhs);
+  mlir::Value rhsImag = builder.createComplexImag(loc, rhs);
+  mlir::Value loweredResult = lowerComplexFMul(*this, builder, loc, op, 
lhsReal,
+                                               lhsImag, rhsReal, rhsImag);
+  op.replaceAllUsesWith(loweredResult);
+  op.erase();
+}
+
 void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
   cir::CIRBaseBuilderTy builder(getContext());
   builder.setInsertionPointAfter(op);
@@ -1104,8 +1133,17 @@ void 
LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
   mlir::Value lhsImag = builder.createComplexImag(loc, lhs);
   mlir::Value rhsReal = builder.createComplexReal(loc, rhs);
   mlir::Value rhsImag = builder.createComplexImag(loc, rhs);
-  mlir::Value loweredResult = lowerComplexMul(*this, builder, loc, op, lhsReal,
-                                              lhsImag, rhsReal, rhsImag);
+
+  mlir::Value resultRealLhs = builder.createMul(loc, lhsReal, rhsReal); // ac
+  mlir::Value resultRealRhs = builder.createMul(loc, lhsImag, rhsImag); // bd
+  mlir::Value resultImagLhs = builder.createMul(loc, lhsReal, rhsImag); // ad
+  mlir::Value resultImagRhs = builder.createMul(loc, lhsImag, rhsReal); // bc
+  mlir::Value resultReal = builder.createSub(loc, resultRealLhs, 
resultRealRhs);
+  mlir::Value resultImag = builder.createAdd(loc, resultImagLhs, 
resultImagRhs);
+
+  mlir::Value loweredResult =
+      builder.createComplexCreate(loc, resultReal, resultImag);
+
   op.replaceAllUsesWith(loweredResult);
   op.erase();
 }
@@ -1154,9 +1192,9 @@ cir::FuncOp 
LoweringPreparePass::getOrCreateDtorFunc(CIRBaseBuilderTy &builder,
   //   cir.call %_ZN1SD1Ev(%0) : (!cir.ptr<!rec_S>) -> ()
   //   (implicit cir.yield)
   //
-  // That is, if the second operation is a call that takes the get_global 
result
-  // as its only operand, and the only other operation is a yield, then we can
-  // just return the called function.
+  // That is, if the second operation is a call that takes the get_global
+  // result as its only operand, and the only other operation is a yield, then
+  // we can just return the called function.
   if (dtorBlock.getOperations().size() == 3) {
     auto callOp = mlir::dyn_cast<cir::CallOp>(&*(++opIt));
     auto yieldOp = mlir::dyn_cast<cir::YieldOp>(&*(++opIt));
@@ -2459,6 +2497,10 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) {
     lowerCastOp(cast);
   } else if (auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
     lowerComplexConjOp(complexConj);
+  } else if (auto complexDiv = mlir::dyn_cast<cir::ComplexFDivOp>(op)) {
+    lowerComplexFDivOp(complexDiv);
+  } else if (auto complexMul = mlir::dyn_cast<cir::ComplexFMulOp>(op)) {
+    lowerComplexFMulOp(complexMul);
   } else if (auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
     lowerComplexDivOp(complexDiv);
   } else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
@@ -3084,10 +3126,10 @@ void LoweringPreparePass::runOnOperation() {
   mlirModule->walk([&](mlir::Operation *op) {
     if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
                   cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
-                  cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
-                  cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
-                  cir::CmpThreeWayOp, cir::LocalInitOp, cir::StdOpInterface>(
-            op))
+                  cir::ComplexFMulOp, cir::ComplexFDivOp, cir::DynamicCastOp,
+                  cir::FuncOp, cir::CallOp, cir::GetGlobalOp, cir::GlobalOp,
+                  cir::StoreOp, cir::CmpThreeWayOp, cir::LocalInitOp,
+                  cir::StdOpInterface>(op))
       opsToTransform.push_back(op);
   });
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4bdbe38df24e8..5a6a1a33ea333 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5219,6 +5219,60 @@ mlir::LogicalResult 
CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
+    cir::ComplexCreateOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type complexLLVMTy =
+      getTypeConverter()->convertType(op.getResult().getType());
+  auto initialComplex =
+      mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
+
+  auto realComplex = mlir::LLVM::InsertValueOp::create(
+      rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
+      ArrayRef(int64_t{0}));
+
+  auto complex = mlir::LLVM::InsertValueOp::create(
+      rewriter, op->getLoc(), realComplex, adaptor.getImag(),
+      ArrayRef(int64_t{1}));
+
+  rewriter.replaceOp(op, complex);
+  return mlir::success();
+}
+
+mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
+    cir::ComplexRealOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
+  mlir::Value operand = adaptor.getOperand();
+  if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
+    operand = mlir::LLVM::ExtractValueOp::create(
+        rewriter, op.getLoc(), resultLLVMTy, operand,
+        llvm::ArrayRef<std::int64_t>{0});
+  }
+  rewriter.replaceOp(op, operand);
+  return mlir::success();
+}
+
+mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
+    cir::ComplexImagOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
+  mlir::Value operand = adaptor.getOperand();
+  mlir::Location loc = op.getLoc();
+
+  if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
+    operand = mlir::LLVM::ExtractValueOp::create(
+        rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
+  } else {
+    mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
+    operand =
+        mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
+  }
+
+  rewriter.replaceOp(op, operand);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
     cir::ComplexAddOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
@@ -5268,40 +5322,6 @@ mlir::LogicalResult 
CIRToLLVMComplexAddOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
-mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
-    cir::ComplexCreateOp op, OpAdaptor adaptor,
-    mlir::ConversionPatternRewriter &rewriter) const {
-  mlir::Type complexLLVMTy =
-      getTypeConverter()->convertType(op.getResult().getType());
-  auto initialComplex =
-      mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
-
-  auto realComplex = mlir::LLVM::InsertValueOp::create(
-      rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
-      ArrayRef(int64_t{0}));
-
-  auto complex = mlir::LLVM::InsertValueOp::create(
-      rewriter, op->getLoc(), realComplex, adaptor.getImag(),
-      ArrayRef(int64_t{1}));
-
-  rewriter.replaceOp(op, complex);
-  return mlir::success();
-}
-
-mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
-    cir::ComplexRealOp op, OpAdaptor adaptor,
-    mlir::ConversionPatternRewriter &rewriter) const {
-  mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
-  mlir::Value operand = adaptor.getOperand();
-  if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
-    operand = mlir::LLVM::ExtractValueOp::create(
-        rewriter, op.getLoc(), resultLLVMTy, operand,
-        llvm::ArrayRef<std::int64_t>{0});
-  }
-  rewriter.replaceOp(op, operand);
-  return mlir::success();
-}
-
 mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
     cir::ComplexSubOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
@@ -5351,23 +5371,83 @@ mlir::LogicalResult 
CIRToLLVMComplexSubOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
-mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
-    cir::ComplexImagOp op, OpAdaptor adaptor,
+mlir::LogicalResult CIRToLLVMComplexFAddOpLowering::matchAndRewrite(
+    cir::ComplexFAddOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
-  mlir::Value operand = adaptor.getOperand();
+  mlir::Value lhs = adaptor.getLhs();
+  mlir::Value rhs = adaptor.getRhs();
   mlir::Location loc = op.getLoc();
 
-  if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
-    operand = mlir::LLVM::ExtractValueOp::create(
-        rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
-  } else {
-    mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
-    operand =
-        mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
-  }
+  auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
+  mlir::Type complexElemTy =
+      getTypeConverter()->convertType(complexType.getElementType());
+  auto lhsReal = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
+  auto lhsImag = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
+  auto rhsReal = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
+  auto rhsImag = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
+
+  assert(!cir::MissingFeatures::fastMathFlags());
+  assert(!cir::MissingFeatures::fpConstraints());
+  mlir::Value newReal = mlir::LLVM::FAddOp::create(rewriter, loc, 
complexElemTy,
+                                                   lhsReal, rhsReal);
+  mlir::Value newImag = mlir::LLVM::FAddOp::create(rewriter, loc, 
complexElemTy,
+                                                   lhsImag, rhsImag);
+
+  mlir::Type complexLLVMTy =
+      getTypeConverter()->convertType(op.getResult().getType());
+  auto initialComplex =
+      mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
+
+  auto realComplex = mlir::LLVM::InsertValueOp::create(
+      rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
+
+  rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
+      op, realComplex, newImag, ArrayRef(int64_t{1}));
+
+  return mlir::success();
+}
+
+mlir::LogicalResult CIRToLLVMComplexFSubOpLowering::matchAndRewrite(
+    cir::ComplexFSubOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Value lhs = adaptor.getLhs();
+  mlir::Value rhs = adaptor.getRhs();
+  mlir::Location loc = op.getLoc();
+
+  auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
+  mlir::Type complexElemTy =
+      getTypeConverter()->convertType(complexType.getElementType());
+  auto lhsReal = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
+  auto lhsImag = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
+  auto rhsReal = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
+  auto rhsImag = mlir::LLVM::ExtractValueOp::create(
+      rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
+
+  assert(!cir::MissingFeatures::fastMathFlags());
+  assert(!cir::MissingFeatures::fpConstraints());
+  mlir::Value newReal = mlir::LLVM::FSubOp::create(rewriter, loc, 
complexElemTy,
+                                                   lhsReal, rhsReal);
+  mlir::Value newImag = mlir::LLVM::FSubOp::create(rewriter, loc, 
complexElemTy,
+                                                   lhsImag, rhsImag);
+
+  mlir::Type complexLLVMTy =
+      getTypeConverter()->convertType(op.getResult().getType());
+  auto initialComplex =
+      mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
+
+  auto realComplex = mlir::LLVM::InsertValueOp::create(
+      rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
+
+  rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
+      op, realComplex, newImag, ArrayRef(int64_t{1}));
 
-  rewriter.replaceOp(op, operand);
   return mlir::success();
 }
 
diff --git a/clang/test/CIR/CodeGen/complex-compound-assignment.cpp 
b/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
index e56717f064fa6..ba79157f38254 100644
--- a/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
+++ b/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
@@ -21,7 +21,7 @@ void foo() {
 // CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[RESULT:.*]] = cir.complex.add %[[TMP_B]], %[[TMP_A]] : 
!cir.complex<!cir.float>
+// CIR: %[[RESULT:.*]] = cir.complex.fadd %[[TMP_B]], %[[TMP_A]] : 
!cir.complex<!cir.float>
 // CIR: cir.store{{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
 
 // LLVM: %[[A_ADDR:.*]] = alloca { float, float }, align 4
@@ -65,7 +65,7 @@ void foo1() {
 // CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[RESULT:.*]] = cir.complex.sub %[[TMP_B]], %[[TMP_A]] : 
!cir.complex<!cir.float>
+// CIR: %[[RESULT:.*]] = cir.complex.fsub %[[TMP_B]], %[[TMP_A]] : 
!cir.complex<!cir.float>
 // CIR: cir.store{{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
 
 // LLVM: %[[A_ADDR:.*]] = alloca { float, float }, align 4
@@ -163,7 +163,7 @@ void foo3() {
 // CIR: %[[B_REAL_F32:.*]] = cir.cast floating %[[B_REAL]] : !cir.f16 -> 
!cir.float
 // CIR: %[[B_IMAG_F32:.*]] = cir.cast floating %[[B_IMAG]] : !cir.f16 -> 
!cir.float
 // CIR: %[[B_COMPLEX_F32:.*]] = cir.complex.create %[[B_REAL_F32]], 
%[[B_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>
-// CIR: %[[ADD_A_B:.*]] = cir.complex.add %[[B_COMPLEX_F32]], 
%[[A_COMPLEX_F32]] : !cir.complex<!cir.float>
+// CIR: %[[ADD_A_B:.*]] = cir.complex.fadd %[[B_COMPLEX_F32]], 
%[[A_COMPLEX_F32]] : !cir.complex<!cir.float>
 // CIR: %[[ADD_REAL:.*]] = cir.complex.real %[[ADD_A_B]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR: %[[ADD_IMAG:.*]] = cir.complex.imag %[[ADD_A_B]] : 
!cir.complex<!cir.float> -> !cir.float
 // CIR: %[[ADD_REAL_F16:.*]] = cir.cast floating %[[ADD_REAL]] : !cir.float -> 
!cir.f16
diff --git a/clang/test/CIR/CodeGen/complex-mul-div.cpp 
b/clang/test/CIR/CodeGen/complex-mul-div.cpp
index 13e3b39f7f10b..b357199ad2f10 100644
--- a/clang/test/CIR/CodeGen/complex-mul-div.cpp
+++ b/clang/test/CIR/CodeGen/complex-mul-div.cpp
@@ -40,11 +40,11 @@ void foo() {
   float _Complex c = a * b;
 }
 
-// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(basic) : 
!cir.complex<!cir.float>
+// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.fmul {{.*}}, {{.*}} range(basic) : 
!cir.complex<!cir.float>
 
-// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} 
range(improved) : !cir.complex<!cir.float>
+// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.fmul {{.*}}, {{.*}} 
range(improved) : !cir.complex<!cir.float>
 
-// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!cir.float>
+// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.fmul {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!cir.float>
 
 // CIR-AFTER-MUL-COMBINED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER-MUL-COMBINED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -105,7 +105,7 @@ void foo() {
 // OGCG-MUL-COMBINED: store float %[[C_REAL]], ptr %[[C_REAL_PTR]], align 4
 // OGCG-MUL-COMBINED: store float %[[C_IMAG]], ptr %[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-FULL: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(full) : 
!cir.complex<!cir.float>
+// CIR-BEFORE-FULL: %{{.*}} = cir.complex.fmul {{.*}}, {{.*}} range(full) : 
!cir.complex<!cir.float>
 
 // CIR-AFTER-FULL: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER-FULL: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -217,13 +217,13 @@ void foo1() {
   int _Complex c = a * b;
 }
 
-// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(basic) : 
!cir.complex<!s32i>
+// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} 
range(improved) : !cir.complex<!s32i>
+// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!s32i>
+// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-FULL: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(full) : 
!cir.complex<!s32i>
+// CIR-BEFORE-FULL: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
 // CIR-AFTER-INT: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>
 // CIR-AFTER-INT: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>
@@ -336,7 +336,7 @@ void foo3() {
   float _Complex c = a / b;
 }
 
-// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(basic) : 
!cir.complex<!cir.float>
+// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} range(basic) : 
!cir.complex<!cir.float>
 
 // CIR-AFTER-BASIC: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER-BASIC: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -412,7 +412,7 @@ void foo3() {
 // OGCG-BASIC: store float %[[RESULT_REAL]], ptr %[[C_REAL_PTR]], align 4
 // OGCG-BASIC: store float %[[RESULT_IMAG]], ptr %[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(improved) : !cir.complex<!cir.float>
+// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} 
range(improved) : !cir.complex<!cir.float>
 
 // CIR-AFTER-IMPROVED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER-IMPROVED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -543,7 +543,7 @@ void foo3() {
 // OGCG-IMPROVED:  store float %[[RESULT_REAL]], ptr %[[C_REAL_PTR]], align 4
 // OGCG-IMPROVED:  store float %[[RESULT_IMAG]], ptr %[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!cir.float>
+// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!cir.float>
 
 // CIR-AFTER-PROMOTED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER-PROMOTED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -642,7 +642,7 @@ void foo3() {
 // OGCG-PROMOTED: store float %[[UNPROMOTION_RESULT_REAL]], ptr 
%[[C_REAL_PTR]], align 4
 // OGCG-PROMOTED: store float %[[UNPROMOTION_RESULT_IMAG]], ptr 
%[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-FULL: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(full) : 
!cir.complex<!cir.float>
+// CIR-BEFORE-FULL: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} range(full) : 
!cir.complex<!cir.float>
 
 // CIR-AFTER-FULL: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-AFTER-FULL: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -702,13 +702,13 @@ void foo4() {
   int _Complex c = a / b;
 }
 
-// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(basic) : 
!cir.complex<!s32i>
+// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(improved) : !cir.complex<!s32i>
+// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!s32i>
+// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-FULL: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(full) : 
!cir.complex<!s32i>
+// CIR-BEFORE-FULL: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
 // CIR-COMBINED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>
 // CIR-COMBINED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>
@@ -836,7 +836,7 @@ void foo6() {
   float _Complex c = a / b;
 }
 
-// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(basic) : 
!cir.complex<!cir.float>
+// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} range(basic) : 
!cir.complex<!cir.float>
 
 // CIR-AFTER-BASIC: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.float>
 // CIR-AFTER-BASIC: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -911,7 +911,7 @@ void foo6() {
 // OGCG-BASIC: store float %[[RESULT_REAL]], ptr %[[C_REAL_PTR]], align 4
 // OGCG-BASIC: store float %[[RESULT_IMAG]], ptr %[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(improved) : !cir.complex<!cir.float>
+// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} 
range(improved) : !cir.complex<!cir.float>
 
 // CIR-AFTER-IMPROVED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.float>
 // CIR-AFTER-IMPROVED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -1041,7 +1041,7 @@ void foo6() {
 // OGCG-IMPROVED:  store float %[[RESULT_REAL]], ptr %[[C_REAL_PTR]], align 4
 // OGCG-IMPROVED:  store float %[[RESULT_IMAG]], ptr %[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!cir.float>
+// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!cir.float>
 
 // CIR-AFTER-PROMOTED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.float>
 // CIR-AFTER-PROMOTED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -1137,7 +1137,7 @@ void foo6() {
 // OGCG-PROMOTED: store float %[[UNPROMOTION_RESULT_REAL]], ptr 
%[[C_REAL_PTR]], align 4
 // OGCG-PROMOTED: store float %[[UNPROMOTION_RESULT_IMAG]], ptr 
%[[C_IMAG_PTR]], align 4
 
-// CIR-BEFORE-FULL: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(full) : 
!cir.complex<!cir.float>
+// CIR-BEFORE-FULL: %{{.*}} = cir.complex.fdiv {{.*}}, {{.*}} range(full) : 
!cir.complex<!cir.float>
 
 // CIR-AFTER-FULL: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.float>
 // CIR-AFTER-FULL: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
@@ -1196,13 +1196,13 @@ void foo7() {
   int _Complex c = a / b;
 }
 
-// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(basic) : 
!cir.complex<!s32i>
+// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(improved) : !cir.complex<!s32i>
+// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} 
range(promoted) : !cir.complex<!s32i>
+// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
-// CIR-BEFORE-FULL: %{{.*}} = cir.complex.div {{.*}}, {{.*}} range(full) : 
!cir.complex<!s32i>
+// CIR-BEFORE-FULL: %{{.*}} = cir.complex.div {{.*}}, {{.*}} : 
!cir.complex<!s32i>
 
 // CIR-COMBINED: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : 
!cir.ptr<!cir.complex<!s32i>>
 // CIR-COMBINED: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!s32i>
diff --git a/clang/test/CIR/CodeGen/complex-plus-minus.cpp 
b/clang/test/CIR/CodeGen/complex-plus-minus.cpp
index 31c16310786fe..b0949364f6e0e 100644
--- a/clang/test/CIR/CodeGen/complex-plus-minus.cpp
+++ b/clang/test/CIR/CodeGen/complex-plus-minus.cpp
@@ -58,7 +58,7 @@ void foo2() {
 // CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[ADD:.*]] = cir.complex.add %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
+// CIR: %[[ADD:.*]] = cir.complex.fadd %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
 
 // LLVM: %[[A_ADDR:.*]] = alloca { float, float }, align 4
 // LLVM: %[[B_ADDR:.*]] = alloca { float, float }, align 4
@@ -104,9 +104,9 @@ void foo3() {
 // CIR: %[[RESULT:.*]] = cir.alloca "d" {{.*}} init : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[ADD_A_B:.*]] = cir.complex.add %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
+// CIR: %[[ADD_A_B:.*]] = cir.complex.fadd %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
 // CIR: %[[TMP_C:.*]] = cir.load{{.*}} %[[C_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[ADD_A_B_C:.*]] = cir.complex.add %[[ADD_A_B]], %[[TMP_C]] : 
!cir.complex<!cir.float>
+// CIR: %[[ADD_A_B_C:.*]] = cir.complex.fadd %[[ADD_A_B]], %[[TMP_C]] : 
!cir.complex<!cir.float>
 // CIR: cir.store{{.*}} %[[ADD_A_B_C]], %[[RESULT]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // LLVM: %[[A_ADDR:.*]] = alloca { float, float }, align 4
@@ -214,7 +214,7 @@ void foo5() {
 // CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[SUB:.*]] = cir.complex.sub %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
+// CIR: %[[SUB:.*]] = cir.complex.fsub %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
 
 // LLVM: %[[A_ADDR:.*]] = alloca { float, float }, align 4
 // LLVM: %[[B_ADDR:.*]] = alloca { float, float }, align 4
@@ -260,9 +260,9 @@ void foo6() {
 // CIR: %[[RESULT:.*]] = cir.alloca "d" {{.*}} init : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
 // CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[SUB_A_B:.*]] = cir.complex.sub %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
+// CIR: %[[SUB_A_B:.*]] = cir.complex.fsub %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.float>
 // CIR: %[[TMP_C:.*]] = cir.load{{.*}} %[[C_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[SUB_A_B_C:.*]] = cir.complex.sub %[[SUB_A_B]], %[[TMP_C]] : 
!cir.complex<!cir.float>
+// CIR: %[[SUB_A_B_C:.*]] = cir.complex.fsub %[[SUB_A_B]], %[[TMP_C]] : 
!cir.complex<!cir.float>
 // CIR: cir.store{{.*}} %[[SUB_A_B_C]], %[[RESULT]] : 
!cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
 
 // LLVM: %[[A_ADDR:.*]] = alloca { float, float }, align 4
diff --git a/clang/test/CIR/CodeGen/complex.cpp 
b/clang/test/CIR/CodeGen/complex.cpp
index 99b30cae657b5..1a3c7e6b6d3af 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1984,10 +1984,10 @@ void compare_two_complex_bin_ops() {
 // CIR: %[[C_ADDR:.*]] = cir.alloca "c" {{.*}} init : !cir.ptr<!cir.bool>
 // CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
 // CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
-// CIR: %[[COMPLEX_AB:.*]] = cir.complex.add %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.double>
+// CIR: %[[COMPLEX_AB:.*]] = cir.complex.fadd %[[TMP_A]], %[[TMP_B]] : 
!cir.complex<!cir.double>
 // CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
 // CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
-// CIR: %[[COMPLEX_BA:.*]] = cir.complex.add %[[TMP_B]], %[[TMP_A]] : 
!cir.complex<!cir.double>
+// CIR: %[[COMPLEX_BA:.*]] = cir.complex.fadd %[[TMP_B]], %[[TMP_A]] : 
!cir.complex<!cir.double>
 // CIR: %[[RESULT:.*]] = cir.cmp ne %[[COMPLEX_AB]], %[[COMPLEX_BA]] : 
!cir.complex<!cir.double>
 // CIR: cir.store {{.*}} %[[RESULT]], %[[C_ADDR]] : !cir.bool, 
!cir.ptr<!cir.bool>
 

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

Reply via email to