xref: /freebsd/contrib/llvm-project/llvm/lib/Support/FloatingPointMode.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
106c3fb27SDimitry Andric //===- FloatingPointMode.cpp ------------------------------------*- C++ -*-===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "llvm/ADT/FloatingPointMode.h"
1006c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric using namespace llvm;
1306c3fb27SDimitry Andric 
1406c3fb27SDimitry Andric FPClassTest llvm::fneg(FPClassTest Mask) {
1506c3fb27SDimitry Andric   FPClassTest NewMask = Mask & fcNan;
1606c3fb27SDimitry Andric   if (Mask & fcNegInf)
1706c3fb27SDimitry Andric     NewMask |= fcPosInf;
1806c3fb27SDimitry Andric   if (Mask & fcNegNormal)
1906c3fb27SDimitry Andric     NewMask |= fcPosNormal;
2006c3fb27SDimitry Andric   if (Mask & fcNegSubnormal)
2106c3fb27SDimitry Andric     NewMask |= fcPosSubnormal;
2206c3fb27SDimitry Andric   if (Mask & fcNegZero)
2306c3fb27SDimitry Andric     NewMask |= fcPosZero;
2406c3fb27SDimitry Andric   if (Mask & fcPosZero)
2506c3fb27SDimitry Andric     NewMask |= fcNegZero;
2606c3fb27SDimitry Andric   if (Mask & fcPosSubnormal)
2706c3fb27SDimitry Andric     NewMask |= fcNegSubnormal;
2806c3fb27SDimitry Andric   if (Mask & fcPosNormal)
2906c3fb27SDimitry Andric     NewMask |= fcNegNormal;
3006c3fb27SDimitry Andric   if (Mask & fcPosInf)
3106c3fb27SDimitry Andric     NewMask |= fcNegInf;
3206c3fb27SDimitry Andric   return NewMask;
3306c3fb27SDimitry Andric }
3406c3fb27SDimitry Andric 
35*5f757f3fSDimitry Andric FPClassTest llvm::inverse_fabs(FPClassTest Mask) {
3606c3fb27SDimitry Andric   FPClassTest NewMask = Mask & fcNan;
3706c3fb27SDimitry Andric   if (Mask & fcPosZero)
3806c3fb27SDimitry Andric     NewMask |= fcZero;
3906c3fb27SDimitry Andric   if (Mask & fcPosSubnormal)
4006c3fb27SDimitry Andric     NewMask |= fcSubnormal;
4106c3fb27SDimitry Andric   if (Mask & fcPosNormal)
4206c3fb27SDimitry Andric     NewMask |= fcNormal;
4306c3fb27SDimitry Andric   if (Mask & fcPosInf)
4406c3fb27SDimitry Andric     NewMask |= fcInf;
4506c3fb27SDimitry Andric   return NewMask;
4606c3fb27SDimitry Andric }
4706c3fb27SDimitry Andric 
48*5f757f3fSDimitry Andric FPClassTest llvm::unknown_sign(FPClassTest Mask) {
49*5f757f3fSDimitry Andric   FPClassTest NewMask = Mask & fcNan;
50*5f757f3fSDimitry Andric   if (Mask & fcZero)
51*5f757f3fSDimitry Andric     NewMask |= fcZero;
52*5f757f3fSDimitry Andric   if (Mask & fcSubnormal)
53*5f757f3fSDimitry Andric     NewMask |= fcSubnormal;
54*5f757f3fSDimitry Andric   if (Mask & fcNormal)
55*5f757f3fSDimitry Andric     NewMask |= fcNormal;
56*5f757f3fSDimitry Andric   if (Mask & fcInf)
57*5f757f3fSDimitry Andric     NewMask |= fcInf;
58*5f757f3fSDimitry Andric   return NewMask;
59*5f757f3fSDimitry Andric }
60*5f757f3fSDimitry Andric 
6106c3fb27SDimitry Andric // Every bitfield has a unique name and one or more aliasing names that cover
6206c3fb27SDimitry Andric // multiple bits. Names should be listed in order of preference, with higher
6306c3fb27SDimitry Andric // popcounts listed first.
6406c3fb27SDimitry Andric //
6506c3fb27SDimitry Andric // Bits are consumed as printed. Each field should only be represented in one
6606c3fb27SDimitry Andric // printed field.
6706c3fb27SDimitry Andric static constexpr std::pair<FPClassTest, StringLiteral> NoFPClassName[] = {
6806c3fb27SDimitry Andric   {fcAllFlags, "all"},
6906c3fb27SDimitry Andric   {fcNan, "nan"},
7006c3fb27SDimitry Andric   {fcSNan, "snan"},
7106c3fb27SDimitry Andric   {fcQNan, "qnan"},
7206c3fb27SDimitry Andric   {fcInf, "inf"},
7306c3fb27SDimitry Andric   {fcNegInf, "ninf"},
7406c3fb27SDimitry Andric   {fcPosInf, "pinf"},
7506c3fb27SDimitry Andric   {fcZero, "zero"},
7606c3fb27SDimitry Andric   {fcNegZero, "nzero"},
7706c3fb27SDimitry Andric   {fcPosZero, "pzero"},
7806c3fb27SDimitry Andric   {fcSubnormal, "sub"},
7906c3fb27SDimitry Andric   {fcNegSubnormal, "nsub"},
8006c3fb27SDimitry Andric   {fcPosSubnormal, "psub"},
8106c3fb27SDimitry Andric   {fcNormal, "norm"},
8206c3fb27SDimitry Andric   {fcNegNormal, "nnorm"},
8306c3fb27SDimitry Andric   {fcPosNormal, "pnorm"}
8406c3fb27SDimitry Andric };
8506c3fb27SDimitry Andric 
8606c3fb27SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, FPClassTest Mask) {
8706c3fb27SDimitry Andric   OS << '(';
8806c3fb27SDimitry Andric 
8906c3fb27SDimitry Andric   if (Mask == fcNone) {
9006c3fb27SDimitry Andric     OS << "none)";
9106c3fb27SDimitry Andric     return OS;
9206c3fb27SDimitry Andric   }
9306c3fb27SDimitry Andric 
9406c3fb27SDimitry Andric   ListSeparator LS(" ");
9506c3fb27SDimitry Andric   for (auto [BitTest, Name] : NoFPClassName) {
9606c3fb27SDimitry Andric     if ((Mask & BitTest) == BitTest) {
9706c3fb27SDimitry Andric       OS << LS << Name;
9806c3fb27SDimitry Andric 
9906c3fb27SDimitry Andric       // Clear the bits so we don't print any aliased names later.
10006c3fb27SDimitry Andric       Mask &= ~BitTest;
10106c3fb27SDimitry Andric     }
10206c3fb27SDimitry Andric   }
10306c3fb27SDimitry Andric 
10406c3fb27SDimitry Andric   assert(Mask == 0 && "didn't print some mask bits");
10506c3fb27SDimitry Andric 
10606c3fb27SDimitry Andric   OS << ')';
10706c3fb27SDimitry Andric   return OS;
10806c3fb27SDimitry Andric }
109