xref: /freebsd/contrib/llvm-project/llvm/include/llvm/IR/FMF.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/Compiler.h"
17 
18 namespace llvm {
19 class raw_ostream;
20 
21 /// Convenience struct for specifying and reasoning about fast-math flags.
22 class FastMathFlags {
23 private:
24   friend class FPMathOperator;
25 
26   unsigned Flags = 0;
27 
FastMathFlags(unsigned F)28   FastMathFlags(unsigned F) : Flags(F) {}
29 
30 public:
31   // This is how the bits are used in Value::SubclassOptionalData so they
32   // should fit there too.
33   // WARNING: We're out of space. SubclassOptionalData only has 7 bits. New
34   // functionality will require a change in how this information is stored.
35   enum {
36     AllowReassoc    = (1 << 0),
37     NoNaNs          = (1 << 1),
38     NoInfs          = (1 << 2),
39     NoSignedZeros   = (1 << 3),
40     AllowReciprocal = (1 << 4),
41     AllowContract   = (1 << 5),
42     ApproxFunc      = (1 << 6),
43     FlagEnd         = (1 << 7)
44   };
45 
46   constexpr static unsigned AllFlagsMask = FlagEnd - 1;
47 
48   FastMathFlags() = default;
49 
getFast()50   static FastMathFlags getFast() {
51     FastMathFlags FMF;
52     FMF.setFast();
53     return FMF;
54   }
55 
any()56   bool any() const { return Flags != 0; }
none()57   bool none() const { return Flags == 0; }
all()58   bool all() const { return Flags == AllFlagsMask; }
59 
clear()60   void clear() { Flags = 0; }
set()61   void set() { Flags = AllFlagsMask; }
62 
63   /// Flag queries
allowReassoc()64   bool allowReassoc() const    { return 0 != (Flags & AllowReassoc); }
noNaNs()65   bool noNaNs() const          { return 0 != (Flags & NoNaNs); }
noInfs()66   bool noInfs() const          { return 0 != (Flags & NoInfs); }
noSignedZeros()67   bool noSignedZeros() const   { return 0 != (Flags & NoSignedZeros); }
allowReciprocal()68   bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
allowContract()69   bool allowContract() const   { return 0 != (Flags & AllowContract); }
approxFunc()70   bool approxFunc() const      { return 0 != (Flags & ApproxFunc); }
71   /// 'Fast' means all bits are set.
isFast()72   bool isFast() const          { return all(); }
73 
74   /// Flag setters
75   void setAllowReassoc(bool B = true) {
76     Flags = (Flags & ~AllowReassoc) | B * AllowReassoc;
77   }
78   void setNoNaNs(bool B = true) {
79     Flags = (Flags & ~NoNaNs) | B * NoNaNs;
80   }
81   void setNoInfs(bool B = true) {
82     Flags = (Flags & ~NoInfs) | B * NoInfs;
83   }
84   void setNoSignedZeros(bool B = true) {
85     Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros;
86   }
87   void setAllowReciprocal(bool B = true) {
88     Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal;
89   }
90   void setAllowContract(bool B = true) {
91     Flags = (Flags & ~AllowContract) | B * AllowContract;
92   }
93   void setApproxFunc(bool B = true) {
94     Flags = (Flags & ~ApproxFunc) | B * ApproxFunc;
95   }
96   void setFast(bool B = true) { B ? set() : clear(); }
97 
98   void operator&=(const FastMathFlags &OtherFlags) {
99     Flags &= OtherFlags.Flags;
100   }
101   void operator|=(const FastMathFlags &OtherFlags) {
102     Flags |= OtherFlags.Flags;
103   }
104   bool operator!=(const FastMathFlags &OtherFlags) const {
105     return Flags != OtherFlags.Flags;
106   }
107 
108   /// Print fast-math flags to \p O.
109   LLVM_ABI void print(raw_ostream &O) const;
110 
111   /// Intersect rewrite-based flags
intersectRewrite(FastMathFlags LHS,FastMathFlags RHS)112   static inline FastMathFlags intersectRewrite(FastMathFlags LHS,
113                                                FastMathFlags RHS) {
114     const unsigned RewriteMask =
115         AllowReassoc | AllowReciprocal | AllowContract | ApproxFunc;
116     return FastMathFlags(RewriteMask & LHS.Flags & RHS.Flags);
117   }
118 
119   /// Union value flags
unionValue(FastMathFlags LHS,FastMathFlags RHS)120   static inline FastMathFlags unionValue(FastMathFlags LHS, FastMathFlags RHS) {
121     const unsigned ValueMask = NoNaNs | NoInfs | NoSignedZeros;
122     return FastMathFlags(ValueMask & (LHS.Flags | RHS.Flags));
123   }
124 };
125 
126 inline FastMathFlags operator|(FastMathFlags LHS, FastMathFlags RHS) {
127   LHS |= RHS;
128   return LHS;
129 }
130 
131 inline FastMathFlags operator&(FastMathFlags LHS, FastMathFlags RHS) {
132   LHS &= RHS;
133   return LHS;
134 }
135 
136 inline raw_ostream &operator<<(raw_ostream &O, FastMathFlags FMF) {
137   FMF.print(O);
138   return O;
139 }
140 
141 } // end namespace llvm
142 
143 #endif // LLVM_IR_FMF_H
144