[clang] Full control of range reduction for complex multiplication and (PR #81316)

Zahira Ammarguellat via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 9 12:42:37 PST 2024


https://github.com/zahiraam created https://github.com/llvm/llvm-project/pull/81316

division.

>From 5cf9dd1073ce6ae72aebbbd8fc4723ec48b39816 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 9 Feb 2024 12:38:34 -0800
Subject: [PATCH] Full control of range reduction for complex multiplication
 and division.

---
 clang/include/clang/Basic/LangOptions.h      |  26 ++-
 clang/include/clang/Driver/Options.td        |  10 +-
 clang/lib/CodeGen/CGExprComplex.cpp          |  28 ++-
 clang/lib/Driver/ToolChains/Clang.cpp        |  86 +++----
 clang/test/CodeGen/cx-complex-range.c        | 232 +++++++++++--------
 clang/test/CodeGen/pragma-cx-limited-range.c |   2 +-
 clang/test/Driver/range.c                    | 101 +++++---
 7 files changed, 307 insertions(+), 178 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index c1cc5548ef10c0..5ef29909bfa502 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -414,7 +414,31 @@ class LangOptions : public LangOptionsBase {
     IncompleteOnly = 3,
   };
 
-  enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran, CX_None };
+  /// Controls for the complex arithmetic range rules.
+  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
+  };
 
 public:
   /// The used language standard.
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 4b232b8aab722a..527ab27a3d2358 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1030,12 +1030,18 @@ 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
 def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 9ddf0e763f139b..f41c69190b0e5c 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,7 +310,9 @@ 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 =                                                                 \
@@ -790,7 +806,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 +998,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 13bf2421154372..f990249fb059cd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2688,17 +2688,17 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
 }
 
 static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
-  StringRef RangeStr = "";
   switch (Range) {
   case LangOptions::ComplexRangeKind::CX_Limited:
-    return "-fcx-limited-range";
-    break;
-  case LangOptions::ComplexRangeKind::CX_Fortran:
-    return "-fcx-fortran-rules";
-    break;
+    return "-fcomplex-arithmetic=limited";
+  case LangOptions::ComplexRangeKind::CX_Smith:
+    return "-fcomplex-arithmetic=smith";
+  case LangOptions::ComplexRangeKind::CX_Extend:
+    return "-fcomplex-arithmetic=extend";
+  case LangOptions::ComplexRangeKind::CX_Full:
+    return "-fcomplex-arithmetic=full";
   default:
-    return RangeStr;
-    break;
+    return "";
   }
 }
 
@@ -2710,22 +2710,30 @@ static void EmitComplexRangeDiag(const Driver &D,
         << EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2);
 }
 
-static std::string
-RenderComplexRangeOption(LangOptions::ComplexRangeKind Range) {
-  std::string ComplexRangeStr = "-complex-range=";
+static std::string ComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
   switch (Range) {
   case LangOptions::ComplexRangeKind::CX_Full:
-    ComplexRangeStr += "full";
+    return "full";
     break;
   case LangOptions::ComplexRangeKind::CX_Limited:
-    ComplexRangeStr += "limited";
+    return "limited";
     break;
-  case LangOptions::ComplexRangeKind::CX_Fortran:
-    ComplexRangeStr += "fortran";
+  case LangOptions::ComplexRangeKind::CX_Smith:
+    return "smith";
+    break;
+  case LangOptions::ComplexRangeKind::CX_Extend:
+    return "extend";
     break;
   default:
-    assert(0 && "Unexpected range option");
+    return "";
   }
+}
+
+static std::string
+RenderComplexRangeOption(LangOptions::ComplexRangeKind Range) {
+  std::string ComplexRangeStr = ComplexRangeToStr(Range);
+  if (!ComplexRangeStr.empty())
+    return "-complex-range=" + ComplexRangeStr;
   return ComplexRangeStr;
 }
 
@@ -2789,24 +2797,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 +3243,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=" +
+                                           ComplexRangeToStr(Range)));
+  }
 }
 
 static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c
index 2d8507c710f202..02c5fc57547ce9 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=FRTRN
 
 // 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 %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=smith -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=FRTRN
 
+// 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
+
+// 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
+//
+// 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
+//
 _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
-
   return a / 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
+//
+// FRTRN: alloca { float, float }
+// FRTRN-NEXT: alloca { float, float }
+// FRTRN-NEXT: alloca { float, float }
+// FRTRN: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+// FRTRN-NEXT: load float, ptr {{.*}}
+// FRTRN-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+// FRTRN-NEXT: load float, ptr {{.*}}
+// FRTRN-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0
+// FRTRN-NEXT: load float, ptr {{.*}}
+// FRTRN-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1
+// FRTRN-NEXT: load float
+// FRTRN-NEXT: fmul{{.*}}float
+// FRTRN-NEXT: fmul{{.*}}float
+// FRTRN-NEXT: fmul{{.*}}float
+// FRTRN-NEXT: fmul{{.*}}float
+// FRTRN-NEXT: fsub{{.*}}float
+// FRTRN-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
+//
 _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
-
   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..8fa09c9af2f7f3 100644
--- a/clang/test/CodeGen/pragma-cx-limited-range.c
+++ b/clang/test/CodeGen/pragma-cx-limited-range.c
@@ -8,7 +8,7 @@
 // RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL
 
 // 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=smith -o - | FileCheck --check-prefix=FRTRN %s
 
 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \
 // RUN: -fno-cx-fortran-rules -o - | FileCheck --check-prefix=FULL %s
diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c
index 49116df2f4480e..e63b7e527315ab 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 -fcx-limited-range -fno-cx-limited-range \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s
-
-// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=smith -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=extend -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=EXTND %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 -### -Werror -target x86_64 -fcx-limited-range -c %s 2>&1 \
+// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=extend \
+// RUN: -fcomplex-arithmetic=smith  -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=WARN8 %s
+
+// 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 -### -Werror -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=FRTRN %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 -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: -complex-range=smith
 // 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]
+// 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]



More information about the cfe-commits mailing list