[llvm] [LoopInterchange] Don't rely on ASSERTS build for tests. NFC. (PR #116780)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 19 02:41:04 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Sjoerd Meijer (sjoerdmeijer)
<details>
<summary>Changes</summary>
A lot of interchange tests unnecessary relied on a build with ASSERTS enabled. Instead, simply check the IR output for both negative and positive tests so that we don't rely on debug messages. This increases test coverage as these tests will now also run with non-assert builds. For a couple of files keeping some of the debug tests was useful, so separated out them out and moved them to a similarly named *-remarks.ll file.
---
Patch is 52.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116780.diff
11 Files Affected:
- (added) llvm/test/Transforms/LoopInterchange/call-instructions-remarks.ll (+63)
- (modified) llvm/test/Transforms/LoopInterchange/call-instructions.ll (+41-68)
- (added) llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar-remark.ll (+117)
- (modified) llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar.ll (+39-122)
- (modified) llvm/test/Transforms/LoopInterchange/innermost-latch-uses-values-in-middle-header.ll (+53-11)
- (modified) llvm/test/Transforms/LoopInterchange/interchange-flow-dep-outer.ll (+65-24)
- (modified) llvm/test/Transforms/LoopInterchange/interchange-no-deps.ll (+53-18)
- (modified) llvm/test/Transforms/LoopInterchange/interchanged-loop-nest-3.ll (+57-15)
- (modified) llvm/test/Transforms/LoopInterchange/not-interchanged-dependencies-1.ll (+32-10)
- (modified) llvm/test/Transforms/LoopInterchange/not-interchanged-loop-nest-3.ll (+52-15)
- (modified) llvm/test/Transforms/LoopInterchange/not-interchanged-tightly-nested.ll (+119-25)
``````````diff
diff --git a/llvm/test/Transforms/LoopInterchange/call-instructions-remarks.ll b/llvm/test/Transforms/LoopInterchange/call-instructions-remarks.ll
new file mode 100644
index 00000000000000..4ed3e7e0f5d003
--- /dev/null
+++ b/llvm/test/Transforms/LoopInterchange/call-instructions-remarks.ll
@@ -0,0 +1,63 @@
+; REQUIRES: asserts
+; RUN: opt < %s -passes=loop-interchange -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t -S \
+; RUN: -verify-dom-info -verify-loop-info 2>&1
+; RUN: FileCheck --input-file=%t %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+ at A = common global [100 x [100 x i32]] zeroinitializer
+
+declare void @foo(i64 %a)
+declare void @bar(i64 %a) readnone
+
+;;--------------------------------------Test case 01------------------------------------
+;; Not safe to interchange, because the called function `foo` is not marked as
+;; readnone, so it could introduce dependences.
+;;
+;; for(int i=0;i<100;i++) {
+;; for(int j=1;j<100;j++) {
+;; foo(i);
+;; A[j][i] = A[j][i]+k;
+;; }
+;; }
+
+; CHECK: --- !Missed
+; CHECK-NEXT: Pass: loop-interchange
+; CHECK-NEXT: Name: CallInst
+; CHECK-NEXT: Function: interchange_01
+; CHECK-NEXT: Args:
+; CHECK-NEXT: - String: Cannot interchange loops due to call instruction.
+
+define void @interchange_01(i32 %k) {
+entry:
+ br label %for1.header
+
+for1.header:
+ %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc10 ]
+ br label %for2
+
+for2:
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for2 ], [ 1, %for1.header ]
+ call void @foo(i64 %indvars.iv23)
+ %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %indvars.iv, i64 %indvars.iv23
+ %lv = load i32, ptr %arrayidx5
+ %add = add nsw i32 %lv, %k
+ store i32 %add, ptr %arrayidx5
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv, 99
+ br i1 %exitcond, label %for2.loopexit , label %for2
+
+for2.loopexit:
+ br label %for1.inc10
+
+for1.inc10:
+ %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
+ %exitcond26 = icmp eq i64 %indvars.iv23, 99
+ br i1 %exitcond26, label %for1.loopexit, label %for1.header
+
+for1.loopexit:
+ br label %exit
+
+exit:
+ ret void
+}
diff --git a/llvm/test/Transforms/LoopInterchange/call-instructions.ll b/llvm/test/Transforms/LoopInterchange/call-instructions.ll
index 49e877aa0d36e7..b207166302d21c 100644
--- a/llvm/test/Transforms/LoopInterchange/call-instructions.ll
+++ b/llvm/test/Transforms/LoopInterchange/call-instructions.ll
@@ -1,7 +1,5 @@
-; REQUIRES: asserts
-; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t -S \
-; RUN: -verify-dom-info -verify-loop-info -stats 2>&1 | FileCheck -check-prefix=STATS %s
-; RUN: FileCheck --input-file=%t %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=loop-interchange -S -verify-dom-info -verify-loop-info 2>&1 | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -10,58 +8,6 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
declare void @foo(i64 %a)
declare void @bar(i64 %a) readnone
-;;--------------------------------------Test case 01------------------------------------
-;; Not safe to interchange, because the called function `foo` is not marked as
-;; readnone, so it could introduce dependences.
-;;
-;; for(int i=0;i<100;i++) {
-;; for(int j=1;j<100;j++) {
-;; foo(i);
-;; A[j][i] = A[j][i]+k;
-;; }
-;; }
-
-; CHECK: --- !Missed
-; CHECK-NEXT: Pass: loop-interchange
-; CHECK-NEXT: Name: CallInst
-; CHECK-NEXT: Function: interchange_01
-; CHECK-NEXT: Args:
-; CHECK-NEXT: - String: Cannot interchange loops due to call instruction.
-
-define void @interchange_01(i32 %k) {
-entry:
- br label %for1.header
-
-for1.header:
- %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc10 ]
- br label %for2
-
-for2:
- %indvars.iv = phi i64 [ %indvars.iv.next, %for2 ], [ 1, %for1.header ]
- call void @foo(i64 %indvars.iv23)
- %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %indvars.iv, i64 %indvars.iv23
- %lv = load i32, ptr %arrayidx5
- %add = add nsw i32 %lv, %k
- store i32 %add, ptr %arrayidx5
- %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %exitcond = icmp eq i64 %indvars.iv, 99
- br i1 %exitcond, label %for2.loopexit , label %for2
-
-for2.loopexit:
- br label %for1.inc10
-
-for1.inc10:
- %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
- %exitcond26 = icmp eq i64 %indvars.iv23, 99
- br i1 %exitcond26, label %for1.loopexit, label %for1.header
-
-for1.loopexit:
- br label %exit
-
-exit:
- ret void
-}
-
;;--------------------------------------Test case 02------------------------------------
;; Safe to interchange, because the called function `bar` is marked as readnone,
;; so it cannot introduce dependences.
@@ -72,16 +18,46 @@ exit:
;; A[j][i] = A[j][i]+k;
;; }
;; }
-
-; CHECK: --- !Passed
-; CHECK-NEXT: Pass: loop-interchange
-; CHECK-NEXT: Name: Interchanged
-; CHECK-NEXT: Function: interchange_02
-; CHECK-NEXT: Args:
-; CHECK-NEXT: - String: Loop interchanged with enclosing loop.
-; CHECK-NEXT: ...
-
+;
define void @interchange_02(i32 %k) {
+; CHECK-LABEL: define void @interchange_02(
+; CHECK-SAME: i32 [[K:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[FOR2_PREHEADER:.*]]
+; CHECK: [[FOR1_HEADER_PREHEADER:.*]]:
+; CHECK-NEXT: br label %[[FOR1_HEADER:.*]]
+; CHECK: [[FOR1_HEADER]]:
+; CHECK-NEXT: [[INDVARS_IV23:%.*]] = phi i64 [ [[INDVARS_IV_NEXT24:%.*]], %[[FOR1_INC10:.*]] ], [ 0, %[[FOR1_HEADER_PREHEADER]] ]
+; CHECK-NEXT: br label %[[FOR2_SPLIT1:.*]]
+; CHECK: [[FOR2_PREHEADER]]:
+; CHECK-NEXT: br label %[[FOR2:.*]]
+; CHECK: [[FOR2]]:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0:%.*]], %[[FOR2_SPLIT:.*]] ], [ 1, %[[FOR2_PREHEADER]] ]
+; CHECK-NEXT: br label %[[FOR1_HEADER_PREHEADER]]
+; CHECK: [[FOR2_SPLIT1]]:
+; CHECK-NEXT: call void @bar(i64 [[INDVARS_IV23]])
+; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 [[INDVARS_IV]], i64 [[INDVARS_IV23]]
+; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LV]], [[K]]
+; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX5]], align 4
+; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV]], 99
+; CHECK-NEXT: br label %[[FOR2_LOOPEXIT:.*]]
+; CHECK: [[FOR2_SPLIT]]:
+; CHECK-NEXT: [[TMP0]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[INDVARS_IV]], 99
+; CHECK-NEXT: br i1 [[TMP1]], label %[[FOR1_LOOPEXIT:.*]], label %[[FOR2]]
+; CHECK: [[FOR2_LOOPEXIT]]:
+; CHECK-NEXT: br label %[[FOR1_INC10]]
+; CHECK: [[FOR1_INC10]]:
+; CHECK-NEXT: [[INDVARS_IV_NEXT24]] = add nuw nsw i64 [[INDVARS_IV23]], 1
+; CHECK-NEXT: [[EXITCOND26:%.*]] = icmp eq i64 [[INDVARS_IV23]], 99
+; CHECK-NEXT: br i1 [[EXITCOND26]], label %[[FOR2_SPLIT]], label %[[FOR1_HEADER]]
+; CHECK: [[FOR1_LOOPEXIT]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
entry:
br label %for1.header
@@ -114,6 +90,3 @@ for1.loopexit:
exit:
ret void
}
-
-; Check stats, we interchanged 1 out of 2 loops.
-; STATS: 1 loop-interchange - Number of loops interchanged
diff --git a/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar-remark.ll b/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar-remark.ll
new file mode 100644
index 00000000000000..51fa6469cdbbbf
--- /dev/null
+++ b/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar-remark.ll
@@ -0,0 +1,117 @@
+; REQUIRES: asserts
+; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info -S -debug 2>&1 | FileCheck %s
+
+ at A = common global [100 x [100 x i64]] zeroinitializer
+ at N = dso_local local_unnamed_addr global i64 100, align 8
+
+; for(int i=0;i<100;i++)
+; for(int j=0;j<i;j++)
+; A[j][i] = A[j][i]+k;
+;
+; Inner loop induction variable exit condition depends on the
+; outer loop induction variable, i.e., triangular loops.
+;
+; CHECK: Loop structure not understood by pass
+; CHECK: Not interchanging loops. Cannot prove legality.
+;
+define void @interchange_01(i64 %k) {
+entry:
+ br label %for1.header
+
+for1.header:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
+ br label %for2
+
+for2:
+ %j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
+ %arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
+ %lv = load i64, ptr %arrayidx5
+ %add = add nsw i64 %lv, %k
+ store i64 %add, ptr %arrayidx5
+ %j.next = add nuw nsw i64 %j, 1
+ %exitcond = icmp eq i64 %j, %i
+ br i1 %exitcond, label %for1.inc10, label %for2
+
+for1.inc10:
+ %i.next = add nuw nsw i64 %i, 1
+ %exitcond26 = icmp eq i64 %i, 99
+ br i1 %exitcond26, label %for.end12, label %for1.header
+
+for.end12:
+ ret void
+}
+
+
+; for(int i=0;i<100;i++)
+; for(int j=0;j+i<100;j++)
+; A[j][i] = A[j][i]+k;
+;
+; Inner loop induction variable exit condition depends on the
+; outer loop induction variable, i.e., triangular loops.
+;
+; CHECK: Loop structure not understood by pass
+; CHECK: Not interchanging loops. Cannot prove legality.
+;
+define void @interchange_02(i64 %k) {
+entry:
+ br label %for1.header
+
+for1.header:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
+ br label %for2
+
+for2:
+ %j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
+ %arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
+ %lv = load i64, ptr %arrayidx5
+ %add = add nsw i64 %lv, %k
+ store i64 %add, ptr %arrayidx5
+ %0 = add nuw nsw i64 %j, %i
+ %j.next = add nuw nsw i64 %j, 1
+ %exitcond = icmp eq i64 %0, 100
+ br i1 %exitcond, label %for1.inc10, label %for2
+
+for1.inc10:
+ %i.next = add nuw nsw i64 %i, 1
+ %exitcond26 = icmp eq i64 %i, 99
+ br i1 %exitcond26, label %for.end12, label %for1.header
+
+for.end12:
+ ret void
+}
+
+; for(int i=0;i<100;i++)
+; for(int j=0;i>j;j++)
+; A[j][i] = A[j][i]+k;
+;
+; Inner loop induction variable exit condition depends on the
+; outer loop induction variable, i.e., triangular loops.
+; CHECK: Loop structure not understood by pass
+; CHECK: Not interchanging loops. Cannot prove legality.
+;
+define void @interchange_03(i64 %k) {
+entry:
+ br label %for1.header
+
+for1.header:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
+ br label %for2
+
+for2:
+ %j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
+ %arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
+ %lv = load i64, ptr %arrayidx5
+ %add = add nsw i64 %lv, %k
+ store i64 %add, ptr %arrayidx5
+ %j.next = add nuw nsw i64 %j, 1
+ %exitcond = icmp ne i64 %i, %j
+ br i1 %exitcond, label %for2, label %for1.inc10
+
+for1.inc10:
+ %i.next = add nuw nsw i64 %i, 1
+ %exitcond26 = icmp eq i64 %i, 99
+ br i1 %exitcond26, label %for.end12, label %for1.header
+
+for.end12:
+ ret void
+}
diff --git a/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar.ll b/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar.ll
index 0a1d1e52507994..ff88375e318567 100644
--- a/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar.ll
+++ b/llvm/test/Transforms/LoopInterchange/inner-indvar-depend-on-outer-indvar.ll
@@ -1,130 +1,47 @@
-; REQUIRES: asserts
-; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -verify-dom-info -verify-loop-info \
-; RUN: -S -debug 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info -S 2>&1 | FileCheck %s
@A = common global [100 x [100 x i64]] zeroinitializer
@N = dso_local local_unnamed_addr global i64 100, align 8
-
-;; for(int i=0;i<100;i++)
-;; for(int j=0;j<i;j++)
-;; A[j][i] = A[j][i]+k;
-
-;; Inner loop induction variable exit condition depends on the
-;; outer loop induction variable, i.e., triangular loops.
-; CHECK: Loop structure not understood by pass
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_01(i64 %k) {
-entry:
- br label %for1.header
-
-for1.header:
- %i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
- br label %for2
-
-for2:
- %j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
- %arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
- %lv = load i64, ptr %arrayidx5
- %add = add nsw i64 %lv, %k
- store i64 %add, ptr %arrayidx5
- %j.next = add nuw nsw i64 %j, 1
- %exitcond = icmp eq i64 %j, %i
- br i1 %exitcond, label %for1.inc10, label %for2
-
-for1.inc10:
- %i.next = add nuw nsw i64 %i, 1
- %exitcond26 = icmp eq i64 %i, 99
- br i1 %exitcond26, label %for.end12, label %for1.header
-
-for.end12:
- ret void
-}
-
-
-;; for(int i=0;i<100;i++)
-;; for(int j=0;j+i<100;j++)
-;; A[j][i] = A[j][i]+k;
-
-;; Inner loop induction variable exit condition depends on the
-;; outer loop induction variable, i.e., triangular loops.
-; CHECK: Loop structure not understood by pass
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_02(i64 %k) {
-entry:
- br label %for1.header
-
-for1.header:
- %i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
- br label %for2
-
-for2:
- %j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
- %arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
- %lv = load i64, ptr %arrayidx5
- %add = add nsw i64 %lv, %k
- store i64 %add, ptr %arrayidx5
- %0 = add nuw nsw i64 %j, %i
- %j.next = add nuw nsw i64 %j, 1
- %exitcond = icmp eq i64 %0, 100
- br i1 %exitcond, label %for1.inc10, label %for2
-
-for1.inc10:
- %i.next = add nuw nsw i64 %i, 1
- %exitcond26 = icmp eq i64 %i, 99
- br i1 %exitcond26, label %for.end12, label %for1.header
-
-for.end12:
- ret void
-}
-
-;; for(int i=0;i<100;i++)
-;; for(int j=0;i>j;j++)
-;; A[j][i] = A[j][i]+k;
-
-;; Inner loop induction variable exit condition depends on the
-;; outer loop induction variable, i.e., triangular loops.
-; CHECK: Loop structure not understood by pass
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_03(i64 %k) {
-entry:
- br label %for1.header
-
-for1.header:
- %i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
- br label %for2
-
-for2:
- %j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
- %arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
- %lv = load i64, ptr %arrayidx5
- %add = add nsw i64 %lv, %k
- store i64 %add, ptr %arrayidx5
- %j.next = add nuw nsw i64 %j, 1
- %exitcond = icmp ne i64 %i, %j
- br i1 %exitcond, label %for2, label %for1.inc10
-
-for1.inc10:
- %i.next = add nuw nsw i64 %i, 1
- %exitcond26 = icmp eq i64 %i, 99
- br i1 %exitcond26, label %for.end12, label %for1.header
-
-for.end12:
- ret void
-}
-
-;; for(int i=0;i<100;i++)
-;; for(int j=0;N>j;j++)
-;; A[j][i] = A[j][i]+k;
-
-;; Inner loop induction variable exit condition depends on
-;; an outer loop invariant, can do interchange.
-; CHECK: Loops interchanged
-
+; Inner loop induction variable exit condition depends on
+; an outer loop invariant, can do interchange.
+;
define void @interchange_04(i64 %k) {
+; CHECK-LABEL: define void @interchange_04(
+; CHECK-SAME: i64 [[K:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @N, align 4
+; CHECK-NEXT: br label %[[FOR2_PREHEADER:.*]]
+; CHECK: [[FOR1_HEADER_PREHEADER:.*]]:
+; CHECK-NEXT: br label %[[FOR1_HEADER:.*]]
+; CHECK: [[FOR1_HEADER]]:
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], %[[FOR1_INC10:.*]] ], [ 0, %[[FOR1_HEADER_PREHEADER]] ]
+; CHECK-NEXT: br label %[[FOR2_SPLIT1:.*]]
+; CHECK: [[FOR2_PREHEADER]]:
+; CHECK-NEXT: br label %[[FOR2:.*]]
+; CHECK: [[FOR2]]:
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[TMP1:%.*]], %[[FOR2_SPLIT:.*]] ], [ 0, %[[FOR2_PREHEADER]] ]
+; CHECK-NEXT: br label %[[FOR1_HEADER_PREHEADER]]
+; CHECK: [[FOR2_SPLIT1]]:
+; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 [[J]], i64 [[I]]
+; CHECK-NEXT: [[LV:%.*]] = load i64, ptr [[ARRAYIDX5]], align 4
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[LV]], [[K]]
+; CHECK-NEXT: store i64 [[ADD]], ptr [[ARRAYIDX5]], align 4
+; CHECK-NEXT: [[J_NEXT:%.*]] = add nuw nsw i64 [[J]], 1
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[TMP0]], [[J]]
+; CHECK-NEXT: br label %[[FOR1_INC10]]
+; CHECK: [[FOR2_SPLIT]]:
+; CHECK-NEXT: [[TMP1]] = add nuw nsw i64 [[J]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[TMP0]], [[J]]
+; CHECK-NEXT: br i1 [[TMP2]], label %[[FOR2]], label %[[FOR_END12:.*]]
+; CHECK: [[FOR1_INC10]]:
+; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1
+; CHECK-NEXT: [[EXITCOND26:%.*]] = icmp eq i64 [[I]], 99
+; CHECK-NEXT: br i1 [[EXITCOND26]], label %[[FOR2_SPLIT]], label %[[FOR1_HEADER]]
+; CHECK: [[FOR_END12]]:
+; CHECK-NEXT: ret void
+;
entry:
%0 = load i64, ptr @N, align 4
br label %for1.header
diff --git a/llvm/test/Transforms/LoopInterchange/innermost-latch-uses-values-in-middle-header.ll b/llvm/test/Transforms/LoopInterchange/innermost-latch-uses-values-in-middle-header.ll
index 11e59c6db9f327..bad84224d445ab 100644
--- a/llvm/test/Transforms/LoopInterchange/innermost-latch-uses-values-in-middle-header.ll
+++ b/llvm/test/Transforms/LoopInterchange/innermost-latch-uses-values-in-middle-header.ll
@@ -1,19 +1,61 @@
-; REQUIRES: asserts
-; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -verify-dom-info -verify-loop-info \
-; RUN: -S -debug 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info -S 2>&1 | FileCheck %s
@a = common global i32 0, align 4
@d = common dso_local local_unnamed_addr global [1 x [6 x i32]] zeroinitializer, align 4
-;; After interchanging the innermost and the middle loop, we should not continue
-;; doing interchange for the (new) middle loop and the outermost loop, because of
-;; values defined in the new innermost loop not available in the exiting block of
-;; the entire loop nest.
-; CHECK: Loops are legal to interchange
-; CHECK: Loops interchanged.
-; CHECK: Found unsupported PHI nodes in inner loop latch.
-; CHECK: Not interchanging loops. Cannot prove legality.
+; After interchanging the innermost and the middle loop, we should not continue
+; doing interchange for the (new) middle loop and the outermost loop, because of
+; values defined in the new innermost loop not available in the exiting block of
+; the entire loop nest.
+;
define void @innermost_latch_uses_values_in_middle_header() {
+; CHECK-LABEL: define void @innermost_latch_uses_values_in_middle_header() {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4
+; CHECK-NEXT: [[B:%.*]] = add i32 80, 1
+; CHECK-NEXT: br label %[[OUTERMOST_HEADER:.*]]
+; CHECK: [[OUTERMOST_HEADER]]:
+; CHECK-NEXT: [[INDVAR_OUTERMOST:%.*]] = phi i32 [ 10, %[[ENTRY]] ], [ [[INDVAR_OUTERMOST_NEXT:%.*]], %[[OUTERMOST_LATCH:.*]] ]
+; CHECK-NEXT: [[TOBOOL71_I:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[TOBOOL71_I]], label %[[INNERMOST_HEADER_PREHEADER:.*]], label %[[OUTERMOST_LATCH]]
+; CHECK: [[MIDDLE_HEADER_PREHEADER:.*]]:
+; CHECK-NEXT: br label %[[MIDDLE_HEADER:.*]]
+; CHECK: [[MIDDLE_HEADER]]:
+; CHECK-NEXT: [[INDVAR_MIDDLE:%.*]] = phi i64 [ [[INDVAR_MIDDLE_NEXT:%.*]], %[[MIDDLE_LATCH:.*]] ], [ 4, %[[MIDDLE_HEADER_PREHEADER]] ]
+; CHECK-NEXT: [[INDVAR_MIDDLE_WIDE:%.*]] = zext i32 [[B]] to i64
+; CHECK-NEXT: br label %[[INNERMOST_BODY:.*]]
+; CHECK: [[INNERMOST_HEADER_PREHEADER]]:
+; CHECK-NEXT: br label %[[INNERMOST_...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/116780
More information about the llvm-commits
mailing list