LLVM 24.0.0git
KnownFPClass.cpp
Go to the documentation of this file.
1//===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- 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
15#include "llvm/ADT/APFloat.h"
18
19using namespace llvm;
20
22 : KnownFPClasses(C.classify()), SignBit(C.isNegative()) {}
23
24/// Return true if it's possible to assume IEEE treatment of input denormals in
25/// \p F for \p Val.
27 return Mode.Input == DenormalMode::IEEE;
28}
29
34
39
44
47 return false;
48
49 // If we know there are no denormals, nothing can be flushed to zero.
51 return true;
52
53 switch (Mode.Input) {
55 return true;
57 // Negative subnormal won't flush to +0
60 default:
61 // Both positive and negative subnormal could flush to +0
62 return false;
63 }
64
65 llvm_unreachable("covered switch over denormal mode");
66}
67
69 DenormalMode Mode) {
70 KnownFPClasses = Src.KnownFPClasses;
71 // If we aren't assuming the source can't be a zero, we don't have to check if
72 // a denormal input could be flushed.
73 if (!Src.isKnownNeverPosZero() && !Src.isKnownNeverNegZero())
74 return;
75
76 // If we know the input can't be a denormal, it can't be flushed to 0.
77 if (Src.isKnownNeverSubnormal())
78 return;
79
80 if (!Src.isKnownNeverPosSubnormal() && Mode != DenormalMode::getIEEE())
82
83 if (!Src.isKnownNeverNegSubnormal() && Mode != DenormalMode::getIEEE()) {
86
87 if (Mode.Input == DenormalMode::PositiveZero ||
88 Mode.Output == DenormalMode::PositiveZero ||
89 Mode.Input == DenormalMode::Dynamic ||
90 Mode.Output == DenormalMode::Dynamic)
92 }
93}
94
96 const KnownFPClass &RHS_, MinMaxKind Kind,
97 DenormalMode Mode) {
98 KnownFPClass KnownLHS = LHS_;
99 KnownFPClass KnownRHS = RHS_;
100
101 bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN();
102 KnownFPClass Known = KnownLHS | KnownRHS;
103
104 // If either operand is not NaN, the result is not NaN.
105 if (NeverNaN &&
106 (Kind == MinMaxKind::minnum || Kind == MinMaxKind::maxnum ||
108 Known.knownNot(fcNan);
109
110 if (Kind == MinMaxKind::maxnum || Kind == MinMaxKind::maximumnum) {
111 if (KnownLHS.isKnownNeverNaN())
112 Known.knownNot(orderedStrictlyLess(KnownLHS.KnownFPClasses));
113 if (KnownRHS.isKnownNeverNaN())
114 Known.knownNot(orderedStrictlyLess(KnownRHS.KnownFPClasses));
115 } else if (Kind == MinMaxKind::maximum) {
116 Known.knownNot(orderedStrictlyLess(KnownLHS.KnownFPClasses) |
118 } else if (Kind == MinMaxKind::minnum || Kind == MinMaxKind::minimumnum) {
119 if (KnownLHS.isKnownNeverNaN())
120 Known.knownNot(orderedStrictlyGreater(KnownLHS.KnownFPClasses));
121 if (KnownRHS.isKnownNeverNaN())
122 Known.knownNot(orderedStrictlyGreater(KnownRHS.KnownFPClasses));
123 } else if (Kind == MinMaxKind::minimum) {
124 Known.knownNot(orderedStrictlyGreater(KnownLHS.KnownFPClasses) |
126 } else
127 llvm_unreachable("unhandled intrinsic");
128
129 // Fixup zero handling if denormals could be returned as a zero.
130 //
131 // As there's no spec for denormal flushing, be conservative with the
132 // treatment of denormals that could be flushed to zero. For older
133 // subtargets on AMDGPU the min/max instructions would not flush the
134 // output and return the original value.
135 //
136 if ((Known.KnownFPClasses & fcZero) != fcNone &&
137 !Known.isKnownNeverSubnormal()) {
138 if (Mode != DenormalMode::getIEEE())
139 Known.KnownFPClasses |= fcZero;
140 }
141
142 if (Known.isKnownNeverNaN()) {
143 if (KnownLHS.SignBit && KnownRHS.SignBit &&
144 *KnownLHS.SignBit == *KnownRHS.SignBit) {
145 if (*KnownLHS.SignBit)
146 Known.signBitMustBeOne();
147 else
148 Known.signBitMustBeZero();
149 } else if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::minimum ||
150 Kind == MinMaxKind::maximumnum ||
151 Kind == MinMaxKind::minimumnum) ||
152 // FIXME: Should be using logical zero versions
153 ((KnownLHS.isKnownNeverNegZero() ||
154 KnownRHS.isKnownNeverPosZero()) &&
155 (KnownLHS.isKnownNeverPosZero() ||
156 KnownRHS.isKnownNeverNegZero()))) {
157 // Don't take sign bit from NaN operands.
158 if (!KnownLHS.isKnownNeverNaN())
159 KnownLHS.SignBit = std::nullopt;
160 if (!KnownRHS.isKnownNeverNaN())
161 KnownRHS.SignBit = std::nullopt;
162 if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::maximumnum ||
163 Kind == MinMaxKind::maxnum) &&
164 (KnownLHS.SignBit == false || KnownRHS.SignBit == false))
165 Known.signBitMustBeZero();
166 else if ((Kind == MinMaxKind::minimum || Kind == MinMaxKind::minimumnum ||
167 Kind == MinMaxKind::minnum) &&
168 (KnownLHS.SignBit == true || KnownRHS.SignBit == true))
169 Known.signBitMustBeOne();
170 }
171 }
172
173 return Known;
174}
175
177 DenormalMode DenormMode) {
179
180 // This is essentially a stronger form of
181 // propagateCanonicalizingSrc. Other "canonicalizing" operations don't
182 // actually have an IR canonicalization guarantee.
183
184 // Canonicalize may flush denormals to zero, so we have to consider the
185 // denormal mode to preserve known-not-0 knowledge.
186 Known.KnownFPClasses = KnownSrc.KnownFPClasses | fcZero | fcQNan;
187
188 // Stronger version of propagateNaN
189 // Canonicalize is guaranteed to quiet signaling nans.
190 if (KnownSrc.isKnownNeverNaN())
191 Known.knownNot(fcNan);
192 else
193 Known.knownNot(fcSNan);
194
195 // FIXME: Missing check of IEEE like types.
196
197 // If the parent function flushes denormals, the canonical output cannot be a
198 // denormal.
199 if (DenormMode == DenormalMode::getIEEE()) {
200 if (KnownSrc.isKnownNever(fcPosZero))
201 Known.knownNot(fcPosZero);
202 if (KnownSrc.isKnownNever(fcNegZero))
203 Known.knownNot(fcNegZero);
204 return Known;
205 }
206
207 if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
208 Known.knownNot(fcSubnormal);
209
210 if (DenormMode == DenormalMode::getPreserveSign()) {
211 if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal))
212 Known.knownNot(fcPosZero);
213 if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal))
214 Known.knownNot(fcNegZero);
215 return Known;
216 }
217
218 if (DenormMode.Input == DenormalMode::PositiveZero ||
219 (DenormMode.Output == DenormalMode::PositiveZero &&
220 DenormMode.Input == DenormalMode::IEEE)) {
221 // -0.0 is not a subnormal and should not be flushed.
222 if (KnownSrc.isKnownNever(fcNegZero))
223 Known.knownNot(fcNegZero);
224
225 if (KnownSrc.isKnownNever(fcPosZero | fcSubnormal))
226 Known.knownNot(fcPosZero);
227 }
228
229 return Known;
230}
231
233 const KnownBits &Bits) {
234 assert(FltSemantics.sizeInBits == Bits.getBitWidth() &&
235 "Bitcast operand has incorrect bit width");
237
238 // Transfer information from the sign bit.
239 if (Bits.isNonNegative())
240 Known.signBitMustBeZero();
241 else if (Bits.isNegative())
242 Known.signBitMustBeOne();
243
244 if (APFloat::isIEEELikeFP(FltSemantics)) {
245 // IEEE floats are NaN when all bits of the exponent plus at least one of
246 // the fraction bits are 1. This means:
247 // - If we assume unknown bits are 0 and the value is NaN, it will
248 // always be NaN
249 // - If we assume unknown bits are 1 and the value is not NaN, it can
250 // never be NaN
251 // Note: They do not hold for x86_fp80 format.
252 if (APFloat(FltSemantics, Bits.One).isNaN())
253 Known.KnownFPClasses = fcNan;
254 else if (!APFloat(FltSemantics, ~Bits.Zero).isNaN())
255 Known.knownNot(fcNan);
256
257 // Build KnownBits representing Inf and check if it must be equal or
258 // unequal to this value.
259 auto InfKB =
260 KnownBits::makeConstant(APFloat::getInf(FltSemantics).bitcastToAPInt());
261 InfKB.Zero.clearSignBit();
262 if (const auto InfResult = KnownBits::eq(Bits, InfKB)) {
263 assert(!InfResult.value());
264 Known.knownNot(fcInf);
265 } else if (Bits == InfKB) {
266 Known.KnownFPClasses = fcInf;
267 }
268
269 // Build KnownBits representing Zero and check if it must be equal or
270 // unequal to this value.
271 auto ZeroKB = KnownBits::makeConstant(
272 APFloat::getZero(FltSemantics).bitcastToAPInt());
273 ZeroKB.Zero.clearSignBit();
274 if (const auto ZeroResult = KnownBits::eq(Bits, ZeroKB)) {
275 assert(!ZeroResult.value());
276 Known.knownNot(fcZero);
277 } else if (Bits == ZeroKB) {
278 Known.KnownFPClasses = fcZero;
279 }
280 }
281
282 return Known;
283}
284
285// Handle known sign bit and nan cases for fadd.
286static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
287 const KnownFPClass &KnownRHS, DenormalMode Mode) {
289
290 // Adding positive and negative infinity produces NaN, but only if both
291 // opposite-sign infinity combinations are possible.
292 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
293 (KnownLHS.isKnownNever(fcPosInf) || KnownRHS.isKnownNever(fcNegInf)) &&
294 (KnownLHS.isKnownNever(fcNegInf) || KnownRHS.isKnownNever(fcPosInf)))
295 Known.knownNot(fcNan);
296
297 if (KnownLHS.cannotBeOrderedLessThanZero() &&
298 KnownRHS.cannotBeOrderedLessThanZero()) {
300
301 // This can't underflow if one of the operands is known normal.
302 if (KnownLHS.isKnownNever(fcZero | fcPosSubnormal) ||
304 Known.knownNot(fcZero | fcPosSubnormal);
305 }
306
307 if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
310
311 // This can't underflow if one of the operands is known normal.
312 if (KnownLHS.isKnownNever(fcZero | fcNegSubnormal) ||
314 Known.knownNot(fcZero | fcNegSubnormal);
315 }
316
317 return Known;
318}
319
321 const KnownFPClass &KnownRHS,
322 DenormalMode Mode) {
323 KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
324
325 // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
326 if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
327 KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
328 // Make sure output negative denormal can't flush to -0
329 (Mode.Output == DenormalMode::IEEE ||
330 Mode.Output == DenormalMode::PositiveZero))
331 Known.knownNot(fcNegZero);
332
333 return Known;
334}
335
337 DenormalMode Mode) {
338 KnownFPClass Known = fadd(KnownSrc, KnownSrc, Mode);
339
340 // Doubling 0 will give the same 0.
341 if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
342 (Mode.Output == DenormalMode::IEEE ||
343 (Mode.Output == DenormalMode::PreserveSign &&
344 KnownSrc.isKnownNeverPosSubnormal()) ||
345 (Mode.Output == DenormalMode::PositiveZero &&
346 KnownSrc.isKnownNeverSubnormal())))
347 Known.knownNot(fcPosZero);
348
349 return Known;
350}
351
353 const KnownFPClass &KnownRHS,
354 DenormalMode Mode) {
355 return fadd(KnownLHS, fneg(KnownRHS), Mode);
356}
357
359 const KnownFPClass &KnownRHS,
360 DenormalMode Mode) {
362
363 // +X * +Y or -X * -Y => +Q
364 // +X * -Y or -X * +Y => -Q
365 Known.propagateXorSign(KnownLHS, KnownRHS);
366
367 // Inf * Y => Inf or NaN
368 if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
369 KnownRHS.isKnownAlways(fcInf | fcNan))
370 Known.knownNot(fcNormal | fcSubnormal | fcZero);
371
372 // 0 * Y => 0 or NaN
373 if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
374 KnownLHS.isKnownAlways(fcZero | fcNan))
375 Known.knownNot(fcNormal | fcSubnormal | fcInf);
376
377 if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
378 return Known;
379
380 // 0 * +/-inf => NaN
381 if ((KnownRHS.isKnownNeverInfinity() ||
382 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
383 (KnownLHS.isKnownNeverInfinity() ||
384 KnownRHS.isKnownNeverLogicalZero(Mode)))
385 Known.knownNot(fcNan);
386
387 return Known;
388}
389
390// TODO: This generalizes to known ranges
392 const APFloat &CRHS, DenormalMode Mode) {
393 // Match denormal scaling pattern, similar to the case in ldexp. If the
394 // constant's exponent is sufficiently large, the result cannot be subnormal.
395
396 const fltSemantics &Flt = CRHS.getSemantics();
397 unsigned Precision = APFloat::semanticsPrecision(Flt);
398 const int MantissaBits = Precision - 1;
399
400 int MinKnownExponent = ilogb(CRHS);
401 bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);
402
403 KnownFPClass Known = KnownFPClass::fmul(KnownLHS, KnownFPClass(CRHS), Mode);
404 if (CannotBeSubnormal)
405 Known.knownNot(fcSubnormal);
406
407 // Multiply of values <= 1 cannot introduce overflow.
408 if (KnownLHS.isKnownNever(fcInf)) {
409 if (MinKnownExponent < 0)
410 Known.knownNot(fcInf);
411 else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(APFloat::getOne(
412 Flt)) == APFloat::cmpEqual)
413 Known.knownNot(fcInf);
414 }
415
416 return Known;
417}
418
420 const KnownFPClass &KnownRHS,
421 DenormalMode Mode) {
423
424 // Only 0/0, Inf/Inf produce NaN.
425 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
426 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
427 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
428 KnownRHS.isKnownNeverLogicalZero(Mode))) {
429 Known.knownNot(fcNan);
430 }
431
432 // X / -0.0 => -Inf (or NaN)
433 // +X / +Y or -X / -Y => +Q
434 // +X / -Y or -X / +Y => -Q
435 Known.propagateXorSign(KnownLHS, KnownRHS);
436
437 // 0 / X => 0 or NaN
438 if (KnownLHS.isKnownAlways(fcZero))
439 Known.knownNot(fcSubnormal | fcNormal | fcInf);
440
441 // X / 0 => NaN or Inf
442 if (KnownRHS.isKnownAlways(fcZero))
443 Known.knownNot(fcFinite);
444
445 return Known;
446}
447
449 DenormalMode Mode) {
450 // X / X is always exactly 1.0 or a NaN.
452
453 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
454 Known.knownNot(fcNan);
455 else if (KnownSrc.isKnownNever(fcSNan))
456 Known.knownNot(fcSNan);
457
458 return Known;
459}
461 DenormalMode Mode) {
462 // X % X is always exactly [+-]0.0 or a NaN.
464
465 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
466 Known.knownNot(fcNan);
467 else if (KnownSrc.isKnownNever(fcSNan))
468 Known.knownNot(fcSNan);
469
470 return Known;
471}
472
474 const KnownFPClass &KnownRHS,
475 const KnownFPClass &KnownAddend,
476 DenormalMode Mode) {
477 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
478
479 // FMA differs from the base fmul + fadd handling only in the treatment of -0
480 // results.
481 //
482 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
483 // unlike for a separate fadd.
484 return fadd_impl(Mul, KnownAddend, Mode);
485}
486
488 const KnownFPClass &KnownAddend,
489 DenormalMode Mode) {
490 KnownFPClass Squared = square(KnownSquared, Mode);
491 KnownFPClass Known = fadd_impl(Squared, KnownAddend, Mode);
492
493 // Since we know the squared input must be positive, the add of opposite sign
494 // infinities nan hazard only applies for negative inf.
495 //
496 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
497 // not pinf. Other than the degenerate always-subnormal input case, we can't
498 // prove that without a known range.
499 if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
500 Known.knownNot(fcNan);
501
502 return Known;
503}
504
507 Known.knownNot(fcNegative);
508
509 Known.propagateNaN(KnownSrc);
510
511 if (KnownSrc.cannotBeOrderedLessThanZero()) {
512 // If the source is positive this cannot underflow.
513 Known.knownNot(fcPosZero);
514
515 // Cannot introduce denormal values.
516 Known.knownNot(fcPosSubnormal);
517 }
518
519 // If the source is negative, this cannot overflow to infinity.
520 if (KnownSrc.cannotBeOrderedGreaterThanZero())
521 Known.knownNot(fcPosInf);
522
523 return Known;
524}
525
527 DenormalMode Mode) {
528 propagateDenormal(Src, Mode);
529 propagateNaN(Src, /*PreserveSign=*/true);
530}
531
533 DenormalMode Mode) {
535 Known.knownNot(fcNegZero | fcSubnormal);
536
537 if (KnownSrc.isKnownNeverPosInfinity())
538 Known.knownNot(fcPosInf);
539
540 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
541 Known.knownNot(fcNan);
542
543 if (KnownSrc.isKnownNeverLogicalZero(Mode))
544 Known.knownNot(fcNegInf);
545
546 return Known;
547}
548
550 DenormalMode Mode) {
552 Known.knownNot(fcPosSubnormal);
553
554 if (KnownSrc.isKnownNeverPosInfinity())
555 Known.knownNot(fcPosInf);
556 if (KnownSrc.isKnownNever(fcSNan))
557 Known.knownNot(fcSNan);
558
559 // Any negative value besides -0 returns a nan.
560 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
561 Known.knownNot(fcNan);
562
563 // The only negative value that can be returned is -0 for -0 inputs.
565
566 // If the input denormal mode could be PreserveSign, a negative
567 // subnormal input could produce a negative zero output.
568 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
569 Known.knownNot(fcNegZero);
570
571 return Known;
572}
573
576
577 // Return NaN on infinite inputs.
578 Known.knownNot(fcInf);
579 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
580 Known.knownNot(fcNan);
581
582 return Known;
583}
584
586 return sin(KnownSrc);
587}
588
591
592 // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
593 Known.knownNot(fcInf);
594
595 // NaN propagates. tan(+-Inf) is NaN.
596 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
597 Known.knownNot(fcNan);
598
599 return Known;
600}
601
604
605 // sinh is sign-preserving: sinh(x) < 0 iff x < 0.
606 if (KnownSrc.isKnownNever(fcNegative))
607 Known.knownNot(fcNegative);
608
609 Known.propagateNaN(KnownSrc);
610
611 return Known;
612}
613
616
617 // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative,
618 // zero, or subnormal.
619 Known.knownNot(fcNegative | fcZero | fcSubnormal);
620
621 Known.propagateNaN(KnownSrc);
622
623 return Known;
624}
625
628
629 // tanh is bounded to (-1, 1), never Inf.
630 Known.knownNot(fcInf);
631
632 // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
633 if (KnownSrc.isKnownNever(fcNegative))
634 Known.knownNot(fcNegative);
635
636 Known.propagateNaN(KnownSrc);
637
638 return Known;
639}
640
643
644 // asin is bounded to [-pi/2, pi/2], never Inf.
645 Known.knownNot(fcInf);
646
647 if (KnownSrc.isKnownNever(fcSNan))
648 Known.knownNot(fcSNan);
649
650 // asin is sign-preserving.
651 if (KnownSrc.isKnownNever(fcNegative))
652 Known.knownNot(fcNegative);
653
654 // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
655 // out NaN without knowing the source is in [-1, 1].
656 return Known;
657}
658
661
662 // acos is bounded to [0, pi], never Inf or negative.
663 Known.knownNot(fcInf);
664 Known.knownNot(fcNegative);
665
666 if (KnownSrc.isKnownNever(fcSNan))
667 Known.knownNot(fcSNan);
668
669 // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
670 // out NaN without knowing the source is in [-1, 1].
671 return Known;
672}
673
676
677 // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
678 Known.knownNot(fcInf);
679
680 // atan is sign-preserving: atan(x) < 0 iff x < 0.
681 if (KnownSrc.isKnownNever(fcNegative))
682 Known.knownNot(fcNegative);
683
684 Known.propagateNaN(KnownSrc);
685
686 return Known;
687}
688
690 const KnownFPClass &KnownRHS) {
692
693 // atan2 result is in (-pi, pi], never Inf.
694 Known.knownNot(fcInf);
695
696 // NaN if either operand is NaN.
697 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
698 Known.knownNot(fcNan);
699
700 return Known;
701}
702
704 const fltSemantics &DstTy,
705 const fltSemantics &SrcTy) {
706 // Infinity, nan and zero propagate from source.
707 KnownFPClass Known = KnownSrc;
708
709 // All subnormal inputs should be in the normal range in the result type.
710 if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
711 if (Known.KnownFPClasses & fcPosSubnormal)
712 Known.KnownFPClasses |= fcPosNormal;
713 if (Known.KnownFPClasses & fcNegSubnormal)
714 Known.KnownFPClasses |= fcNegNormal;
715 Known.knownNot(fcSubnormal);
716 }
717
718 // Sign bit of a nan isn't guaranteed.
719 if (!Known.isKnownNeverNaN())
720 Known.SignBit = std::nullopt;
721
722 return Known;
723}
724
727
728 // Sign should be preserved
729 // TODO: Handle cannot be ordered greater than zero
730 if (KnownSrc.cannotBeOrderedLessThanZero())
732
733 Known.propagateNaN(KnownSrc, true);
734
735 // Infinity needs a range check.
736 return Known;
737}
738
740 bool IsTrunc,
741 bool IsMultiUnitFPType) {
743
744 // Integer results cannot be subnormal.
745 Known.knownNot(fcSubnormal);
746
747 Known.propagateNaN(KnownSrc, true);
748
749 // Pass through infinities, except PPC_FP128 is a special case for
750 // intrinsics other than trunc.
751 if (IsTrunc || !IsMultiUnitFPType) {
752 if (KnownSrc.isKnownNeverPosInfinity())
753 Known.knownNot(fcPosInf);
754 if (KnownSrc.isKnownNeverNegInfinity())
755 Known.knownNot(fcNegInf);
756 }
757
758 // Negative round ups to 0 produce -0
759 if (KnownSrc.isKnownNever(fcPosFinite))
760 Known.knownNot(fcPosFinite);
761 if (KnownSrc.isKnownNever(fcNegFinite))
762 Known.knownNot(fcNegFinite);
763
764 return Known;
765}
766
768 DenormalMode Mode) {
770 Known.knownNot(fcSubnormal);
771
772 if (KnownSrc.isKnownNever(fcNegative))
773 Known.knownNot(fcNegative);
774 else {
775 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
776 Known.knownNot(fcNegZero);
777 if (KnownSrc.isKnownNever(fcNegInf))
778 Known.knownNot(fcNegInf);
779 }
780
781 if (KnownSrc.isKnownNever(fcPositive))
782 Known.knownNot(fcPositive);
783 else {
784 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
785 Known.knownNot(fcPosZero);
786 if (KnownSrc.isKnownNever(fcPosInf))
787 Known.knownNot(fcPosInf);
788 }
789
790 Known.propagateNaN(KnownSrc);
791 return Known;
792}
793
795 const APInt &ConstantRangeExpMin,
796 const APInt &ConstantRangeExpMax,
797 const fltSemantics &Flt, DenormalMode Mode) {
799 Known.propagateNaN(KnownSrc, /*PropagateSign=*/true);
800
801 // Sign is preserved, but underflows may produce zeroes.
802 if (KnownSrc.isKnownNever(fcNegative))
803 Known.knownNot(fcNegative);
804 else if (KnownSrc.cannotBeOrderedLessThanZero())
806
807 if (KnownSrc.isKnownNever(fcPositive))
808 Known.knownNot(fcPositive);
809 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
811
812 unsigned Precision = APFloat::semanticsPrecision(Flt);
813 const int MantissaBits = Precision - 1;
814 if (ConstantRangeExpMin.sge(MantissaBits))
815 Known.knownNot(fcSubnormal);
816
817 if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
818 // ldexp(x, 0) -> x, so propagate everything.
819 Known.propagateCanonicalizingSrc(KnownSrc, Mode);
820 } else if (ConstantRangeExpMax.isNonPositive()) {
821 // If we know the power is <= 0, can't introduce inf
822 if (KnownSrc.isKnownNeverPosInfinity())
823 Known.knownNot(fcPosInf);
824 if (KnownSrc.isKnownNeverNegInfinity())
825 Known.knownNot(fcNegInf);
826 } else if (ConstantRangeExpMin.isNonNegative()) {
827 // If we know the power is >= 0, can't introduce subnormal or zero
828 if (KnownSrc.isKnownNeverPosSubnormal())
829 Known.knownNot(fcPosSubnormal);
830 if (KnownSrc.isKnownNeverNegSubnormal())
831 Known.knownNot(fcNegSubnormal);
832 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
833 Known.knownNot(fcPosZero);
834 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
835 Known.knownNot(fcNegZero);
836 }
837
838 return Known;
839}
840
842 const KnownBits &ExpBits,
843 const fltSemantics &Flt, DenormalMode Mode) {
844 return ldexp(KnownSrc, ExpBits.getSignedMinValue(),
845 ExpBits.getSignedMaxValue(), Flt, Mode);
846}
847
849 const KnownBits &ExponentKnownBits) {
851 Known.propagateNaN(KnownSrc);
852
853 if (ExponentKnownBits.isZero()) {
854 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
855 // return 1.0 or a NaN.
856 if (KnownSrc.isKnownNever(fcSNan)) {
857 Known.knownNot(~fcPosNormal);
858 return Known;
859 }
860
861 Known.knownNot(~(fcPosNormal | fcNan));
862 return Known;
863 }
864
865 // powi(x, exp) --> inf
866 // when:
867 // * powi(inf, exp), exp > 0
868 // * powi(+/-0, exp), exp < 0
869 // * powi(finite, exp), |exp| > 1
870 // * powi(subnormal, -1)
871 // TODO:
872 // 1. This simple all or nothing approach. We can do better
873 // and cover sign/parity and exp > 1 vs exp < -1 separately.
874 // 2. powi(0/nan, exp), exp > 0 can be refinable
875 // to fcNan | fcZero | fcPosNormal.
876 {
877 APInt MinExp = ExponentKnownBits.getSignedMinValue();
878 APInt MaxExp = ExponentKnownBits.getSignedMaxValue();
879
880 // powi(inf, exp), exp > 0
881 bool MayInfSrc =
882 !KnownSrc.isKnownNever(fcInf) && MaxExp.isStrictlyPositive();
883
884 // powi(+/-0, exp), exp < 0
885 bool MayDivByZero = !KnownSrc.isKnownNever(fcZero) && MinExp.isNegative();
886
887 // powi(finite, exp), |exp| > 1
888 bool MayFinite = !KnownSrc.isKnownNever(fcNormal | fcSubnormal);
889 bool MayAbsExpGT1 = MinExp.slt(-1) || MaxExp.sgt(1);
890 bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;
891
892 // powi(subnormal, -1)
893 bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
894 bool MaySubnormInv = !KnownSrc.isKnownNever(fcSubnormal) && MayBeNegOne;
895
896 if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
897 Known.knownNot(fcInf);
898 }
899
900 if (ExponentKnownBits.isEven()) {
901 Known.knownNot(fcNegative);
902 return Known;
903 }
904
905 // Given that exp is an integer, here are the
906 // ways that pow can return a negative value:
907 //
908 // pow(-x, exp) --> negative if exp is odd and x is negative.
909 // pow(-0, exp) --> -inf if exp is negative odd.
910 // pow(-0, exp) --> -0 if exp is positive odd.
911 // pow(-inf, exp) --> -0 if exp is negative odd.
912 // pow(-inf, exp) --> -inf if exp is positive odd.
913 if (KnownSrc.isKnownNever(fcNegative))
914 Known.knownNot(fcNegative);
915
916 return Known;
917}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS, const KnownFPClass &KnownRHS, DenormalMode Mode)
static bool inputDenormalIsIEEE(DenormalMode Mode)
Return true if it's possible to assume IEEE treatment of input denormals in F for Val.
static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode)
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")))
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
Definition APFloat.cpp:254
static LLVM_ABI bool isRepresentableAsNormalIn(const fltSemantics &Src, const fltSemantics &Dst)
Definition APFloat.cpp:304
static LLVM_ABI bool isIEEELikeFP(const fltSemantics &)
Definition APFloat.cpp:295
cmpResult compareAbsoluteValue(const APFloat &RHS) const
Definition APFloat.h:1530
const fltSemantics & getSemantics() const
Definition APFloat.h:1583
bool isNaN() const
Definition APFloat.h:1573
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1184
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1194
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1175
Class for arbitrary precision integers.
Definition APInt.h:78
bool sgt(const APInt &RHS) const
Signed greater than comparison.
Definition APInt.h:1210
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:330
bool isNonPositive() const
Determine if this APInt Value is non-positive (<= 0).
Definition APInt.h:362
bool isStrictlyPositive() const
Determine if this APInt Value is positive.
Definition APInt.h:357
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
Definition APInt.h:335
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition APInt.h:1139
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1246
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
@ Known
Known to have no common set bits.
LLVM_ABI FPClassTest orderedStrictlyGreater(FPClassTest Mask, bool OrderedZeroSign=false)
Returns all FPClasses which are greater than all values in Mask That is, return all classes for which...
int ilogb(const APFloat &Arg)
Returns the exponent of the internal representation of the APFloat.
Definition APFloat.h:1684
LLVM_ABI FPClassTest orderedStrictlyLess(FPClassTest Mask, bool OrderedZeroSign=false)
Returns all FPClasses which are less than all values in Mask That is, return all classes for which th...
@ Mul
Product of integers.
Represent subnormal handling kind for floating point instruction inputs and outputs.
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
constexpr bool outputsAreZero() const
Return true if output denormals should be flushed to 0.
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
@ PositiveZero
Denormals are flushed to positive zero.
@ Dynamic
Denormals have unknown treatment.
@ IEEE
IEEE-754 denormal numbers preserved.
static constexpr DenormalMode getPositiveZero()
constexpr bool inputsAreZero() const
Return true if input denormals must be implicitly treated as 0.
static constexpr DenormalMode getPreserveSign()
DenormalModeKind Output
Denormal flushing mode for floating point instruction results in the default floating point environme...
static constexpr DenormalMode getIEEE()
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
Definition KnownBits.h:315
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isZero() const
Returns true if value is all zero.
Definition KnownBits.h:78
APInt getSignedMaxValue() const
Return the maximal signed value possible given these KnownBits.
Definition KnownBits.h:152
bool isEven() const
Return if the value is known even (the low bit is 0).
Definition KnownBits.h:162
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
Definition KnownBits.h:136
bool isKnownNeverInfOrNaN() const
Return true if it's known this can never be an infinity or 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
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.
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
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.
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.
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 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.
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 -...
LLVM_ABI void propagateCanonicalizingSrc(const KnownFPClass &Src, DenormalMode Mode)
Report known classes if Src is evaluated through a potentially canonicalizing operation.
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.
static LLVM_ABI KnownFPClass fadd(const KnownFPClass &LHS, const KnownFPClass &RHS, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fadd.
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.
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.
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.
unsigned int sizeInBits
Definition APFloat.h:1029