zahiraam updated this revision to Diff 475902.
zahiraam marked 5 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136176/new/

https://reviews.llvm.org/D136176

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/CodeGen/X86/fexcess-precision.c
  clang/test/Driver/fexcess-precision.c

Index: clang/test/Driver/fexcess-precision.c
===================================================================
--- /dev/null
+++ clang/test/Driver/fexcess-precision.c
@@ -0,0 +1,17 @@
+// RUN: %clang -### -target i386 -fexcess-precision=fast -c %s 2>&1  \
+// RUN:   | FileCheck --check-prefix=CHECK-FAST %s
+// RUN: %clang -### -target i386 -fexcess-precision=standard -c %s 2>&1  \
+// RUN:   | FileCheck --check-prefix=CHECK-STD %s
+// RUN: %clang -### -target x86_64 -fexcess-precision=standard -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-STD %s
+// RUN: %clang -### -target x86_64 -fexcess-precision=fast -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-FAST %s
+// RUN: %clang -### -target i386 -fexcess-precision=none -c %s 2>&1  \
+// RUN:   | FileCheck --check-prefix=CHECK-ERR %s
+// RUN: %clang -### -target x86_64 -fexcess-precision=none -c %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-NONE %s
+
+// CHECK-FAST: "-fexcess-precision=fast"
+// CHECK-STD: "-fexcess-precision=standard"
+// CHECK-NONE: "-fexcess-precision=none"
+// CHECK-ERR: error: unsupported option '-fexcess-precision=none' for target 'i386'
Index: clang/test/CodeGen/X86/fexcess-precision.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/X86/fexcess-precision.c
@@ -0,0 +1,286 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=fast \
+// RUN: -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=standard \
+// RUN: -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=fast \
+// RUN: -emit-llvm -ffp-eval-method=source -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=standard \
+// RUN: -emit-llvm -ffp-eval-method=source -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -emit-llvm -ffp-eval-method=source -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=fast \
+// RUN: -emit-llvm -ffp-eval-method=double -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-DBL %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=standard \
+// RUN: -emit-llvm -ffp-eval-method=double -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-DBL %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -emit-llvm -ffp-eval-method=double -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-DBL %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=fast \
+// RUN: -emit-llvm -ffp-eval-method=extended -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-FP80 %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=standard \
+// RUN: -emit-llvm -ffp-eval-method=extended -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-FP80 %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -emit-llvm -ffp-eval-method=extended -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-FP80 %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -ffp-contract=on -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-CONTRACT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -fmath-errno -ffp-contract=on -fno-rounding-math \
+// RUN: -ffp-eval-method=source -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-CONTRACT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -fmath-errno -ffp-contract=on -fno-rounding-math \
+// RUN: -ffp-eval-method=double -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-CONTRACT-DBL %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -fmath-errno -ffp-contract=on -fno-rounding-math \
+// RUN: -ffp-eval-method=extended -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-CONTRACT-EXT %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexcess-precision=none \
+// RUN: -fapprox-func -fmath-errno -fno-signed-zeros -mreassociate \
+// RUN: -freciprocal-math -ffp-contract=on -fno-rounding-math \
+// RUN: -funsafe-math-optimizations -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefixes=CHECK-UNSAFE %s
+
+// CHECK-EXT-LABEL: @f(
+// CHECK-EXT-NEXT:  entry:
+// CHECK-EXT-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-EXT-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-EXT-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-EXT-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-EXT-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-EXT-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-EXT-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-EXT-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-EXT-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-EXT-NEXT:    [[EXT:%.*]] = fpext half [[TMP0]] to float
+// CHECK-EXT-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-EXT-NEXT:    [[EXT1:%.*]] = fpext half [[TMP1]] to float
+// CHECK-EXT-NEXT:    [[MUL:%.*]] = fmul float [[EXT]], [[EXT1]]
+// CHECK-EXT-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-EXT-NEXT:    [[EXT2:%.*]] = fpext half [[TMP2]] to float
+// CHECK-EXT-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-EXT-NEXT:    [[EXT3:%.*]] = fpext half [[TMP3]] to float
+// CHECK-EXT-NEXT:    [[MUL4:%.*]] = fmul float [[EXT2]], [[EXT3]]
+// CHECK-EXT-NEXT:    [[ADD:%.*]] = fadd float [[MUL]], [[MUL4]]
+// CHECK-EXT-NEXT:    [[UNPROMOTION:%.*]] = fptrunc float [[ADD]] to half
+// CHECK-EXT-NEXT:    ret half [[UNPROMOTION]]
+//
+// CHECK-NO-EXT-LABEL: @f(
+// CHECK-NO-EXT-NEXT:  entry:
+// CHECK-NO-EXT-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-NO-EXT-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-NO-EXT-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-NO-EXT-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-NO-EXT-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-NO-EXT-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-NO-EXT-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-NO-EXT-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-NO-EXT-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-NO-EXT-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-NO-EXT-NEXT:    [[MUL:%.*]] = fmul half [[TMP0]], [[TMP1]]
+// CHECK-NO-EXT-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-NO-EXT-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-NO-EXT-NEXT:    [[MUL1:%.*]] = fmul half [[TMP2]], [[TMP3]]
+// CHECK-NO-EXT-NEXT:    [[ADD:%.*]] = fadd half [[MUL]], [[MUL1]]
+// CHECK-NO-EXT-NEXT:    ret half [[ADD]]
+//
+// CHECK-EXT-DBL-LABEL: @f(
+// CHECK-EXT-DBL-NEXT:  entry:
+// CHECK-EXT-DBL-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-EXT-DBL-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-EXT-DBL-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-EXT-DBL-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-EXT-DBL-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-EXT-DBL-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-EXT-DBL-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-EXT-DBL-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-EXT-DBL-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-EXT-DBL-NEXT:    [[CONV:%.*]] = fpext half [[TMP0]] to double
+// CHECK-EXT-DBL-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-EXT-DBL-NEXT:    [[CONV1:%.*]] = fpext half [[TMP1]] to double
+// CHECK-EXT-DBL-NEXT:    [[MUL:%.*]] = fmul double [[CONV]], [[CONV1]]
+// CHECK-EXT-DBL-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-EXT-DBL-NEXT:    [[CONV2:%.*]] = fpext half [[TMP2]] to double
+// CHECK-EXT-DBL-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-EXT-DBL-NEXT:    [[CONV3:%.*]] = fpext half [[TMP3]] to double
+// CHECK-EXT-DBL-NEXT:    [[MUL4:%.*]] = fmul double [[CONV2]], [[CONV3]]
+// CHECK-EXT-DBL-NEXT:    [[ADD:%.*]] = fadd double [[MUL]], [[MUL4]]
+// CHECK-EXT-DBL-NEXT:    [[CONV5:%.*]] = fptrunc double [[ADD]] to half
+// CHECK-EXT-DBL-NEXT:    ret half [[CONV5]]
+//
+// CHECK-EXT-FP80-LABEL: @f(
+// CHECK-EXT-FP80-NEXT:  entry:
+// CHECK-EXT-FP80-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-EXT-FP80-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-EXT-FP80-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-EXT-FP80-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-EXT-FP80-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-EXT-FP80-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-EXT-FP80-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-EXT-FP80-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-EXT-FP80-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-EXT-FP80-NEXT:    [[CONV:%.*]] = fpext half [[TMP0]] to x86_fp80
+// CHECK-EXT-FP80-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-EXT-FP80-NEXT:    [[CONV1:%.*]] = fpext half [[TMP1]] to x86_fp80
+// CHECK-EXT-FP80-NEXT:    [[MUL:%.*]] = fmul x86_fp80 [[CONV]], [[CONV1]]
+// CHECK-EXT-FP80-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-EXT-FP80-NEXT:    [[CONV2:%.*]] = fpext half [[TMP2]] to x86_fp80
+// CHECK-EXT-FP80-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-EXT-FP80-NEXT:    [[CONV3:%.*]] = fpext half [[TMP3]] to x86_fp80
+// CHECK-EXT-FP80-NEXT:    [[MUL4:%.*]] = fmul x86_fp80 [[CONV2]], [[CONV3]]
+// CHECK-EXT-FP80-NEXT:    [[ADD:%.*]] = fadd x86_fp80 [[MUL]], [[MUL4]]
+// CHECK-EXT-FP80-NEXT:    [[CONV5:%.*]] = fptrunc x86_fp80 [[ADD]] to half
+// CHECK-EXT-FP80-NEXT:    ret half [[CONV5]]
+//
+// CHECK-CONTRACT-LABEL: @f(
+// CHECK-CONTRACT-NEXT:  entry:
+// CHECK-CONTRACT-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-CONTRACT-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-CONTRACT-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-CONTRACT-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-CONTRACT-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-CONTRACT-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-CONTRACT-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-CONTRACT-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-CONTRACT-NEXT:    [[MUL1:%.*]] = fmul half [[TMP2]], [[TMP3]]
+// CHECK-CONTRACT-NEXT:    [[TMP4:%.*]] = call half @llvm.fmuladd.f16(half [[TMP0]], half [[TMP1]], half [[MUL1]])
+// CHECK-CONTRACT-NEXT:    ret half [[TMP4]]
+//
+// CHECK-CONTRACT-DBL-LABEL: @f(
+// CHECK-CONTRACT-DBL-NEXT:  entry:
+// CHECK-CONTRACT-DBL-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-DBL-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-DBL-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-DBL-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-DBL-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    [[CONV:%.*]] = fpext half [[TMP0]] to double
+// CHECK-CONTRACT-DBL-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    [[CONV1:%.*]] = fpext half [[TMP1]] to double
+// CHECK-CONTRACT-DBL-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    [[CONV2:%.*]] = fpext half [[TMP2]] to double
+// CHECK-CONTRACT-DBL-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-CONTRACT-DBL-NEXT:    [[CONV3:%.*]] = fpext half [[TMP3]] to double
+// CHECK-CONTRACT-DBL-NEXT:    [[MUL4:%.*]] = fmul double [[CONV2]], [[CONV3]]
+// CHECK-CONTRACT-DBL-NEXT:    [[TMP4:%.*]] = call double @llvm.fmuladd.f64(double [[CONV]], double [[CONV1]], double [[MUL4]])
+// CHECK-CONTRACT-DBL-NEXT:    [[CONV5:%.*]] = fptrunc double [[TMP4]] to half
+// CHECK-CONTRACT-DBL-NEXT:    ret half [[CONV5]]
+//
+// CHECK-CONTRACT-EXT-LABEL: @f(
+// CHECK-CONTRACT-EXT-NEXT:  entry:
+// CHECK-CONTRACT-EXT-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-EXT-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-EXT-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-EXT-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-CONTRACT-EXT-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    [[CONV:%.*]] = fpext half [[TMP0]] to x86_fp80
+// CHECK-CONTRACT-EXT-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    [[CONV1:%.*]] = fpext half [[TMP1]] to x86_fp80
+// CHECK-CONTRACT-EXT-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    [[CONV2:%.*]] = fpext half [[TMP2]] to x86_fp80
+// CHECK-CONTRACT-EXT-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-CONTRACT-EXT-NEXT:    [[CONV3:%.*]] = fpext half [[TMP3]] to x86_fp80
+// CHECK-CONTRACT-EXT-NEXT:    [[MUL4:%.*]] = fmul x86_fp80 [[CONV2]], [[CONV3]]
+// CHECK-CONTRACT-EXT-NEXT:    [[TMP4:%.*]] = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 [[CONV]], x86_fp80 [[CONV1]], x86_fp80 [[MUL4]])
+// CHECK-CONTRACT-EXT-NEXT:    [[CONV5:%.*]] = fptrunc x86_fp80 [[TMP4]] to half
+// CHECK-CONTRACT-EXT-NEXT:    ret half [[CONV5]]
+//
+// CHECK-UNSAFE-LABEL: @f(
+// CHECK-UNSAFE-NEXT:  entry:
+// CHECK-UNSAFE-NEXT:    [[A_ADDR:%.*]] = alloca half
+// CHECK-UNSAFE-NEXT:    [[B_ADDR:%.*]] = alloca half
+// CHECK-UNSAFE-NEXT:    [[C_ADDR:%.*]] = alloca half
+// CHECK-UNSAFE-NEXT:    [[D_ADDR:%.*]] = alloca half
+// CHECK-UNSAFE-NEXT:    store half [[A:%.*]], ptr [[A_ADDR]]
+// CHECK-UNSAFE-NEXT:    store half [[B:%.*]], ptr [[B_ADDR]]
+// CHECK-UNSAFE-NEXT:    store half [[C:%.*]], ptr [[C_ADDR]]
+// CHECK-UNSAFE-NEXT:    store half [[D:%.*]], ptr [[D_ADDR]]
+// CHECK-UNSAFE-NEXT:    [[TMP0:%.*]] = load half, ptr [[A_ADDR]]
+// CHECK-UNSAFE-NEXT:    [[TMP1:%.*]] = load half, ptr [[B_ADDR]]
+// CHECK-UNSAFE-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]]
+// CHECK-UNSAFE-NEXT:    [[TMP3:%.*]] = load half, ptr [[D_ADDR]]
+// CHECK-UNSAFE-NEXT:    [[MUL1:%.*]] = fmul reassoc nsz arcp afn half [[TMP2]], [[TMP3]]
+// CHECK-UNSAFE-NEXT:    [[TMP4:%.*]] = call reassoc nsz arcp afn half @llvm.fmuladd.f16(half [[TMP0]], half [[TMP1]], half [[MUL1]])
+// CHECK-UNSAFE-NEXT:    ret half [[TMP4]]
+//
+_Float16 f(_Float16 a, _Float16 b, _Float16 c, _Float16 d) {
+    return a * b + c * d;
+}
+
+// CHECK-EXT-LABEL: @getFEM(
+// CHECK-EXT-NEXT:  entry:
+// CHECK-EXT-NEXT:    ret i32 0
+//
+// CHECK-NO-EXT-LABEL: @getFEM(
+// CHECK-NO-EXT-NEXT:  entry:
+// CHECK-NO-EXT-NEXT:    ret i32 0
+//
+// CHECK-EXT-DBL-LABEL: @getFEM(
+// CHECK-EXT-DBL-NEXT:  entry:
+// CHECK-EXT-DBL-NEXT:    ret i32 1
+//
+// CHECK-EXT-FP80-LABEL: @getFEM(
+// CHECK-EXT-FP80-NEXT:  entry:
+// CHECK-EXT-FP80-NEXT:    ret i32 2
+//
+// CHECK-CONTRACT-LABEL: @getFEM(
+// CHECK-CONTRACT-NEXT:  entry:
+// CHECK-CONTRACT-NEXT:    ret i32 0
+//
+// CHECK-CONTRACT-DBL-LABEL: @getFEM(
+// CHECK-CONTRACT-DBL-NEXT:  entry:
+// CHECK-CONTRACT-DBL-NEXT:    ret i32 1
+//
+// CHECK-CONTRACT-EXT-LABEL: @getFEM(
+// CHECK-CONTRACT-EXT-NEXT:  entry:
+// CHECK-CONTRACT-EXT-NEXT:    ret i32 2
+//
+// CHECK-UNSAFE-LABEL: @getFEM(
+// CHECK-UNSAFE-NEXT:  entry:
+// CHECK-UNSAFE-NEXT:    ret i32 -1
+//
+int getFEM() {
+  return __FLT_EVAL_METHOD__;
+}
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2792,6 +2792,7 @@
       !JA.isOffloading(Action::OFK_HIP))
     FPContract = "on";
   bool StrictFPModel = false;
