Skip to content

Commit fd4e77c

Browse files
[flang][driver] Accelerate complex division when -ffast-math is specified (#159689)
This patch accelerates complex division by passing `-complex-range=basic` to the frontend when the `-ffast-math` option is specified. This behavior is the same as `-fcomplex-arithmetic=basic`. A warning is issued if a different value is specified for `-fcomplex-arithmetic=`. The warning conditions will be unified with clang.
1 parent 89ed525 commit fd4e77c

File tree

7 files changed

+179
-66
lines changed

7 files changed

+179
-66
lines changed

clang/include/clang/Driver/CommonArgs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
304304
// Render a frontend option corresponding to ComplexRangeKind.
305305
std::string renderComplexRangeOption(LangOptions::ComplexRangeKind Range);
306306

307+
// Set the complex range and output a warning as needed.
308+
void setComplexRange(const Driver &D, StringRef NewOpt,
309+
LangOptions::ComplexRangeKind NewRange, StringRef &LastOpt,
310+
LangOptions::ComplexRangeKind &Range);
311+
307312
} // end namespace tools
308313
} // end namespace driver
309314
} // end namespace clang

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 28 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,42 +2723,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
27232723
}
27242724
}
27252725

2726-
static void EmitComplexRangeDiag(const Driver &D, StringRef LastOpt,
2727-
LangOptions::ComplexRangeKind Range,
2728-
StringRef NewOpt,
2729-
LangOptions::ComplexRangeKind NewRange) {
2730-
// Do not emit a warning if NewOpt overrides LastOpt in the following cases.
2731-
//
2732-
// | LastOpt | NewOpt |
2733-
// |-----------------------|-----------------------|
2734-
// | -fcx-limited-range | -fno-cx-limited-range |
2735-
// | -fno-cx-limited-range | -fcx-limited-range |
2736-
// | -fcx-fortran-rules | -fno-cx-fortran-rules |
2737-
// | -fno-cx-fortran-rules | -fcx-fortran-rules |
2738-
// | -ffast-math | -fno-fast-math |
2739-
// | -ffp-model= | -ffast-math |
2740-
// | -ffp-model= | -fno-fast-math |
2741-
// | -ffp-model= | -ffp-model= |
2742-
// | -fcomplex-arithmetic= | -fcomplex-arithmetic= |
2743-
if (LastOpt == NewOpt || NewOpt.empty() || LastOpt.empty() ||
2744-
(LastOpt == "-fcx-limited-range" && NewOpt == "-fno-cx-limited-range") ||
2745-
(LastOpt == "-fno-cx-limited-range" && NewOpt == "-fcx-limited-range") ||
2746-
(LastOpt == "-fcx-fortran-rules" && NewOpt == "-fno-cx-fortran-rules") ||
2747-
(LastOpt == "-fno-cx-fortran-rules" && NewOpt == "-fcx-fortran-rules") ||
2748-
(LastOpt == "-ffast-math" && NewOpt == "-fno-fast-math") ||
2749-
(LastOpt.starts_with("-ffp-model=") && NewOpt == "-ffast-math") ||
2750-
(LastOpt.starts_with("-ffp-model=") && NewOpt == "-fno-fast-math") ||
2751-
(LastOpt.starts_with("-ffp-model=") &&
2752-
NewOpt.starts_with("-ffp-model=")) ||
2753-
(LastOpt.starts_with("-fcomplex-arithmetic=") &&
2754-
NewOpt.starts_with("-fcomplex-arithmetic=")))
2755-
return;
2756-
2757-
D.Diag(clang::diag::warn_drv_overriding_complex_range)
2758-
<< LastOpt << NewOpt << complexRangeKindToStr(Range)
2759-
<< complexRangeKindToStr(NewRange);
2760-
}
2761-
27622726
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
27632727
bool OFastEnabled, const ArgList &Args,
27642728
ArgStringList &CmdArgs,
@@ -2815,27 +2779,19 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
28152779
std::string ComplexRangeStr;
28162780
StringRef LastComplexRangeOption;
28172781

