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 // Normal and subnormal results require two non-zero finite operands.
438 if ((KnownLHS.isKnownNever(fcNegNormal | fcNegSubnormal) &&
442 Known.knownNot(fcNegNormal | fcNegSubnormal);
443 if ((KnownLHS.isKnownNever(fcNegNormal | fcNegSubnormal) &&
447 Known.knownNot(fcPosNormal | fcPosSubnormal);
448
449 // 0 / X => 0 or NaN
450 if (KnownLHS.isKnownAlways(fcZero))
451 Known.knownNot(fcSubnormal | fcNormal | fcInf);
452
453 // X / 0 => NaN or Inf
454 if (KnownRHS.isKnownAlways(fcZero))
455 Known.knownNot(fcFinite);
456
457 return Known;
458}
459
461 DenormalMode Mode) {
462 // X / X is always exactly 1.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}
473 DenormalMode Mode) {
474 // X % X is always exactly [+-]0.0 or a NaN.
476
477 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
478 Known.knownNot(fcNan);
479 else if (KnownSrc.isKnownNever(fcSNan))
480 Known.knownNot(fcSNan);
481
482 return Known;
483}
484
486 const KnownFPClass &KnownRHS,
487 const KnownFPClass &KnownAddend,
488 DenormalMode Mode) {
489 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
490
491 // FMA differs from the base fmul + fadd handling only in the treatment of -0
492 // results.
493 //
494 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
495 // unlike for a separate fadd.
496 return fadd_impl(Mul, KnownAddend, Mode);
497}
498
500 const KnownFPClass &KnownAddend,
501 DenormalMode Mode) {
502 KnownFPClass Squared = square(KnownSquared, Mode);
503 KnownFPClass Known = fadd_impl(Squared, KnownAddend, Mode);
504
505 // Since we know the squared input must be positive, the add of opposite sign
506 // infinities nan hazard only applies for negative inf.
507 //
508 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
509 // not pinf. Other than the degenerate always-subnormal input case, we can't
510 // prove that without a known range.
511 if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
512 Known.knownNot(fcNan);
513
514 return Known;
515}
516
519 Known.knownNot(fcNegative);
520
521 Known.propagateNonNaN(KnownSrc);
522
523 if (KnownSrc.cannotBeOrderedLessThanZero()) {
524 // If the source is positive this cannot underflow.
525 Known.knownNot(fcPosZero);
526
527 // Cannot introduce denormal values.
528 Known.knownNot(fcPosSubnormal);
529 }
530
531 // If the source is negative, this cannot overflow to infinity.
532 if (KnownSrc.cannotBeOrderedGreaterThanZero())
533 Known.knownNot(fcPosInf);
534
535 return Known;
536}
537
539 DenormalMode Mode) {
540 propagateDenormal(Src, Mode);
541 propagateNonNaN(Src, /*PreserveSign=*/true);
542}
543
545 DenormalMode Mode) {
547 Known.knownNot(fcNegZero | fcSubnormal);
548
549 if (KnownSrc.isKnownNeverPosInfinity())
550 Known.knownNot(fcPosInf);
551
552 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
553 Known.knownNot(fcNan);
554
555 if (KnownSrc.isKnownNeverLogicalZero(Mode))
556 Known.knownNot(fcNegInf);
557
558 return Known;
559}
560
562 DenormalMode Mode) {
564 Known.knownNot(fcPosSubnormal);
565
566 if (KnownSrc.isKnownNeverPosInfinity())
567 Known.knownNot(fcPosInf);
568
569 Known.propagateNonSNaN(KnownSrc);
570
571 // Any negative value besides -0 returns a nan.
572 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
573 Known.knownNot(fcNan);
574
575 // The only negative value that can be returned is -0 for -0 inputs.
577
578 // If the input denormal mode could be PreserveSign, a negative
579 // subnormal input could produce a negative zero output.
580 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
581 Known.knownNot(fcNegZero);
582
583 return Known;
584}
585
588
589 // Return NaN on infinite inputs.
590 Known.knownNot(fcInf);
591 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
592 Known.knownNot(fcNan);
593
594 return Known;
595}
596
598 return sin(KnownSrc);
599}
600
603
604 // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
605 Known.knownNot(fcInf);
606
607 // NaN propagates. tan(+-Inf) is NaN.
608 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
609 Known.knownNot(fcNan);
610
611 return Known;
612}
613
616
617 // sinh is sign-preserving: sinh(x) < 0 iff x < 0.
618 if (KnownSrc.isKnownNever(fcNegative))
619 Known.knownNot(fcNegative);
620
621 Known.propagateNonNaN(KnownSrc);
622
623 return Known;
624}
625
628
629 // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative,
630 // zero, or subnormal.
631 Known.knownNot(fcNegative | fcZero | fcSubnormal);
632
633 Known.propagateNonNaN(KnownSrc);
634
635 return Known;
636}
637
640
641 // tanh is bounded to (-1, 1), never Inf.
642 Known.knownNot(fcInf);
643
644 // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
645 if (KnownSrc.isKnownNever(fcNegative))
646 Known.knownNot(fcNegative);
647
648 Known.propagateNonNaN(KnownSrc);
649
650 return Known;
651}
652
655
656 // asin is bounded to [-pi/2, pi/2], never Inf.
657 Known.knownNot(fcInf);
658
659 Known.propagateNonSNaN(KnownSrc);
660
661 // asin is sign-preserving.
662 if (KnownSrc.isKnownNever(fcNegative))
663 Known.knownNot(fcNegative);
664
665 // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
666 // out NaN without knowing the source is in [-1, 1].
667 return Known;
668}
669
672
673 // acos is bounded to [0, pi], never Inf or negative.
674 Known.knownNot(fcInf);
675 Known.knownNot(fcNegative);
676
677 Known.propagateNonSNaN(KnownSrc);
678
679 // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
680 // out NaN without knowing the source is in [-1, 1].
681 return Known;
682}
683
686
687 // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
688 Known.knownNot(fcInf);
689
690 // atan is sign-preserving: atan(x) < 0 iff x < 0.
691 if (KnownSrc.isKnownNever(fcNegative))
692 Known.knownNot(fcNegative);
693
694 Known.propagateNonNaN(KnownSrc);
695
696 return Known;
697}
698
700 const KnownFPClass &KnownRHS) {
702
703 // atan2 result is in (-pi, pi], never Inf.
704 Known.knownNot(fcInf);
705
706 Known.propagateNonNaN(KnownLHS, KnownRHS);
707
708 return Known;
709}
710
712 const fltSemantics &DstTy,
713 const fltSemantics &SrcTy) {
714 // Infinity, nan and zero propagate from source.
715 KnownFPClass Known = KnownSrc;
716
717 // All subnormal inputs should be in the normal range in the result type.
718 if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
719 if (Known.KnownFPClasses & fcPosSubnormal)
720 Known.KnownFPClasses |= fcPosNormal;
721 if (Known.KnownFPClasses & fcNegSubnormal)
722 Known.KnownFPClasses |= fcNegNormal;
723 Known.knownNot(fcSubnormal);
724 }
725
726 // Sign bit of a nan isn't guaranteed.
727 if (!Known.isKnownNeverNaN())
728 Known.SignBit = std::nullopt;
729
730 return Known;
731}
732
735
736 // Sign should be preserved
737 // TODO: Handle cannot be ordered greater than zero
738 if (KnownSrc.cannotBeOrderedLessThanZero())
740
741 Known.propagateNonNaN(KnownSrc, true);
742
743 // Infinity needs a range check.
744 return Known;
745}
746
748 bool IsTrunc,
749 bool IsMultiUnitFPType) {
751
752 // Integer results cannot be subnormal.
753 Known.knownNot(fcSubnormal);
754
755 Known.propagateNonNaN(KnownSrc, true);
756
757 // Pass through infinities, except PPC_FP128 is a special case for
758 // intrinsics other than trunc.
759 if (IsTrunc || !IsMultiUnitFPType) {
760 if (KnownSrc.isKnownNeverPosInfinity())
761 Known.knownNot(fcPosInf);
762 if (KnownSrc.isKnownNeverNegInfinity())
763 Known.knownNot(fcNegInf);
764 }
765
766 // Negative round ups to 0 produce -0
767 if (KnownSrc.isKnownNever(fcPosFinite))
768 Known.knownNot(fcPosFinite);
769 if (KnownSrc.isKnownNever(fcNegFinite))
770 Known.knownNot(fcNegFinite);
771
772 return Known;
773}
774
776 DenormalMode Mode) {
778 Known.knownNot(fcSubnormal);
779
780 if (KnownSrc.isKnownNever(fcNegative))
781 Known.knownNot(fcNegative);
782 else {
783 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
784 Known.knownNot(fcNegZero);
785 if (KnownSrc.isKnownNever(fcNegInf))
786 Known.knownNot(fcNegInf);
787 }
788
789 if (KnownSrc.isKnownNever(fcPositive))
790 Known.knownNot(fcPositive);
791 else {
792 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
793 Known.knownNot(fcPosZero);
794 if (KnownSrc.isKnownNever(fcPosInf))
795 Known.knownNot(fcPosInf);
796 }
797
798 Known.propagateNonNaN(KnownSrc);
799 return Known;
800}
801
803 const APInt &ConstantRangeExpMin,
804 const APInt &ConstantRangeExpMax,
805 const fltSemantics &Flt, DenormalMode Mode) {
807 Known.propagateNonNaN(KnownSrc, /*PreserveSign=*/true);
808
809 // Sign is preserved, but underflows may produce zeroes.
810 if (KnownSrc.isKnownNever(fcNegative))
811 Known.knownNot(fcNegative);
812 else if (KnownSrc.cannotBeOrderedLessThanZero())
814
815 if (KnownSrc.isKnownNever(fcPositive))
816 Known.knownNot(fcPositive);
817 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
819
820 unsigned Precision = APFloat::semanticsPrecision(Flt);
821 const int MantissaBits = Precision - 1;
822 if (ConstantRangeExpMin.sge(MantissaBits))
823 Known.knownNot(fcSubnormal);
824
825 if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
826 // ldexp(x, 0) -> x, so propagate everything.
827 Known.propagateCanonicalizingSrc(KnownSrc, Mode);
828 } else if (ConstantRangeExpMax.isNonPositive()) {
829 // If we know the power is <= 0, can't introduce inf
830 if (KnownSrc.isKnownNeverPosInfinity())
831 Known.knownNot(fcPosInf);
832 if (KnownSrc.isKnownNeverNegInfinity())
833 Known.knownNot(fcNegInf);
834 } else if (ConstantRangeExpMin.isNonNegative()) {
835 // If we know the power is >= 0, can't introduce subnormal or zero
836 if (KnownSrc.isKnownNeverPosSubnormal())
837 Known.knownNot(fcPosSubnormal);
838 if (KnownSrc.isKnownNeverNegSubnormal())
839 Known.knownNot(fcNegSubnormal);
840 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
841 Known.knownNot(fcPosZero);
842 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
843 Known.knownNot(fcNegZero);
844 }
845
846 return Known;
847}
848
850 const KnownBits &ExpBits,
851 const fltSemantics &Flt, DenormalMode Mode) {
852 return ldexp(KnownSrc, ExpBits.getSignedMinValue(),
853 ExpBits.getSignedMaxValue(), Flt, Mode);
854}
855
857 const KnownBits &ExponentKnownBits) {
859 Known.propagateNonNaN(KnownSrc);
860
861 if (ExponentKnownBits.isZero()) {
862 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
863 // return 1.0 or a NaN.
864 if (KnownSrc.isKnownNever(fcSNan)) {
865 Known.knownNot(~fcPosNormal);
866 return Known;
867 }
868
869 Known.knownNot(~(fcPosNormal | fcNan));
870 return Known;
871 }
872
873 // powi(x, exp) --> inf
874 // when:
875 // * powi(inf, exp), exp > 0
876 // * powi(+/-0, exp), exp < 0
877 // * powi(finite, exp), |exp| > 1
878 // * powi(subnormal, -1)
879 // TODO:
880 // 1. This simple all or nothing approach. We can do better
881 // and cover sign/parity and exp > 1 vs exp < -1 separately.
882 // 2. powi(0/nan, exp), exp > 0 can be refinable
883 // to fcNan | fcZero | fcPosNormal.
884 {
885 APInt MinExp = ExponentKnownBits.getSignedMinValue();
886 APInt MaxExp = ExponentKnownBits.getSignedMaxValue();
887
888 // powi(inf, exp), exp > 0
889 bool MayInfSrc =
890 !KnownSrc.isKnownNever(fcInf) && MaxExp.isStrictlyPositive();
891
892 // powi(+/-0, exp), exp < 0
893 bool MayDivByZero = !KnownSrc.isKnownNever(fcZero) && MinExp.isNegative();
894
895 // powi(finite, exp), |exp| > 1
896 bool MayFinite = !KnownSrc.isKnownNever(fcNormal | fcSubnormal);
897 bool MayAbsExpGT1 = MinExp.slt(-1) || MaxExp.sgt(1);
898 bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;
899
900 // powi(subnormal, -1)
901 bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
902 bool MaySubnormInv = !KnownSrc.isKnownNever(fcSubnormal) && MayBeNegOne;
903
904 if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
905 Known.knownNot(fcInf);
906 }
907
908 if (ExponentKnownBits.isEven()) {
909 Known.knownNot(fcNegative);
910 return Known;
911 }
912
913 // Given that exp is an integer, here are the
914 // ways that pow can return a negative value:
915 //
916 // pow(-x, exp) --> negative if exp is odd and x is negative.
917 // pow(-0, exp) --> -inf if exp is negative odd.
918 // pow(-0, exp) --> -0 if exp is positive odd.
919 // pow(-inf, exp) --> -0 if exp is negative odd.
920 // pow(-inf, exp) --> -inf if exp is positive odd.
921 if (KnownSrc.isKnownNever(fcNegative))
922 Known.knownNot(fcNegative);
923
924 return Known;
925}
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:1206
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:377
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:326
bool isNonPositive() const
Determine if this APInt Value is non-positive (<= 0).
Definition APInt.h:358
bool isStrictlyPositive() const
Determine if this APInt Value is positive.
Definition APInt.h:353
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
Definition APInt.h:331
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition APInt.h:1135
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1242
#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.
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 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.
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