Skip to content

Commit 049f179

Browse files
tgymnicharsenm
andauthored
[Analysis][NFC] Extract KnownFPClass (#133457)
- extract KnownFPClass for future use inside of GISelKnownBits --------- Co-authored-by: Matt Arsenault <[email protected]>
1 parent 133c1af commit 049f179

File tree

14 files changed

+513
-406
lines changed

14 files changed

+513
-406
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 27 additions & 307 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class DominatorTree;
3434
class GEPOperator;
3535
class WithOverflowInst;
3636
struct KnownBits;
37+
struct KnownFPClass;
3738
class Loop;
3839
class LoopInfo;
3940
class MDNode;
@@ -255,244 +256,6 @@ std::tuple<Value *, FPClassTest, FPClassTest>
255256
fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
256257
const APFloat &RHS, bool LookThroughSrc = true);
257258

258-
struct KnownFPClass {
259-
/// Floating-point classes the value could be one of.
260-
FPClassTest KnownFPClasses = fcAllFlags;
261-
262-
/// std::nullopt if the sign bit is unknown, true if the sign bit is
263-
/// definitely set or false if the sign bit is definitely unset.
264-
std::optional<bool> SignBit;
265-
266-
bool operator==(KnownFPClass Other) const {
267-
return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
268-
}
269-
270-
/// Return true if it's known this can never be one of the mask entries.
271-
bool isKnownNever(FPClassTest Mask) const {
272-
return (KnownFPClasses & Mask) == fcNone;
273-
}
274-
275-
bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
276-
277-
bool isUnknown() const {
278-
return KnownFPClasses == fcAllFlags && !SignBit;
279-
}
280-
281-
/// Return true if it's known this can never be a nan.
282-
bool isKnownNeverNaN() const {
283-
return isKnownNever(fcNan);
284-
}
285-
286-
/// Return true if it's known this must always be a nan.
287-
bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
288-
289-
/// Return true if it's known this can never be an infinity.
290-
bool isKnownNeverInfinity() const {
291-
return isKnownNever(fcInf);
292-
}
293-
294-
/// Return true if it's known this can never be +infinity.
295-
bool isKnownNeverPosInfinity() const {
296-
return isKnownNever(fcPosInf);
297-
}
298-
299-
/// Return true if it's known this can never be -infinity.
300-
bool isKnownNeverNegInfinity() const {
301-
return isKnownNever(fcNegInf);
302-
}
303-
304-
/// Return true if it's known this can never be a subnormal
305-
bool isKnownNeverSubnormal() const {
306-
return isKnownNever(fcSubnormal);
307-
}
308-
309-
/// Return true if it's known this can never be a positive subnormal
310-
bool isKnownNeverPosSubnormal() const {
311-
return isKnownNever(fcPosSubnormal);
312-
}
313-
314-
/// Return true if it's known this can never be a negative subnormal
315-
bool isKnownNeverNegSubnormal() const {
316-
return isKnownNever(fcNegSubnormal);
317-
}
318-
319-
/// Return true if it's known this can never be a zero. This means a literal
320-
/// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
321-
bool isKnownNeverZero() const {
322-
return isKnownNever(fcZero);
323-
}
324-
325-
/// Return true if it's known this can never be a literal positive zero.
326-
bool isKnownNeverPosZero() const {
327-
return isKnownNever(fcPosZero);
328-
}
329-
330-
/// Return true if it's known this can never be a negative zero. This means a
331-
/// literal -0 and does not include denormal inputs implicitly treated as -0.
332-
bool isKnownNeverNegZero() const {
333-
return isKnownNever(fcNegZero);
334-
}
335-
336-
/// Return true if it's know this can never be interpreted as a zero. This
337-
/// extends isKnownNeverZero to cover the case where the assumed
338-
/// floating-point mode for the function interprets denormals as zero.
339-
bool isKnownNeverLogicalZero(const Function &F, Type *Ty) const;
340-
341-
/// Return true if it's know this can never be interpreted as a negative zero.
342-
bool isKnownNeverLogicalNegZero(const Function &F, Type *Ty) const;
343-
344-
/// Return true if it's know this can never be interpreted as a positive zero.
345-
bool isKnownNeverLogicalPosZero(const Function &F, Type *Ty) const;
346-
347-
static constexpr FPClassTest OrderedLessThanZeroMask =
348-
fcNegSubnormal | fcNegNormal | fcNegInf;
349-
static constexpr FPClassTest OrderedGreaterThanZeroMask =
350-
fcPosSubnormal | fcPosNormal | fcPosInf;
351-
352-
/// Return true if we can prove that the analyzed floating-point value is
353-
/// either NaN or never less than -0.0.
354-
///
355-
/// NaN --> true
356-
/// +0 --> true
357-
/// -0 --> true
358-
/// x > +0 --> true
359-
/// x < -0 --> false
360-
bool cannotBeOrderedLessThanZero() const {
361-
return isKnownNever(OrderedLessThanZeroMask);
362-
}
363-
364-
/// Return true if we can prove that the analyzed floating-point value is
365-
/// either NaN or never greater than -0.0.
366-
/// NaN --> true
367-
/// +0 --> true
368-
/// -0 --> true
369-
/// x > +0 --> false
370-
/// x < -0 --> true
371-
bool cannotBeOrderedGreaterThanZero() const {
372-
return isKnownNever(OrderedGreaterThanZeroMask);
373-
}
374-
375-
KnownFPClass &operator|=(const KnownFPClass &RHS) {
376-
KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
377-
378-
if (SignBit != RHS.SignBit)
379-
SignBit = std::nullopt;
380-
return *this;
381-
}
382-
383-
void knownNot(FPClassTest RuleOut) {
384-
KnownFPClasses = KnownFPClasses & ~RuleOut;
385-
if (isKnownNever(fcNan) && !SignBit) {
386-
if (isKnownNever(fcNegative))
387-
SignBit = false;
388-
else if (isKnownNever(fcPositive))
389-
SignBit = true;
390-
}
391-
}
392-
393-
void fneg() {
394-
KnownFPClasses = llvm::fneg(KnownFPClasses);
395-
if (SignBit)
396-
SignBit = !*SignBit;
397-
}
398-
399-
void fabs() {
400-
if (KnownFPClasses & fcNegZero)
401-
KnownFPClasses |= fcPosZero;
402-
403-
if (KnownFPClasses & fcNegInf)
404-
KnownFPClasses |= fcPosInf;
405-
406-
if (KnownFPClasses & fcNegSubnormal)
407-
KnownFPClasses |= fcPosSubnormal;
408-
409-
if (KnownFPClasses & fcNegNormal)
410-
KnownFPClasses |= fcPosNormal;
411-
412-
signBitMustBeZero();
413-
}
414-
415-
/// Return true if the sign bit must be 0, ignoring the sign of nans.
416-
bool signBitIsZeroOrNaN() const {
417-
return isKnownNever(fcNegative);
418-
}
419-
420-
/// Assume the sign bit is zero.
421-
void signBitMustBeZero() {
422-
KnownFPClasses &= (fcPositive | fcNan);
423-
SignBit = false;
424-
}
425-
426-
/// Assume the sign bit is one.
427-
void signBitMustBeOne() {
428-
KnownFPClasses &= (fcNegative | fcNan);
429-
SignBit = true;
430-
}
431-
432-
void copysign(const KnownFPClass &Sign) {
433-
// Don't know anything about the sign of the source. Expand the possible set
434-
// to its opposite sign pair.
435-
if (KnownFPClasses & fcZero)
436-
KnownFPClasses |= fcZero;
437-
if (KnownFPClasses & fcSubnormal)
438-
KnownFPClasses |= fcSubnormal;
439-
if (KnownFPClasses & fcNormal)
440-
KnownFPClasses |= fcNormal;
441-
if (KnownFPClasses & fcInf)
442-
KnownFPClasses |= fcInf;
443-
444-
// Sign bit is exactly preserved even for nans.
445-
SignBit = Sign.SignBit;
446-
447-
// Clear sign bits based on the input sign mask.
448-
if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
449-
KnownFPClasses &= (fcNegative | fcNan);
450-
if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
451-
KnownFPClasses &= (fcPositive | fcNan);
452-
}
453-
454-
// Propagate knowledge that a non-NaN source implies the result can also not
455-
// be a NaN. For unconstrained operations, signaling nans are not guaranteed
456-
// to be quieted but cannot be introduced.
457-
void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
458-
if (Src.isKnownNever(fcNan)) {
459-
knownNot(fcNan);
460-
if (PreserveSign)
461-
SignBit = Src.SignBit;
462-
} else if (Src.isKnownNever(fcSNan))
463-
knownNot(fcSNan);
464-
}
465-
466-
/// Propagate knowledge from a source value that could be a denormal or
467-
/// zero. We have to be conservative since output flushing is not guaranteed,
468-
/// so known-never-zero may not hold.
469-
///
470-
/// This assumes a copy-like operation and will replace any currently known
471-
/// information.
472-
void propagateDenormal(const KnownFPClass &Src, const Function &F, Type *Ty);
473-
474-
/// Report known classes if \p Src is evaluated through a potentially
475-
/// canonicalizing operation. We can assume signaling nans will not be
476-
/// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
477-
///
478-
/// This assumes a copy-like operation and will replace any currently known
479-
/// information.
480-
void propagateCanonicalizingSrc(const KnownFPClass &Src, const Function &F,
481-
Type *Ty);
482-
483-
void resetAll() { *this = KnownFPClass(); }
484-
};
485-
486-
inline KnownFPClass operator|(KnownFPClass LHS, const KnownFPClass &RHS) {
487-
LHS |= RHS;
488-
return LHS;
489-
}
490-
491-
inline KnownFPClass operator|(const KnownFPClass &LHS, KnownFPClass &&RHS) {
492-
RHS |= LHS;
493-
return std::move(RHS);
494-
}
495-
496259
/// Determine which floating-point classes are valid for \p V, and return them
497260
/// in KnownFPClass bit sets.
498261
///
@@ -510,56 +273,30 @@ KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
510273
KnownFPClass computeKnownFPClass(const Value *V, FPClassTest InterestedClasses,
511274
unsigned Depth, const SimplifyQuery &SQ);
512275

513-
inline KnownFPClass computeKnownFPClass(
514-
const Value *V, const DataLayout &DL,
515-
FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
516-
const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
517-
const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
518-
bool UseInstrInfo = true) {
519-
return computeKnownFPClass(
520-
V, InterestedClasses, Depth,
521-
SimplifyQuery(DL, TLI, DT, AC, CxtI, UseInstrInfo));
522-
}
276+
KnownFPClass computeKnownFPClass(const Value *V, const DataLayout &DL,
277+
FPClassTest InterestedClasses = fcAllFlags,
278+
unsigned Depth = 0,
279+
const TargetLibraryInfo *TLI = nullptr,
280+
AssumptionCache *AC = nullptr,
281+
const Instruction *CxtI = nullptr,
282+
const DominatorTree *DT = nullptr,
283+
bool UseInstrInfo = true);
523284

524285
/// Wrapper to account for known fast math flags at the use instruction.
525-
inline KnownFPClass
526-
computeKnownFPClass(const Value *V, const APInt &DemandedElts,
527-
FastMathFlags FMF, FPClassTest InterestedClasses,
528-
unsigned Depth, const SimplifyQuery &SQ) {
529-
if (FMF.noNaNs())
530-
InterestedClasses &= ~fcNan;
531-
if (FMF.noInfs())
532-
InterestedClasses &= ~fcInf;
533-
534-
KnownFPClass Result =
535-
computeKnownFPClass(V, DemandedElts, InterestedClasses, Depth, SQ);
536-
537-
if (FMF.noNaNs())
538-
Result.KnownFPClasses &= ~fcNan;
539-
if (FMF.noInfs())
540-
Result.KnownFPClasses &= ~fcInf;
541-
return Result;
542-
}
286+
KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
287+
FastMathFlags FMF,
288+
FPClassTest InterestedClasses, unsigned Depth,
289+
const SimplifyQuery &SQ);
543290

