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
26/// Return true if it's possible to assume IEEE treatment of input denormals in
27/// \p F for \p Val.
28static bool inputDenormalIsIEEE(DenormalMode Mode) {
29 return Mode.Input == DenormalMode::IEEE;
30}
31
32static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) {
33 return Mode.Input == DenormalMode::IEEE ||
34 Mode.Input == DenormalMode::PositiveZero;
35}
36
37bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const {
38 return isKnownNeverZero() &&
39 (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode));
40}
41
42bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const {
43 return isKnownNeverNegZero() &&
44 (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode));
45}
46
47bool KnownFPClass::isKnownNeverLogicalPosZero(DenormalMode Mode) const {
48 if (!isKnownNeverPosZero())
49 return false;
50
51 // If we know there are no denormals, nothing can be flushed to zero.
52 if (isKnownNeverSubnormal())
53 return true;
54
55 switch (Mode.Input) {
56 case DenormalMode::IEEE:
57 return true;
58 case DenormalMode::PreserveSign:
59 // Negative subnormal won't flush to +0
60 return isKnownNeverPosSubnormal();
61 case DenormalMode::PositiveZero:
62 default:
63 // Both positive and negative subnormal could flush to +0
64 return false;
65 }
66
67 llvm_unreachable("covered switch over denormal mode");
68}
69
70void KnownFPClass::propagateDenormal(const KnownFPClass &Src,
71 DenormalMode Mode) {
72 setKnownFPClasses(Src.getKnownFPClasses());
73 // If we aren't assuming the source can't be a zero, we don't have to check if
74 // a denormal input could be flushed.
75 if (!Src.isKnownNeverPosZero() && !Src.isKnownNeverNegZero())
76 return;
77
78 // If we know the input can't be a denormal, it can't be flushed to 0.
79 if (Src.isKnownNeverSubnormal())
80 return;
81
82 if (!Src.isKnownNeverPosSubnormal() && Mode != DenormalMode::getIEEE())
83 setKnownFPClasses(getKnownFPClasses() | fcPosZero);
84
85 if (!Src.isKnownNeverNegSubnormal() && Mode != DenormalMode::getIEEE()) {
86 if (Mode != DenormalMode::getPositiveZero())
87 setKnownFPClasses(getKnownFPClasses() | fcNegZero);
88
89 if (Mode.Input == DenormalMode::PositiveZero ||
90 Mode.Output == DenormalMode::PositiveZero ||
91 Mode.Input == DenormalMode::Dynamic ||
92 Mode.Output == DenormalMode::Dynamic)
93 setKnownFPClasses(getKnownFPClasses() | fcPosZero);
94 }
95}
96
97KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &LHS_,
98 const KnownFPClass &RHS_, MinMaxKind Kind,
99 DenormalMode Mode) {
100 KnownFPClass KnownLHS = LHS_;
101 KnownFPClass KnownRHS = RHS_;
102
103 bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN();
104 KnownFPClass Known = KnownLHS | KnownRHS;
105
106 // If either operand is not NaN, the result is not NaN.
107 if (NeverNaN &&
108 (Kind == MinMaxKind::minnum || Kind == MinMaxKind::maxnum ||
109 Kind == MinMaxKind::minimumnum || Kind == MinMaxKind::maximumnum))
110 Known.knownNot(RuleOut: fcNan);
111
112 if (Kind == MinMaxKind::maxnum || Kind == MinMaxKind::maximumnum) {
113 if (KnownLHS.isKnownNeverNaN())
114 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownLHS.getKnownFPClasses()));
115 if (KnownRHS.isKnownNeverNaN())
116 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownRHS.getKnownFPClasses()));
117 } else if (Kind == MinMaxKind::maximum) {
118 Known.knownNot(RuleOut: orderedStrictlyLess(Mask: KnownLHS.getKnownFPClasses()) |
119 orderedStrictlyLess(Mask: KnownRHS.getKnownFPClasses()));
120 } else if (Kind == MinMaxKind::minnum || Kind == MinMaxKind::minimumnum) {
121 if (KnownLHS.isKnownNeverNaN())
122 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownLHS.getKnownFPClasses()));
123 if (KnownRHS.isKnownNeverNaN())
124 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownRHS.getKnownFPClasses()));
125 } else if (Kind == MinMaxKind::minimum) {
126 Known.knownNot(RuleOut: orderedStrictlyGreater(Mask: KnownLHS.getKnownFPClasses()) |
127 orderedStrictlyGreater(Mask: KnownRHS.getKnownFPClasses()));
128 } else
129 llvm_unreachable("unhandled intrinsic");
130
131 // Fixup zero handling if denormals could be returned as a zero.
132 //
133 // As there's no spec for denormal flushing, be conservative with the
134 // treatment of denormals that could be flushed to zero. For older
135 // subtargets on AMDGPU the min/max instructions would not flush the
136 // output and return the original value.
137 //
138 if ((Known.getKnownFPClasses() & fcZero) != fcNone &&
139 !Known.isKnownNeverSubnormal()) {
140 if (Mode != DenormalMode::getIEEE())
141 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcZero);
142 }
143
144 if (Known.isKnownNeverNaN()) {
145 if (KnownLHS.getSignBit() && KnownRHS.getSignBit() &&
146 *KnownLHS.getSignBit() == *KnownRHS.getSignBit()) {
147 if (*KnownLHS.getSignBit())
148 Known.signBitMustBeOne();
149 else
150 Known.signBitMustBeZero();
151 } else if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::minimum ||
152 Kind == MinMaxKind::maximumnum ||
153 Kind == MinMaxKind::minimumnum) ||
154 // FIXME: Should be using logical zero versions
155 ((KnownLHS.isKnownNeverNegZero() ||
156 KnownRHS.isKnownNeverPosZero()) &&
157 (KnownLHS.isKnownNeverPosZero() ||
158 KnownRHS.isKnownNeverNegZero()))) {
159 // Don't take sign bit from NaN operands.
160 if (!KnownLHS.isKnownNeverNaN())
161 KnownLHS.setSignBit(std::nullopt);
162 if (!KnownRHS.isKnownNeverNaN())
163 KnownRHS.setSignBit(std::nullopt);
164 if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::maximumnum ||
165 Kind == MinMaxKind::maxnum) &&
166 (KnownLHS.getSignBit() == false || KnownRHS.getSignBit() == false))
167 Known.signBitMustBeZero();
168 else if ((Kind == MinMaxKind::minimum || Kind == MinMaxKind::minimumnum ||
169 Kind == MinMaxKind::minnum) &&
170 (KnownLHS.getSignBit() == true || KnownRHS.getSignBit() == true))
171 Known.signBitMustBeOne();
172 }
173 }
174
175 return Known;
176}
177
178KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc,
179 DenormalMode DenormMode) {
180 KnownFPClass Known;
181
182 // This is essentially a stronger form of
183 // propagateCanonicalizingSrc. Other "canonicalizing" operations don't
184 // actually have an IR canonicalization guarantee.
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 if (APFloat::isIEEELikeFP(FltSemantics)) {
268 const unsigned MantissaBits = FltSemantics.precision - 1;
269 const APInt ExponentMask = APInt::getBitsSet(
270 numBits: FltSemantics.sizeInBits, loBit: MantissaBits, hiBit: FltSemantics.sizeInBits - 1);
271 const APInt MantissaMask =
272 APInt::getLowBitsSet(numBits: FltSemantics.sizeInBits, loBitsSet: MantissaBits);
273
274 const bool ExponentKnownAllZeros =
275 (Bits.Zero & ExponentMask) == ExponentMask;
276 const bool ExponentKnownAllOnes = (Bits.One & ExponentMask) == ExponentMask;
277 const bool ExponentKnownNotAllZeros = !(Bits.One & ExponentMask).isZero();
278 const bool ExponentKnownNotAllOnes = !(Bits.Zero & ExponentMask).isZero();
279
280 const bool MantissaKnownAllZeros =
281 (Bits.Zero & MantissaMask) == MantissaMask;
282 const bool MantissaKnownNotAllZeros = !(Bits.One & MantissaMask).isZero();
283
284 // Zero and subnormal require an exponent with all zero bits.
285 if (ExponentKnownNotAllZeros)
286 Known.knownNot(RuleOut: fcZero | fcSubnormal);
287
288 // Infinity and NaN require an exponent with all one bits.
289 if (ExponentKnownNotAllOnes)
290 Known.knownNot(RuleOut: fcInf | fcNan);
291
292 // Normal values have an exponent that is not all zeros or all ones.
293 if (ExponentKnownAllZeros || ExponentKnownAllOnes)
294 Known.knownNot(RuleOut: fcNormal);
295
296 // Zero and infinity require a mantissa with all zero bits.
297 if (MantissaKnownNotAllZeros)
298 Known.knownNot(RuleOut: fcZero | fcInf);
299
300 // Subnormal and NaN require a non-zero mantissa.
301 if (MantissaKnownAllZeros)
302 Known.knownNot(RuleOut: fcSubnormal | fcNan);
303
304 const bool QuietBitKnownSet = Bits.One[MantissaBits - 1];
305 const bool QuietBitKnownClear = Bits.Zero[MantissaBits - 1];
306
307 if (QuietBitKnownSet)
308 Known.knownNot(RuleOut: fcSNan);
309 else if (QuietBitKnownClear)
310 Known.knownNot(RuleOut: fcQNan);
311 }
312
313 return Known;
314}
315
316KnownBits KnownFPClass::toKnownBits(const fltSemantics &FltSemantics) const {
317 KnownBits Known(FltSemantics.sizeInBits);
318 const FPClassTest FPClasses = getKnownFPClasses();
319
320 // Return unknown if poison.
321 if (FPClasses == fcNone)
322 return Known;
323
324 // Return unknown for types we have not validated.
325 auto IsSupported = [](const fltSemantics &Semantics) {
326 switch (APFloat::SemanticsToEnum(Sem: Semantics)) {
327 case APFloatBase::S_IEEEhalf:
328 case APFloatBase::S_BFloat:
329 case APFloatBase::S_IEEEsingle:
330 case APFloatBase::S_IEEEdouble:
331 case APFloatBase::S_IEEEquad:
332 case APFloatBase::S_x87DoubleExtended:
333 return true;
334 default:
335 return false;
336 }
337 };
338 if (!IsSupported(FltSemantics))
339 return Known;
340
341 if (isKnownNever(Mask: fcNormal | fcSubnormal | fcNan)) {
342 Known.setAllConflict();
343
344 if (FPClasses & fcInf)
345 Known = Known.intersectWith(RHS: KnownBits::makeConstant(
346 C: APFloat::getInf(Sem: FltSemantics).bitcastToAPInt()));
347
348 if (FPClasses & fcZero)
349 Known = Known.intersectWith(
350 RHS: KnownBits::makeConstant(C: APInt::getZero(numBits: FltSemantics.sizeInBits)));
351
352 Known.Zero.clearSignBit();
353 Known.One.clearSignBit();
354 }
355
356 if (std::optional<bool> Sign = getSignBit()) {
357 if (*Sign)
358 Known.makeNegative();
359 else
360 Known.makeNonNegative();
361 }
362
363 return Known;
364}
365
366// Handle known sign bit and nan cases for fadd.
367static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
368 const KnownFPClass &KnownRHS, DenormalMode Mode) {
369 KnownFPClass Known;
370
371 // Adding positive and negative infinity produces NaN, but only if both
372 // opposite-sign infinity combinations are possible.
373 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
374 (KnownLHS.isKnownNever(Mask: fcPosInf) || KnownRHS.isKnownNever(Mask: fcNegInf)) &&
375 (KnownLHS.isKnownNever(Mask: fcNegInf) || KnownRHS.isKnownNever(Mask: fcPosInf)))
376 Known.knownNot(RuleOut: fcNan);
377
378 if (KnownLHS.cannotBeOrderedLessThanZero() &&
379 KnownRHS.cannotBeOrderedLessThanZero()) {
380 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
381
382 // This can't underflow if one of the operands is known normal.
383 if (KnownLHS.isKnownNever(Mask: fcZero | fcPosSubnormal) ||
384 KnownRHS.isKnownNever(Mask: fcZero | fcPosSubnormal))
385 Known.knownNot(RuleOut: fcZero | fcPosSubnormal);
386 }
387
388 if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
389 KnownRHS.cannotBeOrderedGreaterThanZero()) {
390 Known.knownNot(RuleOut: KnownFPClass::OrderedGreaterThanZeroMask);
391
392 // This can't underflow if one of the operands is known normal.
393 if (KnownLHS.isKnownNever(Mask: fcZero | fcNegSubnormal) ||
394 KnownRHS.isKnownNever(Mask: fcZero | fcNegSubnormal))
395 Known.knownNot(RuleOut: fcZero | fcNegSubnormal);
396 }
397
398 return Known;
399}
400
401KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
402 const KnownFPClass &KnownRHS,
403 DenormalMode Mode) {
404 KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
405
406 // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
407 if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
408 KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
409 // Make sure output negative denormal can't flush to -0
410 (Mode.Output == DenormalMode::IEEE ||
411 Mode.Output == DenormalMode::PositiveZero))
412 Known.knownNot(RuleOut: fcNegZero);
413
414 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
415
416 return Known;
417}
418
419KnownFPClass KnownFPClass::fadd_self(const KnownFPClass &KnownSrc,
420 DenormalMode Mode) {
421 KnownFPClass Known = fadd(KnownLHS: KnownSrc, KnownRHS: KnownSrc, Mode);
422
423 // Doubling 0 will give the same 0.
424 if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
425 (Mode.Output == DenormalMode::IEEE ||
426 (Mode.Output == DenormalMode::PreserveSign &&
427 KnownSrc.isKnownNeverPosSubnormal()) ||
428 (Mode.Output == DenormalMode::PositiveZero &&
429 KnownSrc.isKnownNeverSubnormal())))
430 Known.knownNot(RuleOut: fcPosZero);
431
432 return Known;
433}
434
435KnownFPClass KnownFPClass::fsub(const KnownFPClass &KnownLHS,
436 const KnownFPClass &KnownRHS,
437 DenormalMode Mode) {
438 return fadd(KnownLHS, KnownRHS: fneg(Src: KnownRHS), Mode);
439}
440
441KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
442 const KnownFPClass &KnownRHS,
443 DenormalMode Mode) {
444 KnownFPClass Known;
445
446 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
447
448 // +X * +Y or -X * -Y => +Q
449 // +X * -Y or -X * +Y => -Q
450 Known.propagateXorSign(LHS: KnownLHS, RHS: KnownRHS);
451
452 // Inf * Y => Inf or NaN
453 if (KnownLHS.isKnownAlways(Mask: fcInf | fcNan) ||
454 KnownRHS.isKnownAlways(Mask: fcInf | fcNan))
455 Known.knownNot(RuleOut: fcNormal | fcSubnormal | fcZero);
456
457 // 0 * Y => 0 or NaN
458 if (KnownRHS.isKnownAlways(Mask: fcZero | fcNan) ||
459 KnownLHS.isKnownAlways(Mask: fcZero | fcNan))
460 Known.knownNot(RuleOut: fcNormal | fcSubnormal | fcInf);
461
462 if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
463 return Known;
464
465 // 0 * +/-inf => NaN
466 if ((KnownRHS.isKnownNeverInfinity() ||
467 KnownLHS.isKnownNeverLogicalZero(Mode)) &&
468 (KnownLHS.isKnownNeverInfinity() ||
469 KnownRHS.isKnownNeverLogicalZero(Mode)))
470 Known.knownNot(RuleOut: fcNan);
471
472 return Known;
473}
474
475// TODO: This generalizes to known ranges
476KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
477 const APFloat &CRHS, DenormalMode Mode) {
478 // Match denormal scaling pattern, similar to the case in ldexp. If the
479 // constant's exponent is sufficiently large, the result cannot be subnormal.
480
481 const fltSemantics &Flt = CRHS.getSemantics();
482 unsigned Precision = APFloat::semanticsPrecision(Flt);
483 const int MantissaBits = Precision - 1;
484
485 int MinKnownExponent = ilogb(Arg: CRHS);
486 bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);
487
488 KnownFPClass Known = KnownFPClass::fmul(KnownLHS, KnownRHS: KnownFPClass(CRHS), Mode);
489 if (CannotBeSubnormal)
490 Known.knownNot(RuleOut: fcSubnormal);
491
492 // Multiply of values <= 1 cannot introduce overflow.
493 if (KnownLHS.isKnownNever(Mask: fcInf)) {
494 if (MinKnownExponent < 0)
495 Known.knownNot(RuleOut: fcInf);
496 else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(RHS: APFloat::getOne(
497 Sem: Flt)) == APFloat::cmpEqual)
498 Known.knownNot(RuleOut: fcInf);
499 }
500
501 return Known;
502}
503
504KnownFPClass KnownFPClass::fdiv(const KnownFPClass &KnownLHS,
505 const KnownFPClass &KnownRHS,
506 DenormalMode Mode) {
507 KnownFPClass Known;
508
509 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
510
511 // Only 0/0, Inf/Inf produce NaN.
512 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
513 (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
514 (KnownLHS.isKnownNeverLogicalZero(Mode) ||
515 KnownRHS.isKnownNeverLogicalZero(Mode))) {
516 Known.knownNot(RuleOut: fcNan);
517 }
518
519 // X / -0.0 => -Inf (or NaN)
520 // +X / +Y or -X / -Y => +Q
521 // +X / -Y or -X / +Y => -Q
522 Known.propagateXorSign(LHS: KnownLHS, RHS: KnownRHS);
523
524 // Normal and subnormal results require two non-zero finite operands.
525 if ((KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal) &&
526 KnownRHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)) ||
527 (KnownLHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal) &&
528 KnownRHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal)))
529 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
530 if ((KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal) &&
531 KnownRHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal)) ||
532 (KnownLHS.isKnownNever(Mask: fcPosNormal | fcPosSubnormal) &&
533 KnownRHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)))
534 Known.knownNot(RuleOut: fcPosNormal | fcPosSubnormal);
535
536 // 0 / X => 0 or NaN
537 if (KnownLHS.isKnownAlways(Mask: fcZero))
538 Known.knownNot(RuleOut: fcSubnormal | fcNormal | fcInf);
539
540 // X / 0 => NaN or Inf
541 if (KnownRHS.isKnownAlways(Mask: fcZero))
542 Known.knownNot(RuleOut: fcFinite);
543
544 return Known;
545}
546
547KnownFPClass KnownFPClass::fdiv_self(const KnownFPClass &KnownSrc,
548 DenormalMode Mode) {
549 // X / X is always exactly 1.0 or a NaN.
550 KnownFPClass Known(fcNan | fcPosNormal);
551
552 Known.propagateNonSNaN(Src: KnownSrc);
553
554 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
555 Known.knownNot(RuleOut: fcNan);
556
557 return Known;
558}
559
560KnownFPClass KnownFPClass::frem(const KnownFPClass &KnownLHS,
561 const KnownFPClass &KnownRHS,
562 DenormalMode Mode) {
563 KnownFPClass Known;
564
565 Known.knownNot(RuleOut: fcInf);
566
567 // Inf REM x and x REM 0 produce NaN.
568 if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
569 KnownLHS.isKnownNeverInfinity() &&
570 KnownRHS.isKnownNeverLogicalZero(Mode)) {
571 Known.knownNot(RuleOut: fcNan);
572 }
573
574 // The sign for frem is the same as the first operand.
575 if (KnownLHS.cannotBeOrderedLessThanZero())
576 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
577 if (KnownLHS.cannotBeOrderedGreaterThanZero())
578 Known.knownNot(RuleOut: KnownFPClass::OrderedGreaterThanZeroMask);
579
580 // See if we can be more aggressive about the sign of 0.
581 if (KnownLHS.isKnownNever(Mask: fcNegative))
582 Known.knownNot(RuleOut: fcNegative);
583 if (KnownLHS.isKnownNever(Mask: fcPositive))
584 Known.knownNot(RuleOut: fcPositive);
585
586 return Known;
587}
588
589KnownFPClass KnownFPClass::frem_self(const KnownFPClass &KnownSrc,
590 DenormalMode Mode) {
591 // X % X is always exactly [+-]0.0 or a NaN.
592 KnownFPClass Known(fcNan | fcZero);
593
594 if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
595 Known.knownNot(RuleOut: fcNan);
596 else if (KnownSrc.isKnownNever(Mask: fcSNan))
597 Known.knownNot(RuleOut: fcSNan);
598
599 return Known;
600}
601
602KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
603 const KnownFPClass &KnownRHS,
604 const KnownFPClass &KnownAddend,
605 DenormalMode Mode) {
606 KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
607
608 // FMA differs from the base fmul + fadd handling only in the treatment of -0
609 // results.
610 //
611 // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
612 // unlike for a separate fadd.
613 KnownFPClass Known = fadd_impl(KnownLHS: Mul, KnownRHS: KnownAddend, Mode);
614
615 // propagateNonSNaN for 3 arguments.
616 if (KnownLHS.isKnownNever(Mask: fcSNan) && KnownRHS.isKnownNever(Mask: fcSNan) &&
617 KnownAddend.isKnownNever(Mask: fcSNan))
618 Known.knownNot(RuleOut: fcSNan);
619
620 return Known;
621}
622
623KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
624 const KnownFPClass &KnownAddend,
625 DenormalMode Mode) {
626 KnownFPClass Squared = square(Src: KnownSquared, Mode);
627 KnownFPClass Known = fadd_impl(KnownLHS: Squared, KnownRHS: KnownAddend, Mode);
628
629 // Since we know the squared input must be positive, the add of opposite sign
630 // infinities nan hazard only applies for negative inf.
631 //
632 // TODO: Alternatively to proving addend is not -inf, we could know Squared is
633 // not pinf. Other than the degenerate always-subnormal input case, we can't
634 // prove that without a known range.
635 if (KnownAddend.isKnownNever(Mask: fcNegInf | fcNan) && Squared.isKnownNever(Mask: fcNan))
636 Known.knownNot(RuleOut: fcNan);
637
638 Known.propagateNonSNaN(LHS: KnownSquared, RHS: KnownAddend);
639
640 return Known;
641}
642
643KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
644 KnownFPClass Known;
645 Known.knownNot(RuleOut: fcNegative);
646
647 Known.propagateNonNaN(Src: KnownSrc);
648
649 if (KnownSrc.cannotBeOrderedLessThanZero()) {
650 // If the source is positive this cannot underflow.
651 Known.knownNot(RuleOut: fcPosZero);
652
653 // Cannot introduce denormal values.
654 Known.knownNot(RuleOut: fcPosSubnormal);
655 }
656
657 // If the source is negative, this cannot overflow to infinity.
658 if (KnownSrc.cannotBeOrderedGreaterThanZero())
659 Known.knownNot(RuleOut: fcPosInf);
660
661 return Known;
662}
663
664void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
665 DenormalMode Mode) {
666 propagateDenormal(Src, Mode);
667 propagateNonNaN(Src);
668}
669
670KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
671 DenormalMode Mode) {
672 KnownFPClass Known;
673 Known.knownNot(RuleOut: fcNegZero | fcSubnormal);
674
675 Known.propagateNonSNaN(Src: KnownSrc);
676
677 if (KnownSrc.isKnownNeverPosInfinity())
678 Known.knownNot(RuleOut: fcPosInf);
679
680 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
681 Known.knownNot(RuleOut: fcNan);
682
683 if (KnownSrc.isKnownNeverLogicalZero(Mode))
684 Known.knownNot(RuleOut: fcNegInf);
685
686 return Known;
687}
688
689KnownFPClass KnownFPClass::sqrt(const KnownFPClass &KnownSrc,
690 DenormalMode Mode) {
691 KnownFPClass Known;
692 Known.knownNot(RuleOut: fcPosSubnormal);
693
694 if (KnownSrc.isKnownNeverPosInfinity())
695 Known.knownNot(RuleOut: fcPosInf);
696
697 Known.propagateNonSNaN(Src: KnownSrc);
698
699 // Any negative value besides -0 returns a nan.
700 if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
701 Known.knownNot(RuleOut: fcNan);
702
703 // The only negative value that can be returned is -0 for -0 inputs.
704 Known.knownNot(RuleOut: fcNegInf | fcNegSubnormal | fcNegNormal);
705
706 // If the input denormal mode could be PreserveSign, a negative
707 // subnormal input could produce a negative zero output.
708 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
709 Known.knownNot(RuleOut: fcNegZero);
710
711 return Known;
712}
713
714KnownFPClass KnownFPClass::sin(const KnownFPClass &KnownSrc) {
715 KnownFPClass Known;
716
717 // Return NaN on infinite inputs.
718 Known.knownNot(RuleOut: fcInf);
719 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
720 Known.knownNot(RuleOut: fcNan);
721
722 return Known;
723}
724
725KnownFPClass KnownFPClass::cos(const KnownFPClass &KnownSrc) {
726 return sin(KnownSrc);
727}
728
729KnownFPClass KnownFPClass::tan(const KnownFPClass &KnownSrc) {
730 KnownFPClass Known;
731
732 // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
733 Known.knownNot(RuleOut: fcInf);
734
735 // NaN propagates. tan(+-Inf) is NaN.
736 if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
737 Known.knownNot(RuleOut: fcNan);
738
739 return Known;
740}
741
742KnownFPClass KnownFPClass::sinh(const KnownFPClass &KnownSrc) {
743 KnownFPClass Known;
744
745 // sinh is sign-preserving: sinh(x) < 0 iff x < 0.
746 if (KnownSrc.isKnownNever(Mask: fcNegative))
747 Known.knownNot(RuleOut: fcNegative);
748
749 Known.propagateNonNaN(Src: KnownSrc);
750
751 return Known;
752}
753
754KnownFPClass KnownFPClass::cosh(const KnownFPClass &KnownSrc) {
755 KnownFPClass Known;
756
757 // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative,
758 // zero, or subnormal.
759 Known.knownNot(RuleOut: fcNegative | fcZero | fcSubnormal);
760
761 Known.propagateNonNaN(Src: KnownSrc);
762
763 return Known;
764}
765
766KnownFPClass KnownFPClass::tanh(const KnownFPClass &KnownSrc) {
767 KnownFPClass Known;
768
769 // tanh is bounded to (-1, 1), never Inf.
770 Known.knownNot(RuleOut: fcInf);
771
772 // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
773 if (KnownSrc.isKnownNever(Mask: fcNegative))
774 Known.knownNot(RuleOut: fcNegative);
775
776 Known.propagateNonNaN(Src: KnownSrc);
777
778 return Known;
779}
780
781KnownFPClass KnownFPClass::asin(const KnownFPClass &KnownSrc) {
782 KnownFPClass Known;
783
784 // asin is bounded to [-pi/2, pi/2], never Inf.
785 Known.knownNot(RuleOut: fcInf);
786
787 Known.propagateNonSNaN(Src: KnownSrc);
788
789 // asin is sign-preserving for finite arguments.
790 if (KnownSrc.isKnownNever(Mask: fcNegFinite))
791 Known.knownNot(RuleOut: fcNegFinite);
792
793 // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
794 // out NaN without knowing the source is in [-1, 1].
795 return Known;
796}
797
798KnownFPClass KnownFPClass::acos(const KnownFPClass &KnownSrc) {
799 KnownFPClass Known;
800
801 // acos(x) is bounded to [0, pi] for -1 <= x <= 1, and is never negative,
802 // infinite, or subnormal. The smallest non-zero value occurs when x is
803 // close to 1.0, where acos(x) can be approximated by sqrt(2 * (1 - x)).
804 // Since sqrt cannot produce a subnormal result, we can conclude that
805 // acos(x) will also never produce a subnormal result.
806 Known.knownNot(RuleOut: fcNegative | fcInf | fcSubnormal);
807
808 // acos(x) == +0.0 iff x == +1.0
809 if (KnownSrc.isKnownNever(Mask: fcPosNormal))
810 Known.knownNot(RuleOut: fcZero);
811
812 Known.propagateNonSNaN(Src: KnownSrc);
813
814 // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
815 // out NaN without knowing the source is in [-1, 1].
816 return Known;
817}
818
819KnownFPClass KnownFPClass::atan(const KnownFPClass &KnownSrc) {
820 KnownFPClass Known;
821
822 // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
823 Known.knownNot(RuleOut: fcInf);
824
825 // atan is sign-preserving: atan(x) < 0 iff x < 0.
826 if (KnownSrc.isKnownNever(Mask: fcNegative))
827 Known.knownNot(RuleOut: fcNegative);
828
829 Known.propagateNonNaN(Src: KnownSrc);
830
831 return Known;
832}
833
834KnownFPClass KnownFPClass::atan2(const KnownFPClass &KnownY,
835 const KnownFPClass &KnownX,
836 DenormalMode Mode) {
837 KnownFPClass Known;
838
839 // Even though these deductions are correct, we are ignoring the following
840 // potentially erroneous cases:
841 // * atan2(y, inf) is not subnormal
842 // * atan2(inf, x) is not zero or subnormal
843
844 // atan2 result is in (-pi, pi], never Inf.
845 Known.knownNot(RuleOut: fcInf);
846
847 Known.propagateNonNaN(LHS: KnownY, RHS: KnownX);
848
849 // Negative subnormals could be treated like positive zero.
850 const bool XCannotHavePositiveInput = KnownX.isKnownNever(Mask: fcPositive) &&
851 KnownX.isKnownNeverLogicalPosZero(Mode);
852 const bool YCannotHavePositiveInput = KnownY.isKnownNever(Mask: fcPositive) &&
853 KnownY.isKnownNeverLogicalPosZero(Mode);
854
855 // If x <= -0.0, then |atan2(y, x)| >= pi/2
856 if (XCannotHavePositiveInput)
857 Known.knownNot(RuleOut: fcZero | fcSubnormal);
858
859 // If y >= +0.0, then atan2(y, x) >= +0.0
860 if (KnownY.isKnownNever(Mask: fcNegative))
861 Known.knownNot(RuleOut: fcNegative);
862
863 // If y <= -0.0, then atan2(y, x) <= -0.0
864 // We do this deduction last in case we were able to rule out a negative
865 // subnormal result earlier.
866 if (YCannotHavePositiveInput) {
867 Known.knownNot(RuleOut: fcPosSubnormal | fcPosNormal | fcPosInf);
868 // Negative subnormal results can flush to +0.0.
869 if (Known.isKnownNever(Mask: fcNegSubnormal) || !Mode.outputsMayBePositiveZero())
870 Known.knownNot(RuleOut: fcPosZero);
871 }
872
873 return Known;
874}
875
876KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc,
877 const fltSemantics &DstTy,
878 const fltSemantics &SrcTy) {
879 // Infinity, nan and zero propagate from source.
880 KnownFPClass Known = KnownSrc;
881
882 // All subnormal inputs should be in the normal range in the result type.
883 if (APFloat::isRepresentableAsNormalIn(Src: SrcTy, Dst: DstTy)) {
884 if (Known.getKnownFPClasses() & fcPosSubnormal)
885 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosNormal);
886 if (Known.getKnownFPClasses() & fcNegSubnormal)
887 Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegNormal);
888 Known.knownNot(RuleOut: fcSubnormal);
889 }
890
891 // Sign bit of a nan isn't guaranteed.
892 if (!Known.isKnownNeverNaN())
893 Known.setSignBit(std::nullopt);
894
895 return Known;
896}
897
898KnownFPClass KnownFPClass::fptrunc(const KnownFPClass &KnownSrc) {
899 KnownFPClass Known;
900
901 // Sign should be preserved
902 // TODO: Handle cannot be ordered greater than zero
903 if (KnownSrc.cannotBeOrderedLessThanZero())
904 Known.knownNot(RuleOut: KnownFPClass::OrderedLessThanZeroMask);
905
906 Known.propagateNonNaN(Src: KnownSrc);
907
908 // Infinity needs a range check.
909 return Known;
910}
911
912KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc,
913 bool IsTrunc,
914 bool IsMultiUnitFPType) {
915 KnownFPClass Known;
916
917 // Integer results cannot be subnormal.
918 Known.knownNot(RuleOut: fcSubnormal);
919
920 Known.propagateNonNaN(Src: KnownSrc);
921
922 // Pass through infinities, except PPC_FP128 is a special case for
923 // intrinsics other than trunc.
924 if (IsTrunc || !IsMultiUnitFPType) {
925 if (KnownSrc.isKnownNeverPosInfinity())
926 Known.knownNot(RuleOut: fcPosInf);
927 if (KnownSrc.isKnownNeverNegInfinity())
928 Known.knownNot(RuleOut: fcNegInf);
929 }
930
931 // Negative round ups to 0 produce -0
932 if (KnownSrc.isKnownNever(Mask: fcPosFinite))
933 Known.knownNot(RuleOut: fcPosFinite);
934 if (KnownSrc.isKnownNever(Mask: fcNegFinite))
935 Known.knownNot(RuleOut: fcNegFinite);
936
937 return Known;
938}
939
940KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
941 DenormalMode Mode) {
942 KnownFPClass Known;
943 Known.knownNot(RuleOut: fcSubnormal);
944
945 if (KnownSrc.isKnownNever(Mask: fcNegative))
946 Known.knownNot(RuleOut: fcNegative);
947 else {
948 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
949 Known.knownNot(RuleOut: fcNegZero);
950 if (KnownSrc.isKnownNever(Mask: fcNegInf))
951 Known.knownNot(RuleOut: fcNegInf);
952 }
953
954 if (KnownSrc.isKnownNever(Mask: fcPositive))
955 Known.knownNot(RuleOut: fcPositive);
956 else {
957 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
958 Known.knownNot(RuleOut: fcPosZero);
959 if (KnownSrc.isKnownNever(Mask: fcPosInf))
960 Known.knownNot(RuleOut: fcPosInf);
961 }
962
963 Known.propagateNonNaN(Src: KnownSrc);
964 return Known;
965}
966
967KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
968 const APInt &ConstantRangeExpMin,
969 const APInt &ConstantRangeExpMax,
970 const fltSemantics &Flt, DenormalMode Mode) {
971 KnownFPClass Known;
972 Known.propagateNonNaN(Src: KnownSrc);
973
974 // Sign is preserved, but underflows may produce zeroes.
975 if (KnownSrc.isKnownNever(Mask: fcNegative))
976 Known.knownNot(RuleOut: fcNegative);
977 else if (KnownSrc.cannotBeOrderedLessThanZero())
978 Known.knownNot(RuleOut: OrderedLessThanZeroMask);
979
980 if (KnownSrc.isKnownNever(Mask: fcPositive))
981 Known.knownNot(RuleOut: fcPositive);
982 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
983 Known.knownNot(RuleOut: OrderedGreaterThanZeroMask);
984
985 unsigned Precision = APFloat::semanticsPrecision(Flt);
986 const int MantissaBits = Precision - 1;
987 if (ConstantRangeExpMin.sge(RHS: MantissaBits))
988 Known.knownNot(RuleOut: fcSubnormal);
989
990 if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
991 // ldexp(x, 0) -> x, so propagate everything.
992 Known.propagateCanonicalizingSrc(Src: KnownSrc, Mode);
993 } else if (ConstantRangeExpMax.isNonPositive()) {
994 // If we know the power is <= 0, can't introduce inf
995 if (KnownSrc.isKnownNeverPosInfinity())
996 Known.knownNot(RuleOut: fcPosInf);
997 if (KnownSrc.isKnownNeverNegInfinity())
998 Known.knownNot(RuleOut: fcNegInf);
999 } else if (ConstantRangeExpMin.isNonNegative()) {
1000 // If we know the power is >= 0, can't introduce subnormal or zero
1001 if (KnownSrc.isKnownNeverPosSubnormal())
1002 Known.knownNot(RuleOut: fcPosSubnormal);
1003 if (KnownSrc.isKnownNeverNegSubnormal())
1004 Known.knownNot(RuleOut: fcNegSubnormal);
1005 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
1006 Known.knownNot(RuleOut: fcPosZero);
1007 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
1008 Known.knownNot(RuleOut: fcNegZero);
1009 }
1010
1011 return Known;
1012}
1013
1014KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
1015 const KnownBits &ExpBits,
1016 const fltSemantics &Flt, DenormalMode Mode) {
1017 return ldexp(KnownSrc, ConstantRangeExpMin: ExpBits.getSignedMinValue(),
1018 ConstantRangeExpMax: ExpBits.getSignedMaxValue(), Flt, Mode);
1019}
1020
1021KnownFPClass KnownFPClass::pow(const KnownFPClass &KnownLHS,
1022 const KnownFPClass &KnownRHS) {
1023 KnownFPClass Known;
1024
1025 Known.propagateNonSNaN(LHS: KnownLHS, RHS: KnownRHS);
1026
1027 // pow may return NaN if one of the arguments is NaN. NaN may be produced from
1028 // a non-zero-finite-negative base and a non-integer exponent.
1029 if (KnownLHS.isKnownNever(Mask: fcNan | fcNegNormal | fcNegSubnormal) &&
1030 KnownRHS.isKnownNeverNaN())
1031 Known.knownNot(RuleOut: fcNan);
1032
1033 // We could rule out negative and subnormal results when exponent is known to
1034 // never be a normal value, but having either argument being known to never be
1035 // normal is unlikely and not worth considering.
1036
1037 // Only a negative base raised to an odd power returns a negative value.
1038 if (KnownLHS.isKnownNever(Mask: fcNegative)) {
1039 Known.knownNot(RuleOut: fcNegative);
1040 } else if (KnownLHS.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)) {
1041 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
1042 // See if we can also rule out -0.0 or -inf.
1043 // Here at least one of -0.0 or -inf is a possible base.
1044
1045 // pow(-0.0, odd-positive) = -0.0
1046 // pow(-inf, odd-negative) = -0.0
1047 if ((KnownLHS.isKnownNever(Mask: fcNegZero) ||
1048 KnownRHS.isKnownNever(Mask: fcPosNormal)) &&
1049 (KnownLHS.isKnownNever(Mask: fcNegInf) || KnownRHS.isKnownNever(Mask: fcNegNormal)))
1050 Known.knownNot(RuleOut: fcNegZero);
1051
1052 // pow(-0.0, odd-negative) = -inf
1053 // pow(-inf, odd-positive) = -inf
1054 if ((KnownLHS.isKnownNever(Mask: fcNegZero) ||
1055 KnownRHS.isKnownNever(Mask: fcNegNormal)) &&
1056 (KnownLHS.isKnownNever(Mask: fcNegInf) || KnownRHS.isKnownNever(Mask: fcPosNormal)))
1057 Known.knownNot(RuleOut: fcNegInf);
1058 }
1059
1060 return Known;
1061}
1062
1063KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
1064 const KnownBits &ExponentKnownBits) {
1065 KnownFPClass Known;
1066 Known.propagateNonNaN(Src: KnownSrc);
1067
1068 if (ExponentKnownBits.isZero()) {
1069 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
1070 // return 1.0 or a NaN.
1071 if (KnownSrc.isKnownNever(Mask: fcSNan)) {
1072 Known.knownNot(RuleOut: ~fcPosNormal);
1073 return Known;
1074 }
1075
1076 Known.knownNot(RuleOut: ~(fcPosNormal | fcNan));
1077 return Known;
1078 }
1079
1080 // Given that exp is an integer, here are the
1081 // ways that powi can return a negative value:
1082 //
1083 // powi(x, exp) --> negative if exp is odd and x is negative.
1084 // powi(-0, exp) --> -inf if exp is negative odd.
1085 // powi(-0, exp) --> -0 if exp is positive odd.
1086 // powi(-inf, exp) --> -0 if exp is negative odd.
1087 // powi(-inf, exp) --> -inf if exp is positive odd.
1088 if (KnownSrc.isKnownNever(Mask: fcNegative) || ExponentKnownBits.isEven()) {
1089 Known.knownNot(RuleOut: fcNegative);
1090 } else if (KnownSrc.isKnownNever(Mask: fcNegNormal | fcNegSubnormal)) {
1091 Known.knownNot(RuleOut: fcNegNormal | fcNegSubnormal);
1092 // See if we can also rule out -0.0 or -inf.
1093 // Here at least one of -0.0 or -inf is a possible base.
1094
1095 // We already know that ExponentKnownBits.isEven() is false here.
1096 const bool IsKnownNeverOddPositive = ExponentKnownBits.isNegative();
1097 const bool IsKnownNeverOddNegative = ExponentKnownBits.isNonNegative();
1098
1099 // powi(-0.0, odd-positive) = -0.0
1100 // powi(-inf, odd-negative) = -0.0
1101 if ((KnownSrc.isKnownNever(Mask: fcNegZero) || IsKnownNeverOddPositive) &&
1102 (KnownSrc.isKnownNever(Mask: fcNegInf) || IsKnownNeverOddNegative))
1103 Known.knownNot(RuleOut: fcNegZero);
1104
1105 // powi(-0.0, odd-negative) = -inf
1106 // powi(-inf, odd-positive) = -inf
1107 if ((KnownSrc.isKnownNever(Mask: fcNegZero) || IsKnownNeverOddNegative) &&
1108 (KnownSrc.isKnownNever(Mask: fcNegInf) || IsKnownNeverOddPositive))
1109 Known.knownNot(RuleOut: fcNegInf);
1110 }
1111
1112 // powi(x, exp) --> inf
1113 // when:
1114 // * powi(inf, exp), exp > 0
1115 // * powi(+/-0, exp), exp < 0
1116 // * powi(finite, exp), |exp| > 1
1117 // * powi(subnormal, -1)
1118 // TODO:
1119 // 1. This simple all or nothing approach. We can do better
1120 // and cover sign/parity and exp > 1 vs exp < -1 separately.
1121 // 2. powi(0/nan, exp), exp > 0 can be refinable
1122 // to fcNan | fcZero | fcPosNormal.
1123 {
1124 APInt MinExp = ExponentKnownBits.getSignedMinValue();
1125 APInt MaxExp = ExponentKnownBits.getSignedMaxValue();
1126
1127 // powi(inf, exp), exp > 0
1128 bool MayInfSrc =
1129 !KnownSrc.isKnownNever(Mask: fcInf) && MaxExp.isStrictlyPositive();
1130
1131 // powi(+/-0, exp), exp < 0
1132 bool MayDivByZero = !KnownSrc.isKnownNever(Mask: fcZero) && MinExp.isNegative();
1133
1134 // powi(finite, exp), |exp| > 1
1135 bool MayFinite = !KnownSrc.isKnownNever(Mask: fcNormal | fcSubnormal);
1136 bool MayAbsExpGT1 = MinExp.slt(RHS: -1) || MaxExp.sgt(RHS: 1);
1137 bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;
1138
1139 // powi(subnormal, -1)
1140 bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
1141 bool MaySubnormInv = !KnownSrc.isKnownNever(Mask: fcSubnormal) && MayBeNegOne;
1142
1143 if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
1144 Known.knownNot(RuleOut: fcInf);
1145 }
1146
1147 return Known;
1148}
1149