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