[clang] [CIR] Update ComplexRealOp to work on scalar type (PR #161080)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 30 09:03:07 PDT 2025
=?utf-8?q?“Amr?= <amr96 at programmer.net>,
=?utf-8?q?“Amr?= <amr96 at programmer.net>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/161080 at github.com>
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/161080
>From 569c9fea82815b985c77f478ed6f9074a7490ef2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CAmr?= <amr96 at programmer.net>
Date: Sun, 28 Sep 2025 14:47:13 +0200
Subject: [PATCH 1/3] [CIR] Update ComplexRealOp to work on scalar type
---
.../clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 7 ++++---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 9 +++++----
.../clang/CIR/Dialect/IR/CIRTypeConstraints.td | 6 ++++++
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 6 ++++--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 11 ++++++++++-
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 9 +++++++--
clang/test/CIR/CodeGen/complex.cpp | 9 ++++++---
7 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 3f83c302176c0..ef8f7cf79562f 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -148,9 +148,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
}
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
- auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
- return cir::ComplexRealOp::create(*this, loc, operandTy.getElementType(),
- operand);
+ auto resultType = operand.getType();
+ if (mlir::isa<cir::ComplexType>(resultType))
+ resultType = mlir::cast<cir::ComplexType>(resultType).getElementType();
+ return cir::ComplexRealOp::create(*this, loc, resultType, operand);
}
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e1be08c1bbbbd..85ad79a983a93 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3260,18 +3260,19 @@ def CIR_ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> {
def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> {
let summary = "Extract the real part of a complex value";
let description = [{
- `cir.complex.real` operation takes an operand of `!cir.complex` type and
- yields the real part of it.
+ `cir.complex.real` operation takes an operand of `!cir.complex` or scalar
+ type and yields the real part of it.
Example:
```mlir
- %1 = cir.complex.real %0 : !cir.complex<!cir.float> -> !cir.float
+ %real = cir.complex.real %complex : !cir.complex<!cir.float> -> !cir.float
+ %real = cir.complex.real %scalar : !cir.float -> !cir.float
```
}];
let results = (outs CIR_AnyIntOrFloatType:$result);
- let arguments = (ins CIR_ComplexType:$operand);
+ let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand);
let assemblyFormat = [{
$operand `:` qualified(type($operand)) `->` qualified(type($result))
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 82f6e1d33043e..da03a291a7690 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -165,6 +165,12 @@ def CIR_AnyIntOrFloatType : AnyTypeOf<[CIR_AnyFloatType, CIR_AnyIntType],
def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">;
+def CIR_AnyComplexOrIntOrFloatType : AnyTypeOf<[
+ CIR_AnyComplexType, CIR_AnyFloatType, CIR_AnyIntType
+], "complex, integer or floating point type"> {
+ let cppFunctionName = "isComplexOrIntegerOrFloatingPointType";
+}
+
//===----------------------------------------------------------------------===//
// Array Type predicates
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index f4bbced781942..500007f6f241b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2151,8 +2151,10 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
}
if (e->getOpcode() == UO_Real) {
- return promotionTy.isNull() ? Visit(op)
- : cgf.emitPromotedScalarExpr(op, promotionTy);
+ mlir::Value operand = promotionTy.isNull()
+ ? Visit(op)
+ : cgf.emitPromotedScalarExpr(op, promotionTy);
+ return builder.createComplexReal(loc, operand);
}
// __imag on a scalar returns zero. Emit the subexpr to ensure side
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index fb87036fdfe21..1fedc62dc0522 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2388,14 +2388,23 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
//===----------------------------------------------------------------------===//
LogicalResult cir::ComplexRealOp::verify() {
- if (getType() != getOperand().getType().getElementType()) {
+ mlir::Type operandTy = getOperand().getType();
+ if (mlir::isa<cir::ComplexType>(operandTy)) {
+ operandTy = mlir::cast<cir::ComplexType>(operandTy).getElementType();
+ }
+
+ if (getType() != operandTy) {
emitOpError() << ": result type does not match operand type";
return failure();
}
+
return success();
}
OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
+ if (!mlir::isa<cir::ComplexType>(getOperand().getType()))
+ return nullptr;
+
if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
return complexCreateOp.getOperand(0);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 876948d53010b..664bf55d2b7f5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2992,8 +2992,13 @@ mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
cir::ComplexRealOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
- rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
- op, resultLLVMTy, adaptor.getOperand(), llvm::ArrayRef<std::int64_t>{0});
+ 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();
}
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index 4c396d312d148..f686b804a6f95 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1140,7 +1140,8 @@ void real_on_scalar_glvalue() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float
-// CIR: cir.store{{.*}} %[[TMP_A]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+// CIR: %[[A_REAL:.*]] = cir.complex.real %2 : !cir.float -> !cir.float
+// CIR: cir.store{{.*}} %[[A_REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
@@ -1179,7 +1180,8 @@ void real_on_scalar_with_type_promotion() {
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f16
// CIR: %[[TMP_A_F32:.*]] = cir.cast(floating, %[[TMP_A]] : !cir.f16), !cir.float
-// CIR: %[[TMP_A_F16:.*]] = cir.cast(floating, %[[TMP_A_F32]] : !cir.float), !cir.f16
+// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A_F32]] : !cir.float -> !cir.float
+// CIR: %[[TMP_A_F16:.*]] = cir.cast(floating, %[[A_REAL]] : !cir.float), !cir.f16
// CIR: cir.store{{.*}} %[[TMP_A_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2
@@ -1248,7 +1250,8 @@ void real_on_scalar_from_real_with_type_promotion() {
// CIR: %[[A_IMAG_F32:.*]] = cir.cast(floating, %[[A_IMAG]] : !cir.f16), !cir.float
// CIR: %[[A_COMPLEX_F32:.*]] = cir.complex.create %[[A_REAL_F32]], %[[A_IMAG_F32]] : !cir.float -> !cir.complex<!cir.float>
// CIR: %[[A_REAL_F32:.*]] = cir.complex.real %[[A_COMPLEX_F32]] : !cir.complex<!cir.float> -> !cir.float
-// CIR: %[[A_REAL_F16:.*]] = cir.cast(floating, %[[A_REAL_F32]] : !cir.float), !cir.f16
+// CIR: %[[A_REAL:.*]] = cir.complex.real %[[A_REAL_F32]] : !cir.float -> !cir.float
+// CIR: %[[A_REAL_F16:.*]] = cir.cast(floating, %[[A_REAL]] : !cir.float), !cir.f16
// CIR: cir.store{{.*}} %[[A_REAL_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
// LLVM: %[[A_ADDR:.*]] = alloca { half, half }, i64 1, align 2
>From ea00ca23788920bc6ceaa1e58142d3cc31ee38f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CAmr?= <amr96 at programmer.net>
Date: Mon, 29 Sep 2025 17:45:25 +0200
Subject: [PATCH 2/3] Address code review comments
---
clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 4 ++--
clang/include/clang/CIR/Dialect/IR/CIROps.td | 4 ++--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ef8f7cf79562f..8a5bf0376ec98 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -149,8 +149,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
auto resultType = operand.getType();
- if (mlir::isa<cir::ComplexType>(resultType))
- resultType = mlir::cast<cir::ComplexType>(resultType).getElementType();
+ if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
+ resultType = complexResultType.getElementType();
return cir::ComplexRealOp::create(*this, loc, resultType, operand);
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 85ad79a983a93..c71fb566a041a 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3260,8 +3260,8 @@ def CIR_ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> {
def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> {
let summary = "Extract the real part of a complex value";
let description = [{
- `cir.complex.real` operation takes an operand of `!cir.complex` or scalar
- type and yields the real part of it.
+ `cir.complex.real` operation takes an operand of `!cir.complex`, `!cir.int`
+ or `!cir.float` type and yields the real part of it.
Example:
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 1fedc62dc0522..6b5cc808e9a29 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2389,8 +2389,8 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
LogicalResult cir::ComplexRealOp::verify() {
mlir::Type operandTy = getOperand().getType();
- if (mlir::isa<cir::ComplexType>(operandTy)) {
- operandTy = mlir::cast<cir::ComplexType>(operandTy).getElementType();
+ if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) {
+ operandTy = complexOperandTy.getElementType();
}
if (getType() != operandTy) {
>From 10522fd83c20b42286dc50363eb338b731bf7226 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CAmr?= <amr96 at programmer.net>
Date: Tue, 30 Sep 2025 18:02:43 +0200
Subject: [PATCH 3/3] Address code review comments
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 3 ++-
clang/test/CIR/CodeGen/complex.cpp | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c71fb566a041a..569581da273ea 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3261,7 +3261,8 @@ def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> {
let summary = "Extract the real part of a complex value";
let description = [{
`cir.complex.real` operation takes an operand of `!cir.complex`, `!cir.int`
- or `!cir.float` type and yields the real part of it.
+ or `!cir.float`. If the operand is `!cir.complex`, the real part of it will
+ be returned, otherwise the value returned unmodified.
Example:
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index f686b804a6f95..145a0c32fcaa3 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1140,7 +1140,7 @@ void real_on_scalar_glvalue() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float
-// CIR: %[[A_REAL:.*]] = cir.complex.real %2 : !cir.float -> !cir.float
+// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.float -> !cir.float
// CIR: cir.store{{.*}} %[[A_REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4
More information about the cfe-commits
mailing list