Skip to content

Commit 7fe9435

Browse files
committed
Work on cleaning up denormal mode handling
Cleanup handling of the denormal-fp-math attribute. Consolidate places checking the allowed names in one place. This is in preparation for introducing FP type specific variants of the denormal-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. Currently, DAGCombiner incorrectly asssumes non-IEEE behavior by default in the one current user. Clang must be taught to start emitting this attribute by default to avoid regressions when this is switched to assume ieee behavior if the attribute isn't present.
1 parent 6c2151b commit 7fe9435

File tree

10 files changed

+131
-13
lines changed

10 files changed

+131
-13
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "clang/Basic/DebugInfoOptions.h"
1717
#include "clang/Basic/Sanitizers.h"
1818
#include "clang/Basic/XRayInstr.h"
19+
#include "llvm/ADT/FloatingPointMode.h"
1920
#include "llvm/Support/CodeGen.h"
2021
#include "llvm/Support/Regex.h"
2122
#include "llvm/Target/TargetOptions.h"
@@ -163,7 +164,7 @@ class CodeGenOptions : public CodeGenOptionsBase {
163164
std::string FloatABI;
164165

165166
/// The floating-point denormal mode to use.
166-
std::string FPDenormalMode;
167+
llvm::DenormalMode FPDenormalMode = llvm::DenormalMode::Invalid;
167168

168169
/// The float precision limit to use, if non-empty.
169170
std::string LimitFloatPrecision;

clang/lib/CodeGen/CGCall.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,8 +1741,9 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
17411741

17421742
if (CodeGenOpts.NullPointerIsValid)
17431743
FuncAttrs.addAttribute("null-pointer-is-valid", "true");
1744-
if (!CodeGenOpts.FPDenormalMode.empty())
1745-
FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode);
1744+
if (CodeGenOpts.FPDenormalMode != llvm::DenormalMode::Invalid)
1745+
FuncAttrs.addAttribute("denormal-fp-math",
1746+
llvm::denormalModeName(CodeGenOpts.FPDenormalMode));
17461747

17471748
FuncAttrs.addAttribute("no-trapping-math",
17481749
llvm::toStringRef(CodeGenOpts.NoTrappingMath));

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,13 +1266,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
12661266

12671267
if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
12681268
StringRef Val = A->getValue();
1269-
if (Val == "ieee")
1270-
Opts.FPDenormalMode = "ieee";
1271-
else if (Val == "preserve-sign")
1272-
Opts.FPDenormalMode = "preserve-sign";
1273-
else if (Val == "positive-zero")
1274-
Opts.FPDenormalMode = "positive-zero";
1275-
else
1269+
Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
1270+
if (Opts.FPDenormalMode == llvm::DenormalMode::Invalid)
12761271
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
12771272
}
12781273

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===- llvm/Support/FloatingPointMode.h -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Utilities for dealing with flags related to floating point mode controls.
10+
//
11+
//===----------------------------------------------------------------------===/
12+
13+
#ifndef LLVM_FLOATINGPOINTMODE_H
14+
#define LLVM_FLOATINGPOINTMODE_H
15+
16+
#include "llvm/ADT/StringSwitch.h"
17+
18+
namespace llvm {
19+
20+
/// Represent handled modes for denormal (aka subnormal) modes in the floating
21+
/// point environment.
22+
enum class DenormalMode {
23+
Invalid = -1,
24+
25+
/// IEEE-754 denormal numbers preserved.
26+
IEEE,
27+
28+
/// The sign of a flushed-to-zero number is preserved in the sign of 0
29+
PreserveSign,
30+
31+
/// Denormals are flushed to positive zero.
32+
PositiveZero
33+
};
34+
35+
/// Parse the expected names from the denormal-fp-math attribute.
36+
inline DenormalMode parseDenormalFPAttribute(StringRef Str) {
37+
// Assume ieee on unspecified attribute.
38+
return StringSwitch<DenormalMode>(Str)
39+
.Cases("", "ieee", DenormalMode::IEEE)
40+
.Case("preserve-sign", DenormalMode::PreserveSign)
41+
.Case("positive-zero", DenormalMode::PositiveZero)
42+
.Default(DenormalMode::Invalid);
43+
}
44+
45+
/// Return the name used for the denormal handling mode used by the the
46+
/// expected names from the denormal-fp-math attribute.
47+
inline StringRef denormalModeName(DenormalMode Mode) {
48+
switch (Mode) {
49+
case DenormalMode::IEEE:
50+
return "ieee";
51+
case DenormalMode::PreserveSign:
52+
return "preserve-sign";
53+
case DenormalMode::PositiveZero:
54+
return "positive-zero";
55+
default:
56+
return "";
57+
}
58+
}
59+
60+
}
61+
62+
#endif // LLVM_FLOATINGPOINTMODE_H

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/ArrayRef.h"
2121
#include "llvm/ADT/BitVector.h"
2222
#include "llvm/ADT/DenseMap.h"
23+
#include "llvm/ADT/FloatingPointMode.h"
2324
#include "llvm/ADT/GraphTraits.h"
2425
#include "llvm/ADT/Optional.h"
2526
#include "llvm/ADT/SmallVector.h"
@@ -574,6 +575,10 @@ class MachineFunction {
574575
return const_cast<MachineFunction*>(this)->getInfo<Ty>();
575576
}
576577

