LLVM 23.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 at least one operand is known to be positive, the result must be
112 // positive.
113 if ((KnownLHS.cannotBeOrderedLessThanZero() &&
114 KnownLHS.isKnownNeverNaN()) ||
115 (KnownRHS.cannotBeOrderedLessThanZero() && KnownRHS.isKnownNeverNaN()))
117 } else if (Kind == MinMaxKind::maximum) {
118 // If at least one operand is known to be positive, the result must be
119 // positive.
120 if (KnownLHS.cannotBeOrderedLessThanZero() ||
123 } else if (Kind == MinMaxKind::minnum || Kind == MinMaxKind::minimumnum) {
124 // If at least one operand is known to be negative, the result must be
125 // negative.
126 if ((KnownLHS.cannotBeOrderedGreaterThanZero() &&
127 KnownLHS.isKnownNeverNaN()) ||
128 (KnownRHS.cannotBeOrderedGreaterThanZero() &&
129 KnownRHS.isKnownNeverNaN()))
131 } else if (Kind == MinMaxKind::minimum) {
132 // If at least one operand is known to be negative, the result must be
133 // negative.
134 if (KnownLHS.cannotBeOrderedGreaterThanZero() ||
137 } else
138 llvm_unreachable("unhandled intrinsic");
139
140 // Fixup zero handling if denormals could be returned as a zero.
141 //
142 // As there's no spec for denormal flushing, be conservative with the
143 // treatment of denormals that could be flushed to zero. For older
144 // subtargets on AMDGPU the min/max instructions would not flush the
145 // output and return the original value.
146 //
147 if ((Known.KnownFPClasses & fcZero) != fcNone &&
148 !Known.isKnownNeverSubnormal()) {
149 if (Mode != DenormalMode::getIEEE())
150 Known.KnownFPClasses |= fcZero;
151 }
152
153 if (Known.isKnownNeverNaN()) {
154 if (KnownLHS.SignBit && KnownRHS.SignBit &&
155 *KnownLHS.SignBit == *KnownRHS.SignBit) {
156 if (*KnownLHS.SignBit)
157 Known.signBitMustBeOne();
158 else
159 Known.signBitMustBeZero();
160 } else if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::minimum ||
161 Kind == MinMaxKind::maximumnum ||
162 Kind == MinMaxKind::minimumnum) ||
163 // FIXME: Should be using logical zero versions
164 ((KnownLHS.isKnownNeverNegZero() ||
165 KnownRHS.isKnownNeverPosZero()) &&
166 (KnownLHS.isKnownNeverPosZero() ||
167 KnownRHS.isKnownNeverNegZero()))) {
168 // Don't take sign bit from NaN operands.
169 if (!KnownLHS.isKnownNeverNaN())
170 KnownLHS.SignBit = std::nullopt;
171 if (!KnownRHS.isKnownNeverNaN())
172 KnownRHS.SignBit = std::nullopt;
173 if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::maximumnum ||
174 Kind == MinMaxKind::maxnum) &&
175 (KnownLHS.SignBit == false || KnownRHS.SignBit == false))
176 Known.signBitMustBeZero();
177 else if ((Kind == MinMaxKind::minimum || Kind == MinMaxKind::minimumnum ||
178 Kind == MinMaxKind::minnum) &&
179 (KnownLHS.SignBit == true || KnownRHS.SignBit == true))
180 Known.signBitMustBeOne();
181 }
182 }
183
184 return Known;
185}
186
188 DenormalMode DenormMode) {
189 KnownFPClass Known;
190
191 // This is essentially a stronger form of
192 // propagateCanonicalizingSrc. Other "canonicalizing" operations don't
193 // actually have an IR canonicalization guarantee.
194
195 // Canonicalize may flush denormals to zero, so we have to consider the
196 // denormal mode to preserve known-not-0 knowledge.
197 Known.KnownFPClasses = KnownSrc.KnownFPClasses | fcZero | fcQNan;
198
199 // Stronger version of propagateNaN
200 // Canonicalize is guaranteed to quiet signaling nans.
201 if (KnownSrc.isKnownNeverNaN())
202 Known.knownNot(fcNan);
203 else
204 Known.knownNot(fcSNan);
205
206 // FIXME: Missing check of IEEE like types.
207
208 // If the parent function flushes denormals, the canonical output cannot be a
209 // denormal.
210 if (DenormMode == DenormalMode::getIEEE()) {
211 if (KnownSrc.isKnownNever(fcPosZero))
212 Known.knownNot(fcPosZero);
213 if (KnownSrc.isKnownNever(fcNegZero))
214 Known.knownNot(fcNegZero);
215 return Known;
216 }
217
218 if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
219 Known.knownNot(fcSubnormal);
220
221 if (DenormMode == DenormalMode::getPreserveSign()) {
222 if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal))
223 Known.knownNot(fcPosZero);
224 if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal))
225 Known.knownNot(fcNegZero);
226 return Known;
227 }
228
229 if (DenormMode.Input == DenormalMode::PositiveZero ||
230 (DenormMode.Output == DenormalMode::PositiveZero &&
231 DenormMode.Input == DenormalMode::IEEE))
232 Known.knownNot(fcNegZero);
233
234 return Known;
235}
236
237// Handle known sign bit and nan cases for fadd.
238static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
239 const KnownFPClass &KnownRHS, DenormalMode Mode) {
240 KnownFPClass Known;
241
242 // Adding positive and negative infinity produces NaN.
243 // TODO: Check sign of infinities.
244 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
245 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()))
246 Known.knownNot(fcNan);
247
248 if (KnownLHS.cannotBeOrderedLessThanZero() &&
249 KnownRHS.cannotBeOrderedLessThanZero()) {
251
252 // This can't underflow if one of the operands is known normal.
253 if (KnownLHS.isKnownNever(fcZero | fcPosSubnormal) ||
255 Known.knownNot(fcZero);
256 }
257
258 if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
261
262 // This can't underflow if one of the operands is known normal.
263 if (KnownLHS.isKnownNever(fcZero | fcNegSubnormal) ||
265 Known.knownNot(fcZero);
266 }
267
268 return Known;
269}
270
272 const KnownFPClass &KnownRHS,
273 DenormalMode Mode) {
274 KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
275
276 // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
277 if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
278 KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
279 // Make sure output negative denormal can't flush to -0
280 (Mode.Output == DenormalMode::IEEE ||
281 Mode.Output == DenormalMode::PositiveZero))
282 Known.knownNot(fcNegZero);
283
284 return Known;
285}
286
288 DenormalMode Mode) {
289 KnownFPClass Known = fadd(KnownSrc, KnownSrc, Mode);
290
291 // Doubling 0 will give the same 0.
292 if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
293 (Mode.Output == DenormalMode::IEEE ||
294 (Mode.Output == DenormalMode::PreserveSign &&
295 KnownSrc.isKnownNeverPosSubnormal()) ||
296 (Mode.Output == DenormalMode::PositiveZero &&
297 KnownSrc.isKnownNeverSubnormal())))
298 Known.knownNot(fcPosZero);
299
300 return Known;
301}
302
304 const KnownFPClass &KnownRHS,
305 DenormalMode Mode) {
306 return fadd(KnownLHS, fneg(KnownRHS), Mode);
307}
308
310 const KnownFPClass &KnownRHS,
311 DenormalMode Mode) {
312 KnownFPClass Known;
313
314 // xor sign bit.
315 if ((KnownLHS.isKnownNever(fcNegative) &&
316 KnownRHS.isKnownNever(fcNegative)) ||
317 (KnownLHS.isKnownNever(fcPositive) && KnownRHS.isKnownNever(fcPositive)))
318 Known.knownNot(fcNegative);
319
320 if ((KnownLHS.isKnownNever(fcPositive) &&
321 KnownRHS.isKnownNever(fcNegative)) ||
322 (KnownLHS.isKnownNever(fcNegative) && KnownRHS.isKnownNever(fcPositive)))
323 Known.knownNot(fcPositive);
324
325 // inf * anything => inf or nan
326 if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
327 KnownRHS.isKnownAlways(fcInf | fcNan))
329
330 // 0 * anything => 0 or nan
331 if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
332 KnownLHS.isKnownAlways(fcZero | fcNan))
334
335 // +/-0 * +/-inf = nan
336 if ((KnownLHS.isKnownAlways(fcZero | fcNan) &&
337 KnownRHS.isKnownAlways(fcInf | fcNan)) ||
338 (KnownLHS.isKnownAlways(fcInf | fcNan) &&
339 KnownRHS.isKnownAlways(fcZero | fcNan)))
340 Known.knownNot(~fcNan);
341
342 if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
343 return Known;
344
345 // If 0 * +/-inf produces NaN.
346 if ((KnownRHS.isKnownNeverInfinity() ||
347 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
348 (KnownLHS.isKnownNeverInfinity() ||
349 KnownRHS.isKnownNeverLogicalZero(Mode)))
350 Known.knownNot(fcNan);
351
352 return Known;
353}
354
355// TODO: This generalizes to known ranges
357 const APFloat &CRHS, DenormalMode Mode) {
358 // Match denormal scaling pattern, similar to the case in ldexp. If the
359 // constant's exponent is sufficiently large, the result cannot be subnormal.
360
361 const fltSemantics &Flt = CRHS.getSemantics();
362 unsigned Precision = APFloat::semanticsPrecision(Flt);
363 const int MantissaBits = Precision - 1;
364
365 int MinKnownExponent = ilogb(CRHS);
366 bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);
367
368 KnownFPClass Known = KnownFPClass::fmul(KnownLHS, KnownFPClass(CRHS), Mode);
369 if (CannotBeSubnormal)
370 Known.knownNot(fcSubnormal);
371
372 // Multiply of values <= 1 cannot introduce overflow.
373 if (KnownLHS.isKnownNever(fcInf)) {
374 if (MinKnownExponent < 0)
375 Known.knownNot(fcInf);
376 else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(APFloat::getOne(
377 Flt)) == APFloat::cmpEqual)
378 Known.knownNot(fcInf);
379 }
380
381 return Known;
382}
383
385 const KnownFPClass &KnownRHS,
386 DenormalMode Mode) {
387 KnownFPClass Known;
388
389 // Only 0/0, Inf/Inf produce NaN.
390 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
391 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
392 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
393 KnownRHS.isKnownNeverLogicalZero(Mode))) {
394 Known.knownNot(fcNan);
395 }
396
397 // xor sign bit.
398 // X / -0.0 is -Inf (or NaN).
399 // +X / +X is +X
400 if ((KnownLHS.isKnownNever(fcNegative) &&
401 KnownRHS.isKnownNever(fcNegative)) ||
402 (KnownLHS.isKnownNever(fcPositive) && KnownRHS.isKnownNever(fcPositive)))
403 Known.knownNot(fcNegative);
404
405 if ((KnownLHS.isKnownNever(fcPositive) &&
406 KnownRHS.isKnownNever(fcNegative)) ||
407 (KnownLHS.isKnownNever(fcNegative) && KnownRHS.isKnownNever(fcPositive)))
408 Known.knownNot(fcPositive);
409
410 // 0 / x => 0 or nan
411 if (KnownLHS.isKnownAlways(fcZero))
413
414 // x / 0 => nan or inf
415 if (KnownRHS.isKnownAlways(fcZero))
416 Known.knownNot(fcFinite);
417
418 return Known;
419}
420
422 DenormalMode Mode) {
423 // X / X is always exactly 1.0 or a NaN.
425
426 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
427 Known.knownNot(fcNan);
428 else if (KnownSrc.isKnownNever(fcSNan))
429 Known.knownNot(fcSNan);
430
431 return Known;
432}
434 DenormalMode Mode) {
435 // X % X is always exactly [+-]0.0 or a NaN.
436 KnownFPClass Known(fcNan | fcZero);
437
438 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
439 Known.knownNot(fcNan);
440 else if (KnownSrc.isKnownNever(fcSNan))
441 Known.knownNot(fcSNan);
442
443 return Known;
444}
445
447 const KnownFPClass &KnownRHS,
448 const KnownFPClass &KnownAddend,
449 DenormalMode Mode) {
450 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
451
452 // FMA differs from the base fmul + fadd handling only in the treatment of -0
453 // results.
454 //
455 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
456 // unlike for a separate fadd.
457 return fadd_impl(Mul, KnownAddend, Mode);
458}
459
461 const KnownFPClass &KnownAddend,
462 DenormalMode Mode) {
463 KnownFPClass Squared = square(KnownSquared, Mode);
464 KnownFPClass Known = fadd_impl(Squared, KnownAddend, Mode);
465
466 // Since we know the squared input must be positive, the add of opposite sign
467 // infinities nan hazard only applies for negative inf.
468 //
469 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
470 // not pinf. Other than the degenerate always-subnormal input case, we can't
471 // prove that without a known range.
472 if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
473 Known.knownNot(fcNan);
474
475 return Known;
476}
477
479 KnownFPClass Known;
480 Known.knownNot(fcNegative);
481
482 Known.propagateNaN(KnownSrc);
483
484 if (KnownSrc.cannotBeOrderedLessThanZero()) {
485 // If the source is positive this cannot underflow.
486 Known.knownNot(fcPosZero);
487
488 // Cannot introduce denormal values.
490 }
491
492 // If the source is negative, this cannot overflow to infinity.
493 if (KnownSrc.cannotBeOrderedGreaterThanZero())
494 Known.knownNot(fcPosInf);
495
496 return Known;
497}
498
500 DenormalMode Mode) {
501 propagateDenormal(Src, Mode);
502 propagateNaN(Src, /*PreserveSign=*/true);
503}
504
506 DenormalMode Mode) {
507 KnownFPClass Known;
509
510 if (KnownSrc.isKnownNeverPosInfinity())
511 Known.knownNot(fcPosInf);
512
513 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
514 Known.knownNot(fcNan);
515
516 if (KnownSrc.isKnownNeverLogicalZero(Mode))
517 Known.knownNot(fcNegInf);
518
519 return Known;
520}
521
523 DenormalMode Mode) {
524 KnownFPClass Known;
526
527 if (KnownSrc.isKnownNeverPosInfinity())
528 Known.knownNot(fcPosInf);
529 if (KnownSrc.isKnownNever(fcSNan))
530 Known.knownNot(fcSNan);
531
532 // Any negative value besides -0 returns a nan.
533 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
534 Known.knownNot(fcNan);
535
536 // The only negative value that can be returned is -0 for -0 inputs.
538
539 // If the input denormal mode could be PreserveSign, a negative
540 // subnormal input could produce a negative zero output.
541 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
542 Known.knownNot(fcNegZero);
543
544 return Known;
545}
546
548 KnownFPClass Known;
549
550 // Return NaN on infinite inputs.
551 Known.knownNot(fcInf);
552 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
553 Known.knownNot(fcNan);
554
555 return Known;
556}
557
559 return sin(KnownSrc);
560}
561
563 const fltSemantics &DstTy,
564 const fltSemantics &SrcTy) {
565 // Infinity, nan and zero propagate from source.
566 KnownFPClass Known = KnownSrc;
567
568 // All subnormal inputs should be in the normal range in the result type.
569 if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
570 if (Known.KnownFPClasses & fcPosSubnormal)
572 if (Known.KnownFPClasses & fcNegSubnormal)
574 Known.knownNot(fcSubnormal);
575 }
576
577 // Sign bit of a nan isn't guaranteed.
578 if (!Known.isKnownNeverNaN())
579 Known.SignBit = std::nullopt;
580
581 return Known;
582}
583
585 KnownFPClass Known;
586
587 // Sign should be preserved
588 // TODO: Handle cannot be ordered greater than zero
589 if (KnownSrc.cannotBeOrderedLessThanZero())
591
592 Known.propagateNaN(KnownSrc, true);
593
594 // Infinity needs a range check.
595 return Known;
596}
597
599 bool IsTrunc,
600 bool IsMultiUnitFPType) {
601 KnownFPClass Known;
602
603 // Integer results cannot be subnormal.
604 Known.knownNot(fcSubnormal);
605
606 Known.propagateNaN(KnownSrc, true);
607
608 // Pass through infinities, except PPC_FP128 is a special case for
609 // intrinsics other than trunc.
610 if (IsTrunc || !IsMultiUnitFPType) {
611 if (KnownSrc.isKnownNeverPosInfinity())
612 Known.knownNot(fcPosInf);
613 if (KnownSrc.isKnownNeverNegInfinity())
614 Known.knownNot(fcNegInf);
615 }
616
617 // Negative round ups to 0 produce -0
618 if (KnownSrc.isKnownNever(fcPosFinite))
619 Known.knownNot(fcPosFinite);
620 if (KnownSrc.isKnownNever(fcNegFinite))
621 Known.knownNot(fcNegFinite);
622
623 return Known;
624}
625
627 DenormalMode Mode) {
628 KnownFPClass Known;
629 Known.knownNot(fcSubnormal);
630
631 if (KnownSrc.isKnownNever(fcNegative))
632 Known.knownNot(fcNegative);
633 else {
634 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
635 Known.knownNot(fcNegZero);
636 if (KnownSrc.isKnownNever(fcNegInf))
637 Known.knownNot(fcNegInf);
638 }
639
640 if (KnownSrc.isKnownNever(fcPositive))
641 Known.knownNot(fcPositive);
642 else {
643 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
644 Known.knownNot(fcPosZero);
645 if (KnownSrc.isKnownNever(fcPosInf))
646 Known.knownNot(fcPosInf);
647 }
648
649 Known.propagateNaN(KnownSrc);
650 return Known;
651}
652
654 const KnownBits &ExpBits,
655 const fltSemantics &Flt, DenormalMode Mode) {
656 KnownFPClass Known;
657 Known.propagateNaN(KnownSrc, /*PropagateSign=*/true);
658
659 // Sign is preserved, but underflows may produce zeroes.
660 if (KnownSrc.isKnownNever(fcNegative))
661 Known.knownNot(fcNegative);
662 else if (KnownSrc.cannotBeOrderedLessThanZero())
664
665 if (KnownSrc.isKnownNever(fcPositive))
666 Known.knownNot(fcPositive);
667 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
669
670 unsigned Precision = APFloat::semanticsPrecision(Flt);
671 const int MantissaBits = Precision - 1;
672
673 if (ExpBits.getSignedMinValue().sge(static_cast<int64_t>(MantissaBits)))
674 Known.knownNot(fcSubnormal);
675
676 if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) {
677 // ldexp(x, 0) -> x, so propagate everything.
678 Known.propagateCanonicalizingSrc(KnownSrc, Mode);
679 } else if (ExpBits.isNegative()) {
680 // If we know the power is <= 0, can't introduce inf
681 if (KnownSrc.isKnownNeverPosInfinity())
682 Known.knownNot(fcPosInf);
683 if (KnownSrc.isKnownNeverNegInfinity())
684 Known.knownNot(fcNegInf);
685 } else if (ExpBits.isNonNegative()) {
686 // If we know the power is >= 0, can't introduce subnormal or zero
687 if (KnownSrc.isKnownNeverPosSubnormal())
689 if (KnownSrc.isKnownNeverNegSubnormal())
691 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
692 Known.knownNot(fcPosZero);
693 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
694 Known.knownNot(fcNegZero);
695 }
696
697 return Known;
698}
699
700// TODO: Detect no-infinity cases
702 const KnownBits &ExponentKnownBits) {
703 KnownFPClass Known;
704 Known.propagateNaN(KnownSrc);
705
706 if (ExponentKnownBits.isZero()) {
707 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
708 // return 1.0 or a NaN.
709 if (KnownSrc.isKnownNever(fcSNan)) {
710 Known.knownNot(~fcPosNormal);
711 return Known;
712 }
713
714 Known.knownNot(~(fcPosNormal | fcNan));
715 return Known;
716 }
717
718 if (ExponentKnownBits.isEven()) {
719 Known.knownNot(fcNegative);
720 return Known;
721 }
722
723 // Given that exp is an integer, here are the
724 // ways that pow can return a negative value:
725 //
726 // pow(-x, exp) --> negative if exp is odd and x is negative.
727 // pow(-0, exp) --> -inf if exp is negative odd.
728 // pow(-0, exp) --> -0 if exp is positive odd.
729 // pow(-inf, exp) --> -0 if exp is negative odd.
730 // pow(-inf, exp) --> -inf if exp is positive odd.
731 if (KnownSrc.isKnownNever(fcNegative))
732 Known.knownNot(fcNegative);
733
734 return Known;
735}
This file declares a class to represent arbitrary precision floating point values and provide a varie...
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:213
static LLVM_ABI bool isRepresentableAsNormalIn(const fltSemantics &Src, const fltSemantics &Dst)
Definition APFloat.cpp:263
cmpResult compareAbsoluteValue(const APFloat &RHS) const
Definition APFloat.h:1467
const fltSemantics & getSemantics() const
Definition APFloat.h:1520
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1139
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1244
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
int ilogb(const APFloat &Arg)
Returns the exponent of the internal representation of the APFloat.
Definition APFloat.h:1597
@ 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()
bool isNonNegative() const
Returns true if this value is known to be non-negative.
Definition KnownBits.h:108
bool isZero() const
Returns true if value is all zero.
Definition KnownBits.h:80
bool isConstant() const
Returns true if we know the value of all bits.
Definition KnownBits.h:54
bool isEven() const
Return if the value is known even (the low bit is 0).
Definition KnownBits.h:164
bool isNegative() const
Returns true if this value is known to be negative.
Definition KnownBits.h:105
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
Definition KnownBits.h:138
const APInt & getConstant() const
Returns the value when all bits have a known value.
Definition KnownBits.h:60
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
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.
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.
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.
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 ldexp(const KnownFPClass &Src, const KnownBits &N, const fltSemantics &Flt, DenormalMode Mode=DenormalMode::getDynamic())
Propagate known class for ldexp.
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 ...
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.
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.
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 fma_square(const KnownFPClass &Squared, const KnownFPClass &Addend, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for fma squared, squared, addend.
static LLVM_ABI KnownFPClass frem_self(const KnownFPClass &Src, DenormalMode Mode=DenormalMode::getDynamic())
Report known values for frem.
static LLVM_ABI KnownFPClass powi(const KnownFPClass &Src, const KnownBits &N)
Propagate known class for powi.
bool isKnownNeverPosSubnormal() const
Return true if it's known this can never be a positive subnormal.