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;
23struct fltSemantics;
24
26 /// Floating-point classes the value could be one of.
28
29 /// std::nullopt if the sign bit is unknown, true if the sign bit is
30 /// definitely set or false if the sign bit is definitely unset.
31 std::optional<bool> SignBit;
32
33 KnownFPClass(FPClassTest Known = fcAllFlags, std::optional<bool> Sign = {})
34 : KnownFPClasses(Known), SignBit(Sign) {}
35 LLVM_ABI KnownFPClass(const APFloat &C);
36
38 return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
39 }
40
41 /// Return true if it's known this can never be one of the mask entries.
42 bool isKnownNever(FPClassTest Mask) const {
43 return (KnownFPClasses & Mask) == fcNone;
44 }
45
46 bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
47
48 bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; }
49
50 /// Return true if it's known this can never be a nan.
51 bool isKnownNeverNaN() const { return isKnownNever(fcNan); }
52
53 /// Return true if it's known this must always be a nan.
54 bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
55
56 /// Return true if it's known this can never be an infinity.
57 bool isKnownNeverInfinity() const { return isKnownNever(fcInf); }
58
59 /// Return true if it's known this can never be an infinity or nan
60 bool isKnownNeverInfOrNaN() const { return isKnownNever(fcInf | fcNan); }
61
62 /// Return true if it's known this can never be +infinity.
64
65 /// Return true if it's known this can never be -infinity.
67
68 /// Return true if it's known this can never be a subnormal
70
71 /// Return true if it's known this can never be a positive subnormal
73
74 /// Return true if it's known this can never be a negative subnormal
76
77 /// Return true if it's known this can never be a zero. This means a literal
78 /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
79 bool isKnownNeverZero() const { return isKnownNever(fcZero); }
80
81 /// Return true if it's known this can never be a literal positive zero.
82 bool isKnownNeverPosZero() const { return isKnownNever(fcPosZero); }
83
84 /// Return true if it's known this can never be a negative zero. This means a
85 /// literal -0 and does not include denormal inputs implicitly treated as -0.
86 bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); }
87
88 /// Return true if it's known this can never be interpreted as a zero. This
89 /// extends isKnownNeverZero to cover the case where the assumed
90 /// floating-point mode for the function interprets denormals as zero.
92
93 /// Return true if it's known this can never be interpreted as a negative
94 /// zero.
96
97 /// Return true if it's known this can never be interpreted as a positive
98 /// zero.
100
105
106 /// Return true if we can prove that the analyzed floating-point value is
107 /// either NaN or never less than -0.0.
108 ///
109 /// NaN --> true
110 /// +0 --> true
111 /// -0 --> true
112 /// x > +0 --> true
113 /// x < -0 --> false
117
118 /// Return true if we can prove that the analyzed floating-point value is
119 /// either NaN or never greater than -0.0.
120 /// NaN --> true
121 /// +0 --> true
122 /// -0 --> true
123 /// x > +0 --> false
124 /// x < -0 --> true
128
129 /// Return true if it's know this can never be a negative value or a logical
130 /// 0.
131 ///
132 /// NaN --> true
133 /// x >= -0 --> false
134 /// nsub --> true if mode is ieee, false otherwise.
135 /// x < -0 --> true
139
141 return KnownFPClass(KnownFPClasses | RHS.KnownFPClasses,
142 SignBit == RHS.SignBit ? SignBit : std::nullopt);
143 }
144
146 std::optional<bool> MergedSignBit;
147 if (SignBit && !RHS.SignBit)
148 MergedSignBit = SignBit;
149 else if (!SignBit && RHS.SignBit)
150 MergedSignBit = RHS.SignBit;
151
152 return KnownFPClass(KnownFPClasses & RHS.KnownFPClasses, MergedSignBit);
153 }
154
156 KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
157
158 if (SignBit != RHS.SignBit)
159 SignBit = std::nullopt;
160 return *this;
161 }
162
163 void knownNot(FPClassTest RuleOut) {
164 KnownFPClasses = KnownFPClasses & ~RuleOut;
165 if (isKnownNever(fcNan) && !SignBit) {
167 SignBit = false;
168 else if (isKnownNever(fcPositive))
169 SignBit = true;
170 }
171 }
172
173 void fneg() {
175 if (SignBit)
176 SignBit = !*SignBit;
177 }
178
179 static KnownFPClass fneg(const KnownFPClass &Src) {
180 KnownFPClass Known = Src;
181 Known.fneg();
182 return Known;
183 }
184
200
201 static KnownFPClass fabs(const KnownFPClass &Src) {
202 KnownFPClass Known = Src;
203 Known.fabs();
204 return Known;
205 }
206
207 // Enum of min/max intrinsics to avoid dependency on IR.
216
220
221 /// Apply the canonicalize intrinsic to this value. This is essentially a
222 /// stronger form of propagateCanonicalizingSrc.
224 canonicalize(const KnownFPClass &Src,
226
227 /// Report known values for fadd
229 fadd(const KnownFPClass &LHS, const KnownFPClass &RHS,
231
232 /// Report known values for fadd x, x
234 fadd_self(const KnownFPClass &Src,
236
237 /// Report known values for fsub
239 fsub(const KnownFPClass &LHS, const KnownFPClass &RHS,
241
242 /// Report known values for fmul
244 fmul(const KnownFPClass &LHS, const KnownFPClass &RHS,
246
247 // Special case of fmul x, x.
250 KnownFPClass Known = fmul(Src, Src, Mode);
251
252 // X * X is always non-negative or a NaN.
253 Known.knownNot(fcNegative);
254 Known.propagateNaN(Src);
255 return Known;
256 }
257
258 /// Report known values for fdiv
260 fdiv(const KnownFPClass &LHS, const KnownFPClass &RHS,
262
263 /// Report known values for fdiv x, x
265 fdiv_self(const KnownFPClass &Src,
267
268 /// Report known values for frem
270 frem_self(const KnownFPClass &Src,
272
273 /// Report known values for fma
275 fma(const KnownFPClass &LHS, const KnownFPClass &RHS,
276 const KnownFPClass &Addend,
278
279 /// Report known values for fma squared, squared, addend
281 fma_square(const KnownFPClass &Squared, const KnownFPClass &Addend,
283
284 /// Report known values for exp, exp2 and exp10.
285 LLVM_ABI static KnownFPClass exp(const KnownFPClass &Src);
286
287 /// Report known values for sin
288 LLVM_ABI static KnownFPClass sin(const KnownFPClass &Src);
289
290 /// Report known values for cos
291 LLVM_ABI static KnownFPClass cos(const KnownFPClass &Src);
292
293 /// Return true if the sign bit must be 0, ignoring the sign of nans.
295
296 /// Assume the sign bit is zero.
299 SignBit = false;
300 }
301
302 /// Assume the sign bit is one.
305 SignBit = true;
306 }
307
308 void copysign(const KnownFPClass &Sign) {
309 // Don't know anything about the sign of the source. Expand the possible set
310 // to its opposite sign pair.
317 if (KnownFPClasses & fcInf)
319
320 // Sign bit is exactly preserved even for nans.
321 SignBit = Sign.SignBit;
322
323 // Clear sign bits based on the input sign mask.
324 if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
326 if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
328 }
329
330 static KnownFPClass copysign(const KnownFPClass &KnownMag,
331 const KnownFPClass &KnownSign) {
332 KnownFPClass Known = KnownMag;
333 Known.copysign(KnownSign);
334 return Known;
335 }
336
337 // Propagate knowledge that a non-NaN source implies the result can also not
338 // be a NaN. For unconstrained operations, signaling nans are not guaranteed
339 // to be quieted but cannot be introduced.
340 void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
341 if (Src.isKnownNever(fcNan)) {
343 if (PreserveSign)
344 SignBit = Src.SignBit;
345 } else if (Src.isKnownNever(fcSNan))
347 }
348
349 /// Propagate knowledge from a source value that could be a denormal or
350 /// zero. We have to be conservative since output flushing is not guaranteed,
351 /// so known-never-zero may not hold.
352 ///
353 /// This assumes a copy-like operation and will replace any currently known
354 /// information.
356
357 /// Report known classes if \p Src is evaluated through a potentially
358 /// canonicalizing operation. We can assume signaling nans will not be
359 /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
360 ///
361 /// This assumes a copy-like operation and will replace any currently known
362 /// information.
365
366 /// Propagate known class for log/log2/log10
369
370 /// Propagate known class for sqrt
373
374 /// Propagate known class for fpext.
375 static LLVM_ABI KnownFPClass fpext(const KnownFPClass &KnownSrc,
376 const fltSemantics &DstTy,
377 const fltSemantics &SrcTy);
378
379 /// Propagate known class for fptrunc.
380 static LLVM_ABI KnownFPClass fptrunc(const KnownFPClass &KnownSrc);
381
382 /// Propagate known class for rounding intrinsics (trunc, floor, ceil, rint,
383 /// nearbyint, round, roundeven). This is trunc if \p IsTrunc. \p
384 /// IsMultiUnitFPType if this is for a multi-unit floating-point type.
386 bool IsTrunc,
387 bool IsMultiUnitFPType);
388
389 /// Propagate known class for mantissa component of frexp
392
393 void resetAll() { *this = KnownFPClass(); }
394};
395
397 LHS |= RHS;
398 return LHS;
399}
400
402 RHS |= LHS;
403 return std::move(RHS);
404}
405
406} // namespace llvm
407
408#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:2158
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
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.
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 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 ...
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.
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 fma_square(const KnownFPClass &Squared, const KnownFPClass &Addend, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fma squared, squared, addend.
bool operator==(KnownFPClass Other) const
static LLVM_ABI KnownFPClass frem_self(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for frem.
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.