[PATCH] D151911: [LVI] Handle icmp of ashr.

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 20 03:13:25 PDT 2023

nikic added inline comments.

Comment at: llvm/lib/Analysis/LazyValueInfo.cpp:1152
+  // Recognize:
+  // icmp sgt (ashr X, ShAmtC), C --> icmp sgt X, ((C + 1) << ShAmtC) - 1
+  // and friends.
I think the better way to explain this is `icmp slt (ashr X, ShAmtC), C --> icmp slt X, C << ShAmtC` (https://alive2.llvm.org/ce/z/ww5u4i). In this case the only precondition is `((C << ShAmtC) >> ShAmtC) == C`. Same for sge.

All the +1/-1 get introduced by using sgt/sle because we're effectively trying to reduce them to that base case. This also introduces the extra preconditions to avoid overflow on +/-1.

With this in mind, I think we can introduce an abstraction like this to transparently handle all the signed predicates while only specifying the fold for slt (without knowledge of anything about ashr in particular):

static std::optional<ConstantRange> getRangeViaSLT(
    CmpInst::Predicate Pred, APInt RHS,
    function_ref<std::optional<ConstantRange>(const APInt &)> Fn) {
  bool Invert = false;
  if (Pred == ICmpInst::SGT || Pred == ICmpInst::SGE) {
    Pred = ICmpInst::getInversePredicate(Pred);
    Invert = true;
  if (Pred == ICmpInst::SLE) {
    Pred = ICmpInst::SLT;
    if (RHS.isSignedMax())
      return std::nullopt; // Could also return full/empty here, if we wanted.
  assert(Pred == ICmpInst::SLT && "Must be signed predicate");
  if (auto CR = Fn(RHS))
    return Invert ? CR->inverse() : CR;
  return std::nullopt;

And then do something like this:
  const APInt *ShAmtC;
  if (CmpInst::isSigned(EdgePred) &&
      match(LHS, m_AShr(m_Specific(Val), m_APInt(ShAmtC))) &&
      match(RHS, m_APInt(C))) {
    return getRangeViaSLT(EdgePred, *C, [&](const APInt &RHS) {
      APInt New = RHS << *ShAmtC;
      if ((New.ashr(*ShAmtC)) != New)
        return std::nullopt;
      return ConstantRange::getNonEmpty(APInt:.getSignedMinValue(BW), New + 1);

Code is untested, but I think the general idea should work.

Comment at: llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll:1257
+  %s = ashr i8 %x, 2
+  %c = icmp sgt i8 %s, 0
+  br i1 %c, label %if, label %else
Can we have a test where the RHS is not zero? We should also have one where the shift round trip precondition does not hold.

  rG LLVM Github Monorepo



More information about the llvm-commits mailing list