2818-
auto setComplexRange = [&](StringRef NewOption,
2819-
LangOptions::ComplexRangeKind NewRange) {
2820-
// Warn if user overrides the previously set complex number
2821-
// multiplication/division option.
2822-
if (Range != LangOptions::ComplexRangeKind::CX_None && Range != NewRange)
2823-
EmitComplexRangeDiag(D, LastComplexRangeOption, Range, NewOption,
2824-
NewRange);
2825-
LastComplexRangeOption = NewOption;
2826-
Range = NewRange;
2827-
};
2828-
28292782
// Lambda to set fast-math options. This is also used by -ffp-model=fast
28302783
auto applyFastMath = [&](bool Aggressive, StringRef CallerOption) {
28312784
if (Aggressive) {
28322785
HonorINFs = false;
28332786
HonorNaNs = false;
2834-
setComplexRange(CallerOption, LangOptions::ComplexRangeKind::CX_Basic);
2787+
setComplexRange(D, CallerOption, LangOptions::ComplexRangeKind::CX_Basic,
2788+
LastComplexRangeOption, Range);
28352789
} else {
28362790
HonorINFs = true;
28372791
HonorNaNs = true;
2838-
setComplexRange(CallerOption, LangOptions::ComplexRangeKind::CX_Promoted);
2792+
setComplexRange(D, CallerOption,
2793+
LangOptions::ComplexRangeKind::CX_Promoted,
2794+
LastComplexRangeOption, Range);
28392795
}
28402796
MathErrno = false;
28412797
AssociativeMath = true;
@@ -2887,18 +2843,24 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
28872843
default: continue;
28882844

28892845
case options::OPT_fcx_limited_range:
2890-
setComplexRange(A->getSpelling(),
2891-
LangOptions::ComplexRangeKind::CX_Basic);
2846+
setComplexRange(D, A->getSpelling(),
2847+
LangOptions::ComplexRangeKind::CX_Basic,
2848+
LastComplexRangeOption, Range);
28922849
break;
28932850
case options::OPT_fno_cx_limited_range:
2894-
setComplexRange(A->getSpelling(), LangOptions::ComplexRangeKind::CX_Full);
2851+
setComplexRange(D, A->getSpelling(),
2852+
LangOptions::ComplexRangeKind::CX_Full,
2853+
LastComplexRangeOption, Range);
28952854
break;
28962855
case options::OPT_fcx_fortran_rules:
2897-
setComplexRange(A->getSpelling(),
2898-
LangOptions::ComplexRangeKind::CX_Improved);
2856+
setComplexRange(D, A->getSpelling(),
2857+
LangOptions::ComplexRangeKind::CX_Improved,
2858+
LastComplexRangeOption, Range);
28992859
break;
29002860
case options::OPT_fno_cx_fortran_rules:
2901-
setComplexRange(A->getSpelling(), LangOptions::ComplexRangeKind::CX_Full);
2861+
setComplexRange(D, A->getSpelling(),
2862+
LangOptions::ComplexRangeKind::CX_Full,
2863+
LastComplexRangeOption, Range);
29022864
break;
29032865
case options::OPT_fcomplex_arithmetic_EQ: {
29042866
LangOptions::ComplexRangeKind RangeVal;
@@ -2916,7 +2878,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
29162878
<< A->getSpelling() << Val;
29172879
break;
29182880
}
2919-
setComplexRange(Args.MakeArgString(A->getSpelling() + Val), RangeVal);
2881+
setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), RangeVal,
2882+
LastComplexRangeOption, Range);
29202883
break;
29212884
}
29222885
case options::OPT_ffp_model_EQ: {
@@ -2956,8 +2919,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
29562919
FPModel = Val;
29572920
FPContract = "on";
29582921
LastFpContractOverrideOption = "-ffp-model=precise";
2959-
setComplexRange(Args.MakeArgString(A->getSpelling() + Val),
2960-
LangOptions::ComplexRangeKind::CX_Full);
2922+
setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val),
2923+
LangOptions::ComplexRangeKind::CX_Full,
2924+
LastComplexRangeOption, Range);
29612925
} else if (Val == "strict") {
29622926
StrictFPModel = true;
29632927
FPExceptionBehavior = "strict";
@@ -2966,8 +2930,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
29662930
LastFpContractOverrideOption = "-ffp-model=strict";
29672931
TrappingMath = true;
29682932
RoundingFPMath = true;
2969-
setComplexRange(Args.MakeArgString(A->getSpelling() + Val),
2970-
LangOptions::ComplexRangeKind::CX_Full);
2933+
setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val),
2934+
LangOptions::ComplexRangeKind::CX_Full,
2935+
LastComplexRangeOption, Range);
29712936
} else
29722937
D.Diag(diag::err_drv_unsupported_option_argument)
29732938
<< A->getSpelling() << Val;
@@ -3174,8 +3139,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
31743139
SignedZeros = true;
31753140
restoreFPContractState();
31763141
if (Range != LangOptions::ComplexRangeKind::CX_Full)
3177-
setComplexRange(A->getSpelling(),
3178-
LangOptions::ComplexRangeKind::CX_None);
3142+
setComplexRange(D, A->getSpelling(),
3143+
LangOptions::ComplexRangeKind::CX_None,
3144+
LastComplexRangeOption, Range);
31793145
else
31803146
Range = LangOptions::ComplexRangeKind::CX_None;
31813147
LastComplexRangeOption = "";

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3557,3 +3557,51 @@ tools::renderComplexRangeOption(LangOptionsBase::ComplexRangeKind Range) {
35573557
return "-complex-range=" + ComplexRangeStr;
35583558
return ComplexRangeStr;
35593559
}
3560+
3561+
static void emitComplexRangeDiag(const Driver &D, StringRef LastOpt,
3562+
LangOptions::ComplexRangeKind Range,
3563+
StringRef NewOpt,
3564+
LangOptions::ComplexRangeKind NewRange) {
3565+
// Do not emit a warning if NewOpt overrides LastOpt in the following cases.
3566+
//
3567+
// | LastOpt | NewOpt |
3568+
// |-----------------------|-----------------------|
3569+
// | -fcx-limited-range | -fno-cx-limited-range |
3570+
// | -fno-cx-limited-range | -fcx-limited-range |
3571+
// | -fcx-fortran-rules | -fno-cx-fortran-rules |
3572+
// | -fno-cx-fortran-rules | -fcx-fortran-rules |
3573+
// | -ffast-math | -fno-fast-math |
3574+
// | -ffp-model= | -ffast-math |
3575+
// | -ffp-model= | -fno-fast-math |
3576+
// | -ffp-model= | -ffp-model= |
3577+
// | -fcomplex-arithmetic= | -fcomplex-arithmetic= |
3578+
if (LastOpt == NewOpt || NewOpt.empty() || LastOpt.empty() ||
3579+
(LastOpt == "-fcx-limited-range" && NewOpt == "-fno-cx-limited-range") ||
3580+
(LastOpt == "-fno-cx-limited-range" && NewOpt == "-fcx-limited-range") ||
3581+
(LastOpt == "-fcx-fortran-rules" && NewOpt == "-fno-cx-fortran-rules") ||
3582+
(LastOpt == "-fno-cx-fortran-rules" && NewOpt == "-fcx-fortran-rules") ||
3583+
(LastOpt == "-ffast-math" && NewOpt == "-fno-fast-math") ||
3584+
(LastOpt.starts_with("-ffp-model=") && NewOpt == "-ffast-math") ||
3585+
(LastOpt.starts_with("-ffp-model=") && NewOpt == "-fno-fast-math") ||
3586+
(LastOpt.starts_with("-ffp-model=") &&
3587+
NewOpt.starts_with("-ffp-model=")) ||
3588+
(LastOpt.starts_with("-fcomplex-arithmetic=") &&
3589+
NewOpt.starts_with("-fcomplex-arithmetic=")))
3590+
return;
3591+
3592+
D.Diag(clang::diag::warn_drv_overriding_complex_range)
3593+
<< LastOpt << NewOpt << complexRangeKindToStr(Range)
3594+
<< complexRangeKindToStr(NewRange);
3595+
}
3596+
3597+
void tools::setComplexRange(const Driver &D, StringRef NewOpt,
3598+
LangOptions::ComplexRangeKind NewRange,
3599+
StringRef &LastOpt,
3600+
LangOptions::ComplexRangeKind &Range) {
3601+
// Warn if user overrides the previously set complex number
3602+
// multiplication/division option.
3603+
if (Range != LangOptions::ComplexRangeKind::CX_None && Range != NewRange)
3604+
emitComplexRangeDiag(D, LastOpt, Range, NewOpt, NewRange);
3605+
LastOpt = NewOpt;
3606+
Range = NewRange;
3607+
}

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
693693
bool AssociativeMath = false;
694694
bool ReciprocalMath = false;
695695

