https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/159916
>From 7b89241b254a52addc12aa9fc217443f6e902ff3 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@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 | 23 ++++-- clang/test/CIR/CodeGen/complex.cpp | 83 ++++++++++++++++++++++ 2 files changed, 101 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 276adcfc5c6be..a9294eacf3e46 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2125,12 +2125,13 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e, "Invalid UnaryOp kind for ComplexType Real or Imag"); Expr *op = e->getSubExpr(); + mlir::Location loc = cgf.getLoc(e->getExprLoc()); + if (op->getType()->isAnyComplexType()) { // If it's an l-value, load through the appropriate subobject l-value. // Note that we have to ask `e` because `op` might be an l-value that // this won't work for, e.g. an Obj-C property. if (e->isGLValue()) { - mlir::Location loc = cgf.getLoc(e->getExprLoc()); mlir::Value complex = cgf.emitComplexExpr(op); if (!promotionTy.isNull()) { complex = cgf.emitPromotedValue(complex, promotionTy); @@ -2147,11 +2148,23 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e, return {}; } - // __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 43f97f24d939a..51bf073af7f33 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1027,3 +1027,86 @@ void foo37() { // OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 // OGCG: store float %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4 // OGCG: store float %[[A_IMAG]], ptr %[[B_IMAG_PTR]], 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 10a44777535709b094ce9d4fa6955d54623e70ae Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@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 51bf073af7f33..83daa4ee170ea 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1028,7 +1028,7 @@ void foo37() { // OGCG: store float %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4 // OGCG: store float %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4 -void real_glvalue() { +void real_on_scalar_glvalue() { float a; float b = __real__ a; } @@ -1048,7 +1048,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; } @@ -1066,7 +1066,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; } @@ -1092,7 +1092,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; } @@ -1110,3 +1110,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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits