Skip to content

Commit 4c9bb65

Browse files
authored
[CIR] Plus & Minus CompoundAssignment support for ComplexType (#150759)
This change adds support for Plus & Minus CompoundAssignment for ComplexType #141365
1 parent 09146a2 commit 4c9bb65

File tree

6 files changed

+578
-104
lines changed

6 files changed

+578
-104
lines changed

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
116116

117117
mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);
118118

119+
LValue emitCompoundAssignLValue(
120+
const CompoundAssignOperator *e,
121+
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &),
122+
RValue &value);
123+
124+
mlir::Value emitCompoundAssign(
125+
const CompoundAssignOperator *e,
126+
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &));
127+
119128
mlir::Value emitBinAdd(const BinOpInfo &op);
120129
mlir::Value emitBinSub(const BinOpInfo &op);
121130
mlir::Value emitBinMul(const BinOpInfo &op);
@@ -153,6 +162,15 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
153162
HANDLEBINOP(Sub)
154163
HANDLEBINOP(Mul)
155164
#undef HANDLEBINOP
165+
166+
// Compound assignments.
167+
mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) {
168+
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd);
169+
}
170+
171+
mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) {
172+
return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub);
173+
}
156174
};
157175
} // namespace
158176

@@ -166,6 +184,12 @@ static const ComplexType *getComplexType(QualType type) {
166184
}
167185
#endif // NDEBUG
168186

187+
static mlir::Value createComplexFromReal(CIRGenBuilderTy &builder,
188+
mlir::Location loc, mlir::Value real) {
189+
mlir::Value imag = builder.getNullValue(real.getType(), loc);
190+
return builder.createComplexCreate(loc, real, imag);
191+
}
192+
169193
LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
170194
mlir::Value &value) {
171195
assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
@@ -602,7 +626,7 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
602626

603627
mlir::Value result = Visit(const_cast<Expr *>(e));
604628
if (!promotionTy.isNull())
605-
cgf.cgm.errorNYI("emitPromoted emitPromotedValue");
629+
return cgf.emitPromotedValue(result, promotionTy);
606630

607631
return result;
608632
}
@@ -630,6 +654,104 @@ ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
630654
return binOpInfo;
631655
}
632656

657+
LValue ComplexExprEmitter::emitCompoundAssignLValue(
658+
const CompoundAssignOperator *e,
659+
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value) {
660+
QualType lhsTy = e->getLHS()->getType();
661+
QualType rhsTy = e->getRHS()->getType();
662+
SourceLocation exprLoc = e->getExprLoc();
663+
mlir::Location loc = cgf.getLoc(exprLoc);
664+
665+
if (lhsTy->getAs<AtomicType>()) {
666+
cgf.cgm.errorNYI("emitCompoundAssignLValue AtmoicType");
667+
return {};
668+
}
669+
670+
BinOpInfo opInfo{loc};
671+
opInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
672+
673+
assert(!cir::MissingFeatures::cgFPOptionsRAII());
674+
675+
// Load the RHS and LHS operands.
676+
// __block variables need to have the rhs evaluated first, plus this should
677+
// improve codegen a little.
678+
QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
679+
opInfo.ty = promotionTypeCR.isNull() ? e->getComputationResultType()
680+
: promotionTypeCR;
681+
682+
QualType complexElementTy =
683+
opInfo.ty->castAs<ComplexType>()->getElementType();
684+
QualType promotionTypeRHS = getPromotionType(rhsTy);
685+
686+
// The RHS should have been converted to the computation type.
687+
if (e->getRHS()->getType()->isRealFloatingType()) {
688+
if (!promotionTypeRHS.isNull()) {
689+
opInfo.rhs = createComplexFromReal(
690+
cgf.getBuilder(), loc,
691+
cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS));
692+
} else {
693+
assert(cgf.getContext().hasSameUnqualifiedType(complexElementTy, rhsTy));
694+
opInfo.rhs = createComplexFromReal(cgf.getBuilder(), loc,
695+
cgf.emitScalarExpr(e->getRHS()));
696+
}
697+
} else {
698+
if (!promotionTypeRHS.isNull()) {
699+
opInfo.rhs = cgf.emitPromotedComplexExpr(e->getRHS(), promotionTypeRHS);
700+
} else {
701+
assert(cgf.getContext().hasSameUnqualifiedType(opInfo.ty, rhsTy));
702+
opInfo.rhs = Visit(e->getRHS());
703+
}
704+
}
705+
706+
LValue lhs = cgf.emitLValue(e->getLHS());
707+
708+
// Load from the l-value and convert it.
709+
QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
710+
if (lhsTy->isAnyComplexType()) {
711+
mlir::Value lhsValue = emitLoadOfLValue(lhs, exprLoc);
712+
QualType destTy = promotionTypeLHS.isNull() ? opInfo.ty : promotionTypeLHS;
713+
opInfo.lhs = emitComplexToComplexCast(lhsValue, lhsTy, destTy, exprLoc);
714+
} else {
715+
cgf.cgm.errorNYI("emitCompoundAssignLValue emitLoadOfScalar");
716+
return {};
717+
}
718+
719+
// Expand the binary operator.
720+
mlir::Value result = (this->*func)(opInfo);
721+
722+
// Truncate the result and store it into the LHS lvalue.
723+
if (lhsTy->isAnyComplexType()) {
724+
mlir::Value resultValue =
725+
emitComplexToComplexCast(result, opInfo.ty, lhsTy, exprLoc);
726+
emitStoreOfComplex(loc, resultValue, lhs, /*isInit*/ false);
727+
value = RValue::getComplex(resultValue);
728+
} else {
729+
mlir::Value resultValue =
730+
cgf.emitComplexToScalarConversion(result, opInfo.ty, lhsTy, exprLoc);
731+
cgf.emitStoreOfScalar(resultValue, lhs, /*isInit*/ false);
732+
value = RValue::get(resultValue);
733+
}
734+
735+
return lhs;
736+
}
737+
738+
mlir::Value ComplexExprEmitter::emitCompoundAssign(
739+
const CompoundAssignOperator *e,
740+
mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)) {
741+
RValue val;
742+
LValue lv = emitCompoundAssignLValue(e, func, val);
743+
744+
// The result of an assignment in C is the assigned r-value.
745+
if (!cgf.getLangOpts().CPlusPlus)
746+
return val.getComplexValue();
747+
748+
// If the lvalue is non-volatile, return the computed value of the assignment.
749+
if (!lv.isVolatileQualified())
750+
return val.getComplexValue();
751+
752+
return emitLoadOfLValue(lv, e->getExprLoc());
753+
}
754+
633755
mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
634756
assert(!cir::MissingFeatures::fastMathFlags());
635757
assert(!cir::MissingFeatures::cgFPOptionsRAII());
@@ -685,6 +807,31 @@ mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {
685807
return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e));
686808
}
687809

