[clang] [CLANG] Full support of complex multiplication and division. (PR #81514)

Zahira Ammarguellat via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 20 13:25:57 PST 2024


https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/81514

>From 13fd73932251843173cbbc31ca93905ca0469277 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 12 Feb 2024 10:58:19 -0800
Subject: [PATCH 1/2] [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]

>From eb9a35c4b3c42b0caf3ddddce4759dd4b1b640a8 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Tue, 20 Feb 2024 13:24:52 -0800
Subject: [PATCH 2/2] Changed the names of the values for the option and added
 some code to deal with the type promotion.

---
 clang/docs/UsersManual.rst                   |  26 +-
 clang/include/clang/Basic/LangOptions.h      |  41 ++-
 clang/include/clang/Driver/Options.td        |   8 +-
 clang/lib/CodeGen/CGExprComplex.cpp          |  65 ++--
 clang/lib/Driver/ToolChains/Clang.cpp        |  26 +-
 clang/lib/Parse/ParsePragma.cpp              |   2 +-
 clang/test/CodeGen/cx-complex-range.c        | 236 +++++++--------
 clang/test/CodeGen/pragma-cx-limited-range.c | 296 +++++++++----------
 clang/test/Driver/range.c                    |  96 +++---
 9 files changed, 419 insertions(+), 377 deletions(-)

diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 9ea5f89ece7511..732eaf4f2b14e4 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -1851,21 +1851,29 @@ floating point semantic models: precise (the default), strict, and fast.
 
    This option specifies the implementation for complex multiplication and division.
 
-   Valid values are: ``limited``, ``smith``, ``full`` and ``extend``.
+   Valid values are: ``basic``, ``improved``, ``full`` and ``promoted``.
 
-   * ``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
+   * ``basic`` Implementation of complex division and multiplication using
+     algebraic formulas at source precision. No special handling to avoid
+     overflow. NaN and infinite and  values are not handled.
+   * ``improved`` 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.
+     This value offers improved handling for overflow in intermediate calculations,
+     but overflow may occur. NaN and infinite and  values are not handled in some
+     cases.
    * ``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.
+     range of the inputs). Overflow and non-finite values are handled by the
+     library implementation.
+   * ``promoted`` Implementation of complex division using algebraic formulas at
+     higher precision. Overflow is handled. Non-finite values are handled in some
+     cases. If the target hardware does not have native support for a higher precision
+     data type, an implementation for the complex operation will be used to provide
+     improved guards against intermediate overflow, but overflow and underflow may
+     still occur in some cases. NaN and infinite and  values are not handled.
+     This is the default value.
 
 .. _floating-point-environment:
 
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index b8b96d06888291..9eaa59b2d4e7f1 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -400,24 +400,33 @@ class LangOptionsBase {
   // 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.
+   ///  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 by the library implementation.
     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,
+    /// 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).
+    /// This value offers improved handling for overflow in intermediate calculations,
+    /// but overflow may occur. NaN and infinite and  values are not handled in some
+    // cases.
+    CX_Improved,
+
+    /// Implementation of complex division using algebraic formulas at
+    /// higher precision. Overflow is handled. Non-finite values are handled in
+    /// some cases. If the target hardware does not have native support for a
+    /// higher precision data type, an implementation for the complex operation
+    /// will be used to provide improved guards against intermediate overflow,
+    /// but overflow and underflow may still occur in some cases. NaN and
+    /// infinite and  values are not handled. This is the default value.
+    CX_Promoted,
+
+    /// Implementation of complex division and multiplication using
+    /// algebraic formulas at source precision.No special handling to avoid
+    /// overflow.NaN and infinite and values are not handled.
+    CX_Basic,
 
     /// No range rule is enabled.
     CX_None
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 848cc38188d86e..5b791c43e678a6 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1014,13 +1014,13 @@ defm offload_uniform_block : BoolFOption<"offload-uniform-block",
 
 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"]>;
+  Values<"full,improved,promoted,basic">, NormalizedValuesScope<"LangOptions">,
+  NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>;
 
 def complex_range_EQ : Joined<["-"], "complex-range=">, Group<f_Group>,
   Visibility<[CC1Option]>,
-  Values<"full,smith,extend,limited">, NormalizedValuesScope<"LangOptions">,
-  NormalizedValues<["CX_Full", "CX_Smith", "CX_Extend", "CX_Limited"]>,
+  Values<"full,improved,promoted,basic">, NormalizedValuesScope<"LangOptions">,
+  NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>,
   MarshallingInfoEnum<LangOpts<"ComplexRange">, "CX_Full">;
 
 // OpenCL-only Options
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index e01be6e5fdd6ec..2008265f1f6fd9 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -283,23 +283,48 @@ class ComplexExprEmitter
   ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName,
                                         const BinOpInfo &Op);
 
