llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Amr Hesham (AmrDeveloper)

<details>
<summary>Changes</summary>

Fix Codegen for emitting comparisons between Complex &amp; Scalar

---
Full diff: https://github.com/llvm/llvm-project/pull/184006.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+13-2) 
- (modified) clang/test/CIR/CodeGen/complex.cpp (+192) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 03c8369753f35..1276ef2611e51 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1204,9 +1204,20 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
     } else {
       // Complex Comparison: can only be an equality comparison.
       assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
-
       BinOpInfo boInfo = emitBinOps(e);
-      result = cir::CmpOp::create(builder, loc, kind, boInfo.lhs, boInfo.rhs);
+      mlir::Value lhs = boInfo.lhs;
+      if (!mlir::isa<cir::ComplexType>(lhs.getType())) {
+        lhs = builder.createComplexCreate(
+            loc, lhs, builder.getNullValue(lhs.getType(), loc));
+      }
+
+      mlir::Value rhs = boInfo.rhs;
+      if (!mlir::isa<cir::ComplexType>(rhs.getType())) {
+        rhs = builder.createComplexCreate(
+            loc, rhs, builder.getNullValue(rhs.getType(), loc));
+      }
+
+      result = builder.createCompare(loc, kind, lhs, rhs);
     }
 
     return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
