[llvm] [IndVars] Refine tests for evaluating final value pointer AddRecs (NFC). (PR #207076)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 1 13:01:45 PDT 2026
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/207076
Update tests for evaluating final value of pointer AddRecs. Add missing cases and add some brief clarifying comments to some test cases.
>From bf38c5815a94ae2126a9e6bfbaf9ae5590b6f0e5 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 1 Jul 2026 19:35:17 +0100
Subject: [PATCH] [IndVars] Refine tests for evaluating final value pointer
AddRecs (NFC).
Update tests for evaluating final value of pointer AddRecs. Add missing
cases and add some brief clarifying comments to some test cases.
---
.../IndVarSimplify/exit-value-gep-inbounds.ll | 180 +++++++++++++++---
1 file changed, 151 insertions(+), 29 deletions(-)
diff --git a/llvm/test/Transforms/IndVarSimplify/exit-value-gep-inbounds.ll b/llvm/test/Transforms/IndVarSimplify/exit-value-gep-inbounds.ll
index 8037c40c66d7c..4d07c99a78b3e 100644
--- a/llvm/test/Transforms/IndVarSimplify/exit-value-gep-inbounds.ll
+++ b/llvm/test/Transforms/IndVarSimplify/exit-value-gep-inbounds.ll
@@ -1,6 +1,92 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes='loop(indvars)' -verify-scev -S %s | FileCheck %s
+define ptr @unknown_start_inbounds(ptr %p, i64 %n) {
+; CHECK-LABEL: define ptr @unknown_start_inbounds(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP0]]
+; CHECK-NEXT: ret ptr [[SCEVGEP]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %inc = getelementptr inbounds nuw i8, ptr %p, i64 %iv
+ %iv.next = add nuw nsw i64 %iv, 1
+ %cond = icmp eq i64 %iv.next, %n
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ ret ptr %inc
+}
+
+define ptr @unknown_start_nonneg_step(ptr %p, i64 %n, i32 %s) {
+; CHECK-LABEL: define ptr @unknown_start_nonneg_step(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]], i32 [[S:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[STEP:%.*]] = zext i32 [[S]] to i64
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], [[STEP]]
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP1]]
+; CHECK-NEXT: ret ptr [[SCEVGEP]]
+;
+entry:
+ %step = zext i32 %s to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %offset = mul nuw nsw i64 %iv, %step
+ %inc = getelementptr inbounds nuw i8, ptr %p, i64 %offset
+ %iv.next = add nuw nsw i64 %iv, 1
+ %cond = icmp eq i64 %iv.next, %n
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ ret ptr %inc
+}
+
+define ptr @flagged_addexpr_at_scope_key() {
+; CHECK-LABEL: define ptr @flagged_addexpr_at_scope_key() {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT: [[BASE:%.*]] = inttoptr i64 -1 to ptr
+; CHECK-NEXT: [[INC:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 [[IV]]
+; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[IV_NEXT]], 4
+; CHECK-NEXT: br i1 [[C]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi ptr [ [[INC]], %[[LOOP]] ]
+; CHECK-NEXT: ret ptr [[INC_LCSSA]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %base = inttoptr i64 -1 to ptr
+ %inc = getelementptr nuw i8, ptr %base, i64 %iv
+ %iv.next = add nuw nsw i64 %iv, 1
+ %c = icmp eq i64 %iv.next, 4
+ br i1 %c, label %exit, label %loop
+
+exit:
+ ret ptr %inc
+}
+
define ptr @pointer_advance_inbounds(ptr %p, i64 %n) {
; CHECK-LABEL: define ptr @pointer_advance_inbounds(
; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]]) {
@@ -27,6 +113,64 @@ exit:
ret ptr %inc
}
+define ptr @nonconstant_nonneg_step_inbounds(ptr %p, i64 %n, i32 %s) {
+; CHECK-LABEL: define ptr @nonconstant_nonneg_step_inbounds(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]], i32 [[S:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[STEP:%.*]] = zext i32 [[S]] to i64
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[N]], [[STEP]]
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP0]]
+; CHECK-NEXT: ret ptr [[SCEVGEP]]
+;
+entry:
+ %step = zext i32 %s to i64
+ br label %loop
+
+loop:
+ %ptr = phi ptr [ %p, %entry ], [ %inc, %loop ]
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %inc = getelementptr inbounds nuw i8, ptr %ptr, i64 %step
+ %iv.next = add nuw nsw i64 %iv, 1
+ %cond = icmp eq i64 %iv.next, %n
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ ret ptr %inc
+}
+
+; Start of AddRec may wrap.
+define ptr @wrapping_start_nuw(ptr %base) {
+; CHECK-LABEL: define ptr @wrapping_start_nuw(
+; CHECK-SAME: ptr [[BASE:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE]], i64 6
+; CHECK-NEXT: ret ptr [[SCEVGEP]]
+;
+entry:
+ %p0 = getelementptr i8, ptr %base, i64 2
+ br label %loop
+
+loop:
+ %ptr = phi ptr [ %p0, %entry ], [ %inc, %loop ]
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %inc = getelementptr nuw i8, ptr %ptr, i64 1
+ %iv.next = add nuw nsw i64 %iv, 1
+ %cond = icmp eq i64 %iv.next, 4
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ ret ptr %inc
+}
+
+; No no-wrap flag on the step GEP at all.
define ptr @pointer_advance_no_inbounds(ptr %p, i64 %n) {
; CHECK-LABEL: define ptr @pointer_advance_no_inbounds(
; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]]) {
@@ -53,6 +197,8 @@ exit:
ret ptr %inc
}
+; Only the first loop's recurrence is inbounds; the second loop's pointer is
+; advanced by a plain GEP, so no `nuw` may be inferred for its exit value.
define ptr @two_loops_only_first_inbounds(ptr %p, i64 %n) {
; CHECK-LABEL: define ptr @two_loops_only_first_inbounds(
; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]]) {
@@ -95,6 +241,7 @@ exit:
ret ptr %inc2
}
+; The step is of unknown sign, so the closed form may decrease and wrap.
define ptr @unknown_step_inbounds(ptr %p, i64 %n, i64 %step) {
; CHECK-LABEL: define ptr @unknown_step_inbounds(
; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]], i64 [[STEP:%.*]]) {
@@ -122,6 +269,8 @@ exit:
ret ptr %inc
}
+; The start is below the base (negative constant offset), so the offset
+; relative to the base is negative and `nuw` cannot be inferred.
define ptr @start_below_base_inbounds(ptr %base) {
; CHECK-LABEL: define ptr @start_below_base_inbounds(
; CHECK-SAME: ptr [[BASE:%.*]]) {
@@ -149,6 +298,7 @@ exit:
ret ptr %inc
}
+; The start has a symbolic offset of unknown sign.
define ptr @symbolic_start_below_base_inbounds(ptr %base, i64 %m, i64 %n) {
; CHECK-LABEL: define ptr @symbolic_start_below_base_inbounds(
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[M:%.*]], i64 [[N:%.*]]) {
@@ -177,35 +327,7 @@ exit:
ret ptr %inc
}
-define ptr @nonconstant_nonneg_step_inbounds(ptr %p, i64 %n, i32 %s) {
-; CHECK-LABEL: define ptr @nonconstant_nonneg_step_inbounds(
-; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]], i32 [[S:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[STEP:%.*]] = zext i32 [[S]] to i64
-; CHECK-NEXT: br label %[[LOOP:.*]]
-; CHECK: [[LOOP]]:
-; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[N]], [[STEP]]
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP0]]
-; CHECK-NEXT: ret ptr [[SCEVGEP]]
-;
-entry:
- %step = zext i32 %s to i64
- br label %loop
-
-loop:
- %ptr = phi ptr [ %p, %entry ], [ %inc, %loop ]
- %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
- %inc = getelementptr inbounds nuw i8, ptr %ptr, i64 %step
- %iv.next = add nuw nsw i64 %iv, 1
- %cond = icmp eq i64 %iv.next, %n
- br i1 %cond, label %exit, label %loop
-
-exit:
- ret ptr %inc
-}
-
+; Non-affine (polynomial) recurrence.
define ptr @polynomial_addrec_inbounds(ptr %p, i64 %n) {
; CHECK-LABEL: define ptr @polynomial_addrec_inbounds(
; CHECK-SAME: ptr [[P:%.*]], i64 [[N:%.*]]) {
More information about the llvm-commits
mailing list