+  QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType,
+                                                   bool IsDivOpCode) {
+    const TargetInfo &TI = CGF.getContext().getTargetInfo();
+    if (const auto *BT = dyn_cast<BuiltinType>(ElementType)) {
+      switch (BT->getKind()) {
+      case BuiltinType::Kind::Float16:
+      case BuiltinType::Kind::BFloat16: {
+        return CGF.getContext().getComplexType(CGF.getContext().FloatTy);
+      }
+      case BuiltinType::Kind::Float:
+        return CGF.getContext().getComplexType(CGF.getContext().DoubleTy);
+      case BuiltinType::Kind::Double:
+        if (TI.hasLongDoubleType()) {
+          return CGF.getContext().getComplexType(CGF.getContext().LongDoubleTy);
+        } else {
+          return QualType();
+        }
+      case BuiltinType::Kind::LongDouble:
+        if (TI.getTriple().isOSLinux()) {
+          if (TI.hasFloat128Type() && !TI.hasLongDoubleType())
+            return CGF.getContext().getComplexType(CGF.getContext().Float128Ty);
+          else
+            return CGF.getContext().getComplexType(
+                CGF.getContext().LongDoubleTy);
+        }
+        if (TI.getTriple().isOSWindows())
+          return CGF.getContext().getComplexType(CGF.getContext().LongDoubleTy);
+      default:
+        return QualType();
+      }
+    }
+    return QualType();
+  }
+
   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 (IsDivOpCode && ElementType->isFloatingType() &&
+          CGF.getLangOpts().getComplexRange() ==
+              LangOptions::ComplexRangeKind::CX_Promoted)
+        return HigherPrecisionTypeForComplexArithmetic(ElementType,
+                                                       IsDivOpCode);
       if (ElementType.UseExcessPrecision(CGF.getContext()))
         return CGF.getContext().getComplexType(CGF.getContext().FloatTy);
     }
@@ -804,9 +829,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
       ResR = Builder.CreateFSub(AC, BD, "mul_r");
       ResI = Builder.CreateFAdd(AD, BC, "mul_i");
 
-      if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited ||
-          Op.FPFeatures.getComplexRange() == LangOptions::CX_Smith ||
-          Op.FPFeatures.getComplexRange() == LangOptions::CX_Extend)
+      if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
+          Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
+          Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
         return ComplexPairTy(ResR, ResI);
 
       // Emit the test for the real part becoming NaN and create a branch to
@@ -997,10 +1022,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_Smith)
+    if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved)
       return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
