[llvm] [LoopVectorize] Add tests for reverse early-exit loops in deref regions (PR #228062)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 06:56:53 PDT 2026


================
@@ -0,0 +1,97 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "scalar.ph:" --version 6
+; RUN: opt -p loop-vectorize -force-vector-width=4 -S %s | FileCheck %s
+
+; The loops below walk a dereferenceable region backwards, so every load is
+; safe.
+
+; TODO: The AR runs over [0, %length), which is exactly the region the assume
+; marks dereferenceable, so the early-exit loop should be vectorized.
+define ptr @reverse_reaches_base_dynamic_length(i64 %length, ptr %ptr) {
+; CHECK-LABEL: define ptr @reverse_reaches_base_dynamic_length(
+; CHECK-SAME: i64 [[LENGTH:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i64 [[LENGTH]], 0
+; CHECK-NEXT:    br i1 [[NULL_CHECK]], label %[[EXIT:.*]], label %[[PREHEADER:.*]]
+; CHECK:       [[PREHEADER]]:
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[PTR]], i64 [[LENGTH]]) ]
+; CHECK-NEXT:    [[START:%.*]] = sub i64 [[LENGTH]], 1
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ], [ [[START]], %[[PREHEADER]] ]
+; CHECK-NEXT:    [[ELEMENT_GEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[IV]]
+; CHECK-NEXT:    [[ELEMENT:%.*]] = load i8, ptr [[ELEMENT_GEP]], align 1
+; CHECK-NEXT:    [[FOUND_CHECK:%.*]] = icmp eq i8 [[ELEMENT]], 0
+; CHECK-NEXT:    br i1 [[FOUND_CHECK]], label %[[EXIT_LOOPEXIT:.*]], label %[[LATCH]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], -1
+; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ne i64 [[IV]], 0
+; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label %[[LOOP]], label %[[EXIT_LOOPEXIT]]
+; CHECK:       [[EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %null_check = icmp eq i64 %length, 0
+  br i1 %null_check, label %exit, label %preheader
+
+preheader:
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ptr, i64 %length) ]
+  %start = sub i64 %length, 1
+  br label %loop
+
+loop:
+  %iv = phi i64 [ %iv.next, %latch ], [ %start, %preheader ]
+  %element_gep = getelementptr i8, ptr %ptr, i64 %iv
+  %element = load i8, ptr %element_gep, align 1
+  %found_check = icmp eq i8 %element, 0
+  br i1 %found_check, label %exit, label %latch
+
+latch:
+  %iv.next = add i64 %iv, -1
+  %range_check = icmp ne i64 %iv, 0
+  br i1 %range_check, label %loop, label %exit
+
+exit:
+  ret ptr null
----------------
fhahn wrote:

better return something, so this is not a n-op loop

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


More information about the llvm-commits mailing list