xref: /freebsd/contrib/llvm-project/llvm/lib/Support/FloatingPointMode.cpp (revision a90b9d0159070121c221b966469c3e36d912bf82)
1 //===- FloatingPointMode.cpp ------------------------------------*- 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 #include "llvm/ADT/FloatingPointMode.h"
10 #include "llvm/ADT/StringExtras.h"
11 
12 using namespace llvm;
13 
14 FPClassTest llvm::fneg(FPClassTest Mask) {
15   FPClassTest NewMask = Mask & fcNan;
16   if (Mask & fcNegInf)
17     NewMask |= fcPosInf;
18   if (Mask & fcNegNormal)
19     NewMask |= fcPosNormal;
20   if (Mask & fcNegSubnormal)
21     NewMask |= fcPosSubnormal;
22   if (Mask & fcNegZero)
23     NewMask |= fcPosZero;
24   if (Mask & fcPosZero)
25     NewMask |= fcNegZero;
26   if (Mask & fcPosSubnormal)
27     NewMask |= fcNegSubnormal;
28   if (Mask & fcPosNormal)
29     NewMask |= fcNegNormal;
30   if (Mask & fcPosInf)
31     NewMask |= fcNegInf;
32   return NewMask;
33 }
34 
35 FPClassTest llvm::inverse_fabs(FPClassTest Mask) {
36   FPClassTest NewMask = Mask & fcNan;
37   if (Mask & fcPosZero)
38     NewMask |= fcZero;
39   if (Mask & fcPosSubnormal)
40     NewMask |= fcSubnormal;
41   if (Mask & fcPosNormal)
42     NewMask |= fcNormal;
43   if (Mask & fcPosInf)
44     NewMask |= fcInf;
45   return NewMask;
46 }
47 
48 FPClassTest llvm::unknown_sign(FPClassTest Mask) {
49   FPClassTest NewMask = Mask & fcNan;
50   if (Mask & fcZero)
51     NewMask |= fcZero;
52   if (Mask & fcSubnormal)
53     NewMask |= fcSubnormal;
54   if (Mask & fcNormal)
55     NewMask |= fcNormal;
56   if (Mask & fcInf)
57     NewMask |= fcInf;
58   return NewMask;
59 }
60 
61 // Every bitfield has a unique name and one or more aliasing names that cover
62 // multiple bits. Names should be listed in order of preference, with higher
63 // popcounts listed first.
64 //
65 // Bits are consumed as printed. Each field should only be represented in one
66 // printed field.
67 static constexpr std::pair<FPClassTest, StringLiteral> NoFPClassName[] = {
68   {fcAllFlags, "all"},
69   {fcNan, "nan"},
70   {fcSNan, "snan"},
71   {fcQNan, "qnan"},
72   {fcInf, "inf"},
73   {fcNegInf, "ninf"},
74   {fcPosInf, "pinf"},
75   {fcZero, "zero"},
76   {fcNegZero, "nzero"},
77   {fcPosZero, "pzero"},
78   {fcSubnormal, "sub"},
79   {fcNegSubnormal, "nsub"},
80   {fcPosSubnormal, "psub"},
81   {fcNormal, "norm"},
82   {fcNegNormal, "nnorm"},
83   {fcPosNormal, "pnorm"}
84 };
85 
86 raw_ostream &llvm::operator<<(raw_ostream &OS, FPClassTest Mask) {
87   OS << '(';
88 
89   if (Mask == fcNone) {
90     OS << "none)";
91     return OS;
92   }
93 
94   ListSeparator LS(" ");
95   for (auto [BitTest, Name] : NoFPClassName) {
96     if ((Mask & BitTest) == BitTest) {
97       OS << LS << Name;
98 
99       // Clear the bits so we don't print any aliased names later.
100       Mask &= ~BitTest;
101     }
102   }
103 
104   assert(Mask == 0 && "didn't print some mask bits");
105 
106   OS << ')';
107   return OS;
108 }
109