xref: /llvm-project/llvm/test/Transforms/LoopStrengthReduce/lsr-term-fold.ll (revision 6dc23b70097e4135ecde33f49550b1f473a5c385)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes="loop-reduce,loop-term-fold" -S | FileCheck %s
3
4target datalayout = "e-p:64:64:64-n64"
5
6define void @const_tripcount(ptr %a) {
7; CHECK-LABEL: @const_tripcount(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
10; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
11; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
12; CHECK:       for.body:
13; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
14; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
15; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
16; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
17; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
18; CHECK:       for.end:
19; CHECK-NEXT:    ret void
20;
21entry:
22  %uglygep = getelementptr i8, ptr %a, i64 84
23  br label %for.body
24
25for.body:                                         ; preds = %for.body, %entry
26  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
27  %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ 379, %entry ]
28  store i32 1, ptr %lsr.iv1, align 4
29  %lsr.iv.next = add nsw i64 %lsr.iv, -1
30  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4
31  %exitcond.not = icmp eq i64 %lsr.iv.next, 0
32  br i1 %exitcond.not, label %for.end, label %for.body
33
34for.end:                                          ; preds = %for.body
35  ret void
36}
37
38define void @runtime_tripcount(ptr %a, i32 %N) {
39; CHECK-LABEL: @runtime_tripcount(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
42; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[N:%.*]], -1
43; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
44; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 2
45; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 88
46; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP3]]
47; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
48; CHECK:       for.body:
49; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
50; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
51; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
52; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
53; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
54; CHECK:       for.end:
55; CHECK-NEXT:    ret void
56;
57entry:
58  %uglygep = getelementptr i8, ptr %a, i32 84
59  br label %for.body
60
61for.body:                                         ; preds = %for.body, %entry
62  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
63  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ %N, %entry ]
64  store i32 1, ptr %lsr.iv1, align 4
65  %lsr.iv.next = add nsw i32 %lsr.iv, -1
66  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4
67  %exitcond.not = icmp eq i32 %lsr.iv.next, 0
68  br i1 %exitcond.not, label %for.end, label %for.body
69
70for.end:                                          ; preds = %for.body
71  ret void
72}
73
74; In this case, the i8 IVs increment *isn't* nsw.  As a result, a N of 0
75; is well defined, and thus the post-inc starts at 255.
76define void @wrap_around(ptr %a, i8 %N) {
77; CHECK-LABEL: @wrap_around(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[N:%.*]], -1
80; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i64
81; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 2
82; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 4
83; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP3]]
84; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
85; CHECK:       for.body:
86; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ]
87; CHECK-NEXT:    store i8 1, ptr [[LSR_IV1]], align 4
88; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
89; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
90; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
91; CHECK:       for.end:
92; CHECK-NEXT:    ret void
93;
94entry:
95  br label %for.body
96
97for.body:                                         ; preds = %for.body, %entry
98  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ]
99  %lsr.iv = phi i8 [ %lsr.iv.next, %for.body ], [ %N, %entry ]
100  store i8 1, ptr %lsr.iv1, align 4
101  %lsr.iv.next = add i8 %lsr.iv, -1
102  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4
103  %exitcond.not = icmp eq i8 %lsr.iv.next, 0
104  br i1 %exitcond.not, label %for.end, label %for.body
105
106for.end:                                          ; preds = %for.body
107  ret void
108}
109
110; The replacing AddRec IV is a complicated AddRec. This tests whether
111; the fold terminating condition transformation is writing new terminating
112; condition in the correct type.
113define void @ptr_of_ptr_addrec(ptr %ptrptr, i32 %length) {
114; CHECK-LABEL: @ptr_of_ptr_addrec(
115; CHECK-NEXT:  entry:
116; CHECK-NEXT:    [[START_PTRPTR1:%.*]] = getelementptr inbounds ptr, ptr [[START_PTRPTR:%.*]]
117; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
118; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
119; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 3
120; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 8
121; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[START_PTRPTR]], i64 [[TMP3]]
122; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
123; CHECK:       for.body:
124; CHECK-NEXT:    [[IT_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[START_PTRPTR1]], [[ENTRY:%.*]] ]
125; CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[IT_04]], align 8
126; CHECK-NEXT:    tail call void @foo(ptr [[TMP4]])
127; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr ptr, ptr [[IT_04]], i64 1
128; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[SCEVGEP]]
129; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
130; CHECK:       for.end:
131; CHECK-NEXT:    ret void
132;
133entry:
134  %start.ptrptr = getelementptr inbounds ptr, ptr %ptrptr
135  br label %for.body
136
137for.body:                                         ; preds = %entry, %for.body
138  %i.05 = phi i32 [ %dec, %for.body ], [ %length, %entry ]
139  %it.04 = phi ptr [ %incdec.ptr, %for.body ], [ %start.ptrptr, %entry ]
140  %0 = load ptr, ptr %it.04, align 8
141  tail call void @foo(ptr %0)
142  %incdec.ptr = getelementptr inbounds ptr, ptr %it.04, i64 1
143  %dec = add nsw i32 %i.05, -1
144  %tobool.not = icmp eq i32 %dec, 0
145  br i1 %tobool.not, label %for.end, label %for.body
146
147for.end:                                 ; preds = %for.body
148  ret void
149}
150
151declare void @foo(ptr)
152
153define void @iv_start_non_preheader(ptr %mark, i32 signext %length) {
154; CHECK-LABEL: @iv_start_non_preheader(
155; CHECK-NEXT:  entry:
156; CHECK-NEXT:    [[TOBOOL_NOT3:%.*]] = icmp eq i32 [[LENGTH:%.*]], 0
157; CHECK-NEXT:    br i1 [[TOBOOL_NOT3]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
158; CHECK:       for.body.preheader:
159; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH]], -1
160; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
161; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 3
162; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 8
163; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[MARK:%.*]], i64 [[TMP3]]
164; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
165; CHECK:       for.cond.cleanup.loopexit:
166; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
167; CHECK:       for.cond.cleanup:
168; CHECK-NEXT:    ret void
169; CHECK:       for.body:
170; CHECK-NEXT:    [[DST_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[MARK]], [[FOR_BODY_PREHEADER]] ]
171; CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[DST_04]], align 8
172; CHECK-NEXT:    [[TMP5:%.*]] = call ptr @foo(ptr [[TMP4]])
173; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr ptr, ptr [[DST_04]], i64 1
174; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[SCEVGEP]]
175; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
176;
177entry:
178  %tobool.not3 = icmp eq i32 %length, 0
179  br i1 %tobool.not3, label %for.cond.cleanup, label %for.body
180
181for.cond.cleanup:                                 ; preds = %for.body, %entry
182  ret void
183
184for.body:                                         ; preds = %entry, %for.body
185  %i.05 = phi i32 [ %dec, %for.body ], [ %length, %entry ]
186  %dst.04 = phi ptr [ %incdec.ptr, %for.body ], [ %mark, %entry ]
187  %0 = load ptr, ptr %dst.04, align 8
188  call ptr @foo(ptr %0)
189  %incdec.ptr = getelementptr inbounds ptr, ptr %dst.04, i64 1
190  %dec = add nsw i32 %i.05, -1
191  %tobool.not = icmp eq i32 %dec, 0
192  br i1 %tobool.not, label %for.cond.cleanup, label %for.body
193}
194
195; Consider the case where %a points to a buffer exactly 17 bytes long.  The
196; loop below will access bytes: 0, 4, 8, and 16.  The key bit is that we
197; advance the pointer IV by *4* each time, and thus on the iteration we write
198; byte 16, %uglygep2 (the pointer increment) is past the end of the underlying
199; storage and thus violates the inbounds requirements.  As a result, %uglygep2
200; is poison on the final iteration.  If we insert a branch on that value
201; (without stripping the poison flag), we have inserted undefined behavior
202; where it did not previously exist.
203define void @inbounds_poison_use(ptr %a) {
204; CHECK-LABEL: @inbounds_poison_use(
205; CHECK-NEXT:  entry:
206; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 16
207; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
208; CHECK:       for.body:
209; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ]
210; CHECK-NEXT:    store i8 1, ptr [[LSR_IV1]], align 4
211; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
212; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
213; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
214; CHECK:       for.end:
215; CHECK-NEXT:    ret void
216;
217entry:
218  br label %for.body
219
220for.body:                                         ; preds = %for.body, %entry
221  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ]
222  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 4, %entry ]
223  store i8 1, ptr %lsr.iv1, align 4
224  %lsr.iv.next = add nsw i32 %lsr.iv, -1
225  %uglygep2 = getelementptr inbounds i8, ptr %lsr.iv1, i64 4
226  %exitcond.not = icmp eq i32 %lsr.iv.next, 0
227  br i1 %exitcond.not, label %for.end, label %for.body
228
229for.end:                                          ; preds = %for.body
230  ret void
231}
232
233; In this case, the integer IV has a larger bitwidth than the pointer IV.
234; This means that the smaller IV may wrap around multiple times before
235; the original loop exit is taken.
236define void @iv_size(ptr %a, i128 %N) {
237; CHECK-LABEL: @iv_size(
238; CHECK-NEXT:  entry:
239; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
240; CHECK:       for.body:
241; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A:%.*]], [[ENTRY:%.*]] ]
242; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i128 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[N:%.*]], [[ENTRY]] ]
243; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
244; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i128 [[LSR_IV]], -1
245; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
246; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i128 [[LSR_IV_NEXT]], 0
247; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
248; CHECK:       for.end:
249; CHECK-NEXT:    ret void
250;
251entry:
252  br label %for.body
253
254for.body:                                         ; preds = %for.body, %entry
255  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ]
256  %lsr.iv = phi i128 [ %lsr.iv.next, %for.body ], [ %N, %entry ]
257  store i32 1, ptr %lsr.iv1, align 4
258  %lsr.iv.next = add nsw i128 %lsr.iv, -1
259  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4
260  %exitcond.not = icmp eq i128 %lsr.iv.next, 0
261  br i1 %exitcond.not, label %for.end, label %for.body
262
263for.end:                                          ; preds = %for.body
264  ret void
265}
266
267; To check correct folding not equality terminating condition
268; Due to SLE offset must be - 1600
269define void @IcmpSle(ptr %a) {
270; CHECK-LABEL: @IcmpSle(
271; CHECK-NEXT:  entry:
272; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
273; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
274; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
275; CHECK:       for.body:
276; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
277; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
278; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4
279; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
280; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
281; CHECK:       for.end:
282; CHECK-NEXT:    ret void
283;
284entry:
285  %uglygep = getelementptr i8, ptr %a, i32 84
286  br label %for.body
287
288for.body:                                         ; preds = %for.body, %entry
289  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
290  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 379, %entry ]
291  store i32 1, ptr %lsr.iv1, align 4
292  %lsr.iv.next = add nsw i32 %lsr.iv, -1
293  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4
294  %exitcond.not = icmp sle i32 %lsr.iv.next, 0
295  br i1 %exitcond.not, label %for.end, label %for.body
296
297for.end:                                          ; preds = %for.body
298  ret void
299}
300
301; Due to SLT offset must be - 1604
302define void @IcmpSlt(ptr %a) {
303; CHECK-LABEL: @IcmpSlt(
304; CHECK-NEXT:  entry:
305; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
306; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1604
307; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
308; CHECK:       for.body:
309; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
310; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
311; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4
312; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
313; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
314; CHECK:       for.end:
315; CHECK-NEXT:    ret void
316;
317entry:
318  %uglygep = getelementptr i8, ptr %a, i32 84
319  br label %for.body
320
321for.body:                                         ; preds = %for.body, %entry
322  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
323  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 379, %entry ]
324  store i32 1, ptr %lsr.iv1, align 4
325  %lsr.iv.next = add nsw i32 %lsr.iv, -1
326  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4
327  %exitcond.not = icmp slt i32 %lsr.iv.next, 0
328  br i1 %exitcond.not, label %for.end, label %for.body
329
330for.end:                                          ; preds = %for.body
331  ret void
332}
333
334; Invert predicate and branches
335define void @IcmpSgt(ptr %a) {
336; CHECK-LABEL: @IcmpSgt(
337; CHECK-NEXT:  entry:
338; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
339; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
340; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
341; CHECK:       for.body:
342; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
343; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
344; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4
345; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
346; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
347; CHECK:       for.end:
348; CHECK-NEXT:    ret void
349;
350entry:
351  %uglygep = getelementptr i8, ptr %a, i32 84
352  br label %for.body
353
354for.body:                                         ; preds = %for.body, %entry
355  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
356  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 379, %entry ]
357  store i32 1, ptr %lsr.iv1, align 4
358  %lsr.iv.next = add nsw i32 %lsr.iv, -1
359  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4
360  %exitcond.not = icmp sgt i32 %lsr.iv.next, 0
361  br i1 %exitcond.not, label %for.body, label %for.end
362
363for.end:                                          ; preds = %for.body
364  ret void
365}
366
367; Invert predicate and branches
368define void @SeveralLoopLatch(ptr %a) {
369; CHECK-LABEL: @SeveralLoopLatch(
370; CHECK-NEXT:  entry:
371; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
372; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
373; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
374; CHECK:       for.body:
375; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[ANOTHER_BRANCH:%.*]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
376; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
377; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4
378; CHECK-NEXT:    br label [[ANOTHER_BRANCH]]
379; CHECK:       another.branch:
380; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
381; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
382; CHECK:       for.end:
383; CHECK-NEXT:    ret void
384;
385entry:
386  %uglygep = getelementptr i8, ptr %a, i32 84
387  br label %for.body
388
389for.body:                                         ; preds = %another.branch, %entry
390  %lsr.iv1 = phi ptr [ %uglygep2, %another.branch ], [ %uglygep, %entry ]
391  %lsr.iv = phi i32 [ %lsr.iv.next, %another.branch ], [ 379, %entry ]
392  store i32 1, ptr %lsr.iv1, align 4
393  %lsr.iv.next = add nsw i32 %lsr.iv, -1
394  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4
395  br label %another.branch
396
397another.branch:
398  %exitcond.not = icmp sgt i32 %lsr.iv.next, 0
399  br i1 %exitcond.not, label %for.body, label %for.end
400
401for.end:                                          ; preds = %for.body
402  ret void
403}
404
405; Invert branch in SeveralLoopLatch
406define void @SeveralLoopLatch2(ptr %a) {
407; CHECK-LABEL: @SeveralLoopLatch2(
408; CHECK-NEXT:  entry:
409; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
410; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
411; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
412; CHECK:       for.body:
413; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[ANOTHER_BRANCH:%.*]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
414; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
415; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4
416; CHECK-NEXT:    br label [[ANOTHER_BRANCH]]
417; CHECK:       another.branch:
418; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
419; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
420; CHECK:       for.end:
421; CHECK-NEXT:    ret void
422;
423entry:
424  %uglygep = getelementptr i8, ptr %a, i32 84
425  br label %for.body
426
427for.body:                                         ; preds = %another.branch, %entry
428  %lsr.iv1 = phi ptr [ %uglygep2, %another.branch ], [ %uglygep, %entry ]
429  %lsr.iv = phi i32 [ %lsr.iv.next, %another.branch ], [ 379, %entry ]
430  store i32 1, ptr %lsr.iv1, align 4
431  %lsr.iv.next = add nsw i32 %lsr.iv, -1
432  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4
433  br label %another.branch
434
435another.branch:
436  %exitcond.not = icmp sle i32 %lsr.iv.next, 0
437  br i1 %exitcond.not, label %for.end, label %for.body
438
439for.end:                                          ; preds = %for.body
440  ret void
441}
442
443
444define void @non_branch_terminator(ptr %a) {
445; CHECK-LABEL: @non_branch_terminator(
446; CHECK-NEXT:  entry:
447; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
448; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
449; CHECK:       for.body:
450; CHECK-NEXT:    [[LSR_IV2:%.*]] = phi i64 [ [[LSR_IV_NEXT3:%.*]], [[FOR_BODY]] ], [ 378, [[ENTRY:%.*]] ]
451; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY]] ]
452; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
453; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
454; CHECK-NEXT:    [[LSR_IV_NEXT3]] = add nsw i64 [[LSR_IV2]], -1
455; CHECK-NEXT:    switch i64 [[LSR_IV2]], label [[FOR_BODY]] [
456; CHECK-NEXT:      i64 0, label [[FOR_END:%.*]]
457; CHECK-NEXT:    ]
458; CHECK:       for.end:
459; CHECK-NEXT:    ret void
460;
461entry:
462  %uglygep = getelementptr i8, ptr %a, i64 84
463  br label %for.body
464
465for.body:                                         ; preds = %for.body, %entry
466  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
467  %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ 379, %entry ]
468  store i32 1, ptr %lsr.iv1, align 4
469  %lsr.iv.next = add nsw i64 %lsr.iv, -1
470  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4
471  switch i64 %lsr.iv.next, label %for.body [i64 0, label %for.end]
472
473for.end:                                          ; preds = %for.body
474  ret void
475}
476
477;; The next step of tests exercise various cases with the expansion
478;; budget and different trip counts or estimated trip counts.
479
480define void @profiled_short_tc(ptr %a, i32 %offset, i32 %n) {
481; CHECK-LABEL: @profiled_short_tc(
482; CHECK-NEXT:  entry:
483; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
484; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
485; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
486; CHECK:       for.body:
487; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
488; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]
489; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
490; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], 1
491; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
492; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], [[N:%.*]]
493; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]], !prof [[PROF0:![0-9]+]]
494; CHECK:       for.end:
495; CHECK-NEXT:    ret void
496;
497entry:
498  %offset.nonzero = or i32 %offset, 1
499  %uglygep = getelementptr i8, ptr %a, i64 84
500  br label %for.body
501
502for.body:                                         ; preds = %for.body, %entry
503  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
504  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
505  store i32 1, ptr %lsr.iv1, align 4
506  %lsr.iv.next = add nsw i32 %lsr.iv, 1
507  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
508  %exitcond.not = icmp eq i32 %lsr.iv.next, %n
509  br i1 %exitcond.not, label %for.end, label %for.body, !prof !{!"branch_weights", i32 1, i32 3}
510
511for.end:                                          ; preds = %for.body
512  ret void
513}
514
515define void @profiled_long_tc(ptr %a, i32 %offset, i32 %n) {
516; CHECK-LABEL: @profiled_long_tc(
517; CHECK-NEXT:  entry:
518; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
519; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
520; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], -1
521; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
522; CHECK-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
523; CHECK-NEXT:    [[TMP3:%.*]] = sext i32 [[OFFSET_NONZERO]] to i64
524; CHECK-NEXT:    [[TMP4:%.*]] = mul i64 [[TMP2]], [[TMP3]]
525; CHECK-NEXT:    [[TMP5:%.*]] = add nsw i64 [[TMP4]], 84
526; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP5]]
527; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
528; CHECK:       for.body:
529; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
530; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
531; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
532; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
533; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]], !prof [[PROF1:![0-9]+]]
534; CHECK:       for.end:
535; CHECK-NEXT:    ret void
536;
537entry:
538  %offset.nonzero = or i32 %offset, 1
539  %uglygep = getelementptr i8, ptr %a, i64 84
540  br label %for.body
541
542for.body:                                         ; preds = %for.body, %entry
543  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
544  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
545  store i32 1, ptr %lsr.iv1, align 4
546  %lsr.iv.next = add nsw i32 %lsr.iv, 1
547  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
548  %exitcond.not = icmp eq i32 %lsr.iv.next, %n
549  br i1 %exitcond.not, label %for.end, label %for.body, !prof !{!"branch_weights", i32 1, i32 300}
550
551for.end:                                          ; preds = %for.body
552  ret void
553}
554
555define void @unknown_tc(ptr %a, i32 %offset, i32 %n) {
556; CHECK-LABEL: @unknown_tc(
557; CHECK-NEXT:  entry:
558; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
559; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
560; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], -1
561; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
562; CHECK-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
563; CHECK-NEXT:    [[TMP3:%.*]] = sext i32 [[OFFSET_NONZERO]] to i64
564; CHECK-NEXT:    [[TMP4:%.*]] = mul i64 [[TMP2]], [[TMP3]]
565; CHECK-NEXT:    [[TMP5:%.*]] = add nsw i64 [[TMP4]], 84
566; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP5]]
567; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
568; CHECK:       for.body:
569; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
570; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
571; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
572; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
573; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
574; CHECK:       for.end:
575; CHECK-NEXT:    ret void
576;
577entry:
578  %offset.nonzero = or i32 %offset, 1
579  %uglygep = getelementptr i8, ptr %a, i64 84
580  br label %for.body
581
582for.body:                                         ; preds = %for.body, %entry
583  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
584  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
585  store i32 1, ptr %lsr.iv1, align 4
586  %lsr.iv.next = add nsw i32 %lsr.iv, 1
587  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
588  %exitcond.not = icmp eq i32 %lsr.iv.next, %n
589  br i1 %exitcond.not, label %for.end, label %for.body
590
591for.end:                                          ; preds = %for.body
592  ret void
593}
594
595define void @unknown_tc2(ptr %a, i32 %offset, i32 %n, i32 %step) mustprogress {
596; CHECK-LABEL: @unknown_tc2(
597; CHECK-NEXT:  entry:
598; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
599; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
600; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
601; CHECK:       for.body:
602; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
603; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]
604; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
605; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], [[STEP:%.*]]
606; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
607; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp sge i32 [[LSR_IV_NEXT]], [[N:%.*]]
608; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
609; CHECK:       for.end:
610; CHECK-NEXT:    ret void
611;
612entry:
613  %offset.nonzero = or i32 %offset, 1
614  %uglygep = getelementptr i8, ptr %a, i64 84
615  br label %for.body
616
617for.body:                                         ; preds = %for.body, %entry
618  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
619  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
620  store i32 1, ptr %lsr.iv1, align 4
621  %lsr.iv.next = add nsw i32 %lsr.iv, %step
622  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
623  %exitcond.not = icmp sge i32 %lsr.iv.next, %n
624  br i1 %exitcond.not, label %for.end, label %for.body
625
626for.end:                                          ; preds = %for.body
627  ret void
628}
629
630define void @small_tc_trivial_loop(ptr %a, i32 %offset) {
631; CHECK-LABEL: @small_tc_trivial_loop(
632; CHECK-NEXT:  entry:
633; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
634; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
635; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
636; CHECK:       for.body:
637; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
638; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]
639; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
640; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], 1
641; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
642; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 1
643; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
644; CHECK:       for.end:
645; CHECK-NEXT:    ret void
646;
647entry:
648  %offset.nonzero = or i32 %offset, 1
649  %uglygep = getelementptr i8, ptr %a, i64 84
650  br label %for.body
651
652for.body:                                         ; preds = %for.body, %entry
653  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
654  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
655  store i32 1, ptr %lsr.iv1, align 4
656  %lsr.iv.next = add nsw i32 %lsr.iv, 1
657  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
658  %exitcond.not = icmp eq i32 %lsr.iv.next, 1
659  br i1 %exitcond.not, label %for.end, label %for.body
660
661for.end:                                          ; preds = %for.body
662  ret void
663}
664
665define void @small_tc_below_threshold(ptr %a, i32 %offset) {
666; CHECK-LABEL: @small_tc_below_threshold(
667; CHECK-NEXT:  entry:
668; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
669; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
670; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
671; CHECK:       for.body:
672; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
673; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]
674; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
675; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], 1
676; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
677; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 2
678; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
679; CHECK:       for.end:
680; CHECK-NEXT:    ret void
681;
682entry:
683  %offset.nonzero = or i32 %offset, 1
684  %uglygep = getelementptr i8, ptr %a, i64 84
685  br label %for.body
686
687for.body:                                         ; preds = %for.body, %entry
688  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
689  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
690  store i32 1, ptr %lsr.iv1, align 4
691  %lsr.iv.next = add nsw i32 %lsr.iv, 1
692  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
693  %exitcond.not = icmp eq i32 %lsr.iv.next, 2
694  br i1 %exitcond.not, label %for.end, label %for.body
695
696for.end:                                          ; preds = %for.body
697  ret void
698}
699
700define void @small_tc_above_threshold(ptr %a, i32 %offset) {
701; CHECK-LABEL: @small_tc_above_threshold(
702; CHECK-NEXT:  entry:
703; CHECK-NEXT:    [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1
704; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
705; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[OFFSET_NONZERO]] to i64
706; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[TMP0]], 10
707; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i64 [[TMP1]], 84
708; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]]
709; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
710; CHECK:       for.body:
711; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
712; CHECK-NEXT:    store i32 1, ptr [[LSR_IV1]], align 4
713; CHECK-NEXT:    [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]]
714; CHECK-NEXT:    [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
715; CHECK-NEXT:    br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
716; CHECK:       for.end:
717; CHECK-NEXT:    ret void
718;
719entry:
720  %offset.nonzero = or i32 %offset, 1
721  %uglygep = getelementptr i8, ptr %a, i64 84
722  br label %for.body
723
724for.body:                                         ; preds = %for.body, %entry
725  %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
726  %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ]
727  store i32 1, ptr %lsr.iv1, align 4
728  %lsr.iv.next = add nsw i32 %lsr.iv, 1
729  %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero
730  %exitcond.not = icmp eq i32 %lsr.iv.next, 10
731  br i1 %exitcond.not, label %for.end, label %for.body
732
733for.end:                                          ; preds = %for.body
734  ret void
735}
736