1 ; RUN: opt -S -loop-unroll < %s | FileCheck %s
2 ; RUN: opt -S -passes='require<opt-remark-emit>,loop(unroll-full)' < %s | FileCheck %s
4 ; Unroll twice, with first loop exit kept
5 ; CHECK-LABEL: @s32_max1
8 ; CHECK: br i1 %cmp, label %do.body.1, label %do.end
13 ; CHECK: br label %do.end
14 define void @s32_max1(i32 %n, i32* %p) {
20 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
21 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
22 store i32 %i.0, i32* %arrayidx, align 4
23 %inc = add i32 %i.0, 1
24 %cmp = icmp slt i32 %i.0, %add
25 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 1 times
31 ; Unroll thrice, with first loop exit kept
32 ; CHECK-LABEL: @s32_max2
35 ; CHECK: br i1 %cmp, label %do.body.1, label %do.end
41 ; CHECK: br label %do.end
42 define void @s32_max2(i32 %n, i32* %p) {
48 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
49 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
50 store i32 %i.0, i32* %arrayidx, align 4
51 %inc = add i32 %i.0, 1
52 %cmp = icmp slt i32 %i.0, %add
53 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 2 times
59 ; Should not be unrolled
60 ; CHECK-LABEL: @s32_maxx
63 ; CHECK-NOT: do.body.1:
64 define void @s32_maxx(i32 %n, i32 %x, i32* %p) {
70 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
71 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
72 store i32 %i.0, i32* %arrayidx, align 4
73 %inc = add i32 %i.0, 1
74 %cmp = icmp slt i32 %i.0, %add
75 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or x times
81 ; Should not be unrolled
82 ; CHECK-LABEL: @s32_max2_unpredictable_exit
85 ; CHECK-NOT: do.body.1:
86 define void @s32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) {
92 %i.0 = phi i32 [ %n, %entry ], [ %inc, %if.end ]
93 %cmp = icmp eq i32 %i.0, %x
94 br i1 %cmp, label %do.end, label %if.end ; unpredictable
97 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
98 store i32 %i.0, i32* %arrayidx, align 4
99 %inc = add i32 %i.0, 1
100 %cmp1 = icmp slt i32 %i.0, %add
101 br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times
107 ; Unroll twice, with first loop exit kept
108 ; CHECK-LABEL: @u32_max1
111 ; CHECK: br i1 %cmp, label %do.body.1, label %do.end
116 ; CHECK: br label %do.end
117 define void @u32_max1(i32 %n, i32* %p) {
123 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
124 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
125 store i32 %i.0, i32* %arrayidx, align 4
126 %inc = add i32 %i.0, 1
127 %cmp = icmp ult i32 %i.0, %add
128 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 1 times
134 ; Unroll thrice, with first loop exit kept
135 ; CHECK-LABEL: @u32_max2
138 ; CHECK: br i1 %cmp, label %do.body.1, label %do.end
144 ; CHECK: br label %do.end
145 define void @u32_max2(i32 %n, i32* %p) {
151 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
152 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
153 store i32 %i.0, i32* %arrayidx, align 4
154 %inc = add i32 %i.0, 1
155 %cmp = icmp ult i32 %i.0, %add
156 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 2 times
162 ; Should not be unrolled
163 ; CHECK-LABEL: @u32_maxx
166 ; CHECK-NOT: do.body.1:
167 define void @u32_maxx(i32 %n, i32 %x, i32* %p) {
169 %add = add i32 %x, %n
173 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ]
174 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
175 store i32 %i.0, i32* %arrayidx, align 4
176 %inc = add i32 %i.0, 1
177 %cmp = icmp ult i32 %i.0, %add
178 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or x times
184 ; Should not be unrolled
185 ; CHECK-LABEL: @u32_max2_unpredictable_exit
188 ; CHECK-NOT: do.body.1:
189 define void @u32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) {
195 %i.0 = phi i32 [ %n, %entry ], [ %inc, %if.end ]
196 %cmp = icmp eq i32 %i.0, %x
197 br i1 %cmp, label %do.end, label %if.end ; unpredictable
200 %arrayidx = getelementptr i32, i32* %p, i32 %i.0
201 store i32 %i.0, i32* %arrayidx, align 4
202 %inc = add i32 %i.0, 1
203 %cmp1 = icmp ult i32 %i.0, %add
204 br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times