arsenm created this revision.
arsenm added reviewers: scanon, andrew.w.kaylor, cameron.mcinally, spatel, 
RKSimon, olista01, SjoerdMeijer.
Herald added subscribers: dexonsmith, hiraditya, tpr, mgorny, wdng.
Herald added a project: LLVM.

Cleanup handling of the denormal-fp-math attribute. Consolidate places
checking the allowed names in one place. Also begin migrating towards
the current IEEE-754's standard's preferred terminology of subnormal
over denormal.

      

This is in preparation for introducing FP type specific variants of
the denorm-fp-mode attribute. AMDGPU will switch to using this in
place of the current hacky use of subtarget features for the denormal
mode.

      

Introduce a new header for dealing with FP modes. The constrained
intrinsic classes define related enums that should also be moved into
this header for uses in other contexts.

      

The verifier could use a check to make sure the denorm-fp-mode
attribute is sane, but there currently isn't one.

      

There is a problem with this patch as is. The one place currently
checking this attribute in buildSqrtEstimateImpl (added by D42323 
<https://reviews.llvm.org/D42323>)
oddly doesn't assume the ieee behavior if the attribute isn't
specified as I would expect. The question of why this behaves this way
needs to be resolved to proceed as tests fail due to assuming IEEE
behavior on undecorated functions.


https://reviews.llvm.org/D69598

Files:
  clang/include/clang/Basic/CodeGenOptions.h
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  llvm/include/llvm/ADT/FloatingPointMode.h
  llvm/include/llvm/CodeGen/MachineFunction.h
  llvm/lib/CodeGen/MachineFunction.cpp
  llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
  llvm/unittests/ADT/CMakeLists.txt
  llvm/unittests/ADT/FloatingPointMode.cpp

Index: llvm/unittests/ADT/FloatingPointMode.cpp
===================================================================
--- /dev/null
+++ llvm/unittests/ADT/FloatingPointMode.cpp
@@ -0,0 +1,33 @@
+//===- llvm/unittest/ADT/FloatingPointMode.cpp ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/FloatingPointMode.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(FloatingPointModeTest, ParseSubnormalFPAttribute) {
+  EXPECT_EQ(SubnormalMode::IEEE, parseSubnormalFPAttribute("ieee"));
+  EXPECT_EQ(SubnormalMode::IEEE, parseSubnormalFPAttribute(""));
+  EXPECT_EQ(SubnormalMode::PreserveSign,
+            parseSubnormalFPAttribute("preserve-sign"));
+  EXPECT_EQ(SubnormalMode::PositiveZero,
+            parseSubnormalFPAttribute("positive-zero"));
+  EXPECT_EQ(SubnormalMode::Invalid, parseSubnormalFPAttribute("foo"));
+}
+
+TEST(FloatingPointModeTest, SubnormalAttributeName) {
+  EXPECT_EQ("ieee", subnormalModeName(SubnormalMode::IEEE));
+  EXPECT_EQ("preserve-sign", subnormalModeName(SubnormalMode::PreserveSign));
+  EXPECT_EQ("positive-zero", subnormalModeName(SubnormalMode::PositiveZero));
+  EXPECT_EQ("", subnormalModeName(SubnormalMode::Invalid));
+}
+
+}
Index: llvm/unittests/ADT/CMakeLists.txt
===================================================================
--- llvm/unittests/ADT/CMakeLists.txt
+++ llvm/unittests/ADT/CMakeLists.txt
@@ -20,6 +20,7 @@
   DirectedGraphTest.cpp
   EquivalenceClassesTest.cpp
   FallibleIteratorTest.cpp
+  FloatingPointMode.cpp
   FoldingSet.cpp
   FunctionExtrasTest.cpp
   FunctionRefTest.cpp
Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -20452,9 +20452,8 @@
         SDLoc DL(Op);
         EVT CCVT = getSetCCResultType(VT);
         ISD::NodeType SelOpcode = VT.isVector() ? ISD::VSELECT : ISD::SELECT;
