blob: a49feb5a8946433500cfa0a4815a3a9076b30966 [file] [log] [blame]
//===-- llvm/FMF.h - Fast math flags subclass -------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the fast math flags.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_FMF_H
#define LLVM_IR_FMF_H
#include "llvm/Support/raw_ostream.h"
namespace llvm {
/// Convenience struct for specifying and reasoning about fast-math flags.
class FastMathFlags {
private:
friend class FPMathOperator;
unsigned Flags = 0;
FastMathFlags(unsigned F) {
// If all 7 bits are set, turn this into -1. If the number of bits grows,
// this must be updated. This is intended to provide some forward binary
// compatibility insurance for the meaning of 'fast' in case bits are added.
if (F == 0x7F) Flags = ~0U;
else Flags = F;
}
public:
// This is how the bits are used in Value::SubclassOptionalData so they
// should fit there too.
// WARNING: We're out of space. SubclassOptionalData only has 7 bits. New
// functionality will require a change in how this information is stored.
enum {
AllowReassoc = (1 << 0),
NoNaNs = (1 << 1),
NoInfs = (1 << 2),
NoSignedZeros = (1 << 3),
AllowReciprocal = (1 << 4),
AllowContract = (1 << 5),
ApproxFunc = (1 << 6)
};
FastMathFlags() = default;
static FastMathFlags getFast() {
FastMathFlags FMF;
FMF.setFast();
return FMF;
}
bool any() const { return Flags != 0; }
bool none() const { return Flags == 0; }
bool all() const { return Flags == ~0U; }
void clear() { Flags = 0; }
void set() { Flags = ~0U; }
/// Flag queries
bool allowReassoc() const { return 0 != (Flags & AllowReassoc); }
bool noNaNs() const { return 0 != (Flags & NoNaNs); }
bool noInfs() const { return 0 != (Flags & NoInfs); }
bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); }
bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
bool allowContract() const { return 0 != (Flags & AllowContract); }
bool approxFunc() const { return 0 != (Flags & ApproxFunc); }
/// 'Fast' means all bits are set.
bool isFast() const { return all(); }
/// Flag setters
void setAllowReassoc(bool B = true) {
Flags = (Flags & ~AllowReassoc) | B * AllowReassoc;
}
void setNoNaNs(bool B = true) {
Flags = (Flags & ~NoNaNs) | B * NoNaNs;
}
void setNoInfs(bool B = true) {
Flags = (Flags & ~NoInfs) | B * NoInfs;
}
void setNoSignedZeros(bool B = true) {
Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros;
}
void setAllowReciprocal(bool B = true) {
Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal;
}
void setAllowContract(bool B = true) {
Flags = (Flags & ~AllowContract) | B * AllowContract;
}
void setApproxFunc(bool B = true) {
Flags = (Flags & ~ApproxFunc) | B * ApproxFunc;
}
void setFast(bool B = true) { B ? set() : clear(); }
void operator&=(const FastMathFlags &OtherFlags) {
Flags &= OtherFlags.Flags;
}
void operator|=(const FastMathFlags &OtherFlags) {
Flags |= OtherFlags.Flags;
}
bool operator!=(const FastMathFlags &OtherFlags) const {
return Flags != OtherFlags.Flags;
}
/// Print fast-math flags to \p O.
void print(raw_ostream &O) const;
};
inline raw_ostream &operator<<(raw_ostream &O, FastMathFlags FMF) {
FMF.print(O);
return O;
}
} // end namespace llvm
#endif // LLVM_IR_FMF_H