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 : KnownFPClassesValue(C.classify()) {
23 setSignBit(C.isNegative());
24}
25
26KnownFPClass KnownFPClass::applyInputDenormalMode(const KnownFPClass &KnownSrc,
27 DenormalMode Mode) {
28 KnownFPClass Known = KnownSrc;
29 switch (Mode.Input) {
30 case DenormalMode::IEEE:
31 return Known;
32 case DenormalMode::PreserveSign:
33 if (KnownSrc.getKnownFPClasses() & fcPosSubnormal)
34 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosZero);
35 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
36 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegZero);
37 return Known;
38 case DenormalMode::PositiveZero:
39 if (KnownSrc.getKnownFPClasses() & fcSubnormal) {
40 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosZero);
41 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
42 Known.setSignBit(std::nullopt);
43 }
44 return Known;
45 default:
46 if (KnownSrc.getKnownFPClasses() & fcSubnormal) {
47 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosZero);
48 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
49 Known.setSignBit(std::nullopt);
50 }
51 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
52 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegZero);
53 return Known;
54 }
55
56 llvm_unreachable("covered switch over denormal mode");
57}
58
59KnownFPClass KnownFPClass::applyOutputDenormalMode(const KnownFPClass &KnownSrc,
60 DenormalMode Mode) {
61 KnownFPClass Known = KnownSrc;
62 switch (Mode.Output) {
63 case DenormalMode::IEEE:
64 return Known;
65 case DenormalMode::PreserveSign:
66 if (KnownSrc.getKnownFPClasses() & fcPosSubnormal)
67 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosZero);
68 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
69 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegZero);
70 return Known;
71 case DenormalMode::PositiveZero:
72 if (KnownSrc.getKnownFPClasses() & fcSubnormal) {
73 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosZero);
74 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
75 Known.setSignBit(std::nullopt);
76 }
77 return Known;
78 default:
79 if (KnownSrc.getKnownFPClasses() & fcSubnormal) {
80 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosZero);
81 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
82 Known.setSignBit(std::nullopt);
83 }
84 if (KnownSrc.getKnownFPClasses() & fcNegSubnormal)
85 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegZero);
86 return Known;
87 }
88
89 llvm_unreachable("covered switch over denormal mode");
90}
91
92bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const {
93 return applyInputDenormalMode(KnownSrc: *this, Mode).isKnownNeverZero();
94}
95
96bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const {
97 return applyInputDenormalMode(KnownSrc: *this, Mode).isKnownNeverNegZero();
98}
99
100bool KnownFPClass::isKnownNeverLogicalPosZero(DenormalMode Mode) const {
101 return applyInputDenormalMode(KnownSrc: *this, Mode).isKnownNeverPosZero();
102}
103
104KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &KnownLHS_,
105 const KnownFPClass &KnownRHS_,
106 MinMaxKind Kind, DenormalMode Mode) {
107 KnownFPClass KnownLHS = applyInputDenormalMode(KnownSrc: KnownLHS_, Mode);
108 KnownFPClass KnownRHS = applyInputDenormalMode(KnownSrc: KnownRHS_, Mode);
109
110 KnownFPClass Known;
111
112 Known.propagateNonNaN(LHS: KnownLHS, RHS: KnownRHS);
113
114 // The *num functions return the non-NaN operand if only one operand is NaN.
115 // FIXME: minnum/maxnum may return a NaN if either operand is a signaling NaN.
116 if ((KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN()) &&
117 (Kind == MinMaxKind::minnum || Kind == MinMaxKind::maxnum ||
118 Kind == MinMaxKind::minimumnum || Kind == MinMaxKind::maximumnum))
119 Known.knownNot(RuleOut: fcNan);
120
121 switch (Kind) {
122 case MinMaxKind::maxnum: {
123 if (KnownLHS.isKnownNeverNaN())
124 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownLHS.getKnownFPClasses(),
125 /*OrderedZeroSign=*/false));
126 if (KnownRHS.isKnownNeverNaN())
127 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownRHS.getKnownFPClasses(),
128 /*OrderedZeroSign=*/false));
129 break;
130 }
131 case MinMaxKind::minnum: {
132 if (KnownLHS.isKnownNeverNaN())
133 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownLHS.getKnownFPClasses(),
134 /*OrderedZeroSign=*/false));
135 if (KnownRHS.isKnownNeverNaN())
136 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownRHS.getKnownFPClasses(),
137 /*OrderedZeroSign=*/false));
138 break;
139 }
140 case MinMaxKind::maximumnum: {
141 if (KnownLHS.isKnownNeverNaN())
142 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownLHS.getKnownFPClasses(),
143 /*OrderedZeroSign=*/true));
144 if (KnownRHS.isKnownNeverNaN())
145 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownRHS.getKnownFPClasses(),
146 /*OrderedZeroSign=*/true));
147 break;
148 }
149 case MinMaxKind::minimumnum: {
150 if (KnownLHS.isKnownNeverNaN())
151 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownLHS.getKnownFPClasses(),
152 /*OrderedZeroSign=*/true));
153 if (KnownRHS.isKnownNeverNaN())
154 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownRHS.getKnownFPClasses(),
155 /*OrderedZeroSign=*/true));
156 break;
157 }
158 case MinMaxKind::maximum: {
159 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownLHS.getKnownFPClasses(),
160 /*OrderedZeroSign=*/true) |
161 orderedStrictlyLess(Mask: KnownRHS.getKnownFPClasses(),
162 /*OrderedZeroSign=*/true));
163 break;
164 }
165 case MinMaxKind::minimum: {
166 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownLHS.getKnownFPClasses(),
167 /*OrderedZeroSign=*/true) |
168 orderedStrictlyGreater(Mask: KnownRHS.getKnownFPClasses(),
169 /*OrderedZeroSign=*/true));
170 break;
171 }
172 }
173
174 // Remove impossible non-NaN classes.
175 FPClassTest PossibleClasses =
176 KnownLHS.getKnownFPClasses() | KnownRHS.getKnownFPClasses() | fcNan;
177 Known.knownNot(RuleOut: ~PossibleClasses);
178
179 return applyOutputDenormalMode(KnownSrc: Known, Mode);
180}
181
182KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc,
183 DenormalMode DenormMode) {
184 KnownFPClass Known;
185
186 // Canonicalize may flush denormals to zero, so we have to consider the
187 // denormal mode to preserve known-not-0 knowledge.
188 Known.setKnownFPClasses(KnownSrc.getKnownFPClasses() | fcZero | fcQNan);
189
190 // Stronger version of propagateNaN
191 // Canonicalize is guaranteed to quiet signaling nans.
192 if (KnownSrc.isKnownNeverNaN())
193 Known.knownNot(RuleOut: fcNan);
194 else
195 Known.knownNot(RuleOut: fcSNan);
196
197 // FIXME: Missing check of IEEE like types.
198
199 // If the parent function flushes denormals, the canonical output cannot be a
200 // denormal.
201 if (DenormMode == DenormalMode::getIEEE()) {
202 if (KnownSrc.isKnownNever(Mask: fcPosZero))
203 Known.knownNot(RuleOut: fcPosZero);
204 if (KnownSrc.isKnownNever(Mask: fcNegZero))
205 Known.knownNot(RuleOut: fcNegZero);
206 return Known;
207 }
208
209 if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
210 Known.knownNot(RuleOut: fcSubnormal);
211
212 if (DenormMode == DenormalMode::getPreserveSign()) {
213 if (KnownSrc.isKnownNever(Mask: fcPosZero | fcPosSubnormal))
214 Known.knownNot(RuleOut: fcPosZero);
215 if (KnownSrc.isKnownNever(Mask: fcNegZero | fcNegSubnormal))
216 Known.knownNot(RuleOut: fcNegZero);
217 return Known;
218 }
219
220 if (DenormMode.Input == DenormalMode::PositiveZero ||
221 (DenormMode.Output == DenormalMode::PositiveZero &&
222 DenormMode.Input == DenormalMode::IEEE)) {
223 // -0.0 is not a subnormal and should not be flushed.
224 if (KnownSrc.isKnownNever(Mask: fcNegZero))
225 Known.knownNot(RuleOut: fcNegZero);
226
227 if (KnownSrc.isKnownNever(Mask: fcPosZero | fcSubnormal))
228 Known.knownNot(RuleOut: fcPosZero);
229 }
230
231 return Known;
232}
233
234KnownFPClass KnownFPClass::bitcast(const fltSemantics &FltSemantics,
235 const KnownBits &Bits) {
236 assert(FltSemantics.sizeInBits == Bits.getBitWidth() &&
237 "Bitcast operand has incorrect bit width");
238 KnownFPClass Known;
239
240 // Conflicting known bits do not describe a concrete value. Return unknown.
241 if (Bits.hasConflict())
242 return Known;
243
244 // Return unknown for types we have not validated.
245 auto IsSupported = [](const fltSemantics &Semantics) {
246 switch (APFloat::SemanticsToEnum(Sem: Semantics)) {
247 case APFloatBase::S_IEEEhalf:
248 case APFloatBase::S_BFloat:
249 case APFloatBase::S_IEEEsingle:
250 case APFloatBase::S_IEEEdouble:
251 case APFloatBase::S_IEEEquad:
252 case APFloatBase::S_x87DoubleExtended:
253 return true;
254 default:
255 return false;
256 }
257 };
258 if (!IsSupported(FltSemantics))
259 return Known;
260
261 // Transfer information from the sign bit.
262 if (Bits.isNonNegative())
263 Known.signBitMustBeZero();
264 else if (Bits.isNegative())
265 Known.signBitMustBeOne();
266
267 switch (APFloatBase::SemanticsToEnum(Sem: FltSemantics)) {
268 case APFloatBase::S_IEEEhalf:
269 case APFloatBase::S_BFloat:
270 case APFloatBase::S_IEEEsingle:
271 case APFloatBase::S_IEEEdouble:
272 case APFloatBase::S_IEEEquad: {
273 const unsigned MantissaBits = FltSemantics.precision - 1;
274 const APInt ExponentMask = APInt::getBitsSet(
275 numBits: FltSemantics.sizeInBits, loBit: MantissaBits, hiBit: FltSemantics.sizeInBits - 1);
276 const APInt MantissaMask =
277 APInt::getLowBitsSet(numBits: FltSemantics.sizeInBits, loBitsSet: MantissaBits);
278
279 const bool ExponentKnownAllZeros =
280 (Bits.Zero & ExponentMask) == ExponentMask;
281 const bool ExponentKnownAllOnes = (Bits.One & ExponentMask) == ExponentMask;
282 const bool ExponentKnownNotAllZeros = !(Bits.One & ExponentMask).isZero();
283 const bool ExponentKnownNotAllOnes = !(Bits.Zero & ExponentMask).isZero();
284
285 const bool MantissaKnownAllZeros =
286 (Bits.Zero & MantissaMask) == MantissaMask;
287 const bool MantissaKnownNotAllZeros = !(Bits.One & MantissaMask).isZero();
288
289 // Zero and subnormal require an exponent with all zero bits.
290 if (ExponentKnownNotAllZeros)
291 Known.knownNot(RuleOut: fcZero | fcSubnormal);
292
293 // Infinity and NaN require an exponent with all one bits.
294 if (ExponentKnownNotAllOnes)
295 Known.knownNot(RuleOut: fcInf | fcNan);
296
297 // Normal values have an exponent that is not all zeros or all ones.
298 if (ExponentKnownAllZeros || ExponentKnownAllOnes)
299 Known.knownNot(RuleOut: fcNormal);
300
301 // Zero and infinity require a mantissa with all zero bits.
302 if (MantissaKnownNotAllZeros)
303 Known.knownNot(RuleOut: fcZero | fcInf);
304
305 // Subnormal and NaN require a non-zero mantissa.
306 if (MantissaKnownAllZeros)
307 Known.knownNot(RuleOut: fcSubnormal | fcNan);
308
309 const bool QuietBitKnownSet = Bits.One[MantissaBits - 1];
310 const bool QuietBitKnownClear = Bits.Zero[MantissaBits - 1];
311
312 if (QuietBitKnownSet)
313 Known.knownNot(RuleOut: fcSNan);
314 else if (QuietBitKnownClear)
315 Known.knownNot(RuleOut: fcQNan);
316
317 break;
318 }
319 case APFloatBase::S_x87DoubleExtended: {
320 // Layout of the x87 floating point type:
321 // [0:62] fraction
322 // [63] explicit integer bit
323 // [64:78] exponent
324 // [79] sign bit
325 // APFloat treats the x87 pseudo encodings as documented in
326 // fltSemantics::hasExplicitIntegerBit.
327 constexpr unsigned BitWidth = 80;
328 constexpr unsigned FractionBits = 63;
329 constexpr unsigned IntegerBitIndex = FractionBits;
330 const APInt FractionMask = APInt::getLowBitsSet(numBits: BitWidth, loBitsSet: FractionBits);
331 const APInt ExponentMask =
332 APInt::getBitsSet(numBits: BitWidth, loBit: FractionBits + 1, hiBit: BitWidth - 1);
333
334 const bool ExponentKnownAllZeros =
335 (Bits.Zero & ExponentMask) == ExponentMask;
336 const bool ExponentKnownAllOnes = (Bits.One & ExponentMask) == ExponentMask;
337 const bool ExponentKnownNotAllZeros = !(Bits.One & ExponentMask).isZero();
338 const bool ExponentKnownNotAllOnes = !(Bits.Zero & ExponentMask).isZero();
339 const bool FractionKnownAllZeros =
340 (Bits.Zero & FractionMask) == FractionMask;
341 const bool FractionKnownNotAllZeros = !(Bits.One & FractionMask).isZero();
342 const bool IntegerBitKnownSet = Bits.One[IntegerBitIndex];
343 const bool IntegerBitKnownClear = Bits.Zero[IntegerBitIndex];
344
345 // zero and subnormal require an exponent with all zero bits and a cleared
346 // integer bit.
347 if (ExponentKnownNotAllZeros || IntegerBitKnownSet)
348 Known.knownNot(RuleOut: fcZero | fcSubnormal);
349
350 // Zero requires a zero fraction.
351 if (FractionKnownNotAllZeros)
352 Known.knownNot(RuleOut: fcZero);
353
354 // Infinity requires an exponent with all one bits, a set integer bit, and
355 // a zero fraction.
356 if (ExponentKnownNotAllOnes || IntegerBitKnownClear ||
357 FractionKnownNotAllZeros)
358 Known.knownNot(RuleOut: fcInf);
359
360 // A normal x87 value has its integer bit set. A zero exponent with that
361 // bit set is the x87 pseudodenormal encoding, which APFloat treats as
362 // normal.
363 if (IntegerBitKnownClear || ExponentKnownAllOnes)
364 Known.knownNot(RuleOut: fcNormal);
365
366 // A subnormal has a nonzero fraction; NaNs are possible with a zero
367 // fraction through pseudoinfinity and unnormal encodings.
368 if (FractionKnownAllZeros)
369 Known.knownNot(RuleOut: fcSubnormal);
370
371 // We can rule out NaN if the value has all exponent bits set to zero, or
372 // if the value is a canonical normal or infinity.
373 if (ExponentKnownAllZeros ||
374 (IntegerBitKnownSet &&
375 (ExponentKnownNotAllOnes || FractionKnownAllZeros)))
376 Known.knownNot(RuleOut: fcNan);
377
378 const bool QuietBitKnownSet = Bits.One[FractionBits - 1];
379 const bool QuietBitKnownClear = Bits.Zero[FractionBits - 1];
380
381 if (QuietBitKnownSet)
382 Known.knownNot(RuleOut: fcSNan);
383 else if (QuietBitKnownClear)
384 Known.knownNot(RuleOut: fcQNan);
385
386 break;
387 }
388 default:
389 llvm_unreachable("unhandled supported type");
390 }
391
392 return Known;
393}
394
395KnownBits KnownFPClass::toKnownBits(const fltSemantics &FltSemantics) const {
396 KnownBits Known(FltSemantics.sizeInBits);
397 const FPClassTest FPClasses = getKnownFPClasses();
398
399 // Return unknown if poison.
400 if (FPClasses == fcNone)
401 return Known;
402
403 // Return unknown for types we have not validated.
404 auto IsSupported = [](const fltSemantics &Semantics) {
405 switch (APFloat::SemanticsToEnum(Sem: Semantics)) {
406 case APFloatBase::S_IEEEhalf:
407 case APFloatBase::S_BFloat:
408 case APFloatBase::S_IEEEsingle:
409 case APFloatBase::S_IEEEdouble:
410 case APFloatBase::S_IEEEquad:
411 case APFloatBase::S_x87DoubleExtended:
412 return true;
413 default:
414 return false;
415 }
416 };
417 if (!IsSupported(FltSemantics))
418 return Known;
419
420 switch (APFloat::SemanticsToEnum(Sem: FltSemantics)) {
421 case APFloatBase::S_IEEEhalf:
422 case APFloatBase::S_BFloat:
423 case APFloatBase::S_IEEEsingle:
424 case APFloatBase::S_IEEEdouble:
425 case APFloatBase::S_IEEEquad: {
426 // For ieee types, we cannot deduce anything if the source could be normal.
427 if (FPClasses & fcNormal)
428 break;
429
430 Known.setAllConflict();
431
432 const unsigned BitWidth = FltSemantics.sizeInBits;
433 const unsigned MantissaBits = FltSemantics.precision - 1;
434 const unsigned ExponentBits = BitWidth - MantissaBits - 1;
435
436 APInt MantissaMask = APInt::getLowBitsSet(numBits: BitWidth, loBitsSet: MantissaBits);
437 APInt ExponentMask =
438 APInt::getBitsSet(numBits: BitWidth, loBit: MantissaBits, hiBit: MantissaBits + ExponentBits);
439
440 const unsigned QuietBitIndex = MantissaBits - 1;
441 APInt PayloadMask = MantissaMask;
442 PayloadMask.clearBit(BitPosition: QuietBitIndex);
443
444 if (FPClasses & fcNan) {
445 // Exponent bits cannot be zeros.
446 Known.Zero &= ~ExponentMask;
447 // No individual payload bit is known.
448 Known.Zero &= ~PayloadMask;
449 Known.One &= ~PayloadMask;
450
451 if (FPClasses & fcQNan)
452 Known.Zero.clearBit(BitPosition: QuietBitIndex);
453 if (FPClasses & fcSNan)
454 Known.One.clearBit(BitPosition: QuietBitIndex);
455 }
456 if (FPClasses & fcInf) {
457 // Exponent bits cannot be zeros.
458 Known.Zero &= ~ExponentMask;
459 // Mantissa bits cannot be ones.
460 Known.One &= ~MantissaMask;
461 }
462 if (FPClasses & fcSubnormal) {
463 // Exponent bits cannot be ones.
464 Known.One &= ~ExponentMask;
465 // Unknown mantissa.
466 Known.One &= ~MantissaMask;
467 Known.Zero &= ~MantissaMask;
468 }
469 if (FPClasses & fcZero) {
470 // Exponent bits cannot be ones.
471 Known.One &= ~ExponentMask;
472 // Mantissa cannot be ones.
473 Known.One &= ~MantissaMask;
474 }
475
476 break;
477 }
478 case APFloatBase::S_x87DoubleExtended: {
479 if (!isKnownNever(Mask: fcNormal | fcSubnormal | fcNan))
480 break;
481
482 Known.setAllConflict();
483
484 if (FPClasses & fcInf)
485 Known = Known.intersectWith(RHS: KnownBits::makeConstant(
486 C: APFloat::getInf(Sem: FltSemantics).bitcastToAPInt()));
487
488 if (FPClasses & fcZero)
489 Known = Known.intersectWith(
490 RHS: KnownBits::makeConstant(C: APInt::getZero(numBits: FltSemantics.sizeInBits)));
491
492 break;
493 }
494 default:
495 llvm_unreachable("unhandled supported semantics");
496 }
497
498 Known.Zero.clearSignBit();
499 Known.One.clearSignBit();
500 if (std::optional<bool> Sign = getSignBit()) {
501 if (*Sign)
502 Known.makeNegative();
503 else
504 Known.makeNonNegative();
505 }
506
507 return Known;
508}
509
510// Handle known sign bit and nan cases for fadd.
511static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
512 const KnownFPClass &KnownRHS, DenormalMode Mode) {
513 KnownFPClass Known;
514
515 // Adding positive and negative infinity produces NaN, but only if both
516 // opposite-sign infinity combinations are possible.
517 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
518 (KnownLHS.isKnownNever(Mask: fcPosInf) || KnownRHS.isKnownNever(Mask: fcNegInf)) &&
519 (KnownLHS.isKnownNever(Mask: fcNegInf) || KnownRHS.isKnownNever(Mask: fcPosInf)))
520 Known.knownNot(RuleOut: fcNan);
521
522 if (KnownLHS.cannotBeOrderedLessThanZero() &&
523 KnownRHS.cannotBeOrderedLessThanZero()) {
524 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
525
526 // This can't underflow if one of the operands is known normal.
527 if (KnownLHS.isKnownNever(Mask: fcZero | fcPosSubnormal) ||
528 KnownRHS.isKnownNever(Mask: fcZero | fcPosSubnormal))
529 Known.knownNot(RuleOut: fcZero | fcPosSubnormal);
530 }
531
532 if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
533 KnownRHS.cannotBeOrderedGreaterThanZero()) {
534 Known.knownNot(RuleOut: KnownFPClass::OrderedGreaterThanZeroMask);
535
536 // This can't underflow if one of the operands is known normal.
537 if (KnownLHS.isKnownNever(Mask: fcZero | fcNegSubnormal) ||
538 KnownRHS.isKnownNever(Mask: fcZero | fcNegSubnormal))
539 Known.knownNot(RuleOut: fcZero | fcNegSubnormal);
540 }
541
542 return Known;
543}
544
545KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
546 const KnownFPClass &KnownRHS,
547 DenormalMode Mode) {
548 KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
549
550 // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
551 if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
552 KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
553 // Make sure output negative denormal can't flush to -0
554 (Mode.Output == DenormalMode::IEEE ||
555 Mode.Output == DenormalMode::PositiveZero))
556 Known.knownNot(RuleOut: fcNegZero);
557
558 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
559
560 return Known;
561}
562
563KnownFPClass KnownFPClass::fadd_self(const KnownFPClass &KnownSrc,
564 DenormalMode Mode) {
565 KnownFPClass Known = fadd(KnownLHS: KnownSrc, KnownRHS: KnownSrc, Mode);
566
567 // Doubling 0 will give the same 0.
568 if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
569 (Mode.Output == DenormalMode::IEEE ||
570 (Mode.Output == DenormalMode::PreserveSign &&
571 KnownSrc.isKnownNeverPosSubnormal()) ||
572 (Mode.Output == DenormalMode::PositiveZero &&
573 KnownSrc.isKnownNeverSubnormal())))
574 Known.knownNot(RuleOut: fcPosZero);
575
576 return Known;
577}
578
579KnownFPClass KnownFPClass::fsub(const KnownFPClass &KnownLHS,
580 const KnownFPClass &KnownRHS,
581 DenormalMode Mode) {
582 return fadd(KnownLHS, KnownRHS: fneg(Src: KnownRHS), Mode);
583}
584
585KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS_,
586 const KnownFPClass &KnownRHS_,
587 DenormalMode Mode) {
588 KnownFPClass KnownLHS = applyInputDenormalMode(KnownSrc: KnownLHS_, Mode);
589 KnownFPClass KnownRHS = applyInputDenormalMode(KnownSrc: KnownRHS_, Mode);
590
591 KnownFPClass Known;
592
593 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
594
595 // +X * +Y or -X * -Y => +Q
596 // +X * -Y or -X * +Y => -Q
597 if ((KnownLHS.isKnownNever(Mask: fcNegative) &&
598 KnownRHS.isKnownNever(Mask: fcNegative)) ||
599 (KnownLHS.isKnownNever(Mask: fcPositive) && KnownRHS.isKnownNever(Mask: fcPositive)))
600 Known.knownNot(RuleOut: fcNegative);
601 if ((KnownLHS.isKnownNever(Mask: fcPositive) &&
602 KnownRHS.isKnownNever(Mask: fcNegative)) ||
603 (KnownLHS.isKnownNever(Mask: fcNegative) && KnownRHS.isKnownNever(Mask: fcPositive)))
604 Known.knownNot(RuleOut: fcPositive);
605
606 // Inf * Y => Inf or NaN
607 if (KnownLHS.isKnownAlways(Mask: fcInf | fcNan) ||
608 KnownRHS.isKnownAlways(Mask: fcInf | fcNan))
609 Known.knownNot(RuleOut: fcNormal | fcSubnormal | fcZero);
610
611 // 0 * Y => 0 or NaN
612 if (KnownRHS.isKnownAlways(Mask: fcZero | fcNan) ||
613 KnownLHS.isKnownAlways(Mask: fcZero | fcNan))
614 Known.knownNot(RuleOut: fcNormal | fcSubnormal | fcInf);
615
616 // 0 * +/-inf => NaN
617 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
618 (KnownRHS.isKnownNeverInfinity() || KnownLHS.isKnownNeverZero()) &&
619 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverZero()))
620 Known.knownNot(RuleOut: fcNan);
621
622 return applyOutputDenormalMode(KnownSrc: Known, Mode);
623}
624
625// TODO: This generalizes to known ranges
626KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
627 const APFloat &CRHS, DenormalMode Mode) {
628 // Match denormal scaling pattern, similar to the case in ldexp. If the
629 // constant's exponent is sufficiently large, the result cannot be subnormal.
630
631 const fltSemantics &Flt = CRHS.getSemantics();
632 unsigned Precision = APFloat::semanticsPrecision(Flt);
633 const int MantissaBits = Precision - 1;
634
635 int MinKnownExponent = ilogb(Arg: CRHS);
636 bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);
637
638 KnownFPClass Known = KnownFPClass::fmul(KnownLHS_: KnownLHS, KnownRHS_: KnownFPClass(CRHS), Mode);
639 if (CannotBeSubnormal)
640 Known.knownNot(RuleOut: fcSubnormal);
641
642 // Multiply of values <= 1 cannot introduce overflow.
643 if (KnownLHS.isKnownNever(Mask: fcInf)) {
644 if (MinKnownExponent < 0)
645 Known.knownNot(RuleOut: fcInf);
646 else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(RHS: APFloat::getOne(
647 Sem: Flt)) == APFloat::cmpEqual)
648 Known.knownNot(RuleOut: fcInf);
649 }
650
651 return Known;
652}
653
654KnownFPClass KnownFPClass::fdiv(const KnownFPClass &KnownLHS_,
655 const KnownFPClass &KnownRHS_,
656 DenormalMode Mode) {
657 KnownFPClass KnownLHS = applyInputDenormalMode(KnownSrc: KnownLHS_, Mode);
658 KnownFPClass KnownRHS = applyInputDenormalMode(KnownSrc: KnownRHS_, Mode);
659
660 KnownFPClass Known;
661
662 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
663
664 // Only 0/0, Inf/Inf produce NaN.
665 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
666 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
667 (KnownLHS.isKnownNeverZero() || KnownRHS.isKnownNeverZero())) {
668 Known.knownNot(RuleOut: fcNan);
669 }
670
671 // X / -0.0 => -Inf (or NaN)
672 // +X / +Y or -X / -Y => +Q
673 // +X / -Y or -X / +Y => -Q
674 if ((KnownLHS.isKnownNever(Mask: fcNegative) &&
675 KnownRHS.isKnownNever(Mask: fcNegative)) ||
676 (KnownLHS.isKnownNever(Mask: fcPositive) && KnownRHS.isKnownNever(Mask: fcPositive)))
677 Known.knownNot(RuleOut: fcNegative);
678 if ((KnownLHS.isKnownNever(Mask: fcPositive) &&
679 KnownRHS.isKnownNever(Mask: fcNegative)) ||
680 (KnownLHS.isKnownNever(Mask: fcNegative) && KnownRHS.isKnownNever(Mask: fcPositive)))
681 Known.knownNot(RuleOut: fcPositive);
682
683 // Normal and subnormal results require two non-zero finite operands.
684 if ((KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal) &&
685 KnownRHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)) ||
686 (KnownLHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal) &&
687 KnownRHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal)))
688 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
689 if ((KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal) &&
690 KnownRHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal)) ||
691 (KnownLHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal) &&
692 KnownRHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)))
693 Known.knownNot(RuleOut: fcPosNormal | fcPosSubnormal);
694
695 // 0 / X => 0 or NaN
696 if (KnownLHS.isKnownAlways(Mask: fcZero))
697 Known.knownNot(RuleOut: fcSubnormal | fcNormal | fcInf);
698
699 // X / 0 => NaN or Inf
700 if (KnownRHS.isKnownAlways(Mask: fcZero))
701 Known.knownNot(RuleOut: fcFinite);
702
703 return applyOutputDenormalMode(KnownSrc: Known, Mode);
704}
705
706KnownFPClass KnownFPClass::fdiv_self(const KnownFPClass &KnownSrc,
707 DenormalMode Mode) {
708 // X / X is always exactly 1.0 or a NaN.
709 KnownFPClass Known(fcNan | fcPosNormal);
710
711 Known.propagateNonSNaN(Src: KnownSrc);
712
713 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
714 Known.knownNot(RuleOut: fcNan);
715
716 return Known;
717}
718
719KnownFPClass KnownFPClass::frem(const KnownFPClass &KnownLHS,
720 const KnownFPClass &KnownRHS,
721 DenormalMode Mode) {
722 KnownFPClass Known;
723
724 // We are assuming that frem(x, Inf) is already handled elsewhere.
725
726 Known.knownNot(RuleOut: fcInf);
727
728 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
729
730 // frem(Inf, x) and frem(x, 0) produce NaN.
731 if (KnownLHS.isKnownNeverInfOrNaN() && KnownRHS.isKnownNeverNaN() &&
732 KnownRHS.isKnownNeverLogicalZero(Mode)) {
733 Known.knownNot(RuleOut: fcNan);
734 }
735
736 // The sign for frem is the same as the first operand.
737 if (KnownLHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal))
738 Known.knownNot(RuleOut: fcPosNormal | fcPosSubnormal);
739 if (KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal))
740 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
741
742 // A negative zero result requires a negative finite first operand.
743 if (KnownLHS.isKnownNever(Mask: fcNegFinite))
744 Known.knownNot(RuleOut: fcNegZero);
745
746 // A positive zero result can additionally come from a negative finite
747 // result being flushed to positive zero.
748 if (KnownLHS.isKnownNever(Mask: fcPosFinite) &&
749 KnownLHS.isKnownNeverLogicalPosZero(Mode) &&
750 (!Mode.outputsMayBePositiveZero() ||
751 KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)))
752 Known.knownNot(RuleOut: fcPosZero);
753
754 return Known;
755}
756
757KnownFPClass KnownFPClass::frem_self(const KnownFPClass &KnownSrc,
758 DenormalMode Mode) {
759 // X % X is always exactly [+-]0.0 or a NaN.
760 KnownFPClass Known(fcNan | fcZero);
761
762 Known.propagateNonSNaN(Src: KnownSrc);
763
764 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
765 Known.knownNot(RuleOut: fcNan);
766
767 // The sign of a zero result is the sign of the finite non-zero input.
768 // We do not have to worry about subnormal values flushing to zero, since
769 // frem(+-0.0, +-0.0) = NaN.
770 if (KnownSrc.isKnownNever(Mask: fcPosNormal | fcPosSubnormal))
771 Known.knownNot(RuleOut: fcPosZero);
772 if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegSubnormal))
773 Known.knownNot(RuleOut: fcNegZero);
774
775 return Known;
776}
777
778KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
779 const KnownFPClass &KnownRHS,
780 const KnownFPClass &KnownAddend,
781 DenormalMode Mode) {
782 KnownFPClass Mul = fmul(KnownLHS_: KnownLHS, KnownRHS_: KnownRHS, Mode);
783
784 // FMA differs from the base fmul + fadd handling only in the treatment of -0
785 // results.
786 //
787 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
788 // unlike for a separate fadd.
789 KnownFPClass Known = fadd_impl(KnownLHS: Mul, KnownRHS: KnownAddend, Mode);
790
791 // propagateNonSNaN for 3 arguments.
792 if (KnownLHS.isKnownNever(Mask: fcSNan) && KnownRHS.isKnownNever(Mask: fcSNan) &&
793 KnownAddend.isKnownNever(Mask: fcSNan))
794 Known.knownNot(RuleOut: fcSNan);
795
796 return Known;
797}
798
799KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
800 const KnownFPClass &KnownAddend,
801 DenormalMode Mode) {
802 KnownFPClass Squared = square(Src: KnownSquared, Mode);
803 KnownFPClass Known = fadd_impl(KnownLHS: Squared, KnownRHS: KnownAddend, Mode);
804
805 // Since we know the squared input must be positive, the add of opposite sign
806 // infinities nan hazard only applies for negative inf.
807 //
808 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
809 // not pinf. Other than the degenerate always-subnormal input case, we can't
810 // prove that without a known range.
811 if (KnownAddend.isKnownNever(Mask: fcNegInf | fcNan) && Squared.isKnownNever(Mask: fcNan))
812 Known.knownNot(RuleOut: fcNan);
813
814 Known.propagateNonSNaN(LHS: KnownSquared, RHS: KnownAddend);
815
816 return Known;
817}
818
819KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
820 KnownFPClass Known;
821 Known.knownNot(RuleOut: fcNegative);
822
823 Known.propagateNonNaN(Src: KnownSrc);
824
825 // The following deductions assume that exp10(-1.0) = +0.1 and
826 // exp10(+1.0) = +10.0 are both finite normal values.
827
828 // Zero can only be produced if x < -1.0.
829 if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegInf))
830 Known.knownNot(RuleOut: fcPosZero);
831
832 // Subnormals can only be produced if x < -1.0 and x is finite.
833 if (KnownSrc.isKnownNever(Mask: fcNegNormal))
834 Known.knownNot(RuleOut: fcPosSubnormal);
835
836 // Infinity can only be produced if x > +1.0.
837 if (KnownSrc.isKnownNever(Mask: fcPosNormal | fcPosInf))
838 Known.knownNot(RuleOut: fcPosInf);
839
840 return Known;
841}
842
843KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc, DenormalMode Mode,
844 bool IsMultiUnitFPType) {
845 KnownFPClass Known;
846
847 // PPCDoubleDouble can represent the exact value of 1.0 + subnormal, and
848 // log(1.0 + subnormal) = subnormal.
849 if (!IsMultiUnitFPType)
850 Known.knownNot(RuleOut: fcNegZero | fcSubnormal);
851
852 Known.propagateNonSNaN(Src: KnownSrc);
853
854 if (KnownSrc.isKnownNeverPosInfinity())
855 Known.knownNot(RuleOut: fcPosInf);
856
857 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
858 Known.knownNot(RuleOut: fcNan);
859
860 if (KnownSrc.isKnownNeverLogicalZero(Mode))
861 Known.knownNot(RuleOut: fcNegInf);
862
863 return Known;
864}
865
866KnownFPClass KnownFPClass::sqrt(const KnownFPClass &KnownSrc,
867 DenormalMode Mode) {
868 KnownFPClass Known;
869 Known.knownNot(RuleOut: fcPosSubnormal);
870
871 if (KnownSrc.isKnownNeverPosInfinity())
872 Known.knownNot(RuleOut: fcPosInf);
873
874 Known.propagateNonSNaN(Src: KnownSrc);
875
876 // Any negative value besides -0 returns a nan.
877 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
878 Known.knownNot(RuleOut: fcNan);
879
880 // The only negative value that can be returned is -0 for -0 inputs.
881 Known.knownNot(RuleOut: fcNegInf | fcNegSubnormal | fcNegNormal);
882
883 // If the input denormal mode could be PreserveSign, a negative
884 // subnormal input could produce a negative zero output.
885 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
886 Known.knownNot(RuleOut: fcNegZero);
887
888 return Known;
889}
890
891KnownFPClass KnownFPClass::sin(const KnownFPClass &KnownSrc) {
892 KnownFPClass Known;
893
894 Known.propagateNonSNaN(Src: KnownSrc);
895
896 // Return NaN on infinite inputs.
897 Known.knownNot(RuleOut: fcInf);
898 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
899 Known.knownNot(RuleOut: fcNan);
900
901 return Known;
902}
903
904KnownFPClass KnownFPClass::cos(const KnownFPClass &KnownSrc) {
905 return sin(KnownSrc);
906}
907
908KnownFPClass KnownFPClass::tan(const KnownFPClass &KnownSrc) {
909 KnownFPClass Known;
910
911 // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
912 Known.knownNot(RuleOut: fcInf);
913
914 Known.propagateNonSNaN(Src: KnownSrc);
915
916 // NaN propagates. tan(+-Inf) is NaN.
917 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
918 Known.knownNot(RuleOut: fcNan);
919
920 return Known;
921}
922
923KnownFPClass KnownFPClass::sinh(const KnownFPClass &KnownSrc) {
924 KnownFPClass Known;
925
926 // sinh is sign-preserving: sinh(x) < 0 iff x < 0.
927 if (KnownSrc.isKnownNever(Mask: fcNegative))
928 Known.knownNot(RuleOut: fcNegative);
929
930 // A nonzero positive result requires a nonzero positive input.
931 // Zero remains possible: sinh(+/-0.0) = +/-0.0, and flushing a subnormal
932 // may produce +0.0.
933 if (KnownSrc.isKnownNever(Mask: fcPosSubnormal | fcPosNormal | fcPosInf))
934 Known.knownNot(RuleOut: fcPosSubnormal | fcPosNormal | fcPosInf);
935
936 Known.propagateNonNaN(Src: KnownSrc);
937
938 return Known;
939}
940
941KnownFPClass KnownFPClass::cosh(const KnownFPClass &KnownSrc) {
942 KnownFPClass Known;
943
944 // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative,
945 // zero, or subnormal.
946 Known.knownNot(RuleOut: fcNegative | fcZero | fcSubnormal);
947
948 Known.propagateNonNaN(Src: KnownSrc);
949
950 return Known;
951}
952
953KnownFPClass KnownFPClass::tanh(const KnownFPClass &KnownSrc) {
954 KnownFPClass Known;
955
956 // tanh is bounded to (-1, 1), never Inf.
957 Known.knownNot(RuleOut: fcInf);
958
959 // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
960 if (KnownSrc.isKnownNever(Mask: fcNegSubnormal | fcNegNormal | fcNegInf)) {
961 Known.knownNot(RuleOut: fcNegSubnormal | fcNegNormal);
962
963 // -0.0 is preserved: tanh(-0.0) = -0.0.
964 if (KnownSrc.isKnownNeverNegZero())
965 Known.knownNot(RuleOut: fcNegZero);
966 }
967
968 // Likewise, tanh(x) > 0 iff x > 0. Zero is not ruled out: tanh(+-0.0) =
969 // +-0.0, and a flushed subnormal may become +0.0.
970 if (KnownSrc.isKnownNever(Mask: fcPosSubnormal | fcPosNormal | fcPosInf))
971 Known.knownNot(RuleOut: fcPosSubnormal | fcPosNormal);
972
973 Known.propagateNonNaN(Src: KnownSrc);
974
975 return Known;
976}
977
978KnownFPClass KnownFPClass::asin(const KnownFPClass &KnownSrc) {
979 KnownFPClass Known;
980
981 // asin is bounded to [-pi/2, pi/2], never Inf.
982 Known.knownNot(RuleOut: fcInf);
983
984 Known.propagateNonSNaN(Src: KnownSrc);
985
986 // asin is sign-preserving for finite arguments.
987 if (KnownSrc.isKnownNever(Mask: fcNegFinite))
988 Known.knownNot(RuleOut: fcNegFinite);
989
990 if (KnownSrc.isKnownNever(Mask: fcPosSubnormal | fcPosNormal))
991 Known.knownNot(RuleOut: fcPosSubnormal | fcPosNormal);
992
993 // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
994 // out NaN without knowing the source is in [-1, 1].
995 return Known;
996}
997
998KnownFPClass KnownFPClass::acos(const KnownFPClass &KnownSrc) {
999 KnownFPClass Known;
1000
1001 // acos(x) is bounded to [0, pi] for -1 <= x <= 1, and is never negative,
1002 // infinite, or subnormal. The smallest non-zero value occurs when x is
1003 // close to 1.0, where acos(x) can be approximated by sqrt(2 * (1 - x)).
1004 // Since sqrt cannot produce a subnormal result, we can conclude that
1005 // acos(x) will also never produce a subnormal result.
1006 Known.knownNot(RuleOut: fcNegative | fcInf | fcSubnormal);
1007
1008 // acos(x) == +0.0 iff x == +1.0
1009 if (KnownSrc.isKnownNever(Mask: fcPosNormal))
1010 Known.knownNot(RuleOut: fcZero);
1011
1012 Known.propagateNonSNaN(Src: KnownSrc);
1013
1014 // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
1015 // out NaN without knowing the source is in [-1, 1].
1016 return Known;
1017}
1018
1019KnownFPClass KnownFPClass::atan(const KnownFPClass &KnownSrc) {
1020 KnownFPClass Known;
1021
1022 // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
1023 Known.knownNot(RuleOut: fcInf);
1024
1025 // Ruling out Subnormal/Normal from the result requires the
1026 // input to never be finite-nonzero and never inf, since
1027 // atan(+-inf) = +-pi/2
1028 if (KnownSrc.isKnownNever(Mask: fcNegSubnormal | fcNegNormal | fcNegInf))
1029 Known.knownNot(RuleOut: fcNegSubnormal | fcNegNormal);
1030
1031 if (KnownSrc.isKnownNever(Mask: fcPosSubnormal | fcPosNormal | fcPosInf))
1032 Known.knownNot(RuleOut: fcPosSubnormal | fcPosNormal);
1033
1034 // atan(-0.0) = -0.0. Negative finite inputs may also produce -0.0
1035 // if the result rounds to a negative subnormal that is flushed to zero.
1036 if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegSubnormal | fcNegZero))
1037 Known.knownNot(RuleOut: fcNegZero);
1038
1039 Known.propagateNonNaN(Src: KnownSrc);
1040
1041 return Known;
1042}
1043
1044KnownFPClass KnownFPClass::atan2(const KnownFPClass &KnownY_,
1045 const KnownFPClass &KnownX_,
1046 DenormalMode Mode) {
1047 KnownFPClass KnownY = applyInputDenormalMode(KnownSrc: KnownY_, Mode);
1048 KnownFPClass KnownX = applyInputDenormalMode(KnownSrc: KnownX_, Mode);
1049 KnownFPClass Known;
1050
1051 // Even though these deductions are correct, we are ignoring the following
1052 // potentially erroneous cases:
1053 // * atan2(y, inf) is not subnormal
1054 // * atan2(inf, x) is not zero or subnormal
1055
1056 // atan2 result is in (-pi, pi], never Inf.
1057 Known.knownNot(RuleOut: fcInf);
1058
1059 Known.propagateNonNaN(LHS: KnownY, RHS: KnownX);
1060
1061 // If x <= -0.0, then |atan2(y, x)| >= pi/2
1062 if (KnownX.isKnownNever(Mask: fcPositive))
1063 Known.knownNot(RuleOut: fcZero | fcSubnormal);
1064
1065 // If y >= +0.0, then atan2(y, x) >= +0.0
1066 if (KnownY.isKnownNever(Mask: fcNegative))
1067 Known.knownNot(RuleOut: fcNegative);
1068
1069 // If y <= -0.0, then atan2(y, x) <= -0.0
1070 if (KnownY.isKnownNever(Mask: fcPositive))
1071 Known.knownNot(RuleOut: fcPositive);
1072
1073 return applyOutputDenormalMode(KnownSrc: Known, Mode);
1074}
1075
1076KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc,
1077 const fltSemantics &DstTy,
1078 const fltSemantics &SrcTy) {
1079 // Infinity, nan and zero propagate from source.
1080 KnownFPClass Known = KnownSrc;
1081
1082 // All subnormal inputs should be in the normal range in the result type.
1083 if (APFloat::isRepresentableAsNormalIn(Src: SrcTy, Dst: DstTy)) {
1084 if (Known.getKnownFPClasses() & fcPosSubnormal)
1085 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosNormal);
1086 if (Known.getKnownFPClasses() & fcNegSubnormal)
1087 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegNormal);
1088 Known.knownNot(RuleOut: fcSubnormal);
1089 }
1090
1091 // Sign bit of a nan isn't guaranteed.
1092 if (!Known.isKnownNeverNaN())
1093 Known.setSignBit(std::nullopt);
1094
1095 return Known;
1096}
1097
1098KnownFPClass KnownFPClass::fptrunc(const KnownFPClass &KnownSrc) {
1099 KnownFPClass Known;
1100
1101 // Sign should be preserved
1102 // TODO: Handle cannot be ordered greater than zero
1103 if (KnownSrc.cannotBeOrderedLessThanZero())
1104 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
1105
1106 Known.propagateNonNaN(Src: KnownSrc);
1107
1108 // Infinity needs a range check.
1109 return Known;
1110}
1111
1112KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc,
1113 bool MayBeMultiUnitFPType,
1114 DenormalMode Mode) {
1115 KnownFPClass Known;
1116
1117 // Integer results cannot be subnormal.
1118 Known.knownNot(RuleOut: fcSubnormal);
1119
1120 Known.propagateNonNaN(Src: KnownSrc);
1121
1122 // Pass through infinities, except PPC_FP128 is a special case for intrinsics.
1123 if (!MayBeMultiUnitFPType) {
1124 if (KnownSrc.isKnownNeverPosInfinity())
1125 Known.knownNot(RuleOut: fcPosInf);
1126 if (KnownSrc.isKnownNeverNegInfinity())
1127 Known.knownNot(RuleOut: fcNegInf);
1128 }
1129
1130 if (KnownSrc.isKnownNever(Mask: fcPosNormal | fcPosSubnormal))
1131 Known.knownNot(RuleOut: fcPosNormal);
1132
1133 if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegSubnormal))
1134 Known.knownNot(RuleOut: fcNegNormal);
1135
1136 // Negative round ups towards zero produce negative zero.
1137 if (KnownSrc.isKnownNever(Mask: fcNegFinite))
1138 Known.knownNot(RuleOut: fcNegZero);
1139
1140 // Negative subnormals may flush to positive zero.
1141 if (KnownSrc.isKnownNever(Mask: fcPosFinite) &&
1142 (KnownSrc.isKnownNever(Mask: fcNegSubnormal) ||
1143 !Mode.inputsMayBePositiveZero()))
1144 Known.knownNot(RuleOut: fcPosZero);
1145
1146 return Known;
1147}
1148
1149KnownFPClass KnownFPClass::trunc(const KnownFPClass &KnownSrc,
1150 DenormalMode Mode) {
1151 KnownFPClass Known = roundToIntegral(KnownSrc,
1152 /*MayBeMultiUnitFPType=*/true, Mode);
1153
1154 if (KnownSrc.isKnownNeverPosInfinity())
1155 Known.knownNot(RuleOut: fcPosInf);
1156 if (KnownSrc.isKnownNeverNegInfinity())
1157 Known.knownNot(RuleOut: fcNegInf);
1158
1159 return Known;
1160}
1161
1162KnownFPClass KnownFPClass::floor(const KnownFPClass &KnownSrc,
1163 bool IsMultiUnitFPType, DenormalMode Mode) {
1164 KnownFPClass Known = roundToIntegral(KnownSrc, MayBeMultiUnitFPType: IsMultiUnitFPType, Mode);
1165
1166 // Applicable for multi-unit floating point types.
1167 if (KnownSrc.isKnownNeverPosInfinity())
1168 Known.knownNot(RuleOut: fcPosInf);
1169
1170 return Known;
1171}
1172
1173KnownFPClass KnownFPClass::ceil(const KnownFPClass &KnownSrc,
1174 bool IsMultiUnitFPType, DenormalMode Mode) {
1175 KnownFPClass Known = roundToIntegral(KnownSrc, MayBeMultiUnitFPType: IsMultiUnitFPType, Mode);
1176
1177 // Applicable for multi-unit floating point types.
1178 if (KnownSrc.isKnownNeverNegInfinity())
1179 Known.knownNot(RuleOut: fcNegInf);
1180
1181 return Known;
1182}
1183
1184KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
1185 DenormalMode Mode) {
1186 KnownFPClass Known;
1187
1188 Known.knownNot(RuleOut: fcSubnormal);
1189
1190 Known.propagateNonNaN(Src: KnownSrc);
1191
1192 if (KnownSrc.isKnownNeverPosInfinity())
1193 Known.knownNot(RuleOut: fcPosInf);
1194
1195 if (KnownSrc.isKnownNeverNegInfinity())
1196 Known.knownNot(RuleOut: fcNegInf);
1197
1198 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
1199 Known.knownNot(RuleOut: fcPosZero);
1200
1201 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
1202 Known.knownNot(RuleOut: fcNegZero);
1203
1204 // TODO: These deductions can be improved if subnormal inputs are guaranteed
1205 // to be flushed to zero.
1206 if (KnownSrc.isKnownNever(Mask: fcPosNormal | fcPosSubnormal))
1207 Known.knownNot(RuleOut: fcPosNormal);
1208
1209 if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegSubnormal))
1210 Known.knownNot(RuleOut: fcNegNormal);
1211
1212 return Known;
1213}
1214
1215KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc_,
1216 const APInt &ConstantRangeExpMin,
1217 const APInt &ConstantRangeExpMax,
1218 const fltSemantics &Flt, DenormalMode Mode) {
1219 KnownFPClass Known;
1220
1221 KnownFPClass KnownSrc = applyInputDenormalMode(KnownSrc: KnownSrc_, Mode);
1222
1223 if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
1224 // ldexp(x, 0) -> x
1225 // Here we make sure to properly propagate sNaN and denormals.
1226 Known.setKnownFPClasses(KnownSrc.getKnownFPClasses() | fcNan);
1227 Known.propagateNonNaN(Src: KnownSrc);
1228 return applyOutputDenormalMode(KnownSrc: Known, Mode);
1229 }
1230
1231 Known.propagateNonNaN(Src: KnownSrc);
1232
1233 // Sign is preserved, but underflows may produce zeroes.
1234 if (KnownSrc.isKnownNever(Mask: fcNegative))
1235 Known.knownNot(RuleOut: fcNegative);
1236 else if (KnownSrc.cannotBeOrderedLessThanZero())
1237 Known.knownNot(RuleOut: OrderedLessThanZeroMask);
1238
1239 if (KnownSrc.isKnownNever(Mask: fcPositive))
1240 Known.knownNot(RuleOut: fcPositive);
1241 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
1242 Known.knownNot(RuleOut: OrderedGreaterThanZeroMask);
1243
1244 // TODO: determine when it is safe to rule out subnormal for ppcf128.
1245 if (&Flt != &APFloat::PPCDoubleDouble()) {
1246 unsigned Precision = APFloat::semanticsPrecision(Flt);
1247 const int MantissaBits = Precision - 1;
1248 if (ConstantRangeExpMin.sge(RHS: MantissaBits))
1249 Known.knownNot(RuleOut: fcSubnormal);
1250 }
1251
1252 if (ConstantRangeExpMax.isNonPositive()) {
1253 // If we know the power is <= 0, can't introduce inf
1254 if (KnownSrc.isKnownNeverPosInfinity())
1255 Known.knownNot(RuleOut: fcPosInf);
1256 if (KnownSrc.isKnownNeverNegInfinity())
1257 Known.knownNot(RuleOut: fcNegInf);
1258 } else if (ConstantRangeExpMin.isNonNegative()) {
1259 // If we know the power is >= 0, can't introduce subnormal or zero
1260 if (KnownSrc.isKnownNeverPosSubnormal())
1261 Known.knownNot(RuleOut: fcPosSubnormal);
1262 if (KnownSrc.isKnownNeverNegSubnormal())
1263 Known.knownNot(RuleOut: fcNegSubnormal);
1264 if (KnownSrc.isKnownNeverPosZero())
1265 Known.knownNot(RuleOut: fcPosZero);
1266 if (KnownSrc.isKnownNeverNegZero())
1267 Known.knownNot(RuleOut: fcNegZero);
1268 }
1269
1270 return applyOutputDenormalMode(KnownSrc: Known, Mode);
1271}
1272
1273KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
1274 const KnownBits &ExpBits,
1275 const fltSemantics &Flt, DenormalMode Mode) {
1276 return ldexp(KnownSrc_: KnownSrc, ConstantRangeExpMin: ExpBits.getSignedMinValue(),
1277 ConstantRangeExpMax: ExpBits.getSignedMaxValue(), Flt, Mode);
1278}
1279
1280KnownFPClass KnownFPClass::pow(const KnownFPClass &KnownLHS,
1281 const KnownFPClass &KnownRHS) {
1282 KnownFPClass Known;
1283
1284 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
1285
1286 // pow may return NaN if one of the arguments is NaN. NaN may be produced from
1287 // a non-zero-finite-negative base and a non-integer exponent.
1288 if (KnownLHS.isKnownNever(Mask: fcNan | fcNegNormal | fcNegSubnormal) &&
1289 KnownRHS.isKnownNeverNaN())
1290 Known.knownNot(RuleOut: fcNan);
1291
1292 // We could rule out negative and subnormal results when exponent is known to
1293 // never be a normal value, but having either argument being known to never be
1294 // normal is unlikely and not worth considering.
1295
1296 // Only a negative base raised to an odd power returns a negative value.
1297 if (KnownLHS.isKnownNever(Mask: fcNegative)) {
1298 Known.knownNot(RuleOut: fcNegative);
1299 } else if (KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)) {
1300 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
1301 // See if we can also rule out -0.0 or -inf.
1302 // Here at least one of -0.0 or -inf is a possible base.
1303
1304 // pow(-0.0, odd-positive) = -0.0
1305 // pow(-inf, odd-negative) = -0.0
1306 if ((KnownLHS.isKnownNever(Mask: fcNegZero) ||
1307 KnownRHS.isKnownNever(Mask: fcPosNormal)) &&
1308 (KnownLHS.isKnownNever(Mask: fcNegInf) || KnownRHS.isKnownNever(Mask: fcNegNormal)))
1309 Known.knownNot(RuleOut: fcNegZero);
1310
1311 // pow(-0.0, odd-negative) = -inf
1312 // pow(-inf, odd-positive) = -inf
1313 if ((KnownLHS.isKnownNever(Mask: fcNegZero) ||
1314 KnownRHS.isKnownNever(Mask: fcNegNormal)) &&
1315 (KnownLHS.isKnownNever(Mask: fcNegInf) || KnownRHS.isKnownNever(Mask: fcPosNormal)))
1316 Known.knownNot(RuleOut: fcNegInf);
1317 }
1318
1319 return Known;
1320}
1321
1322KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
1323 const KnownBits &ExponentKnownBits) {
1324 KnownFPClass Known;
1325 Known.propagateNonNaN(Src: KnownSrc);
1326
1327 if (ExponentKnownBits.isZero()) {
1328 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
1329 // return 1.0 or a NaN.
1330 if (KnownSrc.isKnownNever(Mask: fcSNan)) {
1331 Known.knownNot(RuleOut: ~fcPosNormal);
1332 return Known;
1333 }
1334
1335 Known.knownNot(RuleOut: ~(fcPosNormal | fcNan));
1336 return Known;
1337 }
1338
1339 // Given that exp is an integer, here are the
1340 // ways that powi can return a negative value:
1341 //
1342 // powi(x, exp) --> negative if exp is odd and x is negative.
1343 // powi(-0, exp) --> -inf if exp is negative odd.
1344 // powi(-0, exp) --> -0 if exp is positive odd.
1345 // powi(-inf, exp) --> -0 if exp is negative odd.
1346 // powi(-inf, exp) --> -inf if exp is positive odd.
1347 if (KnownSrc.isKnownNever(Mask: fcNegative) || ExponentKnownBits.isEven()) {
1348 Known.knownNot(RuleOut: fcNegative);
1349 } else if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)) {
1350 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
1351 // See if we can also rule out -0.0 or -inf.
1352 // Here at least one of -0.0 or -inf is a possible base.
1353
1354 // We already know that ExponentKnownBits.isEven() is false here.
1355 const bool IsKnownNeverOddPositive = ExponentKnownBits.isNegative();
1356 const bool IsKnownNeverOddNegative = ExponentKnownBits.isNonNegative();
1357
1358 // powi(-0.0, odd-positive) = -0.0
1359 // powi(-inf, odd-negative) = -0.0
1360 if ((KnownSrc.isKnownNever(Mask: fcNegZero) || IsKnownNeverOddPositive) &&
1361 (KnownSrc.isKnownNever(Mask: fcNegInf) || IsKnownNeverOddNegative))
1362 Known.knownNot(RuleOut: fcNegZero);
1363
1364 // powi(-0.0, odd-negative) = -inf
1365 // powi(-inf, odd-positive) = -inf
1366 if ((KnownSrc.isKnownNever(Mask: fcNegZero) || IsKnownNeverOddNegative) &&
1367 (KnownSrc.isKnownNever(Mask: fcNegInf) || IsKnownNeverOddPositive))
1368 Known.knownNot(RuleOut: fcNegInf);
1369 }
1370
1371 // powi(x, exp) --> inf
1372 // when:
1373 // * powi(inf, exp), exp > 0
1374 // * powi(+/-0, exp), exp < 0
1375 // * powi(finite, exp), |exp| > 1
1376 // * powi(subnormal, -1)
1377 // TODO:
1378 // 1. This simple all or nothing approach. We can do better
1379 // and cover sign/parity and exp > 1 vs exp < -1 separately.
1380 // 2. powi(0/nan, exp), exp > 0 can be refinable
1381 // to fcNan | fcZero | fcPosNormal.
1382 {
1383 APInt MinExp = ExponentKnownBits.getSignedMinValue();
1384 APInt MaxExp = ExponentKnownBits.getSignedMaxValue();
1385
1386 // powi(inf, exp), exp > 0
1387 bool MayInfSrc =
1388 !KnownSrc.isKnownNever(Mask: fcInf) && MaxExp.isStrictlyPositive();
1389
1390 // powi(+/-0, exp), exp < 0
1391 bool MayDivByZero = !KnownSrc.isKnownNever(Mask: fcZero) && MinExp.isNegative();
1392
1393 // powi(finite, exp), |exp| > 1
1394 bool MayFinite = !KnownSrc.isKnownNever(Mask: fcNormal | fcSubnormal);
1395 bool MayAbsExpGT1 = MinExp.slt(RHS: -1) || MaxExp.sgt(RHS: 1);
1396 bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;
1397
1398 // powi(subnormal, -1)
1399 bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
1400 bool MaySubnormInv = !KnownSrc.isKnownNever(Mask: fcSubnormal) && MayBeNegOne;
1401
1402 if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
1403 Known.knownNot(RuleOut: fcInf);
1404 }
1405
1406 return Known;
1407}
1408