[llvm] Optimize fptrunc(x)>=C1 --> x>=C2 (PR #99475)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 3 05:51:06 PDT 2025
================
@@ -8031,6 +8031,101 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
return new FCmpInst(Pred, LHSI->getOperand(1), RHSC, "", &I);
}
+
+// Fold fptrunc(x) < constant --> x < constant if possible.
+static Instruction *foldFCmpFpTrunc(FCmpInst &I, Instruction *LHSI,
+ Constant *RHSC) {
+ FCmpInst::Predicate Pred = I.getPredicate();
+ bool RoundDown = false;
+
+ if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
+ Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
+ RoundDown = true;
+ else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
+ Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
+ RoundDown = false;
+ else
+ return nullptr;
+
+ const APFloat *RValue;
+ if (!match(RHSC, m_APFloat(RValue)))
+ return nullptr;
+
+ // RHSC should not be nan or infinity.
+ if (RValue->isNaN() || RValue->isInfinity())
+ return nullptr;
+
+ Type *LType = LHSI->getOperand(0)->getType();
+ Type *RType = RHSC->getType();
+ Type *LEleType = LType->getScalarType();
+ Type *REleType = RType->getScalarType();
+
+ APFloat NextRValue = *RValue;
+ NextRValue.next(RoundDown);
+
+ // Promote 'RValue' and 'NextRValue' to 'LType'.
+ APFloat ExtRValue = *RValue;
+ APFloat ExtNextRValue = NextRValue;
+ bool lossInfo;
+ ExtRValue.convert(LEleType->getFltSemantics(), APFloat::rmNearestTiesToEven,
+ &lossInfo);
+ ExtNextRValue.convert(LEleType->getFltSemantics(),
+ APFloat::rmNearestTiesToEven, &lossInfo);
+
+ // The (negative) maximum of 'RValue' may become infinity when rounded up
+ // (down). Set the limit of 'ExtNextRValue'.
+ if (NextRValue.isInfinity())
+ ExtNextRValue = scalbn(ExtRValue, 1, APFloat::rmNearestTiesToEven);
+
+ // Binary search to find the maximal (or minimal) value after 'RValue'
+ // promotion. 'RValue' should obey normal comparison rules, which means nan or
+ // inf is not allowed here.
+ APFloat RoundValue{LEleType->getFltSemantics()};
+
+ APFloat LowBound = RoundDown ? ExtNextRValue : ExtRValue;
+ APFloat UpBound = RoundDown ? ExtRValue : ExtNextRValue;
+
+ auto IsRoundingFound = [](const APFloat &LowBound, const APFloat &UpBound) {
+ APFloat UpBoundNext = UpBound;
+ UpBoundNext.next(true);
+ return LowBound == UpBoundNext;
+ };
+
+ auto EqualRValueAfterTrunc = [&](const APFloat &ExtValue) {
+ APFloat TruncValue = ExtValue;
+ TruncValue.convert(REleType->getFltSemantics(),
+ APFloat::rmNearestTiesToEven, &lossInfo);
+ return TruncValue == *RValue;
+ };
+
----------------
kissholic wrote:
Yes, binary search can be replaced by average value for most cases, and I got confused before. However, it seems a little tricky to tackle the comparison with the largest value. I tried several ways to work around, but all are unsatisfactory. Might be late for the final solution.
https://github.com/llvm/llvm-project/pull/99475
More information about the llvm-commits
mailing list