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
14#include "llvm/Support/KnownFPClass.h"
15#include "llvm/ADT/APFloat.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/KnownBits.h"
18
19using namespace llvm;
20
21KnownFPClass::KnownFPClass(const APFloat &C)
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.
26static bool inputDenormalIsIEEE(DenormalMode Mode) {
27 return Mode.Input == DenormalMode::IEEE;
28}
29
30static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) {
31 return Mode.Input == DenormalMode::IEEE ||
32 Mode.Input == DenormalMode::PositiveZero;
33}
34
35bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const {
36 return isKnownNeverZero() &&
37 (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode));
38}
39
40bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const {
41 return isKnownNeverNegZero() &&
42 (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode));
43}
44
45bool KnownFPClass::isKnownNeverLogicalPosZero(DenormalMode Mode) const {
46 if (!isKnownNeverPosZero())
47 return false;
48
49 // If we know there are no denormals, nothing can be flushed to zero.
50 if (isKnownNeverSubnormal())
51 return true;
52
53 switch (Mode.Input) {
54 case DenormalMode::IEEE:
55 return true;
56 case DenormalMode::PreserveSign:
57 // Negative subnormal won't flush to +0
58 return isKnownNeverPosSubnormal();
59 case DenormalMode::PositiveZero:
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
68void KnownFPClass::propagateDenormal(const KnownFPClass &Src,
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())
81 KnownFPClasses |= fcPosZero;
82
83 if (!Src.isKnownNeverNegSubnormal() && Mode != DenormalMode::getIEEE()) {
84 if (Mode != DenormalMode::getPositiveZero())
85 KnownFPClasses |= fcNegZero;
86
87 if (Mode.Input == DenormalMode::PositiveZero ||
88 Mode.Output == DenormalMode::PositiveZero ||
89 Mode.Input == DenormalMode::Dynamic ||
90 Mode.Output == DenormalMode::Dynamic)
91 KnownFPClasses |= fcPosZero;
92 }
93}
94
95KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &LHS_,
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 ||
107 Kind == MinMaxKind::minimumnum || Kind == MinMaxKind::maximumnum))
108 Known.knownNot(RuleOut: 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()))
116 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
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() ||
121 KnownRHS.cannotBeOrderedLessThanZero())
122 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
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()))
130 Known.knownNot(RuleOut: KnownFPClass::OrderedGreaterThanZeroMask);
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() ||
135 KnownRHS.cannotBeOrderedGreaterThanZero())
136 Known.knownNot(RuleOut: KnownFPClass::OrderedGreaterThanZeroMask);
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
187KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc,
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(RuleOut: fcNan);
203 else
204 Known.knownNot(RuleOut: 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(Mask: fcPosZero))
212 Known.knownNot(RuleOut: fcPosZero);
213 if (KnownSrc.isKnownNever(Mask: fcNegZero))
214 Known.knownNot(RuleOut: fcNegZero);
215 return Known;
216 }
217
218 if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
219 Known.knownNot(RuleOut: fcSubnormal);
220
221 if (DenormMode == DenormalMode::getPreserveSign()) {
222 if (KnownSrc.isKnownNever(Mask: fcPosZero | fcPosSubnormal))
223 Known.knownNot(RuleOut: fcPosZero);
224 if (KnownSrc.isKnownNever(Mask: fcNegZero | fcNegSubnormal))
225 Known.knownNot(RuleOut: 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(RuleOut: fcNegZero);
233
234 return Known;
235}
236
237// Handle known sign bit and nan cases for fadd.
238static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
239 const KnownFPClass &KnownRHS, DenormalMode Mode) {
240 KnownFPClass Known;
241
242 // Adding positive and negative infinity produces NaN.
243 // TODO: Check sign of infinities.
244 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
245 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()))
246 Known.knownNot(RuleOut: fcNan);
247
248 if (KnownLHS.cannotBeOrderedLessThanZero() &&
249 KnownRHS.cannotBeOrderedLessThanZero()) {
250 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
251
252 // This can't underflow if one of the operands is known normal.
253 if (KnownLHS.isKnownNever(Mask: fcZero | fcPosSubnormal) ||
254 KnownRHS.isKnownNever(Mask: fcZero | fcPosSubnormal))
255 Known.knownNot(RuleOut: fcZero);
256 }
257
258 if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
259 KnownRHS.cannotBeOrderedGreaterThanZero()) {
260 Known.knownNot(RuleOut: KnownFPClass::OrderedGreaterThanZeroMask);
261
262 // This can't underflow if one of the operands is known normal.
263 if (KnownLHS.isKnownNever(Mask: fcZero | fcNegSubnormal) ||
264 KnownRHS.isKnownNever(Mask: fcZero | fcNegSubnormal))
265 Known.knownNot(RuleOut: fcZero);
266 }
267
268 return Known;
269}
270
271KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
272 const KnownFPClass &KnownRHS,
273 DenormalMode Mode) {
274 KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
275
276 // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
277 if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
278 KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
279 // Make sure output negative denormal can't flush to -0
280 (Mode.Output == DenormalMode::IEEE ||
281 Mode.Output == DenormalMode::PositiveZero))
282 Known.knownNot(RuleOut: fcNegZero);
283
284 return Known;
285}
286
287KnownFPClass KnownFPClass::fadd_self(const KnownFPClass &KnownSrc,
288 DenormalMode Mode) {
289 KnownFPClass Known = fadd(KnownLHS: KnownSrc, KnownRHS: KnownSrc, Mode);
290
291 // Doubling 0 will give the same 0.
292 if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
293 (Mode.Output == DenormalMode::IEEE ||
294 (Mode.Output == DenormalMode::PreserveSign &&
295 KnownSrc.isKnownNeverPosSubnormal()) ||
296 (Mode.Output == DenormalMode::PositiveZero &&
297 KnownSrc.isKnownNeverSubnormal())))
298 Known.knownNot(RuleOut: fcPosZero);
299
300 return Known;
301}
302
303KnownFPClass KnownFPClass::fsub(const KnownFPClass &KnownLHS,
304 const KnownFPClass &KnownRHS,
305 DenormalMode Mode) {
306 return fadd(KnownLHS, KnownRHS: fneg(Src: KnownRHS), Mode);
307}
308
309KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
310 const KnownFPClass &KnownRHS,
311 DenormalMode Mode) {
312 KnownFPClass Known;
313
314 // xor sign bit.
315 if ((KnownLHS.isKnownNever(Mask: fcNegative) &&
316 KnownRHS.isKnownNever(Mask: fcNegative)) ||
317 (KnownLHS.isKnownNever(Mask: fcPositive) && KnownRHS.isKnownNever(Mask: fcPositive)))
318 Known.knownNot(RuleOut: fcNegative);
319
320 if ((KnownLHS.isKnownNever(Mask: fcPositive) &&
321 KnownRHS.isKnownNever(Mask: fcNegative)) ||
322 (KnownLHS.isKnownNever(Mask: fcNegative) && KnownRHS.isKnownNever(Mask: fcPositive)))
323 Known.knownNot(RuleOut: fcPositive);
324
325 // inf * anything => inf or nan
326 if (KnownLHS.isKnownAlways(Mask: fcInf | fcNan) ||
327 KnownRHS.isKnownAlways(Mask: fcInf | fcNan))
328 Known.knownNot(RuleOut: fcNormal | fcSubnormal | fcZero);
329
330 // 0 * anything => 0 or nan
331 if (KnownRHS.isKnownAlways(Mask: fcZero | fcNan) ||
332 KnownLHS.isKnownAlways(Mask: fcZero | fcNan))
333 Known.knownNot(RuleOut: fcNormal | fcSubnormal | fcInf);
334
335 // +/-0 * +/-inf = nan
336 if ((KnownLHS.isKnownAlways(Mask: fcZero | fcNan) &&
337 KnownRHS.isKnownAlways(Mask: fcInf | fcNan)) ||
338 (KnownLHS.isKnownAlways(Mask: fcInf | fcNan) &&
339 KnownRHS.isKnownAlways(Mask: fcZero | fcNan)))
340 Known.knownNot(RuleOut: ~fcNan);
341
342 if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
343 return Known;
344
345 // If 0 * +/-inf produces NaN.
346 if ((KnownRHS.isKnownNeverInfinity() ||
347 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
348 (KnownLHS.isKnownNeverInfinity() ||
349 KnownRHS.isKnownNeverLogicalZero(Mode)))
350 Known.knownNot(RuleOut: fcNan);
351
352 return Known;
353}
354
355KnownFPClass KnownFPClass::fdiv(const KnownFPClass &KnownLHS,
356 const KnownFPClass &KnownRHS,
357 DenormalMode Mode) {
358 KnownFPClass Known;
359
360 // Only 0/0, Inf/Inf produce NaN.
361 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
362 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
363 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
364 KnownRHS.isKnownNeverLogicalZero(Mode))) {
365 Known.knownNot(RuleOut: fcNan);
366 }
367
368 // xor sign bit.
369 // X / -0.0 is -Inf (or NaN).
370 // +X / +X is +X
371 if ((KnownLHS.isKnownNever(Mask: fcNegative) &&
372 KnownRHS.isKnownNever(Mask: fcNegative)) ||
373 (KnownLHS.isKnownNever(Mask: fcPositive) && KnownRHS.isKnownNever(Mask: fcPositive)))
374 Known.knownNot(RuleOut: fcNegative);
375
376 if ((KnownLHS.isKnownNever(Mask: fcPositive) &&
377 KnownRHS.isKnownNever(Mask: fcNegative)) ||
378 (KnownLHS.isKnownNever(Mask: fcNegative) && KnownRHS.isKnownNever(Mask: fcPositive)))
379 Known.knownNot(RuleOut: fcPositive);
380
381 // 0 / x => 0 or nan
382 if (KnownLHS.isKnownAlways(Mask: fcZero))
383 Known.knownNot(RuleOut: fcSubnormal | fcNormal | fcInf);
384
385 // x / 0 => nan or inf
386 if (KnownRHS.isKnownAlways(Mask: fcZero))
387 Known.knownNot(RuleOut: fcFinite);
388
389 return Known;
390}
391
392KnownFPClass KnownFPClass::fdiv_self(const KnownFPClass &KnownSrc,
393 DenormalMode Mode) {
394 // X / X is always exactly 1.0 or a NaN.
395 KnownFPClass Known(fcNan | fcPosNormal);
396
397 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
398 Known.knownNot(RuleOut: fcNan);
399 else if (KnownSrc.isKnownNever(Mask: fcSNan))
400 Known.knownNot(RuleOut: fcSNan);
401
402 return Known;
403}
404KnownFPClass KnownFPClass::frem_self(const KnownFPClass &KnownSrc,
405 DenormalMode Mode) {
406 // X % X is always exactly [+-]0.0 or a NaN.
407 KnownFPClass Known(fcNan | fcZero);
408
409 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
410 Known.knownNot(RuleOut: fcNan);
411 else if (KnownSrc.isKnownNever(Mask: fcSNan))
412 Known.knownNot(RuleOut: fcSNan);
413
414 return Known;
415}
416
417KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
418 const KnownFPClass &KnownRHS,
419 const KnownFPClass &KnownAddend,
420 DenormalMode Mode) {
421 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
422
423 // FMA differs from the base fmul + fadd handling only in the treatment of -0
424 // results.
425 //
426 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
427 // unlike for a separate fadd.
428 return fadd_impl(KnownLHS: Mul, KnownRHS: KnownAddend, Mode);
429}
430
431KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
432 const KnownFPClass &KnownAddend,
433 DenormalMode Mode) {
434 KnownFPClass Squared = square(Src: KnownSquared, Mode);
435 KnownFPClass Known = fadd_impl(KnownLHS: Squared, KnownRHS: KnownAddend, Mode);
436
437 // Since we know the squared input must be positive, the add of opposite sign
438 // infinities nan hazard only applies for negative inf.
439 //
440 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
441 // not pinf. Other than the degenerate always-subnormal input case, we can't
442 // prove that without a known range.
443 if (KnownAddend.isKnownNever(Mask: fcNegInf | fcNan) && Squared.isKnownNever(Mask: fcNan))
444 Known.knownNot(RuleOut: fcNan);
445
446 return Known;
447}
448
449KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
450 KnownFPClass Known;
451 Known.knownNot(RuleOut: fcNegative);
452
453 Known.propagateNaN(Src: KnownSrc);
454
455 if (KnownSrc.cannotBeOrderedLessThanZero()) {
456 // If the source is positive this cannot underflow.
457 Known.knownNot(RuleOut: fcPosZero);
458
459 // Cannot introduce denormal values.
460 Known.knownNot(RuleOut: fcPosSubnormal);
461 }
462
463 // If the source is negative, this cannot overflow to infinity.
464 if (KnownSrc.cannotBeOrderedGreaterThanZero())
465 Known.knownNot(RuleOut: fcPosInf);
466
467 return Known;
468}
469
470void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
471 DenormalMode Mode) {
472 propagateDenormal(Src, Mode);
473 propagateNaN(Src, /*PreserveSign=*/true);
474}
475
476KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
477 DenormalMode Mode) {
478 KnownFPClass Known;
479 Known.knownNot(RuleOut: fcNegZero | fcSubnormal);
480
481 if (KnownSrc.isKnownNeverPosInfinity())
482 Known.knownNot(RuleOut: fcPosInf);
483
484 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
485 Known.knownNot(RuleOut: fcNan);
486
487 if (KnownSrc.isKnownNeverLogicalZero(Mode))
488 Known.knownNot(RuleOut: fcNegInf);
489
490 return Known;
491}
492
493KnownFPClass KnownFPClass::sqrt(const KnownFPClass &KnownSrc,
494 DenormalMode Mode) {
495 KnownFPClass Known;
496 Known.knownNot(RuleOut: fcPosSubnormal);
497
498 if (KnownSrc.isKnownNeverPosInfinity())
499 Known.knownNot(RuleOut: fcPosInf);
500 if (KnownSrc.isKnownNever(Mask: fcSNan))
501 Known.knownNot(RuleOut: fcSNan);
502
503 // Any negative value besides -0 returns a nan.
504 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
505 Known.knownNot(RuleOut: fcNan);
506
507 // The only negative value that can be returned is -0 for -0 inputs.
508 Known.knownNot(RuleOut: fcNegInf | fcNegSubnormal | fcNegNormal);
509
510 // If the input denormal mode could be PreserveSign, a negative
511 // subnormal input could produce a negative zero output.
512 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
513 Known.knownNot(RuleOut: fcNegZero);
514
515 return Known;
516}
517
518KnownFPClass KnownFPClass::sin(const KnownFPClass &KnownSrc) {
519 KnownFPClass Known;
520
521 // Return NaN on infinite inputs.
522 Known.knownNot(RuleOut: fcInf);
523 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
524 Known.knownNot(RuleOut: fcNan);
525
526 return Known;
527}
528
529KnownFPClass KnownFPClass::cos(const KnownFPClass &KnownSrc) {
530 return sin(KnownSrc);
531}
532
533KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc,
534 const fltSemantics &DstTy,
535 const fltSemantics &SrcTy) {
536 // Infinity, nan and zero propagate from source.
537 KnownFPClass Known = KnownSrc;
538
539 // All subnormal inputs should be in the normal range in the result type.
540 if (APFloat::isRepresentableAsNormalIn(Src: SrcTy, Dst: DstTy)) {
541 if (Known.KnownFPClasses & fcPosSubnormal)
542 Known.KnownFPClasses |= fcPosNormal;
543 if (Known.KnownFPClasses & fcNegSubnormal)
544 Known.KnownFPClasses |= fcNegNormal;
545 Known.knownNot(RuleOut: fcSubnormal);
546 }
547
548 // Sign bit of a nan isn't guaranteed.
549 if (!Known.isKnownNeverNaN())
550 Known.SignBit = std::nullopt;
551
552 return Known;
553}
554
555KnownFPClass KnownFPClass::fptrunc(const KnownFPClass &KnownSrc) {
556 KnownFPClass Known;
557
558 // Sign should be preserved
559 // TODO: Handle cannot be ordered greater than zero
560 if (KnownSrc.cannotBeOrderedLessThanZero())
561 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
562
563 Known.propagateNaN(Src: KnownSrc, PreserveSign: true);
564
565 // Infinity needs a range check.
566 return Known;
567}
568
569KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc,
570 bool IsTrunc,
571 bool IsMultiUnitFPType) {
572 KnownFPClass Known;
573
574 // Integer results cannot be subnormal.
575 Known.knownNot(RuleOut: fcSubnormal);
576
577 Known.propagateNaN(Src: KnownSrc, PreserveSign: true);
578
579 // Pass through infinities, except PPC_FP128 is a special case for
580 // intrinsics other than trunc.
581 if (IsTrunc || !IsMultiUnitFPType) {
582 if (KnownSrc.isKnownNeverPosInfinity())
583 Known.knownNot(RuleOut: fcPosInf);
584 if (KnownSrc.isKnownNeverNegInfinity())
585 Known.knownNot(RuleOut: fcNegInf);
586 }
587
588 // Negative round ups to 0 produce -0
589 if (KnownSrc.isKnownNever(Mask: fcPosFinite))
590 Known.knownNot(RuleOut: fcPosFinite);
591 if (KnownSrc.isKnownNever(Mask: fcNegFinite))
592 Known.knownNot(RuleOut: fcNegFinite);
593
594 return Known;
595}
596
597KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
598 DenormalMode Mode) {
599 KnownFPClass Known;
600 Known.knownNot(RuleOut: fcSubnormal);
601
602 if (KnownSrc.isKnownNever(Mask: fcNegative))
603 Known.knownNot(RuleOut: fcNegative);
604 else {
605 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
606 Known.knownNot(RuleOut: fcNegZero);
607 if (KnownSrc.isKnownNever(Mask: fcNegInf))
608 Known.knownNot(RuleOut: fcNegInf);
609 }
610
611 if (KnownSrc.isKnownNever(Mask: fcPositive))
612 Known.knownNot(RuleOut: fcPositive);
613 else {
614 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
615 Known.knownNot(RuleOut: fcPosZero);
616 if (KnownSrc.isKnownNever(Mask: fcPosInf))
617 Known.knownNot(RuleOut: fcPosInf);
618 }
619
620 Known.propagateNaN(Src: KnownSrc);
621 return Known;
622}
623
624KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
625 const KnownBits &ExpBits,
626 const fltSemantics &Flt, DenormalMode Mode) {
627 KnownFPClass Known;
628 Known.propagateNaN(Src: KnownSrc, /*PropagateSign=*/PreserveSign: true);
629
630 // Sign is preserved, but underflows may produce zeroes.
631 if (KnownSrc.isKnownNever(Mask: fcNegative))
632 Known.knownNot(RuleOut: fcNegative);
633 else if (KnownSrc.cannotBeOrderedLessThanZero())
634 Known.knownNot(RuleOut: OrderedLessThanZeroMask);
635
636 if (KnownSrc.isKnownNever(Mask: fcPositive))
637 Known.knownNot(RuleOut: fcPositive);
638 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
639 Known.knownNot(RuleOut: OrderedGreaterThanZeroMask);
640
641 unsigned Precision = APFloat::semanticsPrecision(Flt);
642 const int MantissaBits = Precision - 1;
643
644 if (ExpBits.getSignedMinValue().sge(RHS: static_cast<int64_t>(MantissaBits)))
645 Known.knownNot(RuleOut: fcSubnormal);
646
647 if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) {
648 // ldexp(x, 0) -> x, so propagate everything.
649 Known.propagateCanonicalizingSrc(Src: KnownSrc, Mode);
650 } else if (ExpBits.isNegative()) {
651 // If we know the power is <= 0, can't introduce inf
652 if (KnownSrc.isKnownNeverPosInfinity())
653 Known.knownNot(RuleOut: fcPosInf);
654 if (KnownSrc.isKnownNeverNegInfinity())
655 Known.knownNot(RuleOut: fcNegInf);
656 } else if (ExpBits.isNonNegative()) {
657 // If we know the power is >= 0, can't introduce subnormal or zero
658 if (KnownSrc.isKnownNeverPosSubnormal())
659 Known.knownNot(RuleOut: fcPosSubnormal);
660 if (KnownSrc.isKnownNeverNegSubnormal())
661 Known.knownNot(RuleOut: fcNegSubnormal);
662 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
663 Known.knownNot(RuleOut: fcPosZero);
664 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
665 Known.knownNot(RuleOut: fcNegZero);
666 }
667
668 return Known;
669}
670
671// TODO: Detect no-infinity cases
672KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
673 const KnownBits &ExponentKnownBits) {
674 KnownFPClass Known;
675 Known.propagateNaN(Src: KnownSrc);
676
677 if (ExponentKnownBits.isZero()) {
678 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
679 // return 1.0 or a NaN.
680 if (KnownSrc.isKnownNever(Mask: fcSNan)) {
681 Known.knownNot(RuleOut: ~fcPosNormal);
682 return Known;
683 }
684
685 Known.knownNot(RuleOut: ~(fcPosNormal | fcNan));
686 return Known;
687 }
688
689 if (ExponentKnownBits.isEven()) {
690 Known.knownNot(RuleOut: fcNegative);
691 return Known;
692 }
693
694 // Given that exp is an integer, here are the
695 // ways that pow can return a negative value:
696 //
697 // pow(-x, exp) --> negative if exp is odd and x is negative.
698 // pow(-0, exp) --> -inf if exp is negative odd.
699 // pow(-0, exp) --> -0 if exp is positive odd.
700 // pow(-inf, exp) --> -0 if exp is negative odd.
701 // pow(-inf, exp) --> -inf if exp is positive odd.
702 if (KnownSrc.isKnownNever(Mask: fcNegative))
703 Known.knownNot(RuleOut: fcNegative);
704
705 return Known;
706}
707