810+
using CompoundFunc =
811+
mlir::Value (ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &);
812+
813+
static CompoundFunc getComplexOp(BinaryOperatorKind op) {
814+
switch (op) {
815+
case BO_MulAssign:
816+
llvm_unreachable("getComplexOp: BO_MulAssign");
817+
case BO_DivAssign:
818+
llvm_unreachable("getComplexOp: BO_DivAssign");
819+
case BO_SubAssign:
820+
return &ComplexExprEmitter::emitBinSub;
821+
case BO_AddAssign:
822+
return &ComplexExprEmitter::emitBinAdd;
823+
default:
824+
llvm_unreachable("unexpected complex compound assignment");
825+
}
826+
}
827+
828+
LValue CIRGenFunction::emitComplexCompoundAssignmentLValue(
829+
const CompoundAssignOperator *e) {
830+
CompoundFunc op = getComplexOp(e->getOpcode());
831+
RValue val;
832+
return ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, val);
833+
}
834+
688835
mlir::Value CIRGenFunction::emitComplexPrePostIncDec(const UnaryOperator *e,
689836
LValue lv,
690837
cir::UnaryOpKind op,
@@ -729,3 +876,11 @@ mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,
729876
QualType promotionType) {
730877
return ComplexExprEmitter(*this).emitPromoted(e, promotionType);
731878
}
879+
880+
mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result,
881+
QualType promotionType) {
882+
assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() &&
883+
"integral complex will never be promoted");
884+
return builder.createCast(cir::CastKind::float_complex, result,
885+
convertType(promotionType));
886+
}

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,29 @@ mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
19551955
.emitScalarConversion(src, srcTy, dstTy, loc);
19561956
}
19571957

1958+
mlir::Value CIRGenFunction::emitComplexToScalarConversion(mlir::Value src,
1959+
QualType srcTy,
1960+
QualType dstTy,
1961+
SourceLocation loc) {
1962+
assert(srcTy->isAnyComplexType() && hasScalarEvaluationKind(dstTy) &&
1963+
"Invalid complex -> scalar conversion");
1964+
1965+
QualType complexElemTy = srcTy->castAs<ComplexType>()->getElementType();
1966+
if (dstTy->isBooleanType()) {
1967+
auto kind = complexElemTy->isFloatingType()
1968+
? cir::CastKind::float_complex_to_bool
1969+
: cir::CastKind::int_complex_to_bool;
1970+
return builder.createCast(getLoc(loc), kind, src, convertType(dstTy));
1971+
}
1972+
1973+
auto kind = complexElemTy->isFloatingType()
1974+
? cir::CastKind::float_complex_to_real
1975+
: cir::CastKind::int_complex_to_real;
1976+
mlir::Value real =
1977+
builder.createCast(getLoc(loc), kind, src, convertType(complexElemTy));
1978+
return emitScalarConversion(real, complexElemTy, dstTy, loc);
1979+
}
1980+
19581981
mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
19591982
// Perform vector logical not on comparison with zero vector.
19601983
if (e->getType()->isVectorType() &&

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,9 +785,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
785785
}
786786
if (!ty->isAnyComplexType())
787787
return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
788-
cgm.errorNYI(e->getSourceRange(),
789-
"CompoundAssignOperator with ComplexType");
790-
return LValue();
788+
789+
return emitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
791790
}
792791
case Expr::CallExprClass:
793792
case Expr::CXXMemberCallExprClass:

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,11 @@ class CIRGenFunction : public CIRGenTypeCache {
944944
/// sanitizer is enabled, a runtime check is also emitted.
945945
mlir::Value emitCheckedArgForAssume(const Expr *e);
946946

947+
/// Emit a conversion from the specified complex type to the specified
948+
/// destination type, where the destination type is an LLVM scalar type.
949+
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
950+
QualType dstTy, SourceLocation loc);
951+
947952
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
948953
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e);
949954

@@ -1047,6 +1052,8 @@ class CIRGenFunction : public CIRGenTypeCache {
10471052

10481053
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
10491054

1055+
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
1056+
10501057
/// Emit the computation of the specified expression of scalar type.
10511058
mlir::Value emitScalarExpr(const clang::Expr *e);
10521059

@@ -1076,6 +1083,7 @@ class CIRGenFunction : public CIRGenTypeCache {
10761083
cir::UnaryOpKind op, bool isPre);
10771084

10781085
LValue emitComplexAssignmentLValue(const BinaryOperator *e);
1086+
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e);
10791087

10801088
void emitCompoundStmt(const clang::CompoundStmt &s);
10811089

0 commit comments

Comments
 (0)