https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/148025
>From c430b7dd359ffbc9e356ab242d18554830ed5ee2 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Thu, 10 Jul 2025 20:37:25 +0200 Subject: [PATCH 1/2] [CIR] Implement SubOp for ComplexType --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 27 +++ clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 10 ++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 50 ++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 ++ clang/test/CIR/CodeGen/complex-arithmetic.cpp | 154 ++++++++++++++++++ 5 files changed, 251 insertions(+) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 6bee953b378e8..dd70a32516293 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2547,6 +2547,33 @@ def ComplexAddOp : CIR_Op<"complex.add", [Pure, SameOperandsAndResultType]> { }]; } +//===----------------------------------------------------------------------===// +// ComplexSubOp +//===----------------------------------------------------------------------===// + +def ComplexSubOp : CIR_Op<"complex.sub", [Pure, SameOperandsAndResultType]> { + let summary = "Complex subtraction"; + let description = [{ + The `cir.complex.sub` operation takes two complex numbers and returns + their difference. + + Example: + + ```mlir + %2 = cir.complex.sub %0, %1 : !cir.complex<!cir.float> + ``` + }]; + + let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs); + + let results = (outs CIR_ComplexType:$result); + + let assemblyFormat = [{ + $lhs `,` $rhs `:` qualified(type($result)) attr-dict + }]; +} + + //===----------------------------------------------------------------------===// // Bit Manipulation Operations //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 24a9bf13e1880..54623d66f94ee 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -75,6 +75,8 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value emitBinAdd(const BinOpInfo &op); + mlir::Value emitBinSub(const BinOpInfo &op); + QualType getPromotionType(QualType ty, bool isDivOpCode = false) { if (auto *complexTy = ty->getAs<ComplexType>()) { QualType elementTy = complexTy->getElementType(); @@ -105,6 +107,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { } HANDLEBINOP(Add) + HANDLEBINOP(Sub) #undef HANDLEBINOP }; } // namespace @@ -349,6 +352,7 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, case BO_##OP: \ return emitBin##OP(emitBinOps(bo, promotionTy)); HANDLE_BINOP(Add) + HANDLE_BINOP(Sub) #undef HANDLE_BINOP default: break; @@ -394,6 +398,12 @@ mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) { return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs); } +mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); + return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs); +} + LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) { assert(e->getOpcode() == BO_Assign && "Expected assign op"); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index cbbe7a2380268..addff50c22b5b 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2052,6 +2052,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMComplexCreateOpLowering, CIRToLLVMComplexImagOpLowering, CIRToLLVMComplexRealOpLowering, + CIRToLLVMComplexSubOpLowering, CIRToLLVMConstantOpLowering, CIRToLLVMExpectOpLowering, CIRToLLVMFuncOpLowering, @@ -2434,6 +2435,55 @@ mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite( + cir::ComplexSubOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value lhs = adaptor.getLhs(); + mlir::Value rhs = adaptor.getRhs(); + mlir::Location loc = op.getLoc(); + + auto complexType = mlir::cast<cir::ComplexType>(op.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); + + mlir::Value newReal; + mlir::Value newImag; + if (complexElemTy.isInteger()) { + newReal = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsReal, + rhsReal); + newImag = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsImag, + rhsImag); + } else { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::fpConstraints()); + newReal = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsReal, + rhsReal); + newImag = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsImag, + rhsImag); + } + + mlir::Type complexLLVMTy = + getTypeConverter()->convertType(op.getResult().getType()); + auto initialComplex = + rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy); + + auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>( + op->getLoc(), initialComplex, newReal, 0); + + rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex, + newImag, 1); + + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite( cir::ComplexImagOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index a41cf3f50812e..2463de2d07092 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -533,6 +533,16 @@ class CIRToLLVMComplexAddOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMComplexSubOpLowering + : public mlir::OpConversionPattern<cir::ComplexSubOp> { +public: + using mlir::OpConversionPattern<cir::ComplexSubOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::ComplexSubOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + } // namespace direct } // namespace cir diff --git a/clang/test/CIR/CodeGen/complex-arithmetic.cpp b/clang/test/CIR/CodeGen/complex-arithmetic.cpp index 5131c075744c8..155e0797250cd 100644 --- a/clang/test/CIR/CodeGen/complex-arithmetic.cpp +++ b/clang/test/CIR/CodeGen/complex-arithmetic.cpp @@ -158,3 +158,157 @@ void foo3() { // OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1 // OGCG: store float %[[ADD_REAL_A_B_C]], ptr %[[RESULT_REAL_PTR]], align 4 // OGCG: store float %[[ADD_IMAG_A_B_C]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo4() { + int _Complex a; + int _Complex b; + int _Complex c = a - b; +} + +// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"] +// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b"] +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: %[[SUB:.*]] = cir.complex.sub %[[TMP_A]], %[[TMP_B]] : !cir.complex<!s32i> + +// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4 +// LLVM: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[COMPLEX_B]], align 4 +// LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[TMP_A]], 1 +// LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[TMP_B]], 1 +// LLVM: %[[SUB_REAL:.*]] = sub i32 %[[A_REAL]], %[[B_REAL]] +// LLVM: %[[SUB_IMAG:.*]] = sub i32 %[[A_IMAG]], %[[B_IMAG]] +// LLVM: %[[RESULT:.*]] = insertvalue { i32, i32 } poison, i32 %[[SUB_REAL]], 0 +// LLVM: %[[RESULT_2:.*]] = insertvalue { i32, i32 } %[[RESULT]], i32 %[[SUB_IMAG]], 1 + +// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[RESULT:.*]] = 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: %[[SUB_REAL:.*]] = sub i32 %[[A_REAL]], %[[B_REAL]] +// OGCG: %[[SUB_IMAG:.*]] = sub i32 %[[A_IMAG]], %[[B_IMAG]] +// 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 %[[SUB_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store i32 %[[SUB_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo5() { + float _Complex a; + float _Complex b; + float _Complex c = a - b; +} + +// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b"] +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: %[[SUB:.*]] = cir.complex.sub %[[TMP_A]], %[[TMP_B]] : !cir.complex<!cir.float> + +// LLVM: %[[COMPLEX_A:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[COMPLEX_B:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[COMPLEX_A]], align 4 +// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[COMPLEX_B]], align 4 +// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1 +// LLVM: %[[B_REAL:.*]] = extractvalue { float, float } %[[TMP_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[TMP_B]], 1 +// LLVM: %[[SUB_REAL:.*]] = fsub float %[[A_REAL]], %[[B_REAL]] +// LLVM: %[[SUB_IMAG:.*]] = fsub float %[[A_IMAG]], %[[B_IMAG]] +// LLVM: %[[RESULT:.*]] = insertvalue { float, float } poison, float %[[SUB_REAL]], 0 +// LLVM: %[[RESULT_2:.*]] = insertvalue { float, float } %[[RESULT]], float %[[SUB_IMAG]], 1 + +// OGCG: %[[COMPLEX_A:.*]] = alloca { float, float }, align 4 +// OGCG: %[[COMPLEX_B:.*]] = alloca { float, float }, align 4 +// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_A]], 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 %[[COMPLEX_A]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_B]], 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 %[[COMPLEX_B]], i32 0, i32 1 +// OGCG: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 4 +// OGCG: %[[SUB_REAL:.*]] = fsub float %[[A_REAL]], %[[B_REAL]] +// OGCG: %[[SUB_IMAG:.*]] = fsub float %[[A_IMAG]], %[[B_IMAG]] +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1 +// OGCG: store float %[[SUB_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[SUB_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo6() { + float _Complex a; + float _Complex b; + float _Complex c; + float _Complex d = (a - b) - c; +} + +// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b"] +// CIR: %[[COMPLEX_C:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c"] +// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["d", init] +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[COMPLEX_B]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: %[[SUB_A_B:.*]] = cir.complex.sub %[[TMP_A]], %[[TMP_B]] : !cir.complex<!cir.float> +// CIR: %[[TMP_C:.*]] = cir.load{{.*}} %[[COMPLEX_C]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: %[[SUB_A_B_C:.*]] = cir.complex.sub %[[SUB_A_B]], %[[TMP_C]] : !cir.complex<!cir.float> +// CIR: cir.store{{.*}} %[[SUB_A_B_C]], %[[RESULT]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// LLVM: %[[COMPLEX_A:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[COMPLEX_B:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[COMPLEX_C:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[COMPLEX_A]], align 4 +// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[COMPLEX_B]], align 4 +// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0 +// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1 +// LLVM: %[[B_REAL:.*]] = extractvalue { float, float } %[[TMP_B]], 0 +// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[TMP_B]], 1 +// LLVM: %[[SUB_REAL_A_B:.*]] = fsub float %[[A_REAL]], %[[B_REAL]] +// LLVM: %[[SUB_IMAG_A_B:.*]] = fsub float %[[A_IMAG]], %[[B_IMAG]] +// LLVM: %[[A_B:.*]] = insertvalue { float, float } poison, float %[[SUB_REAL_A_B]], 0 +// LLVM: %[[TMP_A_B:.*]] = insertvalue { float, float } %[[A_B]], float %[[SUB_IMAG_A_B]], 1 +// LLVM: %[[TMP_C:.*]] = load { float, float }, ptr %[[COMPLEX_C]], align 4 +// LLVM: %[[A_B_REAL:.*]] = extractvalue { float, float } %[[TMP_A_B]], 0 +// LLVM: %[[A_B_IMAG:.*]] = extractvalue { float, float } %[[TMP_A_B]], 1 +// LLVM: %[[C_REAL:.*]] = extractvalue { float, float } %[[TMP_C]], 0 +// LLVM: %[[C_IMAG:.*]] = extractvalue { float, float } %[[TMP_C]], 1 +// LLVM: %[[SUB_REAL_A_B_C:.*]] = fsub float %[[A_B_REAL]], %[[C_REAL]] +// LLVM: %[[SUB_IMAG_A_B_C:.*]] = fsub float %[[A_B_IMAG]], %[[C_IMAG]] +// LLVM: %[[A_B_C:.*]] = insertvalue { float, float } poison, float %[[SUB_REAL_A_B_C]], 0 +// LLVM: %[[TMP_A_B_C:.*]] = insertvalue { float, float } %[[A_B_C]], float %[[SUB_IMAG_A_B_C]], 1 +// LLVM: store { float, float } %[[TMP_A_B_C]], ptr %[[RESULT]], align 4 + +// OGCG: %[[COMPLEX_A:.*]] = alloca { float, float }, align 4 +// OGCG: %[[COMPLEX_B:.*]] = alloca { float, float }, align 4 +// OGCG: %[[COMPLEX_C:.*]] = alloca { float, float }, align 4 +// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_A]], 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 %[[COMPLEX_A]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_B]], 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 %[[COMPLEX_B]], i32 0, i32 1 +// OGCG: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 4 +// OGCG: %[[SUB_REAL_A_B:.*]] = fsub float %[[A_REAL]], %[[B_REAL]] +// OGCG: %[[SUB_IMAG_A_B:.*]] = fsub float %[[A_IMAG]], %[[B_IMAG]] +// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_C]], i32 0, i32 0 +// OGCG: %[[C_REAL:.*]] = load float, ptr %[[C_REAL_PTR]], align 4 +// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_C]], i32 0, i32 1 +// OGCG: %[[C_IMAG:.*]] = load float, ptr %[[C_IMAG_PTR]], align 4 +// OGCG: %[[SUB_REAL_A_B_C:.*]] = fsub float %[[SUB_REAL_A_B]], %[[C_REAL]] +// OGCG: %[[SUB_IMAG_A_B_C:.*]] = fsub float %[[SUB_IMAG_A_B]], %[[C_IMAG]] +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1 +// 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 >From d3736246b0c671d82c38c258f2122dc36a5de3df Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Fri, 11 Jul 2025 19:30:05 +0200 Subject: [PATCH 2/2] Address code review comments --- clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 1 - clang/test/CIR/CodeGen/complex-arithmetic.cpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 54623d66f94ee..cb155cc35e357 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -74,7 +74,6 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy); mlir::Value emitBinAdd(const BinOpInfo &op); - mlir::Value emitBinSub(const BinOpInfo &op); QualType getPromotionType(QualType ty, bool isDivOpCode = false) { diff --git a/clang/test/CIR/CodeGen/complex-arithmetic.cpp b/clang/test/CIR/CodeGen/complex-arithmetic.cpp index 155e0797250cd..5e384cd34ebfd 100644 --- a/clang/test/CIR/CodeGen/complex-arithmetic.cpp +++ b/clang/test/CIR/CodeGen/complex-arithmetic.cpp @@ -173,6 +173,7 @@ void foo4() { // LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4 // LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[COMPLEX_C:.*]] = alloca { i32, i32 }, i64 1, align 4 // LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4 // LLVM: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[COMPLEX_B]], align 4 // LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_A]], 0 @@ -183,6 +184,7 @@ void foo4() { // LLVM: %[[SUB_IMAG:.*]] = sub i32 %[[A_IMAG]], %[[B_IMAG]] // LLVM: %[[RESULT:.*]] = insertvalue { i32, i32 } poison, i32 %[[SUB_REAL]], 0 // LLVM: %[[RESULT_2:.*]] = insertvalue { i32, i32 } %[[RESULT]], i32 %[[SUB_IMAG]], 1 +// LLVM: store { i32, i32 } %[[RESULT_2]], ptr %[[COMPLEX_C]], align 4 // OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4 // OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits