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

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

https://reviews.llvm.org/D151834

Files:
  clang/include/clang/Basic/FPOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGen/math-errno.c

Index: clang/test/CodeGen/math-errno.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/math-errno.c
@@ -0,0 +1,66 @@
+// -O2
+// RUN: %clang_cc1 -Wno-implicit-function-declaration  \
+// RUN: -ffp-contract=on -fno-rounding-math -O2 -emit-llvm -o - %s \
+// RUN: | FileCheck %s
+
+// -ffast-math
+// RUN: %clang_cc1 -Wno-implicit-function-declaration  \
+// RUN: -menable-no-infs -menable-no-nans -fapprox-func \
+// RUN: -funsafe-math-optimizations -fno-signed-zeros -mreassociate \
+// RUN: -freciprocal-math -ffp-contract=fast -fno-rounding-math -ffast-math \
+// RUN: -ffinite-math-only -ffast-math -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefix=FAST
+
+// -O0
+// RUN: %clang_cc1 -Wno-implicit-function-declaration  \
+// RUN: -ffp-contract=on -fno-rounding-math -O2 -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefix=NOOPT
+
+#pragma float_control(precise,on)
+float f1(float x) {
+  return sqrtf(x);
+}
+
+// CHECK-LABEL: define dso_local float @f1
+// CHECK: tail call float @sqrtf(float noundef {{.*}}) #[[ATTR4_O2:[0-9]+]]
+
+// FAST-LABEL: define dso_local nofpclass(nan inf) float @f1
+// FAST: call fast nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan inf) {{.*}}) #[[ATTR3_FAST:[0-9]+]]
+//
+// NOOPT-LABEL: define dso_local float @f1
+// NOOPT: tail call float @sqrtf(float noundef {{.*}}) #[[ATTR4_NOOPT:[0-9]+]]
+
+
+#pragma float_control(precise,off)
+float f2(float x) {
+  return sqrtf(x);
+}
+
+// CHECK-LABEL: define dso_local float @f2
+// CHECK: tail call float @llvm.sqrt.f32(float {{.*}})
+
+// FAST-LABEL: define dso_local nofpclass(nan inf) float @f2
+// FAST: call fast nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan inf) {{.*}}) #[[ATTR3_FAST]]
+
+// NOOPT-LABEL: define dso_local float @f2
+// NOOPT: tail call float @llvm.sqrt.f32(float {{.*}})
+
+
+__attribute__((optnone))
+float f3(float x) {
+  x = sqrtf(x);
+  return x;
+}
+
+// CHECK-LABEL: define dso_local float @f3
+// CHECK: call float @llvm.sqrt.f32(float {{.*}})
+
+// FAST-LABEL: define dso_local nofpclass(nan inf) float @f3
+// FAST: call fast nofpclass(nan inf) float @sqrtf(float noundef nofpclass(nan inf) {{.*}}) #[[ATTR4_FAST:[0-9]+]]
+
+// NOOPT-LABEL: define dso_local float @f3
+// NOOPT: call float @llvm.sqrt.f32(float {{.*}})
+
+// CHECK: [[ATTR4_O2]] = { nounwind willreturn memory(none) }
+// FAST: [[ATTR3_FAST]] =  { nounwind willreturn memory(none) }
+// NOOPT: [[ATTR4_NOOPT]] = { nounwind willreturn memory(none) }
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -1254,6 +1254,12 @@
                               llvm::AttributeList &Attrs, unsigned &CallingConv,
                               bool AttrOnCallSite, bool IsThunk);
 
+  /// Adjust Memory attribute to ensure that the BE gets the right attribute
+  // in order to generate the library call or the intrinsic for the function
+  // name 'Name'.
+  void AdjustMemoryAttribute(StringRef Name,
+                             CGCalleeInfo CalleeInfo, llvm::AttributeList &Attrs);
+
   /// Adds attributes to F according to our CodeGenOptions and LangOptions, as
   /// though we had emitted it ourselves.  We remove any attributes on F that
   /// conflict with the attributes we add here.
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -2216,6 +2216,17 @@
   return Mask;
 }
 
+void CodeGenModule::AdjustMemoryAttribute(StringRef Name,
+                                          CGCalleeInfo CalleeInfo,
+                                          llvm::AttributeList &Attrs) {
+  if (Attrs.getMemoryEffects().getModRef() == llvm::ModRefInfo::NoModRef) {
+    Attrs = Attrs.removeFnAttribute(getLLVMContext(), llvm::Attribute::Memory);
+    llvm::Attribute MemoryAttr = llvm::Attribute::getWithMemoryEffects(
+        getLLVMContext(), llvm::MemoryEffects::writeOnly());
+    Attrs = Attrs.addFnAttribute(getLLVMContext(), MemoryAttr);
+  }
+}
+
 /// Construct the IR attribute list of a function or call.
 ///
 /// When adding an attribute, please consider where it should be handled:
@@ -5463,11 +5474,17 @@
                              /*AttrOnCallSite=*/true,
                              /*IsThunk=*/false);
 
-  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
     if (FD->hasAttr<StrictFPAttr>())
       // All calls within a strictfp function are marked strictfp
       Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::StrictFP);
 
+    // If -ffast-math is enabled and the function is guarded by an '__attribute__((optnone))
+    // adjust the memory attribute so the BE emits the library call instead of the intrinsic.
+    if (FD->hasAttr<OptimizeNoneAttr>() && getLangOpts().FastMath)
+      CGM.AdjustMemoryAttribute(CalleePtr->getName(), Callee.getAbstractInfo(),
+                                Attrs);
+  }
   // Add call-site nomerge attribute if exists.
   if (InNoMergeAttributedStmt)
     Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoMerge);
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -2246,6 +2246,29 @@
   const unsigned BuiltinIDIfNoAsmLabel =
       FD->hasAttr<AsmLabelAttr>() ? 0 : BuiltinID;
 
+  // MSVC takes into account math-errno when compiling at -O2 level in
+  // the presence of a '#pragma float_control precise(on/off)'.
+  // ErrnoWithO2OrFastMath checks for that.
+  // When compiling with 'ffast-math' check if 'math-errno' is overriden, or
+  // if the '__attribute__((optnone)) is used.
+  // ErrnoWithO2OrFastMath and OptNoneWithFastMath check for that.
+  // In both of these cases don't emit intrinsics.
+  // At -O0 level, no intrinsic should be generated.
+  bool MathErrnoOverrride = false;
+  if (E->hasStoredFPFeatures()) {
+    FPOptionsOverride OP = E->getFPFeatures();
+    if (OP.hasMathErrnoOverride())
+      MathErrnoOverrride = OP.getMathErrnoOverride();
+  }
+  bool ErrnoWithO2OrFastMath =
+      MathErrnoOverrride && (CGM.getCodeGenOpts().OptimizationLevel == 2 ||
+                             CGM.getLangOpts().FastMath);
+  bool OptNoneWithFastMath =
+      CurFuncDecl->hasAttr<OptimizeNoneAttr>() && CGM.getLangOpts().FastMath;
+  bool EmitIntrinsic =
+      ((CGM.getCodeGenOpts().OptimizationLevel != 0) &&
+                       !OptNoneWithFastMath && !ErrnoWithO2OrFastMath);
+
   // There are LLVM math intrinsics/instructions corresponding to math library
   // functions except the LLVM op will never set errno while the math library
   // might. Also, math builtins have the same semantics as their math library
@@ -2257,9 +2280,11 @@
       getContext().BuiltinInfo.isConstWithoutErrnoAndExceptions(BuiltinID);
   bool ConstWithoutExceptions =
       getContext().BuiltinInfo.isConstWithoutExceptions(BuiltinID);
-  if (FD->hasAttr<ConstAttr>() ||
-      ((ConstWithoutErrnoAndExceptions || ConstWithoutExceptions) &&
-       (!ConstWithoutErrnoAndExceptions || (!getLangOpts().MathErrno)))) {
+
+  if ((FD->hasAttr<ConstAttr>() && EmitIntrinsic) || EmitIntrinsic ||
+       ((ConstWithoutErrnoAndExceptions || ConstWithoutExceptions) &&
+         (!ConstWithoutErrnoAndExceptions ||
+        (!getLangOpts().MathErrno && EmitIntrinsic)))) {
     switch (BuiltinIDIfNoAsmLabel) {
     case Builtin::BIceil:
     case Builtin::BIceilf:
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -850,6 +850,7 @@
     setNoSignedZeroOverride(!Value);
     setAllowReciprocalOverride(!Value);
     setAllowApproxFuncOverride(!Value);
+    setMathErrnoOverride(Value);
     if (Value)
       /* Precise mode implies fp_contract=on and disables ffast-math */
       setAllowFPContractWithinStatement();
Index: clang/include/clang/Basic/FPOptions.def
===================================================================
--- clang/include/clang/Basic/FPOptions.def
+++ clang/include/clang/Basic/FPOptions.def
@@ -27,4 +27,5 @@
 OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc)
 OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod)
 OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod)
+OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision)
 #undef OPTION
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to