[llvm] Optimize fptrunc(x)>=C1 --> x>=C2 (PR #99475)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 5 00:49:37 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:
Although the absence of `next(max_float)` which is infinity actually, we can image its existence in wider types, and it should equal to `max_float + (max_float - prev(max_float))` in most cases (if not all). A bound check can ensure its correctness.
This method balance the efficiency and correctness, and keep consistence with logics for other floats despite the fact that it might not be standard for all float types.
https://github.com/llvm/llvm-project/pull/99475
More information about the llvm-commits
mailing list