; RUN: opt < %s -passes='print<loopnest>' -disable-output 2>&1 | FileCheck %s
; Test a perfect 2-dim loop nest of the form:
; for(i=0; i<nx; ++i)
; for(j=0; j<nx; ++j)
; y[i][j] = x[i][j];
define void @perf_nest_2D_1(ptr %y, ptr %x, i64 signext %nx, i64 signext %ny) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_2D_1_loop_j, Loops: ( perf_nest_2D_1_loop_j )
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_2D_1_loop_i, Loops: ( perf_nest_2D_1_loop_i perf_nest_2D_1_loop_j )
entry:
br label %perf_nest_2D_1_loop_i
perf_nest_2D_1_loop_i:
%i = phi i64 [ 0, %entry ], [ %inc13, %inc_i ]
%cmp21 = icmp slt i64 0, %ny
br i1 %cmp21, label %perf_nest_2D_1_loop_j, label %inc_i
perf_nest_2D_1_loop_j:
%j = phi i64 [ 0, %perf_nest_2D_1_loop_i ], [ %inc, %inc_j ]
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %j
%0 = load ptr, ptr %arrayidx, align 8
%arrayidx6 = getelementptr inbounds i32, ptr %0, i64 %j
%1 = load i32, ptr %arrayidx6, align 4
%arrayidx8 = getelementptr inbounds ptr, ptr %y, i64 %j
%2 = load ptr, ptr %arrayidx8, align 8
%arrayidx11 = getelementptr inbounds i32, ptr %2, i64 %i
store i32 %1, ptr %arrayidx11, align 4
br label %inc_j
inc_j:
%inc = add nsw i64 %j, 1
%cmp2 = icmp slt i64 %inc, %ny
br i1 %cmp2, label %perf_nest_2D_1_loop_j, label %inc_i
inc_i:
%inc13 = add nsw i64 %i, 1
%cmp = icmp slt i64 %inc13, %nx
br i1 %cmp, label %perf_nest_2D_1_loop_i, label %perf_nest_2D_1_loop_i_end
perf_nest_2D_1_loop_i_end:
ret void
}
; Test a perfect 2-dim loop nest of the form:
; for (i=0; i<100; ++i)
; for (j=0; j<100; ++j)
; y[i][j] = x[i][j];
define void @perf_nest_2D_2(ptr %y, ptr %x) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_2D_2_loop_j, Loops: ( perf_nest_2D_2_loop_j )
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_2D_2_loop_i, Loops: ( perf_nest_2D_2_loop_i perf_nest_2D_2_loop_j )
entry:
br label %perf_nest_2D_2_loop_i
perf_nest_2D_2_loop_i:
%i = phi i64 [ 0, %entry ], [ %inc13, %inc_i ]
br label %perf_nest_2D_2_loop_j
perf_nest_2D_2_loop_j:
%j = phi i64 [ 0, %perf_nest_2D_2_loop_i ], [ %inc, %inc_j ]
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %j
%0 = load ptr, ptr %arrayidx, align 8
%arrayidx6 = getelementptr inbounds i32, ptr %0, i64 %j
%1 = load i32, ptr %arrayidx6, align 4
%arrayidx8 = getelementptr inbounds ptr, ptr %y, i64 %j
%2 = load ptr, ptr %arrayidx8, align 8
%arrayidx11 = getelementptr inbounds i32, ptr %2, i64 %i
store i32 %1, ptr %arrayidx11, align 4
br label %inc_j
inc_j:
%inc = add nsw i64 %j, 1
%cmp2 = icmp slt i64 %inc, 100
br i1 %cmp2, label %perf_nest_2D_2_loop_j, label %loop_j_end
loop_j_end:
br label %inc_i
inc_i:
%inc13 = add nsw i64 %i, 1
%cmp = icmp slt i64 %inc13, 100
br i1 %cmp, label %perf_nest_2D_2_loop_i, label %perf_nest_2D_2_loop_i_end
perf_nest_2D_2_loop_i_end:
ret void
}
define void @perf_nest_2D_3(ptr %y, ptr %x, i64 signext %nx, i64 signext %ny) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_2D_3_loop_j, Loops: ( perf_nest_2D_3_loop_j )
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_2D_3_loop_i, Loops: ( perf_nest_2D_3_loop_i perf_nest_2D_3_loop_j )
entry:
br label %perf_nest_2D_3_loop_i
perf_nest_2D_3_loop_i:
%i = phi i64 [ 0, %entry ], [ %inc13, %inc_i ]
%cmp21 = icmp slt i64 0, %ny
br label %singleSucc
singleSucc:
br i1 %cmp21, label %preheader.j, label %for.end
preheader.j:
br label %perf_nest_2D_3_loop_j
perf_nest_2D_3_loop_j:
%j = phi i64 [ 0, %preheader.j ], [ %inc, %inc_j ]
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %j
%0 = load ptr, ptr %arrayidx, align 8
%arrayidx6 = getelementptr inbounds i32, ptr %0, i64 %j
%1 = load i32, ptr %arrayidx6, align 4
%arrayidx8 = getelementptr inbounds ptr, ptr %y, i64 %j
%2 = load ptr, ptr %arrayidx8, align 8
%arrayidx11 = getelementptr inbounds i32, ptr %2, i64 %i
store i32 %1, ptr %arrayidx11, align 4
br label %inc_j
inc_j:
%inc = add nsw i64 %j, 1
%cmp2 = icmp slt i64 %inc, %ny
br i1 %cmp2, label %perf_nest_2D_3_loop_j, label %for.exit
for.exit:
br label %for.end
for.end:
br label %inc_i
inc_i:
%inc13 = add nsw i64 %i, 1
%cmp = icmp slt i64 %inc13, %nx
br i1 %cmp, label %perf_nest_2D_3_loop_i, label %perf_nest_2D_3_loop_i_end
perf_nest_2D_3_loop_i_end:
ret void
}
; Test a perfect 3-dim loop nest of the form:
; for (i=0; i<nx; ++i)
; for (j=0; j<ny; ++j)
; for (k=0; j<nk; ++k)
; y[j][j][k] = x[i][j][k];
;
define void @perf_nest_3D_1(ptr %y, ptr %x, i32 signext %nx, i32 signext %ny, i32 signext %nk) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_3D_1_loop_k, Loops: ( perf_nest_3D_1_loop_k )
; CHECK-NEXT: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_3D_1_loop_j, Loops: ( perf_nest_3D_1_loop_j perf_nest_3D_1_loop_k )
; CHECK-NEXT: IsPerfect=true, Depth=3, OutermostLoop: perf_nest_3D_1_loop_i, Loops: ( perf_nest_3D_1_loop_i perf_nest_3D_1_loop_j perf_nest_3D_1_loop_k )
entry:
br label %perf_nest_3D_1_loop_i
perf_nest_3D_1_loop_i:
%i = phi i32 [ 0, %entry ], [ %inci, %for.inci ]
%cmp21 = icmp slt i32 0, %ny
br i1 %cmp21, label %perf_nest_3D_1_loop_j, label %for.inci
perf_nest_3D_1_loop_j:
%j = phi i32 [ 0, %perf_nest_3D_1_loop_i ], [ %incj, %for.incj ]
%cmp22 = icmp slt i32 0, %nk
br i1 %cmp22, label %perf_nest_3D_1_loop_k, label %for.incj
perf_nest_3D_1_loop_k:
%k = phi i32 [ 0, %perf_nest_3D_1_loop_j ], [ %inck, %for.inck ]
%idxprom = sext i32 %i to i64
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %idxprom
%0 = load ptr, ptr %arrayidx, align 8
%idxprom7 = sext i32 %j to i64
%arrayidx8 = getelementptr inbounds ptr, ptr %0, i64 %idxprom7
%1 = load ptr, ptr %arrayidx8, align 8
%idxprom9 = sext i32 %k to i64
%arrayidx10 = getelementptr inbounds i32, ptr %1, i64 %idxprom9
%2 = load i32, ptr %arrayidx10, align 4
%idxprom11 = sext i32 %j to i64
%arrayidx12 = getelementptr inbounds ptr, ptr %y, i64 %idxprom11
%3 = load ptr, ptr %arrayidx12, align 8
%idxprom13 = sext i32 %j to i64
%arrayidx14 = getelementptr inbounds ptr, ptr %3, i64 %idxprom13
%4 = load ptr, ptr %arrayidx14, align 8
%idxprom15 = sext i32 %k to i64
%arrayidx16 = getelementptr inbounds i32, ptr %4, i64 %idxprom15
store i32 %2, ptr %arrayidx16, align 4
br label %for.inck
for.inck:
%inck = add nsw i32 %k, 1
%cmp5 = icmp slt i32 %inck, %nk
br i1 %cmp5, label %perf_nest_3D_1_loop_k, label %for.incj
for.incj:
%incj = add nsw i32 %j, 1
%cmp2 = icmp slt i32 %incj, %ny
br i1 %cmp2, label %perf_nest_3D_1_loop_j, label %for.inci
for.inci:
%inci = add nsw i32 %i, 1
%cmp = icmp slt i32 %inci, %nx
br i1 %cmp, label %perf_nest_3D_1_loop_i, label %perf_nest_3D_1_loop_i_end
perf_nest_3D_1_loop_i_end:
ret void
}
; Test a perfect 3-dim loop nest of the form:
; for (i=0; i<100; ++i)
; for (j=0; j<100; ++j)
; for (k=0; j<100; ++k)
; y[j][j][k] = x[i][j][k];
;
define void @perf_nest_3D_2(ptr %y, ptr %x) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_3D_2_loop_k, Loops: ( perf_nest_3D_2_loop_k )
; CHECK-NEXT: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_3D_2_loop_j, Loops: ( perf_nest_3D_2_loop_j perf_nest_3D_2_loop_k )
; CHECK-NEXT: IsPerfect=true, Depth=3, OutermostLoop: perf_nest_3D_2_loop_i, Loops: ( perf_nest_3D_2_loop_i perf_nest_3D_2_loop_j perf_nest_3D_2_loop_k )
entry:
br label %perf_nest_3D_2_loop_i
perf_nest_3D_2_loop_i:
%i = phi i32 [ 0, %entry ], [ %inci, %for.inci ]
br label %perf_nest_3D_2_loop_j
perf_nest_3D_2_loop_j:
%j = phi i32 [ 0, %perf_nest_3D_2_loop_i ], [ %incj, %for.incj ]
br label %perf_nest_3D_2_loop_k
perf_nest_3D_2_loop_k:
%k = phi i32 [ 0, %perf_nest_3D_2_loop_j ], [ %inck, %for.inck ]
%idxprom = sext i32 %i to i64
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %idxprom
%0 = load ptr, ptr %arrayidx, align 8
%idxprom7 = sext i32 %j to i64
%arrayidx8 = getelementptr inbounds ptr, ptr %0, i64 %idxprom7
%1 = load ptr, ptr %arrayidx8, align 8
%idxprom9 = sext i32 %k to i64
%arrayidx10 = getelementptr inbounds i32, ptr %1, i64 %idxprom9
%2 = load i32, ptr %arrayidx10, align 4
%idxprom11 = sext i32 %j to i64
%arrayidx12 = getelementptr inbounds ptr, ptr %y, i64 %idxprom11
%3 = load ptr, ptr %arrayidx12, align 8
%idxprom13 = sext i32 %j to i64
%arrayidx14 = getelementptr inbounds ptr, ptr %3, i64 %idxprom13
%4 = load ptr, ptr %arrayidx14, align 8
%idxprom15 = sext i32 %k to i64
%arrayidx16 = getelementptr inbounds i32, ptr %4, i64 %idxprom15
store i32 %2, ptr %arrayidx16, align 4
br label %for.inck
for.inck:
%inck = add nsw i32 %k, 1
%cmp5 = icmp slt i32 %inck, 100
br i1 %cmp5, label %perf_nest_3D_2_loop_k, label %loop_k_end
loop_k_end:
br label %for.incj
for.incj:
%incj = add nsw i32 %j, 1
%cmp2 = icmp slt i32 %incj, 100
br i1 %cmp2, label %perf_nest_3D_2_loop_j, label %loop_j_end
loop_j_end:
br label %for.inci
for.inci:
%inci = add nsw i32 %i, 1
%cmp = icmp slt i32 %inci, 100
br i1 %cmp, label %perf_nest_3D_2_loop_i, label %perf_nest_3D_2_loop_i_end
perf_nest_3D_2_loop_i_end:
ret void
}
; Test a perfect loop nest with a live out reduction:
; for (i = 0; i<ni; ++i)
; if (0<nj) { // guard branch for the j-loop
; for (j=0; j<nj; j+=1)
; x+=(i+j);
; }
; return x;
define signext i32 @perf_nest_live_out(i32 signext %x, i32 signext %ni, i32 signext %nj) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_live_out_loop_j, Loops: ( perf_nest_live_out_loop_j )
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_live_out_loop_i, Loops: ( perf_nest_live_out_loop_i perf_nest_live_out_loop_j )
entry:
%cmp4 = icmp slt i32 0, %ni
br i1 %cmp4, label %perf_nest_live_out_loop_i.lr.ph, label %for.end7
perf_nest_live_out_loop_i.lr.ph:
br label %perf_nest_live_out_loop_i
perf_nest_live_out_loop_i:
%x.addr.06 = phi i32 [ %x, %perf_nest_live_out_loop_i.lr.ph ], [ %x.addr.1.lcssa, %for.inc5 ]
%i.05 = phi i32 [ 0, %perf_nest_live_out_loop_i.lr.ph ], [ %inc6, %for.inc5 ]
%cmp21 = icmp slt i32 0, %nj
br i1 %cmp21, label %perf_nest_live_out_loop_j.lr.ph, label %for.inc5
perf_nest_live_out_loop_j.lr.ph:
br label %perf_nest_live_out_loop_j
perf_nest_live_out_loop_j:
%x.addr.13 = phi i32 [ %x.addr.06, %perf_nest_live_out_loop_j.lr.ph ], [ %add4, %perf_nest_live_out_loop_j ]
%j.02 = phi i32 [ 0, %perf_nest_live_out_loop_j.lr.ph ], [ %inc, %perf_nest_live_out_loop_j ]
%add = add nsw i32 %i.05, %j.02
%add4 = add nsw i32 %x.addr.13, %add
%inc = add nsw i32 %j.02, 1
%cmp2 = icmp slt i32 %inc, %nj
br i1 %cmp2, label %perf_nest_live_out_loop_j, label %for.cond1.for.inc5_crit_edge
for.cond1.for.inc5_crit_edge:
%split = phi i32 [ %add4, %perf_nest_live_out_loop_j ]
br label %for.inc5
for.inc5:
%x.addr.1.lcssa = phi i32 [ %split, %for.cond1.for.inc5_crit_edge ], [ %x.addr.06, %perf_nest_live_out_loop_i ]
%inc6 = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc6, %ni
br i1 %cmp, label %perf_nest_live_out_loop_i, label %for.cond.for.end7_crit_edge
for.cond.for.end7_crit_edge:
%split7 = phi i32 [ %x.addr.1.lcssa, %for.inc5 ]
br label %for.end7
for.end7:
%x.addr.0.lcssa = phi i32 [ %split7, %for.cond.for.end7_crit_edge ], [ %x, %entry ]
ret i32 %x.addr.0.lcssa
}
; Test a perfect loop nest of the form:
; for (int i = 0; i < nx; ++i)
; if (i < ny) { // guard branch for the j-loop
; for (int j=i; j < ny; j+=1)
; y[j][i] = x[i][j] + j;
; }
define double @perf_nest_guard_branch(ptr %y, ptr %x, i32 signext %nx, i32 signext %ny) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: test6Loop2, Loops: ( test6Loop2 )
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: test6Loop1, Loops: ( test6Loop1 test6Loop2 )
entry:
%cmp2 = icmp slt i32 0, %nx
br i1 %cmp2, label %test6Loop1.lr.ph, label %for.end13
test6Loop1.lr.ph: ; preds = %entry
br label %test6Loop1
test6Loop1: ; preds = %test6Loop1.lr.ph, %for.inc11
%i.0 = phi i32 [ 0, %test6Loop1.lr.ph ], [ %inc12, %for.inc11 ]
%cmp1 = icmp slt i32 %i.0, %ny
br i1 %cmp1, label %test6Loop2.lr.ph, label %if.end
test6Loop2.lr.ph: ; preds = %if.then
br label %test6Loop2
test6Loop2: ; preds = %test6Loop2.lr.ph, %for.inc
%j.0 = phi i32 [ %i.0, %test6Loop2.lr.ph ], [ %inc, %for.inc ]
%idxprom = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %idxprom
%0 = load ptr, ptr %arrayidx, align 8
%idxprom5 = sext i32 %j.0 to i64
%arrayidx6 = getelementptr inbounds i32, ptr %0, i64 %idxprom5
%1 = load i32, ptr %arrayidx6, align 4
%add = add nsw i32 %1, %j.0
%idxprom7 = sext i32 %j.0 to i64
%arrayidx8 = getelementptr inbounds ptr, ptr %y, i64 %idxprom7
%2 = load ptr, ptr %arrayidx8, align 8
%idxprom9 = sext i32 %i.0 to i64
%arrayidx10 = getelementptr inbounds i32, ptr %2, i64 %idxprom9
store i32 %add, ptr %arrayidx10, align 4
br label %for.inc
for.inc: ; preds = %test6Loop2
%inc = add nsw i32 %j.0, 1
%cmp3 = icmp slt i32 %inc, %ny
br i1 %cmp3, label %test6Loop2, label %for.cond2.for.end_crit_edge
for.cond2.for.end_crit_edge: ; preds = %for.inc
br label %for.end
for.end: ; preds = %for.cond2.for.end_crit_edge, %if.then
br label %if.end
if.end: ; preds = %for.end, %test6Loop1
br label %for.inc11
for.inc11: ; preds = %if.end
%inc12 = add nsw i32 %i.0, 1
%cmp = icmp slt i32 %inc12, %nx
br i1 %cmp, label %test6Loop1, label %for.cond.for.end13_crit_edge
for.cond.for.end13_crit_edge: ; preds = %for.inc11
br label %for.end13
for.end13: ; preds = %for.cond.for.end13_crit_edge, %entry
%arrayidx14 = getelementptr inbounds ptr, ptr %y, i64 0
%3 = load ptr, ptr %arrayidx14, align 8
%arrayidx15 = getelementptr inbounds i32, ptr %3, i64 0
%4 = load i32, ptr %arrayidx15, align 4
%conv = sitofp i32 %4 to double
ret double %conv
}
; Test a perfect loop nest of the form:
; for (int i = 0; i < nx; ++i)
; if (i < ny) { // guard branch for the j-loop
; for (int j=i; j < ny; j+=1)
; y[j][i] = x[i][j] + j;
; }
define double @test6(ptr %y, ptr %x, i32 signext %nx, i32 signext %ny) {
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: test6Loop2, Loops: ( test6Loop2 )
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: test6Loop1, Loops: ( test6Loop1 test6Loop2 )
entry:
%cmp2 = icmp slt i32 0, %nx
br i1 %cmp2, label %test6Loop1.lr.ph, label %for.end13
test6Loop1.lr.ph: ; preds = %entry
br label %test6Loop1
test6Loop1: ; preds = %test6Loop1.lr.ph, %for.inc11
%i.0 = phi i32 [ 0, %test6Loop1.lr.ph ], [ %inc12, %for.inc11 ]
%cmp1 = icmp slt i32 %i.0, %ny
br i1 %cmp1, label %test6Loop2.lr.ph, label %if.end
test6Loop2.lr.ph: ; preds = %if.then
br label %test6Loop2
test6Loop2: ; preds = %test6Loop2.lr.ph, %for.inc
%j.0 = phi i32 [ %i.0, %test6Loop2.lr.ph ], [ %inc, %for.inc ]
%idxprom = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds ptr, ptr %x, i64 %idxprom
%0 = load ptr, ptr %arrayidx, align 8
%idxprom5 = sext i32 %j.0 to i64
%arrayidx6 = getelementptr inbounds i32, ptr %0, i64 %idxprom5
%1 = load i32, ptr %arrayidx6, align 4
%add = add nsw i32 %1, %j.0
%idxprom7 = sext i32 %j.0 to i64
%arrayidx8 = getelementptr inbounds ptr, ptr %y, i64 %idxprom7
%2 = load ptr, ptr %arrayidx8, align 8
%idxprom9 = sext i32 %i.0 to i64
%arrayidx10 = getelementptr inbounds i32, ptr %2, i64 %idxprom9
store i32 %add, ptr %arrayidx10, align 4
br label %for.inc
for.inc: ; preds = %test6Loop2
%inc = add nsw i32 %j.0, 1
%cmp3 = icmp slt i32 %inc, %ny
br i1 %cmp3, label %test6Loop2, label %for.cond2.for.end_crit_edge
for.cond2.for.end_crit_edge: ; preds = %for.inc
br label %for.end
for.end: ; preds = %for.cond2.for.end_crit_edge, %if.then
br label %if.end
if.end: ; preds = %for.end, %test6Loop1
br label %for.inc11
for.inc11: ; preds = %if.end
%inc12 = add nsw i32 %i.0, 1
%cmp = icmp slt i32 %inc12, %nx
br i1 %cmp, label %test6Loop1, label %for.cond.for.end13_crit_edge
for.cond.for.end13_crit_edge: ; preds = %for.inc11
br label %for.end13
for.end13: ; preds = %for.cond.for.end13_crit_edge, %entry
%arrayidx14 = getelementptr inbounds ptr, ptr %y, i64 0
%3 = load ptr, ptr %arrayidx14, align 8
%arrayidx15 = getelementptr inbounds i32, ptr %3, i64 0
%4 = load i32, ptr %arrayidx15, align 4
%conv = sitofp i32 %4 to double
ret double %conv
}