LLVM 22.0.0git
KnownFPClass.h
Go to the documentation of this file.
1//===- llvm/Support/KnownFPClass.h - Stores known fpclass -------*- 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 contains a class for representing known fpclasses used by
10// computeKnownFPClass.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_KNOWNFPCLASS_H
15#define LLVM_SUPPORT_KNOWNFPCLASS_H
16
19#include <optional>
20
21namespace llvm {
22class APFloat;
23
25 /// Floating-point classes the value could be one of.
27
28 /// std::nullopt if the sign bit is unknown, true if the sign bit is
29 /// definitely set or false if the sign bit is definitely unset.
30 std::optional<bool> SignBit;
31
32 KnownFPClass(FPClassTest Known = fcAllFlags, std::optional<bool> Sign = {})
33 : KnownFPClasses(Known), SignBit(Sign) {}
34 KnownFPClass(const APFloat &C);
35
37 return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
38 }
39
40 /// Return true if it's known this can never be one of the mask entries.
41 bool isKnownNever(FPClassTest Mask) const {
42 return (KnownFPClasses & Mask) == fcNone;
43 }
44
45 bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
46
47 bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; }
48
49 /// Return true if it's known this can never be a nan.
50 bool isKnownNeverNaN() const { return isKnownNever(fcNan); }
51
52 /// Return true if it's known this must always be a nan.
53 bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
54
55 /// Return true if it's known this can never be an infinity.
56 bool isKnownNeverInfinity() const { return isKnownNever(fcInf); }
57
58 /// Return true if it's known this can never be an infinity or nan
59 bool isKnownNeverInfOrNaN() const { return isKnownNever(fcInf | fcNan); }
60
61 /// Return true if it's known this can never be +infinity.
63
64 /// Return true if it's known this can never be -infinity.
66
67 /// Return true if it's known this can never be a subnormal
69
70 /// Return true if it's known this can never be a positive subnormal
72
73 /// Return true if it's known this can never be a negative subnormal
75
76 /// Return true if it's known this can never be a zero. This means a literal
77 /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
78 bool isKnownNeverZero() const { return isKnownNever(fcZero); }
79
80 /// Return true if it's known this can never be a literal positive zero.
81 bool isKnownNeverPosZero() const { return isKnownNever(fcPosZero); }
82
83 /// Return true if it's known this can never be a negative zero. This means a
84 /// literal -0 and does not include denormal inputs implicitly treated as -0.
85 bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); }
86
87 /// Return true if it's known this can never be interpreted as a zero. This
88 /// extends isKnownNeverZero to cover the case where the assumed
89 /// floating-point mode for the function interprets denormals as zero.
91
92 /// Return true if it's known this can never be interpreted as a negative
93 /// zero.
95
96 /// Return true if it's known this can never be interpreted as a positive
97 /// zero.
99
104
105 /// Return true if we can prove that the analyzed floating-point value is
106 /// either NaN or never less than -0.0.
107 ///
108 /// NaN --> true
109 /// +0 --> true
110 /// -0 --> true
111 /// x > +0 --> true
112 /// x < -0 --> false
116
117 /// Return true if we can prove that the analyzed floating-point value is
118 /// either NaN or never greater than -0.0.
119 /// NaN --> true
120 /// +0 --> true
121 /// -0 --> true
122 /// x > +0 --> false
123 /// x < -0 --> true
127
128 /// Return true if it's know this can never be a negative value or a logical
129 /// 0.
130 ///
131 /// NaN --> true
132 /// x >= -0 --> false
133 /// nsub --> true if mode is ieee, false otherwise.
134 /// x < -0 --> true
138
140 return KnownFPClass(~(~KnownFPClasses & ~RHS.KnownFPClasses),
141 SignBit == RHS.SignBit ? SignBit : std::nullopt);
142 }
143
145 KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
146
147 if (SignBit != RHS.SignBit)
148 SignBit = std::nullopt;
149 return *this;
150 }
151
152 void knownNot(FPClassTest RuleOut) {
153 KnownFPClasses = KnownFPClasses & ~RuleOut;
154 if (isKnownNever(fcNan) && !SignBit) {
156 SignBit = false;
157 else if (isKnownNever(fcPositive))
158 SignBit = true;
159 }
160 }
161
162 void fneg() {
164 if (SignBit)
165 SignBit = !*SignBit;
166 }
167
183
184 // Enum of min/max intrinsics to avoid dependency on IR.
193
197
198 /// Apply the canonicalize intrinsic to this value. This is essentially a
199 /// stronger form of propagateCanonicalizingSrc.
201 canonicalize(const KnownFPClass &Src,
203
204 /// Report known values for fmul
206 fmul(const KnownFPClass &LHS, const KnownFPClass &RHS,
208
209 // Special case of fmul x, x.
212 KnownFPClass Known = fmul(Src, Src, Mode);
213
214 // X * X is always non-negative or a NaN.
215 Known.knownNot(fcNegative);
216 return Known;
217 }
218
219 /// Report known values for exp, exp2 and exp10.
220 LLVM_ABI static KnownFPClass exp(const KnownFPClass &Src);
221
222 /// Return true if the sign bit must be 0, ignoring the sign of nans.
224
225 /// Assume the sign bit is zero.
228 SignBit = false;
229 }
230
231 /// Assume the sign bit is one.
234 SignBit = true;
235 }
236
237 void copysign(const KnownFPClass &Sign) {
238 // Don't know anything about the sign of the source. Expand the possible set
239 // to its opposite sign pair.
246 if (KnownFPClasses & fcInf)
248
249 // Sign bit is exactly preserved even for nans.
250 SignBit = Sign.SignBit;
251
252 // Clear sign bits based on the input sign mask.
253 if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
255 if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
257 }
258
259 // Propagate knowledge that a non-NaN source implies the result can also not
260 // be a NaN. For unconstrained operations, signaling nans are not guaranteed
261 // to be quieted but cannot be introduced.
262 void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
263 if (Src.isKnownNever(fcNan)) {
265 if (PreserveSign)
266 SignBit = Src.SignBit;
267 } else if (Src.isKnownNever(fcSNan))
269 }
270
271 /// Propagate knowledge from a source value that could be a denormal or
272 /// zero. We have to be conservative since output flushing is not guaranteed,
273 /// so known-never-zero may not hold.
274 ///
275 /// This assumes a copy-like operation and will replace any currently known
276 /// information.
278
279 /// Report known classes if \p Src is evaluated through a potentially
280 /// canonicalizing operation. We can assume signaling nans will not be
281 /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
282 ///
283 /// This assumes a copy-like operation and will replace any currently known
284 /// information.
287
288 /// Propagate known class for log/log2/log10
291
292 void resetAll() { *this = KnownFPClass(); }
293};
294
296 LHS |= RHS;
297 return LHS;
298}
299
301 RHS |= LHS;
302 return std::move(RHS);
303}
304
305} // namespace llvm
306
307#endif
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:213
Utilities for dealing with flags related to floating point properties and mode controls.
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Value * RHS
Value * LHS
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
LLVM_ABI FPClassTest fneg(FPClassTest Mask)
Return the test mask which returns true if the value's sign bit is flipped.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
@ Other
Any other memory.
Definition ModRef.h:68
APInt operator|(APInt a, const APInt &b)
Definition APInt.h:2144
Represent subnormal handling kind for floating point instruction inputs and outputs.
static constexpr DenormalMode getDynamic()
bool isKnownNeverInfOrNaN() const
Return true if it's known this can never be an infinity or nan.
bool isKnownAlwaysNaN() const
Return true if it's known this must always be a nan.
FPClassTest KnownFPClasses
Floating-point classes the value could be one of.
bool isKnownNeverInfinity() const
Return true if it's known this can never be an infinity.
KnownFPClass(FPClassTest Known=fcAllFlags, std::optional< bool > Sign={})
bool cannotBeOrderedGreaterThanZero() const
Return true if we can prove that the analyzed floating-point value is either NaN or never greater tha...
static constexpr FPClassTest OrderedGreaterThanZeroMask
static constexpr FPClassTest OrderedLessThanZeroMask
void knownNot(FPClassTest RuleOut)
static LLVM_ABI KnownFPClass fmul(const KnownFPClass &LHS, const KnownFPClass &RHS, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fmul.
bool isKnownNeverZero() const
Return true if it's known this can never be a zero.
void copysign(const KnownFPClass &Sign)
static KnownFPClass square(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
bool isKnownNeverSubnormal() const
Return true if it's known this can never be a subnormal.
bool isKnownAlways(FPClassTest Mask) const
static LLVM_ABI KnownFPClass canonicalize(const KnownFPClass &Src, DenormalMode DenormMode=DenormalMode::getDynamic())
Apply the canonicalize intrinsic to this value.
LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a zero.
static LLVM_ABI KnownFPClass log(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Propagate known class for log/log2/log10.
LLVM_ABI void propagateDenormal(const KnownFPClass &Src, DenormalMode Mode)
Propagate knowledge from a source value that could be a denormal or zero.
KnownFPClass & operator|=(const KnownFPClass &RHS)
KnownFPClass intersectWith(const KnownFPClass &RHS)
static LLVM_ABI KnownFPClass minMaxLike(const KnownFPClass &LHS, const KnownFPClass &RHS, MinMaxKind Kind, DenormalMode DenormMode=DenormalMode::getDynamic())
bool isUnknown() const
bool isKnownNeverNegInfinity() const
Return true if it's known this can never be -infinity.
bool isKnownNeverNegSubnormal() const
Return true if it's known this can never be a negative subnormal.
bool isKnownNeverPosZero() const
Return true if it's known this can never be a literal positive zero.
static LLVM_ABI KnownFPClass exp(const KnownFPClass &Src)
Report known values for exp, exp2 and exp10.
std::optional< bool > SignBit
std::nullopt if the sign bit is unknown, true if the sign bit is definitely set or false if the sign ...
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
bool isKnownNever(FPClassTest Mask) const
Return true if it's known this can never be one of the mask entries.
bool isKnownNeverNegZero() const
Return true if it's known this can never be a negative zero.
void propagateNaN(const KnownFPClass &Src, bool PreserveSign=false)
bool cannotBeOrderedLessThanZero() const
Return true if we can prove that the analyzed floating-point value is either NaN or never less than -...
void signBitMustBeOne()
Assume the sign bit is one.
LLVM_ABI void propagateCanonicalizingSrc(const KnownFPClass &Src, DenormalMode Mode)
Report known classes if Src is evaluated through a potentially canonicalizing operation.
void signBitMustBeZero()
Assume the sign bit is zero.
LLVM_ABI bool isKnownNeverLogicalPosZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a positive zero.
bool isKnownNeverPosInfinity() const
Return true if it's known this can never be +infinity.
bool cannotBeOrderedGreaterEqZero(DenormalMode Mode) const
Return true if it's know this can never be a negative value or a logical 0.
LLVM_ABI bool isKnownNeverLogicalNegZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a negative zero.
bool operator==(KnownFPClass Other) const
bool signBitIsZeroOrNaN() const
Return true if the sign bit must be 0, ignoring the sign of nans.
bool isKnownNeverPosSubnormal() const
Return true if it's known this can never be a positive subnormal.