578+
/// Returns the denormal handling type for the default rounding mode of the
579+
/// function.
580+
DenormalMode getDenormalMode(const fltSemantics &FPType) const;
581+
577582
/// getBlockNumbered - MachineBasicBlocks are automatically numbered when they
578583
/// are inserted into the machine function. The block number for a machine
579584
/// basic block can be found by using the MBB::getNumber method, this method

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,12 @@ class SelectionDAG {
17111711
return It->second.HeapAllocSite;
17121712
}
17131713

1714+
/// Return the current function's default denormal handling kind for the given
1715+
/// floating point type.
1716+
DenormalMode getDenormalMode(EVT VT) const {
1717+
return MF->getDenormalMode(EVTToAPFloatSemantics(VT));
1718+
}
1719+
17141720
private:
17151721
void InsertNode(SDNode *N);
17161722
bool RemoveNodeFromCSEMaps(SDNode *N);

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,21 @@ getOrCreateJumpTableInfo(unsigned EntryKind) {
270270
return JumpTableInfo;
271271
}
272272

273+
DenormalMode MachineFunction::getDenormalMode(const fltSemantics &FPType) const {
274+
// TODO: Should probably avoid the connection to the IR and store directly
275+
// in the MachineFunction.
276+
Attribute Attr = F.getFnAttribute("denormal-fp-math");
277+
278+
// FIXME: This should assume IEEE behavior on an unspecified
279+
// attribute. However, the one current user incorrectly assumes a non-IEEE
280+
// target by default.
281+
StringRef Val = Attr.getValueAsString();
282+
if (Val.empty())
283+
return DenormalMode::Invalid;
284+
285+
return parseDenormalFPAttribute(Val);
286+
}
287+
273288
/// Should we be emitting segmented stack stuff for the function
274289
bool MachineFunction::shouldSplitStack() const {
275290
return getFunction().hasFnAttribute("split-stack");

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20464,9 +20464,8 @@ SDValue DAGCombiner::buildSqrtEstimateImpl(SDValue Op, SDNodeFlags Flags,
2046420464
SDLoc DL(Op);
2046520465
EVT CCVT = getSetCCResultType(VT);
2046620466
ISD::NodeType SelOpcode = VT.isVector() ? ISD::VSELECT : ISD::SELECT;
20467-
const Function &F = DAG.getMachineFunction().getFunction();
20468-
Attribute Denorms = F.getFnAttribute("denormal-fp-math");
20469-
if (Denorms.getValueAsString().equals("ieee")) {
20467+
DenormalMode DenormMode = DAG.getDenormalMode(VT);
20468+
if (DenormMode == DenormalMode::IEEE) {
2047020469
// fabs(X) < SmallestNormal ? 0.0 : Est
2047120470
const fltSemantics &FltSem = DAG.EVTToAPFloatSemantics(VT);
2047220471
APFloat SmallestNorm = APFloat::getSmallestNormalized(FltSem);

llvm/unittests/ADT/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_llvm_unittest(ADTTests
2121
EnumeratedArrayTest.cpp
2222
EquivalenceClassesTest.cpp
2323
FallibleIteratorTest.cpp
24+
FloatingPointMode.cpp
2425
FoldingSet.cpp
2526
FunctionExtrasTest.cpp
2627
FunctionRefTest.cpp
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===- llvm/unittest/ADT/FloatingPointMode.cpp ----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/ADT/FloatingPointMode.h"
10+
#include "gtest/gtest.h"
11+
12+
using namespace llvm;
13+
14+
namespace {
15+
16+
TEST(FloatingPointModeTest, ParseDenormalFPAttribute) {
17+
EXPECT_EQ(DenormalMode::IEEE, parseDenormalFPAttribute("ieee"));
18+
EXPECT_EQ(DenormalMode::IEEE, parseDenormalFPAttribute(""));
19+
EXPECT_EQ(DenormalMode::PreserveSign,
20+
parseDenormalFPAttribute("preserve-sign"));
21+
EXPECT_EQ(DenormalMode::PositiveZero,
22+
parseDenormalFPAttribute("positive-zero"));
23+
EXPECT_EQ(DenormalMode::Invalid, parseDenormalFPAttribute("foo"));
24+
}
25+
26+
TEST(FloatingPointModeTest, DenormalAttributeName) {
27+
EXPECT_EQ("ieee", denormalModeName(DenormalMode::IEEE));
28+
EXPECT_EQ("preserve-sign", denormalModeName(DenormalMode::PreserveSign));
29+
EXPECT_EQ("positive-zero", denormalModeName(DenormalMode::PositiveZero));
30+
EXPECT_EQ("", denormalModeName(DenormalMode::Invalid));
31+
}
32+
33+
}

0 commit comments

Comments
 (0)