[llvm] [InstCombineCompares] Try to "strengthen" compares based on known bits. (PR #79405)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 24 10:30:46 PST 2024
================
@@ -6100,6 +6101,91 @@ bool InstCombinerImpl::replacedSelectWithOperand(SelectInst *SI,
return false;
}
+// Try to "strengthen" the RHS of compare based on known bits.
+// For example, replace `icmp ugt %x, 14` with `icmp ugt %x, 15` when
+// it is known that the two least significant bits of `%x` is zero.
+static Instruction *strengthenICmpUsingKnownBits(ICmpInst &I,
+ KnownBits Op0Known,
+ KnownBits Op1Known,
+ unsigned BitWidth) {
+ if (!BitWidth)
+ return nullptr;
+ if (!(Op1Known.isConstant() && Op0Known.Zero.isMask()))
+ return nullptr;
+
+ Value *Op0 = I.getOperand(0);
+ ICmpInst::Predicate Pred = I.getPredicate();
+ Type *Ty = Op0->getType();
+ APInt RHSConst = Op1Known.getConstant();
+
+ ConstantRange Op0PredRange =
+ ConstantRange::makeExactICmpRegion(Pred, RHSConst);
+ int KnownZeroMaskLength = BitWidth - Op0Known.Zero.countLeadingZeros();
+ if (KnownZeroMaskLength == 0)
+ return nullptr;
+
+ APInt PowOf2(BitWidth, 1 << KnownZeroMaskLength);
+ APInt Op0MinAccordingToPred(BitWidth, 0);
+ APInt Op0MaxAccordingToPred(BitWidth, 0);
+ APInt Op0MinRefinedByKnownBits(BitWidth, 0);
+ APInt Op0MaxRefinedByKnownBits(BitWidth, 0);
+ APInt NewLower(BitWidth, 0);
+ APInt NewUpper(BitWidth, 0);
+ bool ImprovedLower = false;
+ bool ImprovedUpper = false;
+ if (I.isSigned()) {
+ Op0MinAccordingToPred = Op0PredRange.getSignedMin();
+ Op0MaxAccordingToPred = Op0PredRange.getSignedMax();
+ // Compute the smallest number satisfying the known-bits constrained
+ // which is at greater or equal Op0MinAccordingToPred.
+ Op0MinRefinedByKnownBits =
+ PowOf2 * APIntOps::RoundingSDiv(Op0MinAccordingToPred, PowOf2,
+ APInt::Rounding::UP);
+ // Compute the largest number satisfying the known-bits constrained
+ // which is at less or equal Op0MaxAccordingToPred.
+ Op0MaxRefinedByKnownBits =
+ PowOf2 * APIntOps::RoundingSDiv(Op0MaxAccordingToPred, PowOf2,
+ APInt::Rounding::DOWN);
+ NewLower = APIntOps::smax(Op0MinRefinedByKnownBits, Op0MinAccordingToPred);
+ NewUpper = APIntOps::smin(Op0MaxRefinedByKnownBits, Op0MaxAccordingToPred);
+ ImprovedLower = NewLower.sgt(Op0MinAccordingToPred);
+ ImprovedUpper = NewUpper.slt(Op0MaxAccordingToPred);
+ } else {
+ Op0MinAccordingToPred = Op0PredRange.getUnsignedMin();
+ Op0MaxAccordingToPred = Op0PredRange.getUnsignedMax();
+ Op0MinRefinedByKnownBits =
+ PowOf2 * APIntOps::RoundingUDiv(Op0MinAccordingToPred, PowOf2,
+ APInt::Rounding::UP);
+ Op0MaxRefinedByKnownBits =
+ PowOf2 * APIntOps::RoundingUDiv(Op0MaxAccordingToPred, PowOf2,
+ APInt::Rounding::DOWN);
+ NewLower = APIntOps::umax(Op0MinRefinedByKnownBits, Op0MinAccordingToPred);
+ NewUpper = APIntOps::umin(Op0MaxRefinedByKnownBits, Op0MaxAccordingToPred);
+ ImprovedLower = NewLower.ugt(Op0MinAccordingToPred);
+ ImprovedUpper = NewUpper.ult(Op0MaxAccordingToPred);
+ }
----------------
goldsteinn wrote:
Instead of creating this custom bounds, why not use `ConstantRange`?
https://github.com/llvm/llvm-project/pull/79405
More information about the llvm-commits
mailing list