1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -loop-unroll -S < %s | FileCheck %s
3
4declare void @bar()
5
6define void @test1() {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[LOOP:%.*]]
10; CHECK:       loop:
11; CHECK-NEXT:    call void @bar()
12; CHECK-NEXT:    br i1 true, label [[LATCH:%.*]], label [[EXIT:%.*]]
13; CHECK:       latch:
14; CHECK-NEXT:    call void @bar()
15; CHECK-NEXT:    call void @bar()
16; CHECK-NEXT:    br i1 true, label [[LATCH_1:%.*]], label [[EXIT]]
17; CHECK:       exit:
18; CHECK-NEXT:    ret void
19; CHECK:       latch.1:
20; CHECK-NEXT:    call void @bar()
21; CHECK-NEXT:    call void @bar()
22; CHECK-NEXT:    br i1 true, label [[LATCH_2:%.*]], label [[EXIT]]
23; CHECK:       latch.2:
24; CHECK-NEXT:    call void @bar()
25; CHECK-NEXT:    call void @bar()
26; CHECK-NEXT:    br i1 true, label [[LATCH_3:%.*]], label [[EXIT]]
27; CHECK:       latch.3:
28; CHECK-NEXT:    call void @bar()
29; CHECK-NEXT:    call void @bar()
30; CHECK-NEXT:    br i1 true, label [[LATCH_4:%.*]], label [[EXIT]]
31; CHECK:       latch.4:
32; CHECK-NEXT:    call void @bar()
33; CHECK-NEXT:    call void @bar()
34; CHECK-NEXT:    br i1 true, label [[LATCH_5:%.*]], label [[EXIT]]
35; CHECK:       latch.5:
36; CHECK-NEXT:    call void @bar()
37; CHECK-NEXT:    call void @bar()
38; CHECK-NEXT:    br i1 true, label [[LATCH_6:%.*]], label [[EXIT]]
39; CHECK:       latch.6:
40; CHECK-NEXT:    call void @bar()
41; CHECK-NEXT:    call void @bar()
42; CHECK-NEXT:    br i1 true, label [[LATCH_7:%.*]], label [[EXIT]]
43; CHECK:       latch.7:
44; CHECK-NEXT:    call void @bar()
45; CHECK-NEXT:    call void @bar()
46; CHECK-NEXT:    br i1 true, label [[LATCH_8:%.*]], label [[EXIT]]
47; CHECK:       latch.8:
48; CHECK-NEXT:    call void @bar()
49; CHECK-NEXT:    call void @bar()
50; CHECK-NEXT:    br i1 true, label [[LATCH_9:%.*]], label [[EXIT]]
51; CHECK:       latch.9:
52; CHECK-NEXT:    call void @bar()
53; CHECK-NEXT:    call void @bar()
54; CHECK-NEXT:    br i1 false, label [[LATCH_10:%.*]], label [[EXIT]]
55; CHECK:       latch.10:
56; CHECK-NEXT:    call void @bar()
57; CHECK-NEXT:    br label [[EXIT]]
58;
59entry:
60  br label %loop
61loop:
62  %iv = phi i64 [0, %entry], [%iv.next, %latch]
63  %iv.next = add i64 %iv, 1
64  call void @bar()
65  %cmp1 = icmp ult i64 %iv, 10
66  br i1 %cmp1, label %latch, label %exit
67latch:
68  call void @bar()
69  %cmp2 = icmp ult i64 %iv, 20
70  br i1 %cmp2, label %loop, label %exit
71exit:
72  ret void
73}
74
75; TODO: We should fully unroll this by 10, leave the unrolled latch
76; tests since we don't know if %N < 10, and break the backedge.
77define void @test2(i64 %N) {
78; CHECK-LABEL: @test2(
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    br label [[LOOP:%.*]]
81; CHECK:       loop:
82; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
83; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
84; CHECK-NEXT:    call void @bar()
85; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i64 [[IV]], 10
86; CHECK-NEXT:    br i1 [[CMP1]], label [[LATCH]], label [[EXIT:%.*]]
87; CHECK:       latch:
88; CHECK-NEXT:    call void @bar()
89; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i64 [[IV]], [[N:%.*]]
90; CHECK-NEXT:    br i1 [[CMP2]], label [[LOOP]], label [[EXIT]]
91; CHECK:       exit:
92; CHECK-NEXT:    ret void
93;
94entry:
95  br label %loop
96loop:
97  %iv = phi i64 [0, %entry], [%iv.next, %latch]
98  %iv.next = add i64 %iv, 1
99  call void @bar()
100  %cmp1 = icmp ule i64 %iv, 10
101  br i1 %cmp1, label %latch, label %exit
102latch:
103  call void @bar()
104  %cmp2 = icmp ule i64 %iv, %N
105  br i1 %cmp2, label %loop, label %exit
106exit:
107  ret void
108}
109
110
111; TODO: We could partially unroll this by 2.
112define void @test3(i64 %N, i64 %M) {
113; CHECK-LABEL: @test3(
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    [[N_MASKED:%.*]] = and i64 [[N:%.*]], 65520
116; CHECK-NEXT:    [[M_MASKED:%.*]] = and i64 [[M:%.*]], 65520
117; CHECK-NEXT:    br label [[LOOP:%.*]]
118; CHECK:       loop:
119; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
120; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
121; CHECK-NEXT:    call void @bar()
122; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i64 [[IV]], [[N_MASKED]]
123; CHECK-NEXT:    br i1 [[CMP1]], label [[LATCH]], label [[EXIT:%.*]]
124; CHECK:       latch:
125; CHECK-NEXT:    call void @bar()
126; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i64 [[IV]], [[M_MASKED]]
127; CHECK-NEXT:    br i1 [[CMP2]], label [[LOOP]], label [[EXIT]]
128; CHECK:       exit:
129; CHECK-NEXT:    ret void
130;
131entry:
132  %N.masked = and i64 %N, 65520 ; 0xfff0
133  %M.masked = and i64 %M, 65520 ; 0xfff0
134  br label %loop
135loop:
136  %iv = phi i64 [0, %entry], [%iv.next, %latch]
137  %iv.next = add i64 %iv, 1
138  call void @bar()
139  %cmp1 = icmp ule i64 %iv, %N.masked
140  br i1 %cmp1, label %latch, label %exit
141latch:
142  call void @bar()
143  %cmp2 = icmp ule i64 %iv, %M.masked
144  br i1 %cmp2, label %loop, label %exit
145exit:
146  ret void
147}
148