llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> Fix Codegen for Comparison between two Complex bin ops --- Full diff: https://github.com/llvm/llvm-project/pull/185316.diff 2 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+17-11) - (modified) clang/test/CIR/CodeGen/complex.cpp (+84-4) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 1b5ba5ee6783f..4a2973d3824ee 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1196,19 +1196,25 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { result = builder.createCompare(loc, kind, lhs, rhs); } } else { - // Complex Comparison: can only be an equality comparison. - assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE); - BinOpInfo boInfo = emitBinOps(e); - mlir::Value lhs = boInfo.lhs; - if (!lhsTy->isAnyComplexType()) { - lhs = builder.createComplexCreate( - loc, lhs, builder.getNullValue(lhs.getType(), loc)); + assert((e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE) && + "Complex Comparison: can only be an equality comparison"); + + mlir::Value lhs; + if (lhsTy->isAnyComplexType()) { + lhs = cgf.emitComplexExpr(e->getLHS()); + } else { + mlir::Value lhsReal = Visit(e->getLHS()); + mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc); + lhs = builder.createComplexCreate(loc, lhsReal, lhsImag); } - mlir::Value rhs = boInfo.rhs; - if (!rhsTy->isAnyComplexType()) { - rhs = builder.createComplexCreate( - loc, rhs, builder.getNullValue(rhs.getType(), loc)); + mlir::Value rhs; + if (rhsTy->isAnyComplexType()) { + rhs = cgf.emitComplexExpr(e->getRHS()); + } else { + mlir::Value rhsReal = Visit(e->getRHS()); + mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc); + rhs = builder.createComplexCreate(loc, rhsReal, rhsImag); } result = builder.createCompare(loc, kind, lhs, rhs); diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 48b7dd72ae661..421ef6735db7d 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1734,9 +1734,9 @@ bool eq_float_and_float_complex(float a, float _Complex b) { // CIR: cir.store %[[ARG_0:.*]], %[[A_ADDR]] : !cir.float, !cir.ptr<!cir.float> // CIR: cir.store %[[ARG_1:.*]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> // CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float -// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> // CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float // CIR: %[[COMPLEX_A:.*]] = cir.complex.create %[[TMP_A]], %[[CONST_0F]] : !cir.float -> !cir.complex<!cir.float> +// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> // CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[TMP_B]]) : !cir.complex<!cir.float>, !cir.bool // CIR: cir.store %[[RESULT]], %[[RET_ADDR]] : !cir.bool, !cir.ptr<!cir.bool> @@ -1746,9 +1746,9 @@ bool eq_float_and_float_complex(float a, float _Complex b) { // LLVM: store float %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4 // LLVM: store { float, float } %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4 // LLVM: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4 -// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 4 // LLVM: %[[TMP_COMPLEX_A:.*]] = insertvalue { float, float } {{.*}}, float %[[TMP_A]], 0 // LLVM: %[[COMPLEX_A:.*]] = insertvalue { float, float } %[[TMP_COMPLEX_A]], float 0.000000e+00, 1 +// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 4 // LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[COMPLEX_A]], 0 // LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[COMPLEX_A]], 1 // LLVM: %[[B_REAL:.*]] = extractvalue { float, float } %[[TMP_B]], 0 @@ -1830,9 +1830,9 @@ bool ne_float_and_float_complex(float a, float _Complex b) { // CIR: cir.store %[[ARG_0:.*]], %[[A_ADDR]] : !cir.float, !cir.ptr<!cir.float> // CIR: cir.store %[[ARG_1:.*]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> // CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float -// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> // CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float // CIR: %[[COMPLEX_A:.*]] = cir.complex.create %[[TMP_A]], %[[CONST_0F]] : !cir.float -> !cir.complex<!cir.float> +// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> // CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[TMP_B]]) : !cir.complex<!cir.float>, !cir.bool // CIR: cir.store %[[RESULT]], %[[RET_ADDR]] : !cir.bool, !cir.ptr<!cir.bool> @@ -1842,9 +1842,9 @@ bool ne_float_and_float_complex(float a, float _Complex b) { // LLVM: store float %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4 // LLVM: store { float, float } %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4 // LLVM: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4 -// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 4 // LLVM: %[[TMP_COMPLEX_A:.*]] = insertvalue { float, float } {{.*}}, float %[[TMP_A]], 0 // LLVM: %[[COMPLEX_A:.*]] = insertvalue { float, float } %[[TMP_COMPLEX_A]], float 0.000000e+00, 1 +// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 4 // LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[COMPLEX_A]], 0 // LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[COMPLEX_A]], 1 // LLVM: %[[B_REAL:.*]] = extractvalue { float, float } %[[TMP_B]], 0 @@ -1867,3 +1867,83 @@ bool ne_float_and_float_complex(float a, float _Complex b) { // OGCG: %[[REAL_CMP:.*]] = fcmp une float %[[TMP_A]], %[[B_REAL]] // OGCG: %[[IMAG_CMP:.*]] = fcmp une float 0.000000e+00, %[[B_IMAG]] // OGCG: %[[RESULT:.*]] = or i1 %[[REAL_CMP]], %[[IMAG_CMP]] + +void compare_two_complex_bin_ops() { + double _Complex a; + double _Complex b; + bool c = a + b != b + a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["a"] +// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b"] +// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["c", init] +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[COMPLEX_AB:.*]] = cir.complex.add %[[TMP_A]], %[[TMP_B]] : !cir.complex<!cir.double> +// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[COMPLEX_BA:.*]] = cir.complex.add %[[TMP_B]], %[[TMP_A]] : !cir.complex<!cir.double> +// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_AB]], %[[COMPLEX_BA]]) : !cir.complex<!cir.double>, !cir.bool +// CIR: cir.store {{.*}} %[[RESULT]], %[[C_ADDR]] : !cir.bool, !cir.ptr<!cir.bool> + +// LLVM: %[[A_ADDR:.*]] = alloca { double, double }, i64 1, align 8 +// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 8 +// LLVM: %[[C_ADDR:.*]] = alloca i8, i64 1, align 1 +// LLVM: %[[TMP_A:.*]] = load { double, double }, ptr %[[A_ADDR]], align 8 +// LLVM: %[[TMP_B:.*]] = load { double, double }, ptr %[[B_ADDR]], align 8 +// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[TMP_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[TMP_A]], 1 +// LLVM: %[[B_REAL:.*]] = extractvalue { double, double } %[[TMP_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { double, double } %[[TMP_B]], 1 +// LLVM: %[[ADD_AB_REAL:.*]] = fadd double %[[A_REAL]], %[[B_REAL]] +// LLVM: %[[ADD_AB_IMAG:.*]] = fadd double %[[A_IMAG]], %[[B_IMAG]] +// LLVM: %[[TMP_COMPLEX_AB:.*]] = insertvalue { double, double } poison, double %[[ADD_AB_REAL]], 0 +// LLVM: %[[COMPLEX_AB:.*]] = insertvalue { double, double } %[[TMP_COMPLEX_AB]], double %[[ADD_AB_IMAG]], 1 +// LLVM: %[[TMP_B:.*]] = load { double, double }, ptr %[[B_ADDR]], align 8 +// LLVM: %[[TMP_A:.*]] = load { double, double }, ptr %[[A_ADDR]], align 8 +// LLVM: %[[B_REAL:.*]] = extractvalue { double, double } %[[TMP_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { double, double } %[[TMP_B]], 1 +// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[TMP_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[TMP_A]], 1 +// LLVM: %[[ADD_BA_REAL:.*]] = fadd double %[[B_REAL]], %[[A_REAL]] +// LLVM: %[[ADD_BA_IMAG:.*]] = fadd double %[[B_IMAG]], %[[A_IMAG]] +// LLVM: %[[TMP_COMPLEX_BA:.*]] = insertvalue { double, double } poison, double %[[ADD_BA_REAL]], 0 +// LLVM: %[[COMPLEX_BA:.*]] = insertvalue { double, double } %[[TMP_COMPLEX_BA]], double %[[ADD_BA_IMAG]], 1 +// LLVM: %[[AB_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_AB]], 0 +// LLVM: %[[AB_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_AB]], 1 +// LLVM: %[[BA_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_BA]], 0 +// LLVM: %[[BA_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_BA]], 1 +// LLVM: %[[CMP_NE_REAL:.*]] = fcmp une double %[[AB_REAL]], %[[BA_REAL]] +// LLVM: %[[CMP_NE_IMAG:.*]] = fcmp une double %[[AB_IMAG]], %[[BA_IMAG]] +// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_NE_REAL]], %[[CMP_NE_IMAG]] +// LLVM: %[[RESULT_I8:.*]] = zext i1 %[[RESULT]] to i8 +// LLVM: store i8 %[[RESULT_I8]], ptr %[[C_ADDR]], align 1 + +// OGCG: %[[A_ADDR:.*]] = alloca { double, double }, align 8 +// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8 +// OGCG: %[[C_ADDR:.*]] = alloca i8, align 1 +// 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: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_REAL:.*]] = load double, ptr %[[B_REAL_PTR]], align 8 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: %[[B_IMAG:.*]] = load double, ptr %[[B_IMAG_PTR]], align 8 +// OGCG: %[[ADD_AB_REAL:.*]] = fadd double %[[A_REAL]], %[[B_REAL]] +// OGCG: %[[ADD_AB_IMAG:.*]] = fadd double %[[A_IMAG]], %[[B_IMAG]] +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_REAL:.*]] = load double, ptr %[[B_REAL_PTR]], align 8 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: %[[B_IMAG:.*]] = load double, ptr %[[B_IMAG_PTR]], 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: %[[ADD_BA_REAL:.*]] = fadd double %[[B_REAL]], %[[A_REAL]] +// OGCG: %[[ADD_BA_IMAG:.*]] = fadd double %[[B_IMAG]], %[[A_IMAG]] +// OGCG: %[[CMP_NE_REAL:.*]] = fcmp une double %[[ADD_AB_REAL]], %[[ADD_BA_REAL]] +// OGCG: %[[CMP_NE_IMAG:.*]] = fcmp une double %[[ADD_AB_IMAG]], %[[ADD_BA_IMAG]] +// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_NE_REAL]], %[[CMP_NE_IMAG]] +// OGCG: %[[RESULT_I8:.*]] = zext i1 %[[RESULT]] to i8 +// OGCG: store i8 %[[RESULT_I8]], ptr %[[C_ADDR]], align 1 `````````` </details> https://github.com/llvm/llvm-project/pull/185316 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