696+
StringRef LastComplexRangeOption;
696697
LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None;
697698

698699
if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) {
@@ -720,17 +721,22 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
720721
continue;
721722

722723
case options::OPT_fcomplex_arithmetic_EQ: {
724+
LangOptions::ComplexRangeKind NewRange;
723725
StringRef Val = A->getValue();
724726
if (Val == "full")
725-
Range = LangOptions::ComplexRangeKind::CX_Full;
727+
NewRange = LangOptions::ComplexRangeKind::CX_Full;
726728
else if (Val == "improved")
727-
Range = LangOptions::ComplexRangeKind::CX_Improved;
729+
NewRange = LangOptions::ComplexRangeKind::CX_Improved;
728730
else if (Val == "basic")
729-
Range = LangOptions::ComplexRangeKind::CX_Basic;
731+
NewRange = LangOptions::ComplexRangeKind::CX_Basic;
730732
else {
731733
D.Diag(diag::err_drv_unsupported_option_argument)
732734
<< A->getSpelling() << Val;
735+
break;
733736
}
737+
738+
setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), NewRange,
739+
LastComplexRangeOption, Range);
734740
break;
735741
}
736742
case options::OPT_fhonor_infinities:
@@ -779,6 +785,9 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
779785
ApproxFunc = true;
780786
SignedZeros = false;
781787
FPContract = "fast";
788+
setComplexRange(D, A->getSpelling(),
789+
LangOptions::ComplexRangeKind::CX_Basic,
790+
LastComplexRangeOption, Range);
782791
break;
783792
case options::OPT_fno_fast_math:
784793
HonorINFs = true;
@@ -792,6 +801,9 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
792801
// --ffp-contract=off -fno-fast-math --> -ffp-contract=off
793802
if (FPContract == "fast")
794803
FPContract = "";
804+
setComplexRange(D, A->getSpelling(),
805+
LangOptions::ComplexRangeKind::CX_None,
806+
LastComplexRangeOption, Range);
795807
break;
796808
}
797809

