https://github.com/zahiraam created https://github.com/llvm/llvm-project/pull/81514
None >From 13fd73932251843173cbbc31ca93905ca0469277 Mon Sep 17 00:00:00 2001 From: Ammarguellat <zahira.ammarguel...@intel.com> Date: Mon, 12 Feb 2024 10:58:19 -0800 Subject: [PATCH] [CLANG] Full support of complex multiplication and division. --- clang/docs/UsersManual.rst | 32 +-- clang/include/clang/Basic/LangOptions.h | 27 ++- clang/include/clang/Driver/Options.td | 25 +-- clang/lib/CodeGen/CGExprComplex.cpp | 31 ++- clang/lib/Driver/ToolChains/Clang.cpp | 87 ++++---- clang/lib/Parse/ParsePragma.cpp | 4 +- clang/test/CodeGen/cx-complex-range.c | 222 +++++++++++-------- clang/test/CodeGen/pragma-cx-limited-range.c | 179 +++++++++++++-- clang/test/Driver/range.c | 103 ++++++--- 9 files changed, 475 insertions(+), 235 deletions(-) diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 7391e4cf3a9aeb..9ea5f89ece7511 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1847,19 +1847,25 @@ floating point semantic models: precise (the default), strict, and fast. * ``16`` - Forces ``_Float16`` operations to be emitted without using excess precision arithmetic. -.. option:: -fcx-limited-range: - - This option enables the naive mathematical formulas for complex division and - multiplication with no NaN checking of results. The default is - ``-fno-cx-limited-range``, but this option is enabled by the ``-ffast-math`` - option. - -.. option:: -fcx-fortran-rules: - - This option enables the naive mathematical formulas for complex - multiplication and enables application of Smith's algorithm for complex - division. See SMITH, R. L. Algorithm 116: Complex division. Commun. - ACM 5, 8 (1962). The default is ``-fno-cx-fortran-rules``. +.. option:: -fcomplex-arithmetic=<value>: + + This option specifies the implementation for complex multiplication and division. + + Valid values are: ``limited``, ``smith``, ``full`` and ``extend``. + + * ``limited`` Implementation of complex division and multiplication using + algebraic formulas at source precision. Overflow and non-finites values + are not handled. + * ``smith`` Implementation of complex division using the Smith algorithm at + source precision. Smith's algorithm for complex division. + See SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 (1962). + Overflow is handled. + * ``full`` Implementation of complex division and multiplication using a + call to runtime library functions (generally the case, but the BE might + sometimes replace the library call if it knows enough about the potential + range of the inputs). Overflow and non-finite values are handled. + * ``extend`` Implementation of complex division using algebraic formulas at + higher precision. Overflow is handled. .. _floating-point-environment: diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 862952d336ef31..b8b96d06888291 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -396,7 +396,32 @@ class LangOptionsBase { IncompleteOnly = 3, }; - enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran, CX_None }; + /// Controls the various implementations for complex multiplication and + // division. + enum ComplexRangeKind { + /// Implementation of complex division and multiplication using a call to + /// runtime library functions (generally the case, but the BE might + /// sometimes replace the library call if it knows enough about the + /// potential range of the inputs). Overflow and non-finite values are + /// handled. + CX_Full, + + /// Implementation of complex division using the Smith algorithm at source + /// precision. Overflow is handled. + CX_Smith, + + /// Implementation of complex division using algebraic formulas at higher + /// precision. Overflow is handled. + CX_Extend, + + /// Implementation of complex division and multiplication using algebraic + /// formulas at source precision. Overflow and non-finites values are not + /// handled. + CX_Limited, + + /// No range rule is enabled. + CX_None + }; // Define simple language options (with no accessors). #define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 31e8571758bfce..848cc38188d86e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1012,28 +1012,15 @@ defm offload_uniform_block : BoolFOption<"offload-uniform-block", NegFlag<SetFalse, [], [ClangOption, CC1Option], "Don't assume">, BothFlags<[], [ClangOption], " that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)">>; -def fcx_limited_range : Joined<["-"], "fcx-limited-range">, - Group<f_Group>, Visibility<[ClangOption, CC1Option]>, - HelpText<"Basic algebraic expansions of complex arithmetic operations " - "involving are enabled.">; - -def fno_cx_limited_range : Joined<["-"], "fno-cx-limited-range">, - Group<f_Group>, Visibility<[ClangOption, CC1Option]>, - HelpText<"Basic algebraic expansions of complex arithmetic operations " - "involving are disabled.">; - -def fcx_fortran_rules : Joined<["-"], "fcx-fortran-rules">, - Group<f_Group>, Visibility<[ClangOption, CC1Option]>, - HelpText<"Range reduction is enabled for complex arithmetic operations.">; - -def fno_cx_fortran_rules : Joined<["-"], "fno-cx-fortran-rules">, - Group<f_Group>, Visibility<[ClangOption, CC1Option]>, - HelpText<"Range reduction is disabled for complex arithmetic operations.">; +def fcomplex_arithmetic_EQ : Joined<["-"], "fcomplex-arithmetic=">, Group<f_Group>, + Visibility<[ClangOption, CC1Option]>, + Values<"full,smith,extend,limited">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["CX_Full", "CX_Smith", "CX_Extend", "CX_Limited"]>; def complex_range_EQ : Joined<["-"], "complex-range=">, Group<f_Group>, Visibility<[CC1Option]>, - Values<"full,limited,fortran">, NormalizedValuesScope<"LangOptions">, - NormalizedValues<["CX_Full", "CX_Limited", "CX_Fortran"]>, + Values<"full,smith,extend,limited">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["CX_Full", "CX_Smith", "CX_Extend", "CX_Limited"]>, MarshallingInfoEnum<LangOpts<"ComplexRange">, "CX_Full">; // OpenCL-only Options diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 9ddf0e763f139b..e01be6e5fdd6ec 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -283,9 +283,23 @@ class ComplexExprEmitter ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, const BinOpInfo &Op); - QualType getPromotionType(QualType Ty) { + QualType getPromotionType(QualType Ty, bool IsDivOpCode = false) { if (auto *CT = Ty->getAs<ComplexType>()) { QualType ElementType = CT->getElementType(); + if (CGF.getLangOpts().getComplexRange() == + LangOptions::ComplexRangeKind::CX_Extend && + IsDivOpCode) { + if (ElementType->isFloatingType()) { + if (const auto *BT = dyn_cast<BuiltinType>(ElementType)) + switch (BT->getKind()) { + case BuiltinType::Kind::Float: + return CGF.getContext().getComplexType(CGF.getContext().DoubleTy); + default: + return CGF.getContext().getComplexType( + CGF.getContext().LongDoubleTy); + } + } + } if (ElementType.UseExcessPrecision(CGF.getContext())) return CGF.getContext().getComplexType(CGF.getContext().FloatTy); } @@ -296,11 +310,12 @@ class ComplexExprEmitter #define HANDLEBINOP(OP) \ ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \ - QualType promotionTy = getPromotionType(E->getType()); \ + QualType promotionTy = getPromotionType( \ + E->getType(), \ + (E->getOpcode() == BinaryOperatorKind::BO_Div) ? true : false); \ ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \ if (!promotionTy.isNull()) \ - result = \ - CGF.EmitUnPromotedValue(result, E->getType()); \ + result = CGF.EmitUnPromotedValue(result, E->getType()); \ return result; \ } @@ -790,7 +805,8 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { ResI = Builder.CreateFAdd(AD, BC, "mul_i"); if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited || - Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran) + Op.FPFeatures.getComplexRange() == LangOptions::CX_Smith || + Op.FPFeatures.getComplexRange() == LangOptions::CX_Extend) return ComplexPairTy(ResR, ResI); // Emit the test for the real part becoming NaN and create a branch to @@ -981,9 +997,10 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *OrigLHSi = LHSi; if (!LHSi) LHSi = llvm::Constant::getNullValue(RHSi->getType()); - if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran) + if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Smith) return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi); - else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited) + else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited || + Op.FPFeatures.getComplexRange() == LangOptions::CX_Extend) return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi); else if (!CGF.getLangOpts().FastMath || // '-ffast-math' is used in the command line but followed by an diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 942ebbc4106078..7f4cb46a44f4ca 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2687,45 +2687,42 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } } -static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) { - StringRef RangeStr = ""; +static std::string ComplexRangeKindToStr(LangOptions::ComplexRangeKind Range) { switch (Range) { + case LangOptions::ComplexRangeKind::CX_Full: + return "full"; + break; case LangOptions::ComplexRangeKind::CX_Limited: - return "-fcx-limited-range"; + return "limited"; break; - case LangOptions::ComplexRangeKind::CX_Fortran: - return "-fcx-fortran-rules"; + case LangOptions::ComplexRangeKind::CX_Smith: + return "smith"; break; - default: - return RangeStr; + case LangOptions::ComplexRangeKind::CX_Extend: + return "extend"; break; + default: + return ""; } } +static std::string ComplexArithmeticStr(LangOptions::ComplexRangeKind Range) { + return "-fcomplex-arithmetic=" + ComplexRangeKindToStr(Range); +} + static void EmitComplexRangeDiag(const Driver &D, LangOptions::ComplexRangeKind Range1, LangOptions::ComplexRangeKind Range2) { if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None) D.Diag(clang::diag::warn_drv_overriding_option) - << EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2); + << ComplexArithmeticStr(Range1) << ComplexArithmeticStr(Range2); } static std::string RenderComplexRangeOption(LangOptions::ComplexRangeKind Range) { - std::string ComplexRangeStr = "-complex-range="; - switch (Range) { - case LangOptions::ComplexRangeKind::CX_Full: - ComplexRangeStr += "full"; - break; - case LangOptions::ComplexRangeKind::CX_Limited: - ComplexRangeStr += "limited"; - break; - case LangOptions::ComplexRangeKind::CX_Fortran: - ComplexRangeStr += "fortran"; - break; - default: - assert(0 && "Unexpected range option"); - } + std::string ComplexRangeStr = ComplexRangeKindToStr(Range); + if (!ComplexRangeStr.empty()) + return "-complex-range=" + ComplexRangeStr; return ComplexRangeStr; } @@ -2789,24 +2786,24 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, switch (optID) { default: break; - case options::OPT_fcx_limited_range: { - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Limited); - Range = LangOptions::ComplexRangeKind::CX_Limited; - break; - } - case options::OPT_fno_cx_limited_range: - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full); - Range = LangOptions::ComplexRangeKind::CX_Full; - break; - case options::OPT_fcx_fortran_rules: { - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Fortran); - Range = LangOptions::ComplexRangeKind::CX_Fortran; + case options::OPT_fcomplex_arithmetic_EQ: { + LangOptions::ComplexRangeKind RangeVal; + StringRef Val = A->getValue(); + if (Val.equals("full")) + RangeVal = LangOptions::ComplexRangeKind::CX_Full; + else if (Val.equals("smith")) + RangeVal = LangOptions::ComplexRangeKind::CX_Smith; + else if (Val.equals("extend")) + RangeVal = LangOptions::ComplexRangeKind::CX_Extend; + else if (Val.equals("limited")) + RangeVal = LangOptions::ComplexRangeKind::CX_Limited; + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << LangOptions::ComplexRangeKind::CX_None; + EmitComplexRangeDiag(D, Range, RangeVal); + Range = RangeVal; break; } - case options::OPT_fno_cx_fortran_rules: - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full); - Range = LangOptions::ComplexRangeKind::CX_Full; - break; case options::OPT_ffp_model_EQ: { // If -ffp-model= is seen, reset to fno-fast-math HonorINFs = true; @@ -3235,16 +3232,12 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, if (Range != LangOptions::ComplexRangeKind::CX_None) ComplexRangeStr = RenderComplexRangeOption(Range); - if (!ComplexRangeStr.empty()) + if (!ComplexRangeStr.empty()) { CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr)); - if (Args.hasArg(options::OPT_fcx_limited_range)) - CmdArgs.push_back("-fcx-limited-range"); - if (Args.hasArg(options::OPT_fcx_fortran_rules)) - CmdArgs.push_back("-fcx-fortran-rules"); - if (Args.hasArg(options::OPT_fno_cx_limited_range)) - CmdArgs.push_back("-fno-cx-limited-range"); - if (Args.hasArg(options::OPT_fno_cx_fortran_rules)) - CmdArgs.push_back("-fno-cx-fortran-rules"); + if (Args.hasArg(options::OPT_fcomplex_arithmetic_EQ)) + CmdArgs.push_back(Args.MakeArgString("-fcomplex-arithmetic=" + + ComplexRangeKindToStr(Range))); + } } static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 730ac1a0fee5cc..dc938e4e4ced1f 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -916,8 +916,8 @@ void Parser::HandlePragmaCXLimitedRange() { break; case tok::OOS_DEFAULT: // According to ISO C99 standard chapter 7.3.4, the default value - // for the pragma is ``off'. -fcx-limited-range and -fcx-fortran-rules - // control the default value of these pragmas. + // for the pragma is ``off'. -fcomplex-arithmetic controls the default value + // of these pragmas. Range = getLangOpts().getComplexRange(); break; } diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c index 2d8507c710f202..f78fda61a9d1ce 100644 --- a/clang/test/CodeGen/cx-complex-range.c +++ b/clang/test/CodeGen/cx-complex-range.c @@ -5,120 +5,156 @@ // RUN: -complex-range=limited -o - | FileCheck %s --check-prefix=LMTD // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL +// RUN: -complex-range=smith -o - | FileCheck %s --check-prefix=SMITH // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=fortran -o - | FileCheck %s --check-prefix=FRTRN +// RUN: -complex-range=extend -o - | FileCheck %s --check-prefix=EXTND + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=full -o - | FileCheck %s --check-prefix=FULL // Fast math // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ // RUN: -ffast-math -complex-range=limited -emit-llvm -o - %s \ -// RUN: | FileCheck %s --check-prefix=LMTD-FAST +// RUN: | FileCheck %s --check-prefix=LMTD // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ // RUN: -ffast-math -complex-range=full -emit-llvm -o - %s \ // RUN: | FileCheck %s --check-prefix=FULL -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-fortran-rules -o - | FileCheck %s --check-prefix=FULL - -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fcx-limited-range -fno-cx-limited-range -o - \ -// RUN: | FileCheck %s --check-prefix=FULL - -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-limited-range -fcx-limited-range -o - \ -// RUN: | FileCheck %s --check-prefix=FULL +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=smith -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=SMITH -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-fortran-rules -fcx-fortran-rules -o - \ -// RUN: | FileCheck %s --check-prefix=FULL +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=extend -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=EXTND _Complex float div(_Complex float a, _Complex float b) { // LABEL: define {{.*}} @div( - // FULL: call {{.*}} @__divsc3 - - // LMTD: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fadd float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fadd float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fsub float - // LMTD-NEXT: fdiv float - // LMTD-NEXT: fdiv float - - // FRTRN: call {{.*}}float @llvm.fabs.f32(float {{.*}}) - // FRTRN-NEXT: call {{.*}}float @llvm.fabs.f32(float {{.*}}) - // FRTRN-NEXT: fcmp {{.*}}ugt float - // FRTRN-NEXT: br i1 {{.*}}, label - // FRTRN: abs_rhsr_greater_or_equal_abs_rhsi: - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fsub {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: br label - // FRTRN: abs_rhsr_less_than_abs_rhsi: - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fsub {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: br label - // FRTRN: complex_div: - // FRTRN-NEXT: phi {{.*}}float - // FRTRN-NEXT: phi {{.*}}float - - // LMTD-FAST: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fadd {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fadd {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fsub {{.*}} float - // LMTD-FAST-NEXT: fdiv {{.*}} float - // LMTD-FAST-NEXT: fdiv {{.*}} float + // FULL: call {{.*}} @__divsc3 + // + // LMTD: fmul{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fadd{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fadd{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fsub{{.*}}float + // LMTD-NEXT: fdiv{{.*}}float + // LMTD-NEXT: fdiv{{.*}}float + // + // SMITH: call{{.*}}float @llvm.fabs.f32(float {{.*}}) + // SMITH-NEXT: call{{.*}}float @llvm.fabs.f32(float {{.*}}) + // SMITH-NEXT: fcmp{{.*}}ugt float {{.*}}, {{.*}} + // SMITH-NEXT: br i1 {{.*}}, label + // SMITH: abs_rhsr_greater_or_equal_abs_rhsi: + // SMITH-NEXT: fdiv{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fadd{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fadd{{.*}}float + // SMITH-NEXT: fdiv{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fsub{{.*}}float + // SMITH-NEXT: fdiv{{.*}}float + // SMITH-NEXT: br label + // SMITH: abs_rhsr_less_than_abs_rhsi: + // SMITH-NEXT: fdiv{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fadd{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fadd{{.*}}float + // SMITH-NEXT: fdiv{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fsub{{.*}}float + // SMITH-NEXT: fdiv{{.*}}float + // + // EXTND: load float, ptr {{.*}} + // EXTND: fpext float {{.*}} to double + // EXTND-NEXT: fpext float {{.*}} to double + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // EXTND-NEXT: load float, ptr {{.*}} + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // EXTND-NEXT: load float, ptr {{.*}} + // EXTND-NEXT: fpext float {{.*}} to double + // EXTND-NEXT: fpext float {{.*}} to double + // EXTND-NEXT: fmul{{.*}}double + // EXTND-NEXT: fmul{{.*}}double + // EXTND-NEXT: fadd{{.*}}double + // EXTND-NEXT: fmul{{.*}}double + // EXTND-NEXT: fmul{{.*}}double + // EXTND-NEXT: fadd{{.*}}double + // EXTND-NEXT: fmul{{.*}}double + // EXTND-NEXT: fmul{{.*}}double + // EXTND-NEXT: fsub{{.*}}double + // EXTND-NEXT: fdiv{{.*}}double + // EXTND-NEXT: fdiv{{.*}}double + // EXTND-NEXT: fptrunc double {{.*}} to float + // EXTND-NEXT: fptrunc double {{.*}} to float return a / b; } _Complex float mul(_Complex float a, _Complex float b) { // LABEL: define {{.*}} @mul( - // FULL: call {{.*}} @__mulsc3 - - // LMTD: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fsub float - // LMTD-NEXT: fadd float - - // FRTRN: fmul {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fsub {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - - // LMTD-FAST: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fsub {{.*}} float - // LMTD-FAST-NEXT: fadd {{.*}} float + // FULL: call {{.*}} @__mulsc3 + // + // LMTD: alloca { float, float } + // LMTD-NEXT: alloca { float, float } + // LMTD-NEXT: alloca { float, float } + // LMTD: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // LMTD-NEXT: load float, ptr {{.*}} + // LMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // LMTD-NEXT: load float, ptr {{.*}} + // LMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // LMTD-NEXT: load float, ptr {{.*}} + // LMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // LMTD-NEXT: load float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fmul{{.*}}float + // LMTD-NEXT: fsub{{.*}}float + // LMTD-NEXT: fadd{{.*}}float + // + // SMITH: alloca { float, float } + // SMITH-NEXT: alloca { float, float } + // SMITH-NEXT: alloca { float, float } + // SMITH: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // SMITH-NEXT: load float, ptr {{.*}} + // SMITH-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // SMITH-NEXT: load float, ptr {{.*}} + // SMITH-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // SMITH-NEXT: load float, ptr {{.*}} + // SMITH-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // SMITH-NEXT: load float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fmul{{.*}}float + // SMITH-NEXT: fsub{{.*}}float + // SMITH-NEXT: fadd{{.*}}float + // + // EXTND: alloca { float, float } + // EXTND-NEXT: alloca { float, float } + // EXTND-NEXT: alloca { float, float } + // EXTND: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // EXTND-NEXT: load float, ptr + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // EXTND-NEXT: load float, ptr {{.*}} + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // EXTND-NEXT: load float, ptr {{.*}} + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // EXTND-NEXT: load{{.*}}float + // EXTND-NEXT: fmul{{.*}}float + // EXTND-NEXT: fmul{{.*}}float + // EXTND-NEXT: fmul{{.*}}float + // EXTND-NEXT: fmul{{.*}}float + // EXTND-NEXT: fsub{{.*}}float + // EXTND-NEXT: fadd{{.*}}float return a * b; } diff --git a/clang/test/CodeGen/pragma-cx-limited-range.c b/clang/test/CodeGen/pragma-cx-limited-range.c index 926da8afbee558..bb0576dd51b98d 100644 --- a/clang/test/CodeGen/pragma-cx-limited-range.c +++ b/clang/test/CodeGen/pragma-cx-limited-range.c @@ -5,17 +5,18 @@ // RUN: -complex-range=limited -o - | FileCheck --check-prefix=LMTD %s // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL +// RUN: -complex-range=smith -o - | FileCheck --check-prefix=SMITH %s // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=fortran -o - | FileCheck --check-prefix=FRTRN %s +// RUN: -complex-range=extend -o - | FileCheck --check-prefix=EXTND %s // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-fortran-rules -o - | FileCheck --check-prefix=FULL %s +// RUN: -complex-range=full -o - | FileCheck --check-prefix=FULL %s _Complex float pragma_on_mul(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE ON // LABEL: define {{.*}} @pragma_on_mul( + // FULL: fmul float // FULL-NEXT: fmul float // FULL-NEXT: fmul float @@ -30,12 +31,19 @@ _Complex float pragma_on_mul(_Complex float a, _Complex float b) { // LMTD-NEXT: fsub float // LMTD-NEXT: fadd float - // FRTRN: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fsub float - // FRTRN-NEXT: fadd float + // SMITH: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fsub float + // SMITH-NEXT: fadd float + + // EXTND: fmul float + // EXTND-NEXT: fmul float + // EXTND-NEXT: fmul float + // EXTND-NEXT: fmul float + // EXTND-NEXT: fsub float + // EXTND-NEXT: fadd float return a * b; } @@ -43,11 +51,14 @@ _Complex float pragma_on_mul(_Complex float a, _Complex float b) { _Complex float pragma_off_mul(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE OFF // LABEL: define {{.*}} @pragma_off_mul( + // FULL: call {{.*}} @__mulsc3 // LMTD: call {{.*}} @__mulsc3 - // FRTRN: call {{.*}} @__mulsc3 + // SMITH: call {{.*}} @__mulsc3 + + // EXTND: call {{.*}} @__mulsc3 return a * b; } @@ -55,6 +66,7 @@ _Complex float pragma_off_mul(_Complex float a, _Complex float b) { _Complex float pragma_on_div(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE ON // LABEL: define {{.*}} @pragma_on_div( + // FULL: fmul float // FULL-NEXT: fmul float // FULL-NEXT: fadd float @@ -79,17 +91,33 @@ _Complex float pragma_on_div(_Complex float a, _Complex float b) { // LMTD-NEXT: fdiv float // LMTD-NEXT: fdiv float - // FRTRN: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fadd float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fadd float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fsub float - // FRTRN-NEXT: fdiv float - // FRTRN-NEXT: fdiv float + // SMITH: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fadd float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fadd float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fsub float + // SMITH-NEXT: fdiv float + // SMITH-NEXT: fdiv float + + // EXTND: fpext float {{.*}} to double + // EXTND: fpext float {{.*}} to double + // EXTND: fmul double + // EXTND: fmul double + // EXTND: fadd double + // EXTND: fmul double + // EXTND: fmul double + // EXTND: fadd double + // EXTND: fmul double + // EXTND: fmul double + // EXTND: fsub double + // EXTND: fdiv double + // EXTND: fdiv double + // EXTND: fptrunc double + // EXTND: fptrunc double return a / b; } @@ -97,11 +125,118 @@ _Complex float pragma_on_div(_Complex float a, _Complex float b) { _Complex float pragma_off_div(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE OFF // LABEL: define {{.*}} @pragma_off_div( + // FULL: call {{.*}} @__divsc3 // LMTD: call {{.*}} @__divsc3 - // FRTRN: call {{.*}} @__divsc3 + // SMITH: call {{.*}} @__divsc3 + + // EXTND: call {{.*}} @__divdc3 + + return a / b; +} + +_Complex float pragma_default_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE DEFAULT + // LABEL: define {{.*}} @pragma_on_mul( + + // FULL: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fsub float + // FULL-NEXT: fadd float + + // LMTD: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fsub float + // LMTD-NEXT: fadd float + + // SMITH: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fsub float + // SMITH-NEXT: fadd float + + // EXTND: fmul float + // EXTND-NEXT: fmul float + // EXTND-NEXT: fmul float + // EXTND-NEXT: fmul float + // EXTND-NEXT: fsub float + // EXTND-NEXT: fadd float + + return a * b; +} +_Complex float pragma_default_div(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE DEFAULT + // LABEL: define {{.*}} @pragma_on_divx( + + // FULL: call {{.*}} @__divsc3 + + // LMTD: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fadd float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fadd float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fsub float + // LMTD-NEXT: fdiv float + // LMTD-NEXT: fdiv float + + // SMITH: call{{.*}}float @llvm.fabs.f32(float {{.*}}) + // SMITH-NEXT: call{{.*}}float @llvm.fabs.f32(float {{.*}}) + // SMITH-NEXT: fcmp{{.*}}ugt float {{.*}}, {{.*}} + // SMITH-NEXT: br i1 {{.*}}, label + // SMITH: abs_rhsr_greater_or_equal_abs_rhsi: + // SMITH-NEXT: fdiv float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fadd float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fadd float + // SMITH-NEXT: fdiv float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fsub float + // SMITH-NEXT: fdiv float + // SMITH-NEXT: br label + // SMITH: abs_rhsr_less_than_abs_rhsi: + // SMITH-NEXT: fdiv float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fadd float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fadd float + // SMITH-NEXT: fdiv float + // SMITH-NEXT: fmul float + // SMITH-NEXT: fsub float + // SMITH-NEXT: fdiv float + + // EXTND: load float, ptr {{.*}} + // EXTND: fpext float {{.*}} to double + // EXTND-NEXT: fpext float {{.*}} to double + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // EXTND-NEXT: load float, ptr {{.*}} + // EXTND-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // EXTND-NEXT: load float, ptr {{.*}} + // EXTND-NEXT: fpext float {{.*}} to double + // EXTND-NEXT: fpext float {{.*}} to double + // EXTND-NEXT: fmul double + // EXTND-NEXT: fmul double + // EXTND-NEXT: fadd double + // EXTND-NEXT: fmul double + // EXTND-NEXT: fmul double + // EXTND-NEXT: fadd double + // EXTND-NEXT: fmul double + // EXTND-NEXT: fmul double + // EXTND-NEXT: fsub double + // EXTND-NEXT: fdiv double + // EXTND-NEXT: fdiv double + // EXTND-NEXT: fptrunc double {{.*}} to float + // EXTND-NEXT: fptrunc double {{.*}} to float return a / b; } diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c index 49116df2f4480e..434e9407664ce7 100644 --- a/clang/test/Driver/range.c +++ b/clang/test/Driver/range.c @@ -1,52 +1,93 @@ // Test range options for complex multiplication and division. -// RUN: %clang -### -target x86_64 -fcx-limited-range -c %s 2>&1 \ +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=LMTD %s -// RUN: %clang -### -target x86_64 -fno-cx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=SMITH %s -// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \ -// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=EXTND %s -// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=FRTRN %s - -// RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \ -// RUN: | FileCheck %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s -// RUN: %clang -### -target x86_64 -fcx-limited-range \ -// RUN: -fcx-fortran-rules -c %s 2>&1 \ +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited \ +// RUN: -fcomplex-arithmetic=smith -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=WARN1 %s -// RUN: %clang -### -target x86_64 -fcx-fortran-rules \ -// RUN: -fcx-limited-range -c %s 2>&1 \ +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited \ +// RUN: -fcomplex-arithmetic=full -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=WARN2 %s -// RUN: %clang -### -target x86_64 -ffast-math -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited \ +// RUN: -fcomplex-arithmetic=extend -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN3 %s -// RUN: %clang -### -target x86_64 -ffast-math -fcx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith \ +// RUN: -fcomplex-arithmetic=limited -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN4 %s -// RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith \ +// RUN: -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN5 %s -// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=FULL %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith \ +// RUN: -fcomplex-arithmetic=extend -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN6 %s + + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend \ +// RUN: -fcomplex-arithmetic=limited -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN7 %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend \ +// RUN: -fcomplex-arithmetic=smith -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN8 %s -// RUN: %clang -### -Werror -target x86_64 -fcx-limited-range -c %s 2>&1 \ +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend \ +// RUN: -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN9 %s + + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -fcomplex-arithmetic=limited -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN10 %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -fcomplex-arithmetic=smith -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN11 %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -fcomplex-arithmetic=extend -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN12 %s + +// RUN: %clang -### -target x86_64 -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LMTD %s + +// RUN: %clang -### -target x86_64 -ffast-math -fcomplex-arithmetic=limited -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=LMTD %s -// RUN: %clang -### -Werror -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=FRTRN %s +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LMTD %s // LMTD: -complex-range=limited // FULL: -complex-range=full -// LMTD-NOT: -complex-range=fortran +// EXTND: -complex-range=extend +// LMTD-NOT: -complex-range=smith // CHECK-NOT: -complex-range=limited -// FRTRN: -complex-range=fortran -// FRTRN-NOT: -complex-range=limited -// CHECK-NOT: -complex-range=fortran -// WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option] -// WARN2: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option] +// SMITH: -complex-range=smith +// SMITH-NOT: -complex-range=limited +// CHECK-NOT: -complex-range=smith +// WARN1: warning: overriding '-fcomplex-arithmetic=limited' option with '-fcomplex-arithmetic=smith' [-Woverriding-option] +// WARN2: warning: overriding '-fcomplex-arithmetic=limited' option with '-fcomplex-arithmetic=full' [-Woverriding-option] +// WARN3: warning: overriding '-fcomplex-arithmetic=limited' option with '-fcomplex-arithmetic=extend' [-Woverriding-option] +// WARN4: warning: overriding '-fcomplex-arithmetic=smith' option with '-fcomplex-arithmetic=limited' [-Woverriding-option] +// WARN5: warning: overriding '-fcomplex-arithmetic=smith' option with '-fcomplex-arithmetic=full' [-Woverriding-option] +// WARN6: warning: overriding '-fcomplex-arithmetic=smith' option with '-fcomplex-arithmetic=extend' [-Woverriding-option] +// WARN7: warning: overriding '-fcomplex-arithmetic=extend' option with '-fcomplex-arithmetic=limited' [-Woverriding-option] +// WARN8: warning: overriding '-fcomplex-arithmetic=extend' option with '-fcomplex-arithmetic=smith' [-Woverriding-option] +// WARN9: warning: overriding '-fcomplex-arithmetic=extend' option with '-fcomplex-arithmetic=full' [-Woverriding-option] +// WARN10: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=limited' [-Woverriding-option] +// WARN11: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=smith' [-Woverriding-option] +// WARN12: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=extend' [-Woverriding-option] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits