diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index a8add9d1337c6b..5b813bfc2faf90 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2333,6 +2333,11 @@ class UnaryOperator final return getTrailingFPFeatures(); } + /// Get the store FPOptionsOverride or default if not stored. + FPOptionsOverride getStoredFPFeaturesOrDefault() const { + return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride(); + } + protected: /// Set FPFeatures in trailing storage, used by Serialization & ASTImporter. void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; } @@ -3096,6 +3101,11 @@ class CallExpr : public Expr { *getTrailingFPFeatures() = F; } + /// Get the store FPOptionsOverride or default if not stored. + FPOptionsOverride getStoredFPFeaturesOrDefault() const { + return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride(); + } + /// Get the FP features status of this operator. Only meaningful for /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { @@ -3592,6 +3602,11 @@ class CastExpr : public Expr { return *getTrailingFPFeatures(); } + /// Get the store FPOptionsOverride or default if not stored. + FPOptionsOverride getStoredFPFeaturesOrDefault() const { + return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride(); + } + /// Get the FP features status of this operation. Only meaningful for /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { @@ -4038,6 +4053,10 @@ class BinaryOperator : public Expr { assert(BinaryOperatorBits.HasFPFeatures); *getTrailingFPFeatures() = F; } + /// Get the store FPOptionsOverride or default if not stored. + FPOptionsOverride getStoredFPFeaturesOrDefault() const { + return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride(); + } /// Get the FP features status of this operator. Only meaningful for /// operations on floating point types. diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 9cd7a364cd3f1d..e91e89d728ca09 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1658,6 +1658,11 @@ class CompoundStmt final return *getTrailingObjects(); } + /// Get the store FPOptionsOverride or default if not stored. + FPOptionsOverride getStoredFPFeaturesOrDefault() const { + return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride(); + } + using body_iterator = Stmt **; using body_range = llvm::iterator_range; diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 000d4ff5c06986..4d45f6d64c1cd9 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -328,12 +328,20 @@ class ComplexExprEmitter } } - QualType getPromotionType(QualType Ty, bool IsDivOpCode = false) { + QualType getPromotionType(FPOptionsOverride Features, QualType Ty, + bool IsDivOpCode = false) { if (auto *CT = Ty->getAs()) { QualType ElementType = CT->getElementType(); - if (IsDivOpCode && ElementType->isFloatingType() && - CGF.getLangOpts().getComplexRange() == - LangOptions::ComplexRangeKind::CX_Promoted) + bool IsFloatingType = ElementType->isFloatingType(); + bool IsComplexRangePromoted = CGF.getLangOpts().getComplexRange() == + LangOptions::ComplexRangeKind::CX_Promoted; + bool HasNoComplexRangeOverride = !Features.hasComplexRangeOverride(); + bool HasMatchingComplexRange = Features.hasComplexRangeOverride() && + Features.getComplexRangeOverride() == + CGF.getLangOpts().getComplexRange(); + + if (IsDivOpCode && IsFloatingType && IsComplexRangePromoted && + (HasNoComplexRangeOverride || HasMatchingComplexRange)) return HigherPrecisionTypeForComplexArithmetic(ElementType, IsDivOpCode); if (ElementType.UseExcessPrecision(CGF.getContext())) @@ -347,7 +355,7 @@ class ComplexExprEmitter #define HANDLEBINOP(OP) \ ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \ QualType promotionTy = getPromotionType( \ - E->getType(), \ + E->getStoredFPFeaturesOrDefault(), E->getType(), \ (E->getOpcode() == BinaryOperatorKind::BO_Div) ? true : false); \ ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \ if (!promotionTy.isNull()) \ @@ -641,9 +649,12 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, ComplexPairTy ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *E, QualType PromotionType) { - QualType promotionTy = PromotionType.isNull() - ? getPromotionType(E->getSubExpr()->getType()) - : PromotionType; + E->hasStoredFPFeatures(); + QualType promotionTy = + PromotionType.isNull() + ? getPromotionType(E->getStoredFPFeaturesOrDefault(), + E->getSubExpr()->getType()) + : PromotionType; ComplexPairTy result = VisitPlus(E, promotionTy); if (!promotionTy.isNull()) return CGF.EmitUnPromotedValue(result, E->getSubExpr()->getType()); @@ -661,9 +672,11 @@ ComplexPairTy ComplexExprEmitter::VisitPlus(const UnaryOperator *E, ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E, QualType PromotionType) { - QualType promotionTy = PromotionType.isNull() - ? getPromotionType(E->getSubExpr()->getType()) - : PromotionType; + QualType promotionTy = + PromotionType.isNull() + ? getPromotionType(E->getStoredFPFeaturesOrDefault(), + E->getSubExpr()->getType()) + : PromotionType; ComplexPairTy result = VisitMinus(E, promotionTy); if (!promotionTy.isNull()) return CGF.EmitUnPromotedValue(result, E->getSubExpr()->getType()); @@ -1218,13 +1231,15 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, // __block variables need to have the rhs evaluated first, plus this should // improve codegen a little. QualType PromotionTypeCR; - PromotionTypeCR = getPromotionType(E->getComputationResultType()); + PromotionTypeCR = getPromotionType(E->getStoredFPFeaturesOrDefault(), + E->getComputationResultType()); if (PromotionTypeCR.isNull()) PromotionTypeCR = E->getComputationResultType(); OpInfo.Ty = PromotionTypeCR; QualType ComplexElementTy = OpInfo.Ty->castAs()->getElementType(); - QualType PromotionTypeRHS = getPromotionType(E->getRHS()->getType()); + QualType PromotionTypeRHS = getPromotionType( + E->getStoredFPFeaturesOrDefault(), E->getRHS()->getType()); // The RHS should have been converted to the computation type. if (E->getRHS()->getType()->isRealFloatingType()) { @@ -1252,7 +1267,8 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, // Load from the l-value and convert it. SourceLocation Loc = E->getExprLoc(); - QualType PromotionTypeLHS = getPromotionType(E->getComputationLHSType()); + QualType PromotionTypeLHS = getPromotionType( + E->getStoredFPFeaturesOrDefault(), E->getComputationLHSType()); if (LHSTy->isAnyComplexType()) { ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc); if (!PromotionTypeLHS.isNull()) diff --git a/clang/test/CodeGen/pragma-cx-limited-range.c b/clang/test/CodeGen/pragma-cx-limited-range.c index 68615348c1871f..1c9bf40fd714f8 100644 --- a/clang/test/CodeGen/pragma-cx-limited-range.c +++ b/clang/test/CodeGen/pragma-cx-limited-range.c @@ -106,21 +106,17 @@ _Complex float pragma_on_div(_Complex float a, _Complex float b) { // IMPRVD-NEXT: fdiv float // IMPRVD-NEXT: fdiv float - // PRMTD: fpext float {{.*}} to double - // PRMTD: fpext float {{.*}} to double - // PRMTD: fmul double - // PRMTD: fmul double - // PRMTD: fadd double - // PRMTD: fmul double - // PRMTD: fmul double - // PRMTD: fadd double - // PRMTD: fmul double - // PRMTD: fmul double - // PRMTD: fsub double - // PRMTD: fdiv double - // PRMTD: fdiv double - // PRMTD: fptrunc double - // PRMTD: fptrunc double + // PRMTD: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fadd float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fadd float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fsub float + // PRMTD-NEXT: fdiv float + // PRMTD-NEXT: fdiv float return a / b; } @@ -135,7 +131,7 @@ _Complex float pragma_off_div(_Complex float a, _Complex float b) { // IMPRVD: call {{.*}} @__divsc3 - // PRMTD: call {{.*}} @__divdc3 + // PRMTD: call {{.*}} @__divsc3 return a / b; }