[clang] [CIR] Split ComplexBinOps for float and int (PR #226725)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 26 12:04:43 PDT 2026
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 <amr96 at programmer.net>
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>
More information about the cfe-commits
mailing list