Skip to content

[SDAG][NFC] Convert SDNodeFlags into an enumeration #114167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 73 additions & 86 deletions llvm/include/llvm/CodeGen/SelectionDAGNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,36 +378,48 @@ template<> struct simplify_type<SDUse> {
/// the backend.
struct SDNodeFlags {
private:
bool NoUnsignedWrap : 1;
bool NoSignedWrap : 1;
bool Exact : 1;
bool Disjoint : 1;
bool NonNeg : 1;
bool NoNaNs : 1;
bool NoInfs : 1;
bool NoSignedZeros : 1;
bool AllowReciprocal : 1;
bool AllowContract : 1;
bool ApproximateFuncs : 1;
bool AllowReassociation : 1;

// We assume instructions do not raise floating-point exceptions by default,
// and only those marked explicitly may do so. We could choose to represent
// this via a positive "FPExcept" flags like on the MI level, but having a
// negative "NoFPExcept" flag here makes the flag intersection logic more
// straightforward.
bool NoFPExcept : 1;
// Instructions with attached 'unpredictable' metadata on IR level.
bool Unpredictable : 1;
friend class SDNode;

unsigned Flags = 0;

template <unsigned Flag> void setFlag(bool B) {
Flags = (Flags & ~Flag) | (B ? Flag : 0);
}

public:
enum : unsigned {
None = 0,
NoUnsignedWrap = 1 << 0,
NoSignedWrap = 1 << 1,
Exact = 1 << 2,
Disjoint = 1 << 3,
NonNeg = 1 << 4,
NoNaNs = 1 << 5,
NoInfs = 1 << 6,
NoSignedZeros = 1 << 7,
AllowReciprocal = 1 << 8,
AllowContract = 1 << 9,
ApproximateFuncs = 1 << 10,
AllowReassociation = 1 << 11,

// We assume instructions do not raise floating-point exceptions by default,
// and only those marked explicitly may do so. We could choose to represent
// this via a positive "FPExcept" flags like on the MI level, but having a
// negative "NoFPExcept" flag here makes the flag intersection logic more
// straightforward.
NoFPExcept = 1 << 12,
// Instructions with attached 'unpredictable' metadata on IR level.
Unpredictable = 1 << 13,

// NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
// the class definition when adding new flags.

PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
NonNeg | NoNaNs | NoInfs,
};

/// Default constructor turns off all optimization flags.
SDNodeFlags()
: NoUnsignedWrap(false), NoSignedWrap(false), Exact(false),
Disjoint(false), NonNeg(false), NoNaNs(false), NoInfs(false),
NoSignedZeros(false), AllowReciprocal(false), AllowContract(false),
ApproximateFuncs(false), AllowReassociation(false), NoFPExcept(false),
Unpredictable(false) {}
SDNodeFlags() : Flags(0) {}

/// Propagate the fast-math-flags from an IR FPMathOperator.
void copyFMF(const FPMathOperator &FPMO) {
Expand All @@ -421,71 +433,49 @@ struct SDNodeFlags {
}

// These are mutators for each flag.
void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
void setNoSignedWrap(bool b) { NoSignedWrap = b; }
void setExact(bool b) { Exact = b; }
void setDisjoint(bool b) { Disjoint = b; }
void setNonNeg(bool b) { NonNeg = b; }
void setNoNaNs(bool b) { NoNaNs = b; }
void setNoInfs(bool b) { NoInfs = b; }
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
void setAllowContract(bool b) { AllowContract = b; }
void setApproximateFuncs(bool b) { ApproximateFuncs = b; }
void setAllowReassociation(bool b) { AllowReassociation = b; }
void setNoFPExcept(bool b) { NoFPExcept = b; }
void setUnpredictable(bool b) { Unpredictable = b; }
void setNoUnsignedWrap(bool b) { setFlag<NoUnsignedWrap>(b); }
void setNoSignedWrap(bool b) { setFlag<NoSignedWrap>(b); }
void setExact(bool b) { setFlag<Exact>(b); }
void setDisjoint(bool b) { setFlag<Disjoint>(b); }
void setNonNeg(bool b) { setFlag<NonNeg>(b); }
void setNoNaNs(bool b) { setFlag<NoNaNs>(b); }
void setNoInfs(bool b) { setFlag<NoInfs>(b); }
void setNoSignedZeros(bool b) { setFlag<NoSignedZeros>(b); }
void setAllowReciprocal(bool b) { setFlag<AllowReciprocal>(b); }
void setAllowContract(bool b) { setFlag<AllowContract>(b); }
void setApproximateFuncs(bool b) { setFlag<ApproximateFuncs>(b); }
void setAllowReassociation(bool b) { setFlag<AllowReassociation>(b); }
void setNoFPExcept(bool b) { setFlag<NoFPExcept>(b); }
void setUnpredictable(bool b) { setFlag<Unpredictable>(b); }

// These are accessors for each flag.
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
bool hasNoSignedWrap() const { return NoSignedWrap; }
bool hasExact() const { return Exact; }
bool hasDisjoint() const { return Disjoint; }
bool hasNonNeg() const { return NonNeg; }
bool hasNoNaNs() const { return NoNaNs; }
bool hasNoInfs() const { return NoInfs; }
bool hasNoSignedZeros() const { return NoSignedZeros; }
bool hasAllowReciprocal() const { return AllowReciprocal; }
bool hasAllowContract() const { return AllowContract; }
bool hasApproximateFuncs() const { return ApproximateFuncs; }
bool hasAllowReassociation() const { return AllowReassociation; }
bool hasNoFPExcept() const { return NoFPExcept; }
bool hasUnpredictable() const { return Unpredictable; }
bool hasNoUnsignedWrap() const { return Flags & NoUnsignedWrap; }
bool hasNoSignedWrap() const { return Flags & NoSignedWrap; }
bool hasExact() const { return Flags & Exact; }
bool hasDisjoint() const { return Flags & Disjoint; }
bool hasNonNeg() const { return Flags & NonNeg; }
bool hasNoNaNs() const { return Flags & NoNaNs; }
bool hasNoInfs() const { return Flags & NoInfs; }
bool hasNoSignedZeros() const { return Flags & NoSignedZeros; }
bool hasAllowReciprocal() const { return Flags & AllowReciprocal; }
bool hasAllowContract() const { return Flags & AllowContract; }
bool hasApproximateFuncs() const { return Flags & ApproximateFuncs; }
bool hasAllowReassociation() const { return Flags & AllowReassociation; }
bool hasNoFPExcept() const { return Flags & NoFPExcept; }
bool hasUnpredictable() const { return Flags & Unpredictable; }

bool operator==(const SDNodeFlags &Other) const {
return NoUnsignedWrap == Other.NoUnsignedWrap &&
NoSignedWrap == Other.NoSignedWrap && Exact == Other.Exact &&
Disjoint == Other.Disjoint && NonNeg == Other.NonNeg &&
NoNaNs == Other.NoNaNs && NoInfs == Other.NoInfs &&
NoSignedZeros == Other.NoSignedZeros &&
AllowReciprocal == Other.AllowReciprocal &&
AllowContract == Other.AllowContract &&
ApproximateFuncs == Other.ApproximateFuncs &&
AllowReassociation == Other.AllowReassociation &&
NoFPExcept == Other.NoFPExcept &&
Unpredictable == Other.Unpredictable;
return Flags == Other.Flags;
}

/// Clear any flags in this flag set that aren't also set in Flags. All
/// flags will be cleared if Flags are undefined.
void intersectWith(const SDNodeFlags Flags) {
NoUnsignedWrap &= Flags.NoUnsignedWrap;
NoSignedWrap &= Flags.NoSignedWrap;
Exact &= Flags.Exact;
Disjoint &= Flags.Disjoint;
NonNeg &= Flags.NonNeg;
NoNaNs &= Flags.NoNaNs;
NoInfs &= Flags.NoInfs;
NoSignedZeros &= Flags.NoSignedZeros;
AllowReciprocal &= Flags.AllowReciprocal;
AllowContract &= Flags.AllowContract;
ApproximateFuncs &= Flags.ApproximateFuncs;
AllowReassociation &= Flags.AllowReassociation;
NoFPExcept &= Flags.NoFPExcept;
Unpredictable &= Flags.Unpredictable;
}
void intersectWith(const SDNodeFlags Flags) { this->Flags &= Flags.Flags; }
};

LLVM_DECLARE_ENUM_AS_BITMASK(decltype(SDNodeFlags::None),
SDNodeFlags::Unpredictable);

/// Represents one node in the SelectionDAG.
///
class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
Expand Down Expand Up @@ -1029,10 +1019,7 @@ END_TWO_BYTE_PACK()
void intersectFlagsWith(const SDNodeFlags Flags);

bool hasPoisonGeneratingFlags() const {
SDNodeFlags Flags = getFlags();
return Flags.hasNoUnsignedWrap() || Flags.hasNoSignedWrap() ||
Flags.hasExact() || Flags.hasDisjoint() || Flags.hasNonNeg() ||
Flags.hasNoNaNs() || Flags.hasNoInfs();
return Flags.Flags & SDNodeFlags::PoisonGeneratingFlags;
}

void setCFIType(uint32_t Type) { CFIType = Type; }
Expand Down
Loading