xref: /llvm-project/llvm/test/Transforms/SimpleLoopUnswitch/inject-invariant-conditions.ll (revision 8362cae71b80bc43c8c680cdfb13c495705a622f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
2; RUN: opt < %s -S -simple-loop-unswitch-inject-invariant-conditions=true -passes="loop(simple-loop-unswitch<nontrivial>),simplifycfg" | FileCheck %s
3; RUN: opt < %s -S -simple-loop-unswitch-inject-invariant-conditions=true -passes="loop-mssa(simple-loop-unswitch<nontrivial>),simplifycfg" -verify-memoryssa | FileCheck %s
4
5define i32 @test_01(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
6; CHECK-LABEL: @test_01(
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
9; CHECK-NEXT:    [[INJECTED_COND:%.*]] = icmp ule i32 [[LIMIT:%.*]], [[X]]
10; CHECK-NEXT:    br i1 [[INJECTED_COND]], label [[LOOP_US:%.*]], label [[LOOP:%.*]]
11; CHECK:       loop.us:
12; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ [[IV_NEXT_US:%.*]], [[GUARDED_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
13; CHECK-NEXT:    [[EL_PTR_US:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV_US]]
14; CHECK-NEXT:    [[EL_US:%.*]] = load i32, ptr [[EL_PTR_US]], align 4
15; CHECK-NEXT:    [[BOUND_CHECK_US:%.*]] = icmp ult i32 [[EL_US]], [[LIMIT]]
16; CHECK-NEXT:    br i1 [[BOUND_CHECK_US]], label [[GUARDED_US]], label [[COMMON_RET:%.*]], !prof [[PROF1:![0-9]+]]
17; CHECK:       guarded.us:
18; CHECK-NEXT:    [[RANGE_CHECK_US:%.*]] = icmp ult i32 [[EL_US]], [[X]]
19; CHECK-NEXT:    [[ARR_PTR_US:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL_US]]
20; CHECK-NEXT:    store i32 [[IV_US]], ptr [[ARR_PTR_US]], align 4
21; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
22; CHECK-NEXT:    [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N:%.*]]
23; CHECK-NEXT:    br i1 [[LOOP_COND_US]], label [[LOOP_US]], label [[COMMON_RET]]
24; CHECK:       loop:
25; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY]] ]
26; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
27; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
28; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], [[LIMIT]]
29; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET]], !prof [[PROF1]]
30; CHECK:       guarded:
31; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
32; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]]
33; CHECK:       backedge:
34; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[EL]]
35; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
36; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
37; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N]]
38; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]], !llvm.loop [[LOOP2:![0-9]+]]
39; CHECK:       common.ret:
40; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ 0, [[GUARDED_US]] ], [ -1, [[LOOP]] ], [ -1, [[LOOP_US]] ], [ -2, [[GUARDED]] ]
41; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
42;
43entry:
44  %x = load i32, ptr %x_p, align 4, !noundef !{}
45  br label %loop
46
47loop:                                             ; preds = %backedge, %entry
48  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
49  %el.ptr = getelementptr i32, ptr %p, i32 %iv
50  %el = load i32, ptr %el.ptr, align 4
51  %bound_check = icmp ult i32 %el, %limit
52  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
53
54guarded:                                          ; preds = %loop
55  %range_check = icmp ult i32 %el, %x
56  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
57
58backedge:                                         ; preds = %guarded
59  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
60  store i32 %iv, ptr %arr.ptr, align 4
61  %iv.next = add i32 %iv, 1
62  %loop_cond = icmp slt i32 %iv.next, %n
63  br i1 %loop_cond, label %loop, label %exit
64
65exit:                                             ; preds = %backedge
66  ret i32 0
67
68bound_check_failed:                               ; preds = %loop
69  ret i32 -1
70
71range_check_failed:                               ; preds = %guarded
72  ret i32 -2
73}
74
75; Should not optimize: profile metadata is missing.
76define i32 @test_01_neg_void_profile(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
77; CHECK-LABEL: @test_01_neg_void_profile(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
80; CHECK-NEXT:    br label [[LOOP:%.*]]
81; CHECK:       loop:
82; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
83; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
84; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
85; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], [[LIMIT:%.*]]
86; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET:%.*]]
87; CHECK:       guarded:
88; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
89; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]]
90; CHECK:       backedge:
91; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
92; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
93; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
94; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
95; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]]
96; CHECK:       common.ret:
97; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ -1, [[LOOP]] ], [ -2, [[GUARDED]] ]
98; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
99;
100entry:
101  %x = load i32, ptr %x_p, align 4, !noundef !{}
102  br label %loop
103
104loop:                                             ; preds = %backedge, %entry
105  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
106  %el.ptr = getelementptr i32, ptr %p, i32 %iv
107  %el = load i32, ptr %el.ptr, align 4
108  %bound_check = icmp ult i32 %el, %limit
109  br i1 %bound_check, label %guarded, label %bound_check_failed
110
111guarded:                                          ; preds = %loop
112  %range_check = icmp ult i32 %el, %x
113  br i1 %range_check, label %backedge, label %range_check_failed
114
115backedge:                                         ; preds = %guarded
116  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
117  store i32 %iv, ptr %arr.ptr, align 4
118  %iv.next = add i32 %iv, 1
119  %loop_cond = icmp slt i32 %iv.next, %n
120  br i1 %loop_cond, label %loop, label %exit
121
122exit:                                             ; preds = %backedge
123  ret i32 0
124
125bound_check_failed:                               ; preds = %loop
126  ret i32 -1
127
128range_check_failed:                               ; preds = %guarded
129  ret i32 -2
130}
131
132; Same as test_01, but n and limit are constants.
133define i32 @test_01_constants(ptr noundef %p, ptr noundef %arr, ptr noundef %x_p) {
134; CHECK-LABEL: @test_01_constants(
135; CHECK-NEXT:  entry:
136; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
137; CHECK-NEXT:    [[INJECTED_COND:%.*]] = icmp ule i32 200, 300
138; CHECK-NEXT:    br i1 [[INJECTED_COND]], label [[LOOP_US:%.*]], label [[LOOP:%.*]]
139; CHECK:       loop.us:
140; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ [[IV_NEXT_US:%.*]], [[GUARDED_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
141; CHECK-NEXT:    [[EL_PTR_US:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV_US]]
142; CHECK-NEXT:    [[EL_US:%.*]] = load i32, ptr [[EL_PTR_US]], align 4
143; CHECK-NEXT:    [[BOUND_CHECK_US:%.*]] = icmp ult i32 [[EL_US]], 200
144; CHECK-NEXT:    br i1 [[BOUND_CHECK_US]], label [[GUARDED_US]], label [[COMMON_RET:%.*]], !prof [[PROF1]]
145; CHECK:       guarded.us:
146; CHECK-NEXT:    [[RANGE_CHECK_US:%.*]] = icmp ult i32 [[EL_US]], 300
147; CHECK-NEXT:    [[ARR_PTR_US:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL_US]]
148; CHECK-NEXT:    store i32 [[IV_US]], ptr [[ARR_PTR_US]], align 4
149; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
150; CHECK-NEXT:    [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], 1000
151; CHECK-NEXT:    br i1 [[LOOP_COND_US]], label [[LOOP_US]], label [[COMMON_RET]]
152; CHECK:       loop:
153; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY]] ]
154; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
155; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
156; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 200
157; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]], !prof [[PROF1]]
158; CHECK:       backedge:
159; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[EL]]
160; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
161; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
162; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
163; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]], !llvm.loop [[LOOP4:![0-9]+]]
164; CHECK:       common.ret:
165; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ 0, [[GUARDED_US]] ], [ -1, [[LOOP]] ], [ -1, [[LOOP_US]] ]
166; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
167;
168entry:
169  %x = load i32, ptr %x_p, align 4, !noundef !{}
170  br label %loop
171
172loop:                                             ; preds = %backedge, %entry
173  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
174  %el.ptr = getelementptr i32, ptr %p, i32 %iv
175  %el = load i32, ptr %el.ptr, align 4
176  %bound_check = icmp ult i32 %el, 200
177  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
178
179guarded:                                          ; preds = %loop
180  %range_check = icmp ult i32 %el, 300
181  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
182
183backedge:                                         ; preds = %guarded
184  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
185  store i32 %iv, ptr %arr.ptr, align 4
186  %iv.next = add i32 %iv, 1
187  %loop_cond = icmp slt i32 %iv.next, 1000
188  br i1 %loop_cond, label %loop, label %exit
189
190exit:                                             ; preds = %backedge
191  ret i32 0
192
193bound_check_failed:                               ; preds = %loop
194  ret i32 -1
195
196range_check_failed:                               ; preds = %guarded
197  ret i32 -2
198}
199
200define i32 @test_01_neg_degenerate_profile(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
201; CHECK-LABEL: @test_01_neg_degenerate_profile(
202; CHECK-NEXT:  entry:
203; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
204; CHECK-NEXT:    br label [[LOOP:%.*]]
205; CHECK:       loop:
206; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
207; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
208; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
209; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], [[LIMIT:%.*]]
210; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET:%.*]], !prof [[PROF1]]
211; CHECK:       guarded:
212; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
213; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]], !prof [[PROF5:![0-9]+]]
214; CHECK:       backedge:
215; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
216; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
217; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
218; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
219; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]]
220; CHECK:       common.ret:
221; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ -1, [[LOOP]] ], [ -2, [[GUARDED]] ]
222; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
223;
224entry:
225  %x = load i32, ptr %x_p, align 4, !noundef !{}
226  br label %loop
227
228loop:                                             ; preds = %backedge, %entry
229  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
230  %el.ptr = getelementptr i32, ptr %p, i32 %iv
231  %el = load i32, ptr %el.ptr, align 4
232  %bound_check = icmp ult i32 %el, %limit
233  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
234
235guarded:                                          ; preds = %loop
236  %range_check = icmp ult i32 %el, %x
237  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 0, i32 0}
238
239backedge:                                         ; preds = %guarded
240  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
241  store i32 %iv, ptr %arr.ptr, align 4
242  %iv.next = add i32 %iv, 1
243  %loop_cond = icmp slt i32 %iv.next, %n
244  br i1 %loop_cond, label %loop, label %exit
245
246exit:                                             ; preds = %backedge
247  ret i32 0
248
249bound_check_failed:                               ; preds = %loop
250  ret i32 -1
251
252range_check_failed:                               ; preds = %guarded
253  ret i32 -2
254}
255
256; Should not optimize: cold branch.
257define i32 @test_01_neg_cold(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
258; CHECK-LABEL: @test_01_neg_cold(
259; CHECK-NEXT:  entry:
260; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
261; CHECK-NEXT:    br label [[LOOP:%.*]]
262; CHECK:       loop:
263; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
264; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
265; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
266; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], [[LIMIT:%.*]]
267; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET:%.*]], !prof [[PROF1]]
268; CHECK:       guarded:
269; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
270; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]], !prof [[PROF6:![0-9]+]]
271; CHECK:       backedge:
272; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
273; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
274; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
275; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
276; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]]
277; CHECK:       common.ret:
278; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ -1, [[LOOP]] ], [ -2, [[GUARDED]] ]
279; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
280;
281entry:
282  %x = load i32, ptr %x_p, align 4, !noundef !{}
283  br label %loop
284
285loop:                                             ; preds = %backedge, %entry
286  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
287  %el.ptr = getelementptr i32, ptr %p, i32 %iv
288  %el = load i32, ptr %el.ptr, align 4
289  %bound_check = icmp ult i32 %el, %limit
290  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
291
292guarded:                                          ; preds = %loop
293  %range_check = icmp ult i32 %el, %x
294  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 2, i32 3}
295
296backedge:                                         ; preds = %guarded
297  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
298  store i32 %iv, ptr %arr.ptr, align 4
299  %iv.next = add i32 %iv, 1
300  %loop_cond = icmp slt i32 %iv.next, %n
301  br i1 %loop_cond, label %loop, label %exit
302
303exit:                                             ; preds = %backedge
304  ret i32 0
305
306bound_check_failed:                               ; preds = %loop
307  ret i32 -1
308
309range_check_failed:                               ; preds = %guarded
310  ret i32 -2
311}
312
313; Make sure we don't crash if probability overflows
314define i32 @test_01_neg_overflowing_metadata(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
315; CHECK-LABEL: @test_01_neg_overflowing_metadata(
316; CHECK-NEXT:  entry:
317; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
318; CHECK-NEXT:    br label [[LOOP:%.*]]
319; CHECK:       loop:
320; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
321; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV]]
322; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
323; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], [[LIMIT:%.*]]
324; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET:%.*]], !prof [[PROF7:![0-9]+]]
325; CHECK:       guarded:
326; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
327; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]], !prof [[PROF7]]
328; CHECK:       backedge:
329; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]]
330; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
331; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
332; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
333; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]]
334; CHECK:       common.ret:
335; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ -1, [[LOOP]] ], [ -2, [[GUARDED]] ]
336; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
337;
338entry:
339  %x = load i32, ptr %x_p, align 4, !noundef !{}
340  br label %loop
341
342loop:                                             ; preds = %backedge, %entry
343  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
344  %el.ptr = getelementptr i32, ptr %p, i32 %iv
345  %el = load i32, ptr %el.ptr, align 4
346  %bound_check = icmp ult i32 %el, %limit
347  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 -1, i32 -1000}
348
349guarded:                                          ; preds = %loop
350  %range_check = icmp ult i32 %el, %x
351  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 -1, i32 -1000}
352
353backedge:                                         ; preds = %guarded
354  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
355  store i32 %iv, ptr %arr.ptr, align 4
356  %iv.next = add i32 %iv, 1
357  %loop_cond = icmp slt i32 %iv.next, %n
358  br i1 %loop_cond, label %loop, label %exit
359
360exit:                                             ; preds = %backedge
361  ret i32 0
362
363bound_check_failed:                               ; preds = %loop
364  ret i32 -1
365
366range_check_failed:                               ; preds = %guarded
367  ret i32 -2
368}
369
370
371define i32 @test_02(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
372; CHECK-LABEL: @test_02(
373; CHECK-NEXT:  entry:
374; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
375; CHECK-NEXT:    [[INJECTED_COND:%.*]] = icmp ule i32 -2147483648, [[X]]
376; CHECK-NEXT:    br i1 [[INJECTED_COND]], label [[LOOP_US:%.*]], label [[LOOP:%.*]]
377; CHECK:       loop.us:
378; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ [[IV_NEXT_US:%.*]], [[GUARDED_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
379; CHECK-NEXT:    [[EL_PTR_US:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV_US]]
380; CHECK-NEXT:    [[EL_US:%.*]] = load i32, ptr [[EL_PTR_US]], align 4
381; CHECK-NEXT:    [[BOUND_CHECK_US:%.*]] = icmp sge i32 [[EL_US]], 0
382; CHECK-NEXT:    br i1 [[BOUND_CHECK_US]], label [[GUARDED_US]], label [[COMMON_RET:%.*]], !prof [[PROF1]]
383; CHECK:       guarded.us:
384; CHECK-NEXT:    [[RANGE_CHECK_US:%.*]] = icmp ult i32 [[EL_US]], [[X]]
385; CHECK-NEXT:    [[ARR_PTR_US:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL_US]]
386; CHECK-NEXT:    store i32 [[IV_US]], ptr [[ARR_PTR_US]], align 4
387; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
388; CHECK-NEXT:    [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N:%.*]]
389; CHECK-NEXT:    br i1 [[LOOP_COND_US]], label [[LOOP_US]], label [[COMMON_RET]]
390; CHECK:       loop:
391; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY]] ]
392; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
393; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
394; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp sge i32 [[EL]], 0
395; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET]], !prof [[PROF1]]
396; CHECK:       guarded:
397; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
398; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]]
399; CHECK:       backedge:
400; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[EL]]
401; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
402; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
403; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N]]
404; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]], !llvm.loop [[LOOP8:![0-9]+]]
405; CHECK:       common.ret:
406; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ 0, [[GUARDED_US]] ], [ -1, [[LOOP]] ], [ -1, [[LOOP_US]] ], [ -2, [[GUARDED]] ]
407; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
408;
409entry:
410  %x = load i32, ptr %x_p, align 4, !noundef !{}
411  br label %loop
412
413loop:                                             ; preds = %backedge, %entry
414  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
415  %el.ptr = getelementptr i32, ptr %p, i32 %iv
416  %el = load i32, ptr %el.ptr, align 4
417  %bound_check = icmp sge i32 %el, 0
418  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
419
420guarded:                                          ; preds = %loop
421  %range_check = icmp ult i32 %el, %x
422  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
423
424backedge:                                         ; preds = %guarded
425  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
426  store i32 %iv, ptr %arr.ptr, align 4
427  %iv.next = add i32 %iv, 1
428  %loop_cond = icmp slt i32 %iv.next, %n
429  br i1 %loop_cond, label %loop, label %exit
430
431exit:                                             ; preds = %backedge
432  ret i32 0
433
434bound_check_failed:                               ; preds = %loop
435  ret i32 -1
436
437range_check_failed:                               ; preds = %guarded
438  ret i32 -2
439}
440
441define i32 @test_02_inverse(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
442; CHECK-LABEL: @test_02_inverse(
443; CHECK-NEXT:  entry:
444; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
445; CHECK-NEXT:    [[INJECTED_COND:%.*]] = icmp ule i32 -2147483648, [[X]]
446; CHECK-NEXT:    br i1 [[INJECTED_COND]], label [[LOOP_US:%.*]], label [[LOOP:%.*]]
447; CHECK:       loop.us:
448; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ [[IV_NEXT_US:%.*]], [[GUARDED_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
449; CHECK-NEXT:    [[EL_PTR_US:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV_US]]
450; CHECK-NEXT:    [[EL_US:%.*]] = load i32, ptr [[EL_PTR_US]], align 4
451; CHECK-NEXT:    [[BOUND_CHECK_US:%.*]] = icmp sge i32 [[EL_US]], 0
452; CHECK-NEXT:    br i1 [[BOUND_CHECK_US]], label [[GUARDED_US]], label [[COMMON_RET:%.*]], !prof [[PROF1]]
453; CHECK:       guarded.us:
454; CHECK-NEXT:    [[RANGE_CHECK_US:%.*]] = icmp uge i32 [[EL_US]], [[X]]
455; CHECK-NEXT:    [[ARR_PTR_US:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL_US]]
456; CHECK-NEXT:    store i32 [[IV_US]], ptr [[ARR_PTR_US]], align 4
457; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
458; CHECK-NEXT:    [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N:%.*]]
459; CHECK-NEXT:    br i1 [[LOOP_COND_US]], label [[LOOP_US]], label [[COMMON_RET]]
460; CHECK:       loop:
461; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY]] ]
462; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
463; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
464; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp sge i32 [[EL]], 0
465; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[GUARDED:%.*]], label [[COMMON_RET]], !prof [[PROF1]]
466; CHECK:       guarded:
467; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp uge i32 [[EL]], [[X]]
468; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[COMMON_RET]], label [[BACKEDGE]]
469; CHECK:       backedge:
470; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[EL]]
471; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
472; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
473; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N]]
474; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]], !llvm.loop [[LOOP9:![0-9]+]]
475; CHECK:       common.ret:
476; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ 0, [[GUARDED_US]] ], [ -1, [[LOOP]] ], [ -1, [[LOOP_US]] ], [ -2, [[GUARDED]] ]
477; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
478;
479entry:
480  %x = load i32, ptr %x_p, align 4, !noundef !{}
481  br label %loop
482
483loop:                                             ; preds = %backedge, %entry
484  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
485  %el.ptr = getelementptr i32, ptr %p, i32 %iv
486  %el = load i32, ptr %el.ptr, align 4
487  %bound_check = icmp sge i32 %el, 0
488  br i1 %bound_check, label %guarded, label %bound_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
489
490guarded:                                          ; preds = %loop
491  %range_check = icmp uge i32 %el, %x
492  br i1 %range_check, label %range_check_failed, label %backedge, !prof !{!"branch_weights", i32 1, i32 100}
493
494backedge:                                         ; preds = %guarded
495  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
496  store i32 %iv, ptr %arr.ptr, align 4
497  %iv.next = add i32 %iv, 1
498  %loop_cond = icmp slt i32 %iv.next, %n
499  br i1 %loop_cond, label %loop, label %exit
500
501exit:                                             ; preds = %backedge
502  ret i32 0
503
504bound_check_failed:                               ; preds = %loop
505  ret i32 -1
506
507range_check_failed:                               ; preds = %guarded
508  ret i32 -2
509}
510
511define i32 @test_03(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
512; CHECK-LABEL: @test_03(
513; CHECK-NEXT:  entry:
514; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
515; CHECK-NEXT:    [[INJECTED_COND:%.*]] = icmp ule i32 -2147483648, [[X]]
516; CHECK-NEXT:    br i1 [[INJECTED_COND]], label [[LOOP_US:%.*]], label [[LOOP:%.*]]
517; CHECK:       loop.us:
518; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ [[IV_NEXT_US:%.*]], [[GUARDED_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
519; CHECK-NEXT:    [[EL_PTR_US:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[IV_US]]
520; CHECK-NEXT:    [[EL_US:%.*]] = load i32, ptr [[EL_PTR_US]], align 4
521; CHECK-NEXT:    [[BOUND_CHECK_US:%.*]] = icmp slt i32 [[EL_US]], 0
522; CHECK-NEXT:    br i1 [[BOUND_CHECK_US]], label [[COMMON_RET:%.*]], label [[GUARDED_US]], !prof [[PROF10:![0-9]+]]
523; CHECK:       guarded.us:
524; CHECK-NEXT:    [[RANGE_CHECK_US:%.*]] = icmp ult i32 [[EL_US]], [[X]]
525; CHECK-NEXT:    [[ARR_PTR_US:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL_US]]
526; CHECK-NEXT:    store i32 [[IV_US]], ptr [[ARR_PTR_US]], align 4
527; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
528; CHECK-NEXT:    [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N:%.*]]
529; CHECK-NEXT:    br i1 [[LOOP_COND_US]], label [[LOOP_US]], label [[COMMON_RET]]
530; CHECK:       loop:
531; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY]] ]
532; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
533; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
534; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 0
535; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[COMMON_RET]], label [[GUARDED:%.*]], !prof [[PROF10]]
536; CHECK:       guarded:
537; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL]], [[X]]
538; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]]
539; CHECK:       backedge:
540; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[EL]]
541; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
542; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
543; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N]]
544; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]], !llvm.loop [[LOOP11:![0-9]+]]
545; CHECK:       common.ret:
546; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ 0, [[GUARDED_US]] ], [ -1, [[LOOP]] ], [ -1, [[LOOP_US]] ], [ -2, [[GUARDED]] ]
547; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
548;
549entry:
550  %x = load i32, ptr %x_p, align 4, !noundef !{}
551  br label %loop
552
553loop:                                             ; preds = %backedge, %entry
554  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
555  %el.ptr = getelementptr i32, ptr %p, i32 %iv
556  %el = load i32, ptr %el.ptr, align 4
557  %bound_check = icmp slt i32 %el, 0
558  br i1 %bound_check, label %bound_check_failed, label %guarded, !prof !{!"branch_weights", i32 1, i32 100}
559
560guarded:                                          ; preds = %loop
561  %range_check = icmp ult i32 %el, %x
562  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
563
564backedge:                                         ; preds = %guarded
565  %arr.ptr = getelementptr i32, ptr %arr, i32 %el
566  store i32 %iv, ptr %arr.ptr, align 4
567  %iv.next = add i32 %iv, 1
568  %loop_cond = icmp slt i32 %iv.next, %n
569  br i1 %loop_cond, label %loop, label %exit
570
571exit:                                             ; preds = %backedge
572  ret i32 0
573
574bound_check_failed:                               ; preds = %loop
575  ret i32 -1
576
577range_check_failed:                               ; preds = %guarded
578  ret i32 -2
579}
580
581define i32 @test_04(ptr noundef %p, i32 noundef %n, i32 noundef %limit, ptr noundef %arr, ptr noundef %x_p) {
582; CHECK-LABEL: @test_04(
583; CHECK-NEXT:  entry:
584; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[X_P:%.*]], align 4, !noundef !0
585; CHECK-NEXT:    [[INJECTED_COND:%.*]] = icmp ule i32 128, [[X]]
586; CHECK-NEXT:    br i1 [[INJECTED_COND]], label [[LOOP_US:%.*]], label [[LOOP:%.*]]
587; CHECK:       loop.us:
588; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ [[IV_NEXT_US:%.*]], [[GUARDED_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
589; CHECK-NEXT:    [[EL_PTR_US:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 [[IV_US]]
590; CHECK-NEXT:    [[EL_US:%.*]] = load i8, ptr [[EL_PTR_US]], align 4
591; CHECK-NEXT:    [[BOUND_CHECK_US:%.*]] = icmp slt i8 [[EL_US]], 0
592; CHECK-NEXT:    br i1 [[BOUND_CHECK_US]], label [[COMMON_RET:%.*]], label [[GUARDED_US]], !prof [[PROF10]]
593; CHECK:       guarded.us:
594; CHECK-NEXT:    [[EL_WIDE_US:%.*]] = zext i8 [[EL_US]] to i32
595; CHECK-NEXT:    [[RANGE_CHECK_US:%.*]] = icmp ult i32 [[EL_WIDE_US]], [[X]]
596; CHECK-NEXT:    [[ARR_PTR_US:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL_WIDE_US]]
597; CHECK-NEXT:    store i32 [[IV_US]], ptr [[ARR_PTR_US]], align 4
598; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
599; CHECK-NEXT:    [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N:%.*]]
600; CHECK-NEXT:    br i1 [[LOOP_COND_US]], label [[LOOP_US]], label [[COMMON_RET]]
601; CHECK:       loop:
602; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY]] ]
603; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i8, ptr [[P]], i32 [[IV]]
604; CHECK-NEXT:    [[EL:%.*]] = load i8, ptr [[EL_PTR]], align 4
605; CHECK-NEXT:    [[BOUND_CHECK:%.*]] = icmp slt i8 [[EL]], 0
606; CHECK-NEXT:    br i1 [[BOUND_CHECK]], label [[COMMON_RET]], label [[GUARDED:%.*]], !prof [[PROF10]]
607; CHECK:       guarded:
608; CHECK-NEXT:    [[EL_WIDE:%.*]] = zext i8 [[EL]] to i32
609; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[EL_WIDE]], [[X]]
610; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[COMMON_RET]]
611; CHECK:       backedge:
612; CHECK-NEXT:    [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[EL_WIDE]]
613; CHECK-NEXT:    store i32 [[IV]], ptr [[ARR_PTR]], align 4
614; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
615; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N]]
616; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[COMMON_RET]], !llvm.loop [[LOOP12:![0-9]+]]
617; CHECK:       common.ret:
618; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BACKEDGE]] ], [ 0, [[GUARDED_US]] ], [ -1, [[LOOP]] ], [ -1, [[LOOP_US]] ], [ -2, [[GUARDED]] ]
619; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
620;
621entry:
622  %x = load i32, ptr %x_p, align 4, !noundef !{}
623  br label %loop
624
625loop:                                             ; preds = %backedge, %entry
626  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
627  %el.ptr = getelementptr i8, ptr %p, i32 %iv
628  %el = load i8, ptr %el.ptr, align 4
629  %bound_check = icmp slt i8 %el, 0
630  br i1 %bound_check, label %bound_check_failed, label %guarded, !prof !{!"branch_weights", i32 1, i32 100}
631
632guarded:                                          ; preds = %loop
633  %el.wide = zext i8 %el to i32
634  %range_check = icmp ult i32 %el.wide, %x
635  br i1 %range_check, label %backedge, label %range_check_failed, !prof !{!"branch_weights", i32 100, i32 1}
636
637backedge:                                         ; preds = %guarded
638  %arr.ptr = getelementptr i32, ptr %arr, i32 %el.wide
639  store i32 %iv, ptr %arr.ptr, align 4
640  %iv.next = add i32 %iv, 1
641  %loop_cond = icmp slt i32 %iv.next, %n
642  br i1 %loop_cond, label %loop, label %exit
643
644exit:                                             ; preds = %backedge
645  ret i32 0
646
647bound_check_failed:                               ; preds = %loop
648  ret i32 -1
649
650range_check_failed:                               ; preds = %guarded
651  ret i32 -2
652}
653;.
654; CHECK: [[META0:![0-9]+]] = !{}
655; CHECK: [[PROF1]] = !{!"branch_weights", i32 100, i32 1}
656; CHECK: [[LOOP2]] = distinct !{!2, !3}
657; CHECK: [[META3:![0-9]+]] = !{!"llvm.loop.unswitch.injection.disable"}
658; CHECK: [[LOOP4]] = distinct !{!4, !3}
659; CHECK: [[PROF5]] = !{!"branch_weights", i32 0, i32 0}
660; CHECK: [[PROF6]] = !{!"branch_weights", i32 2, i32 3}
661; CHECK: [[PROF7]] = !{!"branch_weights", i32 -1, i32 -1000}
662; CHECK: [[LOOP8]] = distinct !{!8, !3}
663; CHECK: [[LOOP9]] = distinct !{!9, !3}
664; CHECK: [[PROF10]] = !{!"branch_weights", i32 1, i32 100}
665; CHECK: [[LOOP11]] = distinct !{!11, !3}
666; CHECK: [[LOOP12]] = distinct !{!12, !3}
667;.
668