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