Skip to content

[LoopInterchange] Don't rely on ASSERTS build for tests. NFC. #116780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions llvm/test/Transforms/LoopInterchange/call-instructions-remarks.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
; REQUIRES: asserts
; RUN: opt < %s -passes=loop-interchange -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t -S \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remarks don't require asserts I think

; 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"

@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
}
109 changes: 41 additions & 68 deletions llvm/test/Transforms/LoopInterchange/call-instructions.ll
Original file line number Diff line number Diff line change
@@ -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"

Expand All @@ -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.
Expand All @@ -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

Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
; REQUIRES: asserts
; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info -S -debug 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
}
Loading
Loading