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 // +X * +Y or -X * -Y => +Q
369 // +X * -Y or -X * +Y => -Q
370 Known.propagateXorSign(KnownLHS, KnownRHS);
371
372 // Inf * Y => Inf or NaN
373 if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
374 KnownRHS.isKnownAlways(fcInf | fcNan))
376
377 // 0 * Y => 0 or NaN
378 if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
379 KnownLHS.isKnownAlways(fcZero | fcNan))
381
382 if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
383 return Known;
384
385 // 0 * +/-inf => NaN
386 if ((KnownRHS.isKnownNeverInfinity() ||
387 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
388 (KnownLHS.isKnownNeverInfinity() ||
389 KnownRHS.isKnownNeverLogicalZero(Mode)))
390 Known.knownNot(fcNan);
391
392 return Known;
393}
394
395// TODO: This generalizes to known ranges
397 const APFloat &CRHS, DenormalMode Mode) {
398 // Match denormal scaling pattern, similar to the case in ldexp. If the
399 // constant's exponent is sufficiently large, the result cannot be subnormal.
400
401 const fltSemantics &Flt = CRHS.getSemantics();
402 unsigned Precision = APFloat::semanticsPrecision(Flt);
403 const int MantissaBits = Precision - 1;
404
405 int MinKnownExponent = ilogb(CRHS);
406 bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);
407
408 KnownFPClass Known = KnownFPClass::fmul(KnownLHS, KnownFPClass(CRHS), Mode);
409 if (CannotBeSubnormal)
410 Known.knownNot(fcSubnormal);
411
412 // Multiply of values <= 1 cannot introduce overflow.
413 if (KnownLHS.isKnownNever(fcInf)) {
414 if (MinKnownExponent < 0)
415 Known.knownNot(fcInf);
416 else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(APFloat::getOne(
417 Flt)) == APFloat::cmpEqual)
418 Known.knownNot(fcInf);
419 }
420
421 return Known;
422}
423
425 const KnownFPClass &KnownRHS,
426 DenormalMode Mode) {
427 KnownFPClass Known;
428
429 // Only 0/0, Inf/Inf produce NaN.
430 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
431 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
432 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
433 KnownRHS.isKnownNeverLogicalZero(Mode))) {
434 Known.knownNot(fcNan);
435 }
436
437 // X / -0.0 => -Inf (or NaN)
438 // +X / +Y or -X / -Y => +Q
439 // +X / -Y or -X / +Y => -Q
440 Known.propagateXorSign(KnownLHS, KnownRHS);
441
442 // 0 / X => 0 or NaN
443 if (KnownLHS.isKnownAlways(fcZero))
445
446 // X / 0 => NaN or Inf
447 if (KnownRHS.isKnownAlways(fcZero))
448 Known.knownNot(fcFinite);
449
450 return Known;
451}
452
454 DenormalMode Mode) {
455 // X / X is always exactly 1.0 or a NaN.
457
458 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
459 Known.knownNot(fcNan);
460 else if (KnownSrc.isKnownNever(fcSNan))
461 Known.knownNot(fcSNan);
462
463 return Known;
464}
466 DenormalMode Mode) {
467 // X % X is always exactly [+-]0.0 or a NaN.
468 KnownFPClass Known(fcNan | fcZero);
469
470 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
471 Known.knownNot(fcNan);
472 else if (KnownSrc.isKnownNever(fcSNan))
473 Known.knownNot(fcSNan);
474
475 return Known;
476}
477
479 const KnownFPClass &KnownRHS,
480 const KnownFPClass &KnownAddend,
481 DenormalMode Mode) {
482 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
483
484 // FMA differs from the base fmul + fadd handling only in the treatment of -0
485 // results.
486 //
487 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
488 // unlike for a separate fadd.
489 return fadd_impl(Mul, KnownAddend, Mode);
490}
491
493 const KnownFPClass &KnownAddend,
494 DenormalMode Mode) {
495 KnownFPClass Squared = square(KnownSquared, Mode);
496 KnownFPClass Known = fadd_impl(Squared, KnownAddend, Mode);
497
498 // Since we know the squared input must be positive, the add of opposite sign
499 // infinities nan hazard only applies for negative inf.
500 //
501 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
502 // not pinf. Other than the degenerate always-subnormal input case, we can't
503 // prove that without a known range.
504 if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
505 Known.knownNot(fcNan);
506
507 return Known;
508}
509
511 KnownFPClass Known;
512 Known.knownNot(fcNegative);
513
514 Known.propagateNaN(KnownSrc);
515
516 if (KnownSrc.cannotBeOrderedLessThanZero()) {
517 // If the source is positive this cannot underflow.
518 Known.knownNot(fcPosZero);
519
520 // Cannot introduce denormal values.
522 }
523
524 // If the source is negative, this cannot overflow to infinity.
525 if (KnownSrc.cannotBeOrderedGreaterThanZero())
526 Known.knownNot(fcPosInf);
527
528 return Known;
529}
530
532 DenormalMode Mode) {
533 propagateDenormal(Src, Mode);
534 propagateNaN(Src, /*PreserveSign=*/true);
535}
536
538 DenormalMode Mode) {
539 KnownFPClass Known;
541
542 if (KnownSrc.isKnownNeverPosInfinity())
543 Known.knownNot(fcPosInf);
544
545 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
546 Known.knownNot(fcNan);
547
548 if (KnownSrc.isKnownNeverLogicalZero(Mode))
549 Known.knownNot(fcNegInf);
550
551 return Known;
552}
553
555 DenormalMode Mode) {
556 KnownFPClass Known;
558
559 if (KnownSrc.isKnownNeverPosInfinity())
560 Known.knownNot(fcPosInf);
561 if (KnownSrc.isKnownNever(fcSNan))
562 Known.knownNot(fcSNan);
563
564 // Any negative value besides -0 returns a nan.
565 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
566 Known.knownNot(fcNan);
567
568 // The only negative value that can be returned is -0 for -0 inputs.
570
571 // If the input denormal mode could be PreserveSign, a negative
572 // subnormal input could produce a negative zero output.
573 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
574 Known.knownNot(fcNegZero);
575
576 return Known;
577}
578
580 KnownFPClass Known;
581
582 // Return NaN on infinite inputs.
583 Known.knownNot(fcInf);
584 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
585 Known.knownNot(fcNan);
586
587 return Known;
588}
589
591 return sin(KnownSrc);
592}
593
595 KnownFPClass Known;
596
597 // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
598 Known.knownNot(fcInf);
599
600 // NaN propagates. tan(+-Inf) is NaN.
601 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
602 Known.knownNot(fcNan);
603
604 return Known;
605}
606
608 KnownFPClass Known;
609
610 // sinh is sign-preserving: sinh(x) < 0 iff x < 0.
611 if (KnownSrc.isKnownNever(fcNegative))
612 Known.knownNot(fcNegative);
613
614 Known.propagateNaN(KnownSrc);
615
616 return Known;
617}
618
620 KnownFPClass Known;
621
622 // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative.
623 Known.knownNot(fcNegative);
624
625 Known.propagateNaN(KnownSrc);
626
627 return Known;
628}
629
631 KnownFPClass Known;
632
633 // tanh is bounded to (-1, 1), never Inf.
634 Known.knownNot(fcInf);
635
636 // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
637 if (KnownSrc.isKnownNever(fcNegative))
638 Known.knownNot(fcNegative);
639
640 Known.propagateNaN(KnownSrc);
641
642 return Known;
643}
644
646 KnownFPClass Known;
647
648 // asin is bounded to [-pi/2, pi/2], never Inf.
649 Known.knownNot(fcInf);
650
651 // asin is sign-preserving.
652 if (KnownSrc.isKnownNever(fcNegative))
653 Known.knownNot(fcNegative);
654
655 // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
656 // out NaN without knowing the source is in [-1, 1].
657 Known.propagateNaN(KnownSrc);
658
659 return Known;
660}
661
663 KnownFPClass Known;
664
665 // acos is bounded to [0, pi], never Inf or negative.
666 Known.knownNot(fcInf);
667 Known.knownNot(fcNegative);
668
669 // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
670 // out NaN without knowing the source is in [-1, 1].
671 Known.propagateNaN(KnownSrc);
672
673 return Known;
674}
675
677 KnownFPClass Known;
678
679 // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
680 Known.knownNot(fcInf);
681
682 // atan is sign-preserving: atan(x) < 0 iff x < 0.
683 if (KnownSrc.isKnownNever(fcNegative))
684 Known.knownNot(fcNegative);
685
686 Known.propagateNaN(KnownSrc);
687
688 return Known;
689}
690
692 const KnownFPClass &KnownRHS) {
693 KnownFPClass Known;
694
695 // atan2 result is in (-pi, pi], never Inf.
696 Known.knownNot(fcInf);
697
698 // NaN if either operand is NaN.
699 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
700 Known.knownNot(fcNan);
701
702 return Known;
703}
704
706 const fltSemantics &DstTy,
707 const fltSemantics &SrcTy) {
708 // Infinity, nan and zero propagate from source.
709 KnownFPClass Known = KnownSrc;
710
711 // All subnormal inputs should be in the normal range in the result type.
712 if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
713 if (Known.KnownFPClasses & fcPosSubnormal)
715 if (Known.KnownFPClasses & fcNegSubnormal)
717 Known.knownNot(fcSubnormal);
718 }
719
720 // Sign bit of a nan isn't guaranteed.
721 if (!Known.isKnownNeverNaN())
722 Known.SignBit = std::nullopt;
723
724 return Known;
725}
726
728 KnownFPClass Known;
729
730 // Sign should be preserved
731 // TODO: Handle cannot be ordered greater than zero
732 if (KnownSrc.cannotBeOrderedLessThanZero())
734
735 Known.propagateNaN(KnownSrc, true);
736
737 // Infinity needs a range check.
738 return Known;
739}
740
742 bool IsTrunc,
743 bool IsMultiUnitFPType) {
744 KnownFPClass Known;
745
746 // Integer results cannot be subnormal.
747 Known.knownNot(fcSubnormal);
748
749 Known.propagateNaN(KnownSrc, true);
750
751 // Pass through infinities, except PPC_FP128 is a special case for
752 // intrinsics other than trunc.
753 if (IsTrunc || !IsMultiUnitFPType) {
754 if (KnownSrc.isKnownNeverPosInfinity())
755 Known.knownNot(fcPosInf);
756 if (KnownSrc.isKnownNeverNegInfinity())
757 Known.knownNot(fcNegInf);
758 }
759
760 // Negative round ups to 0 produce -0
761 if (KnownSrc.isKnownNever(fcPosFinite))
762 Known.knownNot(fcPosFinite);
763 if (KnownSrc.isKnownNever(fcNegFinite))
764 Known.knownNot(fcNegFinite);
765
766 return Known;
767}
768
770 DenormalMode Mode) {
771 KnownFPClass Known;
772 Known.knownNot(fcSubnormal);
773
774 if (KnownSrc.isKnownNever(fcNegative))
775 Known.knownNot(fcNegative);
776 else {
777 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
778 Known.knownNot(fcNegZero);
779 if (KnownSrc.isKnownNever(fcNegInf))
780 Known.knownNot(fcNegInf);
781 }
782
783 if (KnownSrc.isKnownNever(fcPositive))
784 Known.knownNot(fcPositive);
785 else {
786 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
787 Known.knownNot(fcPosZero);
788 if (KnownSrc.isKnownNever(fcPosInf))
789 Known.knownNot(fcPosInf);
790 }
791
792 Known.propagateNaN(KnownSrc);
793 return Known;
794}
795
797 const KnownBits &ExpBits,
798 const fltSemantics &Flt, DenormalMode Mode) {
799 KnownFPClass Known;
800 Known.propagateNaN(KnownSrc, /*PropagateSign=*/true);
801
802 // Sign is preserved, but underflows may produce zeroes.
803 if (KnownSrc.isKnownNever(fcNegative))
804 Known.knownNot(fcNegative);
805 else if (KnownSrc.cannotBeOrderedLessThanZero())
807
808 if (KnownSrc.isKnownNever(fcPositive))
809 Known.knownNot(fcPositive);
810 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
812
813 unsigned Precision = APFloat::semanticsPrecision(Flt);
814 const int MantissaBits = Precision - 1;
815
816 if (ExpBits.getSignedMinValue().sge(static_cast<int64_t>(MantissaBits)))
817 Known.knownNot(fcSubnormal);
818
819 if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) {
820 // ldexp(x, 0) -> x, so propagate everything.
821 Known.propagateCanonicalizingSrc(KnownSrc, Mode);
822 } else if (ExpBits.isNegative()) {
823 // If we know the power is <= 0, can't introduce inf
824 if (KnownSrc.isKnownNeverPosInfinity())
825 Known.knownNot(fcPosInf);
826 if (KnownSrc.isKnownNeverNegInfinity())
827 Known.knownNot(fcNegInf);
828 } else if (ExpBits.isNonNegative()) {
829 // If we know the power is >= 0, can't introduce subnormal or zero
830 if (KnownSrc.isKnownNeverPosSubnormal())
832 if (KnownSrc.isKnownNeverNegSubnormal())
834 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
835 Known.knownNot(fcPosZero);
836 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
837 Known.knownNot(fcNegZero);
838 }
839
840 return Known;
841}
842
844 const KnownBits &ExponentKnownBits) {
845 KnownFPClass Known;
846 Known.propagateNaN(KnownSrc);
847
848 if (ExponentKnownBits.isZero()) {
849 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
850 // return 1.0 or a NaN.
851 if (KnownSrc.isKnownNever(fcSNan)) {
852 Known.knownNot(~fcPosNormal);
853 return Known;
854 }
855
856 Known.knownNot(~(fcPosNormal | fcNan));
857 return Known;
858 }
859
860 // powi(x, exp) --> inf
861 // when:
862 // * powi(inf, exp), exp > 0
863 // * powi(+/-0, exp), exp < 0
864 // * powi(finite, exp), |exp| > 1
865 // * powi(subnormal, -1)
866 // TODO:
867 // 1. This simple all or nothing approach. We can do better
868 // and cover sign/parity and exp > 1 vs exp < -1 separately.
869 // 2. powi(0/nan, exp), exp > 0 can be refinable
870 // to fcNan | fcZero | fcPosNormal.
871 {
872 APInt MinExp = ExponentKnownBits.getSignedMinValue();
873 APInt MaxExp = ExponentKnownBits.getSignedMaxValue();
874
875 // powi(inf, exp), exp > 0
876 bool MayInfSrc =
877 !KnownSrc.isKnownNever(fcInf) && MaxExp.isStrictlyPositive();
878
879 // powi(+/-0, exp), exp < 0
880 bool MayDivByZero = !KnownSrc.isKnownNever(fcZero) && MinExp.isNegative();
881
882 // powi(finite, exp), |exp| > 1
883 bool MayFinite = !KnownSrc.isKnownNever(fcNormal | fcSubnormal);
884 bool MayAbsExpGT1 = MinExp.slt(-1) || MaxExp.sgt(1);
885 bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;
886
887 // powi(subnormal, -1)
888 bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
889 bool MaySubnormInv = !KnownSrc.isKnownNever(fcSubnormal) && MayBeNegOne;
890
891 if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
892 Known.knownNot(fcInf);
893 }
894
895 if (ExponentKnownBits.isEven()) {
896 Known.knownNot(fcNegative);
897 return Known;
898 }
899
900 // Given that exp is an integer, here are the
901 // ways that pow can return a negative value:
902 //
903 // pow(-x, exp) --> negative if exp is odd and x is negative.
904 // pow(-0, exp) --> -inf if exp is negative odd.
905 // pow(-0, exp) --> -0 if exp is positive odd.
906 // pow(-inf, exp) --> -0 if exp is negative odd.
907 // pow(-inf, exp) --> -inf if exp is positive odd.
908 if (KnownSrc.isKnownNever(fcNegative))
909 Known.knownNot(fcNegative);
910
911 return Known;
912}
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:1489
const fltSemantics & getSemantics() const
Definition APFloat.h:1542
bool isNaN() const
Definition APFloat.h:1532
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
Class for arbitrary precision integers.
Definition APInt.h:78
bool sgt(const APInt &RHS) const
Signed greater than comparison.
Definition APInt.h:1208
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:330
bool isStrictlyPositive() const
Determine if this APInt Value is positive.
Definition APInt.h:357
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition APInt.h:1137
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:1619
@ 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 isNonNegative() const
Returns true if this value is known to be non-negative.
Definition KnownBits.h:106
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 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:162
bool isNegative() const
Returns true if this value is known to be negative.
Definition KnownBits.h:103
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
Definition KnownBits.h:136
const APInt & getConstant() const
Returns the value when all bits have a known value.
Definition KnownBits.h:58
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
void propagateXorSign(const KnownFPClass &LHS, const KnownFPClass &RHS)
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