https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/146129
>From 964a930b9f96423d04155b9972bfd8540c59d911 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Fri, 27 Jun 2025 20:10:48 +0200 Subject: [PATCH 1/3] [CIR] Implement NotEqualOp for ComplexType --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 25 +++++++ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 5 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 38 ++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 +++ clang/test/CIR/CodeGen/complex.cpp | 72 +++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4daff74cbae5a..b58ebd2dfe509 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2481,6 +2481,31 @@ def ComplexEqualOp : CIR_Op<"complex.eq", [Pure, SameTypeOperands]> { }]; } +//===----------------------------------------------------------------------===// +// ComplexNotEqualOp +//===----------------------------------------------------------------------===// + +def ComplexNotEqualOp : CIR_Op<"complex.neq", [Pure, SameTypeOperands]> { + + let summary = "Computes whether two complex values are not equal"; + let description = [{ + The `complex.equal` op takes two complex numbers and returns whether + they are not equal. + + ```mlir + %r = cir.complex.neq %a, %b : !cir.complex<!cir.float> + ``` + }]; + + let results = (outs CIR_BoolType:$result); + let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs); + + let assemblyFormat = [{ + $lhs `,` $rhs + `:` qualified(type($lhs)) attr-dict + }]; +} + //===----------------------------------------------------------------------===// // Assume Operations //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 955bb5ffc4395..0ba653add826f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -905,9 +905,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { result = builder.create<cir::ComplexEqualOp>(loc, boInfo.lhs, boInfo.rhs); } else { - assert(!cir::MissingFeatures::complexType()); - cgf.cgm.errorNYI(loc, "complex not equal"); - result = builder.getBool(false, loc); + result = + builder.create<cir::ComplexNotEqualOp>(loc, boInfo.lhs, boInfo.rhs); } } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 1034b8780c03c..598283eeaf518 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1903,6 +1903,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMComplexCreateOpLowering, CIRToLLVMComplexEqualOpLowering, CIRToLLVMComplexImagOpLowering, + CIRToLLVMComplexNotEqualOpLowering, CIRToLLVMComplexRealOpLowering, CIRToLLVMConstantOpLowering, CIRToLLVMExpectOpLowering, @@ -2282,6 +2283,43 @@ mlir::LogicalResult CIRToLLVMComplexEqualOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMComplexNotEqualOpLowering::matchAndRewrite( + cir::ComplexNotEqualOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value lhs = adaptor.getLhs(); + mlir::Value rhs = adaptor.getRhs(); + + auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType()); + mlir::Type complexElemTy = + getTypeConverter()->convertType(complexType.getElementType()); + + mlir::Location loc = op.getLoc(); + auto lhsReal = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0); + auto lhsImag = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1); + auto rhsReal = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0); + auto rhsImag = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1); + + if (complexElemTy.isInteger()) { + auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>( + loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal); + auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>( + loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag); + rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp); + return mlir::success(); + } + + auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>( + loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal); + auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>( + loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag); + rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp); + return mlir::success(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 25cf218cf8b6c..5cd1d09b88c00 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -473,6 +473,16 @@ class CIRToLLVMComplexEqualOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMComplexNotEqualOpLowering + : public mlir::OpConversionPattern<cir::ComplexNotEqualOp> { +public: + using mlir::OpConversionPattern<cir::ComplexNotEqualOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::ComplexNotEqualOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + } // namespace direct } // namespace cir diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 1e9ce0e29fd46..b8a0b99c10f0b 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -442,3 +442,75 @@ bool foo19(double _Complex a, double _Complex b) { // OGCG: %[[CMP_IMAG:.*]] = fcmp oeq double %[[A_IMAG]], %[[B_IMAG]] // OGCG: %[[RESULT:.*]] = and i1 %[[CMP_REAL]], %[[CMP_IMAG]] + +bool foo20(int _Complex a, int _Complex b) { + return a != b; +} + +// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : !cir.complex<!s32i> + +// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 +// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 +// LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 1 +// LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 1 +// LLVM: %[[CMP_REAL:.*]] = icmp ne i32 %[[A_REAL]], %[[B_REAL]] +// LLVM: %[[CMP_IMAG:.*]] = icmp ne i32 %[[A_IMAG]], %[[B_IMAG]] +// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]] + +// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4 +// 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: %[[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: %[[CMP_REAL:.*]] = icmp ne i32 %[[A_REAL]], %[[B_REAL]] +// OGCG: %[[CMP_IMAG:.*]] = icmp ne i32 %[[A_IMAG]], %[[B_IMAG]] +// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]] + +bool foo21(double _Complex a, double _Complex b) { + return a != b; +} + +// CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> +// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : !cir.complex<!cir.double> + +// LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8 +// LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8 +// LLVM: %[[A_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_A]], 1 +// LLVM: %[[B_REAL:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { double, double } %[[COMPLEX_B]], 1 +// LLVM: %[[CMP_REAL:.*]] = fcmp une double %[[A_REAL]], %[[B_REAL]] +// LLVM: %[[CMP_IMAG:.*]] = fcmp une double %[[A_IMAG]], %[[B_IMAG]] +// LLVM: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]] + +// OGCG: %[[COMPLEX_A:.*]] = alloca { double, double }, align 8 +// OGCG: %[[COMPLEX_B:.*]] = alloca { double, double }, align 8 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 0 +// OGCG: store double {{.*}}, ptr %[[A_REAL_PTR]], align 8 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], i32 0, i32 1 +// OGCG: store double {{.*}}, ptr %[[A_IMAG_PTR]], align 8 +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 0 +// OGCG: store double {{.*}}, ptr %[[B_REAL_PTR]], align 8 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_B]], i32 0, i32 1 +// OGCG: store double {{.*}}, ptr %[[B_IMAG_PTR]], align 8 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX_A]], 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 %[[COMPLEX_A]], 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 %[[COMPLEX_B]], 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 %[[COMPLEX_B]], i32 0, i32 1 +// OGCG: %[[B_IMAG:.*]] = load double, ptr %[[B_IMAG_PTR]], align 8 +// OGCG: %[[CMP_REAL:.*]] = fcmp une double %[[A_REAL]], %[[B_REAL]] +// OGCG: %[[CMP_IMAG:.*]] = fcmp une double %[[A_IMAG]], %[[B_IMAG]] +// OGCG: %[[RESULT:.*]] = or i1 %[[CMP_REAL]], %[[CMP_IMAG]] >From f6097ef2cf5a8c7fa289ef7a08996786c1ea29a1 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Fri, 27 Jun 2025 20:51:02 +0200 Subject: [PATCH 2/3] Fix op description --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index b58ebd2dfe509..553d7bcc161c5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2464,7 +2464,7 @@ def ComplexEqualOp : CIR_Op<"complex.eq", [Pure, SameTypeOperands]> { let summary = "Computes whether two complex values are equal"; let description = [{ - The `complex.equal` op takes two complex numbers and returns whether + The `cir.complex.eq` op takes two complex numbers and returns whether they are equal. ```mlir @@ -2489,7 +2489,7 @@ def ComplexNotEqualOp : CIR_Op<"complex.neq", [Pure, SameTypeOperands]> { let summary = "Computes whether two complex values are not equal"; let description = [{ - The `complex.equal` op takes two complex numbers and returns whether + The `cir.complex.neq` op takes two complex numbers and returns whether they are not equal. ```mlir >From e8486dbe675b48bfa64d5e14f061ca1b49972121 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Sat, 28 Jun 2025 09:22:59 +0200 Subject: [PATCH 3/3] Replace ComplexEqual and ComplexNotEqual by CmpOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 50 ------ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 10 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 147 ++++++++---------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20 --- clang/test/CIR/CodeGen/complex.cpp | 9 +- 5 files changed, 73 insertions(+), 163 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 553d7bcc161c5..7e45fa464f9d4 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2456,56 +2456,6 @@ def ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { let hasFolder = 1; } -//===----------------------------------------------------------------------===// -// ComplexEqualOp -//===----------------------------------------------------------------------===// - -def ComplexEqualOp : CIR_Op<"complex.eq", [Pure, SameTypeOperands]> { - - let summary = "Computes whether two complex values are equal"; - let description = [{ - The `cir.complex.eq` op takes two complex numbers and returns whether - they are equal. - - ```mlir - %r = cir.complex.eq %a, %b : !cir.complex<!cir.float> - ``` - }]; - - let results = (outs CIR_BoolType:$result); - let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs); - - let assemblyFormat = [{ - $lhs `,` $rhs - `:` qualified(type($lhs)) attr-dict - }]; -} - -//===----------------------------------------------------------------------===// -// ComplexNotEqualOp -//===----------------------------------------------------------------------===// - -def ComplexNotEqualOp : CIR_Op<"complex.neq", [Pure, SameTypeOperands]> { - - let summary = "Computes whether two complex values are not equal"; - let description = [{ - The `cir.complex.neq` op takes two complex numbers and returns whether - they are not equal. - - ```mlir - %r = cir.complex.neq %a, %b : !cir.complex<!cir.float> - ``` - }]; - - let results = (outs CIR_BoolType:$result); - let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs); - - let assemblyFormat = [{ - $lhs `,` $rhs - `:` qualified(type($lhs)) attr-dict - }]; -} - //===----------------------------------------------------------------------===// // Assume Operations //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 0ba653add826f..02f62b863a190 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -901,13 +901,9 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE); BinOpInfo boInfo = emitBinOps(e); - if (e->getOpcode() == BO_EQ) { - result = - builder.create<cir::ComplexEqualOp>(loc, boInfo.lhs, boInfo.rhs); - } else { - result = - builder.create<cir::ComplexNotEqualOp>(loc, boInfo.lhs, boInfo.rhs); - } + cir::CmpOpKind opKind = + e->getOpcode() == BO_EQ ? cir::CmpOpKind::eq : cir::CmpOpKind::ne; + result = builder.create<cir::CmpOp>(loc, opKind, boInfo.lhs, boInfo.rhs); } return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(), diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 598283eeaf518..bdc7492d48211 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1586,7 +1586,6 @@ mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite( assert(!cir::MissingFeatures::dataMemberType()); assert(!cir::MissingFeatures::methodType()); - // Lower to LLVM comparison op. if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) { bool isSigned = mlir::isa<cir::IntType>(type) ? mlir::cast<cir::IntType>(type).isSigned() @@ -1595,22 +1594,82 @@ mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite( convertCmpKindToICmpPredicate(cmpOp.getKind(), isSigned); rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>( cmpOp, kind, adaptor.getLhs(), adaptor.getRhs()); - } else if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) { + return mlir::success(); + } + + if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) { mlir::LLVM::ICmpPredicate kind = convertCmpKindToICmpPredicate(cmpOp.getKind(), /* isSigned=*/false); rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>( cmpOp, kind, adaptor.getLhs(), adaptor.getRhs()); - } else if (mlir::isa<cir::FPTypeInterface>(type)) { + return mlir::success(); + } + + if (mlir::isa<cir::FPTypeInterface>(type)) { mlir::LLVM::FCmpPredicate kind = convertCmpKindToFCmpPredicate(cmpOp.getKind()); rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>( cmpOp, kind, adaptor.getLhs(), adaptor.getRhs()); - } else { - return cmpOp.emitError() << "unsupported type for CmpOp: " << type; + return mlir::success(); } - return mlir::success(); + if (mlir::isa<cir::ComplexType>(type)) { + mlir::Value lhs = adaptor.getLhs(); + mlir::Value rhs = adaptor.getRhs(); + mlir::Location loc = cmpOp.getLoc(); + + auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType()); + mlir::Type complexElemTy = + getTypeConverter()->convertType(complexType.getElementType()); + + auto lhsReal = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0); + auto lhsImag = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1); + auto rhsReal = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0); + auto rhsImag = + rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1); + + if (cmpOp.getKind() == cir::CmpOpKind::eq) { + if (complexElemTy.isInteger()) { + auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>( + loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal); + auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>( + loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag); + rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp); + return mlir::success(); + } + + auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>( + loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal); + auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>( + loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag); + rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp); + return mlir::success(); + } + + if (cmpOp.getKind() == cir::CmpOpKind::ne) { + if (complexElemTy.isInteger()) { + auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>( + loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal); + auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>( + loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag); + rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp); + return mlir::success(); + } + + auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>( + loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal); + auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>( + loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag); + rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp); + return mlir::success(); + } + } + + return cmpOp.emitError() << "unsupported type for CmpOp: " << type; } mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite( @@ -1901,9 +1960,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMCallOpLowering, CIRToLLVMCmpOpLowering, CIRToLLVMComplexCreateOpLowering, - CIRToLLVMComplexEqualOpLowering, CIRToLLVMComplexImagOpLowering, - CIRToLLVMComplexNotEqualOpLowering, CIRToLLVMComplexRealOpLowering, CIRToLLVMConstantOpLowering, CIRToLLVMExpectOpLowering, @@ -2246,80 +2303,6 @@ mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMComplexEqualOpLowering::matchAndRewrite( - cir::ComplexEqualOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value lhs = adaptor.getLhs(); - mlir::Value rhs = adaptor.getRhs(); - - auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType()); - mlir::Type complexElemTy = - getTypeConverter()->convertType(complexType.getElementType()); - - mlir::Location loc = op.getLoc(); - auto lhsReal = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0); - auto lhsImag = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1); - auto rhsReal = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0); - auto rhsImag = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1); - - if (complexElemTy.isInteger()) { - auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>( - loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal); - auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>( - loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag); - rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, realCmp, imagCmp); - return mlir::success(); - } - - auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>( - loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal); - auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>( - loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag); - rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, realCmp, imagCmp); - return mlir::success(); -} - -mlir::LogicalResult CIRToLLVMComplexNotEqualOpLowering::matchAndRewrite( - cir::ComplexNotEqualOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value lhs = adaptor.getLhs(); - mlir::Value rhs = adaptor.getRhs(); - - auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType()); - mlir::Type complexElemTy = - getTypeConverter()->convertType(complexType.getElementType()); - - mlir::Location loc = op.getLoc(); - auto lhsReal = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0); - auto lhsImag = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1); - auto rhsReal = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0); - auto rhsImag = - rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1); - - if (complexElemTy.isInteger()) { - auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>( - loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal); - auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>( - loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag); - rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp); - return mlir::success(); - } - - auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>( - loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal); - auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>( - loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag); - rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, realCmp, imagCmp); - return mlir::success(); -} - std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 5cd1d09b88c00..8502cb1ae5d9f 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -463,26 +463,6 @@ class CIRToLLVMComplexImagOpLowering mlir::ConversionPatternRewriter &) const override; }; -class CIRToLLVMComplexEqualOpLowering - : public mlir::OpConversionPattern<cir::ComplexEqualOp> { -public: - using mlir::OpConversionPattern<cir::ComplexEqualOp>::OpConversionPattern; - - mlir::LogicalResult - matchAndRewrite(cir::ComplexEqualOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - -class CIRToLLVMComplexNotEqualOpLowering - : public mlir::OpConversionPattern<cir::ComplexNotEqualOp> { -public: - using mlir::OpConversionPattern<cir::ComplexNotEqualOp>::OpConversionPattern; - - mlir::LogicalResult - matchAndRewrite(cir::ComplexNotEqualOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - } // namespace direct } // namespace cir diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index b8a0b99c10f0b..dbeeb75d85b89 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -376,7 +376,7 @@ bool foo18(int _Complex a, int _Complex b) { // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> -// CIR: %[[RESULT:.*]] = cir.complex.eq %[[COMPLEX_A]], %[[COMPLEX_B]] : !cir.complex<!s32i> +// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!s32i>, !cir.bool // LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 // LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 @@ -408,7 +408,8 @@ bool foo19(double _Complex a, double _Complex b) { // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> -// CIR: %[[RESULT:.*]] = cir.complex.eq %[[COMPLEX_A]], %[[COMPLEX_B]] : !cir.complex<!cir.double> +// CIR: %[[RESULT:.*]] = cir.cmp(eq, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!cir.double>, !cir.bool + // LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8 // LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8 @@ -449,7 +450,7 @@ bool foo20(int _Complex a, int _Complex b) { // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> -// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : !cir.complex<!s32i> +// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!s32i>, !cir.bool // LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 // LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 @@ -481,7 +482,7 @@ bool foo21(double _Complex a, double _Complex b) { // CIR: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> // CIR: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double> -// CIR: %[[RESULT:.*]] = cir.complex.neq %[[COMPLEX_A]], %[[COMPLEX_B]] : !cir.complex<!cir.double> +// CIR: %[[RESULT:.*]] = cir.cmp(ne, %[[COMPLEX_A]], %[[COMPLEX_B]]) : !cir.complex<!cir.double>, !cir.bool // LLVM: %[[COMPLEX_A:.*]] = load { double, double }, ptr {{.*}}, align 8 // LLVM: %[[COMPLEX_B:.*]] = load { double, double }, ptr {{.*}}, align 8 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits