[llvm] [ValueTracking] isNonZero trunc of sub of ptr2int's with recursive GEP where pointers are limited to a 32bit alloc. (PR #84933)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 24 18:22:39 PDT 2024


================
@@ -910,6 +916,67 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
     Changed = true;
   }
 
+  // Handle scenarios like trunc i64 (sub(ptr2int, ptr2int)) to i32 / trunc i64
+  // (lshr(sub(ptr2int, ptr2int))) to i32, where the ptrs are from same object
+  // and one of the pointers is a recursive GEP. And either the objectSize is
+  // known OR is indicative via a compiler flag, which suggests objectSize<4G.
+
+  // Check if trunc src type is same as Ptr type and dest is a 32bit.
+  if (!Trunc.hasNoUnsignedWrap() && SrcWidth == DL.getPointerSizeInBits() &&
+      DestTy == Type::getInt32Ty(Trunc.getContext())) {
+    Value *A, *B;
+    if (match(Src, m_Sub(m_PtrToIntSameSize(DL, m_Value(A)),
+                         m_PtrToIntSameSize(DL, m_Value(B)))) ||
+        match(Src, m_LShr(m_Sub(m_PtrToIntSameSize(DL, m_Value(A)),
+                                m_PtrToIntSameSize(DL, m_Value(B))),
+                          m_ConstantInt()))) {
+      // Check for a specific pattern where A is recursive GEP with a PHI ptr
+      // with incoming values as (Start,Step) and Start==B.
+      auto *GEPA = dyn_cast<GEPOperator>(A);
+      if (!GEPA) {
+        GEPA = dyn_cast<GEPOperator>(B);
+        std::swap(A, B);
+      }
----------------
nikic wrote:

Don't you need inbounds for this (please also add test)? Otherwise the GEPs may go beyond the limit of the allocation size.

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


More information about the llvm-commits mailing list