1 //===-- llvm/FMF.h - Fast math flags subclass -------------------*- 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 // This file defines the fast math flags.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_IR_FMF_H
14 #define LLVM_IR_FMF_H
15 
16 namespace llvm {
17 class raw_ostream;
18 
19 /// Convenience struct for specifying and reasoning about fast-math flags.
20 class FastMathFlags {
21 private:
22   friend class FPMathOperator;
23 
24   unsigned Flags = 0;
25 
FastMathFlags(unsigned F)26   FastMathFlags(unsigned F) {
27     // If all 7 bits are set, turn this into -1. If the number of bits grows,
28     // this must be updated. This is intended to provide some forward binary
29     // compatibility insurance for the meaning of 'fast' in case bits are added.
30     if (F == 0x7F) Flags = ~0U;
31     else Flags = F;
32   }
33 
34 public:
35   // This is how the bits are used in Value::SubclassOptionalData so they
36   // should fit there too.
37   // WARNING: We're out of space. SubclassOptionalData only has 7 bits. New
38   // functionality will require a change in how this information is stored.
39   enum {
40     AllowReassoc    = (1 << 0),
41     NoNaNs          = (1 << 1),
42     NoInfs          = (1 << 2),
43     NoSignedZeros   = (1 << 3),
44     AllowReciprocal = (1 << 4),
45     AllowContract   = (1 << 5),
46     ApproxFunc      = (1 << 6)
47   };
48 
49   FastMathFlags() = default;
50 
getFast()51   static FastMathFlags getFast() {
52     FastMathFlags FMF;
53     FMF.setFast();
54     return FMF;
55   }
56 
any()57   bool any() const { return Flags != 0; }
none()58   bool none() const { return Flags == 0; }
all()59   bool all() const { return Flags == ~0U; }
60 
clear()61   void clear() { Flags = 0; }
set()62   void set()   { Flags = ~0U; }
63 
64   /// Flag queries
allowReassoc()65   bool allowReassoc() const    { return 0 != (Flags & AllowReassoc); }
noNaNs()66   bool noNaNs() const          { return 0 != (Flags & NoNaNs); }
noInfs()67   bool noInfs() const          { return 0 != (Flags & NoInfs); }
noSignedZeros()68   bool noSignedZeros() const   { return 0 != (Flags & NoSignedZeros); }
allowReciprocal()69   bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
allowContract()70   bool allowContract() const   { return 0 != (Flags & AllowContract); }
approxFunc()71   bool approxFunc() const      { return 0 != (Flags & ApproxFunc); }
72   /// 'Fast' means all bits are set.
isFast()73   bool isFast() const          { return all(); }
74 
75   /// Flag setters
76   void setAllowReassoc(bool B = true) {
77     Flags = (Flags & ~AllowReassoc) | B * AllowReassoc;
78   }
79   void setNoNaNs(bool B = true) {
80     Flags = (Flags & ~NoNaNs) | B * NoNaNs;
81   }
82   void setNoInfs(bool B = true) {
83     Flags = (Flags & ~NoInfs) | B * NoInfs;
84   }
85   void setNoSignedZeros(bool B = true) {
86     Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros;
87   }
88   void setAllowReciprocal(bool B = true) {
89     Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal;
90   }
91   void setAllowContract(bool B = true) {
92     Flags = (Flags & ~AllowContract) | B * AllowContract;
93   }
94   void setApproxFunc(bool B = true) {
95     Flags = (Flags & ~ApproxFunc) | B * ApproxFunc;
96   }
97   void setFast(bool B = true) { B ? set() : clear(); }
98 
99   void operator&=(const FastMathFlags &OtherFlags) {
100     Flags &= OtherFlags.Flags;
101   }
102   void operator|=(const FastMathFlags &OtherFlags) {
103     Flags |= OtherFlags.Flags;
104   }
105   bool operator!=(const FastMathFlags &OtherFlags) const {
106     return Flags != OtherFlags.Flags;
107   }
108 
109   /// Print fast-math flags to \p O.
110   void print(raw_ostream &O) const;
111 };
112 
113 inline FastMathFlags operator|(FastMathFlags LHS, FastMathFlags RHS) {
114   LHS |= RHS;
115   return LHS;
116 }
117 
118 inline FastMathFlags operator&(FastMathFlags LHS, FastMathFlags RHS) {
119   LHS &= RHS;
120   return LHS;
121 }
122 
123 inline raw_ostream &operator<<(raw_ostream &O, FastMathFlags FMF) {
124   FMF.print(O);
125   return O;
126 }
127 
128 } // end namespace llvm
129 
130 #endif // LLVM_IR_FMF_H
131