https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/147090
Implement AbstractConditionalOperator support for ComplexType https://github.com/llvm/llvm-project/issues/141365 >From af5c642067f9b9c046868920efcf584fdc2eabba Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Fri, 4 Jul 2025 19:13:58 +0200 Subject: [PATCH] [CIR] Implement AbstractConditionalOperator for ComplexType --- clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 23 +++++++ clang/test/CIR/CodeGen/complex.cpp | 70 +++++++++++++++++++-- 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index c000b225f31f3..609e6615de198 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -39,6 +39,8 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv, bool isInit); + mlir::Value + VisitAbstractConditionalOperator(const AbstractConditionalOperator *e); mlir::Value VisitArraySubscriptExpr(Expr *e); mlir::Value VisitBinAssign(const BinaryOperator *e); mlir::Value VisitBinComma(const BinaryOperator *e); @@ -125,6 +127,27 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val, builder.createStore(loc, val, destAddr); } +mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator( + const AbstractConditionalOperator *e) { + mlir::Value condValue = Visit(e->getCond()); + mlir::Location loc = cgf.getLoc(e->getSourceRange()); + + return builder + .create<cir::TernaryOp>( + loc, condValue, + /*thenBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + mlir::Value trueValue = Visit(e->getTrueExpr()); + b.create<cir::YieldOp>(loc, trueValue); + }, + /*elseBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + mlir::Value falseValue = Visit(e->getFalseExpr()); + b.create<cir::YieldOp>(loc, falseValue); + }) + .getResult(); +} + mlir::Value ComplexExprEmitter::VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); } diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 09e0ca03aa540..6f7c2d7800516 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -571,10 +571,10 @@ void foo23(int _Complex a, int _Complex b) { // OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4 // OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1 // OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4 -// OGCG: %[[RESULT_REAL_PT:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0 -// OGCG: %[[RESULT_IMAG_PT:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1 -// OGCG: store i32 %[[B_REAL]], ptr %[[RESULT_REAL_PT]], align 4 -// OGCG: store i32 %[[B_IMAG]], ptr %[[RESULT_IMAG_PT]], align 4 +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1 +// OGCG: store i32 %[[B_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store i32 %[[B_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 void foo24() { int _Complex arr[2]; @@ -654,3 +654,65 @@ void foo26(int _Complex* a) { // OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1 // OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4 // OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4 + +void foo27(bool cond, int _Complex a, int _Complex b) { + int _Complex c = cond ? a : b; +} + +// CIR: %[[COND:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["cond", init] +// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a", init] +// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init] +// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init] +// CIR: %[[TMP_COND:.*]] = cir.load{{.*}} %[[COND]] : !cir.ptr<!cir.bool>, !cir.bool +// CIR: %[[RESULT_VAL:.*]] = cir.ternary(%[[TMP_COND]], true { +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: cir.yield %[[TMP_A]] : !cir.complex<!s32i> +// CIR: }, false { +// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: cir.yield %[[TMP_B]] : !cir.complex<!s32i> +// CIR: }) : (!cir.bool) -> !cir.complex<!s32i> +// CIR: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>> + +// LLVM: %[[COND:.*]] = alloca i8, i64 1, align 1 +// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[TMP_COND:.*]] = load i8, ptr %[[COND]], align 1 +// LLVM: %[[COND_VAL:.*]] = trunc i8 %[[TMP_COND]] to i1 +// LLVM: br i1 %[[COND_VAL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]] +// LLVM: [[TRUE_BB]]: +// LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4 +// LLVM: br label %[[END_BB:.*]] +// LLVM: [[FALSE_BB]]: +// LLVM: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[COMPLEX_B]], align 4 +// LLVM: br label %[[END_BB]] +// LLVM: [[END_BB]]: +// LLVM: %[[RESULT_VAL:.*]] = phi { i32, i32 } [ %[[TMP_B]], %[[FALSE_BB]] ], [ %[[TMP_A]], %[[TRUE_BB]] ] +// LLVM: store { i32, i32 } %[[RESULT_VAL]], ptr %[[RESULT]], align 4 + +// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[COND:.*]] = alloca i8, align 1 +// OGCG: %[[RESULT:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[TMP_COND:.*]] = load i8, ptr %[[COND]], align 1 +// OGCG: %[[COND_VAL:.*]] = trunc i8 %[[TMP_COND]] to i1 +// OGCG: br i1 %[[COND_VAL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]] +// OGCG: [[TRUE_BB]]: +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_A]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: br label %[[END_BB:.*]] +// OGCG: [[FALSE_BB]]: +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 0 +// OGCG: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[COMPLEX_B]], i32 0, i32 1 +// OGCG: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4 +// OGCG: br label %[[END_BB]] +// OGCG: [[END_BB]]: +// OGCG: %[[REAL:.*]] = phi i32 [ %[[A_REAL]], %[[TRUE_BB]] ], [ %[[B_REAL]], %[[FALSE_BB]] ] +// OGCG: %[[IMAG:.*]] = phi i32 [ %[[A_IMAG]], %[[TRUE_BB]] ], [ %[[B_IMAG]], %[[FALSE_BB]] ] +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESULT]], i32 0, i32 1 +// OGCG: store i32 %[[REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store i32 %[[IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits