@@ -51,11 +51,12 @@ class ComplexExprEmitter
5151 CGBuilderTy &Builder;
5252 bool IgnoreReal;
5353 bool IgnoreImag;
54- public:
55- ComplexExprEmitter (CodeGenFunction &cgf, bool ir=false , bool ii=false )
56- : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) {
57- }
54+ bool FPHasBeenPromoted;
5855
56+ public:
57+ ComplexExprEmitter (CodeGenFunction &cgf, bool ir = false , bool ii = false )
58+ : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii),
59+ FPHasBeenPromoted (false ) {}
5960
6061 // ===--------------------------------------------------------------------===//
6162 // Utilities
@@ -287,9 +288,54 @@ class ComplexExprEmitter
287288 ComplexPairTy EmitComplexBinOpLibCall (StringRef LibCallName,
288289 const BinOpInfo &Op);
289290
290- QualType getPromotionType (QualType Ty) {
291+ QualType GetHigherPrecisionFPType (QualType ElementType) {
292+ const auto *CurrentBT = dyn_cast<BuiltinType>(ElementType);
293+ switch (CurrentBT->getKind ()) {
294+ case BuiltinType::Kind::Float16:
295+ return CGF.getContext ().FloatTy ;
296+ case BuiltinType::Kind::Float:
297+ case BuiltinType::Kind::BFloat16:
298+ return CGF.getContext ().DoubleTy ;
299+ case BuiltinType::Kind::Double:
300+ return CGF.getContext ().LongDoubleTy ;
301+ default :
302+ return ElementType;
303+ }
304+ }
305+
306+ QualType HigherPrecisionTypeForComplexArithmetic (QualType ElementType,
307+ bool IsDivOpCode) {
308+ QualType HigherElementType = GetHigherPrecisionFPType (ElementType);
309+ const llvm::fltSemantics &ElementTypeSemantics =
310+ CGF.getContext ().getFloatTypeSemantics (ElementType);
311+ const llvm::fltSemantics &HigherElementTypeSemantics =
312+ CGF.getContext ().getFloatTypeSemantics (HigherElementType);
313+ // Check that the promoted type can handle the intermediate values without
314+ // overflowing. This can be interpreted as:
315+ // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <=
316+ // LargerType.LargestFiniteVal.
317+ // In terms of exponent it gives this formula:
318+ // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal
319+ // doubles the exponent of SmallerType.LargestFiniteVal)
320+ if (llvm::APFloat::semanticsMaxExponent (ElementTypeSemantics) * 2 + 1 <=
321+ llvm::APFloat::semanticsMaxExponent (HigherElementTypeSemantics)) {
322+ return CGF.getContext ().getComplexType (HigherElementType);
323+ } else {
324+ FPHasBeenPromoted = true ;
325+ DiagnosticsEngine &Diags = CGF.CGM .getDiags ();
326+ Diags.Report (diag::warn_next_larger_fp_type_same_size_than_fp);
327+ return CGF.getContext ().getComplexType (ElementType);
328+ }
329+ }
330+
331+ QualType getPromotionType (QualType Ty, bool IsDivOpCode = false ) {
291332 if (auto *CT = Ty->getAs <ComplexType>()) {
292333 QualType ElementType = CT->getElementType ();
334+ if (IsDivOpCode && ElementType->isFloatingType () &&
335+ CGF.getLangOpts ().getComplexRange () ==
336+ LangOptions::ComplexRangeKind::CX_Promoted)
337+ return HigherPrecisionTypeForComplexArithmetic (ElementType,
338+ IsDivOpCode);
293339 if (ElementType.UseExcessPrecision (CGF.getContext ()))
294340 return CGF.getContext ().getComplexType (CGF.getContext ().FloatTy );
295341 }
@@ -300,11 +346,12 @@ class ComplexExprEmitter
300346
301347#define HANDLEBINOP (OP ) \
302348 ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \
303- QualType promotionTy = getPromotionType (E->getType ()); \
349+ QualType promotionTy = getPromotionType ( \
350+ E->getType (), \
351+ (E->getOpcode () == BinaryOperatorKind::BO_Div) ? true : false ); \
304352 ComplexPairTy result = EmitBin##OP (EmitBinOps (E, promotionTy)); \
305353 if (!promotionTy.isNull ()) \
306- result = \
307- CGF.EmitUnPromotedValue (result, E->getType ()); \
354+ result = CGF.EmitUnPromotedValue (result, E->getType ()); \
308355 return result; \
309356 }
310357
@@ -794,8 +841,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
794841 ResR = Builder.CreateFSub (AC, BD, " mul_r" );
795842 ResI = Builder.CreateFAdd (AD, BC, " mul_i" );
796843
797- if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Limited ||
798- Op.FPFeatures .getComplexRange () == LangOptions::CX_Fortran)
844+ if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Basic ||
845+ Op.FPFeatures .getComplexRange () == LangOptions::CX_Improved ||
846+ Op.FPFeatures .getComplexRange () == LangOptions::CX_Promoted)
799847 return ComplexPairTy (ResR, ResI);
800848
801849 // Emit the test for the real part becoming NaN and create a branch to
@@ -986,14 +1034,17 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
9861034 llvm::Value *OrigLHSi = LHSi;
9871035 if (!LHSi)
9881036 LHSi = llvm::Constant::getNullValue (RHSi->getType ());
989- if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Fortran)
1037+ QualType ComplexElementTy = Op.Ty ->castAs <ComplexType>()->getElementType ();
1038+ if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Improved ||
1039+ (Op.FPFeatures .getComplexRange () == LangOptions::CX_Promoted &&
1040+ FPHasBeenPromoted))
9901041 return EmitRangeReductionDiv (LHSr, LHSi, RHSr, RHSi);
991- else if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Limited)
1042+ else if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Basic ||
1043+ Op.FPFeatures .getComplexRange () == LangOptions::CX_Promoted)
9921044 return EmitAlgebraicDiv (LHSr, LHSi, RHSr, RHSi);
993- else if (!CGF.getLangOpts ().FastMath ||
994- // '-ffast-math' is used in the command line but followed by an
995- // '-fno-cx-limited-range'.
996- Op.FPFeatures .getComplexRange () == LangOptions::CX_Full) {
1045+ // '-ffast-math' is used in the command line but followed by an
1046+ // '-fno-cx-limited-range' or '-fcomplex-arithmetic=full'.
1047+ else if (Op.FPFeatures .getComplexRange () == LangOptions::CX_Full) {
9971048 LHSi = OrigLHSi;
9981049 // If we have a complex operand on the RHS and FastMath is not allowed, we
9991050 // delegate to a libcall to handle all of the complexities and minimize
0 commit comments