llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> - Reorder the CIRGenExprComplex functions to be similar to OCG. - Add errors for unhandled visitors. - Rename the test file to be similar to `complex-mul-div`. Issue: https://github.com/llvm/llvm-project/issues/141365 --- Patch is 47.74 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/156241.diff 2 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+519-431) - (renamed) clang/test/CIR/CodeGen/complex-plus-minus.cpp () ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index cbdd525068f5d..36ea5d08c2948 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -6,6 +6,16 @@ using namespace clang; using namespace clang::CIRGen; +#ifndef NDEBUG +/// Return the complex type that we are meant to emit. +static const ComplexType *getComplexType(QualType type) { + type = type.getCanonicalType(); + if (const ComplexType *comp = dyn_cast<ComplexType>(type)) + return comp; + return cast<ComplexType>(cast<AtomicType>(type)->getValueType()); +} +#endif // NDEBUG + namespace { class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { CIRGenFunction &cgf; @@ -19,13 +29,6 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { // Utilities //===--------------------------------------------------------------------===// - LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val); - - mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy); - - mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant, - Expr *e); - /// Given an expression with complex type that represents a value l-value, /// this method emits the address of the l-value, then loads and returns the /// result. @@ -48,20 +51,75 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType, QualType destType, SourceLocation loc); + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + mlir::Value Visit(Expr *e) { + return StmtVisitor<ComplexExprEmitter, mlir::Value>::Visit(e); + } + + mlir::Value VisitStmt(Stmt *s) { + cgf.cgm.errorNYI(s->getBeginLoc(), "ComplexExprEmitter VisitStmt"); + return {}; + } + + mlir::Value VisitExpr(Expr *e); + mlir::Value VisitConstantExpr(ConstantExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitConstantExpr"); + return {}; + } + + mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); } + mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) { + return Visit(ge->getResultExpr()); + } + mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il); mlir::Value - VisitAbstractConditionalOperator(const AbstractConditionalOperator *e); - mlir::Value VisitArraySubscriptExpr(Expr *e); - mlir::Value VisitBinAssign(const BinaryOperator *e); - mlir::Value VisitBinComma(const BinaryOperator *e); - mlir::Value VisitCallExpr(const CallExpr *e); - mlir::Value VisitCastExpr(CastExpr *e); - mlir::Value VisitChooseExpr(ChooseExpr *e); - mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e); - mlir::Value VisitDeclRefExpr(DeclRefExpr *e); - mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e); - mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e); - mlir::Value VisitInitListExpr(InitListExpr *e); + VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe) { + return Visit(pe->getReplacement()); + } + mlir::Value VisitCoawaitExpr(CoawaitExpr *s) { + cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoawaitExpr"); + return {}; + } + mlir::Value VisitCoyieldExpr(CoyieldExpr *s) { + cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr"); + return {}; + } + mlir::Value VisitUnaryCoawait(const UnaryOperator *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryCoawait"); + return {}; + } + + mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant, + Expr *e) { + assert(constant && "not a constant"); + if (constant.isReference()) + return emitLoadOfLValue(constant.getReferenceLValue(cgf, e), + e->getExprLoc()); + + mlir::TypedAttr valueAttr = constant.getValue(); + return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr); + } + // l-values. + mlir::Value VisitDeclRefExpr(DeclRefExpr *e) { + if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e)) + return emitConstant(constant, e); + return emitLoadOfLValue(e); + } + mlir::Value VisitObjCIvarRefExpr(ObjCIvarRefExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitObjCIvarRefExpr"); + return {}; + } + mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitObjCMessageExpr"); + return {}; + } + mlir::Value VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); } mlir::Value VisitMemberExpr(MemberExpr *me) { if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) { cgf.emitIgnoredExpr(me->getBase()); @@ -69,45 +127,99 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { } return emitLoadOfLValue(me); } + mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitOpaqueValueExpr"); + return {}; + } - mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { - return emitLoadOfLValue(e); + mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitPseudoObjectExpr"); + return {}; } - mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il); - mlir::Value VisitParenExpr(ParenExpr *e); - mlir::Value - VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e); + mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy); + mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e) { + // Unlike for scalars, we don't have to worry about function->ptr demotion + // here. + if (e->changesVolatileQualification()) + return emitLoadOfLValue(e); + return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); + } + mlir::Value VisitCastExpr(CastExpr *e) { + if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) { + // Bind VLAs in the cast type. + if (ece->getType()->isVariablyModifiedType()) { + cgf.cgm.errorNYI(e->getExprLoc(), + "VisitCastExpr Bind VLAs in the cast type"); + return {}; + } + } - mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op, - bool isPre); + if (e->changesVolatileQualification()) + return emitLoadOfLValue(e); + + return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); + } + mlir::Value VisitCallExpr(const CallExpr *e); + mlir::Value VisitStmtExpr(const StmtExpr *e); + // Operators. + mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op, + bool isPre) { + LValue lv = cgf.emitLValue(e->getSubExpr()); + return cgf.emitComplexPrePostIncDec(e, lv, op, isPre); + } mlir::Value VisitUnaryPostDec(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, false); } - mlir::Value VisitUnaryPostInc(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, false); } - mlir::Value VisitUnaryPreDec(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, true); } - mlir::Value VisitUnaryPreInc(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, true); } - - mlir::Value VisitUnaryDeref(const Expr *e); + mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); } mlir::Value VisitUnaryPlus(const UnaryOperator *e); - + mlir::Value VisitUnaryMinus(const UnaryOperator *e); mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind, QualType promotionType); - - mlir::Value VisitUnaryMinus(const UnaryOperator *e); - mlir::Value VisitUnaryNot(const UnaryOperator *e); + // LNot,Real,Imag never return complex. + mlir::Value VisitUnaryExtension(const UnaryOperator *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryExtension"); + return {}; + } + mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) { + cgf.cgm.errorNYI(dae->getExprLoc(), + "ComplexExprEmitter VisitCXXDefaultArgExpr"); + return {}; + } + mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) { + cgf.cgm.errorNYI(die->getExprLoc(), + "ComplexExprEmitter VisitCXXDefaultInitExpr"); + return {}; + } + mlir::Value VisitExprWithCleanups(ExprWithCleanups *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitExprWithCleanups"); + return {}; + } + mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) { + mlir::Location loc = cgf.getLoc(e->getExprLoc()); + mlir::Type complexTy = cgf.convertType(e->getType()); + return builder.getNullValue(complexTy, loc); + } + mlir::Value VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitImplicitValueInitExpr"); + return {}; + } struct BinOpInfo { mlir::Location loc; @@ -121,14 +233,11 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { QualType promotionTy = QualType()); mlir::Value emitPromoted(const Expr *e, QualType promotionTy); - mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy); - LValue emitCompoundAssignLValue( const CompoundAssignOperator *e, mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value); - mlir::Value emitCompoundAssign( const CompoundAssignOperator *e, mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)); @@ -166,52 +275,179 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { HANDLEBINOP(Div) #undef HANDLEBINOP + mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitCXXRewrittenBinaryOperator"); + return {}; + } + // Compound assignments. mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd); } - mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub); } - mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul); } - mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv); } + // GCC rejects rem/and/or/xor for integer complex. + // Logical and/or always return int, never complex. + + // No comparisons produce a complex result. + + LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val); + mlir::Value VisitBinAssign(const BinaryOperator *e); + mlir::Value VisitBinComma(const BinaryOperator *e); + + mlir::Value + VisitAbstractConditionalOperator(const AbstractConditionalOperator *e); + mlir::Value VisitChooseExpr(ChooseExpr *e); + + mlir::Value VisitInitListExpr(InitListExpr *e); + + mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { + return emitLoadOfLValue(e); + } + mlir::Value VisitVAArgExpr(VAArgExpr *e); + + mlir::Value VisitAtomicExpr(AtomicExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitAtomicExpr"); + return {}; + } + + mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitPackIndexingExpr"); + return {}; + } }; } // namespace -#ifndef NDEBUG -// Only used in asserts -static const ComplexType *getComplexType(QualType type) { - type = type.getCanonicalType(); - if (const ComplexType *comp = dyn_cast<ComplexType>(type)) - return comp; - return cast<ComplexType>(cast<AtomicType>(type)->getValueType()); +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to +/// load the real and imaginary pieces, returning them as Real/Imag. +mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv, + SourceLocation loc) { + assert(lv.isSimple() && "non-simple complex l-value?"); + if (lv.getType()->isAtomicType()) + cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV"); + + const Address srcAddr = lv.getAddress(); + return builder.createLoad(cgf.getLoc(loc), srcAddr); } -#endif // NDEBUG -LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e, - mlir::Value &value) { - assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(), - e->getRHS()->getType()) && - "Invalid assignment"); +/// EmitStoreOfComplex - Store the specified real/imag parts into the +/// specified value pointer. +void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val, + LValue lv, bool isInit) { + if (lv.getType()->isAtomicType() || + (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) { + cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV"); + return; + } - // Emit the RHS. __block variables need the RHS evaluated first. - value = Visit(e->getRHS()); + const Address destAddr = lv.getAddress(); + builder.createStore(loc, val, destAddr); +} - // Compute the address to store into. - LValue lhs = cgf.emitLValue(e->getLHS()); +//===----------------------------------------------------------------------===// +// Visitor Methods +//===----------------------------------------------------------------------===// - // Store the result value into the LHS lvalue. - emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false); - return lhs; +mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr"); + return {}; +} + +mlir::Value +ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) { + auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType())); + mlir::Type elementTy = ty.getElementType(); + mlir::Location loc = cgf.getLoc(il->getExprLoc()); + + mlir::TypedAttr realValueAttr; + mlir::TypedAttr imagValueAttr; + + if (mlir::isa<cir::IntType>(elementTy)) { + llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue(); + realValueAttr = cir::IntAttr::get(elementTy, 0); + imagValueAttr = cir::IntAttr::get(elementTy, imagValue); + } else { + assert(mlir::isa<cir::FPTypeInterface>(elementTy) && + "Expected complex element type to be floating-point"); + + llvm::APFloat imagValue = + cast<FloatingLiteral>(il->getSubExpr())->getValue(); + realValueAttr = cir::FPAttr::get( + elementTy, llvm::APFloat::getZero(imagValue.getSemantics())); + imagValueAttr = cir::FPAttr::get(elementTy, imagValue); + } + + auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr); + return builder.create<cir::ConstantOp>(loc, complexAttr); +} + +mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) { + if (e->getCallReturnType(cgf.getContext())->isReferenceType()) + return emitLoadOfLValue(e); + return cgf.emitCallExpr(e).getComplexValue(); +} + +mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr"); + return {}; +} + +mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val, + QualType srcType, + QualType destType, + SourceLocation loc) { + if (srcType == destType) + return val; + + // Get the src/dest element type. + QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType(); + QualType destElemTy = destType->castAs<ComplexType>()->getElementType(); + + cir::CastKind castOpKind; + if (srcElemTy->isFloatingType() && destElemTy->isFloatingType()) + castOpKind = cir::CastKind::float_complex; + else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType()) + castOpKind = cir::CastKind::float_complex_to_int_complex; + else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType()) + castOpKind = cir::CastKind::int_complex_to_float_complex; + else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType()) + castOpKind = cir::CastKind::int_complex; + else + llvm_unreachable("unexpected src type or dest type"); + + return builder.createCast(cgf.getLoc(loc), castOpKind, val, + cgf.convertType(destType)); +} + +mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val, + QualType srcType, + QualType destType, + SourceLocation loc) { + cir::CastKind castOpKind; + if (srcType->isFloatingType()) + castOpKind = cir::CastKind::float_to_complex; + else if (srcType->isIntegerType()) + castOpKind = cir::CastKind::int_to_complex; + else + llvm_unreachable("unexpected src type"); + + return builder.createCast(cgf.getLoc(loc), castOpKind, val, + cgf.convertType(destType)); } mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, @@ -334,6 +570,14 @@ mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) { return result; } +mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) { + QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); + mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy); + if (!promotionTy.isNull()) + return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType()); + return result; +} + mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind, QualType promotionType) { @@ -349,258 +593,149 @@ mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e, return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op); } -mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) { - QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); - mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy); - if (!promotionTy.isNull()) - return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType()); - return result; +mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) { + mlir::Value op = Visit(e->getSubExpr()); + return builder.createNot(op); } -mlir::Value ComplexExprEmitter::emitConstant( - const CIRGenFunction::ConstantEmission &constant, Expr *e) { - assert(constant && "not a constant"); - if (constant.isReference()) - return emitLoadOfLValue(constant.getReferenceLValue(cgf, e), - e->getExprLoc()); - - mlir::TypedAttr valueAttr = constant.getValue(); - return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr); -} +mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); -mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv, - ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/156241 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits