//===-- 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