LLVM 23.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;
23class APInt;
24struct fltSemantics;
25struct KnownBits;
26
28 /// Floating-point classes the value could be one of.
30
31 /// std::nullopt if the sign bit is unknown, true if the sign bit is
32 /// definitely set or false if the sign bit is definitely unset.
33 std::optional<bool> SignBit;
34
35 KnownFPClass(FPClassTest Known = fcAllFlags, std::optional<bool> Sign = {})
36 : KnownFPClasses(Known), SignBit(Sign) {}
37 LLVM_ABI KnownFPClass(const APFloat &C);
38
40 return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
41 }
42
43 /// Return true if it's known this can never be one of the mask entries.
44 bool isKnownNever(FPClassTest Mask) const {
45 return (KnownFPClasses & Mask) == fcNone;
46 }
47
48 bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
49
50 bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; }
51
52 /// Return true if it's known this can never be a nan.
53 bool isKnownNeverNaN() const { return isKnownNever(fcNan); }
54
55 /// Return true if it's known this must always be a nan.
56 bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
57
58 /// Return true if it's known this can never be an infinity.
59 bool isKnownNeverInfinity() const { return isKnownNever(fcInf); }
60
61 /// Return true if it's known this can never be an infinity or nan
62 bool isKnownNeverInfOrNaN() const { return isKnownNever(fcInf | fcNan); }
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 -infinity.
69
70 /// Return true if it's known this can never be a subnormal
72
73 /// Return true if it's known this can never be a positive subnormal
75
76 /// Return true if it's known this can never be a negative subnormal
78
79 /// Return true if it's known this can never be a zero. This means a literal
80 /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
81 bool isKnownNeverZero() const { return isKnownNever(fcZero); }
82
83 /// Return true if it's known this can never be a literal positive zero.
84 bool isKnownNeverPosZero() const { return isKnownNever(fcPosZero); }
85
86 /// Return true if it's known this can never be a negative zero. This means a
87 /// literal -0 and does not include denormal inputs implicitly treated as -0.
88 bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); }
89
90 /// Return true if it's known this can never be interpreted as a zero. This
91 /// extends isKnownNeverZero to cover the case where the assumed
92 /// floating-point mode for the function interprets denormals as zero.
94
95 /// Return true if it's known this can never be interpreted as a negative
96 /// zero.
98
99 /// Return true if it's known this can never be interpreted as a positive
100 /// zero.
102
107
108 /// Return true if we can prove that the analyzed floating-point value is
109 /// either NaN or never less than -0.0.
110 ///
111 /// NaN --> true
112 /// +0 --> true
113 /// -0 --> true
114 /// x > +0 --> true
115 /// x < -0 --> false
119
120 /// Return true if we can prove that the analyzed floating-point value is
121 /// either NaN or never greater than -0.0.
122 /// NaN --> true
123 /// +0 --> true
124 /// -0 --> true
125 /// x > +0 --> false
126 /// x < -0 --> true
130
131 /// Return true if it's known this can never be a positive value or a logical
132 /// 0.
133 ///
134 /// NaN --> true
135 /// x <= +0 --> false
136 /// psub --> true if mode is ieee, false otherwise.
137 /// x > +0 --> true
141
142 /// Return true if it's know this can never be a negative value or a logical
143 /// 0.
144 ///
145 /// NaN --> true
146 /// x >= -0 --> false
147 /// nsub --> true if mode is ieee, false otherwise.
148 /// x < -0 --> true
152
154 return KnownFPClass(KnownFPClasses | RHS.KnownFPClasses,
155 SignBit == RHS.SignBit ? SignBit : std::nullopt);
156 }
157
159 std::optional<bool> MergedSignBit;
160 if (SignBit && !RHS.SignBit)
161 MergedSignBit = SignBit;
162 else if (!SignBit && RHS.SignBit)
163 MergedSignBit = RHS.SignBit;
164
165 return KnownFPClass(KnownFPClasses & RHS.KnownFPClasses, MergedSignBit);
166 }
167
169 KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
170
171 if (SignBit != RHS.SignBit)
172 SignBit = std::nullopt;
173 return *this;
174 }
175
176 void knownNot(FPClassTest RuleOut) {
177 KnownFPClasses = KnownFPClasses & ~RuleOut;
178 if (isKnownNever(fcNan) && !SignBit) {
180 SignBit = false;
181 else if (isKnownNever(fcPositive))
182 SignBit = true;
183 }
184 }
185
186 void fneg() {
188 if (SignBit)
189 SignBit = !*SignBit;
190 }
191
192 static KnownFPClass fneg(const KnownFPClass &Src) {
193 KnownFPClass Known = Src;
194 Known.fneg();
195 return Known;
196 }
197
213
214 static KnownFPClass fabs(const KnownFPClass &Src) {
215 KnownFPClass Known = Src;
216 Known.fabs();
217 return Known;
218 }
219
220 // Enum of min/max intrinsics to avoid dependency on IR.
229
233
234 /// Apply the canonicalize intrinsic to this value. This is essentially a
235 /// stronger form of propagateCanonicalizingSrc.
237 canonicalize(const KnownFPClass &Src,
239
240 /// Report known values for a bitcast into a float with provided semantics.
241 LLVM_ABI static KnownFPClass bitcast(const fltSemantics &FltSemantics,
242 const KnownBits &Bits);
243
244 /// Report known values for fadd
246 fadd(const KnownFPClass &LHS, const KnownFPClass &RHS,
248
249 /// Report known values for fadd x, x
251 fadd_self(const KnownFPClass &Src,
253
254 /// Report known values for fsub
256 fsub(const KnownFPClass &LHS, const KnownFPClass &RHS,
258
259 /// Report known values for fmul
261 fmul(const KnownFPClass &LHS, const KnownFPClass &RHS,
263
264 // Special case of fmul x, x.
267 KnownFPClass Known = fmul(Src, Src, Mode);
268
269 // X * X is always non-negative or a NaN.
270 Known.knownNot(fcNegative);
271 Known.propagateNaN(Src);
272 return Known;
273 }
274
276 fmul(const KnownFPClass &LHS, const APFloat &RHS,
278
279 /// Report known values for fdiv
281 fdiv(const KnownFPClass &LHS, const KnownFPClass &RHS,
283
284 /// Report known values for fdiv x, x
286 fdiv_self(const KnownFPClass &Src,
288
289 /// Report known values for frem
291 frem_self(const KnownFPClass &Src,
293
294 /// Report known values for fma
296 fma(const KnownFPClass &LHS, const KnownFPClass &RHS,
297 const KnownFPClass &Addend,
299
300 /// Report known values for fma squared, squared, addend
302 fma_square(const KnownFPClass &Squared, const KnownFPClass &Addend,
304
305 /// Report known values for exp, exp2 and exp10.
306 LLVM_ABI static KnownFPClass exp(const KnownFPClass &Src);
307
308 /// Report known values for sin
309 LLVM_ABI static KnownFPClass sin(const KnownFPClass &Src);
310
311 /// Report known values for cos
312 LLVM_ABI static KnownFPClass cos(const KnownFPClass &Src);
313
314 /// Report known values for tan
315 LLVM_ABI static KnownFPClass tan(const KnownFPClass &Src);
316
317 /// Report known values for sinh
318 LLVM_ABI static KnownFPClass sinh(const KnownFPClass &Src);
319
320 /// Report known values for cosh
321 LLVM_ABI static KnownFPClass cosh(const KnownFPClass &Src);
322
323 /// Report known values for tanh
324 LLVM_ABI static KnownFPClass tanh(const KnownFPClass &Src);
325
326 /// Report known values for asin
327 LLVM_ABI static KnownFPClass asin(const KnownFPClass &Src);
328
329 /// Report known values for acos
330 LLVM_ABI static KnownFPClass acos(const KnownFPClass &Src);
331
332 /// Report known values for atan
333 LLVM_ABI static KnownFPClass atan(const KnownFPClass &Src);
334
335 /// Report known values for atan2
337 const KnownFPClass &RHS);
338
339 /// Return true if the sign bit must be 0, ignoring the sign of nans.
341
342 /// Assume the sign bit is zero.
345 SignBit = false;
346 }
347
348 /// Assume the sign bit is one.
351 SignBit = true;
352 }
353
354 void copysign(const KnownFPClass &Sign) {
355 // Don't know anything about the sign of the source. Expand the possible set
356 // to its opposite sign pair.
363 if (KnownFPClasses & fcInf)
365
366 // Sign bit is exactly preserved even for nans.
367 SignBit = Sign.SignBit;
368
369 // Clear sign bits based on the input sign mask.
370 if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
372 if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
374 }
375
376 static KnownFPClass copysign(const KnownFPClass &KnownMag,
377 const KnownFPClass &KnownSign) {
378 KnownFPClass Known = KnownMag;
379 Known.copysign(KnownSign);
380 return Known;
381 }
382
383 // Propagate knowledge that a non-NaN source implies the result can also not
384 // be a NaN. For unconstrained operations, signaling nans are not guaranteed
385 // to be quieted but cannot be introduced.
386 void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
387 if (Src.isKnownNever(fcNan)) {
389 if (PreserveSign)
390 SignBit = Src.SignBit;
391 } else if (Src.isKnownNever(fcSNan))
393 }
394
395 // Propagate knowledge for operations whose result sign is the xor of the
396 // operand signs, such as multiply and divide. This only rules out possible
397 // non-NaN sign classes. NaNs do not have a constrained sign class here.
399 if ((LHS.isKnownNever(fcNegative) && RHS.isKnownNever(fcNegative)) ||
400 (LHS.isKnownNever(fcPositive) && RHS.isKnownNever(fcPositive)))
402
403 if ((LHS.isKnownNever(fcPositive) && RHS.isKnownNever(fcNegative)) ||
404 (LHS.isKnownNever(fcNegative) && RHS.isKnownNever(fcPositive)))
406 }
407
408 /// Propagate knowledge from a source value that could be a denormal or
409 /// zero. We have to be conservative since output flushing is not guaranteed,
410 /// so known-never-zero may not hold.
411 ///
412 /// This assumes a copy-like operation and will replace any currently known
413 /// information.
415
416 /// Report known classes if \p Src is evaluated through a potentially
417 /// canonicalizing operation. We can assume signaling nans will not be
418 /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
419 ///
420 /// This assumes a copy-like operation and will replace any currently known
421 /// information.
424
425 /// Propagate known class for log/log2/log10
428
429 /// Propagate known class for sqrt
432
433 /// Propagate known class for fpext.
434 static LLVM_ABI KnownFPClass fpext(const KnownFPClass &KnownSrc,
435 const fltSemantics &DstTy,
436 const fltSemantics &SrcTy);
437
438 /// Propagate known class for fptrunc.
439 static LLVM_ABI KnownFPClass fptrunc(const KnownFPClass &KnownSrc);
440
441 /// Propagate known class for rounding intrinsics (trunc, floor, ceil, rint,
442 /// nearbyint, round, roundeven). This is trunc if \p IsTrunc. \p
443 /// IsMultiUnitFPType if this is for a multi-unit floating-point type.
445 bool IsTrunc,
446 bool IsMultiUnitFPType);
447
448 /// Propagate known class for mantissa component of frexp
451
452 /// Propagate known class for ldexp, assuming the exponent is known to be
453 /// within [\p ConstantRangeMin, \p ConstantRangeMax]
454 ///
455 // TODO: This really ought to use ConstantRange, but it's in IR not Support.
457 ldexp(const KnownFPClass &Src, const APInt &ConstantRangeMin,
458 const APInt &ConstantRangeMax, const fltSemantics &Flt,
461 const KnownFPClass &Src, const KnownBits &ExpBits,
463
464 /// Propagate known class for powi
465 static LLVM_ABI KnownFPClass powi(const KnownFPClass &Src,
466 const KnownBits &N);
467
468 void resetAll() { *this = KnownFPClass(); }
469};
470
472 LHS |= RHS;
473 return LHS;
474}
475
477 RHS |= LHS;
478 return std::move(RHS);
479}
480
481} // namespace llvm
482
483#endif
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:215
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
Class for arbitrary precision integers.
Definition APInt.h:78
This is an optimization pass for GlobalISel generic memory operations.
@ Known
Known to have no common set bits.
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:2174
#define N
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 LLVM_ABI KnownFPClass sin(const KnownFPClass &Src)
Report known values for sin.
static LLVM_ABI KnownFPClass fdiv_self(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fdiv x, x.
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.
static LLVM_ABI KnownFPClass fadd_self(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fadd x, x.
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())
static LLVM_ABI KnownFPClass fsub(const KnownFPClass &LHS, const KnownFPClass &RHS, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fsub.
bool isKnownNeverSubnormal() const
Return true if it's known this can never be a subnormal.
bool isKnownAlways(FPClassTest Mask) const
KnownFPClass unionWith(const KnownFPClass &RHS) const
void propagateXorSign(const KnownFPClass &LHS, const KnownFPClass &RHS)
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.
static LLVM_ABI KnownFPClass atan(const KnownFPClass &Src)
Report known values for atan.
LLVM_ABI void propagateDenormal(const KnownFPClass &Src, DenormalMode Mode)
Propagate knowledge from a source value that could be a denormal or zero.
bool cannotBeOrderedLessEqZero(DenormalMode Mode) const
Return true if it's known this can never be a positive value or a logical 0.
static LLVM_ABI KnownFPClass atan2(const KnownFPClass &LHS, const KnownFPClass &RHS)
Report known values for atan2.
static LLVM_ABI KnownFPClass fdiv(const KnownFPClass &LHS, const KnownFPClass &RHS, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fdiv.
KnownFPClass & operator|=(const KnownFPClass &RHS)
static KnownFPClass fneg(const KnownFPClass &Src)
static LLVM_ABI KnownFPClass roundToIntegral(const KnownFPClass &Src, bool IsTrunc, bool IsMultiUnitFPType)
Propagate known class for rounding intrinsics (trunc, floor, ceil, rint, nearbyint,...
static LLVM_ABI KnownFPClass cos(const KnownFPClass &Src)
Report known values for cos.
static LLVM_ABI KnownFPClass cosh(const KnownFPClass &Src)
Report known values for cosh.
static LLVM_ABI KnownFPClass minMaxLike(const KnownFPClass &LHS, const KnownFPClass &RHS, MinMaxKind Kind, DenormalMode DenormMode=DenormalMode::getDynamic())
bool isUnknown() const
KnownFPClass intersectWith(const KnownFPClass &RHS) 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.
static LLVM_ABI KnownFPClass frexp_mant(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Propagate known class for mantissa component of frexp.
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 ...
static LLVM_ABI KnownFPClass asin(const KnownFPClass &Src)
Report known values for asin.
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.
static LLVM_ABI KnownFPClass fpext(const KnownFPClass &KnownSrc, const fltSemantics &DstTy, const fltSemantics &SrcTy)
Propagate known class for fpext.
static KnownFPClass copysign(const KnownFPClass &KnownMag, const KnownFPClass &KnownSign)
bool isKnownNeverNegZero() const
Return true if it's known this can never be a negative zero.
static LLVM_ABI KnownFPClass fma(const KnownFPClass &LHS, const KnownFPClass &RHS, const KnownFPClass &Addend, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fma.
static LLVM_ABI KnownFPClass tan(const KnownFPClass &Src)
Report known values for tan.
void propagateNaN(const KnownFPClass &Src, bool PreserveSign=false)
static LLVM_ABI KnownFPClass fptrunc(const KnownFPClass &KnownSrc)
Propagate known class for fptrunc.
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.
static LLVM_ABI KnownFPClass sqrt(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Propagate known class for sqrt.
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.
static LLVM_ABI KnownFPClass fadd(const KnownFPClass &LHS, const KnownFPClass &RHS, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fadd.
static KnownFPClass fabs(const KnownFPClass &Src)
LLVM_ABI bool isKnownNeverLogicalNegZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a negative zero.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
static LLVM_ABI KnownFPClass fma_square(const KnownFPClass &Squared, const KnownFPClass &Addend, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fma squared, squared, addend.
static LLVM_ABI KnownFPClass acos(const KnownFPClass &Src)
Report known values for acos.
bool operator==(KnownFPClass Other) const
static LLVM_ABI KnownFPClass frem_self(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for frem.
static LLVM_ABI KnownFPClass powi(const KnownFPClass &Src, const KnownBits &N)
Propagate known class for powi.
bool signBitIsZeroOrNaN() const
Return true if the sign bit must be 0, ignoring the sign of nans.
static LLVM_ABI KnownFPClass ldexp(const KnownFPClass &Src, const APInt &ConstantRangeMin, const APInt &ConstantRangeMax, const fltSemantics &Flt, DenormalMode Mode=DenormalMode::getDynamic())
Propagate known class for ldexp, assuming the exponent is known to be within [ConstantRangeMin,...
static LLVM_ABI KnownFPClass sinh(const KnownFPClass &Src)
Report known values for sinh.
bool isKnownNeverPosSubnormal() const
Return true if it's known this can never be a positive subnormal.
static LLVM_ABI KnownFPClass tanh(const KnownFPClass &Src)
Report known values for tanh.