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