Author: Amr Hesham Date: 2026-08-05T04:21:27Z New Revision: 442469093a0ea00244b39dfb8ab26545439fe363
URL: https://github.com/llvm/llvm-project/commit/442469093a0ea00244b39dfb8ab26545439fe363 DIFF: https://github.com/llvm/llvm-project/commit/442469093a0ea00244b39dfb8ab26545439fe363.diff LOG: [CIR] Fix imag value in Scalar and Complex substraction (#214019) Fix imaginary value in Scalar and Complex subtraction Issue #213998 Added: Modified: clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp clang/test/CIR/CodeGen/complex-plus-minus.cpp Removed: ################################################################################ diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 2d99d3111e903..8780122ee2db2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -666,11 +666,17 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) { return builder.createComplexCreate(op.loc, newReal, imag); } + auto createNeg = [&](mlir::Location loc, mlir::Value a) { + return cir::isFPOrVectorOfFPType(a.getType()) ? builder.createFNeg(loc, a) + : builder.createNeg(loc, a); + }; + assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); mlir::Value real = builder.createComplexReal(op.loc, op.rhs); mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); mlir::Value newReal = createSub(op.loc, op.lhs, real); - return builder.createComplexCreate(op.loc, newReal, imag); + mlir::Value newImag = createNeg(op.loc, imag); + return builder.createComplexCreate(op.loc, newReal, newImag); } static cir::ComplexRangeKind diff --git a/clang/test/CIR/CodeGen/complex-plus-minus.cpp b/clang/test/CIR/CodeGen/complex-plus-minus.cpp index de3c1e127f0e1..d432d3ee96942 100644 --- a/clang/test/CIR/CodeGen/complex-plus-minus.cpp +++ b/clang/test/CIR/CodeGen/complex-plus-minus.cpp @@ -315,3 +315,75 @@ void foo6() { // OGCG: store float %[[SUB_REAL_A_B_C]], ptr %[[RESULT_REAL_PTR]], align 4 // OGCG: store float %[[SUB_IMAG_A_B_C]], ptr %[[RESULT_IMAG_PTR]], align 4 +void scalar_complex_minus() { + double real = 0.5; + double imag = -0.25; + double _Complex a = __builtin_complex(real, imag); + double _Complex b = real - a; +} + +// CIR: %[[REAL_ADDR:.*]] = cir.alloca "real" {{.*}} init : !cir.ptr<!cir.double> +// CIR: %[[IMAG_ADDR:.*]] = cir.alloca "imag" {{.*}} init : !cir.ptr<!cir.double> +// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} init : !cir.ptr<!cir.complex<!cir.double>> +// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} init : !cir.ptr<!cir.complex<!cir.double>> +// CIR: %[[CONST_5F:.*]] = cir.const #cir.fp<5.000000e-01> : !cir.double +// CIR: cir.store {{.*}} %[[CONST_5F]], %[[REAL_ADDR]] : !cir.double, !cir.ptr<!cir.double> +// CIR: %[[CONST_N2_5F:.*]] = cir.const #cir.fp<-2.500000e-01> : !cir.double +// CIR: cir.store {{.*}} %[[CONST_N2_5F]], %[[IMAG_ADDR]] : !cir.double, !cir.ptr<!cir.double> +// CIR: %[[TMP_REAL:.*]] = cir.load {{.*}} %[[REAL_ADDR]] : !cir.ptr<!cir.double>, !cir.double +// CIR: %[[TMP_IMAG:.*]] = cir.load {{.*}} %[[IMAG_ADDR]] : !cir.ptr<!cir.double>, !cir.double +// CIR: %[[COMPLEX_A:.*]] = cir.complex.create %[[TMP_REAL]], %[[TMP_IMAG]] : !cir.double -> !cir.complex<!cir.double> +// CIR: cir.store {{.*}} %[[COMPLEX_A]], %[[A_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>> +// CIR: %[[TMP_REAL:.*]] = cir.load {{.*}} %[[REAL_ADDR]] : !cir.ptr<!cir.double>, !cir.double +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.double> -> !cir.double +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.double> -> !cir.double +// CIR: %[[RESULT_REAL:.*]] = cir.fsub %[[TMP_REAL]], %[[A_REAL]] : !cir.double +// CIR: %[[RESULT_IMAG:.*]] = cir.fneg %[[A_IMAG]] : !cir.double +// CIR: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], %[[RESULT_IMAG]] : !cir.double -> !cir.complex<!cir.double> +// CIR: cir.store {{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>> + +// LLVM: %[[REAL_ADDR:.*]] = alloca double, i64 1, align 8 +// LLVM: %[[IMAG_ADDR:.*]] = alloca double, i64 1, align 8 +// LLVM: %[[A_ADDR:.*]] = alloca { double, double }, i64 1, align 8 +// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 8 +// LLVM: store double 5.000000e-01, ptr %[[REAL_ADDR]], align 8 +// LLVM: store double -2.500000e-01, ptr %[[IMAG_ADDR]], align 8 +// LLVM: %[[TMP_REAL:.*]] = load double, ptr %[[REAL_ADDR]], align 8 +// LLVM: %[[TMP_IMAG:.*]] = load double, ptr %[[IMAG_ADDR]], align 8 +// LLVM: %[[TMP_COMPLEX_A:.*]] = insertvalue { double, double } {{.*}}, double %[[TMP_REAL]], 0 +// LLVM: %[[COMPLEX_A:.*]] = insertvalue { double, double } %[[TMP_COMPLEX_A]], double %[[TMP_IMAG]], 1 +// LLVM: store { double, double } %[[COMPLEX_A]], ptr %[[A_ADDR]], align 8 +// LLVM: %[[TMP_REAL:.*]] = load double, ptr %[[REAL_ADDR]], align 8 +// LLVM: %[[TMP_A:.*]] = load { double, double }, ptr %[[A_ADDR]], align 8 +// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[TMP_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[TMP_A]], 1 +// LLVM: %[[RESULT_REAL:.*]] = fsub double %[[TMP_REAL]], %[[A_REAL]] +// LLVM: %[[RESULT_IMAG:.*]] = fneg double %[[A_IMAG]] +// LLVM: %[[TMP_RESULT:.*]] = insertvalue { double, double } {{.*}}, double %[[RESULT_REAL]], 0 +// LLVM: %[[RESULT:.*]] = insertvalue { double, double } %[[TMP_RESULT]], double %[[RESULT_IMAG]], 1 +// LLVM: store { double, double } %[[RESULT]], ptr %[[B_ADDR]], align 8 + +// OGCG: %[[REAL_ADDR:.*]] = alloca double, align 8 +// OGCG: %[[IMAG_ADDR:.*]] = alloca double, align 8 +// OGCG: %[[A_ADDR:.*]] = alloca { double, double }, align 8 +// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8 +// OGCG: store double 5.000000e-01, ptr %[[REAL_ADDR]], align 8 +// OGCG: store double -2.500000e-01, ptr %[[IMAG_ADDR]], align 8 +// OGCG: %[[TMP_REAL:.*]] = load double, ptr %[[REAL_ADDR]], align 8 +// OGCG: %[[TMP_IMAG:.*]] = load double, ptr %[[IMAG_ADDR]], align 8 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store double %[[TMP_REAL]], ptr %[[A_REAL_PTR]], align 8 +// OGCG: store double %[[TMP_IMAG]], ptr %[[A_IMAG_PTR]], align 8 +// OGCG: %[[TMP_REAL:.*]] = load double, ptr %[[REAL_ADDR]], align 8 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8 +// OGCG: %[[RESULT_REAL:.*]] = fsub double %[[TMP_REAL]], %[[A_REAL]] +// OGCG: %[[RESULT_IMAG:.*]] = fneg double %[[A_IMAG]] +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store double %[[RESULT_REAL]], ptr %[[B_REAL_PTR]], align 8 +// OGCG: store double %[[RESULT_IMAG]], ptr %[[B_IMAG_PTR]], align 8 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
