[llvm] [SCEV] Move a test into IndVars (PR #147360)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 9 03:12:21 PDT 2025


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/147360

>From 859afa2ff1119c4900adfefa179e629527a13683 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 7 Jul 2025 18:55:23 +0100
Subject: [PATCH 1/2] [SCEV] Move a test into IndVars, preserve coverage

Move the guards.ll into IndVars, as it is really an IndVars test, and
duplicate it in SCEV with an appropriate RUN line.
---
 llvm/test/Analysis/ScalarEvolution/guards.ll  | 135 ++++++------
 llvm/test/Transforms/IndVarSimplify/guards.ll | 195 ++++++++++++++++++
 2 files changed, 256 insertions(+), 74 deletions(-)
 create mode 100644 llvm/test/Transforms/IndVarSimplify/guards.ll

diff --git a/llvm/test/Analysis/ScalarEvolution/guards.ll b/llvm/test/Analysis/ScalarEvolution/guards.ll
index 431b4b189ca60..56e770f98febc 100644
--- a/llvm/test/Analysis/ScalarEvolution/guards.ll
+++ b/llvm/test/Analysis/ScalarEvolution/guards.ll
@@ -1,5 +1,5 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
-; RUN: opt -S -passes=indvars < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s
 
 ; Check that SCEV is able to recognize and use guards to prove
 ; conditions gaurding loop entries and backedges.  This isn't intended
@@ -14,21 +14,20 @@ declare void @llvm.experimental.guard(i1, ...)
 declare void @use(i64 %x)
 
 define void @test_1(ptr %cond_buf, ptr %len_buf) {
-; CHECK-LABEL: define void @test_1
-; CHECK-SAME: (ptr [[COND_BUF:%.*]], ptr [[LEN_BUF:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4, !range [[RNG0:![0-9]+]]
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LOOP]] ]
-; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
-; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp samesign ult i32 [[IV_INC]], [[LEN]]
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
-; CHECK-NEXT:    [[BECOND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
-; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
-; CHECK:       leave:
-; CHECK-NEXT:    ret void
+; CHECK-LABEL: 'test_1'
+; CHECK-NEXT:  Classifying expressions for: @test_1
+; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4, !range !0
+; CHECK-NEXT:    --> %len U: [1,-2147483648) S: [1,-2147483648)
+; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
+; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %becond = load volatile i1, ptr %cond_buf, align 1
+; CHECK-NEXT:    --> %becond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:  Determining loop execution counts for: @test_1
+; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
 ;
 entry:
   %len = load i32, ptr %len_buf, !range !{i32 1, i32 2147483648}
@@ -53,23 +52,21 @@ leave:
 }
 
 define void @test_2(i32 %n, ptr %len_buf) {
-; CHECK-LABEL: define void @test_2
-; CHECK-SAME: (i32 [[N:%.*]], ptr [[LEN_BUF:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4, !range [[RNG1:![0-9]+]]
-; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[LEN]] to i64
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[N]] to i64
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
-; CHECK-NEXT:    call void @use(i64 [[INDVARS_IV]])
-; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp samesign ult i64 [[INDVARS_IV_NEXT]], [[TMP0]]
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
-; CHECK-NEXT:    [[BECOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[TMP1]]
-; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
-; CHECK:       leave:
-; CHECK-NEXT:    ret void
+; CHECK-LABEL: 'test_2'
+; CHECK-NEXT:  Classifying expressions for: @test_2
+; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4, !range !0
+; CHECK-NEXT:    --> %len U: [0,-2147483648) S: [0,-2147483648)
+; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: %n LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
+; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + %n) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.sext = sext i32 %iv to i64
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 %n to i64) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @test_2
+; CHECK-NEXT:  Loop %loop: backedge-taken count is %n
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is %n
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
 ;
 
 entry:
@@ -95,23 +92,20 @@ leave:
 }
 
 define void @test_3(ptr %cond_buf, ptr %len_buf) {
-; CHECK-LABEL: define void @test_3
-; CHECK-SAME: (ptr [[COND_BUF:%.*]], ptr [[LEN_BUF:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4
-; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 [[LEN]], 0
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[ENTRY_COND]]) [ "deopt"() ]
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LOOP]] ]
-; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
-; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp slt i32 [[IV_INC]], [[LEN]]
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
-; CHECK-NEXT:    [[BECOND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
-; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
-; CHECK:       leave:
-; CHECK-NEXT:    ret void
+; CHECK-LABEL: 'test_3'
+; CHECK-NEXT:  Classifying expressions for: @test_3
+; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4
+; CHECK-NEXT:    --> %len U: full-set S: full-set
+; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
+; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %becond = load volatile i1, ptr %cond_buf, align 1
+; CHECK-NEXT:    --> %becond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:  Determining loop execution counts for: @test_3
+; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
 ;
 
 entry:
@@ -138,29 +132,22 @@ leave:
 }
 
 define void @test_4(ptr %cond_buf, ptr %len_buf) {
-; CHECK-LABEL: define void @test_4
-; CHECK-SAME: (ptr [[COND_BUF:%.*]], ptr [[LEN_BUF:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4
-; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 [[LEN]], 0
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[ENTRY_COND]]) [ "deopt"() ]
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[BE:%.*]] ]
-; CHECK-NEXT:    [[IV_INC]] = add i32 [[IV]], 1
-; CHECK-NEXT:    [[COND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
-; CHECK-NEXT:    br i1 [[COND]], label [[LEFT:%.*]], label [[BE]]
-; CHECK:       left:
-; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp slt i32 [[IV_INC]], [[LEN]]
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
-; CHECK-NEXT:    br label [[BE]]
-; CHECK:       be:
-; CHECK-NEXT:    [[IV_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]]
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_CMP]]) [ "deopt"() ]
-; CHECK-NEXT:    [[BECOND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
-; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
-; CHECK:       leave:
-; CHECK-NEXT:    ret void
+; CHECK-LABEL: 'test_4'
+; CHECK-NEXT:  Classifying expressions for: @test_4
+; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4
+; CHECK-NEXT:    --> %len U: full-set S: full-set
+; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
+; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %cond = load volatile i1, ptr %cond_buf, align 1
+; CHECK-NEXT:    --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:    %becond = load volatile i1, ptr %cond_buf, align 1
+; CHECK-NEXT:    --> %becond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:  Determining loop execution counts for: @test_4
+; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
 ;
 
 entry:
diff --git a/llvm/test/Transforms/IndVarSimplify/guards.ll b/llvm/test/Transforms/IndVarSimplify/guards.ll
new file mode 100644
index 0000000000000..431b4b189ca60
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/guards.ll
@@ -0,0 +1,195 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -S -passes=indvars < %s | FileCheck %s
+
+; Check that SCEV is able to recognize and use guards to prove
+; conditions gaurding loop entries and backedges.  This isn't intended
+; to be a comprehensive test of SCEV's simplification capabilities,
+; tests directly testing e.g. if SCEV can elide a sext should go
+; elsewhere.
+
+target datalayout = "n8:16:32:64"
+
+declare void @llvm.experimental.guard(i1, ...)
+
+declare void @use(i64 %x)
+
+define void @test_1(ptr %cond_buf, ptr %len_buf) {
+; CHECK-LABEL: define void @test_1
+; CHECK-SAME: (ptr [[COND_BUF:%.*]], ptr [[LEN_BUF:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4, !range [[RNG0:![0-9]+]]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
+; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp samesign ult i32 [[IV_INC]], [[LEN]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
+; CHECK-NEXT:    [[BECOND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
+; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
+; CHECK:       leave:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %len = load i32, ptr %len_buf, !range !{i32 1, i32 2147483648}
+  br label %loop
+
+loop:
+
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i32 %iv, 1
+
+  %iv.cmp = icmp slt i32 %iv, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
+
+  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
+
+  %becond = load volatile i1, ptr %cond_buf
+  br i1 %becond, label %loop, label %leave
+
+leave:
+  ret void
+}
+
+define void @test_2(i32 %n, ptr %len_buf) {
+; CHECK-LABEL: define void @test_2
+; CHECK-SAME: (i32 [[N:%.*]], ptr [[LEN_BUF:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4, !range [[RNG1:![0-9]+]]
+; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[LEN]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    call void @use(i64 [[INDVARS_IV]])
+; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp samesign ult i64 [[INDVARS_IV_NEXT]], [[TMP0]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
+; CHECK-NEXT:    [[BECOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
+; CHECK:       leave:
+; CHECK-NEXT:    ret void
+;
+
+entry:
+  %len = load i32, ptr %len_buf, !range !{i32 0, i32 2147483648}
+  br label %loop
+
+loop:
+
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i32 %iv, 1
+
+  %iv.sext = sext i32 %iv to i64
+  call void @use(i64 %iv.sext)
+
+  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
+
+  %becond = icmp ne i32 %iv, %n
+  br i1 %becond, label %loop, label %leave
+
+leave:
+  ret void
+}
+
+define void @test_3(ptr %cond_buf, ptr %len_buf) {
+; CHECK-LABEL: define void @test_3
+; CHECK-SAME: (ptr [[COND_BUF:%.*]], ptr [[LEN_BUF:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4
+; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 [[LEN]], 0
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[ENTRY_COND]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
+; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp slt i32 [[IV_INC]], [[LEN]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
+; CHECK-NEXT:    [[BECOND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
+; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
+; CHECK:       leave:
+; CHECK-NEXT:    ret void
+;
+
+entry:
+  %len = load i32, ptr %len_buf
+  %entry.cond = icmp sgt i32 %len, 0
+  call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i32 %iv, 1
+
+  %iv.cmp = icmp slt i32 %iv, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
+
+  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
+
+  %becond = load volatile i1, ptr %cond_buf
+  br i1 %becond, label %loop, label %leave
+
+leave:
+  ret void
+}
+
+define void @test_4(ptr %cond_buf, ptr %len_buf) {
+; CHECK-LABEL: define void @test_4
+; CHECK-SAME: (ptr [[COND_BUF:%.*]], ptr [[LEN_BUF:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4
+; CHECK-NEXT:    [[ENTRY_COND:%.*]] = icmp sgt i32 [[LEN]], 0
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[ENTRY_COND]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[BE:%.*]] ]
+; CHECK-NEXT:    [[IV_INC]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
+; CHECK-NEXT:    br i1 [[COND]], label [[LEFT:%.*]], label [[BE]]
+; CHECK:       left:
+; CHECK-NEXT:    [[IV_INC_CMP:%.*]] = icmp slt i32 [[IV_INC]], [[LEN]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_INC_CMP]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[BE]]
+; CHECK:       be:
+; CHECK-NEXT:    [[IV_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IV_CMP]]) [ "deopt"() ]
+; CHECK-NEXT:    [[BECOND:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
+; CHECK-NEXT:    br i1 [[BECOND]], label [[LOOP]], label [[LEAVE:%.*]]
+; CHECK:       leave:
+; CHECK-NEXT:    ret void
+;
+
+entry:
+  %len = load i32, ptr %len_buf
+  %entry.cond = icmp sgt i32 %len, 0
+  call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  %iv.inc = add i32 %iv, 1
+
+  %cond = load volatile i1, ptr %cond_buf
+  br i1 %cond, label %left, label %be
+
+left:
+  ; Does not dominate the backedge, so cannot be used in the inductive proof
+  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
+  br label %be
+
+be:
+
+  %iv.cmp = icmp slt i32 %iv, %len
+  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
+
+  %becond = load volatile i1, ptr %cond_buf
+  br i1 %becond, label %loop, label %leave
+
+leave:
+  ret void
+}

>From e2e743e22378ddacc28ece957884373a5b831bb1 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Wed, 9 Jul 2025 11:10:20 +0100
Subject: [PATCH 2/2] [SCEV/test] Remove guards.ll

---
 llvm/test/Analysis/ScalarEvolution/guards.ll | 182 -------------------
 1 file changed, 182 deletions(-)
 delete mode 100644 llvm/test/Analysis/ScalarEvolution/guards.ll

diff --git a/llvm/test/Analysis/ScalarEvolution/guards.ll b/llvm/test/Analysis/ScalarEvolution/guards.ll
deleted file mode 100644
index 56e770f98febc..0000000000000
--- a/llvm/test/Analysis/ScalarEvolution/guards.ll
+++ /dev/null
@@ -1,182 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s
-
-; Check that SCEV is able to recognize and use guards to prove
-; conditions gaurding loop entries and backedges.  This isn't intended
-; to be a comprehensive test of SCEV's simplification capabilities,
-; tests directly testing e.g. if SCEV can elide a sext should go
-; elsewhere.
-
-target datalayout = "n8:16:32:64"
-
-declare void @llvm.experimental.guard(i1, ...)
-
-declare void @use(i64 %x)
-
-define void @test_1(ptr %cond_buf, ptr %len_buf) {
-; CHECK-LABEL: 'test_1'
-; CHECK-NEXT:  Classifying expressions for: @test_1
-; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4, !range !0
-; CHECK-NEXT:    --> %len U: [1,-2147483648) S: [1,-2147483648)
-; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
-; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %becond = load volatile i1, ptr %cond_buf, align 1
-; CHECK-NEXT:    --> %becond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
-; CHECK-NEXT:  Determining loop execution counts for: @test_1
-; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
-; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
-; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
-;
-entry:
-  %len = load i32, ptr %len_buf, !range !{i32 1, i32 2147483648}
-  br label %loop
-
-loop:
-
-  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
-  %iv.inc = add i32 %iv, 1
-
-  %iv.cmp = icmp slt i32 %iv, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
-
-  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
-
-  %becond = load volatile i1, ptr %cond_buf
-  br i1 %becond, label %loop, label %leave
-
-leave:
-  ret void
-}
-
-define void @test_2(i32 %n, ptr %len_buf) {
-; CHECK-LABEL: 'test_2'
-; CHECK-NEXT:  Classifying expressions for: @test_2
-; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4, !range !0
-; CHECK-NEXT:    --> %len U: [0,-2147483648) S: [0,-2147483648)
-; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
-; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: %n LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + %n) LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %iv.sext = sext i32 %iv to i64
-; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 %n to i64) LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:  Determining loop execution counts for: @test_2
-; CHECK-NEXT:  Loop %loop: backedge-taken count is %n
-; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is %n
-; CHECK-NEXT:  Loop %loop: Trip multiple is 1
-;
-
-entry:
-  %len = load i32, ptr %len_buf, !range !{i32 0, i32 2147483648}
-  br label %loop
-
-loop:
-
-  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
-  %iv.inc = add i32 %iv, 1
-
-  %iv.sext = sext i32 %iv to i64
-  call void @use(i64 %iv.sext)
-
-  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
-
-  %becond = icmp ne i32 %iv, %n
-  br i1 %becond, label %loop, label %leave
-
-leave:
-  ret void
-}
-
-define void @test_3(ptr %cond_buf, ptr %len_buf) {
-; CHECK-LABEL: 'test_3'
-; CHECK-NEXT:  Classifying expressions for: @test_3
-; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4
-; CHECK-NEXT:    --> %len U: full-set S: full-set
-; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
-; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %becond = load volatile i1, ptr %cond_buf, align 1
-; CHECK-NEXT:    --> %becond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
-; CHECK-NEXT:  Determining loop execution counts for: @test_3
-; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
-; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
-; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
-;
-
-entry:
-  %len = load i32, ptr %len_buf
-  %entry.cond = icmp sgt i32 %len, 0
-  call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
-  br label %loop
-
-loop:
-  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
-  %iv.inc = add i32 %iv, 1
-
-  %iv.cmp = icmp slt i32 %iv, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
-
-  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
-
-  %becond = load volatile i1, ptr %cond_buf
-  br i1 %becond, label %loop, label %leave
-
-leave:
-  ret void
-}
-
-define void @test_4(ptr %cond_buf, ptr %len_buf) {
-; CHECK-LABEL: 'test_4'
-; CHECK-NEXT:  Classifying expressions for: @test_4
-; CHECK-NEXT:    %len = load i32, ptr %len_buf, align 4
-; CHECK-NEXT:    --> %len U: full-set S: full-set
-; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
-; CHECK-NEXT:    --> {0,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %iv.inc = add i32 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
-; CHECK-NEXT:    %cond = load volatile i1, ptr %cond_buf, align 1
-; CHECK-NEXT:    --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
-; CHECK-NEXT:    %becond = load volatile i1, ptr %cond_buf, align 1
-; CHECK-NEXT:    --> %becond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
-; CHECK-NEXT:  Determining loop execution counts for: @test_4
-; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
-; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
-; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
-;
-
-entry:
-  %len = load i32, ptr %len_buf
-  %entry.cond = icmp sgt i32 %len, 0
-  call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
-  br label %loop
-
-loop:
-  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
-  %iv.inc = add i32 %iv, 1
-
-  %cond = load volatile i1, ptr %cond_buf
-  br i1 %cond, label %left, label %be
-
-left:
-  ; Does not dominate the backedge, so cannot be used in the inductive proof
-  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
-  br label %be
-
-be:
-
-  %iv.cmp = icmp slt i32 %iv, %len
-  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
-
-  %becond = load volatile i1, ptr %cond_buf
-  br i1 %becond, label %loop, label %leave
-
-leave:
-  ret void
-}



More information about the llvm-commits mailing list