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