-        const Function &F = DAG.getMachineFunction().getFunction();
-        Attribute Denorms = F.getFnAttribute("denormal-fp-math");
-        if (Denorms.getValueAsString().equals("ieee")) {
+        SubnormalMode SubnormMode = DAG.getMachineFunction().getSubnormalMode();
+        if (SubnormMode == SubnormalMode::IEEE) {
           // fabs(X) < SmallestNormal ? 0.0 : Est
           const fltSemantics &FltSem = DAG.EVTToAPFloatSemantics(VT);
           APFloat SmallestNorm = APFloat::getSmallestNormalized(FltSem);
@@ -20464,6 +20463,8 @@
           SDValue IsDenorm = DAG.getSetCC(DL, CCVT, Fabs, NormC, ISD::SETLT);
           Est = DAG.getNode(SelOpcode, DL, VT, IsDenorm, FPZero, Est);
         } else {
+          assert(SubnormMode == SubnormalMode::PreserveSign ||
+                 SubnormMode == SubnormalMode::PositiveZero);
           // X == 0.0 ? 0.0 : Est
           SDValue FPZero = DAG.getConstantFP(0.0, DL, VT);
           SDValue IsZero = DAG.getSetCC(DL, CCVT, Op, FPZero, ISD::SETEQ);
Index: llvm/lib/CodeGen/MachineFunction.cpp
===================================================================
--- llvm/lib/CodeGen/MachineFunction.cpp
+++ llvm/lib/CodeGen/MachineFunction.cpp
@@ -270,6 +270,13 @@
   return JumpTableInfo;
 }
 
+SubnormalMode MachineFunction::getSubnormalMode() const {
+  // TODO: Should probably avoid the connection to the IR and store directly
+  // in the MachineFunction.
+  Attribute Attr = F.getFnAttribute("denormal-fp-math");
+  return parseSubnormalFPAttribute(Attr.getValueAsString());
+}
+
 /// Should we be emitting segmented stack stuff for the function
 bool MachineFunction::shouldSplitStack() const {
   return getFunction().hasFnAttribute("split-stack");
Index: llvm/include/llvm/CodeGen/MachineFunction.h
===================================================================
--- llvm/include/llvm/CodeGen/MachineFunction.h
+++ llvm/include/llvm/CodeGen/MachineFunction.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FloatingPointMode.h"
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
@@ -579,6 +580,10 @@
      return const_cast<MachineFunction*>(this)->getInfo<Ty>();
   }
 
+  /// Returns the subnormal handling type for the default rounding mode of the
+  /// function.
+  SubnormalMode getSubnormalMode() const;
+
   /// getBlockNumbered - MachineBasicBlocks are automatically numbered when they
   /// are inserted into the machine function.  The block number for a machine
   /// basic block can be found by using the MBB::getNumber method, this method
Index: llvm/include/llvm/ADT/FloatingPointMode.h
===================================================================
--- /dev/null
+++ llvm/include/llvm/ADT/FloatingPointMode.h
@@ -0,0 +1,62 @@
+//===- llvm/Support/FloatingPointMode.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for dealing with flags related to floating point mode controls.
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_FLOATINGPOINTMODE_H
+#define LLVM_FLOATINGPOINTMODE_H
+
+#include "llvm/ADT/StringSwitch.h"
+
+namespace llvm {
+
+/// Represent handled modes for subnormal (aka denormal) modes in the floating
+/// point environment.
+enum class SubnormalMode {
+  Invalid = -1,
+
+  /// IEEE-754 subnormal numbers preserved.
+  IEEE,
+
+  /// The sign of a flushed-to-zero number is preserved in the sign of 0
+  PreserveSign,
+
+  /// Subnormals are flushed to positive zero.
+  PositiveZero
+};
+
+/// Parse the expected names from the denormal-fp-math attribute.
+inline SubnormalMode parseSubnormalFPAttribute(StringRef Str) {
+  // Assume ieee on unspecified attribute.
+  return StringSwitch<SubnormalMode>(Str)
+    .Cases("", "ieee", SubnormalMode::IEEE)
+    .Case("preserve-sign", SubnormalMode::PreserveSign)
+    .Case("positive-zero", SubnormalMode::PositiveZero)
+    .Default(SubnormalMode::Invalid);
+}
+
+/// Return the name used for the subnormal handling mode used by the the
+/// expected names from the denormal-fp-math attribute.
+inline StringRef subnormalModeName(SubnormalMode Mode) {
+  switch (Mode) {
+  case SubnormalMode::IEEE:
+    return "ieee";
+  case SubnormalMode::PreserveSign:
+    return "preserve-sign";
+  case SubnormalMode::PositiveZero:
+    return "positive-zero";
+  default:
+    return "";
+  }
+}
+
+}
+
+#endif // LLVM_FLOATINGPOINTMODE_H
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -1261,13 +1261,8 @@
 
   if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
     StringRef Val = A->getValue();
-    if (Val == "ieee")
-      Opts.FPDenormalMode = "ieee";
-    else if (Val == "preserve-sign")
-      Opts.FPDenormalMode = "preserve-sign";
-    else if (Val == "positive-zero")
-      Opts.FPDenormalMode = "positive-zero";
-    else
+    Opts.FPSubnormalMode = llvm::parseSubnormalFPAttribute(Val);
+    if (Opts.FPSubnormalMode == llvm::SubnormalMode::Invalid)
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
   }
 
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1732,8 +1732,9 @@
 
     if (CodeGenOpts.NullPointerIsValid)
       FuncAttrs.addAttribute("null-pointer-is-valid", "true");
-    if (!CodeGenOpts.FPDenormalMode.empty())
-      FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode);
+    if (CodeGenOpts.FPSubnormalMode != llvm::SubnormalMode::Invalid)
+      FuncAttrs.addAttribute("denormal-fp-math",
+                             llvm::subnormalModeName(CodeGenOpts.FPSubnormalMode));
 
     FuncAttrs.addAttribute("no-trapping-math",
                            llvm::toStringRef(CodeGenOpts.NoTrappingMath));
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -16,6 +16,7 @@
 #include "clang/Basic/DebugInfoOptions.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/FloatingPointMode.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Target/TargetOptions.h"
@@ -162,8 +163,8 @@
   /// The ABI to use for passing floating point arguments.
   std::string FloatABI;
 
-  /// The floating-point denormal mode to use.
-  std::string FPDenormalMode;
+  /// The floating-point subnormal mode to use.
+  llvm::SubnormalMode FPSubnormalMode = llvm::SubnormalMode::Invalid;
 
   /// The float precision limit to use, if non-empty.
   std::string LimitFloatPrecision;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to