mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-19 15:13:49 -04:00
95265ffb1f
As preparation for LoopInterchange becoming a loop pass, it needs to preserve ScalarEvolution. Even though interchanging should not change the trip count of the loop, it modifies loop entry, latch and exit blocks. I added -verify-scev to some loop interchange tests, but the verification does not catch problems caused by missing invalidation of SE in loop interchange, as the trip counts themselves do not change. So there might be potential to make the SE verification covering more stuff in the future. Reviewers: mkazantsev, efriedma, karthikthecool Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D52026 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@342209 91177308-0d34-0410-b5e6-96231b3b80d8
168 lines
6.1 KiB
LLVM
168 lines
6.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -verify-loop-info -verify-scev -S | FileCheck %s
|
|
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
@A = common global [100 x [100 x i64]] zeroinitializer
|
|
@B = common global [100 x i64] zeroinitializer
|
|
|
|
;; for(int i=0;i<100;i++)
|
|
;; for(int j=0;j<100;j++)
|
|
;; A[j][i] = A[j][i]+k;
|
|
|
|
define void @interchange_01(i64 %k, i64 %N) {
|
|
; CHECK-LABEL: @interchange_01(
|
|
; 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 [ [[INDVARS_IV_NEXT:%.*]], [[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]], [100 x [100 x i64]]* @A, i64 0, i64 [[INDVARS_IV]], i64 [[INDVARS_IV23]]
|
|
; CHECK-NEXT: [[LV:%.*]] = load i64, i64* [[ARRAYIDX5]]
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[LV]], [[K:%.*]]
|
|
; CHECK-NEXT: store i64 [[ADD]], i64* [[ARRAYIDX5]]
|
|
; CHECK-NEXT: br label [[FOR1_INC10]]
|
|
; CHECK: for2.split:
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV]], 99
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END12:%.*]], label [[FOR2]]
|
|
; 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: for.end12:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for1.header
|
|
|
|
for1.header:
|
|
%j23 = phi i64 [ 0, %entry ], [ %j.next24, %for1.inc10 ]
|
|
br label %for2
|
|
|
|
for2:
|
|
%j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
|
|
%arrayidx5 = getelementptr inbounds [100 x [100 x i64]], [100 x [100 x i64]]* @A, i64 0, i64 %j, i64 %j23
|
|
%lv = load i64, i64* %arrayidx5
|
|
%add = add nsw i64 %lv, %k
|
|
store i64 %add, i64* %arrayidx5
|
|
%j.next = add nuw nsw i64 %j, 1
|
|
%exitcond = icmp eq i64 %j, 99
|
|
br i1 %exitcond, label %for1.inc10, label %for2
|
|
|
|
for1.inc10:
|
|
%j.next24 = add nuw nsw i64 %j23, 1
|
|
%exitcond26 = icmp eq i64 %j23, 99
|
|
br i1 %exitcond26, label %for.end12, label %for1.header
|
|
|
|
for.end12:
|
|
ret void
|
|
}
|
|
|
|
;; for(int i=0;i<100;i++)
|
|
;; for(int j=100;j>=0;j--)
|
|
;; A[j][i] = A[j][i]+k;
|
|
|
|
define void @interchange_02(i64 %k) {
|
|
; CHECK-LABEL: @interchange_02(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR3_PREHEADER:%.*]]
|
|
; CHECK: for1.header.preheader:
|
|
; CHECK-NEXT: br label [[FOR1_HEADER:%.*]]
|
|
; CHECK: for1.header:
|
|
; CHECK-NEXT: [[INDVARS_IV19:%.*]] = phi i64 [ [[INDVARS_IV_NEXT20:%.*]], [[FOR1_INC10:%.*]] ], [ 0, [[FOR1_HEADER_PREHEADER:%.*]] ]
|
|
; CHECK-NEXT: br label [[FOR3_SPLIT1:%.*]]
|
|
; CHECK: for3.preheader:
|
|
; CHECK-NEXT: br label [[FOR3:%.*]]
|
|
; CHECK: for3:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR3_SPLIT:%.*]] ], [ 100, [[FOR3_PREHEADER]] ]
|
|
; CHECK-NEXT: br label [[FOR1_HEADER_PREHEADER]]
|
|
; CHECK: for3.split1:
|
|
; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x [100 x i64]], [100 x [100 x i64]]* @A, i64 0, i64 [[INDVARS_IV]], i64 [[INDVARS_IV19]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[ARRAYIDX5]]
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP0]], [[K:%.*]]
|
|
; CHECK-NEXT: store i64 [[ADD]], i64* [[ARRAYIDX5]]
|
|
; CHECK-NEXT: br label [[FOR1_INC10]]
|
|
; CHECK: for3.split:
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0
|
|
; CHECK-NEXT: br i1 [[CMP2]], label [[FOR3]], label [[FOR_END11:%.*]]
|
|
; CHECK: for1.inc10:
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT20]] = add nuw nsw i64 [[INDVARS_IV19]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT20]], 100
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR3_SPLIT]], label [[FOR1_HEADER]]
|
|
; CHECK: for.end11:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for1.header
|
|
|
|
for1.header:
|
|
%j19 = phi i64 [ 0, %entry ], [ %j.next20, %for1.inc10 ]
|
|
br label %for3
|
|
|
|
for3:
|
|
%j = phi i64 [ 100, %for1.header ], [ %j.next, %for3 ]
|
|
%arrayidx5 = getelementptr inbounds [100 x [100 x i64]], [100 x [100 x i64]]* @A, i64 0, i64 %j, i64 %j19
|
|
%0 = load i64, i64* %arrayidx5
|
|
%add = add nsw i64 %0, %k
|
|
store i64 %add, i64* %arrayidx5
|
|
%j.next = add nsw i64 %j, -1
|
|
%cmp2 = icmp sgt i64 %j, 0
|
|
br i1 %cmp2, label %for3, label %for1.inc10
|
|
|
|
for1.inc10:
|
|
%j.next20 = add nuw nsw i64 %j19, 1
|
|
%exitcond = icmp eq i64 %j.next20, 100
|
|
br i1 %exitcond, label %for.end11, label %for1.header
|
|
|
|
for.end11:
|
|
ret void
|
|
}
|
|
|
|
;; Test to make sure we can handle output dependencies.
|
|
;;
|
|
;; for (int i = 1; i < 100; ++i)
|
|
;; for(int j = 1; j < 99; ++j) {
|
|
;; A[j][i] = i;
|
|
;; A[j][i+1] = j;
|
|
;; }
|
|
;; FIXME: DA misses this case after D35430
|
|
|
|
define void @interchange_10() {
|
|
entry:
|
|
br label %for1.header
|
|
|
|
for1.header:
|
|
%j23 = phi i64 [ 1, %entry ], [ %j.next24, %for1.inc10 ]
|
|
%j.next24 = add nuw nsw i64 %j23, 1
|
|
br label %for2
|
|
|
|
for2:
|
|
%j = phi i64 [ %j.next, %for2 ], [ 1, %for1.header ]
|
|
%j.next = add nuw nsw i64 %j, 1
|
|
%arrayidx5 = getelementptr inbounds [100 x [100 x i64]], [100 x [100 x i64]]* @A, i64 0, i64 %j, i64 %j23
|
|
store i64 %j, i64* %arrayidx5
|
|
%arrayidx10 = getelementptr inbounds [100 x [100 x i64]], [100 x [100 x i64]]* @A, i64 0, i64 %j, i64 %j.next24
|
|
store i64 %j23, i64* %arrayidx10
|
|
%exitcond = icmp eq i64 %j, 99
|
|
br i1 %exitcond, label %for1.inc10, label %for2
|
|
|
|
for1.inc10:
|
|
%exitcond26 = icmp eq i64 %j23, 98
|
|
br i1 %exitcond26, label %for.end12, label %for1.header
|
|
|
|
for.end12:
|
|
ret void
|
|
|
|
}
|