[llvm] [SCEV] Fix sign bits of pointers wider than their index type. (PR #225786)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 07:06:21 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Florian Hahn (fhahn)

<details>
<summary>Changes</summary>

ComputeNumSignBits counts bits over the full pointer width. If all sign bits are in the high bits, the code previously did not adjust the number of signed bits. For narrow index types, this could result in the number of sign bits > than the narrow bitwidth triggering an assert in APInt (test example has 64 bit pointer with 16 bit index width.

If all sign bits are in the high bits outside the index width, they do not add any information for the index, just use 1 in that case.

Fixes a crash in the added tests.

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


2 Files Affected:

- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+5-6) 
- (modified) llvm/test/Analysis/ScalarEvolution/ptrtoaddr-i32-index-width.ll (+67-1) 


``````````diff
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 8886186440658..b822b7a5d3927 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6942,12 +6942,11 @@ const ConstantRange &ScalarEvolution::getRangeRef(
     // sign bits than for the value of those sign bits.
     unsigned NS = ComputeNumSignBits(V, DL, &AC, nullptr, &DT);
     if (U->getType()->isPointerTy()) {
-      // If the pointer size is larger than the index size type, this can cause
-      // NS to be larger than BitWidth. So compensate for this.
-      unsigned ptrSize = DL.getPointerTypeSizeInBits(U->getType());
-      int ptrIdxDiff = ptrSize - BitWidth;
-      if (ptrIdxDiff > 0 && ptrSize > BitWidth && NS > (unsigned)ptrIdxDiff)
-        NS -= ptrIdxDiff;
+      // NS counts the sign bits of the whole pointer; drop those above the
+      // index bits.
+      unsigned PtrIdxDiff =
+          DL.getPointerTypeSizeInBits(U->getType()) - BitWidth;
+      NS = NS > PtrIdxDiff ? NS - PtrIdxDiff : 1;
     }
 
     if (NS > 1) {
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoaddr-i32-index-width.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoaddr-i32-index-width.ll
index a60705e341dcf..d65e90c1f85f6 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoaddr-i32-index-width.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoaddr-i32-index-width.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
 ; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s
 
-target datalayout="p:64:64:64:32"
+target datalayout="p:64:64:64:32-p2:64:64:64:16"
 
 define void @ptrtoaddr(ptr %in, ptr %out0) {
 ; CHECK-LABEL: 'ptrtoaddr'
@@ -68,3 +68,69 @@ define void @ptrtoaddr_of_gep(ptr %in, ptr %out0) {
   store i32  %p0, ptr  %out0
   ret void
 }
+
+; The high 32 bits are zero, which says nothing about the index bits.
+define void @ptrtoaddr_of_inttoptr_high_bits_zero(i64 %x, ptr %out0) {
+; CHECK-LABEL: 'ptrtoaddr_of_inttoptr_high_bits_zero'
+; CHECK-NEXT:  Classifying expressions for: @ptrtoaddr_of_inttoptr_high_bits_zero
+; CHECK-NEXT:    %m = and i64 %x, 4294967295
+; CHECK-NEXT:    --> (zext i32 (trunc i64 %x to i32) to i64) U: [0,4294967296) S: [0,4294967296)
+; CHECK-NEXT:    %p = inttoptr i64 %m to ptr
+; CHECK-NEXT:    --> %p U: full-set S: full-set
+; CHECK-NEXT:    %p0 = ptrtoaddr ptr %p to i32
+; CHECK-NEXT:    --> (ptrtoaddr ptr %p to i32) U: full-set S: full-set
+; CHECK-NEXT:  Determining loop execution counts for: @ptrtoaddr_of_inttoptr_high_bits_zero
+;
+  %m = and i64 %x, 4294967295
+  %p = inttoptr i64 %m to ptr
+  %p0 = ptrtoaddr ptr %p to i32
+  store i32 %p0, ptr %out0
+  ret void
+}
+
+; The index is less than half the pointer width.
+define void @ptrtoaddr_of_inttoptr_high_bits_zero_i16_index(i64 %x, ptr %out0) {
+; CHECK-LABEL: 'ptrtoaddr_of_inttoptr_high_bits_zero_i16_index'
+; CHECK-NEXT:  Classifying expressions for: @ptrtoaddr_of_inttoptr_high_bits_zero_i16_index
+; CHECK-NEXT:    %m = and i64 %x, 4294967295
+; CHECK-NEXT:    --> (zext i32 (trunc i64 %x to i32) to i64) U: [0,4294967296) S: [0,4294967296)
+; CHECK-NEXT:    %p = inttoptr i64 %m to ptr addrspace(2)
+; CHECK-NEXT:    --> %p U: full-set S: full-set
+; CHECK-NEXT:    %p0 = ptrtoaddr ptr addrspace(2) %p to i16
+; CHECK-NEXT:    --> (ptrtoaddr ptr addrspace(2) %p to i16) U: full-set S: full-set
+; CHECK-NEXT:  Determining loop execution counts for: @ptrtoaddr_of_inttoptr_high_bits_zero_i16_index
+;
+  %m = and i64 %x, 4294967295
+  %p = inttoptr i64 %m to ptr addrspace(2)
+  %p0 = ptrtoaddr ptr addrspace(2) %p to i16
+  store i16 %p0, ptr %out0
+  ret void
+}
+
+; The pointer has 49 sign bits, leaving 17 in the index.
+define void @ptrtoaddr_of_select_sign_bits(i1 %c, i64 %x, i64 %y, ptr %out0) {
+; CHECK-LABEL: 'ptrtoaddr_of_select_sign_bits'
+; CHECK-NEXT:  Classifying expressions for: @ptrtoaddr_of_select_sign_bits
+; CHECK-NEXT:    %a = and i64 %x, 32767
+; CHECK-NEXT:    --> (zext i15 (trunc i64 %x to i15) to i64) U: [0,32768) S: [0,32768)
+; CHECK-NEXT:    %b = or i64 %y, -32768
+; CHECK-NEXT:    --> %b U: [-32768,0) S: [-32768,0)
+; CHECK-NEXT:    %pa = inttoptr i64 %a to ptr
+; CHECK-NEXT:    --> %pa U: [0,32768) S: [0,32768)
+; CHECK-NEXT:    %pb = inttoptr i64 %b to ptr
+; CHECK-NEXT:    --> %pb U: [-32768,0) S: [-32768,0)
+; CHECK-NEXT:    %p = select i1 %c, ptr %pa, ptr %pb
+; CHECK-NEXT:    --> %p U: [-32768,32768) S: [-32768,32768)
+; CHECK-NEXT:    %p0 = ptrtoaddr ptr %p to i32
+; CHECK-NEXT:    --> (ptrtoaddr ptr %p to i32) U: [-32768,32768) S: [-32768,32768)
+; CHECK-NEXT:  Determining loop execution counts for: @ptrtoaddr_of_select_sign_bits
+;
+  %a = and i64 %x, 32767
+  %b = or i64 %y, -32768
+  %pa = inttoptr i64 %a to ptr
+  %pb = inttoptr i64 %b to ptr
+  %p = select i1 %c, ptr %pa, ptr %pb
+  %p0 = ptrtoaddr ptr %p to i32
+  store i32 %p0, ptr %out0
+  ret void
+}

``````````

</details>


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


More information about the llvm-commits mailing list