flang/docs/ComplexOperations.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ While [the same option in clang][2] allows specifying `promoted`, this is not
9393
implemented in Flang. Also, in the case of `improved`, clang does not handle NaN
9494
and infinite values, but Flang does. These behavioral differences arise because
9595
the transformation of complex division calculations depends on the implementation
96-
of ComplexToStandard, which may change in the future.
96+
of ComplexToStandard, which may change in the future. If you specify
97+
`-ffast-math`, the lowering is the same as specifiying
98+
`-fcomplex-arithmetic=basic`.
9799

98100
[1]: https://discourse.llvm.org/t/rfc-change-lowering-of-fortran-math-intrinsics/63971
99101
[2]: https://clang.llvm.org/docs/UsersManual.html#cmdoption-fcomplex-arithmetic

flang/docs/FlangDriver.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ documentation for more details.
573573
These correspond to LLVM IR Fast Math attributes:
574574
https://llvm.org/docs/LangRef.html#fast-math-flags
575575

576+
In addition to the above, `-ffast-math` also enables
577+
`-fcomplex-arithmetic=basic`.
578+
576579
When `-ffast-math` is specified, any linker steps generated by the compiler
577580
driver will also link to `crtfastmath.o`, which adds a static constructor
578581
that sets the FTZ/DAZ bits in MXCSR, affecting not only the current only the

flang/test/Driver/complex-range.f90

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,83 @@
1515
! RUN: not %flang -### -fcomplex-arithmetic=foo -c %s 2>&1 \
1616
! RUN: | FileCheck %s --check-prefix=ERR
1717

18+
! RUN: %flang -### -ffast-math -c %s 2>&1 \
19+
! RUN: | FileCheck %s --check-prefix=BASIC
20+
21+
! RUN: %flang -### -fno-fast-math -c %s 2>&1 \
22+
! RUN: | FileCheck %s --check-prefix=RANGE
23+
24+
! RUN: %flang -### -Werror -ffast-math -fno-fast-math -c %s 2>&1 \
25+
! RUN: | FileCheck --check-prefixes=RANGE %s
26+
27+
! RUN: %flang -### -ffast-math -fcomplex-arithmetic=full -c %s 2>&1 \
28+
! RUN: | FileCheck --check-prefixes=FULL,ARITH-FULL-OVERRIDING,FAST-OVERRIDDEN %s
29+
30+
! RUN: %flang -### -ffast-math -fcomplex-arithmetic=improved -c %s 2>&1 \
31+
! RUN: | FileCheck --check-prefixes=IMPRVD,ARITH-IMPROVED-OVERRIDING,FAST-OVERRIDDEN %s
32+
33+
! RUN: %flang -### -Werror -ffast-math -fcomplex-arithmetic=basic -c %s 2>&1 \
34+
! RUN: | FileCheck --check-prefixes=BASIC %s
35+
36+
! RUN: %flang -### -Werror -fno-fast-math -ffast-math -c %s 2>&1 \
37+
! RUN: | FileCheck --check-prefixes=BASIC %s
38+
39+
! RUN: %flang -### -Werror -fno-fast-math -fcomplex-arithmetic=full -c %s 2>&1 \
40+
! RUN: | FileCheck --check-prefixes=FULL %s
41+
42+
! RUN: %flang -### -Werror -fno-fast-math -fcomplex-arithmetic=improved -c %s 2>&1 \
43+
! RUN: | FileCheck --check-prefixes=IMPRVD %s
44+
45+
! RUN: %flang -### -Werror -fno-fast-math -fcomplex-arithmetic=basic -c %s 2>&1 \
46+
! RUN: | FileCheck --check-prefixes=BASIC %s
47+
48+
! RUN: %flang -### -fcomplex-arithmetic=full -ffast-math -c %s 2>&1 \
49+
! RUN: | FileCheck --check-prefixes=BASIC,FAST-OVERRIDING,ARITH-FULL-OVERRIDDEN %s
50+
51+
! RUN: %flang -### -Werror -fcomplex-arithmetic=full -fno-fast-math -c %s 2>&1 \
52+
! RUN: | FileCheck --check-prefixes=RANGE %s
53+
54+
! RUN: %flang -### -Werror -fcomplex-arithmetic=full -fcomplex-arithmetic=improved -c %s 2>&1 \
55+
! RUN: | FileCheck --check-prefixes=IMPRVD %s
56+
57+
! RUN: %flang -### -Werror -fcomplex-arithmetic=full -fcomplex-arithmetic=basic -c %s 2>&1 \
58+
! RUN: | FileCheck --check-prefixes=BASIC %s
59+
60+
! RUN: %flang -### -fcomplex-arithmetic=improved -ffast-math -c %s 2>&1 \
61+
! RUN: | FileCheck --check-prefixes=BASIC,FAST-OVERRIDING,ARITH-IMPROVED-OVERRIDDEN %s
62+
63+
! RUN: %flang -### -fcomplex-arithmetic=improved -fno-fast-math -c %s 2>&1 \
64+
! RUN: | FileCheck --check-prefixes=RANGE,NOFAST-OVERRIDING,ARITH-IMPROVED-OVERRIDDEN %s
65+
66+
! RUN: %flang -### -Werror -fcomplex-arithmetic=improved -fcomplex-arithmetic=full -c %s 2>&1 \
67+
! RUN: | FileCheck --check-prefixes=FULL %s
68+
69+
! RUN: %flang -### -Werror -fcomplex-arithmetic=improved -fcomplex-arithmetic=basic -c %s 2>&1 \
70+
! RUN: | FileCheck --check-prefixes=BASIC %s
71+
72+
! RUN: %flang -### -Werror -fcomplex-arithmetic=basic -ffast-math -c %s 2>&1 \
73+
! RUN: | FileCheck --check-prefixes=BASIC %s
74+
75+
! RUN: %flang -### -fcomplex-arithmetic=basic -fno-fast-math -c %s 2>&1 \
76+
! RUN: | FileCheck --check-prefixes=RANGE,NOFAST-OVERRIDING,ARITH-BASIC-OVERRIDDEN %s
77+
78+
! RUN: %flang -### -Werror -fcomplex-arithmetic=basic -fcomplex-arithmetic=full -c %s 2>&1 \
79+
! RUN: | FileCheck --check-prefixes=FULL %s
80+
81+
! RUN: %flang -### -Werror -fcomplex-arithmetic=basic -fcomplex-arithmetic=improved -c %s 2>&1 \
82+
! RUN: | FileCheck --check-prefixes=IMPRVD %s
83+
84+
85+
! FAST-OVERRIDING: warning: '-ffast-math' sets complex range to "basic"
86+
! NOFAST-OVERRIDING: warning: '-fno-fast-math' sets complex range to "none"
87+
! ARITH-FULL-OVERRIDING: warning: '-fcomplex-arithmetic=full' sets complex range to "full"
88+
! ARITH-IMPROVED-OVERRIDING: warning: '-fcomplex-arithmetic=improved' sets complex range to "improved"
89+
90+
! FAST-OVERRIDDEN: overriding the setting of "basic" that was implied by '-ffast-math' [-Woverriding-complex-range]
91+
! ARITH-FULL-OVERRIDDEN: overriding the setting of "full" that was implied by '-fcomplex-arithmetic=full' [-Woverriding-complex-range]
92+
! ARITH-IMPROVED-OVERRIDDEN: overriding the setting of "improved" that was implied by '-fcomplex-arithmetic=improved' [-Woverriding-complex-range]
93+
! ARITH-BASIC-OVERRIDDEN: overriding the setting of "basic" that was implied by '-fcomplex-arithmetic=basic' [-Woverriding-complex-range]
94+
1895
! RANGE-NOT: -complex-range=
1996
! FULL: -complex-range=full
2097
! IMPRVD: -complex-range=improved

0 commit comments

Comments
 (0)