[clang] [CIR] Implement Unary real & imag on scalar expr (PR #159916)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 24 10:35:12 PDT 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/159916
>From c2fd4826027f715829f638c8b1ba67146d3512f9 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 20 Sep 2025 13:03:39 +0200
Subject: [PATCH 1/2] [CIR] Implement Unary real & imag on scalar expr
---
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 20 ++++-
clang/test/CIR/CodeGen/complex.cpp | 85 +++++++++++++++++++++-
2 files changed, 100 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 85f73fa214eec..3b22c689ecd9f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2140,11 +2140,23 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
: builder.createComplexImag(loc, complex);
}
- // __real or __imag on a scalar returns zero. Emit the subexpr to ensure side
+ if (e->getOpcode() == UO_Real) {
+ return promotionTy.isNull() ? Visit(op)
+ : cgf.emitPromotedScalarExpr(op, promotionTy);
+ }
+
+ // __imag on a scalar returns zero. Emit the subexpr to ensure side
// effects are evaluated, but not the actual value.
- cgf.cgm.errorNYI(e->getSourceRange(),
- "VisitRealImag __real or __imag on a scalar");
- return {};
+ if (op->isGLValue())
+ cgf.emitLValue(op);
+ else if (!promotionTy.isNull())
+ cgf.emitPromotedScalarExpr(op, promotionTy);
+ else
+ cgf.emitScalarExpr(op);
+
+ mlir::Type valueTy =
+ cgf.convertType(promotionTy.isNull() ? e->getType() : promotionTy);
+ return builder.getNullValue(valueTy, loc);
}
/// Return the size or alignment of the type of argument of the sizeof
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index b6fcd5210ad34..1d3c10a9cb5bc 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1092,4 +1092,87 @@ void imag_on_non_glvalue() {
// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
-// OGCG: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 4
\ No newline at end of file
+// OGCG: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 4
+
+void real_glvalue() {
+ float a;
+ float b = __real__ a;
+}
+
+// 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>
+
+// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4
+// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4
+// LLVM: store float %[[TMP_A]], ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4
+// OGCG: store float %[[TMP_A]], ptr %[[B_ADDR]], align 4
+
+void imag_glvalue() {
+ float a;
+ float b = __imag__ a;
+}
+
+// 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: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[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
+// LLVM: store float 0.000000e+00, ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: store float 0.000000e+00, ptr %[[B_ADDR]], align 4
+
+void real_glvalue_with_type_promotion() {
+ _Float16 a;
+ _Float16 b = __real__ a;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"]
+// 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: cir.store{{.*}} %[[TMP_A_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
+
+// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2
+// LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 2
+// LLVM: %[[TMP_A:.*]] = load half, ptr %[[A_ADDR]], align 2
+// LLVM: %[[TMP_A_F32:.*]] = fpext half %[[TMP_A]] to float
+// LLVM: %[[TMP_A_F16:.*]] = fptrunc float %[[TMP_A_F32]] to half
+// LLVM: store half %[[TMP_A_F16]], ptr %[[B_ADDR]], align 2
+
+// OGCG: %[[A_ADDR:.*]] = alloca half, align 2
+// OGCG: %[[B_ADDR:.*]] = alloca half, align 2
+// OGCG: %[[TMP_A:.*]] = load half, ptr %[[A_ADDR]], align 2
+// OGCG: %[[TMP_A_F32:.*]] = fpext half %[[TMP_A]] to float
+// OGCG: %[[TMP_A_F16:.*]] = fptrunc float %[[TMP_A_F32]] to half
+// OGCG: store half %[[TMP_A_F16]], ptr %[[B_ADDR]], align 2
+
+void imagl_glvalue_with_type_promotion() {
+ _Float16 a;
+ _Float16 b = __imag__ a;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]
+// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: %[[CONST_ZERO_F16:.*]] = cir.cast(floating, %[[CONST_ZERO]] : !cir.float), !cir.f16
+// CIR: cir.store{{.*}} %[[CONST_ZERO_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
+
+// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2
+// LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 2
+// LLVM: store half 0xH0000, ptr %[[B_ADDR]], align 2
+
+// OGCG: %[[A_ADDR:.*]] = alloca half, align 2
+// OGCG: %[[B_ADDR:.*]] = alloca half, align 2
+// OGCG: store half 0xH0000, ptr %[[B_ADDR]], align 2
>From c14adeab873b2fdb1e9fdabdc368b747eb600aac Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Tue, 23 Sep 2025 18:04:13 +0200
Subject: [PATCH 2/2] Rename test functions & Add one more test function
---
clang/test/CIR/CodeGen/complex.cpp | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index 1d3c10a9cb5bc..db9678c802721 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1094,7 +1094,7 @@ void imag_on_non_glvalue() {
// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
// OGCG: store float %[[A_IMAG]], ptr %[[B_ADDR]], align 4
-void real_glvalue() {
+void real_on_scalar_glvalue() {
float a;
float b = __real__ a;
}
@@ -1114,7 +1114,7 @@ void real_glvalue() {
// OGCG: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4
// OGCG: store float %[[TMP_A]], ptr %[[B_ADDR]], align 4
-void imag_glvalue() {
+void imag_on_scalar_glvalue() {
float a;
float b = __imag__ a;
}
@@ -1132,7 +1132,7 @@ void imag_glvalue() {
// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
// OGCG: store float 0.000000e+00, ptr %[[B_ADDR]], align 4
-void real_glvalue_with_type_promotion() {
+void real_on_scalar_with_type_promotion() {
_Float16 a;
_Float16 b = __real__ a;
}
@@ -1158,7 +1158,7 @@ void real_glvalue_with_type_promotion() {
// OGCG: %[[TMP_A_F16:.*]] = fptrunc float %[[TMP_A_F32]] to half
// OGCG: store half %[[TMP_A_F16]], ptr %[[B_ADDR]], align 2
-void imagl_glvalue_with_type_promotion() {
+void imag_on_scalar_with_type_promotion() {
_Float16 a;
_Float16 b = __imag__ a;
}
@@ -1176,3 +1176,22 @@ void imagl_glvalue_with_type_promotion() {
// OGCG: %[[A_ADDR:.*]] = alloca half, align 2
// OGCG: %[[B_ADDR:.*]] = alloca half, align 2
// OGCG: store half 0xH0000, ptr %[[B_ADDR]], align 2
+
+void imag_on_const_scalar() {
+ float a;
+ float b = __imag__ 1.0f;
+}
+
+// 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: %[[CONST_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[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
+// LLVM: store float 0.000000e+00, ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: store float 0.000000e+00, ptr %[[B_ADDR]], align 4
More information about the cfe-commits
mailing list