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