+++ /dev/null
-; REQUIRES: asserts
-; RUN: opt < %s -basicaa -loop-interchange -S -debug 2>&1 | 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 i32]] zeroinitializer
-@B = common global [100 x i32] zeroinitializer
-
-;; Loops should not be interchanged in this case as it is not profitable.
-;; for(int i=0;i<100;i++)
-;; for(int j=0;j<100;j++)
-;; A[i][j] = A[i][j]+k;
-
-; CHECK: Interchanging loops not profitable.
-
-define void @interchange_03(i32 %k) {
-entry:
- br label %for.cond1.preheader
-
-for.cond1.preheader:
- %indvars.iv21 = phi i64 [ 0, %entry ], [ %indvars.iv.next22, %for.inc10 ]
- br label %for.body3
-
-for.body3:
- %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body3 ]
- %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv21, i64 %indvars.iv
- %0 = load i32, i32* %arrayidx5
- %add = add nsw i32 %0, %k
- store i32 %add, i32* %arrayidx5
- %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %exitcond = icmp eq i64 %indvars.iv.next, 100
- br i1 %exitcond, label %for.inc10, label %for.body3
-
-for.inc10:
- %indvars.iv.next22 = add nuw nsw i64 %indvars.iv21, 1
- %exitcond23 = icmp eq i64 %indvars.iv.next22, 100
- br i1 %exitcond23, label %for.end12, label %for.cond1.preheader
-
-for.end12:
- ret void
-}
+++ /dev/null
-; REQUIRES: asserts
-; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -S -debug 2>&1 | 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 i32]] zeroinitializer
-
-;; Test to make sure we can handle output dependencies.
-;;
-;; for (int i = 0; i < 2; ++i)
-;; for(int j = 0; j < 3; ++j) {
-;; A[j][i] = i;
-;; A[j][i+1] = j;
-;; }
-
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-@A10 = local_unnamed_addr global [3 x [3 x i32]] zeroinitializer, align 16
-
-define void @interchange_10() {
-entry:
- br label %for.cond1.preheader
-
-for.cond.loopexit: ; preds = %for.body4
- %exitcond28 = icmp ne i64 %indvars.iv.next27, 2
- br i1 %exitcond28, label %for.cond1.preheader, label %for.cond.cleanup
-
-for.cond1.preheader: ; preds = %for.cond.loopexit, %entry
- %indvars.iv26 = phi i64 [ 0, %entry ], [ %indvars.iv.next27, %for.cond.loopexit ]
- %indvars.iv.next27 = add nuw nsw i64 %indvars.iv26, 1
- br label %for.body4
-
-for.cond.cleanup: ; preds = %for.cond.loopexit
- ret void
-
-for.body4: ; preds = %for.body4, %for.cond1.preheader
- %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body4 ]
- %arrayidx6 = getelementptr inbounds [3 x [3 x i32]], [3 x [3 x i32]]* @A10, i64 0, i64 %indvars.iv, i64 %indvars.iv26
- %tmp = trunc i64 %indvars.iv26 to i32
- store i32 %tmp, i32* %arrayidx6, align 4
- %arrayidx10 = getelementptr inbounds [3 x [3 x i32]], [3 x [3 x i32]]* @A10, i64 0, i64 %indvars.iv, i64 %indvars.iv.next27
- %tmp1 = trunc i64 %indvars.iv to i32
- store i32 %tmp1, i32* %arrayidx10, align 4
- %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %exitcond = icmp ne i64 %indvars.iv.next, 3
- br i1 %exitcond, label %for.body4, label %for.cond.loopexit
-}
+++ /dev/null
-; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -S -pass-remarks=loop-interchange 2>&1 | 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 i32]] zeroinitializer
-@B = common global [100 x i32] zeroinitializer
-
-;; for(int i=0;i<100;i++)
-;; for(int j=100;j>=0;j--)
-;; A[j][i] = A[j][i]+k;
-
-; CHECK: Loop interchanged with enclosing loop.
-
-define void @interchange_02(i32 %k) {
-entry:
- br label %for.cond1.preheader
-
-for.cond1.preheader:
- %indvars.iv19 = phi i64 [ 0, %entry ], [ %indvars.iv.next20, %for.inc10 ]
- br label %for.body3
-
-for.body3:
- %indvars.iv = phi i64 [ 100, %for.cond1.preheader ], [ %indvars.iv.next, %for.body3 ]
- %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv, i64 %indvars.iv19
- %0 = load i32, i32* %arrayidx5
- %add = add nsw i32 %0, %k
- store i32 %add, i32* %arrayidx5
- %indvars.iv.next = add nsw i64 %indvars.iv, -1
- %cmp2 = icmp sgt i64 %indvars.iv, 0
- br i1 %cmp2, label %for.body3, label %for.inc10
-
-for.inc10:
- %indvars.iv.next20 = add nuw nsw i64 %indvars.iv19, 1
- %exitcond = icmp eq i64 %indvars.iv.next20, 100
- br i1 %exitcond, label %for.end11, label %for.cond1.preheader
-
-for.end11:
- ret void
-}
+++ /dev/null
-; REQUIRES: asserts
-; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -S -debug 2>&1 | 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 i32]] zeroinitializer
-@B = common global [100 x i32] zeroinitializer
-
-;; for(int i=0;i<N;i++)
-;; for(int j=1;j<N;j++)
-;; A[j][i] = A[j][i]+k;
-
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_01(i32 %k, i32 %N) {
-entry:
- %cmp21 = icmp sgt i32 %N, 0
- br i1 %cmp21, label %for.cond1.preheader.lr.ph, label %for.end12
-
-for.cond1.preheader.lr.ph:
- %cmp219 = icmp sgt i32 %N, 1
- %0 = add i32 %N, -1
- br label %for.cond1.preheader
-
-for.cond1.preheader:
- %indvars.iv23 = phi i64 [ 0, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next24, %for.inc10 ]
- br i1 %cmp219, label %for.body3, label %for.inc10
-
-for.body3:
- %indvars.iv = phi i64 [ %indvars.iv.next, %for.body3 ], [ 1, %for.cond1.preheader ]
- %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv, i64 %indvars.iv23
- %1 = load i32, i32* %arrayidx5
- %add = add nsw i32 %1, %k
- store i32 %add, i32* %arrayidx5
- %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %lftr.wideiv = trunc i64 %indvars.iv to i32
- %exitcond = icmp eq i32 %lftr.wideiv, %0
- br i1 %exitcond, label %for.inc10, label %for.body3
-
-for.inc10:
- %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
- %lftr.wideiv25 = trunc i64 %indvars.iv23 to i32
- %exitcond26 = icmp eq i32 %lftr.wideiv25, %0
- br i1 %exitcond26, label %for.end12, label %for.cond1.preheader
-
-for.end12:
- ret void
-}
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -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
+
+}
-; REQUIRES: asserts
-; RUN: opt < %s -loop-interchange -verify-dom-info -S -debug 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -loop-interchange -verify-dom-info -S 2>&1 | FileCheck %s
;; Checks the order of the inner phi nodes does not cause havoc.
;; The inner loop has a reduction into c. The IV is not the first phi.
-; CHECK: Not interchanging loops. Cannot prove legality.
-
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv8--linux-gnueabihf"
+
+
; Function Attrs: norecurse nounwind
define void @test(i32 %T, [90 x i32]* noalias nocapture %C, i16* noalias nocapture readonly %A, i16* noalias nocapture readonly %B) local_unnamed_addr #0 {
+; CHECK-LABEL: @test(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR3_PREHEADER:%.*]]
+; CHECK: for1.header.preheader:
+; CHECK-NEXT: br label [[FOR1_HEADER:%.*]]
+; CHECK: for1.header:
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC20:%.*]], [[FOR1_INC19:%.*]] ], [ 0, [[FOR1_HEADER_PREHEADER:%.*]] ]
+; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I]], 90
+; CHECK-NEXT: br label [[FOR2_HEADER_PREHEADER:%.*]]
+; CHECK: for2.header.preheader:
+; CHECK-NEXT: br label [[FOR2_HEADER:%.*]]
+; CHECK: for2.header:
+; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[INC17:%.*]], [[FOR2_INC16:%.*]] ], [ 0, [[FOR2_HEADER_PREHEADER]] ]
+; CHECK-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds [90 x i32], [90 x i32]* [[C:%.*]], i32 [[I]], i32 [[J]]
+; CHECK-NEXT: [[ARRAYIDX14_PROMOTED:%.*]] = load i32, i32* [[ARRAYIDX14]], align 4
+; CHECK-NEXT: br label [[FOR3_SPLIT1:%.*]]
+; CHECK: for3.preheader:
+; CHECK-NEXT: br label [[FOR3:%.*]]
+; CHECK: for3:
+; CHECK-NEXT: [[K:%.*]] = phi i32 [ [[INC:%.*]], [[FOR3_SPLIT:%.*]] ], [ 1, [[FOR3_PREHEADER]] ]
+; CHECK-NEXT: br label [[FOR1_HEADER_PREHEADER]]
+; CHECK: for3.split1:
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[K]], [[MUL]]
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i32 [[ADD]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[ARRAYIDX]], align 2
+; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32
+; CHECK-NEXT: [[ADD15:%.*]] = add nsw i32 [[CONV]], [[ARRAYIDX14_PROMOTED]]
+; CHECK-NEXT: br label [[FOR2_INC16]]
+; CHECK: for3.split:
+; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[K]], 1
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 90
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR1_LOOPEXIT:%.*]], label [[FOR3]]
+; CHECK: for2.inc16:
+; CHECK-NEXT: store i32 [[ADD15]], i32* [[ARRAYIDX14]], align 4
+; CHECK-NEXT: [[INC17]] = add nuw nsw i32 [[J]], 1
+; CHECK-NEXT: [[EXITCOND47:%.*]] = icmp eq i32 [[INC17]], 90
+; CHECK-NEXT: br i1 [[EXITCOND47]], label [[FOR1_INC19]], label [[FOR2_HEADER]]
+; CHECK: for1.inc19:
+; CHECK-NEXT: [[INC20]] = add nuw nsw i32 [[I]], 1
+; CHECK-NEXT: [[EXITCOND48:%.*]] = icmp eq i32 [[INC20]], 90
+; CHECK-NEXT: br i1 [[EXITCOND48]], label [[FOR3_SPLIT]], label [[FOR1_HEADER]]
+; CHECK: for1.loopexit:
+; CHECK-NEXT: br label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
entry:
- %cmp45 = icmp sgt i32 %T, 0
- br i1 %cmp45, label %for.body3.lr.ph.preheader, label %for.end21
-
-for.body3.lr.ph.preheader: ; preds = %entry
- br label %for.body3.lr.ph
+ br label %for1.header
-for.body3.lr.ph: ; preds = %for.body3.lr.ph.preheader, %for.inc19
- %i.046 = phi i32 [ %inc20, %for.inc19 ], [ 0, %for.body3.lr.ph.preheader ]
- %mul = mul nsw i32 %i.046, %T
- br label %for.body6.lr.ph
+for1.header: ; preds = %entry
+ %i = phi i32 [ %inc20, %for1.inc19 ], [ 0, %entry ]
+ %mul = mul nsw i32 %i, 90
+ br label %for2.header
-for.body6.lr.ph: ; preds = %for.inc16, %for.body3.lr.ph
- %j.043 = phi i32 [ 0, %for.body3.lr.ph ], [ %inc17, %for.inc16 ]
- %arrayidx14 = getelementptr inbounds [90 x i32], [90 x i32]* %C, i32 %i.046, i32 %j.043
+for2.header: ; preds = %for2.inc16, %for1.header
+ %j = phi i32 [ 0, %for1.header ], [ %inc17, %for2.inc16 ]
+ %arrayidx14 = getelementptr inbounds [90 x i32], [90 x i32]* %C, i32 %i, i32 %j
%arrayidx14.promoted = load i32, i32* %arrayidx14, align 4
- br label %for.body6
+ br label %for3
-for.body6: ; preds = %for.body6, %for.body6.lr.ph
- %add1541 = phi i32 [ %arrayidx14.promoted, %for.body6.lr.ph ], [ %add15, %for.body6 ]
- %k.040 = phi i32 [ 0, %for.body6.lr.ph ], [ %inc, %for.body6 ]
- %add = add nsw i32 %k.040, %mul
+for3: ; preds = %for3, %for2.header
+ %add1541 = phi i32 [ %arrayidx14.promoted, %for2.header ], [ %add15, %for3 ]
+ %k = phi i32 [ 1, %for2.header ], [ %inc, %for3 ]
+ %add = add nsw i32 %k, %mul
%arrayidx = getelementptr inbounds i16, i16* %A, i32 %add
%0 = load i16, i16* %arrayidx, align 2
%conv = sext i16 %0 to i32
- %mul7 = mul nsw i32 %k.040, %T
- %add8 = add nsw i32 %mul7, %j.043
- %arrayidx9 = getelementptr inbounds i16, i16* %B, i32 %add8
- %1 = load i16, i16* %arrayidx9, align 2
- %conv10 = sext i16 %1 to i32
- %mul11 = mul nsw i32 %conv10, %conv
- %add15 = add nsw i32 %mul11, %add1541
- %inc = add nuw nsw i32 %k.040, 1
- %exitcond = icmp eq i32 %inc, %T
- br i1 %exitcond, label %for.inc16, label %for.body6
+ %add15 = add nsw i32 %conv, %add1541
+ %inc = add nuw nsw i32 %k, 1
+ %exitcond = icmp eq i32 %inc, 90
+ br i1 %exitcond, label %for2.inc16, label %for3
-for.inc16: ; preds = %for.body6
- %add15.lcssa = phi i32 [ %add15, %for.body6 ]
+for2.inc16: ; preds = %for.body6
+ %add15.lcssa = phi i32 [ %add15, %for3 ]
store i32 %add15.lcssa, i32* %arrayidx14, align 4
- %inc17 = add nuw nsw i32 %j.043, 1
- %exitcond47 = icmp eq i32 %inc17, %T
- br i1 %exitcond47, label %for.inc19, label %for.body6.lr.ph
+ %inc17 = add nuw nsw i32 %j, 1
+ %exitcond47 = icmp eq i32 %inc17, 90
+ br i1 %exitcond47, label %for1.inc19, label %for2.header
-for.inc19: ; preds = %for.inc16
- %inc20 = add nuw nsw i32 %i.046, 1
- %exitcond48 = icmp eq i32 %inc20, %T
- br i1 %exitcond48, label %for.end21.loopexit, label %for.body3.lr.ph
+for1.inc19: ; preds = %for2.inc16
+ %inc20 = add nuw nsw i32 %i, 1
+ %exitcond48 = icmp eq i32 %inc20, 90
+ br i1 %exitcond48, label %for1.loopexit, label %for1.header
-for.end21.loopexit: ; preds = %for.inc19
- br label %for.end21
+for1.loopexit: ; preds = %for1.inc19
+ br label %exit
-for.end21: ; preds = %for.end21.loopexit, %entry
+exit: ; preds = %for1.loopexit
ret void
}
-; REQUIRES: asserts
-; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -S -debug 2>&1 | FileCheck %s
+; RUN: opt < %s -loop-interchange -pass-remarks-output=%t \
+; RUN: -pass-remarks=loop-interchange -pass-remarks-missed=loop-interchange
+; RUN: FileCheck -input-file %t %s
+
;; We test profitability model in these test cases.
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
;;---------------------------------------Test case 01---------------------------------
;; Loops interchange will result in code vectorization and hence profitable. Check for interchange.
-;; for(int i=1;i<N;i++)
-;; for(int j=1;j<N;j++)
+;; for(int i=1;i<100;i++)
+;; for(int j=1;j<100;j++)
;; A[j][i] = A[j - 1][i] + B[j][i];
+;; FIXME: DA misses this case after D35430
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_01(i32 %N) {
+; CHECK: Name: Dependence
+; CHECK-NEXT: Function: interchange_01
+define void @interchange_01() {
entry:
- %cmp27 = icmp sgt i32 %N, 1
- br i1 %cmp27, label %for.cond1.preheader.lr.ph, label %for.end16
-
-for.cond1.preheader.lr.ph:
- %0 = add i32 %N, -1
- br label %for.body3.preheader
-
-for.body3.preheader:
- %indvars.iv30 = phi i64 [ 1, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next31, %for.inc14 ]
- br label %for.body3
-
-for.body3:
- %indvars.iv = phi i64 [ %indvars.iv.next, %for.body3 ], [ 1, %for.body3.preheader ]
- %1 = add nsw i64 %indvars.iv, -1
- %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %1, i64 %indvars.iv30
- %2 = load i32, i32* %arrayidx5
- %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @B, i64 0, i64 %indvars.iv, i64 %indvars.iv30
- %3 = load i32, i32* %arrayidx9
- %add = add nsw i32 %3, %2
- %arrayidx13 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv, i64 %indvars.iv30
+ br label %for2.preheader
+
+for2.preheader:
+ %i30 = phi i64 [ 1, %entry ], [ %i.next31, %for1.inc14 ]
+ br label %for2
+
+for2:
+ %j = phi i64 [ %i.next, %for2 ], [ 1, %for2.preheader ]
+ %j.prev = add nsw i64 %j, -1
+ %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %j.prev, i64 %i30
+ %lv1 = load i32, i32* %arrayidx5
+ %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @B, i64 0, i64 %j, i64 %i30
+ %lv2 = load i32, i32* %arrayidx9
+ %add = add nsw i32 %lv1, %lv2
+ %arrayidx13 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %j, i64 %i30
store i32 %add, i32* %arrayidx13
- %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %lftr.wideiv = trunc i64 %indvars.iv to i32
- %exitcond = icmp eq i32 %lftr.wideiv, %0
- br i1 %exitcond, label %for.inc14, label %for.body3
+ %i.next = add nuw nsw i64 %j, 1
+ %exitcond = icmp eq i64 %j, 99
+ br i1 %exitcond, label %for1.inc14, label %for2
-for.inc14:
- %indvars.iv.next31 = add nuw nsw i64 %indvars.iv30, 1
- %lftr.wideiv32 = trunc i64 %indvars.iv30 to i32
- %exitcond33 = icmp eq i32 %lftr.wideiv32, %0
- br i1 %exitcond33, label %for.end16, label %for.body3.preheader
+for1.inc14:
+ %i.next31 = add nuw nsw i64 %i30, 1
+ %exitcond33 = icmp eq i64 %i30, 99
+ br i1 %exitcond33, label %for.end16, label %for2.preheader
for.end16:
ret void
}
;; ---------------------------------------Test case 02---------------------------------
-;; Check loop interchange profitability model.
+;; Check loop interchange profitability model.
;; This tests profitability model when operands of getelementpointer and not exactly the induction variable but some
;; arithmetic operation on them.
;; for(int i=1;i<N;i++)
;; for(int j=1;j<N;j++)
;; A[j-1][i-1] = A[j - 1][i-1] + B[j-1][i-1];
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_02(i32 %N) {
+; CHECK: Name: Interchanged
+; CHECK-NEXT: Function: interchange_02
+define void @interchange_02() {
entry:
- %cmp32 = icmp sgt i32 %N, 1
- br i1 %cmp32, label %for.cond1.preheader.lr.ph, label %for.end21
-
-for.cond1.preheader.lr.ph:
- %0 = add i32 %N, -1
- br label %for.body3.lr.ph
-
-for.body3.lr.ph:
- %indvars.iv35 = phi i64 [ 1, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next36, %for.inc19 ]
- %1 = add nsw i64 %indvars.iv35, -1
- br label %for.body3
-
-for.body3:
- %indvars.iv = phi i64 [ 1, %for.body3.lr.ph ], [ %indvars.iv.next, %for.body3 ]
- %2 = add nsw i64 %indvars.iv, -1
- %arrayidx6 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %2, i64 %1
- %3 = load i32, i32* %arrayidx6
- %arrayidx12 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @B, i64 0, i64 %2, i64 %1
- %4 = load i32, i32* %arrayidx12
- %add = add nsw i32 %4, %3
+ br label %for1.header
+
+for1.header:
+ %i35 = phi i64 [ 1, %entry ], [ %i.next36, %for1.inc19 ]
+ %i.prev = add nsw i64 %i35, -1
+ br label %for2
+
+for2:
+ %j = phi i64 [ 1, %for1.header ], [ %i.next, %for2 ]
+ %j.prev = add nsw i64 %j, -1
+ %arrayidx6 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %j.prev, i64 %i.prev
+ %lv1 = load i32, i32* %arrayidx6
+ %arrayidx12 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @B, i64 0, i64 %j.prev, i64 %i.prev
+ %lv2 = load i32, i32* %arrayidx12
+ %add = add nsw i32 %lv1, %lv2
store i32 %add, i32* %arrayidx6
- %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %lftr.wideiv = trunc i64 %indvars.iv to i32
- %exitcond = icmp eq i32 %lftr.wideiv, %0
- br i1 %exitcond, label %for.inc19, label %for.body3
+ %i.next = add nuw nsw i64 %j, 1
+ %exitcond = icmp eq i64 %j, 99
+ br i1 %exitcond, label %for1.inc19, label %for2
-for.inc19:
- %indvars.iv.next36 = add nuw nsw i64 %indvars.iv35, 1
- %lftr.wideiv38 = trunc i64 %indvars.iv35 to i32
- %exitcond39 = icmp eq i32 %lftr.wideiv38, %0
- br i1 %exitcond39, label %for.end21, label %for.body3.lr.ph
+for1.inc19:
+ %i.next36 = add nuw nsw i64 %i35, 1
+ %exitcond39 = icmp eq i64 %i35, 99
+ br i1 %exitcond39, label %for.end21, label %for1.header
for.end21:
ret void
;;---------------------------------------Test case 03---------------------------------
;; Loops interchange is not profitable.
-;; for(int i=1;i<N;i++)
-;; for(int j=1;j<N;j++)
+;; for(int i=1;i<100;i++)
+;; for(int j=1;j<100;j++)
;; A[i-1][j-1] = A[i - 1][j-1] + B[i][j];
-; CHECK: Not interchanging loops. Cannot prove legality.
-
-define void @interchange_03(i32 %N){
+; CHECK: Name: InterchangeNotProfitable
+; CHECK-ENXT: Function: interchange_03
+define void @interchange_03(){
entry:
- %cmp31 = icmp sgt i32 %N, 1
- br i1 %cmp31, label %for.cond1.preheader.lr.ph, label %for.end19
+ br label %for1.header
+
+for1.header:
+ %i34 = phi i64 [ 1, %entry ], [ %i.next35, %for1.inc17 ]
+ %i.prev = add nsw i64 %i34, -1
+ br label %for2
+
+for2:
+ %j = phi i64 [ 1, %for1.header ], [ %i.next, %for2 ]
+ %j.prev = add nsw i64 %j, -1
+ %arrayidx6 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %i.prev, i64 %j.prev
+ %lv1 = load i32, i32* %arrayidx6
+ %arrayidx10 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @B, i64 0, i64 %i34, i64 %j
+ %lv2 = load i32, i32* %arrayidx10
+ %add = add nsw i32 %lv1, %lv2
+ store i32 %add, i32* %arrayidx6
+ %i.next = add nuw nsw i64 %j, 1
+ %exitcond = icmp eq i64 %j, 99
+ br i1 %exitcond, label %for1.inc17, label %for2
-for.cond1.preheader.lr.ph:
- %0 = add i32 %N, -1
- br label %for.body3.lr.ph
+for1.inc17:
+ %i.next35 = add nuw nsw i64 %i34, 1
+ %exitcond38 = icmp eq i64 %i34, 99
+ br i1 %exitcond38, label %for.end19, label %for1.header
-for.body3.lr.ph:
- %indvars.iv34 = phi i64 [ 1, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next35, %for.inc17 ]
- %1 = add nsw i64 %indvars.iv34, -1
+for.end19:
+ ret void
+}
+
+;; Loops should not be interchanged in this case as it is not profitable.
+;; for(int i=0;i<100;i++)
+;; for(int j=0;j<100;j++)
+;; A[i][j] = A[i][j]+k;
+
+; CHECK: Name: InterchangeNotProfitable
+; CHECK-ENXT: Function: interchange_04
+define void @interchange_04(i32 %k) {
+entry:
+ br label %for.cond1.preheader
+
+for.cond1.preheader:
+ %indvars.iv21 = phi i64 [ 0, %entry ], [ %indvars.iv.next22, %for.inc10 ]
br label %for.body3
for.body3:
- %indvars.iv = phi i64 [ 1, %for.body3.lr.ph ], [ %indvars.iv.next, %for.body3 ]
- %2 = add nsw i64 %indvars.iv, -1
- %arrayidx6 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %1, i64 %2
- %3 = load i32, i32* %arrayidx6
- %arrayidx10 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @B, i64 0, i64 %indvars.iv34, i64 %indvars.iv
- %4 = load i32, i32* %arrayidx10
- %add = add nsw i32 %4, %3
- store i32 %add, i32* %arrayidx6
+ %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body3 ]
+ %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv21, i64 %indvars.iv
+ %0 = load i32, i32* %arrayidx5
+ %add = add nsw i32 %0, %k
+ store i32 %add, i32* %arrayidx5
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
- %lftr.wideiv = trunc i64 %indvars.iv to i32
- %exitcond = icmp eq i32 %lftr.wideiv, %0
- br i1 %exitcond, label %for.inc17, label %for.body3
+ %exitcond = icmp eq i64 %indvars.iv.next, 100
+ br i1 %exitcond, label %for.inc10, label %for.body3
-for.inc17:
- %indvars.iv.next35 = add nuw nsw i64 %indvars.iv34, 1
- %lftr.wideiv37 = trunc i64 %indvars.iv34 to i32
- %exitcond38 = icmp eq i32 %lftr.wideiv37, %0
- br i1 %exitcond38, label %for.end19, label %for.body3.lr.ph
+for.inc10:
+ %indvars.iv.next22 = add nuw nsw i64 %indvars.iv21, 1
+ %exitcond23 = icmp eq i64 %indvars.iv.next22, 100
+ br i1 %exitcond23, label %for.end12, label %for.cond1.preheader
-for.end19:
+for.end12:
ret void
}
;; }
;; Not tightly nested. Do not interchange.
-;; Not interchanged hence the phi's in the inner loop will not be split. Check for the same.
-; CHECK: Not interchanging loops. Cannot prove legality.
+;; Not interchanged hence the phi's in the inner loop will not be split.
+; CHECK: Outer loops with reductions are not supported currently.
define void @reduction_03(i32 %N) {
entry:
;; Y+=X;
;; }
-;; Not interchanged hence the phi's in the inner loop will not be split. Check for the same.
-; CHECK: Not interchanging loops. Cannot prove legality.
+;; Not interchanged hence the phi's in the inner loop will not be split.
+; CHECK: Only inner loops with induction or reduction PHI nodes are supported currently.
define void @reduction_04(i32 %N) {
entry: