1
+ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1
2
; RUN: opt -S -verify-loop-info -irce < %s | FileCheck %s
2
3
; RUN: opt -S -verify-loop-info -passes='require<branch-prob>,irce' < %s | FileCheck %s
3
4
4
5
define void @f_0 (i32 *%arr , i32 *%a_len_ptr , i32 %n , i1* %cond_buf ) {
5
6
; CHECK-LABEL: @f_0(
6
-
7
- ; CHECK: loop.preheader:
8
- ; CHECK: [[len_sub:[^ ]+]] = add nsw i32 %len, -4
9
- ; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = call i32 @llvm.smin.i32(i32 %n, i32 [[len_sub]])
10
- ; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = call i32 @llvm.smax.i32(i32 [[exit_main_loop_at_hiclamp]], i32 0)
11
- ; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]]
12
- ; CHECK: br i1 [[enter_main_loop]], label %[[loop_preheader2:[^ ,]+]], label %main.pseudo.exit
13
-
14
- ; CHECK: [[loop_preheader2]]:
15
- ; CHECK: br label %loop
16
-
17
- entry:
7
+ ; CHECK-NEXT: entry:
8
+ ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[A_LEN_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]]
9
+ ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
10
+ ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
11
+ ; CHECK: loop.preheader:
12
+ ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[LEN]], -4
13
+ ; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[N]], i32 [[TMP0]])
14
+ ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 0)
15
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
16
+ ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER1:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
17
+ ; CHECK: loop.preheader1:
18
+ ; CHECK-NEXT: br label [[LOOP:%.*]]
19
+ ; CHECK: loop:
20
+ ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER1]] ]
21
+ ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1
22
+ ; CHECK-NEXT: [[IDX_FOR_ABC:%.*]] = add i32 [[IDX]], 4
23
+ ; CHECK-NEXT: [[ABC_ACTUAL:%.*]] = icmp slt i32 [[IDX_FOR_ABC]], [[LEN]]
24
+ ; CHECK-NEXT: [[COND:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]], align 1
25
+ ; CHECK-NEXT: [[ABC:%.*]] = and i1 [[COND]], true
26
+ ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT2:%.*]], !prof [[PROF1:![0-9]+]]
27
+ ; CHECK: in.bounds:
28
+ ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX_FOR_ABC]]
29
+ ; CHECK-NEXT: store i32 0, i32* [[ADDR]], align 4
30
+ ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]]
31
+ ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
32
+ ; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
33
+ ; CHECK: main.exit.selector:
34
+ ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
35
+ ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]]
36
+ ; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
37
+ ; CHECK: main.pseudo.exit:
38
+ ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
39
+ ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
40
+ ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
41
+ ; CHECK: out.of.bounds.loopexit:
42
+ ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
43
+ ; CHECK: out.of.bounds.loopexit2:
44
+ ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
45
+ ; CHECK: out.of.bounds:
46
+ ; CHECK-NEXT: ret void
47
+ ; CHECK: exit.loopexit.loopexit:
48
+ ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
49
+ ; CHECK: exit.loopexit:
50
+ ; CHECK-NEXT: br label [[EXIT]]
51
+ ; CHECK: exit:
52
+ ; CHECK-NEXT: ret void
53
+ ; CHECK: postloop:
54
+ ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
55
+ ; CHECK: loop.postloop:
56
+ ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
57
+ ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
58
+ ; CHECK-NEXT: [[IDX_FOR_ABC_POSTLOOP:%.*]] = add i32 [[IDX_POSTLOOP]], 4
59
+ ; CHECK-NEXT: [[ABC_ACTUAL_POSTLOOP:%.*]] = icmp slt i32 [[IDX_FOR_ABC_POSTLOOP]], [[LEN]]
60
+ ; CHECK-NEXT: [[COND_POSTLOOP:%.*]] = load volatile i1, i1* [[COND_BUF]], align 1
61
+ ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = and i1 [[COND_POSTLOOP]], [[ABC_ACTUAL_POSTLOOP]]
62
+ ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF1]]
63
+ ; CHECK: in.bounds.postloop:
64
+ ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_FOR_ABC_POSTLOOP]]
65
+ ; CHECK-NEXT: store i32 0, i32* [[ADDR_POSTLOOP]], align 4
66
+ ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
67
+ ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]], !irce.loop.clone !7
68
+ ;
69
+ entry:
18
70
%len = load i32 , i32* %a_len_ptr , !range !0
19
71
%first.itr.check = icmp sgt i32 %n , 0
20
72
br i1 %first.itr.check , label %loop , label %exit
21
73
22
- loop:
74
+ loop:
23
75
%idx = phi i32 [ 0 , %entry ] , [ %idx.next , %in.bounds ]
24
76
%idx.next = add i32 %idx , 1
25
77
%idx.for.abc = add i32 %idx , 4
@@ -28,70 +80,115 @@ define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) {
28
80
%abc = and i1 %cond , %abc.actual
29
81
br i1 %abc , label %in.bounds , label %out.of.bounds , !prof !1
30
82
31
- ; CHECK: loop:
32
- ; CHECK: %cond = load volatile i1, i1* %cond_buf
33
- ; CHECK: %abc = and i1 %cond, true
34
- ; CHECK: br i1 %abc, label %in.bounds, label %[[loop_exit:[^ ,]+]], !prof !1
35
-
36
- ; CHECK: [[loop_exit]]:
37
- ; CHECK: br label %out.of.bounds
38
-
39
- in.bounds:
83
+ in.bounds:
40
84
%addr = getelementptr i32 , i32* %arr , i32 %idx.for.abc
41
85
store i32 0 , i32* %addr
42
86
%next = icmp slt i32 %idx.next , %n
43
87
br i1 %next , label %loop , label %exit
44
88
45
- out.of.bounds:
89
+ out.of.bounds:
46
90
ret void
47
91
48
- exit:
92
+ exit:
49
93
ret void
50
94
}
51
95
52
96
define void @f_1 (
53
- i32* %arr_a , i32* %a_len_ptr , i32* %arr_b , i32* %b_len_ptr , i32 %n ) {
54
97
; CHECK-LABEL: @f_1(
55
-
56
- ; CHECK: loop.preheader:
57
- ; CHECK: [[smax_len:[^ ]+]] = call i32 @llvm.smin.i32(i32 %len.b, i32 %len.a)
58
- ; CHECK: [[upper_limit_loclamp:[^ ]+]] = call i32 @llvm.smin.i32(i32 [[smax_len]], i32 %n)
59
- ; CHECK: [[upper_limit:[^ ]+]] = call i32 @llvm.smax.i32(i32 [[upper_limit_loclamp]], i32 0)
60
-
61
- entry:
98
+ ; CHECK-NEXT: entry:
99
+ ; CHECK-NEXT: [[LEN_A:%.*]] = load i32, i32* [[A_LEN_PTR:%.*]], align 4, !range [[RNG0]]
100
+ ; CHECK-NEXT: [[LEN_B:%.*]] = load i32, i32* [[B_LEN_PTR:%.*]], align 4, !range [[RNG0]]
101
+ ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
102
+ ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
103
+ ; CHECK: loop.preheader:
104
+ ; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN_B]], i32 [[LEN_A]])
105
+ ; CHECK-NEXT: [[SMIN1:%.*]] = call i32 @llvm.smin.i32(i32 [[SMIN]], i32 [[N]])
106
+ ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN1]], i32 0)
107
+ ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
108
+ ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
109
+ ; CHECK: loop.preheader2:
110
+ ; CHECK-NEXT: br label [[LOOP:%.*]]
111
+ ; CHECK: loop:
112
+ ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ]
113
+ ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1
114
+ ; CHECK-NEXT: [[ABC_A:%.*]] = icmp slt i32 [[IDX]], [[LEN_A]]
115
+ ; CHECK-NEXT: [[ABC_B:%.*]] = icmp slt i32 [[IDX]], [[LEN_B]]
116
+ ; CHECK-NEXT: [[ABC:%.*]] = and i1 true, true
117
+ ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof [[PROF1]]
118
+ ; CHECK: in.bounds:
119
+ ; CHECK-NEXT: [[ADDR_A:%.*]] = getelementptr i32, i32* [[ARR_A:%.*]], i32 [[IDX]]
120
+ ; CHECK-NEXT: store i32 0, i32* [[ADDR_A]], align 4
121
+ ; CHECK-NEXT: [[ADDR_B:%.*]] = getelementptr i32, i32* [[ARR_B:%.*]], i32 [[IDX]]
122
+ ; CHECK-NEXT: store i32 -1, i32* [[ADDR_B]], align 4
123
+ ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]]
124
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
125
+ ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
126
+ ; CHECK: main.exit.selector:
127
+ ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
128
+ ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]]
129
+ ; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
130
+ ; CHECK: main.pseudo.exit:
131
+ ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
132
+ ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
133
+ ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
134
+ ; CHECK: out.of.bounds.loopexit:
135
+ ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
136
+ ; CHECK: out.of.bounds.loopexit3:
137
+ ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
138
+ ; CHECK: out.of.bounds:
139
+ ; CHECK-NEXT: ret void
140
+ ; CHECK: exit.loopexit.loopexit:
141
+ ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
142
+ ; CHECK: exit.loopexit:
143
+ ; CHECK-NEXT: br label [[EXIT]]
144
+ ; CHECK: exit:
145
+ ; CHECK-NEXT: ret void
146
+ ; CHECK: postloop:
147
+ ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
148
+ ; CHECK: loop.postloop:
149
+ ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
150
+ ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
151
+ ; CHECK-NEXT: [[ABC_A_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[LEN_A]]
152
+ ; CHECK-NEXT: [[ABC_B_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[LEN_B]]
153
+ ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = and i1 [[ABC_A_POSTLOOP]], [[ABC_B_POSTLOOP]]
154
+ ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF1]]
155
+ ; CHECK: in.bounds.postloop:
156
+ ; CHECK-NEXT: [[ADDR_A_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR_A]], i32 [[IDX_POSTLOOP]]
157
+ ; CHECK-NEXT: store i32 0, i32* [[ADDR_A_POSTLOOP]], align 4
158
+ ; CHECK-NEXT: [[ADDR_B_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR_B]], i32 [[IDX_POSTLOOP]]
159
+ ; CHECK-NEXT: store i32 -1, i32* [[ADDR_B_POSTLOOP]], align 4
160
+ ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
161
+ ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone !7
162
+ ;
163
+ i32* %arr_a , i32* %a_len_ptr , i32* %arr_b , i32* %b_len_ptr , i32 %n ) {
164
+
165
+
166
+ entry:
62
167
%len.a = load i32 , i32* %a_len_ptr , !range !0
63
168
%len.b = load i32 , i32* %b_len_ptr , !range !0
64
169
%first.itr.check = icmp sgt i32 %n , 0
65
170
br i1 %first.itr.check , label %loop , label %exit
66
171
67
- loop:
172
+ loop:
68
173
%idx = phi i32 [ 0 , %entry ] , [ %idx.next , %in.bounds ]
69
174
%idx.next = add i32 %idx , 1
70
175
%abc.a = icmp slt i32 %idx , %len.a
71
176
%abc.b = icmp slt i32 %idx , %len.b
72
177
%abc = and i1 %abc.a , %abc.b
73
178
br i1 %abc , label %in.bounds , label %out.of.bounds , !prof !1
74
179
75
- ; CHECK: loop:
76
- ; CHECK: %abc = and i1 true, true
77
- ; CHECK: br i1 %abc, label %in.bounds, label %[[oob_loopexit:[^ ,]+]], !prof !1
78
-
79
- ; CHECK: [[oob_loopexit]]:
80
- ; CHECK-NEXT: br label %out.of.bounds
81
-
82
-
83
- in.bounds:
180
+ in.bounds:
84
181
%addr.a = getelementptr i32 , i32* %arr_a , i32 %idx
85
182
store i32 0 , i32* %addr.a
86
183
%addr.b = getelementptr i32 , i32* %arr_b , i32 %idx
87
184
store i32 -1 , i32* %addr.b
88
185
%next = icmp slt i32 %idx.next , %n
89
186
br i1 %next , label %loop , label %exit
90
187
91
- out.of.bounds:
188
+ out.of.bounds:
92
189
ret void
93
190
94
- exit:
191
+ exit:
95
192
ret void
96
193
}
97
194
0 commit comments