| //===-- llvm/FMF.h - Fast math flags subclass -------------------*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the fast math flags. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_IR_FMF_H |
| #define LLVM_IR_FMF_H |
| |
| #include "llvm/Support/raw_ostream.h" |
| |
| namespace llvm { |
| |
| /// Convenience struct for specifying and reasoning about fast-math flags. |
| class FastMathFlags { |
| private: |
| friend class FPMathOperator; |
| |
| unsigned Flags = 0; |
| |
| FastMathFlags(unsigned F) { |
| // If all 7 bits are set, turn this into -1. If the number of bits grows, |
| // this must be updated. This is intended to provide some forward binary |
| // compatibility insurance for the meaning of 'fast' in case bits are added. |
| if (F == 0x7F) Flags = ~0U; |
| else Flags = F; |
| } |
| |
| public: |
| // This is how the bits are used in Value::SubclassOptionalData so they |
| // should fit there too. |
| // WARNING: We're out of space. SubclassOptionalData only has 7 bits. New |
| // functionality will require a change in how this information is stored. |
| enum { |
| AllowReassoc = (1 << 0), |
| NoNaNs = (1 << 1), |
| NoInfs = (1 << 2), |
| NoSignedZeros = (1 << 3), |
| AllowReciprocal = (1 << 4), |
| AllowContract = (1 << 5), |
| ApproxFunc = (1 << 6) |
| }; |
| |
| FastMathFlags() = default; |
| |
| static FastMathFlags getFast() { |
| FastMathFlags FMF; |
| FMF.setFast(); |
| return FMF; |
| } |
| |
| bool any() const { return Flags != 0; } |
| bool none() const { return Flags == 0; } |
| bool all() const { return Flags == ~0U; } |
| |
| void clear() { Flags = 0; } |
| void set() { Flags = ~0U; } |
| |
| /// Flag queries |
| bool allowReassoc() const { return 0 != (Flags & AllowReassoc); } |
| bool noNaNs() const { return 0 != (Flags & NoNaNs); } |
| bool noInfs() const { return 0 != (Flags & NoInfs); } |
| bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } |
| bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } |
| bool allowContract() const { return 0 != (Flags & AllowContract); } |
| bool approxFunc() const { return 0 != (Flags & ApproxFunc); } |
| /// 'Fast' means all bits are set. |
| bool isFast() const { return all(); } |
| |
| /// Flag setters |
| void setAllowReassoc(bool B = true) { |
| Flags = (Flags & ~AllowReassoc) | B * AllowReassoc; |
| } |
| void setNoNaNs(bool B = true) { |
| Flags = (Flags & ~NoNaNs) | B * NoNaNs; |
| } |
| void setNoInfs(bool B = true) { |
| Flags = (Flags & ~NoInfs) | B * NoInfs; |
| } |
| void setNoSignedZeros(bool B = true) { |
| Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros; |
| } |
| void setAllowReciprocal(bool B = true) { |
| Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal; |
| } |
| void setAllowContract(bool B = true) { |
| Flags = (Flags & ~AllowContract) | B * AllowContract; |
| } |
| void setApproxFunc(bool B = true) { |
| Flags = (Flags & ~ApproxFunc) | B * ApproxFunc; |
| } |
| void setFast(bool B = true) { B ? set() : clear(); } |
| |
| void operator&=(const FastMathFlags &OtherFlags) { |
| Flags &= OtherFlags.Flags; |
| } |
| void operator|=(const FastMathFlags &OtherFlags) { |
| Flags |= OtherFlags.Flags; |
| } |
| bool operator!=(const FastMathFlags &OtherFlags) const { |
| return Flags != OtherFlags.Flags; |
| } |
| |
| /// Print fast-math flags to \p O. |
| void print(raw_ostream &O) const; |
| }; |
| |
| inline raw_ostream &operator<<(raw_ostream &O, FastMathFlags FMF) { |
| FMF.print(O); |
| return O; |
| } |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_IR_FMF_H |