[llvm] [LVI] Handle icmp of ashr. (PR #68010)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 19 10:44:36 PDT 2023


================
@@ -1148,6 +1149,57 @@ static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
           CR.getUnsignedMin().zext(BitWidth), APInt(BitWidth, 0)));
   }
 
+  // Recognize:
+  // icmp sgt (ashr X, ShAmtC), C --> icmp sgt X, ((C + 1) << ShAmtC) - 1
+  // and friends.
+  // Preconditions: (C != SIGNED_MAX) &&
+  //                ((C+1) << ShAmtC != SIGNED_MIN) &&
+  //                (((C+1) << ShAmtC) >> ShAmtC) == (C+1)
+  const APInt *ShAmtC;
+  if (CmpInst::isSigned(EdgePred) &&
+      match(LHS, m_AShr(m_Specific(Val), m_APInt(ShAmtC))) &&
+      match(RHS, m_APInt(C))) {
+    APInt New = ((*C + 1) << *ShAmtC) - 1;
+    APInt MaxSigned = APInt::getSignedMaxValue(New.getBitWidth());
+    APInt MinSigned = APInt::getSignedMinValue(New.getBitWidth());
+    auto CheckPreConds = [&]() {
+      if (*C == MaxSigned)
+        return false;
+      APInt Shifted = (*C + 1) << *ShAmtC;
+      if (Shifted == MinSigned)
+        return false;
+      if ((Shifted.ashr(*ShAmtC)) != (*C + 1))
+        return false;
+      return true;
+    };
+    if (!CheckPreConds())
+      return ValueLatticeElement::getOverdefined();
+    APInt Lower, Upper;
+    switch (EdgePred) {
+    default:
+      llvm_unreachable("Unknown signed predicate!");
+    case ICmpInst::ICMP_SGT:
+      Lower = New + 1;
+      Upper = MaxSigned;
+      break;
+    case ICmpInst::ICMP_SLE:
+      Lower = MinSigned;
+      Upper = New + 1;
+      break;
+    case ICmpInst::ICMP_SGE:
----------------
goldsteinn wrote:

Does this hold for preds other then SGT/SLE: https://alive2.llvm.org/ce/z/wHF_sk

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


More information about the llvm-commits mailing list