544-
inline KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
545-
FPClassTest InterestedClasses,
546-
unsigned Depth,
547-
const SimplifyQuery &SQ) {
548-
auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
549-
APInt DemandedElts =
550-
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
551-
return computeKnownFPClass(V, DemandedElts, FMF, InterestedClasses, Depth,
552-
SQ);
553-
}
291+
KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
292+
FPClassTest InterestedClasses, unsigned Depth,
293+
const SimplifyQuery &SQ);
554294

555295
/// Return true if we can prove that the specified FP value is never equal to
556296
/// -0.0. Users should use caution when considering PreserveSign
557297
/// denormal-fp-math.
558-
inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
559-
const SimplifyQuery &SQ) {
560-
KnownFPClass Known = computeKnownFPClass(V, fcNegZero, Depth, SQ);
561-
return Known.isKnownNeverNegZero();
562-
}
298+
bool cannotBeNegativeZero(const Value *V, unsigned Depth,
299+
const SimplifyQuery &SQ);
563300

564301
/// Return true if we can prove that the specified FP value is either NaN or
565302
/// never less than -0.0.
@@ -569,46 +306,29 @@ inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
569306
/// -0 --> true
570307
/// x > +0 --> true
571308
/// x < -0 --> false
572-
inline bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
573-
const SimplifyQuery &SQ) {
574-
KnownFPClass Known =
575-
computeKnownFPClass(V, KnownFPClass::OrderedLessThanZeroMask, Depth, SQ);
576-
return Known.cannotBeOrderedLessThanZero();
577-
}
309+
bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
310+
const SimplifyQuery &SQ);
578311