diff --git a/clang/test/CIR/CodeGen/complex.cpp 
b/clang/test/CIR/CodeGen/complex.cpp
index 734dddc4848b9..9881b15f93621 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1675,3 +1675,195 @@ void load_store_volatile_2() {
 // OGCG: %[[DV_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[DV_ADDR]], i32 0, i32 1
 // OGCG: store volatile i32 %[[D_REAL]], ptr %[[DV_REAL_PTR]], align 4
 // OGCG: store volatile i32 %[[D_IMAG]], ptr %[[DV_IMAG_PTR]], align 4
+
+bool eq_float_complex_and_float(float _Complex a, float b) {
+  return a == b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", 
init]
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, 
["__retval"]
+// CIR: cir.store %[[ARG_0:.*]], %[[A_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
+// CIR: cir.store %[[ARG_1:.*]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.float>, 
!cir.float
+// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: %[[COMPLEX_B:.*]] = cir.complex.create %[[TMP_B]], %[[CONST_0F]] : 
!cir.float -> !cir.complex<!cir.float>
+// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[TMP_A]], %[[COMPLEX_B]]) : 
!cir.complex<!cir.float>, !cir.bool
+// CIR: cir.store %[[RESULT]], %[[RET_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }
+// LLVM: %[[B_ADDR:.*]] = alloca float
+// LLVM: %[[RET_ADDR:.*]] = alloca i8
+// LLVM: store { float, float } %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4
+// LLVM: store float %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4
+// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// LLVM: %[[TMP_COMPLEX_B:.*]] = insertvalue { float, float } {{.*}}, float 
%[[TMP_B]], 0
+// LLVM: %[[COMPLEX_B:.*]] = insertvalue { float, float } %[[TMP_COMPLEX_B]], 
float 0.000000e+00, 1
+// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
+// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
+// LLVM: %[[B_REAL:.*]] = extractvalue { float, float } %[[COMPLEX_B]], 0
+// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[COMPLEX_B]], 1
+// LLVM: %[[REAL_CMP:.*]] = fcmp oeq float %[[A_REAL]], %[[B_REAL]]
+// LLVM: %[[IMAG_CMP:.*]] = fcmp oeq float %[[A_IMAG]], %[[B_IMAG]]
+// LLVM: %[[RESULT:.*]] = and i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+// LLVM: %[[RESULT_I8:.*]] = zext i1 %[[RESULT]] to i8
+// LLVM: store i8 %[[RESULT_I8]], ptr %[[RET_ADDR]], align 1
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: store <2 x float> %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4
+// OGCG: store float %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 0
+// 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: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// OGCG: %[[REAL_CMP:.*]] = fcmp oeq float %[[A_REAL]], %[[TMP_B]]
+// OGCG: %[[IMAG_CMP:.*]] = fcmp oeq float %[[A_IMAG]], 0.000000e+00
+// OGCG: %[[RESULT:.*]] = and i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+
+bool eq_float_and_float_complex(float a, float _Complex b) {
+  return a == b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a", 
init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, 
["__retval"]
+// 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: %[[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>
+
+// LLVM: %[[A_ADDR:.*]] = alloca float
+// LLVM: %[[B_ADDR:.*]] = alloca { float, float }
+// LLVM: %[[RET_ADDR:.*]] = alloca i8
+// 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: %[[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
+// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[TMP_B]], 1
+// LLVM: %[[REAL_CMP:.*]] = fcmp oeq float %[[A_REAL]], %[[B_REAL]]
+// LLVM: %[[IMAG_CMP:.*]] = fcmp oeq float %[[A_IMAG]], %[[B_IMAG]]
+// LLVM: %[[RESULT:.*]] = and i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+// LLVM: %[[RESULT_I8:.*]] = zext i1 %[[RESULT]] to i8
+// LLVM: store i8 %[[RESULT_I8]], ptr %[[RET_ADDR]], align 1
+
+// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[A_ADDR:.*]] = alloca float, align 4
+// OGCG: store <2 x float> %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4
+// OGCG: store float %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4
+// OGCG: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_REAL:.*]] = load float, ptr %[[B_REAL_PTR]], align 4
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[B_ADDR]], i32 0, i32 1
+// OGCG: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 4
+// OGCG: %[[REAL_CMP:.*]] = fcmp oeq float %[[TMP_A]], %[[B_REAL]]
+// OGCG: %[[IMAG_CMP:.*]] = fcmp oeq float 0.000000e+00, %[[B_IMAG]]
+// OGCG: %[[RESULT:.*]] = and i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+
+bool ne_float_complex_and_float(float _Complex a, float b) {
+  return a != b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", 
init]
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, 
["__retval"]
+// CIR: cir.store %[[ARG_0:.*]], %[[A_ADDR]] : !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>
+// CIR: cir.store %[[ARG_1:.*]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : 
!cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.float>, 
!cir.float
+// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
+// CIR: %[[COMPLEX_B:.*]] = cir.complex.create %[[TMP_B]], %[[CONST_0F]] : 
!cir.float -> !cir.complex<!cir.float>
+// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[TMP_A]], %[[COMPLEX_B]]) : 
!cir.complex<!cir.float>, !cir.bool
+// CIR: cir.store %[[RESULT]], %[[RET_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }
+// LLVM: %[[B_ADDR:.*]] = alloca float
+// LLVM: %[[RET_ADDR:.*]] = alloca i8
+// LLVM: store { float, float } %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4
+// LLVM: store float %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4
+// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// LLVM: %[[TMP_COMPLEX_B:.*]] = insertvalue { float, float } {{.*}}, float 
%[[TMP_B]], 0
+// LLVM: %[[COMPLEX_B:.*]] = insertvalue { float, float } %[[TMP_COMPLEX_B]], 
float 0.000000e+00, 1
+// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
+// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
+// LLVM: %[[B_REAL:.*]] = extractvalue { float, float } %[[COMPLEX_B]], 0
+// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[COMPLEX_B]], 1
+// LLVM: %[[REAL_CMP:.*]] = fcmp une float %[[A_REAL]], %[[B_REAL]]
+// LLVM: %[[IMAG_CMP:.*]] = fcmp une float %[[A_IMAG]], %[[B_IMAG]]
+// LLVM: %[[RESULT:.*]] = or i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+// LLVM: %[[RESULT_I8:.*]] = zext i1 %[[RESULT]] to i8
+// LLVM: store i8 %[[RESULT_I8]], ptr %[[RET_ADDR]], align 1
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: store <2 x float> %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4
+// OGCG: store float %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[A_ADDR]], i32 0, i32 0
+// 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: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// OGCG: %[[REAL_CMP:.*]] = fcmp une float %[[A_REAL]], %[[TMP_B]]
+// OGCG: %[[IMAG_CMP:.*]] = fcmp une float %[[A_IMAG]], 0.000000e+00
+// OGCG: %[[RESULT:.*]] = or i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+
+bool ne_float_and_float_complex(float a, float _Complex b) {
+  return a != b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a", 
init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, 
!cir.ptr<!cir.complex<!cir.float>>, ["b", init]
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, 
["__retval"]
+// 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: %[[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>
+
+// LLVM: %[[A_ADDR:.*]] = alloca float
+// LLVM: %[[B_ADDR:.*]] = alloca { float, float }
+// LLVM: %[[RET_ADDR:.*]] = alloca i8
+// 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: %[[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
+// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[TMP_B]], 1
+// LLVM: %[[REAL_CMP:.*]] = fcmp une float %[[A_REAL]], %[[B_REAL]]
+// LLVM: %[[IMAG_CMP:.*]] = fcmp une float %[[A_IMAG]], %[[B_IMAG]]
+// LLVM: %[[RESULT:.*]] = or i1 %[[REAL_CMP]], %[[IMAG_CMP]]
+// LLVM: %[[RESULT_I8:.*]] = zext i1 %[[RESULT]] to i8
+// LLVM: store i8 %[[RESULT_I8]], ptr %[[RET_ADDR]], align 1
+
+// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[A_ADDR:.*]] = alloca float, align 4
+// OGCG: store <2 x float> %[[ARG_1:.*]], ptr %[[B_ADDR]], align 4
+// OGCG: store float %[[ARG_0:.*]], ptr %[[A_ADDR]], align 4
+// OGCG: %[[TMP_A:.*]] = load float, ptr %[[A_ADDR]], align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_REAL:.*]] = load float, ptr %[[B_REAL_PTR]], align 4
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr 
%[[B_ADDR]], i32 0, i32 1
+// OGCG: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 4
+// 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]]

``````````

</details>


https://github.com/llvm/llvm-project/pull/184006
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to