[llvm] [GISel] Add KnownFPClass Analysis to GISelValueTrackingPass (PR #134611)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue May 13 03:03:33 PDT 2025
================
@@ -637,6 +653,1102 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
ComputeKnownBitsCache[R] = Known;
}
+static bool outputDenormalIsIEEEOrPosZero(const MachineFunction &MF, LLT Ty) {
+ Ty = Ty.getScalarType();
+ DenormalMode Mode = MF.getDenormalMode(getFltSemanticForLLT(Ty));
+ return Mode.Output == DenormalMode::IEEE ||
+ Mode.Output == DenormalMode::PositiveZero;
+}
+
+std::pair<Register, FPClassTest> GISelValueTracking::fcmpToClassTest(
+ FCmpInst::Predicate Pred, const MachineFunction &MF, Register LHS,
+ const APFloat *ConstRHS, bool LookThroughSrc) {
+
+ auto [Src, ClassIfTrue, ClassIfFalse] =
+ fcmpImpliesClass(Pred, MF, LHS, *ConstRHS, LookThroughSrc);
+ if (Src && ClassIfTrue == ~ClassIfFalse)
+ return {Src, ClassIfTrue};
+
+ return {Register(), fcAllFlags};
+}
+
+std::tuple<Register, FPClassTest, FPClassTest>
+GISelValueTracking::fcmpImpliesClass(CmpInst::Predicate Pred,
+ const MachineFunction &MF, Register LHS,
+ FPClassTest RHSClass,
+ bool LookThroughSrc) {
+ auto LookThrough = [&](Register LHS, Register &Src) {
+ return LookThroughSrc && mi_match(LHS, MRI, m_GFabs(m_Reg(Src)));
+ };
+
+ auto ModeQuery = [&](Register LHS) {
+ LLT Ty = MRI.getType(LHS).getScalarType();
+ return MF.getDenormalMode(getFltSemanticForLLT(Ty));
+ };
+
+ return llvm::fcmpImpliesClass(Pred, ModeQuery, LHS, RHSClass, LookThrough);
+}
+
+std::tuple<Register, FPClassTest, FPClassTest>
+GISelValueTracking::fcmpImpliesClass(CmpInst::Predicate Pred,
+ const MachineFunction &MF, Register LHS,
+ const APFloat &ConstRHS,
+ bool LookThroughSrc) {
+ auto LookThrough = [&](Register LHS, Register &Src) {
+ return LookThroughSrc && mi_match(LHS, MRI, m_GFabs(m_Reg(Src)));
+ };
+
+ auto ModeQuery = [&](Register LHS) {
+ LLT Ty = MRI.getType(LHS).getScalarType();
+ return MF.getDenormalMode(getFltSemanticForLLT(Ty));
+ };
+
+ return llvm::fcmpImpliesClass(Pred, ModeQuery, LHS, ConstRHS, LookThrough);
+}
+
+std::tuple<Register, FPClassTest, FPClassTest>
+GISelValueTracking::fcmpImpliesClass(CmpInst::Predicate Pred,
+ const MachineFunction &MF, Register LHS,
+ Register RHS, bool LookThroughSrc) {
+
+ const ConstantFP *ConstRHS;
+ if (!mi_match(RHS, MRI, m_GFCst(ConstRHS)))
+ return {Register(), fcAllFlags, fcAllFlags};
+
+ auto LookThrough = [&](Register LHS, Register &Src) {
+ return LookThroughSrc && mi_match(LHS, MRI, m_GFabs(m_Reg(Src)));
+ };
+
+ auto ModeQuery = [&](Register LHS) {
+ LLT Ty = MRI.getType(LHS).getScalarType();
+ return MF.getDenormalMode(getFltSemanticForLLT(Ty));
+ };
+
+ // TODO: Just call computeKnownFPClass for RHS to handle non-constants.
+ return llvm::fcmpImpliesClass(Pred, ModeQuery, LHS, ConstRHS->getValueAPF(),
+ LookThrough);
+}
+
+void GISelValueTracking::computeKnownFPClass(Register R, KnownFPClass &Known,
+ FPClassTest InterestedClasses,
+ unsigned Depth) {
+ LLT Ty = MRI.getType(R);
+ APInt DemandedElts =
+ Ty.isFixedVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
+ computeKnownFPClass(R, DemandedElts, InterestedClasses, Known, Depth);
+}
+
+void GISelValueTracking::computeKnownFPClassForFPTrunc(
+ const MachineInstr &MI, const APInt &DemandedElts,
+ FPClassTest InterestedClasses, KnownFPClass &Known, unsigned Depth) {
+ if ((InterestedClasses & (KnownFPClass::OrderedLessThanZeroMask | fcNan)) ==
+ fcNone)
+ return;
+
+ Register Val = MI.getOperand(1).getReg();
+ KnownFPClass KnownSrc;
+ computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
+ Depth + 1);
+
+ // Sign should be preserved
+ // TODO: Handle cannot be ordered greater than zero
+ if (KnownSrc.cannotBeOrderedLessThanZero())
+ Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+
+ Known.propagateNaN(KnownSrc, true);
+
+ // Infinity needs a range check.
+}
+
+void GISelValueTracking::computeKnownFPClass(Register R,
+ const APInt &DemandedElts,
+ FPClassTest InterestedClasses,
+ KnownFPClass &Known,
+ unsigned Depth) {
+ assert(Known.isUnknown() && "should not be called with known information");
+
+ if (!DemandedElts) {
+ // No demanded elts, better to assume we don't know anything.
+ Known.resetAll();
+ return;
+ }
+
+ assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+
+ MachineInstr &MI = *MRI.getVRegDef(R);
+ unsigned Opcode = MI.getOpcode();
+ LLT DstTy = MRI.getType(R);
+
+ if (!DstTy.isValid()) {
+ Known.resetAll();
+ return;
+ }
+
+ if (auto Cst = GFConstant::getConstant(R, MRI)) {
+ switch (Cst->getKind()) {
+ case GFConstant::GFConstantKind::Scalar: {
+ auto APF = Cst->getScalarValue();
+ Known.KnownFPClasses = APF.classify();
+ Known.SignBit = APF.isNegative();
+ break;
+ }
+ case GFConstant::GFConstantKind::FixedVector: {
+ Known.KnownFPClasses = fcNone;
+ bool SignBitAllZero = true;
+ bool SignBitAllOne = true;
+
+ for (auto C : *Cst) {
+ Known.KnownFPClasses |= C.classify();
+ if (C.isNegative())
+ SignBitAllZero = false;
+ else
+ SignBitAllOne = false;
+ }
+
+ if (SignBitAllOne != SignBitAllZero)
+ Known.SignBit = SignBitAllOne;
+
+ break;
+ }
+ case GFConstant::GFConstantKind::ScalableVector: {
+ Known.resetAll();
+ break;
+ }
+ }
+
+ return;
+ }
+
+ FPClassTest KnownNotFromFlags = fcNone;
+ if (MI.getFlag(MachineInstr::MIFlag::FmNoNans))
+ KnownNotFromFlags |= fcNan;
+ if (MI.getFlag(MachineInstr::MIFlag::FmNoInfs))
+ KnownNotFromFlags |= fcInf;
+
+ // We no longer need to find out about these bits from inputs if we can
+ // assume this from flags/attributes.
+ InterestedClasses &= ~KnownNotFromFlags;
+
+ auto ClearClassesFromFlags =
+ make_scope_exit([=, &Known] { Known.knownNot(KnownNotFromFlags); });
+
+ // All recursive calls that increase depth must come after this.
+ if (Depth == MaxAnalysisRecursionDepth)
+ return;
+
+ // auto CacheEntry = ComputeKnownFPClassCache.find(R);
+ // if (CacheEntry != ComputeKnownFPClassCache.end()) {
+ // Known = CacheEntry->second;
+ // LLVM_DEBUG(dbgs() << "Cache hit at ");
+ // // LLVM_DEBUG(dumpResult(MI, Known, Depth));
+ // // assert(Known.getBitWidth() == BitWidth && "Cache entry size doesn't
+ // match"); return;
+ // }
----------------
arsenm wrote:
Commented out debug printing
https://github.com/llvm/llvm-project/pull/134611
More information about the llvm-commits
mailing list