[clang] [CIR] CompoundAssignment from ComplexType to ScalarType (PR #152915)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 10 06:13:28 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
@llvm/pr-subscribers-clang
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
This change adds support for the CompoundAssignment for ComplexType and updates our approach for emitting bin op between Complex & Scalar
https://github.com/llvm/llvm-project/issues/141365
---
Patch is 26.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152915.diff
5 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+94-20)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+3-5)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+2)
- (modified) clang/test/CIR/CodeGen/complex-compound-assignment.cpp (+89-11)
- (modified) clang/test/CIR/CodeGen/complex-mul-div.cpp (+58-12)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index cba06a1489a29..85cd0282ffc2a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -188,12 +188,6 @@ static const ComplexType *getComplexType(QualType type) {
}
#endif // NDEBUG
-static mlir::Value createComplexFromReal(CIRGenBuilderTy &builder,
- mlir::Location loc, mlir::Value real) {
- mlir::Value imag = builder.getNullValue(real.getType(), loc);
- return builder.createComplexCreate(loc, real, imag);
-}
-
LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
mlir::Value &value) {
assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
@@ -644,8 +638,12 @@ ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,
return Visit(const_cast<Expr *>(e));
}
- cgf.cgm.errorNYI("emitPromotedComplexOperand non-complex type");
- return {};
+ if (!promotionTy.isNull()) {
+ QualType complexElementTy =
+ promotionTy->castAs<ComplexType>()->getElementType();
+ return cgf.emitPromotedScalarExpr(e, complexElementTy);
+ }
+ return cgf.emitScalarExpr(e);
}
ComplexExprEmitter::BinOpInfo
@@ -690,13 +688,10 @@ LValue ComplexExprEmitter::emitCompoundAssignLValue(
// The RHS should have been converted to the computation type.
if (e->getRHS()->getType()->isRealFloatingType()) {
if (!promotionTypeRHS.isNull()) {
- opInfo.rhs = createComplexFromReal(
- cgf.getBuilder(), loc,
- cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS));
+ opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
} else {
assert(cgf.getContext().hasSameUnqualifiedType(complexElementTy, rhsTy));
- opInfo.rhs = createComplexFromReal(cgf.getBuilder(), loc,
- cgf.emitScalarExpr(e->getRHS()));
+ opInfo.rhs = cgf.emitScalarExpr(e->getRHS());
}
} else {
if (!promotionTypeRHS.isNull()) {
@@ -716,8 +711,27 @@ LValue ComplexExprEmitter::emitCompoundAssignLValue(
QualType destTy = promotionTypeLHS.isNull() ? opInfo.ty : promotionTypeLHS;
opInfo.lhs = emitComplexToComplexCast(lhsValue, lhsTy, destTy, exprLoc);
} else {
- cgf.cgm.errorNYI("emitCompoundAssignLValue emitLoadOfScalar");
- return {};
+ mlir::Value lhsVal = cgf.emitLoadOfScalar(lhs, exprLoc);
+ // For floating point real operands we can directly pass the scalar form
+ // to the binary operator emission and potentially get more efficient code.
+ if (lhsTy->isRealFloatingType()) {
+ QualType promotedComplexElementTy;
+ if (!promotionTypeLHS.isNull()) {
+ promotedComplexElementTy =
+ cast<ComplexType>(promotionTypeLHS)->getElementType();
+ if (!cgf.getContext().hasSameUnqualifiedType(promotedComplexElementTy,
+ promotionTypeLHS))
+ lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy,
+ promotedComplexElementTy, exprLoc);
+ } else {
+ if (!cgf.getContext().hasSameUnqualifiedType(complexElementTy, lhsTy))
+ lhsVal = cgf.emitScalarConversion(lhsVal, lhsTy, complexElementTy,
+ exprLoc);
+ }
+ opInfo.lhs = lhsVal;
+ } else {
+ opInfo.lhs = emitScalarToComplexCast(lhsVal, lhsTy, opInfo.ty, exprLoc);
+ }
}
// Expand the binary operator.
@@ -759,13 +773,45 @@ mlir::Value ComplexExprEmitter::emitCompoundAssign(
mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
assert(!cir::MissingFeatures::fastMathFlags());
assert(!cir::MissingFeatures::cgFPOptionsRAII());
- return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs);
+
+ if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
+ mlir::isa<cir::ComplexType>(op.rhs.getType()))
+ return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs);
+
+ if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
+ mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
+ mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
+ mlir::Value newReal = builder.createAdd(op.loc, real, op.rhs);
+ return builder.createComplexCreate(op.loc, newReal, imag);
+ }
+
+ 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 = builder.createAdd(op.loc, op.lhs, real);
+ return builder.createComplexCreate(op.loc, newReal, imag);
}
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);
+
+ if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
+ mlir::isa<cir::ComplexType>(op.rhs.getType()))
+ return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs);
+
+ if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
+ mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
+ mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
+ mlir::Value newReal = builder.createSub(op.loc, real, op.rhs);
+ return builder.createComplexCreate(op.loc, newReal, imag);
+ }
+
+ 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 = builder.createSub(op.loc, op.lhs, real);
+ return builder.createComplexCreate(op.loc, newReal, imag);
}
static cir::ComplexRangeKind
@@ -788,9 +834,28 @@ getComplexRangeAttr(LangOptions::ComplexRangeKind range) {
mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
assert(!cir::MissingFeatures::fastMathFlags());
assert(!cir::MissingFeatures::cgFPOptionsRAII());
- cir::ComplexRangeKind rangeKind =
- getComplexRangeAttr(op.fpFeatures.getComplexRange());
- return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind);
+
+ if (mlir::isa<cir::ComplexType>(op.lhs.getType()) &&
+ mlir::isa<cir::ComplexType>(op.rhs.getType())) {
+ cir::ComplexRangeKind rangeKind =
+ getComplexRangeAttr(op.fpFeatures.getComplexRange());
+ return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind);
+ }
+
+ if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
+ mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
+ mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
+ mlir::Value newReal = builder.createMul(op.loc, real, op.rhs);
+ mlir::Value newImag = builder.createMul(op.loc, imag, op.rhs);
+ return builder.createComplexCreate(op.loc, newReal, newImag);
+ }
+
+ 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 = builder.createMul(op.loc, op.lhs, real);
+ mlir::Value newImag = builder.createMul(op.loc, op.lhs, imag);
+ return builder.createComplexCreate(op.loc, newReal, newImag);
}
LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
@@ -888,3 +953,12 @@ mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result,
return builder.createCast(cir::CastKind::float_complex, result,
convertType(promotionType));
}
+
+LValue CIRGenFunction::emitScalarCompoundAssignWithComplex(
+ const CompoundAssignOperator *e, mlir::Value &result) {
+ CompoundFunc op = getComplexOp(e->getOpcode());
+ RValue value;
+ LValue ret = ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, value);
+ result = value.getValue();
+ return ret;
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 3e06513bb6cf0..d4c7d306cb110 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1066,14 +1066,12 @@ LValue ScalarExprEmitter::emitCompoundAssignLValue(
const CompoundAssignOperator *e,
mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
mlir::Value &result) {
+ if (e->getComputationResultType()->isAnyComplexType())
+ return cgf.emitScalarCompoundAssignWithComplex(e, result);
+
QualType lhsTy = e->getLHS()->getType();
BinOpInfo opInfo;
- if (e->getComputationResultType()->isAnyComplexType()) {
- cgf.cgm.errorNYI(result.getLoc(), "complex lvalue assign");
- return LValue();
- }
-
// Emit the RHS first. __block variables need to have the rhs evaluated
// first, plus this should improve codegen a little.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 065039ec041e0..e5815a054cebd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1100,6 +1100,8 @@ class CIRGenFunction : public CIRGenTypeCache {
LValue emitComplexAssignmentLValue(const BinaryOperator *e);
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e);
+ LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e,
+ mlir::Value &result);
void emitCompoundStmt(const clang::CompoundStmt &s);
diff --git a/clang/test/CIR/CodeGen/complex-compound-assignment.cpp b/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
index 82450259f424b..9a6659bd5d93e 100644
--- a/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
+++ b/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
@@ -296,26 +296,22 @@ void foo5() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b"]
// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.float>, !cir.float
-// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
-// CIR: %[[COMPLEX_B:.*]] = cir.complex.create %[[TMP_B]], %[[CONST_ZERO]] : !cir.float -> !cir.complex<!cir.float>
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
-// CIR: %[[RESULT:.*]] = cir.complex.add %[[TMP_A]], %[[COMPLEX_B]] : !cir.complex<!cir.float>
+// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
+// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
+// CIR: %[[RESULT_REAL:.*]] = cir.binop(add, %[[A_REAL]], %[[TMP_B]]) : !cir.float
+// CIR: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], %[[A_IMAG]] : !cir.float -> !cir.complex<!cir.float>
// CIR: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, 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: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], 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 } %[[COMPLEX_B]], 0
-// LLVM: %[[B_IMAG:.*]] = extractvalue { float, float } %[[COMPLEX_B]], 1
-// LLVM: %[[ADD_REAL:.*]] = fadd float %[[A_REAL]], %[[B_REAL]]
-// LLVM: %[[ADD_IMAG:.*]] = fadd float %[[A_IMAG]], %[[B_IMAG]]
-// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } poison, float %[[ADD_REAL]], 0
-// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[ADD_IMAG]], 1
+// LLVM: %[[RESULT_REAL:.*]] = fadd float %[[A_REAL]], %[[TMP_B]]
+// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[RESULT_REAL]], 0
+// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[A_IMAG]], 1
// LLVM: store { float, float } %[[RESULT]], ptr %[[A_ADDR]], align 4
// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
@@ -494,3 +490,85 @@ void foo7() {
// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1
// OGCG: store float %[[FINAL_REAL]], ptr %[[C_REAL_PTR]], align 4
// OGCG: store float %[[FINAL_IMAG]], ptr %[[C_IMAG_PTR]], align 4
+
+void foo8() {
+ float _Complex a;
+ float b;
+ a *= b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b"]
+// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.float>, !cir.float
+// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
+// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float
+// CIR: %[[RESULT_REAL:.*]] = cir.binop(mul, %[[A_REAL]], %[[TMP_B]]) : !cir.float
+// CIR: %[[RESULT_IMAG:.*]] = cir.binop(mul, %[[A_IMAG]], %[[TMP_B]]) : !cir.float
+// CIR: %[[RESULT:.*]] = cir.complex.create %[[RESULT_REAL]], %[[RESULT_IMAG]] : !cir.float -> !cir.complex<!cir.float>
+// CIR: cir.store{{.*}} %[[RESULT]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
+// LLVM: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
+// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
+// LLVM: %[[RESULT_REAL:.*]] = fmul float %[[A_REAL]], %[[TMP_B]]
+// LLVM: %[[RESULT_IMAG:.*]] = fmul float %[[A_IMAG]], %[[TMP_B]]
+// LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[RESULT_REAL]], 0
+// LLVM: %[[RESULT:.*]] = insertvalue { float, float } %[[TMP_RESULT]], float %[[RESULT_IMAG]], 1
+// LLVM: store { float, float } %[[RESULT]], ptr %[[A_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[TMP_B:.*]] = load float, 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: %[[RESULT_REAL:.*]] = fmul float %[[A_REAL]], %[[TMP_B]]
+// OGCG: %[[RESULT_IMAG:.*]] = fmul float %[[A_IMAG]], %[[TMP_B]]
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: store float %[[RESULT_REAL]], ptr %[[A_REAL_PTR]], align 4
+// OGCG: store float %[[RESULT_IMAG]], ptr %[[A_IMAG_PTR]], align 4
+
+#ifndef __cplusplus
+void foo9() {
+ float _Complex a;
+ float b;
+ b += a;
+}
+#endif
+
+// C_CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
+// C_CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b"]
+// C_CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// C_CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.float>, !cir.float
+// C_CIR: %[[A_REAL:.*]] = cir.complex.real %[[A_ADDR]] : !cir.complex<!cir.float> -> !cir.float
+// C_CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[A_ADDR]] : !cir.complex<!cir.float> -> !cir.float
+// C_CIR: %[[NEW_REAL:.*]] = cir.binop(add, %[[TMP_B]], %[[A_REAL]]) : !cir.float
+// C_CIR: %[[RESULT:.*]] = cir.complex.create %[[NEW_REAL]], %[[A_IMAG]] : !cir.float -> !cir.complex<!cir.float>
+// C_CIR: %[[RESULT_REAL:.*]] = cir.complex.real %[[RESULT]] : !cir.complex<!cir.float> -> !cir.float
+// C_CIR: cir.store{{.*}} %[[RESULT_REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+
+// C_LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// C_LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
+// C_LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// C_LLVM: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// C_LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0
+// C_LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1
+// C_LLVM: %[[NEW_REAL:.*]] = fadd float %[[TMP_B]], %[[A_REAL]]
+// C_LLVM: %[[TMP_RESULT:.*]] = insertvalue { float, float } {{.*}}, float %[[NEW_REAL]], 0
+// C_LLVM: store float %[[NEW_REAL]], ptr %[[B_ADDR]], align 4
+
+// C_OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// C_OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// C_OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// C_OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
+// C_OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// C_OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
+// C_OGCG: %[[TMP_B:.*]] = load float, ptr %[[B_ADDR]], align 4
+// C_OGCG: %[[ADD_REAL:.*]] = fadd float %[[TMP_B]], %[[A_REAL]]
+// C_OGCG: store float %[[ADD_REAL]], ptr %[[B_ADDR]], align 4
diff --git a/clang/test/CIR/CodeGen/complex-mul-div.cpp b/clang/test/CIR/CodeGen/complex-mul-div.cpp
index 9d71ef7453001..633080577092c 100644
--- a/clang/test/CIR/CodeGen/complex-mul-div.cpp
+++ b/clang/test/CIR/CodeGen/complex-mul-div.cpp
@@ -1,38 +1,38 @@
// complex-range basic
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -complex-range=basic -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE-BASIC %s
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=basic -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED
+// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED,CIR-COMBINED
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=basic -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
-// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED,LLVM-COMBINED
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=basic -Wno-unused-value -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG-INT,OGCG-MUL-COMBINED
+// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG-INT,OGCG-MUL-COMBINED,OGCG-COMBINED
// complex-range improved
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -complex-range=improved -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE-IMPROVED %s
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=improved -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED
+// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED,CIR-COMBINED
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=improved -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
-// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED,LLVM-COMBIN...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/152915
More information about the cfe-commits
mailing list