+  StringRef FPPrecision = "standard";
 
   if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
     CmdArgs.push_back("-mlimit-float-precision");
@@ -2987,6 +2988,20 @@
       break;
     }
 
+     case options::OPT_fexcess_precision_EQ: {
+      StringRef Val = A->getValue();
+       if (TC.getTriple().getArch() == llvm::Triple::x86 && Val.equals("none"))
+        D.Diag(diag::err_drv_unsupported_opt_for_target)
+             << "-fexcess-precision=none"
+             << TC.getTriple().str();
+       if (Val.equals("standard") || Val.equals("fast") || Val.equals("none")) {
+         FPPrecision = Val;
+       } else {
+         D.Diag(diag::err_drv_unsupported_option_argument)
+             << A->getOption().getName() << Val;
+       }
+      break;
+    }
     case options::OPT_ffinite_math_only:
       HonorINFs = false;
       HonorNaNs = false;
@@ -3154,6 +3169,9 @@
   if (!FPEvalMethod.empty())
     CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + FPEvalMethod));
 
+  if (!FPPrecision.empty())
+    CmdArgs.push_back(Args.MakeArgString("-fexcess-precision=" + FPPrecision));
+
   ParseMRecip(D, Args, CmdArgs);
 
   // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -814,7 +814,13 @@
                             Value *(ScalarExprEmitter::*F)(const BinOpInfo &));
 
   QualType getPromotionType(QualType Ty) {
-    if (CGF.getTarget().shouldEmitFloat16WithExcessPrecision()) {
+    LangOptions::FPExcessPrecisionModeKind Precision =
+        CGF.getContext().getLangOpts().getFPPrecisionMode();
+    LangOptions::FPEvalMethodKind Ev =
+        CGF.getContext().getLangOpts().getFPEvalMethod();
+    if (CGF.getTarget().shouldEmitFloat16WithExcessPrecision() &&
+        (Precision == LangOptions::FPExcessPrecisionModeKind::FPP_Standard ||
+         Precision == LangOptions::FPExcessPrecisionModeKind::FPP_Fast)) {
       if (Ty->isAnyComplexType()) {
         QualType ElementType = Ty->castAs<ComplexType>()->getElementType();
         if (ElementType->isFloat16Type())
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1570,8 +1570,11 @@
 def fignore_exceptions : Flag<["-"], "fignore-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Enable support for ignoring exception handling constructs">,
   MarshallingInfoFlag<LangOpts<"IgnoreExceptions">>;
-def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">,
-    Group<clang_ignored_gcc_optimization_f_Group>;
+def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Specifies the precision in which this floating-point operations will be calculated.">,
+  Values<"standard,fast,none">, NormalizedValuesScope<"LangOptions">,
+  NormalizedValues<["FPP_Standard", "FPP_Fast", "FPP_None"]>,
+  MarshallingInfoEnum<LangOpts<"FPPrecisionMode">, "FPP_Standard">;
 def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
 def : Flag<["-"], "fno-expensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
 def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>;
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -298,6 +298,12 @@
     FEM_UnsetOnCommandLine = 3
   };
 
+   enum FPExcessPrecisionModeKind {
+    FPP_Standard,
+    FPP_Fast,
+    FPP_None
+  };
+
   /// Possible exception handling behavior.
   enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm };
 
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -317,6 +317,7 @@
 BENIGN_LANGOPT(RoundingMath, 1, false, "Do not assume default floating-point rounding behavior")
 BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Default, "FP Exception Behavior Mode type")
 BENIGN_ENUM_LANGOPT(FPEvalMethod, FPEvalMethodKind, 2, FEM_UnsetOnCommandLine, "FP type used for floating point arithmetic")
+BENIGN_ENUM_LANGOPT(FPPrecisionMode, FPExcessPrecisionModeKind, 2, FPP_Standard, "FP precision used for floating point arithmetic")
 LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
 LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
 LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to