@@ -51,11 +51,12 @@ class ComplexExprEmitter
51
51
CGBuilderTy &Builder;
52
52
bool IgnoreReal;
53
53
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;
58
55
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 ) {}
59
60
60
61
// ===--------------------------------------------------------------------===//
61
62
// Utilities
@@ -287,9 +288,54 @@ class ComplexExprEmitter
287
288
ComplexPairTy EmitComplexBinOpLibCall (StringRef LibCallName,
288
289
const BinOpInfo &Op);
289
290
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 ) {
291
332
if (auto *CT = Ty->getAs <ComplexType>()) {
292
333
QualType ElementType = CT->getElementType ();
334
+ if (IsDivOpCode && ElementType->isFloatingType () &&
335
+ CGF.getLangOpts ().getComplexRange () ==
336
+ LangOptions::ComplexRangeKind::CX_Promoted)
337
+ return HigherPrecisionTypeForComplexArithmetic (ElementType,
338
+ IsDivOpCode);
293
339
if (ElementType.UseExcessPrecision (CGF.getContext ()))
294
340
return CGF.getContext ().getComplexType (CGF.getContext ().FloatTy );
295
341
}
@@ -300,11 +346,12 @@ class ComplexExprEmitter
300
346
301
347
#define HANDLEBINOP (OP ) \
302
348
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 ); \
304
352
ComplexPairTy result = EmitBin##OP (EmitBinOps (E, promotionTy)); \
305
353
if (!promotionTy.isNull ()) \
306
- result = \
307
- CGF.EmitUnPromotedValue (result, E->getType ()); \
354
+ result = CGF.EmitUnPromotedValue (result, E->getType ()); \
308
355
return result; \
309
356
}
310
357
@@ -794,8 +841,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
794
841
ResR = Builder.CreateFSub (AC, BD, " mul_r" );
795
842
ResI = Builder.CreateFAdd (AD, BC, " mul_i" );
796
843
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)
799
847
return ComplexPairTy (ResR, ResI);
800
848
801
849
// Emit the test for the real part becoming NaN and create a branch to
@@ -986,14 +1034,17 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
986
1034
llvm::Value *OrigLHSi = LHSi;
987
1035
if (!LHSi)
988
1036
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))
990
1041
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)
992
1044
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) {
997
1048
LHSi = OrigLHSi;
998
1049
// If we have a complex operand on the RHS and FastMath is not allowed, we
999
1050
// delegate to a libcall to handle all of the complexities and minimize
0 commit comments