[llvm] Optimize fptrunc(x)>=C1 --> x>=C2 (PR #99475)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 7 00:17:30 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;
+  };
+
----------------
arsenm wrote:

Are you planning on switching the patch to do this? Needs comments either way 

https://github.com/llvm/llvm-project/pull/99475


More information about the llvm-commits mailing list