[llvm] [LVI] Look through pointer operand when evaluating ptrtoints (PR #162627)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 9 03:09:30 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Antonio Frighetto (antoniofrighetto)

<details>
<summary>Changes</summary>

Add support for constraints over `ptrtoint` casts. Particularly, assumed predicate invariants over the integral value of a pointer are constraints on the cast to integer value itself.

Fixes: https://github.com/llvm/llvm-project/issues/158324.

---
Full diff: https://github.com/llvm/llvm-project/pull/162627.diff


2 Files Affected:

- (modified) llvm/lib/Analysis/LazyValueInfo.cpp (+20) 
- (modified) llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll (+55) 


``````````diff
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 0e5bc481383a0..bc6b704bbc943 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -966,6 +966,7 @@ LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
   // recurse on our operand.  This can cut a long search short if we know we're
   // not going to be able to get any useful information anways.
   switch (CI->getOpcode()) {
+  case Instruction::PtrToInt:
   case Instruction::Trunc:
   case Instruction::SExt:
   case Instruction::ZExt:
@@ -977,6 +978,11 @@ LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
     return ValueLatticeElement::getOverdefined();
   }
 
+  // Assumed predicate over the integral value of the pointer are constraints on
+  // the cast to integer value itself.
+  if (auto *PTI = dyn_cast<PtrToIntInst>(CI))
+    return getBlockValue(PTI->getPointerOperand(), BB, PTI);
+
   // Figure out the range of the LHS.  If that fails, we still apply the
   // transfer rule on the full set since we may be able to locally infer
   // interesting facts.
@@ -1350,6 +1356,20 @@ std::optional<ValueLatticeElement> LazyValueInfoImpl::getValueFromICmpCondition(
   }
 
   Type *Ty = Val->getType();
+
+  // On the off-chance we may compute a range over the address of a pointer.
+  ConstantInt *CI = nullptr;
+  if (Ty->isPointerTy() && LHS == Val &&
+      match(RHS, m_IntToPtr(m_ConstantInt(CI)))) {
+    if (Ty->getPointerAddressSpace() ==
+        RHS->getType()->getPointerAddressSpace()) {
+      ConstantRange RHSRange(CI->getValue());
+      ConstantRange AllowedR =
+          ConstantRange::makeAllowedICmpRegion(EdgePred, RHSRange);
+      return ValueLatticeElement::getRange(AllowedR);
+    }
+  }
+
   if (!Ty->isIntegerTy())
     return ValueLatticeElement::getOverdefined();
 
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
index c9ee233b5a461..68fc73743f607 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
@@ -355,3 +355,58 @@ define i8 @test_umax_nneg(i8 %a, i8 %b) {
   %ret = call i8 @llvm.umax.i8(i8 %nneg_a, i8 %nneg_b)
   ret i8 %ret
 }
+
+define i8 @test_umin_ptr_address(ptr %p) {
+; CHECK-LABEL: @test_umin_ptr_address(
+; CHECK-NEXT:    [[PI:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT:    [[PI_SHR:%.*]] = lshr i64 [[PI]], 32
+; CHECK-NEXT:    [[PI_HI:%.*]] = trunc nuw nsw i64 [[PI_SHR]] to i8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[P]], inttoptr (i64 176093659136 to ptr)
+; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT:    ret i8 [[PI_HI]]
+;
+  %pi = ptrtoint ptr %p to i64
+  %pi.shr = lshr i64 %pi, 32
+  %pi.hi = trunc nuw i64 %pi.shr to i8
+  %umin = call i8 @llvm.umin.i8(i8 %pi.hi, i8 41)
+  %cmp = icmp ult ptr %p, inttoptr (i64 176093659136 to ptr)
+  call void @llvm.assume(i1 %cmp)
+  ret i8 %umin
+}
+
+define i8 @test_umax_ptr_address(ptr %p) {
+; CHECK-LABEL: @test_umax_ptr_address(
+; CHECK-NEXT:    [[PI:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT:    [[PI_SHR:%.*]] = lshr i64 [[PI]], 32
+; CHECK-NEXT:    [[PI_HI:%.*]] = trunc nuw i64 [[PI_SHR]] to i8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt ptr [[P]], inttoptr (i64 180388626431 to ptr)
+; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT:    ret i8 [[PI_HI]]
+;
+  %pi = ptrtoint ptr %p to i64
+  %pi.shr = lshr i64 %pi, 32
+  %pi.hi = trunc nuw i64 %pi.shr to i8
+  %umin = call i8 @llvm.umax.i8(i8 %pi.hi, i8 41)
+  %cmp = icmp ugt ptr %p, inttoptr (i64 180388626431 to ptr)
+  call void @llvm.assume(i1 %cmp)
+  ret i8 %umin
+}
+
+define i8 @test_umin_ptr_address_negative(ptr %p) {
+; CHECK-LABEL: @test_umin_ptr_address_negative(
+; CHECK-NEXT:    [[PI:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT:    [[PI_SHR:%.*]] = lshr i64 [[PI]], 32
+; CHECK-NEXT:    [[PI_HI:%.*]] = trunc nuw i64 [[PI_SHR]] to i8
+; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[PI_HI]], i8 41)
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne ptr [[P]], inttoptr (i64 176093659136 to ptr)
+; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT:    ret i8 [[UMIN]]
+;
+  %pi = ptrtoint ptr %p to i64
+  %pi.shr = lshr i64 %pi, 32
+  %pi.hi = trunc nuw i64 %pi.shr to i8
+  %umin = call i8 @llvm.umin.i8(i8 %pi.hi, i8 41)
+  %cmp = icmp ne ptr %p, inttoptr (i64 176093659136 to ptr)
+  call void @llvm.assume(i1 %cmp)
+  ret i8 %umin
+}

``````````

</details>


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


More information about the llvm-commits mailing list