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
238 const KnownBits &Bits) {
239 assert(FltSemantics.sizeInBits == Bits.getBitWidth() &&
240 "Bitcast operand has incorrect bit width");
241 KnownFPClass Known;
242
243 // Transfer information from the sign bit.
244 if (Bits.isNonNegative())
245 Known.signBitMustBeZero();
246 else if (Bits.isNegative())
247 Known.signBitMustBeOne();
248
249 if (APFloat::isIEEELikeFP(FltSemantics)) {
250 // IEEE floats are NaN when all bits of the exponent plus at least one of
251 // the fraction bits are 1. This means:
252 // - If we assume unknown bits are 0 and the value is NaN, it will
253 // always be NaN
254 // - If we assume unknown bits are 1 and the value is not NaN, it can
255 // never be NaN
256 // Note: They do not hold for x86_fp80 format.
257 if (APFloat(FltSemantics, Bits.One).isNaN())
258 Known.KnownFPClasses = fcNan;
259 else if (!APFloat(FltSemantics, ~Bits.Zero).isNaN())
260 Known.knownNot(fcNan);
261
262 // Build KnownBits representing Inf and check if it must be equal or
263 // unequal to this value.
264 auto InfKB =
265 KnownBits::makeConstant(APFloat::getInf(FltSemantics).bitcastToAPInt());
266 InfKB.Zero.clearSignBit();
267 if (const auto InfResult = KnownBits::eq(Bits, InfKB)) {
268 assert(!InfResult.value());
269 Known.knownNot(fcInf);
270 } else if (Bits == InfKB) {
271 Known.KnownFPClasses = fcInf;
272 }
273
274 // Build KnownBits representing Zero and check if it must be equal or
275 // unequal to this value.
276 auto ZeroKB = KnownBits::makeConstant(
277 APFloat::getZero(FltSemantics).bitcastToAPInt());
278 ZeroKB.Zero.clearSignBit();
279 if (const auto ZeroResult = KnownBits::eq(Bits, ZeroKB)) {
280 assert(!ZeroResult.value());
281 Known.knownNot(fcZero);
282 } else if (Bits == ZeroKB) {
283 Known.KnownFPClasses = fcZero;
284 }
285 }
286
287 return Known;
288}
289
290// Handle known sign bit and nan cases for fadd.
291static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
292 const KnownFPClass &KnownRHS, DenormalMode Mode) {
293 KnownFPClass Known;
294
295 // Adding positive and negative infinity produces NaN, but only if both
296 // opposite-sign infinity combinations are possible.
297 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
298 (KnownLHS.isKnownNever(fcPosInf) || KnownRHS.isKnownNever(fcNegInf)) &&
299 (KnownLHS.isKnownNever(fcNegInf) || KnownRHS.isKnownNever(fcPosInf)))
300 Known.knownNot(fcNan);
301
302 if (KnownLHS.cannotBeOrderedLessThanZero() &&
303 KnownRHS.cannotBeOrderedLessThanZero()) {
305
306 // This can't underflow if one of the operands is known normal.
307 if (KnownLHS.isKnownNever(fcZero | fcPosSubnormal) ||
310 }
311
312 if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
315
316 // This can't underflow if one of the operands is known normal.
317 if (KnownLHS.isKnownNever(fcZero | fcNegSubnormal) ||
320 }
321
322 return Known;
323}
324
326 const KnownFPClass &KnownRHS,
327 DenormalMode Mode) {
328 KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
329
330 // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
331 if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
332 KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
333 // Make sure output negative denormal can't flush to -0
334 (Mode.Output == DenormalMode::IEEE ||
335 Mode.Output == DenormalMode::PositiveZero))
336 Known.knownNot(fcNegZero);
337
338 return Known;
339}
340
342 DenormalMode Mode) {
343 KnownFPClass Known = fadd(KnownSrc, KnownSrc, Mode);
344
345 // Doubling 0 will give the same 0.
346 if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
347 (Mode.Output == DenormalMode::IEEE ||
348 (Mode.Output == DenormalMode::PreserveSign &&
349 KnownSrc.isKnownNeverPosSubnormal()) ||
350 (Mode.Output == DenormalMode::PositiveZero &&
351 KnownSrc.isKnownNeverSubnormal())))
352 Known.knownNot(fcPosZero);
353
354 return Known;
355}
356
358 const KnownFPClass &KnownRHS,
359 DenormalMode Mode) {
360 return fadd(KnownLHS, fneg(KnownRHS), Mode);
361}
362
364 const KnownFPClass &KnownRHS,
365 DenormalMode Mode) {
366 KnownFPClass Known;
367
368 // xor sign bit.
369 if ((KnownLHS.isKnownNever(fcNegative) &&
370 KnownRHS.isKnownNever(fcNegative)) ||
371 (KnownLHS.isKnownNever(fcPositive) && KnownRHS.isKnownNever(fcPositive)))
372 Known.knownNot(fcNegative);
373
374 if ((KnownLHS.isKnownNever(fcPositive) &&
375 KnownRHS.isKnownNever(fcNegative)) ||
376 (KnownLHS.isKnownNever(fcNegative) && KnownRHS.isKnownNever(fcPositive)))
377 Known.knownNot(fcPositive);
378
379 // inf * anything => inf or nan
380 if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
381 KnownRHS.isKnownAlways(fcInf | fcNan))
383
384 // 0 * anything => 0 or nan
385 if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
386 KnownLHS.isKnownAlways(fcZero | fcNan))
388
389 // +/-0 * +/-inf = nan
390 if ((KnownLHS.isKnownAlways(fcZero | fcNan) &&
391 KnownRHS.isKnownAlways(fcInf | fcNan)) ||
392 (KnownLHS.isKnownAlways(fcInf | fcNan) &&
393 KnownRHS.isKnownAlways(fcZero | fcNan)))
394 Known.knownNot(~fcNan);
395
396 if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
397 return Known;
398
399 // If 0 * +/-inf produces NaN.
400 if ((KnownRHS.isKnownNeverInfinity() ||
401 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
402 (KnownLHS.isKnownNeverInfinity() ||
403 KnownRHS.isKnownNeverLogicalZero(Mode)))
404 Known.knownNot(fcNan);
405
406 return Known;
407}
408
409// TODO: This generalizes to known ranges
411 const APFloat &CRHS, DenormalMode Mode) {
412 // Match denormal scaling pattern, similar to the case in ldexp. If the
413 // constant's exponent is sufficiently large, the result cannot be subnormal.
414
415 const fltSemantics &Flt = CRHS.getSemantics();
416 unsigned Precision = APFloat::semanticsPrecision(Flt);
417 const int MantissaBits = Precision - 1;
418
419 int MinKnownExponent = ilogb(CRHS);
420 bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);
421
422 KnownFPClass Known = KnownFPClass::fmul(KnownLHS, KnownFPClass(CRHS), Mode);
423 if (CannotBeSubnormal)
424 Known.knownNot(fcSubnormal);
425
426 // Multiply of values <= 1 cannot introduce overflow.
427 if (KnownLHS.isKnownNever(fcInf)) {
428 if (MinKnownExponent < 0)
429 Known.knownNot(fcInf);
430 else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(APFloat::getOne(
431 Flt)) == APFloat::cmpEqual)
432 Known.knownNot(fcInf);
433 }
434
435 return Known;
436}
437
439 const KnownFPClass &KnownRHS,
440 DenormalMode Mode) {
441 KnownFPClass Known;
442
443 // Only 0/0, Inf/Inf produce NaN.
444 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
445 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
446 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
447 KnownRHS.isKnownNeverLogicalZero(Mode))) {
448 Known.knownNot(fcNan);
449 }
450
451 // xor sign bit.
452 // X / -0.0 is -Inf (or NaN).
453 // +X / +X is +X
454 if ((KnownLHS.isKnownNever(fcNegative) &&
455 KnownRHS.isKnownNever(fcNegative)) ||
456 (KnownLHS.isKnownNever(fcPositive) && KnownRHS.isKnownNever(fcPositive)))
457 Known.knownNot(fcNegative);
458
459 if ((KnownLHS.isKnownNever(fcPositive) &&
460 KnownRHS.isKnownNever(fcNegative)) ||
461 (KnownLHS.isKnownNever(fcNegative) && KnownRHS.isKnownNever(fcPositive)))
462 Known.knownNot(fcPositive);
463
464 // 0 / x => 0 or nan
465 if (KnownLHS.isKnownAlways(fcZero))
467
468 // x / 0 => nan or inf
469 if (KnownRHS.isKnownAlways(fcZero))
470 Known.knownNot(fcFinite);
471
472 return Known;
473}
474
476 DenormalMode Mode) {
477 // X / X is always exactly 1.0 or a NaN.
479
480 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
481 Known.knownNot(fcNan);
482 else if (KnownSrc.isKnownNever(fcSNan))
483 Known.knownNot(fcSNan);
484
485 return Known;
486}
488 DenormalMode Mode) {
489 // X % X is always exactly [+-]0.0 or a NaN.
490 KnownFPClass Known(fcNan | fcZero);
491
492 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
493 Known.knownNot(fcNan);
494 else if (KnownSrc.isKnownNever(fcSNan))
495 Known.knownNot(fcSNan);
496
497 return Known;
498}
499
501 const KnownFPClass &KnownRHS,
502 const KnownFPClass &KnownAddend,
503 DenormalMode Mode) {
504 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
505
506 // FMA differs from the base fmul + fadd handling only in the treatment of -0
507 // results.
508 //
509 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
510 // unlike for a separate fadd.
511 return fadd_impl(Mul, KnownAddend, Mode);
512}
513
515 const KnownFPClass &KnownAddend,
516 DenormalMode Mode) {
517 KnownFPClass Squared = square(KnownSquared, Mode);
518 KnownFPClass Known = fadd_impl(Squared, KnownAddend, Mode);
519
520 // Since we know the squared input must be positive, the add of opposite sign
521 // infinities nan hazard only applies for negative inf.
522 //
523 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
524 // not pinf. Other than the degenerate always-subnormal input case, we can't
525 // prove that without a known range.
526 if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
527 Known.knownNot(fcNan);
528
529 return Known;
530}
531
533 KnownFPClass Known;
534 Known.knownNot(fcNegative);
535
536 Known.propagateNaN(KnownSrc);
537
538 if (KnownSrc.cannotBeOrderedLessThanZero()) {
539 // If the source is positive this cannot underflow.
540 Known.knownNot(fcPosZero);
541
542 // Cannot introduce denormal values.
544 }
545
546 // If the source is negative, this cannot overflow to infinity.
547 if (KnownSrc.cannotBeOrderedGreaterThanZero())
548 Known.knownNot(fcPosInf);
549
550 return Known;
551}
552
554 DenormalMode Mode) {
555 propagateDenormal(Src, Mode);
556 propagateNaN(Src, /*PreserveSign=*/true);
557}
558
560 DenormalMode Mode) {
561 KnownFPClass Known;
563
564 if (KnownSrc.isKnownNeverPosInfinity())
565 Known.knownNot(fcPosInf);
566
567 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
568 Known.knownNot(fcNan);
569
570 if (KnownSrc.isKnownNeverLogicalZero(Mode))
571 Known.knownNot(fcNegInf);
572
573 return Known;
574}
575
577 DenormalMode Mode) {
578 KnownFPClass Known;
580
581 if (KnownSrc.isKnownNeverPosInfinity())
582 Known.knownNot(fcPosInf);
583 if (KnownSrc.isKnownNever(fcSNan))
584 Known.knownNot(fcSNan);
585
586 // Any negative value besides -0 returns a nan.
587 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
588 Known.knownNot(fcNan);
589
590 // The only negative value that can be returned is -0 for -0 inputs.
592
593 // If the input denormal mode could be PreserveSign, a negative
594 // subnormal input could produce a negative zero output.
595 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
596 Known.knownNot(fcNegZero);
597
598 return Known;
599}
600
602 KnownFPClass Known;
603
604 // Return NaN on infinite inputs.
605 Known.knownNot(fcInf);
606 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
607 Known.knownNot(fcNan);
608
609 return Known;
610}
611
613 return sin(KnownSrc);
614}
615
617 KnownFPClass Known;
618
619 // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
620 Known.knownNot(fcInf);
621
622 // NaN propagates. tan(+-Inf) is NaN.
623 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
624 Known.knownNot(fcNan);
625
626 return Known;
627}
628
630 KnownFPClass Known;
631
632 // sinh is sign-preserving: sinh(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
642 KnownFPClass Known;
643
644 // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative.
645 Known.knownNot(fcNegative);
646
647 Known.propagateNaN(KnownSrc);
648
649 return Known;
650}
651
653 KnownFPClass Known;
654
655 // tanh is bounded to (-1, 1), never Inf.
656 Known.knownNot(fcInf);
657
658 // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
659 if (KnownSrc.isKnownNever(fcNegative))
660 Known.knownNot(fcNegative);
661
662 Known.propagateNaN(KnownSrc);
663
664 return Known;
665}
666
668 KnownFPClass Known;
669
670 // asin is bounded to [-pi/2, pi/2], never Inf.
671 Known.knownNot(fcInf);
672
673 // asin is sign-preserving.
674 if (KnownSrc.isKnownNever(fcNegative))
675 Known.knownNot(fcNegative);
676
677 // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
678 // out NaN without knowing the source is in [-1, 1].
679 Known.propagateNaN(KnownSrc);
680
681 return Known;
682}
683
685 KnownFPClass Known;
686
687 // acos is bounded to [0, pi], never Inf or negative.
688 Known.knownNot(fcInf);
689 Known.knownNot(fcNegative);
690
691 // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
692 // out NaN without knowing the source is in [-1, 1].
693 Known.propagateNaN(KnownSrc);
694
695 return Known;
696}
697
699 KnownFPClass Known;
700
701 // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
702 Known.knownNot(fcInf);
703
704 // atan is sign-preserving: atan(x) < 0 iff x < 0.
705 if (KnownSrc.isKnownNever(fcNegative))
706 Known.knownNot(fcNegative);
707
708 Known.propagateNaN(KnownSrc);
709
710 return Known;
711}
712
714 const KnownFPClass &KnownRHS) {
715 KnownFPClass Known;
716
717 // atan2 result is in (-pi, pi], never Inf.
718 Known.knownNot(fcInf);
719
720 // NaN if either operand is NaN.
721 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
722 Known.knownNot(fcNan);
723
724 return Known;
725}
726
728 const fltSemantics &DstTy,
729 const fltSemantics &SrcTy) {
730 // Infinity, nan and zero propagate from source.
731 KnownFPClass Known = KnownSrc;
732
733 // All subnormal inputs should be in the normal range in the result type.
734 if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
735 if (Known.KnownFPClasses & fcPosSubnormal)
737 if (Known.KnownFPClasses & fcNegSubnormal)
739 Known.knownNot(fcSubnormal);
740 }
741
742 // Sign bit of a nan isn't guaranteed.
743 if (!Known.isKnownNeverNaN())
744 Known.SignBit = std::nullopt;
745
746 return Known;
747}
748
750 KnownFPClass Known;
751
752 // Sign should be preserved
753 // TODO: Handle cannot be ordered greater than zero
754 if (KnownSrc.cannotBeOrderedLessThanZero())
756
757 Known.propagateNaN(KnownSrc, true);
758
759 // Infinity needs a range check.
760 return Known;
761}
762
764 bool IsTrunc,
765 bool IsMultiUnitFPType) {
766 KnownFPClass Known;
767
768 // Integer results cannot be subnormal.
769 Known.knownNot(fcSubnormal);
770
771 Known.propagateNaN(KnownSrc, true);
772
773 // Pass through infinities, except PPC_FP128 is a special case for
774 // intrinsics other than trunc.
775 if (IsTrunc || !IsMultiUnitFPType) {
776 if (KnownSrc.isKnownNeverPosInfinity())
777 Known.knownNot(fcPosInf);
778 if (KnownSrc.isKnownNeverNegInfinity())
779 Known.knownNot(fcNegInf);
780 }
781
782 // Negative round ups to 0 produce -0
783 if (KnownSrc.isKnownNever(fcPosFinite))
784 Known.knownNot(fcPosFinite);
785 if (KnownSrc.isKnownNever(fcNegFinite))
786 Known.knownNot(fcNegFinite);
787
788 return Known;
789}
790
792 DenormalMode Mode) {
793 KnownFPClass Known;
794 Known.knownNot(fcSubnormal);
795
796 if (KnownSrc.isKnownNever(fcNegative))
797 Known.knownNot(fcNegative);
798 else {
799 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
800 Known.knownNot(fcNegZero);
801 if (KnownSrc.isKnownNever(fcNegInf))
802 Known.knownNot(fcNegInf);
803 }
804
805 if (KnownSrc.isKnownNever(fcPositive))
806 Known.knownNot(fcPositive);
807 else {
808 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
809 Known.knownNot(fcPosZero);
810 if (KnownSrc.isKnownNever(fcPosInf))
811 Known.knownNot(fcPosInf);
812 }
813
814 Known.propagateNaN(KnownSrc);
815 return Known;
816}
817
819 const KnownBits &ExpBits,
820 const fltSemantics &Flt, DenormalMode Mode) {
821 KnownFPClass Known;
822 Known.propagateNaN(KnownSrc, /*PropagateSign=*/true);
823
824 // Sign is preserved, but underflows may produce zeroes.
825 if (KnownSrc.isKnownNever(fcNegative))
826 Known.knownNot(fcNegative);
827 else if (KnownSrc.cannotBeOrderedLessThanZero())
829
830 if (KnownSrc.isKnownNever(fcPositive))
831 Known.knownNot(fcPositive);
832 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
834
835 unsigned Precision = APFloat::semanticsPrecision(Flt);
836 const int MantissaBits = Precision - 1;
837
838 if (ExpBits.getSignedMinValue().sge(static_cast<int64_t>(MantissaBits)))
839 Known.knownNot(fcSubnormal);
840
841 if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) {
842 // ldexp(x, 0) -> x, so propagate everything.
843 Known.propagateCanonicalizingSrc(KnownSrc, Mode);
844 } else if (ExpBits.isNegative()) {
845 // If we know the power is <= 0, can't introduce inf
846 if (KnownSrc.isKnownNeverPosInfinity())
847 Known.knownNot(fcPosInf);
848 if (KnownSrc.isKnownNeverNegInfinity())
849 Known.knownNot(fcNegInf);
850 } else if (ExpBits.isNonNegative()) {
851 // If we know the power is >= 0, can't introduce subnormal or zero
852 if (KnownSrc.isKnownNeverPosSubnormal())
854 if (KnownSrc.isKnownNeverNegSubnormal())
856 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
857 Known.knownNot(fcPosZero);
858 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
859 Known.knownNot(fcNegZero);
860 }
861
862 return Known;
863}
864
865// TODO: Detect no-infinity cases
867 const KnownBits &ExponentKnownBits) {
868 KnownFPClass Known;
869 Known.propagateNaN(KnownSrc);
870
871 if (ExponentKnownBits.isZero()) {
872 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
873 // return 1.0 or a NaN.
874 if (KnownSrc.isKnownNever(fcSNan)) {
875 Known.knownNot(~fcPosNormal);
876 return Known;
877 }
878
879 Known.knownNot(~(fcPosNormal | fcNan));
880 return Known;
881 }
882
883 if (ExponentKnownBits.isEven()) {
884 Known.knownNot(fcNegative);
885 return Known;
886 }
887
888 // Given that exp is an integer, here are the
889 // ways that pow can return a negative value:
890 //
891 // pow(-x, exp) --> negative if exp is odd and x is negative.
892 // pow(-0, exp) --> -inf if exp is negative odd.
893 // pow(-0, exp) --> -0 if exp is positive odd.
894 // pow(-inf, exp) --> -0 if exp is negative odd.
895 // pow(-inf, exp) --> -inf if exp is positive odd.
896 if (KnownSrc.isKnownNever(fcNegative))
897 Known.knownNot(fcNegative);
898
899 return Known;
900}
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 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:214
static LLVM_ABI bool isRepresentableAsNormalIn(const fltSemantics &Src, const fltSemantics &Dst)
Definition APFloat.cpp:264
static LLVM_ABI bool isIEEELikeFP(const fltSemantics &)
Definition APFloat.cpp:255
cmpResult compareAbsoluteValue(const APFloat &RHS) const
Definition APFloat.h:1471
const fltSemantics & getSemantics() const
Definition APFloat.h:1524
bool isNaN() const
Definition APFloat.h:1514
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1143
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1153
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1134
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.
int ilogb(const APFloat &Arg)
Returns the exponent of the internal representation of the APFloat.
Definition APFloat.h:1601
@ 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:317
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 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.
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 ldexp(const KnownFPClass &Src, const KnownBits &N, const fltSemantics &Flt, DenormalMode Mode=DenormalMode::getDynamic())
Propagate known class for ldexp.
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 -...
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 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 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:1007