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 (KnownLHS.SignBit && KnownRHS.SignBit) {
346 if (*KnownLHS.SignBit == *KnownRHS.SignBit)
347 Known.signBitMustBeZero();
348 else
349 Known.signBitMustBeOne();
350 }
351
352 // If 0 * +/-inf produces NaN.
353 if ((KnownRHS.isKnownNeverInfinity() ||
354 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
355 (KnownLHS.isKnownNeverInfinity() ||
356 KnownRHS.isKnownNeverLogicalZero(Mode)))
357 Known.knownNot(RuleOut: fcNan);
358
359 return Known;
360}
361
362KnownFPClass KnownFPClass::fdiv(const KnownFPClass &KnownLHS,
363 const KnownFPClass &KnownRHS,
364 DenormalMode Mode) {
365 KnownFPClass Known;
366
367 // Only 0/0, Inf/Inf produce NaN.
368 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
369 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
370 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
371 KnownRHS.isKnownNeverLogicalZero(Mode))) {
372 Known.knownNot(RuleOut: fcNan);
373 }
374
375 // xor sign bit.
376 // X / -0.0 is -Inf (or NaN).
377 // +X / +X is +X
378 if ((KnownLHS.isKnownNever(Mask: fcNegative) &&
379 KnownRHS.isKnownNever(Mask: fcNegative)) ||
380 (KnownLHS.isKnownNever(Mask: fcPositive) && KnownRHS.isKnownNever(Mask: fcPositive)))
381 Known.knownNot(RuleOut: fcNegative);
382
383 if ((KnownLHS.isKnownNever(Mask: fcPositive) &&
384 KnownRHS.isKnownNever(Mask: fcNegative)) ||
385 (KnownLHS.isKnownNever(Mask: fcNegative) && KnownRHS.isKnownNever(Mask: fcPositive)))
386 Known.knownNot(RuleOut: fcPositive);
387
388 // 0 / x => 0 or nan
389 if (KnownLHS.isKnownAlways(Mask: fcZero))
390 Known.knownNot(RuleOut: fcSubnormal | fcNormal | fcInf);
391
392 // x / 0 => nan or inf
393 if (KnownRHS.isKnownAlways(Mask: fcZero))
394 Known.knownNot(RuleOut: fcFinite);
395
396 return Known;
397}
398
399KnownFPClass KnownFPClass::fdiv_self(const KnownFPClass &KnownSrc,
400 DenormalMode Mode) {
401 // X / X is always exactly 1.0 or a NaN.
402 KnownFPClass Known(fcNan | fcPosNormal);
403
404 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
405 Known.knownNot(RuleOut: fcNan);
406 else if (KnownSrc.isKnownNever(Mask: fcSNan))
407 Known.knownNot(RuleOut: fcSNan);
408
409 return Known;
410}
411KnownFPClass KnownFPClass::frem_self(const KnownFPClass &KnownSrc,
412 DenormalMode Mode) {
413 // X % X is always exactly [+-]0.0 or a NaN.
414 KnownFPClass Known(fcNan | fcZero);
415
416 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
417 Known.knownNot(RuleOut: fcNan);
418 else if (KnownSrc.isKnownNever(Mask: fcSNan))
419 Known.knownNot(RuleOut: fcSNan);
420
421 return Known;
422}
423
424KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
425 const KnownFPClass &KnownRHS,
426 const KnownFPClass &KnownAddend,
427 DenormalMode Mode) {
428 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
429
430 // FMA differs from the base fmul + fadd handling only in the treatment of -0
431 // results.
432 //
433 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
434 // unlike for a separate fadd.
435 return fadd_impl(KnownLHS: Mul, KnownRHS: KnownAddend, Mode);
436}
437
438KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
439 const KnownFPClass &KnownAddend,
440 DenormalMode Mode) {
441 KnownFPClass Squared = square(Src: KnownSquared, Mode);
442 KnownFPClass Known = fadd_impl(KnownLHS: Squared, KnownRHS: KnownAddend, Mode);
443
444 // Since we know the squared input must be positive, the add of opposite sign
445 // infinities nan hazard only applies for negative inf.
446 //
447 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
448 // not pinf. Other than the degenerate always-subnormal input case, we can't
449 // prove that without a known range.
450 if (KnownAddend.isKnownNever(Mask: fcNegInf | fcNan) && Squared.isKnownNever(Mask: fcNan))
451 Known.knownNot(RuleOut: fcNan);
452
453 return Known;
454}
455
456KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
457 KnownFPClass Known;
458 Known.knownNot(RuleOut: fcNegative);
459
460 Known.propagateNaN(Src: KnownSrc);
461
462 if (KnownSrc.cannotBeOrderedLessThanZero()) {
463 // If the source is positive this cannot underflow.
464 Known.knownNot(RuleOut: fcPosZero);
465
466 // Cannot introduce denormal values.
467 Known.knownNot(RuleOut: fcPosSubnormal);
468 }
469
470 // If the source is negative, this cannot overflow to infinity.
471 if (KnownSrc.cannotBeOrderedGreaterThanZero())
472 Known.knownNot(RuleOut: fcPosInf);
473
474 return Known;
475}
476
477void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
478 DenormalMode Mode) {
479 propagateDenormal(Src, Mode);
480 propagateNaN(Src, /*PreserveSign=*/true);
481}
482
483KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
484 DenormalMode Mode) {
485 KnownFPClass Known;
486 Known.knownNot(RuleOut: fcNegZero | fcSubnormal);
487
488 if (KnownSrc.isKnownNeverPosInfinity())
489 Known.knownNot(RuleOut: fcPosInf);
490
491 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
492 Known.knownNot(RuleOut: fcNan);
493
494 if (KnownSrc.isKnownNeverLogicalZero(Mode))
495 Known.knownNot(RuleOut: fcNegInf);
496
497 return Known;
498}
499
500KnownFPClass KnownFPClass::sqrt(const KnownFPClass &KnownSrc,
501 DenormalMode Mode) {
502 KnownFPClass Known;
503 Known.knownNot(RuleOut: fcPosSubnormal);
504
505 if (KnownSrc.isKnownNeverPosInfinity())
506 Known.knownNot(RuleOut: fcPosInf);
507 if (KnownSrc.isKnownNever(Mask: fcSNan))
508 Known.knownNot(RuleOut: fcSNan);
509
510 // Any negative value besides -0 returns a nan.
511 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
512 Known.knownNot(RuleOut: fcNan);
513
514 // The only negative value that can be returned is -0 for -0 inputs.
515 Known.knownNot(RuleOut: fcNegInf | fcNegSubnormal | fcNegNormal);
516
517 // If the input denormal mode could be PreserveSign, a negative
518 // subnormal input could produce a negative zero output.
519 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
520 Known.knownNot(RuleOut: fcNegZero);
521
522 return Known;
523}
524
525KnownFPClass KnownFPClass::sin(const KnownFPClass &KnownSrc) {
526 KnownFPClass Known;
527
528 // Return NaN on infinite inputs.
529 Known.knownNot(RuleOut: fcInf);
530 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
531 Known.knownNot(RuleOut: fcNan);
532
533 return Known;
534}
535
536KnownFPClass KnownFPClass::cos(const KnownFPClass &KnownSrc) {
537 return sin(KnownSrc);
538}
539
540KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc,
541 const fltSemantics &DstTy,
542 const fltSemantics &SrcTy) {
543 // Infinity, nan and zero propagate from source.
544 KnownFPClass Known = KnownSrc;
545
546 // All subnormal inputs should be in the normal range in the result type.
547 if (APFloat::isRepresentableAsNormalIn(Src: SrcTy, Dst: DstTy)) {
548 if (Known.KnownFPClasses & fcPosSubnormal)
549 Known.KnownFPClasses |= fcPosNormal;
550 if (Known.KnownFPClasses & fcNegSubnormal)
551 Known.KnownFPClasses |= fcNegNormal;
552 Known.knownNot(RuleOut: fcSubnormal);
553 }
554
555 // Sign bit of a nan isn't guaranteed.
556 if (!Known.isKnownNeverNaN())
557 Known.SignBit = std::nullopt;
558
559 return Known;
560}
561
562KnownFPClass KnownFPClass::fptrunc(const KnownFPClass &KnownSrc) {
563 KnownFPClass Known;
564
565 // Sign should be preserved
566 // TODO: Handle cannot be ordered greater than zero
567 if (KnownSrc.cannotBeOrderedLessThanZero())
568 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
569
570 Known.propagateNaN(Src: KnownSrc, PreserveSign: true);
571
572 // Infinity needs a range check.
573 return Known;
574}
575
576KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc,
577 bool IsTrunc,
578 bool IsMultiUnitFPType) {
579 KnownFPClass Known;
580
581 // Integer results cannot be subnormal.
582 Known.knownNot(RuleOut: fcSubnormal);
583
584 Known.propagateNaN(Src: KnownSrc, PreserveSign: true);
585
586 // Pass through infinities, except PPC_FP128 is a special case for
587 // intrinsics other than trunc.
588 if (IsTrunc || !IsMultiUnitFPType) {
589 if (KnownSrc.isKnownNeverPosInfinity())
590 Known.knownNot(RuleOut: fcPosInf);
591 if (KnownSrc.isKnownNeverNegInfinity())
592 Known.knownNot(RuleOut: fcNegInf);
593 }
594
595 // Negative round ups to 0 produce -0
596 if (KnownSrc.isKnownNever(Mask: fcPosFinite))
597 Known.knownNot(RuleOut: fcPosFinite);
598 if (KnownSrc.isKnownNever(Mask: fcNegFinite))
599 Known.knownNot(RuleOut: fcNegFinite);
600
601 return Known;
602}
603
604KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
605 DenormalMode Mode) {
606 KnownFPClass Known;
607 Known.knownNot(RuleOut: fcSubnormal);
608
609 if (KnownSrc.isKnownNever(Mask: fcNegative))
610 Known.knownNot(RuleOut: fcNegative);
611 else {
612 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
613 Known.knownNot(RuleOut: fcNegZero);
614 if (KnownSrc.isKnownNever(Mask: fcNegInf))
615 Known.knownNot(RuleOut: fcNegInf);
616 }
617
618 if (KnownSrc.isKnownNever(Mask: fcPositive))
619 Known.knownNot(RuleOut: fcPositive);
620 else {
621 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
622 Known.knownNot(RuleOut: fcPosZero);
623 if (KnownSrc.isKnownNever(Mask: fcPosInf))
624 Known.knownNot(RuleOut: fcPosInf);
625 }
626
627 Known.propagateNaN(Src: KnownSrc);
628 return Known;
629}
630
631KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
632 const KnownBits &ExpBits,
633 const fltSemantics &Flt, DenormalMode Mode) {
634 KnownFPClass Known;
635 Known.propagateNaN(Src: KnownSrc, /*PropagateSign=*/PreserveSign: true);
636
637 // Sign is preserved, but underflows may produce zeroes.
638 if (KnownSrc.isKnownNever(Mask: fcNegative))
639 Known.knownNot(RuleOut: fcNegative);
640 else if (KnownSrc.cannotBeOrderedLessThanZero())
641 Known.knownNot(RuleOut: OrderedLessThanZeroMask);
642
643 if (KnownSrc.isKnownNever(Mask: fcPositive))
644 Known.knownNot(RuleOut: fcPositive);
645 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
646 Known.knownNot(RuleOut: OrderedGreaterThanZeroMask);
647
648 unsigned Precision = APFloat::semanticsPrecision(Flt);
649 const int MantissaBits = Precision - 1;
650
651 if (ExpBits.getSignedMinValue().sge(RHS: static_cast<int64_t>(MantissaBits)))
652 Known.knownNot(RuleOut: fcSubnormal);
653
654 if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) {
655 // ldexp(x, 0) -> x, so propagate everything.
656 Known.propagateCanonicalizingSrc(Src: KnownSrc, Mode);
657 } else if (ExpBits.isNegative()) {
658 // If we know the power is <= 0, can't introduce inf
659 if (KnownSrc.isKnownNeverPosInfinity())
660 Known.knownNot(RuleOut: fcPosInf);
661 if (KnownSrc.isKnownNeverNegInfinity())
662 Known.knownNot(RuleOut: fcNegInf);
663 } else if (ExpBits.isNonNegative()) {
664 // If we know the power is >= 0, can't introduce subnormal or zero
665 if (KnownSrc.isKnownNeverPosSubnormal())
666 Known.knownNot(RuleOut: fcPosSubnormal);
667 if (KnownSrc.isKnownNeverNegSubnormal())
668 Known.knownNot(RuleOut: fcNegSubnormal);
669 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
670 Known.knownNot(RuleOut: fcPosZero);
671 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
672 Known.knownNot(RuleOut: fcNegZero);
673 }
674
675 return Known;
676}
677
678KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
679 const KnownBits &ExponentKnownBits) {
680 KnownFPClass Known;
681 if (ExponentKnownBits.isEven()) {
682 Known.knownNot(RuleOut: fcNegative);
683 return Known;
684 }
685
686 // Given that exp is an integer, here are the
687 // ways that pow can return a negative value:
688 //
689 // pow(-x, exp) --> negative if exp is odd and x is negative.
690 // pow(-0, exp) --> -inf if exp is negative odd.
691 // pow(-0, exp) --> -0 if exp is positive odd.
692 // pow(-inf, exp) --> -0 if exp is negative odd.
693 // pow(-inf, exp) --> -inf if exp is positive odd.
694 if (KnownSrc.isKnownNever(Mask: fcNegative))
695 Known.knownNot(RuleOut: fcNegative);
696
697 return Known;
698}
699