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