[llvm] [LV][NFC] Add test for EE-loop with dereferenceable_or_null arg and deref assumption (PR #211803)

Aleksandr Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 24 07:26:16 PDT 2026


https://github.com/aleks-tmb updated https://github.com/llvm/llvm-project/pull/211803

>From c8bea475359bd27e21eb03ea7a27995c57d3015d Mon Sep 17 00:00:00 2001
From: Aleksandr Popov <apopov at azul.com>
Date: Fri, 24 Jul 2026 14:18:02 +0000
Subject: [PATCH] [LV][NFC] Add test for EE-loop with dereferenceable_or_null
 arg and deref assumption

Precommit test showing that a single-early-exit loop is not vectorized when
the pointer is passed as dereferenceable_or_null and the actual accessed
length is only known via a dereferenceable assumption.
---
 .../single-early-exit-deref-assumptions.ll    | 58 +++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/llvm/test/Transforms/LoopVectorize/single-early-exit-deref-assumptions.ll b/llvm/test/Transforms/LoopVectorize/single-early-exit-deref-assumptions.ll
index b73720c126d03..2b4bc017fecbb 100644
--- a/llvm/test/Transforms/LoopVectorize/single-early-exit-deref-assumptions.ll
+++ b/llvm/test/Transforms/LoopVectorize/single-early-exit-deref-assumptions.ll
@@ -1439,6 +1439,64 @@ loop.end:
   ret i64 %retval
 }
 
+; TODO: The dereferenceable_or_null attribute alone is not enough to prove the accesses
+; are safe, but combined with the dereferenceable assumption on the same pointer
+; we can vectorize the early-exit loop.
+define i8 @early_exit_deref_or_null_arg_with_deref_assumption(ptr dereferenceable_or_null(16) %ptr) nofree nosync {
+; CHECK-LABEL: define i8 @early_exit_deref_or_null_arg_with_deref_assumption(
+; CHECK-SAME: ptr dereferenceable_or_null(16) [[PTR:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[LEN_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 8
+; CHECK-NEXT:    [[LEN:%.*]] = load i64, ptr [[LEN_GEP]], align 4
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[PTR]], i64 [[LEN]]) ]
+; CHECK-NEXT:    [[NC:%.*]] = icmp ne i64 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[NC]], label %[[SCALAR_PH:.*]], label %[[DEOPT:.*]]
+; CHECK:       [[SCALAR_PH]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ], [ 0, %[[SCALAR_PH]] ]
+; CHECK-NEXT:    [[ELEMENT_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 [[IV]]
+; CHECK-NEXT:    [[ELEMENT:%.*]] = load i8, ptr [[ELEMENT_GEP]], align 1
+; CHECK-NEXT:    [[RC:%.*]] = icmp eq i8 [[ELEMENT]], 1
+; CHECK-NEXT:    br i1 [[RC]], label %[[EXIT:.*]], label %[[LATCH]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[LEN]]
+; CHECK-NEXT:    br i1 [[EC]], label %[[DEOPT_LOOPEXIT:.*]], label %[[LOOP]]
+; CHECK:       [[DEOPT_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[DEOPT]]
+; CHECK:       [[DEOPT]]:
+; CHECK-NEXT:    unreachable
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[ELEMENT_LCSSA:%.*]] = phi i8 [ [[ELEMENT]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i8 [[ELEMENT_LCSSA]]
+;
+entry:
+  %len_gep = getelementptr inbounds nuw i8, ptr %ptr, i64 8
+  %len = load i64, ptr %len_gep, align 4
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ptr, i64 %len) ]
+  %nc = icmp ne i64 %len, 0
+  br i1 %nc, label %loop, label %deopt
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
+  %element_gep = getelementptr inbounds nuw i8, ptr %ptr, i64 %iv
+  %element = load i8, ptr %element_gep, align 1
+  %rc = icmp eq i8 %element, 1
+  br i1 %rc, label %exit, label %latch
+
+latch:
+  %iv.next = add nuw nsw i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, %len
+  br i1 %ec, label %deopt, label %loop
+
+deopt:
+  unreachable
+
+exit:
+  ret i8 %element
+}
+
 ; Multiple deref assumes that are all too small must not allow vectorizing.
 define i64 @early_exit_deref_assumption_multiple_too_small(ptr noalias %p1, ptr noalias %p2) nofree nosync {
 ; CHECK-LABEL: define i64 @early_exit_deref_assumption_multiple_too_small(



More information about the llvm-commits mailing list