-    else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited ||
-             Op.FPFeatures.getComplexRange() == LangOptions::CX_Extend)
+    else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
+             Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
       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 7f4cb46a44f4ca..54bf4d48d08df7 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2692,14 +2692,14 @@ static std::string ComplexRangeKindToStr(LangOptions::ComplexRangeKind Range) {
   case LangOptions::ComplexRangeKind::CX_Full:
     return "full";
     break;
-  case LangOptions::ComplexRangeKind::CX_Limited:
-    return "limited";
+  case LangOptions::ComplexRangeKind::CX_Basic:
+    return "basic";
     break;
-  case LangOptions::ComplexRangeKind::CX_Smith:
-    return "smith";
+  case LangOptions::ComplexRangeKind::CX_Improved:
+    return "improved";
     break;
-  case LangOptions::ComplexRangeKind::CX_Extend:
-    return "extend";
+  case LangOptions::ComplexRangeKind::CX_Promoted:
+    return "promoted";
     break;
   default:
     return "";
@@ -2791,12 +2791,12 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
       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 if (Val.equals("improved"))
+        RangeVal = LangOptions::ComplexRangeKind::CX_Improved;
+      else if (Val.equals("promoted"))
+        RangeVal = LangOptions::ComplexRangeKind::CX_Promoted;
+      else if (Val.equals("basic"))
+        RangeVal = LangOptions::ComplexRangeKind::CX_Basic;
       else
         D.Diag(diag::err_drv_unsupported_option_argument)
             << A->getSpelling() << LangOptions::ComplexRangeKind::CX_None;
@@ -3073,7 +3073,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
       SeenUnsafeMathModeOption = true;
       // ffast-math enables fortran rules for complex multiplication and
       // division.
-      Range = LangOptions::ComplexRangeKind::CX_Limited;
+      Range = LangOptions::ComplexRangeKind::CX_Basic;
       break;
     }
     case options::OPT_fno_fast_math:
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index dc938e4e4ced1f..87894ef47f8cb6 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -909,7 +909,7 @@ void Parser::HandlePragmaCXLimitedRange() {
   LangOptions::ComplexRangeKind Range;
   switch (OOS) {
   case tok::OOS_ON:
-    Range = LangOptions::CX_Limited;
+    Range = LangOptions::CX_Basic;
     break;
   case tok::OOS_OFF:
     Range = LangOptions::CX_Full;
diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c
index f78fda61a9d1ce..8b467402b22770 100644
--- a/clang/test/CodeGen/cx-complex-range.c
+++ b/clang/test/CodeGen/cx-complex-range.c
@@ -2,98 +2,98 @@
 // RUN: -o - | FileCheck %s --check-prefix=FULL
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
-// RUN: -complex-range=limited -o - | FileCheck %s --check-prefix=LMTD
+// RUN: -complex-range=basic -o - | FileCheck %s --check-prefix=BASIC
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
-// RUN: -complex-range=smith -o - | FileCheck %s --check-prefix=SMITH
+// RUN: -complex-range=improved -o - | FileCheck %s --check-prefix=IMPRVD
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
-// RUN: -complex-range=extend -o - | FileCheck %s --check-prefix=EXTND
+// RUN: -complex-range=promoted -o - | FileCheck %s --check-prefix=PRMTD
 
 // 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
+// RUN: -ffast-math -complex-range=basic -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=BASIC
 
 // 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 -triple x86_64-unknown-linux-gnu \
-// RUN: -ffast-math -complex-range=smith -emit-llvm -o - %s \
-// RUN: | FileCheck %s --check-prefix=SMITH
+// RUN: -ffast-math -complex-range=improved -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=IMPRVD
 
 // 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
+// RUN: -ffast-math -complex-range=promoted -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=PRMTD
 
 _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
+  // BASIC: fmul{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fadd{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fadd{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fsub{{.*}}float
+  // BASIC-NEXT: fdiv{{.*}}float
+  // BASIC-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
+  // IMPRVD: call{{.*}}float @llvm.fabs.f32(float {{.*}})
+  // IMPRVD-NEXT: call{{.*}}float @llvm.fabs.f32(float {{.*}})
+  // IMPRVD-NEXT: fcmp{{.*}}ugt float {{.*}}, {{.*}}
+  // IMPRVD-NEXT:   br i1 {{.*}}, label
+  // IMPRVD:  abs_rhsr_greater_or_equal_abs_rhsi:
+  // IMPRVD-NEXT: fdiv{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fadd{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fadd{{.*}}float
+  // IMPRVD-NEXT: fdiv{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fsub{{.*}}float
+  // IMPRVD-NEXT: fdiv{{.*}}float
+  // IMPRVD-NEXT: br label
+  // IMPRVD: abs_rhsr_less_than_abs_rhsi:
+  // IMPRVD-NEXT: fdiv{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fadd{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fadd{{.*}}float
+  // IMPRVD-NEXT: fdiv{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fsub{{.*}}float
+  // IMPRVD-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
+  // PRMTD: load float, ptr {{.*}}
+  // PRMTD: fpext float {{.*}} to double
+  // PRMTD-NEXT: fpext float {{.*}} to double
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // PRMTD-NEXT: load float, ptr {{.*}}
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // PRMTD-NEXT: load float, ptr {{.*}}
+  // PRMTD-NEXT: fpext float {{.*}} to double
+  // PRMTD-NEXT: fpext float {{.*}} to double
+  // PRMTD-NEXT: fmul{{.*}}double
+  // PRMTD-NEXT: fmul{{.*}}double
+  // PRMTD-NEXT: fadd{{.*}}double
+  // PRMTD-NEXT: fmul{{.*}}double
+  // PRMTD-NEXT: fmul{{.*}}double
+  // PRMTD-NEXT: fadd{{.*}}double
+  // PRMTD-NEXT: fmul{{.*}}double
+  // PRMTD-NEXT: fmul{{.*}}double
+  // PRMTD-NEXT: fsub{{.*}}double
+  // PRMTD-NEXT: fdiv{{.*}}double
+  // PRMTD-NEXT: fdiv{{.*}}double
+  // PRMTD-NEXT: fptrunc double {{.*}} to float
+  // PRMTD-NEXT: fptrunc double {{.*}} to float
 
   return a / b;
 }
@@ -102,59 +102,59 @@ _Complex float mul(_Complex float a, _Complex float b) {
   // LABEL: define {{.*}} @mul(
   // 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
+  // BASIC: alloca { float, float }
+  // BASIC-NEXT: alloca { float, float }
+  // BASIC-NEXT: alloca { float, float }
+  // BASIC: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // BASIC-NEXT: load float, ptr {{.*}}
+  // BASIC-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // BASIC-NEXT: load float, ptr {{.*}}
+  // BASIC-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // BASIC-NEXT: load float, ptr {{.*}}
+  // BASIC-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // BASIC-NEXT: load float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fmul{{.*}}float
+  // BASIC-NEXT: fsub{{.*}}float
+  // BASIC-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
+  // IMPRVD: alloca { float, float }
+  // IMPRVD-NEXT: alloca { float, float }
+  // IMPRVD-NEXT: alloca { float, float }
+  // IMPRVD: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // IMPRVD-NEXT: load float, ptr {{.*}}
+  // IMPRVD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // IMPRVD-NEXT: load float, ptr {{.*}}
+  // IMPRVD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // IMPRVD-NEXT: load float, ptr {{.*}}
+  // IMPRVD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // IMPRVD-NEXT: load float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fmul{{.*}}float
+  // IMPRVD-NEXT: fsub{{.*}}float
+  // IMPRVD-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
+  // PRMTD: alloca { float, float }
+  // PRMTD-NEXT: alloca { float, float }
+  // PRMTD-NEXT: alloca { float, float }
+  // PRMTD: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // PRMTD-NEXT: load float, ptr
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // PRMTD-NEXT: load float, ptr {{.*}}
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // PRMTD-NEXT: load float, ptr {{.*}}
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // PRMTD-NEXT: load{{.*}}float
+  // PRMTD-NEXT: fmul{{.*}}float
+  // PRMTD-NEXT: fmul{{.*}}float
+  // PRMTD-NEXT: fmul{{.*}}float
+  // PRMTD-NEXT: fmul{{.*}}float
+  // PRMTD-NEXT: fsub{{.*}}float
+  // PRMTD-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 bb0576dd51b98d..d47c71905887d9 100644
--- a/clang/test/CodeGen/pragma-cx-limited-range.c
+++ b/clang/test/CodeGen/pragma-cx-limited-range.c
@@ -2,13 +2,13 @@
 // RUN: -o - | FileCheck %s --check-prefix=FULL
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
-// RUN: -complex-range=limited -o - | FileCheck --check-prefix=LMTD %s
+// RUN: -complex-range=basic -o - | FileCheck --check-prefix=BASIC %s
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
-// RUN: -complex-range=smith -o - | FileCheck --check-prefix=SMITH %s
+// RUN: -complex-range=improved -o - | FileCheck --check-prefix=IMPRVD %s
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
-// RUN: -complex-range=extend -o - | FileCheck --check-prefix=EXTND %s
+// RUN: -complex-range=promoted -o - | FileCheck --check-prefix=PRMTD %s
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
 // RUN: -complex-range=full -o - | FileCheck --check-prefix=FULL %s
@@ -24,26 +24,26 @@ _Complex float pragma_on_mul(_Complex float a, _Complex float b) {
   // 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
+  // BASIC: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fsub float
+  // BASIC-NEXT: fadd float
+
+  // IMPRVD: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fsub float
+  // IMPRVD-NEXT: fadd float
+
+  // PRMTD: fmul float
+  // PRMTD-NEXT: fmul float
+  // PRMTD-NEXT: fmul float
+  // PRMTD-NEXT: fmul float
+  // PRMTD-NEXT: fsub float
+  // PRMTD-NEXT: fadd float
 
   return a * b;
 }
@@ -54,11 +54,11 @@ _Complex float pragma_off_mul(_Complex float a, _Complex float b) {
 
   // FULL: call {{.*}} @__mulsc3
 
-  // LMTD: call {{.*}} @__mulsc3
+  // BASIC: call {{.*}} @__mulsc3
 
-  // SMITH: call {{.*}} @__mulsc3
+  // IMPRVD: call {{.*}} @__mulsc3
 
-  // EXTND: call {{.*}} @__mulsc3
+  // PRMTD: call {{.*}} @__mulsc3
 
   return a * b;
 }
@@ -79,45 +79,45 @@ _Complex float pragma_on_div(_Complex float a, _Complex float b) {
   // FULL-NEXT: fdiv float
   // FULL: fdiv float
 
-  // 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: 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
+  // BASIC: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fadd float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fadd float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fsub float
+  // BASIC-NEXT: fdiv float
+  // BASIC-NEXT: fdiv float
+
+  // IMPRVD: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fadd float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fadd float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fsub float
+  // 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
 
   return a / b;
 }
@@ -128,11 +128,11 @@ _Complex float pragma_off_div(_Complex float a, _Complex float b) {
 
   // FULL: call {{.*}} @__divsc3
 
-  // LMTD: call {{.*}} @__divsc3
+  // BASIC: call {{.*}} @__divsc3
 
-  // SMITH: call {{.*}} @__divsc3
+  // IMPRVD: call {{.*}} @__divsc3
 
-  // EXTND: call {{.*}} @__divdc3
+  // PRMTD: call {{.*}} @__divdc3
 
   return a / b;
 }
@@ -148,26 +148,26 @@ _Complex float pragma_default_mul(_Complex float a, _Complex float b) {
   // 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
+  // BASIC: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fsub float
+  // BASIC-NEXT: fadd float
+
+  // IMPRVD: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fsub float
+  // IMPRVD-NEXT: fadd float
+
+  // PRMTD: fmul float
+  // PRMTD-NEXT: fmul float
+  // PRMTD-NEXT: fmul float
+  // PRMTD-NEXT: fmul float
+  // PRMTD-NEXT: fsub float
+  // PRMTD-NEXT: fadd float
 
   return a * b;
 }
@@ -177,66 +177,66 @@ _Complex float pragma_default_div(_Complex float a, _Complex float b) {
 
   // 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
+  // BASIC: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fadd float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fadd float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fmul float
+  // BASIC-NEXT: fsub float
+  // BASIC-NEXT: fdiv float
+  // BASIC-NEXT: fdiv float
+
+  // IMPRVD: call{{.*}}float @llvm.fabs.f32(float {{.*}})
+  // IMPRVD-NEXT: call{{.*}}float @llvm.fabs.f32(float {{.*}})
+  // IMPRVD-NEXT: fcmp{{.*}}ugt float {{.*}}, {{.*}}
+  // IMPRVD-NEXT:   br i1 {{.*}}, label
+  // IMPRVD:  abs_rhsr_greater_or_equal_abs_rhsi:
+  // IMPRVD-NEXT: fdiv float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fadd float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fadd float
+  // IMPRVD-NEXT: fdiv float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fsub float
+  // IMPRVD-NEXT: fdiv float
+  // IMPRVD-NEXT: br label
+  // IMPRVD: abs_rhsr_less_than_abs_rhsi:
+  // IMPRVD-NEXT: fdiv float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fadd float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fadd float
+  // IMPRVD-NEXT: fdiv float
+  // IMPRVD-NEXT: fmul float
+  // IMPRVD-NEXT: fsub float
+  // IMPRVD-NEXT: fdiv float
+
+  // PRMTD: load float, ptr {{.*}}
+  // PRMTD: fpext float {{.*}} to double
+  // PRMTD-NEXT: fpext float {{.*}} to double
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+  // PRMTD-NEXT: load float, ptr {{.*}}
+  // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+  // PRMTD-NEXT: load float, ptr {{.*}}
+  // PRMTD-NEXT: fpext float {{.*}} to double
+  // PRMTD-NEXT: fpext float {{.*}} to double
+  // PRMTD-NEXT: fmul double
+  // PRMTD-NEXT: fmul double
+  // PRMTD-NEXT: fadd double
+  // PRMTD-NEXT: fmul double
+  // PRMTD-NEXT: fmul double
+  // PRMTD-NEXT: fadd double
+  // PRMTD-NEXT: fmul double
+  // PRMTD-NEXT: fmul double
+  // PRMTD-NEXT: fsub double
+  // PRMTD-NEXT: fdiv double
+  // PRMTD-NEXT: fdiv double
+  // PRMTD-NEXT: fptrunc double {{.*}} to float
+  // PRMTD-NEXT: fptrunc double {{.*}} to float
 
   return a / b;
 }
diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c
index 434e9407664ce7..b064fa9378ab9d 100644
--- a/clang/test/Driver/range.c
+++ b/clang/test/Driver/range.c
@@ -1,93 +1,93 @@
 // Test range options for complex multiplication and division.
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=LMTD %s
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=BASIC %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=SMITH %s
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=IMPRVD %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=EXTND %s
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=PRMTD %s
 
 // RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=FULL %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited \
-// RUN: -fcomplex-arithmetic=smith -c %s 2>&1 \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \
+// RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN1 %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \
 // RUN: -fcomplex-arithmetic=full -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN2 %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited \
-// RUN: -fcomplex-arithmetic=extend -c %s 2>&1 \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \
+// RUN: -fcomplex-arithmetic=promoted -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN3 %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith \
-// RUN: -fcomplex-arithmetic=limited  -c %s 2>&1 \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved \
+// RUN: -fcomplex-arithmetic=basic  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN4 %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved \
 // RUN: -fcomplex-arithmetic=full  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN5 %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith \
-// RUN: -fcomplex-arithmetic=extend  -c %s 2>&1 \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved \
+// RUN: -fcomplex-arithmetic=promoted  -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: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \
+// RUN: -fcomplex-arithmetic=basic  -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: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \
+// RUN: -fcomplex-arithmetic=improved  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN8 %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \
 // 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: -fcomplex-arithmetic=basic  -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: -fcomplex-arithmetic=improved  -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: -fcomplex-arithmetic=promoted  -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:   | FileCheck --check-prefix=BASIC %s
 
-// RUN: %clang -### -target x86_64 -ffast-math -fcomplex-arithmetic=limited -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=LMTD %s
+// RUN: %clang -### -target x86_64 -ffast-math -fcomplex-arithmetic=basic -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=BASIC %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=limited -ffast-math -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=LMTD %s
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic -ffast-math -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=BASIC %s
 
-// LMTD: -complex-range=limited
+// BASIC: -complex-range=basic
 // FULL: -complex-range=full
-// EXTND: -complex-range=extend
-// LMTD-NOT: -complex-range=smith
-// CHECK-NOT: -complex-range=limited
-// 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]
+// PRMTD: -complex-range=promoted
+// BASIC-NOT: -complex-range=improved
+// CHECK-NOT: -complex-range=basic
+// IMPRVD: -complex-range=improved
+// IMPRVD-NOT: -complex-range=basic
+// CHECK-NOT: -complex-range=improved
+// WARN1: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=improved' [-Woverriding-option]
+// WARN2: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=full' [-Woverriding-option]
+// WARN3: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=promoted' [-Woverriding-option]
+// WARN4: warning: overriding '-fcomplex-arithmetic=improved' option with '-fcomplex-arithmetic=basic' [-Woverriding-option]
+// WARN5: warning: overriding '-fcomplex-arithmetic=improved' option with '-fcomplex-arithmetic=full' [-Woverriding-option]
+// WARN6: warning: overriding '-fcomplex-arithmetic=improved' option with '-fcomplex-arithmetic=promoted' [-Woverriding-option]
+// WARN7: warning: overriding '-fcomplex-arithmetic=promoted' option with '-fcomplex-arithmetic=basic' [-Woverriding-option]
+// WARN8: warning: overriding '-fcomplex-arithmetic=promoted' option with '-fcomplex-arithmetic=improved' [-Woverriding-option]
+// WARN9: warning: overriding '-fcomplex-arithmetic=promoted' option with '-fcomplex-arithmetic=full' [-Woverriding-option]
+// WARN10: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=basic' [-Woverriding-option]
+// WARN11: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=improved' [-Woverriding-option]
+// WARN12: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=promoted' [-Woverriding-option]



More information about the cfe-commits mailing list