[llvm] [InstCombine] canonicalize sign bit checks (PR #122962)
Jacob Young via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 15 09:42:18 PST 2025
================
@@ -7025,6 +7027,66 @@ static Instruction *canonicalizeICmpBool(ICmpInst &I,
}
}
+// (icmp X, Y) --> (icmp slt/sgt X, 0/-1) iff Y is outside the signed range of X
+static ICmpInst *canonicalizeSignBitCheck(ICmpInst::Predicate Pred, Value *X,
+ const ConstantRange &XRange,
+ const ConstantRange &YRange) {
+ if (XRange.isSignWrappedSet())
+ return nullptr;
+ unsigned BitWidth = XRange.getBitWidth();
+ APInt SMin = APInt::getSignedMinValue(BitWidth);
+ APInt Zero = APInt::getZero(BitWidth);
+ auto NegResult =
+ XRange.intersectWith(ConstantRange(SMin, Zero), ConstantRange::Signed)
+ .icmpOrInverse(Pred, YRange);
+ if (!NegResult)
+ return nullptr;
+ auto PosResult =
+ XRange.intersectWith(ConstantRange(Zero, SMin), ConstantRange::Signed)
+ .icmpOrInverse(Pred, YRange);
+ if (!PosResult)
+ return nullptr;
+ assert(NegResult != PosResult &&
+ "Known result should been simplified already.");
+ Type *Ty = X->getType();
+ if (*NegResult)
+ return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantInt::getNullValue(Ty));
+ return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantInt::getAllOnesValue(Ty));
+}
----------------
jacobly0 wrote:
I'm trying to use a form that other combines will recognize as a sign check, such as `icmp slt X, 0` or `icmp ugt X, smax`. I'm also not clear which side is considered maximally constrained here. For example if `-5 <= X <= 5` then `icmp ugt X, -6` <=> `icmp slt X, 0` <=> `icmp ult X, 6`. I'm choosing the signed comparison because sign checks can be cheaper and have special combines written for them.
https://github.com/llvm/llvm-project/pull/122962
More information about the llvm-commits
mailing list