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 | |
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 | |
51 | static FastMathFlags getFast() { |
52 | FastMathFlags FMF; |
53 | FMF.setFast(); |
54 | return FMF; |
55 | } |
56 | |
57 | bool any() const { return Flags != 0; } |
58 | bool none() const { return Flags == 0; } |
59 | bool all() const { return Flags == ~0U; } |
60 | |
61 | void clear() { Flags = 0; } |
62 | void set() { Flags = ~0U; } |
63 | |
64 | /// Flag queries |
65 | bool allowReassoc() const { return 0 != (Flags & AllowReassoc); } |
66 | bool noNaNs() const { return 0 != (Flags & NoNaNs); } |
67 | bool noInfs() const { return 0 != (Flags & NoInfs); } |
68 | bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } |
69 | bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } |
70 | bool allowContract() const { return 0 != (Flags & AllowContract); } |
71 | bool approxFunc() const { return 0 != (Flags & ApproxFunc); } |
72 | /// 'Fast' means all bits are set. |
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 | |