579312
/// Return true if the floating-point scalar value is not an infinity or if
580313
/// the floating-point vector value has no infinities. Return false if a value
581314
/// could ever be infinity.
582-
inline bool isKnownNeverInfinity(const Value *V, unsigned Depth,
583-
const SimplifyQuery &SQ) {
584-
KnownFPClass Known = computeKnownFPClass(V, fcInf, Depth, SQ);
585-
return Known.isKnownNeverInfinity();
586-
}
315+
bool isKnownNeverInfinity(const Value *V, unsigned Depth,
316+
const SimplifyQuery &SQ);
587317

588318
/// Return true if the floating-point value can never contain a NaN or infinity.
589-
inline bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
590-
const SimplifyQuery &SQ) {
591-
KnownFPClass Known = computeKnownFPClass(V, fcInf | fcNan, Depth, SQ);
592-
return Known.isKnownNeverNaN() && Known.isKnownNeverInfinity();
593-
}
319+
bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
320+
const SimplifyQuery &SQ);
594321

595322
/// Return true if the floating-point scalar value is not a NaN or if the
596323
/// floating-point vector value has no NaN elements. Return false if a value
597324
/// could ever be NaN.
598-
inline bool isKnownNeverNaN(const Value *V, unsigned Depth,
599-
const SimplifyQuery &SQ) {
600-
KnownFPClass Known = computeKnownFPClass(V, fcNan, Depth, SQ);
601-
return Known.isKnownNeverNaN();
602-
}
325+
bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ);
603326

604327
/// Return false if we can prove that the specified FP value's sign bit is 0.
605328
/// Return true if we can prove that the specified FP value's sign bit is 1.
606329
/// Otherwise return std::nullopt.
607-
inline std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
608-
const SimplifyQuery &SQ) {
609-
KnownFPClass Known = computeKnownFPClass(V, fcAllFlags, Depth, SQ);
610-
return Known.SignBit;
611-
}
330+
std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
331+
const SimplifyQuery &SQ);
612332

613333
/// If the specified value can be set by repeating the same byte in memory,
614334
/// return the i8 value that it is represented with. This is true for all i8

0 commit comments

Comments
 (0)