LLVM 24.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.propagateNonNaN(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 an operation cannot introduce a signaling NaN.
385 if (Src.isKnownNever(fcSNan))
387 }
388
389 // Propagate knowledge that an operation cannot introduce a signaling NaN.
391 if (LHS.isKnownNever(fcSNan) && RHS.isKnownNever(fcSNan))
393 }
394
395 // Propagate knowledge that a non-NaN source implies the result can also not
396 // be a NaN. For unconstrained operations, signaling nans are not guaranteed
397 // to be quieted but cannot be introduced.
398 void propagateNonNaN(const KnownFPClass &Src, bool PreserveSign = false) {
399 propagateNonSNaN(Src);
400 if (Src.isKnownNever(fcNan)) {
402 if (PreserveSign)
403 SignBit = Src.SignBit;
404 }
405 }
406
409 if (LHS.isKnownNeverNaN() && RHS.isKnownNeverNaN())
411 }
412
413 // Propagate knowledge for operations whose result sign is the xor of the
414 // operand signs, such as multiply and divide. This only rules out possible
415 // non-NaN sign classes. NaNs do not have a constrained sign class here.
417 if ((LHS.isKnownNever(fcNegative) && RHS.isKnownNever(fcNegative)) ||
418 (LHS.isKnownNever(fcPositive) && RHS.isKnownNever(fcPositive)))
420
421 if ((LHS.isKnownNever(fcPositive) && RHS.isKnownNever(fcNegative)) ||
422 (LHS.isKnownNever(fcNegative) && RHS.isKnownNever(fcPositive)))
424 }
425
426 /// Propagate knowledge from a source value that could be a denormal or
427 /// zero. We have to be conservative since output flushing is not guaranteed,
428 /// so known-never-zero may not hold.
429 ///
430 /// This assumes a copy-like operation and will replace any currently known
431 /// information.
433
434 /// Report known classes if \p Src is evaluated through a potentially
435 /// canonicalizing operation. We can assume signaling nans will not be
436 /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
437 ///
438 /// This assumes a copy-like operation and will replace any currently known
439 /// information.
442
443 /// Propagate known class for log/log2/log10
446
447 /// Propagate known class for sqrt
450
451 /// Propagate known class for fpext.
452 static LLVM_ABI KnownFPClass fpext(const KnownFPClass &KnownSrc,
453 const fltSemantics &DstTy,
454 const fltSemantics &SrcTy);
455
456 /// Propagate known class for fptrunc.
457 static LLVM_ABI KnownFPClass fptrunc(const KnownFPClass &KnownSrc);
458
459 /// Propagate known class for rounding intrinsics (trunc, floor, ceil, rint,
460 /// nearbyint, round, roundeven). This is trunc if \p IsTrunc. \p
461 /// IsMultiUnitFPType if this is for a multi-unit floating-point type.
463 bool IsTrunc,
464 bool IsMultiUnitFPType);
465
466 /// Propagate known class for mantissa component of frexp
469
470 /// Propagate known class for ldexp, assuming the exponent is known to be
471 /// within [\p ConstantRangeMin, \p ConstantRangeMax]
472 ///
473 // TODO: This really ought to use ConstantRange, but it's in IR not Support.
475 ldexp(const KnownFPClass &Src, const APInt &ConstantRangeMin,
476 const APInt &ConstantRangeMax, const fltSemantics &Flt,
479 const KnownFPClass &Src, const KnownBits &ExpBits,
481
482 /// Propagate known class for powi
483 static LLVM_ABI KnownFPClass powi(const KnownFPClass &Src,
484 const KnownBits &N);
485
486 void resetAll() { *this = KnownFPClass(); }
487};
488
490 LHS |= RHS;
491 return LHS;
492}
493
495 RHS |= LHS;
496 return std::move(RHS);
497}
498
499} // namespace llvm
500
501#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:2170
#define N
Represent subnormal handling kind for floating point instruction inputs and outputs.
static constexpr DenormalMode getDynamic()
void propagateNonSNaN(const KnownFPClass &LHS, const KnownFPClass &RHS)
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
void propagateNonNaN(const KnownFPClass &LHS, const KnownFPClass &RHS)
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.
void propagateNonNaN(const KnownFPClass &Src, bool PreserveSign=false)
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.
static LLVM_ABI KnownFPClass fptrunc(const KnownFPClass &KnownSrc)
Propagate known class for fptrunc.
void propagateNonSNaN(const KnownFPClass &Src)
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.