Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / SLPVectorizer / AArch64 / memory-runtime-checks.ll
blob70cdd08548b2df84463e793632629031d0446755
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -aa-pipeline='basic-aa,scoped-noalias-aa' -passes=slp-vectorizer -mtriple=arm64-apple-darwin -S %s | FileCheck %s
4 define void @needs_versioning_not_profitable(ptr %dst, ptr %src) {
5 ; CHECK-LABEL: @needs_versioning_not_profitable(
6 ; CHECK-NEXT:  entry:
7 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
8 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
9 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
10 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
11 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
12 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
13 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
14 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
15 ; CHECK-NEXT:    ret void
17 entry:
18   %src.0 = load i32, ptr %src, align 4
19   %r.0 = ashr i32 %src.0, 16
20   store i32 %r.0, ptr %dst, align 4
21   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
22   %src.1 = load i32, ptr %src.gep.1, align 4
23   %r.1 = ashr i32 %src.1, 16
24   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
25   store i32 %r.1, ptr %dst.gep.1, align 4
26   ret void
29 define void @needs_versioning_profitable(ptr %dst, ptr %src) {
30 ; CHECK-LABEL: @needs_versioning_profitable(
31 ; CHECK-NEXT:  entry:
32 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
33 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
34 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
35 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
36 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
37 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
38 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
39 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
40 ; CHECK-NEXT:    [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2
41 ; CHECK-NEXT:    [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4
42 ; CHECK-NEXT:    [[R_2:%.*]] = ashr i32 [[SRC_2]], 16
43 ; CHECK-NEXT:    [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
44 ; CHECK-NEXT:    store i32 [[R_2]], ptr [[DST_GEP_2]], align 4
45 ; CHECK-NEXT:    [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3
46 ; CHECK-NEXT:    [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4
47 ; CHECK-NEXT:    [[R_3:%.*]] = ashr i32 [[SRC_3]], 16
48 ; CHECK-NEXT:    [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3
49 ; CHECK-NEXT:    store i32 [[R_3]], ptr [[DST_GEP_3]], align 4
50 ; CHECK-NEXT:    ret void
52 entry:
53   %src.0 = load i32, ptr %src, align 4
54   %r.0 = ashr i32 %src.0, 16
55   store i32 %r.0, ptr %dst, align 4
56   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
57   %src.1 = load i32, ptr %src.gep.1, align 4
58   %r.1 = ashr i32 %src.1, 16
59   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
60   store i32 %r.1, ptr %dst.gep.1, align 4
61   %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2
62   %src.2 = load i32, ptr %src.gep.2, align 4
63   %r.2 = ashr i32 %src.2, 16
64   %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2
65   store i32 %r.2, ptr %dst.gep.2, align 4
66   %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3
67   %src.3 = load i32, ptr %src.gep.3, align 4
68   %r.3 = ashr i32 %src.3, 16
69   %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3
70   store i32 %r.3, ptr %dst.gep.3, align 4
72   ret void
75 define void @needs_versioning_profitable_2_sources(ptr %dst, ptr %A, ptr %B) {
76 ; CHECK-LABEL: @needs_versioning_profitable_2_sources(
77 ; CHECK-NEXT:  entry:
78 ; CHECK-NEXT:    [[A_0:%.*]] = load i32, ptr [[A:%.*]], align 4
79 ; CHECK-NEXT:    [[B_0:%.*]] = load i32, ptr [[B:%.*]], align 4
80 ; CHECK-NEXT:    [[R_0:%.*]] = add i32 [[A_0]], [[B_0]]
81 ; CHECK-NEXT:    [[MUL_0:%.*]] = mul i32 [[R_0]], 2
82 ; CHECK-NEXT:    store i32 [[MUL_0]], ptr [[DST:%.*]], align 4
83 ; CHECK-NEXT:    [[A_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 1
84 ; CHECK-NEXT:    [[A_1:%.*]] = load i32, ptr [[A_GEP_1]], align 4
85 ; CHECK-NEXT:    [[B_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 1
86 ; CHECK-NEXT:    [[B_1:%.*]] = load i32, ptr [[B_GEP_1]], align 4
87 ; CHECK-NEXT:    [[R_1:%.*]] = add i32 [[A_1]], [[B_1]]
88 ; CHECK-NEXT:    [[MUL_1:%.*]] = mul i32 [[R_1]], 2
89 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
90 ; CHECK-NEXT:    store i32 [[MUL_1]], ptr [[DST_GEP_1]], align 4
91 ; CHECK-NEXT:    [[A_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 2
92 ; CHECK-NEXT:    [[A_2:%.*]] = load i32, ptr [[A_GEP_2]], align 4
93 ; CHECK-NEXT:    [[B_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 2
94 ; CHECK-NEXT:    [[B_2:%.*]] = load i32, ptr [[B_GEP_2]], align 4
95 ; CHECK-NEXT:    [[R_2:%.*]] = add i32 [[A_2]], [[B_2]]
96 ; CHECK-NEXT:    [[MUL_2:%.*]] = mul i32 [[R_2]], 2
97 ; CHECK-NEXT:    [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
98 ; CHECK-NEXT:    store i32 [[MUL_2]], ptr [[DST_GEP_2]], align 4
99 ; CHECK-NEXT:    [[A_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 3
100 ; CHECK-NEXT:    [[A_3:%.*]] = load i32, ptr [[A_GEP_3]], align 4
101 ; CHECK-NEXT:    [[B_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 3
102 ; CHECK-NEXT:    [[B_3:%.*]] = load i32, ptr [[B_GEP_3]], align 4
103 ; CHECK-NEXT:    [[R_3:%.*]] = add i32 [[A_3]], [[B_3]]
104 ; CHECK-NEXT:    [[MUL_3:%.*]] = mul i32 [[R_3]], 2
105 ; CHECK-NEXT:    [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3
106 ; CHECK-NEXT:    store i32 [[MUL_3]], ptr [[DST_GEP_3]], align 4
107 ; CHECK-NEXT:    ret void
109 entry:
110   %A.0 = load i32, ptr %A, align 4
111   %B.0 = load i32, ptr %B, align 4
112   %r.0 = add i32 %A.0, %B.0
113   %mul.0 = mul i32 %r.0, 2
114   store i32 %mul.0, ptr %dst, align 4
115   %A.gep.1 = getelementptr inbounds i32, ptr %A, i64 1
116   %A.1 = load i32, ptr %A.gep.1, align 4
117   %B.gep.1 = getelementptr inbounds i32, ptr %B, i64 1
118   %B.1 = load i32, ptr %B.gep.1, align 4
119   %r.1 = add i32 %A.1, %B.1
120   %mul.1 = mul i32 %r.1, 2
121   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
122   store i32 %mul.1, ptr %dst.gep.1, align 4
123   %A.gep.2 = getelementptr inbounds i32, ptr %A, i64 2
124   %A.2 = load i32, ptr %A.gep.2, align 4
125   %B.gep.2 = getelementptr inbounds i32, ptr %B, i64 2
126   %B.2 = load i32, ptr %B.gep.2, align 4
127   %r.2 = add i32 %A.2, %B.2
128   %mul.2 = mul i32 %r.2, 2
129   %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2
130   store i32 %mul.2, ptr %dst.gep.2, align 4
131   %A.gep.3 = getelementptr inbounds i32, ptr %A, i64 3
132   %A.3 = load i32, ptr %A.gep.3, align 4
133   %B.gep.3 = getelementptr inbounds i32, ptr %B, i64 3
134   %B.3 = load i32, ptr %B.gep.3, align 4
135   %r.3 = add i32 %A.3, %B.3
136   %mul.3 = mul i32 %r.3, 2
137   %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3
138   store i32 %mul.3, ptr %dst.gep.3, align 4
140   ret void
143 declare void @use(i32)
145 declare void @bar()
147 define void @needs_versioning_profitable_split_points(ptr %dst, ptr %src) {
148 ; CHECK-LABEL: @needs_versioning_profitable_split_points(
149 ; CHECK-NEXT:  entry:
150 ; CHECK-NEXT:    call void @bar()
151 ; CHECK-NEXT:    call void @bar()
152 ; CHECK-NEXT:    call void @bar()
153 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
154 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
155 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
156 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
157 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
158 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
159 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
160 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
161 ; CHECK-NEXT:    [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2
162 ; CHECK-NEXT:    [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4
163 ; CHECK-NEXT:    [[R_2:%.*]] = ashr i32 [[SRC_2]], 16
164 ; CHECK-NEXT:    [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
165 ; CHECK-NEXT:    store i32 [[R_2]], ptr [[DST_GEP_2]], align 4
166 ; CHECK-NEXT:    [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3
167 ; CHECK-NEXT:    [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4
168 ; CHECK-NEXT:    [[R_3:%.*]] = ashr i32 [[SRC_3]], 16
169 ; CHECK-NEXT:    [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3
170 ; CHECK-NEXT:    store i32 [[R_3]], ptr [[DST_GEP_3]], align 4
171 ; CHECK-NEXT:    call void @bar()
172 ; CHECK-NEXT:    ret void
174 entry:
175   call void @bar()
176   call void @bar()
177   call void @bar()
179   %src.0 = load i32, ptr %src, align 4
180   %r.0 = ashr i32 %src.0, 16
181   store i32 %r.0, ptr %dst, align 4
182   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
183   %src.1 = load i32, ptr %src.gep.1, align 4
184   %r.1 = ashr i32 %src.1, 16
185   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
186   store i32 %r.1, ptr %dst.gep.1, align 4
187   %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2
188   %src.2 = load i32, ptr %src.gep.2, align 4
189   %r.2 = ashr i32 %src.2, 16
190   %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2
191   store i32 %r.2, ptr %dst.gep.2, align 4
192   %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3
193   %src.3 = load i32, ptr %src.gep.3, align 4
194   %r.3 = ashr i32 %src.3, 16
195   %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3
196   store i32 %r.3, ptr %dst.gep.3, align 4
198   call void @bar()
199   ret void
202 define void @needs_versioning_profitable_load_used_outside_region1(ptr %dst, ptr %src, i1 %c) {
203 ; CHECK-LABEL: @needs_versioning_profitable_load_used_outside_region1(
204 ; CHECK-NEXT:  entry:
205 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
206 ; CHECK:       then:
207 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
208 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
209 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
210 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
211 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
212 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
213 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
214 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
215 ; CHECK-NEXT:    [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2
216 ; CHECK-NEXT:    [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4
217 ; CHECK-NEXT:    [[R_2:%.*]] = ashr i32 [[SRC_2]], 16
218 ; CHECK-NEXT:    [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
219 ; CHECK-NEXT:    store i32 [[R_2]], ptr [[DST_GEP_2]], align 4
220 ; CHECK-NEXT:    [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3
221 ; CHECK-NEXT:    [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4
222 ; CHECK-NEXT:    [[R_3:%.*]] = ashr i32 [[SRC_3]], 16
223 ; CHECK-NEXT:    [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3
224 ; CHECK-NEXT:    store i32 [[R_3]], ptr [[DST_GEP_3]], align 4
225 ; CHECK-NEXT:    [[SRC_GEP_5:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 5
226 ; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[SRC_GEP_5]], align 4
227 ; CHECK-NEXT:    call void @use(i32 [[L]])
228 ; CHECK-NEXT:    br label [[EXIT]]
229 ; CHECK:       exit:
230 ; CHECK-NEXT:    ret void
232 entry:
233   br i1 %c, label %then, label %exit
235 then:
236   %src.0 = load i32, ptr %src, align 4
237   %r.0 = ashr i32 %src.0, 16
238   store i32 %r.0, ptr %dst, align 4
239   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
240   %src.1 = load i32, ptr %src.gep.1, align 4
241   %r.1 = ashr i32 %src.1, 16
242   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
243   store i32 %r.1, ptr %dst.gep.1, align 4
244   %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2
245   %src.2 = load i32, ptr %src.gep.2, align 4
246   %r.2 = ashr i32 %src.2, 16
247   %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2
248   store i32 %r.2, ptr %dst.gep.2, align 4
249   %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3
250   %src.3 = load i32, ptr %src.gep.3, align 4
251   %r.3 = ashr i32 %src.3, 16
252   %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3
253   store i32 %r.3, ptr %dst.gep.3, align 4
254   %src.gep.5 = getelementptr inbounds i32, ptr %src, i64 5
255   %l = load i32, ptr %src.gep.5
256   call void @use(i32 %l)
257   br label %exit
259 exit:
260   ret void
263 define void @needs_versioning_profitable_load_used_outside_region2(ptr %dst, ptr %src, i1 %c) {
264 ; CHECK-LABEL: @needs_versioning_profitable_load_used_outside_region2(
265 ; CHECK-NEXT:  entry:
266 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
267 ; CHECK:       then:
268 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
269 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
270 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
271 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
272 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
273 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
274 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
275 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
276 ; CHECK-NEXT:    [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2
277 ; CHECK-NEXT:    [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4
278 ; CHECK-NEXT:    [[SRC_GEP_5:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 5
279 ; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[SRC_GEP_5]], align 4
280 ; CHECK-NEXT:    [[R_2:%.*]] = ashr i32 [[SRC_2]], 16
281 ; CHECK-NEXT:    [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
282 ; CHECK-NEXT:    store i32 [[R_2]], ptr [[DST_GEP_2]], align 4
283 ; CHECK-NEXT:    [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3
284 ; CHECK-NEXT:    [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4
285 ; CHECK-NEXT:    [[R_3:%.*]] = ashr i32 [[SRC_3]], 16
286 ; CHECK-NEXT:    [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3
287 ; CHECK-NEXT:    store i32 [[R_3]], ptr [[DST_GEP_3]], align 4
288 ; CHECK-NEXT:    call void @use(i32 [[L]])
289 ; CHECK-NEXT:    br label [[EXIT]]
290 ; CHECK:       exit:
291 ; CHECK-NEXT:    ret void
293 entry:
294   br i1 %c, label %then, label %exit
296 then:
297   %src.0 = load i32, ptr %src, align 4
298   %r.0 = ashr i32 %src.0, 16
299   store i32 %r.0, ptr %dst, align 4
300   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
301   %src.1 = load i32, ptr %src.gep.1, align 4
302   %r.1 = ashr i32 %src.1, 16
303   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
304   store i32 %r.1, ptr %dst.gep.1, align 4
305   %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2
306   %src.2 = load i32, ptr %src.gep.2, align 4
307   %src.gep.5 = getelementptr inbounds i32, ptr %src, i64 5
308   %l = load i32, ptr %src.gep.5
309   %r.2 = ashr i32 %src.2, 16
310   %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2
311   store i32 %r.2, ptr %dst.gep.2, align 4
312   %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3
313   %src.3 = load i32, ptr %src.gep.3, align 4
314   %r.3 = ashr i32 %src.3, 16
315   %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3
316   store i32 %r.3, ptr %dst.gep.3, align 4
317   call void @use(i32 %l)
318   br label %exit
320 exit:
321   ret void
324 define void @no_version(ptr nocapture %dst, ptr nocapture readonly %src) {
325 ; CHECK-LABEL: @no_version(
326 ; CHECK-NEXT:  entry:
327 ; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i32>, ptr [[SRC:%.*]], align 4
328 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i32> [[TMP0]], <i32 16, i32 16>
329 ; CHECK-NEXT:    store <2 x i32> [[TMP1]], ptr [[DST:%.*]], align 4
330 ; CHECK-NEXT:    ret void
332 entry:
333   %src.0 = load i32, ptr %src, align 4
334   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
335   %src.1 = load i32, ptr %src.gep.1, align 4
336   %r.0 = ashr i32 %src.0, 16
337   %r.1 = ashr i32 %src.1, 16
338   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
339   store i32 %r.0, ptr %dst, align 4
340   store i32 %r.1, ptr %dst.gep.1, align 4
341   ret void
344 define void @version_multiple(ptr nocapture %out_block, ptr nocapture readonly %counter) {
345 ; CHECK-LABEL: @version_multiple(
346 ; CHECK-NEXT:  entry:
347 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[COUNTER:%.*]], align 4
348 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[OUT_BLOCK:%.*]], align 4
349 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], [[TMP0]]
350 ; CHECK-NEXT:    store i32 [[XOR]], ptr [[OUT_BLOCK]], align 4
351 ; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr inbounds i32, ptr [[COUNTER]], i64 1
352 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX_1]], align 4
353 ; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr inbounds i32, ptr [[OUT_BLOCK]], i64 1
354 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX2_1]], align 4
355 ; CHECK-NEXT:    [[XOR_1:%.*]] = xor i32 [[TMP3]], [[TMP2]]
356 ; CHECK-NEXT:    store i32 [[XOR_1]], ptr [[ARRAYIDX2_1]], align 4
357 ; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr inbounds i32, ptr [[COUNTER]], i64 2
358 ; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX_2]], align 4
359 ; CHECK-NEXT:    [[ARRAYIDX2_2:%.*]] = getelementptr inbounds i32, ptr [[OUT_BLOCK]], i64 2
360 ; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX2_2]], align 4
361 ; CHECK-NEXT:    [[XOR_2:%.*]] = xor i32 [[TMP5]], [[TMP4]]
362 ; CHECK-NEXT:    store i32 [[XOR_2]], ptr [[ARRAYIDX2_2]], align 4
363 ; CHECK-NEXT:    [[ARRAYIDX_3:%.*]] = getelementptr inbounds i32, ptr [[COUNTER]], i64 3
364 ; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX_3]], align 4
365 ; CHECK-NEXT:    [[ARRAYIDX2_3:%.*]] = getelementptr inbounds i32, ptr [[OUT_BLOCK]], i64 3
366 ; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX2_3]], align 4
367 ; CHECK-NEXT:    [[XOR_3:%.*]] = xor i32 [[TMP7]], [[TMP6]]
368 ; CHECK-NEXT:    store i32 [[XOR_3]], ptr [[ARRAYIDX2_3]], align 4
369 ; CHECK-NEXT:    ret void
371 entry:
372   %0 = load i32, ptr %counter, align 4
373   %1 = load i32, ptr %out_block, align 4
374   %xor = xor i32 %1, %0
375   store i32 %xor, ptr %out_block, align 4
376   %arrayidx.1 = getelementptr inbounds i32, ptr %counter, i64 1
377   %2 = load i32, ptr %arrayidx.1, align 4
378   %arrayidx2.1 = getelementptr inbounds i32, ptr %out_block, i64 1
379   %3 = load i32, ptr %arrayidx2.1, align 4
380   %xor.1 = xor i32 %3, %2
381   store i32 %xor.1, ptr %arrayidx2.1, align 4
382   %arrayidx.2 = getelementptr inbounds i32, ptr %counter, i64 2
383   %4 = load i32, ptr %arrayidx.2, align 4
384   %arrayidx2.2 = getelementptr inbounds i32, ptr %out_block, i64 2
385   %5 = load i32, ptr %arrayidx2.2, align 4
386   %xor.2 = xor i32 %5, %4
387   store i32 %xor.2, ptr %arrayidx2.2, align 4
388   %arrayidx.3 = getelementptr inbounds i32, ptr %counter, i64 3
389   %6 = load i32, ptr %arrayidx.3, align 4
390   %arrayidx2.3 = getelementptr inbounds i32, ptr %out_block, i64 3
391   %7 = load i32, ptr %arrayidx2.3, align 4
392   %xor.3 = xor i32 %7, %6
393   store i32 %xor.3, ptr %arrayidx2.3, align 4
394   ret void
397 define i32 @use_outside_version_bb(ptr %dst, ptr %src, i1 %c.1) {
398 ; CHECK-LABEL: @use_outside_version_bb(
399 ; CHECK-NEXT:  entry:
400 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
401 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
402 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
403 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
404 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
405 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
406 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
407 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
408 ; CHECK-NEXT:    br label [[EXIT:%.*]]
409 ; CHECK:       exit:
410 ; CHECK-NEXT:    ret i32 [[R_0]]
412 entry:
413   %src.0 = load i32, ptr %src, align 4
414   %r.0 = ashr i32 %src.0, 16
415   store i32 %r.0, ptr %dst, align 4
416   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
417   %src.1 = load i32, ptr %src.gep.1, align 4
418   %r.1 = ashr i32 %src.1, 16
419   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
420   store i32 %r.1, ptr %dst.gep.1, align 4
421   br label %exit
423 exit:
424   ret i32 %r.0
427 define i32 @value_used_in_return(ptr %dst, ptr %src, i32 %x) {
428 ; CHECK-LABEL: @value_used_in_return(
429 ; CHECK-NEXT:  entry:
430 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
431 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
432 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
433 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
434 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
435 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
436 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
437 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
438 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X:%.*]], 20
439 ; CHECK-NEXT:    ret i32 [[ADD]]
441 entry:
442   %src.0 = load i32, ptr %src, align 4
443   %r.0 = ashr i32 %src.0, 16
444   store i32 %r.0, ptr %dst, align 4
445   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
446   %src.1 = load i32, ptr %src.gep.1, align 4
447   %r.1 = ashr i32 %src.1, 16
448   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
449   store i32 %r.1, ptr %dst.gep.1, align 4
450   %add = add i32 %x, 20
451   ret i32 %add
453 define i32 @needs_versioning2_cond_br(ptr %dst, ptr %src, i1 %c.1) {
454 ; CHECK-LABEL: @needs_versioning2_cond_br(
455 ; CHECK-NEXT:  entry:
456 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
457 ; CHECK:       then:
458 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4
459 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
460 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
461 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
462 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
463 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
464 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
465 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
466 ; CHECK-NEXT:    ret i32 10
467 ; CHECK:       else:
468 ; CHECK-NEXT:    ret i32 0
470 entry:
471   br i1 %c.1, label %then, label %else
473 then:
474   %src.0 = load i32, ptr %src, align 4
475   %r.0 = ashr i32 %src.0, 16
476   store i32 %r.0, ptr %dst, align 4
477   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
478   %src.1 = load i32, ptr %src.gep.1, align 4
479   %r.1 = ashr i32 %src.1, 16
480   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
481   store i32 %r.1, ptr %dst.gep.1, align 4
482   ret i32 10
485 else:
486   ret i32 0
489 define void @pointer_defined_in_bb(ptr %dst, ptr %src.p) {
490 ; CHECK-LABEL: @pointer_defined_in_bb(
491 ; CHECK-NEXT:  entry:
492 ; CHECK-NEXT:    [[SRC:%.*]] = load ptr, ptr [[SRC_P:%.*]], align 8
493 ; CHECK-NEXT:    [[SRC_0:%.*]] = load i32, ptr [[SRC]], align 4
494 ; CHECK-NEXT:    [[R_0:%.*]] = ashr i32 [[SRC_0]], 16
495 ; CHECK-NEXT:    store i32 [[R_0]], ptr [[DST:%.*]], align 4
496 ; CHECK-NEXT:    [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
497 ; CHECK-NEXT:    [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4
498 ; CHECK-NEXT:    [[R_1:%.*]] = ashr i32 [[SRC_1]], 16
499 ; CHECK-NEXT:    [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1
500 ; CHECK-NEXT:    store i32 [[R_1]], ptr [[DST_GEP_1]], align 4
501 ; CHECK-NEXT:    ret void
503 entry:
504   %src = load ptr, ptr %src.p
505   %src.0 = load i32, ptr %src, align 4
506   %r.0 = ashr i32 %src.0, 16
507   store i32 %r.0, ptr %dst, align 4
508   %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1
509   %src.1 = load i32, ptr %src.gep.1, align 4
510   %r.1 = ashr i32 %src.1, 16
511   %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1
512   store i32 %r.1, ptr %dst.gep.1, align 4
513   ret void
516 define void @clobber_same_underlying_object(ptr %this) {
517 ; CHECK-LABEL: @clobber_same_underlying_object(
518 ; CHECK-NEXT:  entry:
519 ; CHECK-NEXT:    [[P_3:%.*]] = getelementptr inbounds i32, ptr [[THIS:%.*]], i32 3
520 ; CHECK-NEXT:    store i32 10, ptr [[P_3]], align 8
521 ; CHECK-NEXT:    tail call void @clobber()
522 ; CHECK-NEXT:    [[P_4:%.*]] = getelementptr inbounds i32, ptr [[THIS]], i32 4
523 ; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[P_4]], align 8
524 ; CHECK-NEXT:    store i32 20, ptr [[P_4]], align 8
525 ; CHECK-NEXT:    ret void
527 entry:
528   %p.3 = getelementptr inbounds i32, ptr %this, i32 3
529   store i32 10, ptr %p.3, align 8
530   tail call void @clobber()
531   %p.4 = getelementptr inbounds i32, ptr %this, i32 4
532   %l2 = load i32, ptr %p.4, align 8
533   store i32 20, ptr %p.4, align 8
534   ret void
537 declare void @clobber()
539 define void @slp_not_beneficial(ptr %A, ptr %B) {
540 ; CHECK-LABEL: @slp_not_beneficial(
541 ; CHECK-NEXT:  bb:
542 ; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 4
543 ; CHECK-NEXT:    store i32 0, ptr [[TMP]], align 8
544 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 5
545 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 4
546 ; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 8
547 ; CHECK-NEXT:    store i32 [[TMP5]], ptr [[TMP3]], align 8
548 ; CHECK-NEXT:    ret void
551   %tmp = getelementptr inbounds i32, ptr %A, i32 4
552   store i32 0, ptr %tmp, align 8
553   %tmp3 = getelementptr inbounds i32, ptr %A, i32 5
554   %tmp4 = getelementptr inbounds i32, ptr %B, i32 4
555   %tmp5 = load i32, ptr %tmp4, align 8
556   store i32 %tmp5, ptr %tmp3, align 8
557   ret void
560 define void @widget(ptr %ptr, ptr %ptr.2) {
561 ; CHECK-LABEL: @widget(
562 ; CHECK-NEXT:  bb1:
563 ; CHECK-NEXT:    [[TMP3:%.*]] = load double, ptr null, align 8
564 ; CHECK-NEXT:    [[TMP4:%.*]] = fmul double undef, [[TMP3]]
565 ; CHECK-NEXT:    [[TMP6:%.*]] = load double, ptr [[PTR:%.*]], align 8
566 ; CHECK-NEXT:    [[TMP7:%.*]] = fadd double [[TMP6]], [[TMP4]]
567 ; CHECK-NEXT:    store double [[TMP7]], ptr [[PTR]], align 8
568 ; CHECK-NEXT:    [[TMP9:%.*]] = load double, ptr [[PTR_2:%.*]], align 8
569 ; CHECK-NEXT:    [[TMP10:%.*]] = fmul double undef, [[TMP9]]
570 ; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds double, ptr [[PTR]], i32 1
571 ; CHECK-NEXT:    [[TMP12:%.*]] = load double, ptr [[TMP11]], align 8
572 ; CHECK-NEXT:    [[TMP13:%.*]] = fadd double [[TMP12]], [[TMP10]]
573 ; CHECK-NEXT:    store double [[TMP13]], ptr [[TMP11]], align 8
574 ; CHECK-NEXT:    br label [[BB15:%.*]]
575 ; CHECK:       bb15:
576 ; CHECK-NEXT:    br label [[BB15]]
578 bb1:                                              ; preds = %bb
579   %tmp3 = load double, ptr null, align 8
580   %tmp4 = fmul double undef, %tmp3
581   %tmp6 = load double, ptr %ptr, align 8
582   %tmp7 = fadd double %tmp6, %tmp4
583   store double %tmp7, ptr %ptr, align 8
584   %tmp9 = load double, ptr %ptr.2, align 8
585   %tmp10 = fmul double undef, %tmp9
586   %tmp11 = getelementptr inbounds double, ptr %ptr, i32 1
587   %tmp12 = load double, ptr %tmp11, align 8
588   %tmp13 = fadd double %tmp12, %tmp10
589   store double %tmp13, ptr %tmp11, align 8
590   br label %bb15
592 bb15:                                             ; preds = %bb15, %bb14
593   br label %bb15
596 %struct = type { i32, i32, float, float }
598 ; Some points we collected as candidates for runtime checks have been removed
599 ; before generating runtime checks. Make sure versioning is skipped.
600 define void @test_bounds_removed_before_runtime_checks(ptr %A, ptr %B, i1 %c) {
601 ; CHECK-LABEL: @test_bounds_removed_before_runtime_checks(
602 ; CHECK-NEXT:  entry:
603 ; CHECK-NEXT:    store <2 x i32> <i32 10, i32 300>, ptr [[A:%.*]], align 8
604 ; CHECK-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[B:%.*]], align 8
605 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB23:%.*]], label [[BB14:%.*]]
606 ; CHECK:       bb14:
607 ; CHECK-NEXT:    [[TMP15:%.*]] = sext i32 10 to i64
608 ; CHECK-NEXT:    [[TMP16:%.*]] = add nsw i64 2, [[TMP15]]
609 ; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 [[TMP16]]
610 ; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 3
611 ; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [[STRUCT:%.*]], ptr [[A]], i64 0, i32 2
612 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[TMP20]], align 8
613 ; CHECK-NEXT:    [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1
614 ; CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT]], ptr [[A]], i64 0, i32 3
615 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[TMP22]], align 4
616 ; CHECK-NEXT:    br label [[BB23]]
617 ; CHECK:       bb23:
618 ; CHECK-NEXT:    ret void
620 entry:
621   %tmp1 = fmul float 10.0, 20.0
622   %tmp2 = fptosi float %tmp1 to i32
623   %tmp3 = fmul float 30.0, 20.0
624   %tmp4 = fptosi float %tmp3 to i32
625   %tmp5 = icmp sgt i32 100, %tmp2
626   %tmp6 = select i1 %tmp5, i32 %tmp2, i32 10
627   %tmp7 = select i1 false, i32 0, i32 %tmp6
628   %tmp8 = icmp sgt i32 200, %tmp4
629   %tmp9 = select i1 %tmp8, i32 %tmp4, i32 300
630   %tmp10 = select i1 false, i32 0, i32 %tmp9
631   store i32 %tmp7, ptr %A, align 8
632   %tmp12 = getelementptr inbounds %struct, ptr %A, i64 0, i32 1
633   store i32 %tmp10, ptr %tmp12, align 4
634   %tmp13 = load ptr, ptr %B, align 8
635   br i1 %c, label %bb23, label %bb14
637 bb14:
638   %tmp15 = sext i32 %tmp7 to i64
639   %tmp16 = add nsw i64 2, %tmp15
640   %tmp17 = getelementptr inbounds i32, ptr %tmp13, i64 %tmp16
641   %tmp19 = getelementptr inbounds i8, ptr %tmp17, i64 3
642   %tmp20 = getelementptr inbounds %struct, ptr %A, i64 0, i32 2
643   store float 0.0, ptr %tmp20, align 8
644   %tmp21 = load i8, ptr %tmp19, align 1
645   %tmp22 = getelementptr inbounds %struct, ptr %A, i64 0, i32 3
646   store float 0.0, ptr %tmp22, align 4
647   br label %bb23
649 bb23:
650   ret void
653 ; In this test there's a single bound, do not generate runtime checks.
654 define void @single_membound(ptr %arg, ptr %arg1, double %x) {
655 ; CHECK-LABEL: @single_membound(
656 ; CHECK-NEXT:  entry:
657 ; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds double, ptr [[ARG:%.*]], i64 1
658 ; CHECK-NEXT:    [[TMP:%.*]] = fsub double [[X:%.*]], 9.900000e+01
659 ; CHECK-NEXT:    store double [[TMP]], ptr [[TMP9]], align 8
660 ; CHECK-NEXT:    [[TMP12:%.*]] = load double, ptr [[ARG1:%.*]], align 8
661 ; CHECK-NEXT:    [[TMP13:%.*]] = fsub double 1.000000e+00, [[TMP12]]
662 ; CHECK-NEXT:    br label [[BB15:%.*]]
663 ; CHECK:       bb15:
664 ; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x double> poison, double [[TMP]], i32 0
665 ; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[TMP13]], i32 1
666 ; CHECK-NEXT:    [[TMP2:%.*]] = fmul <2 x double> [[TMP1]], <double 2.000000e+01, double 3.000000e+01>
667 ; CHECK-NEXT:    store <2 x double> [[TMP2]], ptr [[TMP9]], align 8
668 ; CHECK-NEXT:    ret void
670 entry:
671   %tmp = fsub double %x, 99.0
672   %tmp9 = getelementptr inbounds double, ptr %arg, i64 1
673   store double %tmp, ptr %tmp9, align 8
674   %tmp12 = load double, ptr %arg1, align 8
675   %tmp13 = fsub double 1.0, %tmp12
676   %tmp14 = getelementptr inbounds double, ptr %arg, i64 2
677   br label %bb15
679 bb15:
680   %tmp16 = fmul double %tmp, 20.0
681   store double %tmp16, ptr %tmp9, align 8
682   %tmp17 = fmul double %tmp13, 30.0
683   store double %tmp17, ptr %tmp14, align 8
684   ret void
687 %struct.2 = type { [4 x float] }
689 ; Make sure we do not crash when we encounter a SCEVCouldNotCompute.
690 define void @no_lcssa_phi(ptr %A, ptr %B, i1 %c) {
691 ; CHECK-LABEL: @no_lcssa_phi(
692 ; CHECK-NEXT:  bb:
693 ; CHECK-NEXT:    br label [[LOOP:%.*]]
694 ; CHECK:       loop:
695 ; CHECK-NEXT:    [[PTR_PHI:%.*]] = phi ptr [ [[A:%.*]], [[BB:%.*]] ], [ null, [[LOOP]] ]
696 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
697 ; CHECK:       exit:
698 ; CHECK-NEXT:    [[L_0:%.*]] = load float, ptr [[B:%.*]], align 8
699 ; CHECK-NEXT:    [[ADD_0:%.*]] = fadd float [[L_0]], 1.000000e+01
700 ; CHECK-NEXT:    [[MUL_0:%.*]] = fmul float [[ADD_0]], 3.000000e+01
701 ; CHECK-NEXT:    store float [[MUL_0]], ptr [[PTR_PHI]], align 8
702 ; CHECK-NEXT:    [[B_GEP_1:%.*]] = getelementptr inbounds float, ptr [[B]], i64 1
703 ; CHECK-NEXT:    [[L_1:%.*]] = load float, ptr [[B_GEP_1]], align 8
704 ; CHECK-NEXT:    [[ADD_1:%.*]] = fadd float [[L_1]], 1.000000e+01
705 ; CHECK-NEXT:    [[MUL_1:%.*]] = fmul float [[ADD_1]], 3.000000e+01
706 ; CHECK-NEXT:    [[A_GEP_1:%.*]] = getelementptr inbounds [[STRUCT_2:%.*]], ptr [[PTR_PHI]], i64 0, i32 0, i32 1
707 ; CHECK-NEXT:    store float [[MUL_1]], ptr [[A_GEP_1]], align 8
708 ; CHECK-NEXT:    [[B_GEP_2:%.*]] = getelementptr inbounds float, ptr [[B]], i64 2
709 ; CHECK-NEXT:    [[L_2:%.*]] = load float, ptr [[B_GEP_2]], align 8
710 ; CHECK-NEXT:    [[ADD_2:%.*]] = fadd float [[L_2]], 1.000000e+01
711 ; CHECK-NEXT:    [[MUL_2:%.*]] = fmul float [[ADD_2]], 3.000000e+01
712 ; CHECK-NEXT:    [[A_GEP_2:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI]], i64 0, i32 0, i32 2
713 ; CHECK-NEXT:    store float [[MUL_2]], ptr [[A_GEP_2]], align 8
714 ; CHECK-NEXT:    [[B_GEP_3:%.*]] = getelementptr inbounds float, ptr [[B]], i64 3
715 ; CHECK-NEXT:    [[L_3:%.*]] = load float, ptr [[B_GEP_3]], align 8
716 ; CHECK-NEXT:    [[ADD_3:%.*]] = fadd float [[L_3]], 1.000000e+01
717 ; CHECK-NEXT:    [[MUL_3:%.*]] = fmul float [[ADD_3]], 3.000000e+01
718 ; CHECK-NEXT:    [[A_GEP_3:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI]], i64 0, i32 0, i32 3
719 ; CHECK-NEXT:    store float [[MUL_3]], ptr [[A_GEP_3]], align 8
720 ; CHECK-NEXT:    ret void
723   br label %loop
725 loop:
726   %ptr.phi = phi ptr [ %A, %bb ], [ null, %loop ]
727   br i1 %c, label %exit, label %loop
729 exit:
730   %l.0 = load float, ptr %B, align 8
731   %add.0 = fadd float %l.0, 10.0
732   %mul.0 = fmul float %add.0, 30.0
733   store float %mul.0, ptr %ptr.phi, align 8
734   %B.gep.1 = getelementptr inbounds float, ptr %B, i64 1
735   %l.1 = load float, ptr %B.gep.1, align 8
736   %add.1 = fadd float %l.1, 10.0
737   %mul.1 = fmul float %add.1, 30.0
738   %A.gep.1 = getelementptr inbounds %struct.2, ptr %ptr.phi, i64 0, i32 0, i32 1
739   store float %mul.1, ptr %A.gep.1, align 8
740   %B.gep.2 = getelementptr inbounds float, ptr %B, i64 2
741   %l.2 = load float, ptr %B.gep.2, align 8
742   %add.2 = fadd float %l.2, 10.0
743   %mul.2 = fmul float %add.2, 30.0
744   %A.gep.2 = getelementptr inbounds %struct.2, ptr %ptr.phi, i64 0, i32 0, i32 2
745   store float %mul.2, ptr %A.gep.2, align 8
746   %B.gep.3 = getelementptr inbounds float, ptr %B, i64 3
747   %l.3 = load float, ptr %B.gep.3, align 8
748   %add.3 = fadd float %l.3, 10.0
749   %mul.3 = fmul float %add.3, 30.0
750   %A.gep.3 = getelementptr inbounds %struct.2, ptr %ptr.phi, i64 0, i32 0, i32 3
751   store float %mul.3, ptr %A.gep.3, align 8
752   ret void
755 ; Make sure lcssa phis as pointer bases are handled properly.
756 define void @lcssa_phi(ptr %A, ptr %B, i1 %c) {
757 ; CHECK-LABEL: @lcssa_phi(
758 ; CHECK-NEXT:  bb:
759 ; CHECK-NEXT:    br label [[LOOP:%.*]]
760 ; CHECK:       loop:
761 ; CHECK-NEXT:    [[PTR_PHI:%.*]] = phi ptr [ [[A:%.*]], [[BB:%.*]] ], [ null, [[LOOP]] ]
762 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
763 ; CHECK:       exit:
764 ; CHECK-NEXT:    [[PTR_PHI_LCSSA:%.*]] = phi ptr [ [[PTR_PHI]], [[LOOP]] ]
765 ; CHECK-NEXT:    [[L_0:%.*]] = load float, ptr [[B:%.*]], align 8
766 ; CHECK-NEXT:    [[ADD_0:%.*]] = fadd float [[L_0]], 1.000000e+01
767 ; CHECK-NEXT:    [[MUL_0:%.*]] = fmul float [[ADD_0]], 3.000000e+01
768 ; CHECK-NEXT:    store float [[MUL_0]], ptr [[PTR_PHI_LCSSA]], align 8
769 ; CHECK-NEXT:    [[B_GEP_1:%.*]] = getelementptr inbounds float, ptr [[B]], i64 1
770 ; CHECK-NEXT:    [[L_1:%.*]] = load float, ptr [[B_GEP_1]], align 8
771 ; CHECK-NEXT:    [[ADD_1:%.*]] = fadd float [[L_1]], 1.000000e+01
772 ; CHECK-NEXT:    [[MUL_1:%.*]] = fmul float [[ADD_1]], 3.000000e+01
773 ; CHECK-NEXT:    [[A_GEP_1:%.*]] = getelementptr inbounds [[STRUCT_2:%.*]], ptr [[PTR_PHI_LCSSA]], i64 0, i32 0, i32 1
774 ; CHECK-NEXT:    store float [[MUL_1]], ptr [[A_GEP_1]], align 8
775 ; CHECK-NEXT:    [[B_GEP_2:%.*]] = getelementptr inbounds float, ptr [[B]], i64 2
776 ; CHECK-NEXT:    [[L_2:%.*]] = load float, ptr [[B_GEP_2]], align 8
777 ; CHECK-NEXT:    [[ADD_2:%.*]] = fadd float [[L_2]], 1.000000e+01
778 ; CHECK-NEXT:    [[MUL_2:%.*]] = fmul float [[ADD_2]], 3.000000e+01
779 ; CHECK-NEXT:    [[A_GEP_2:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI_LCSSA]], i64 0, i32 0, i32 2
780 ; CHECK-NEXT:    store float [[MUL_2]], ptr [[A_GEP_2]], align 8
781 ; CHECK-NEXT:    [[B_GEP_3:%.*]] = getelementptr inbounds float, ptr [[B]], i64 3
782 ; CHECK-NEXT:    [[L_3:%.*]] = load float, ptr [[B_GEP_3]], align 8
783 ; CHECK-NEXT:    [[ADD_3:%.*]] = fadd float [[L_3]], 1.000000e+01
784 ; CHECK-NEXT:    [[MUL_3:%.*]] = fmul float [[ADD_3]], 3.000000e+01
785 ; CHECK-NEXT:    [[A_GEP_3:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI_LCSSA]], i64 0, i32 0, i32 3
786 ; CHECK-NEXT:    store float [[MUL_3]], ptr [[A_GEP_3]], align 8
787 ; CHECK-NEXT:    ret void
790   br label %loop
792 loop:
793   %ptr.phi = phi ptr [ %A, %bb ], [ null, %loop ]
794   br i1 %c, label %exit, label %loop
796 exit:
797   %ptr.phi.lcssa = phi ptr [ %ptr.phi, %loop ]
798   %l.0 = load float, ptr %B, align 8
799   %add.0 = fadd float %l.0, 10.0
800   %mul.0 = fmul float %add.0, 30.0
801   store float %mul.0, ptr %ptr.phi.lcssa, align 8
802   %B.gep.1 = getelementptr inbounds float, ptr %B, i64 1
803   %l.1 = load float, ptr %B.gep.1, align 8
804   %add.1 = fadd float %l.1, 10.0
805   %mul.1 = fmul float %add.1, 30.0
806   %A.gep.1 = getelementptr inbounds %struct.2, ptr %ptr.phi.lcssa, i64 0, i32 0, i32 1
807   store float %mul.1, ptr %A.gep.1, align 8
808   %B.gep.2 = getelementptr inbounds float, ptr %B, i64 2
809   %l.2 = load float, ptr %B.gep.2, align 8
810   %add.2 = fadd float %l.2, 10.0
811   %mul.2 = fmul float %add.2, 30.0
812   %A.gep.2 = getelementptr inbounds %struct.2, ptr %ptr.phi.lcssa, i64 0, i32 0, i32 2
813   store float %mul.2, ptr %A.gep.2, align 8
814   %B.gep.3 = getelementptr inbounds float, ptr %B, i64 3
815   %l.3 = load float, ptr %B.gep.3, align 8
816   %add.3 = fadd float %l.3, 10.0
817   %mul.3 = fmul float %add.3, 30.0
818   %A.gep.3 = getelementptr inbounds %struct.2, ptr %ptr.phi.lcssa, i64 0, i32 0, i32 3
819   store float %mul.3, ptr %A.gep.3, align 8
820   ret void
823 %struct.spam = type { [60 x i32], i32, [12 x i8] }
825 declare void @foo(ptr)
827 ; Test case with a basic block where parts can be vectorized without versioning.
828 define i32 @block_partly_vectorized_without_versioning(ptr readonly %arg, ptr nocapture readonly %arg1, ptr nocapture %arg2, ptr nocapture readonly %arg3, ptr %A, ptr %B) {
829 ; CHECK-LABEL: @block_partly_vectorized_without_versioning(
830 ; CHECK-NEXT:  bb:
831 ; CHECK-NEXT:    [[T:%.*]] = alloca <16 x i8>, align 16
832 ; CHECK-NEXT:    [[T5:%.*]] = getelementptr inbounds i8, ptr [[ARG3:%.*]], i64 1
833 ; CHECK-NEXT:    [[T6:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 2
834 ; CHECK-NEXT:    [[T7:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 3
835 ; CHECK-NEXT:    [[T8:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 4
836 ; CHECK-NEXT:    [[T9:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 5
837 ; CHECK-NEXT:    [[T10:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 6
838 ; CHECK-NEXT:    [[T11:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 7
839 ; CHECK-NEXT:    [[T12:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 8
840 ; CHECK-NEXT:    [[T13:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 9
841 ; CHECK-NEXT:    [[T14:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 10
842 ; CHECK-NEXT:    [[T15:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 11
843 ; CHECK-NEXT:    [[T16:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 12
844 ; CHECK-NEXT:    [[T17:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 13
845 ; CHECK-NEXT:    [[T18:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 14
846 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[A:%.*]], align 1
847 ; CHECK-NEXT:    [[TMP1:%.*]] = load <16 x i8>, ptr [[B:%.*]], align 1
848 ; CHECK-NEXT:    [[TMP2:%.*]] = xor <16 x i8> [[TMP0]], [[TMP1]]
849 ; CHECK-NEXT:    store <16 x i8> [[TMP2]], ptr [[ARG1:%.*]], align 1
850 ; CHECK-NEXT:    [[T21:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 15
851 ; CHECK-NEXT:    call void @foo(ptr nonnull [[T]])
852 ; CHECK-NEXT:    [[T26:%.*]] = load i8, ptr [[ARG3]], align 1
853 ; CHECK-NEXT:    [[T27:%.*]] = load i8, ptr [[ARG2:%.*]], align 1
854 ; CHECK-NEXT:    [[T28:%.*]] = xor i8 [[T27]], [[T26]]
855 ; CHECK-NEXT:    store i8 [[T28]], ptr [[ARG2]], align 1
856 ; CHECK-NEXT:    [[T29:%.*]] = load i8, ptr [[T5]], align 1
857 ; CHECK-NEXT:    [[T30:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 1
858 ; CHECK-NEXT:    [[T31:%.*]] = load i8, ptr [[T30]], align 1
859 ; CHECK-NEXT:    [[T32:%.*]] = xor i8 [[T31]], [[T29]]
860 ; CHECK-NEXT:    store i8 [[T32]], ptr [[T30]], align 1
861 ; CHECK-NEXT:    [[T33:%.*]] = load i8, ptr [[T6]], align 1
862 ; CHECK-NEXT:    [[T34:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 2
863 ; CHECK-NEXT:    [[T35:%.*]] = load i8, ptr [[T34]], align 1
864 ; CHECK-NEXT:    [[T36:%.*]] = xor i8 [[T35]], [[T33]]
865 ; CHECK-NEXT:    store i8 [[T36]], ptr [[T34]], align 1
866 ; CHECK-NEXT:    [[T37:%.*]] = load i8, ptr [[T7]], align 1
867 ; CHECK-NEXT:    [[T38:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 3
868 ; CHECK-NEXT:    [[T39:%.*]] = load i8, ptr [[T38]], align 1
869 ; CHECK-NEXT:    [[T40:%.*]] = xor i8 [[T39]], [[T37]]
870 ; CHECK-NEXT:    store i8 [[T40]], ptr [[T38]], align 1
871 ; CHECK-NEXT:    [[T41:%.*]] = load i8, ptr [[T8]], align 1
872 ; CHECK-NEXT:    [[T42:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 4
873 ; CHECK-NEXT:    [[T43:%.*]] = load i8, ptr [[T42]], align 1
874 ; CHECK-NEXT:    [[T44:%.*]] = xor i8 [[T43]], [[T41]]
875 ; CHECK-NEXT:    store i8 [[T44]], ptr [[T42]], align 1
876 ; CHECK-NEXT:    [[T45:%.*]] = load i8, ptr [[T9]], align 1
877 ; CHECK-NEXT:    [[T46:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 5
878 ; CHECK-NEXT:    [[T47:%.*]] = load i8, ptr [[T46]], align 1
879 ; CHECK-NEXT:    [[T48:%.*]] = xor i8 [[T47]], [[T45]]
880 ; CHECK-NEXT:    store i8 [[T48]], ptr [[T46]], align 1
881 ; CHECK-NEXT:    [[T49:%.*]] = load i8, ptr [[T10]], align 1
882 ; CHECK-NEXT:    [[T50:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 6
883 ; CHECK-NEXT:    [[T51:%.*]] = load i8, ptr [[T50]], align 1
884 ; CHECK-NEXT:    [[T52:%.*]] = xor i8 [[T51]], [[T49]]
885 ; CHECK-NEXT:    store i8 [[T52]], ptr [[T50]], align 1
886 ; CHECK-NEXT:    [[T53:%.*]] = load i8, ptr [[T11]], align 1
887 ; CHECK-NEXT:    [[T54:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 7
888 ; CHECK-NEXT:    [[T55:%.*]] = load i8, ptr [[T54]], align 1
889 ; CHECK-NEXT:    [[T56:%.*]] = xor i8 [[T55]], [[T53]]
890 ; CHECK-NEXT:    store i8 [[T56]], ptr [[T54]], align 1
891 ; CHECK-NEXT:    [[T57:%.*]] = load i8, ptr [[T12]], align 1
892 ; CHECK-NEXT:    [[T58:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 8
893 ; CHECK-NEXT:    [[T59:%.*]] = load i8, ptr [[T58]], align 1
894 ; CHECK-NEXT:    [[T60:%.*]] = xor i8 [[T59]], [[T57]]
895 ; CHECK-NEXT:    store i8 [[T60]], ptr [[T58]], align 1
896 ; CHECK-NEXT:    [[T61:%.*]] = load i8, ptr [[T13]], align 1
897 ; CHECK-NEXT:    [[T62:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 9
898 ; CHECK-NEXT:    [[T63:%.*]] = load i8, ptr [[T62]], align 1
899 ; CHECK-NEXT:    [[T64:%.*]] = xor i8 [[T63]], [[T61]]
900 ; CHECK-NEXT:    store i8 [[T64]], ptr [[T62]], align 1
901 ; CHECK-NEXT:    [[T65:%.*]] = load i8, ptr [[T14]], align 1
902 ; CHECK-NEXT:    [[T66:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 10
903 ; CHECK-NEXT:    [[T67:%.*]] = load i8, ptr [[T66]], align 1
904 ; CHECK-NEXT:    [[T68:%.*]] = xor i8 [[T67]], [[T65]]
905 ; CHECK-NEXT:    store i8 [[T68]], ptr [[T66]], align 1
906 ; CHECK-NEXT:    [[T69:%.*]] = load i8, ptr [[T15]], align 1
907 ; CHECK-NEXT:    [[T70:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 11
908 ; CHECK-NEXT:    [[T71:%.*]] = load i8, ptr [[T70]], align 1
909 ; CHECK-NEXT:    [[T72:%.*]] = xor i8 [[T71]], [[T69]]
910 ; CHECK-NEXT:    store i8 [[T72]], ptr [[T70]], align 1
911 ; CHECK-NEXT:    [[T73:%.*]] = load i8, ptr [[T16]], align 1
912 ; CHECK-NEXT:    [[T74:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 12
913 ; CHECK-NEXT:    [[T75:%.*]] = load i8, ptr [[T74]], align 1
914 ; CHECK-NEXT:    [[T76:%.*]] = xor i8 [[T75]], [[T73]]
915 ; CHECK-NEXT:    store i8 [[T76]], ptr [[T74]], align 1
916 ; CHECK-NEXT:    [[T77:%.*]] = load i8, ptr [[T17]], align 1
917 ; CHECK-NEXT:    [[T78:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 13
918 ; CHECK-NEXT:    [[T79:%.*]] = load i8, ptr [[T78]], align 1
919 ; CHECK-NEXT:    [[T80:%.*]] = xor i8 [[T79]], [[T77]]
920 ; CHECK-NEXT:    store i8 [[T80]], ptr [[T78]], align 1
921 ; CHECK-NEXT:    [[T81:%.*]] = load i8, ptr [[T18]], align 1
922 ; CHECK-NEXT:    [[T82:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 14
923 ; CHECK-NEXT:    [[T83:%.*]] = load i8, ptr [[T82]], align 1
924 ; CHECK-NEXT:    [[T84:%.*]] = xor i8 [[T83]], [[T81]]
925 ; CHECK-NEXT:    store i8 [[T84]], ptr [[T82]], align 1
926 ; CHECK-NEXT:    [[T85:%.*]] = load i8, ptr [[T21]], align 1
927 ; CHECK-NEXT:    [[T86:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 15
928 ; CHECK-NEXT:    [[T87:%.*]] = load i8, ptr [[T86]], align 1
929 ; CHECK-NEXT:    [[T88:%.*]] = xor i8 [[T87]], [[T85]]
930 ; CHECK-NEXT:    store i8 [[T88]], ptr [[T86]], align 1
931 ; CHECK-NEXT:    ret i32 1
934   %t = alloca <16 x i8>, align 16
935   %t5 = getelementptr inbounds i8, ptr %arg3, i64 1
936   %t6 = getelementptr inbounds i8, ptr %arg3, i64 2
937   %t7 = getelementptr inbounds i8, ptr %arg3, i64 3
938   %t8 = getelementptr inbounds i8, ptr %arg3, i64 4
939   %t9 = getelementptr inbounds i8, ptr %arg3, i64 5
940   %t10 = getelementptr inbounds i8, ptr %arg3, i64 6
941   %t11 = getelementptr inbounds i8, ptr %arg3, i64 7
942   %t12 = getelementptr inbounds i8, ptr %arg3, i64 8
943   %t13 = getelementptr inbounds i8, ptr %arg3, i64 9
944   %t14 = getelementptr inbounds i8, ptr %arg3, i64 10
945   %t15 = getelementptr inbounds i8, ptr %arg3, i64 11
946   %t16 = getelementptr inbounds i8, ptr %arg3, i64 12
947   %t17 = getelementptr inbounds i8, ptr %arg3, i64 13
948   %t18 = getelementptr inbounds i8, ptr %arg3, i64 14
949   %A.0 = load i8, ptr %A
950   %B.0 = load i8, ptr %B
951   %xor.0 = xor i8 %A.0, %B.0
952   %A.gep.1 = getelementptr i8, ptr %A, i64 1
953   %A.1 = load i8, ptr %A.gep.1
954   %B.gep.1 = getelementptr i8, ptr %B, i64 1
955   %B.1 = load i8, ptr %B.gep.1
956   %xor.1 = xor i8 %A.1, %B.1
957   %A.gep.2 = getelementptr i8, ptr %A, i64 2
958   %A.2 = load i8, ptr %A.gep.2
959   %B.gep.2 = getelementptr i8, ptr %B, i64 2
960   %B.2 = load i8, ptr %B.gep.2
961   %xor.2 = xor i8 %A.2, %B.2
962   %A.gep.3 = getelementptr i8, ptr %A, i64 3
963   %A.3 = load i8, ptr %A.gep.3
964   %B.gep.3 = getelementptr i8, ptr %B, i64 3
965   %B.3 = load i8, ptr %B.gep.3
966   %xor.3 = xor i8 %A.3, %B.3
967   %A.gep.4 = getelementptr i8, ptr %A, i64 4
968   %A.4 = load i8, ptr %A.gep.4
969   %B.gep.4 = getelementptr i8, ptr %B, i64 4
970   %B.4 = load i8, ptr %B.gep.4
971   %xor.4 = xor i8 %A.4, %B.4
972   %A.gep.5 = getelementptr i8, ptr %A, i64 5
973   %A.5 = load i8, ptr %A.gep.5
974   %B.gep.5 = getelementptr i8, ptr %B, i64 5
975   %B.5 = load i8, ptr %B.gep.5
976   %xor.5 = xor i8 %A.5, %B.5
977   %A.gep.6 = getelementptr i8, ptr %A, i64 6
978   %A.6 = load i8, ptr %A.gep.6
979   %B.gep.6 = getelementptr i8, ptr %B, i64 6
980   %B.6 = load i8, ptr %B.gep.6
981   %xor.6 = xor i8 %A.6, %B.6
982   %A.gep.7 = getelementptr i8, ptr %A, i64 7
983   %A.7 = load i8, ptr %A.gep.7
984   %B.gep.7 = getelementptr i8, ptr %B, i64 7
985   %B.7 = load i8, ptr %B.gep.7
986   %xor.7 = xor i8 %A.7, %B.7
987   %A.gep.8 = getelementptr i8, ptr %A, i64 8
988   %A.8 = load i8, ptr %A.gep.8
989   %B.gep.8 = getelementptr i8, ptr %B, i64 8
990   %B.8 = load i8, ptr %B.gep.8
991   %xor.8 = xor i8 %A.8, %B.8
992   %A.gep.9 = getelementptr i8, ptr %A, i64 9
993   %A.9 = load i8, ptr %A.gep.9
994   %B.gep.9 = getelementptr i8, ptr %B, i64 9
995   %B.9 = load i8, ptr %B.gep.9
996   %xor.9 = xor i8 %A.9, %B.9
997   %A.gep.10 = getelementptr i8, ptr %A, i64 10
998   %A.10 = load i8, ptr %A.gep.10
999   %B.gep.10 = getelementptr i8, ptr %B, i64 10
1000   %B.10 = load i8, ptr %B.gep.10
1001   %xor.10 = xor i8 %A.10, %B.10
1002   %A.gep.11 = getelementptr i8, ptr %A, i64 11
1003   %A.11 = load i8, ptr %A.gep.11
1004   %B.gep.11 = getelementptr i8, ptr %B, i64 11
1005   %B.11 = load i8, ptr %B.gep.11
1006   %xor.11 = xor i8 %A.11, %B.11
1007   %A.gep.12 = getelementptr i8, ptr %A, i64 12
1008   %A.12 = load i8, ptr %A.gep.12
1009   %B.gep.12 = getelementptr i8, ptr %B, i64 12
1010   %B.12 = load i8, ptr %B.gep.12
1011   %xor.12 = xor i8 %A.12, %B.12
1012   %A.gep.13 = getelementptr i8, ptr %A, i64 13
1013   %A.13 = load i8, ptr %A.gep.13
1014   %B.gep.13 = getelementptr i8, ptr %B, i64 13
1015   %B.13 = load i8, ptr %B.gep.13
1016   %xor.13 = xor i8 %A.13, %B.13
1017   %A.gep.14 = getelementptr i8, ptr %A, i64 14
1018   %A.14 = load i8, ptr %A.gep.14
1019   %B.gep.14 = getelementptr i8, ptr %B, i64 14
1020   %B.14 = load i8, ptr %B.gep.14
1021   %xor.14 = xor i8 %A.14, %B.14
1022   %A.gep.15 = getelementptr i8, ptr %A, i64 15
1023   %A.15 = load i8, ptr %A.gep.15
1024   %B.gep.15 = getelementptr i8, ptr %B, i64 15
1025   %B.15 = load i8, ptr %B.gep.15
1026   %xor.15 = xor i8 %A.15, %B.15
1027   store i8 %xor.0, ptr %arg1
1028   %R.gep.1 = getelementptr i8, ptr %arg1, i64 1
1029   store i8 %xor.1, ptr %R.gep.1
1030   %R.gep.2 = getelementptr i8, ptr %arg1, i64 2
1031   store i8 %xor.2, ptr %R.gep.2
1032   %R.gep.3 = getelementptr i8, ptr %arg1, i64 3
1033   store i8 %xor.3, ptr %R.gep.3
1034   %R.gep.4 = getelementptr i8, ptr %arg1, i64 4
1035   store i8 %xor.4, ptr %R.gep.4
1036   %R.gep.5 = getelementptr i8, ptr %arg1, i64 5
1037   store i8 %xor.5, ptr %R.gep.5
1038   %R.gep.6 = getelementptr i8, ptr %arg1, i64 6
1039   store i8 %xor.6, ptr %R.gep.6
1040   %R.gep.7 = getelementptr i8, ptr %arg1, i64 7
1041   store i8 %xor.7, ptr %R.gep.7
1042   %R.gep.8 = getelementptr i8, ptr %arg1, i64 8
1043   store i8 %xor.8, ptr %R.gep.8
1044   %R.gep.9 = getelementptr i8, ptr %arg1, i64 9
1045   store i8 %xor.9, ptr %R.gep.9
1046   %R.gep.10 = getelementptr i8, ptr %arg1, i64 10
1047   store i8 %xor.10, ptr %R.gep.10
1048   %R.gep.11 = getelementptr i8, ptr %arg1, i64 11
1049   store i8 %xor.11, ptr %R.gep.11
1050   %R.gep.12 = getelementptr i8, ptr %arg1, i64 12
1051   store i8 %xor.12, ptr %R.gep.12
1052   %R.gep.13 = getelementptr i8, ptr %arg1, i64 13
1053   store i8 %xor.13, ptr %R.gep.13
1054   %R.gep.14 = getelementptr i8, ptr %arg1, i64 14
1055   store i8 %xor.14, ptr %R.gep.14
1056   %R.gep.15 = getelementptr i8, ptr %arg1, i64 15
1057   store i8 %xor.15, ptr %R.gep.15
1060   %t21 = getelementptr inbounds i8, ptr %arg3, i64 15
1062   call void @foo(ptr nonnull %t)
1063   %t26 = load i8, ptr %arg3, align 1
1064   %t27 = load i8, ptr %arg2, align 1
1065   %t28 = xor i8 %t27, %t26
1066   store i8 %t28, ptr %arg2, align 1
1067   %t29 = load i8, ptr %t5, align 1
1068   %t30 = getelementptr inbounds i8, ptr %arg2, i64 1
1069   %t31 = load i8, ptr %t30, align 1
1070   %t32 = xor i8 %t31, %t29
1071   store i8 %t32, ptr %t30, align 1
1072   %t33 = load i8, ptr %t6, align 1
1073   %t34 = getelementptr inbounds i8, ptr %arg2, i64 2
1074   %t35 = load i8, ptr %t34, align 1
1075   %t36 = xor i8 %t35, %t33
1076   store i8 %t36, ptr %t34, align 1
1077   %t37 = load i8, ptr %t7, align 1
1078   %t38 = getelementptr inbounds i8, ptr %arg2, i64 3
1079   %t39 = load i8, ptr %t38, align 1
1080   %t40 = xor i8 %t39, %t37
1081   store i8 %t40, ptr %t38, align 1
1082   %t41 = load i8, ptr %t8, align 1
1083   %t42 = getelementptr inbounds i8, ptr %arg2, i64 4
1084   %t43 = load i8, ptr %t42, align 1
1085   %t44 = xor i8 %t43, %t41
1086   store i8 %t44, ptr %t42, align 1
1087   %t45 = load i8, ptr %t9, align 1
1088   %t46 = getelementptr inbounds i8, ptr %arg2, i64 5
1089   %t47 = load i8, ptr %t46, align 1
1090   %t48 = xor i8 %t47, %t45
1091   store i8 %t48, ptr %t46, align 1
1092   %t49 = load i8, ptr %t10, align 1
1093   %t50 = getelementptr inbounds i8, ptr %arg2, i64 6
1094   %t51 = load i8, ptr %t50, align 1
1095   %t52 = xor i8 %t51, %t49
1096   store i8 %t52, ptr %t50, align 1
1097   %t53 = load i8, ptr %t11, align 1
1098   %t54 = getelementptr inbounds i8, ptr %arg2, i64 7
1099   %t55 = load i8, ptr %t54, align 1
1100   %t56 = xor i8 %t55, %t53
1101   store i8 %t56, ptr %t54, align 1
1102   %t57 = load i8, ptr %t12, align 1
1103   %t58 = getelementptr inbounds i8, ptr %arg2, i64 8
1104   %t59 = load i8, ptr %t58, align 1
1105   %t60 = xor i8 %t59, %t57
1106   store i8 %t60, ptr %t58, align 1
1107   %t61 = load i8, ptr %t13, align 1
1108   %t62 = getelementptr inbounds i8, ptr %arg2, i64 9
1109   %t63 = load i8, ptr %t62, align 1
1110   %t64 = xor i8 %t63, %t61
1111   store i8 %t64, ptr %t62, align 1
1112   %t65 = load i8, ptr %t14, align 1
1113   %t66 = getelementptr inbounds i8, ptr %arg2, i64 10
1114   %t67 = load i8, ptr %t66, align 1
1115   %t68 = xor i8 %t67, %t65
1116   store i8 %t68, ptr %t66, align 1
1117   %t69 = load i8, ptr %t15, align 1
1118   %t70 = getelementptr inbounds i8, ptr %arg2, i64 11
1119   %t71 = load i8, ptr %t70, align 1
1120   %t72 = xor i8 %t71, %t69
1121   store i8 %t72, ptr %t70, align 1
1122   %t73 = load i8, ptr %t16, align 1
1123   %t74 = getelementptr inbounds i8, ptr %arg2, i64 12
1124   %t75 = load i8, ptr %t74, align 1
1125   %t76 = xor i8 %t75, %t73
1126   store i8 %t76, ptr %t74, align 1
1127   %t77 = load i8, ptr %t17, align 1
1128   %t78 = getelementptr inbounds i8, ptr %arg2, i64 13
1129   %t79 = load i8, ptr %t78, align 1
1130   %t80 = xor i8 %t79, %t77
1131   store i8 %t80, ptr %t78, align 1
1132   %t81 = load i8, ptr %t18, align 1
1133   %t82 = getelementptr inbounds i8, ptr %arg2, i64 14
1134   %t83 = load i8, ptr %t82, align 1
1135   %t84 = xor i8 %t83, %t81
1136   store i8 %t84, ptr %t82, align 1
1137   %t85 = load i8, ptr %t21, align 1
1138   %t86 = getelementptr inbounds i8, ptr %arg2, i64 15
1139   %t87 = load i8, ptr %t86, align 1
1140   %t88 = xor i8 %t87, %t85
1141   store i8 %t88, ptr %t86, align 1
1142   ret i32 1
1145 ; A test case where instructions required to compute the pointer bounds get
1146 ; vectorized before versioning. Make sure there is no crash.
1147 define void @crash_instructions_deleted(ptr %t, ptr %a, ptr noalias %ptr) {
1148 ; CHECK-LABEL: @crash_instructions_deleted(
1149 ; CHECK-NEXT:  bb:
1150 ; CHECK-NEXT:    [[T15:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 2
1151 ; CHECK-NEXT:    store <2 x i32> <i32 0, i32 10>, ptr [[T15]], align 8
1152 ; CHECK-NEXT:    [[T17:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
1153 ; CHECK-NEXT:    br label [[BB18:%.*]]
1154 ; CHECK:       bb18:
1155 ; CHECK-NEXT:    [[T19:%.*]] = sext i32 0 to i64
1156 ; CHECK-NEXT:    [[T20:%.*]] = add nsw i64 1, [[T19]]
1157 ; CHECK-NEXT:    [[T21:%.*]] = getelementptr inbounds i32, ptr [[T17]], i64 [[T20]]
1158 ; CHECK-NEXT:    [[T23:%.*]] = getelementptr inbounds i8, ptr [[T21]], i64 1
1159 ; CHECK-NEXT:    [[T24:%.*]] = getelementptr inbounds i8, ptr [[T21]], i64 2
1160 ; CHECK-NEXT:    [[T25:%.*]] = getelementptr inbounds i8, ptr [[T21]], i64 3
1161 ; CHECK-NEXT:    [[T26:%.*]] = load i8, ptr [[T21]], align 1
1162 ; CHECK-NEXT:    [[T27:%.*]] = uitofp i8 [[T26]] to float
1163 ; CHECK-NEXT:    [[T28:%.*]] = fdiv float [[T27]], 2.550000e+02
1164 ; CHECK-NEXT:    store float [[T28]], ptr [[T:%.*]], align 8
1165 ; CHECK-NEXT:    [[T30:%.*]] = load i8, ptr [[T23]], align 1
1166 ; CHECK-NEXT:    [[T31:%.*]] = uitofp i8 [[T30]] to float
1167 ; CHECK-NEXT:    [[T32:%.*]] = fdiv float [[T31]], 2.550000e+02
1168 ; CHECK-NEXT:    [[T33:%.*]] = getelementptr inbounds float, ptr [[T]], i64 1
1169 ; CHECK-NEXT:    store float [[T32]], ptr [[T33]], align 4
1170 ; CHECK-NEXT:    [[T34:%.*]] = load i8, ptr [[T24]], align 1
1171 ; CHECK-NEXT:    [[T35:%.*]] = uitofp i8 [[T34]] to float
1172 ; CHECK-NEXT:    [[T36:%.*]] = fdiv float [[T35]], 2.550000e+02
1173 ; CHECK-NEXT:    [[T37:%.*]] = getelementptr inbounds float, ptr [[T]], i64 2
1174 ; CHECK-NEXT:    store float [[T36]], ptr [[T37]], align 8
1175 ; CHECK-NEXT:    [[T38:%.*]] = load i8, ptr [[T25]], align 1
1176 ; CHECK-NEXT:    [[T39:%.*]] = uitofp i8 [[T38]] to float
1177 ; CHECK-NEXT:    [[T40:%.*]] = fdiv float [[T39]], 2.550000e+02
1178 ; CHECK-NEXT:    [[T41:%.*]] = getelementptr inbounds float, ptr [[T]], i64 3
1179 ; CHECK-NEXT:    store float [[T40]], ptr [[T41]], align 4
1180 ; CHECK-NEXT:    ret void
1183   %t6 = icmp slt i32 10, 0
1184   %t7 = icmp sgt i32 20, 20
1185   %t9 = select i1 %t7, i32 5, i32 0
1186   %t10 = select i1 %t6, i32 0, i32 %t9
1187   %t11 = icmp slt i32 10, 0
1188   %t12 = icmp sgt i32 20, 20
1189   %t13 = select i1 %t12, i32 5, i32 10
1190   %t14 = select i1 %t11, i32 0, i32 %t13
1191   %t15 = getelementptr inbounds i32, ptr %a, i32 2
1192   store i32 %t10, ptr %t15, align 8
1193   %t16 = getelementptr inbounds i32, ptr %a, i32 3
1194   store i32 %t14, ptr %t16, align 4
1195   %t17 = load ptr, ptr %ptr, align 8
1196   br label %bb18
1198 bb18:                                             ; preds = %bb5
1199   %t19 = sext i32 %t10 to i64
1200   %t20 = add nsw i64 1, %t19
1201   %t21 = getelementptr inbounds i32, ptr %t17, i64 %t20
1202   %t23 = getelementptr inbounds i8, ptr %t21, i64 1
1203   %t24 = getelementptr inbounds i8, ptr %t21, i64 2
1204   %t25 = getelementptr inbounds i8, ptr %t21, i64 3
1205   %t26 = load i8, ptr %t21, align 1
1206   %t27 = uitofp i8 %t26 to float
1207   %t28 = fdiv float %t27, 2.550000e+02
1208   store float %t28, ptr %t, align 8
1209   %t30 = load i8, ptr %t23, align 1
1210   %t31 = uitofp i8 %t30 to float
1211   %t32 = fdiv float %t31, 2.550000e+02
1212   %t33 = getelementptr inbounds float, ptr %t, i64 1
1213   store float %t32, ptr %t33, align 4
1214   %t34 = load i8, ptr %t24, align 1
1215   %t35 = uitofp i8 %t34 to float
1216   %t36 = fdiv float %t35, 2.550000e+02
1217   %t37 = getelementptr inbounds float, ptr %t, i64 2
1218   store float %t36, ptr %t37, align 8
1219   %t38 = load i8, ptr %t25, align 1
1220   %t39 = uitofp i8 %t38 to float
1221   %t40 = fdiv float %t39, 2.550000e+02
1222   %t41 = getelementptr inbounds float, ptr %t, i64 3
1223   store float %t40, ptr %t41, align 4
1224   ret void
1227 ; A test case where there are no instructions accessing a tracked object in a
1228 ; block for which versioning was requested.
1229 define void @crash_no_tracked_instructions(ptr %arg, ptr %arg.2, ptr %arg.3, i1 %c) {
1230 ; CHECK-LABEL: @crash_no_tracked_instructions(
1231 ; CHECK-NEXT:  entry:
1232 ; CHECK-NEXT:    [[T19:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
1233 ; CHECK-NEXT:    [[T20:%.*]] = load float, ptr [[ARG_3:%.*]], align 4
1234 ; CHECK-NEXT:    [[TMP0:%.*]] = insertelement <2 x float> <float 0.000000e+00, float poison>, float [[T20]], i32 1
1235 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB22:%.*]], label [[BB30:%.*]]
1236 ; CHECK:       bb22:
1237 ; CHECK-NEXT:    [[T23:%.*]] = fmul float [[T20]], 9.900000e+01
1238 ; CHECK-NEXT:    [[T25:%.*]] = getelementptr inbounds float, ptr [[T19]], i64 2
1239 ; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[T23]], i32 0
1240 ; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1241 ; CHECK-NEXT:    [[TMP3:%.*]] = fmul <2 x float> [[TMP2]], <float 9.900000e+01, float 1.000000e+01>
1242 ; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x float> [[TMP3]], i32 1
1243 ; CHECK-NEXT:    store float [[TMP4]], ptr [[T25]], align 4
1244 ; CHECK-NEXT:    [[T27:%.*]] = load float, ptr [[ARG_2:%.*]], align 8
1245 ; CHECK-NEXT:    [[TMP5:%.*]] = fadd <2 x float> [[TMP3]], <float 2.000000e+01, float 2.000000e+01>
1246 ; CHECK-NEXT:    br label [[BB30]]
1247 ; CHECK:       bb30:
1248 ; CHECK-NEXT:    [[TMP6:%.*]] = phi <2 x float> [ [[TMP5]], [[BB22]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
1249 ; CHECK-NEXT:    br label [[BB36:%.*]]
1250 ; CHECK:       bb36:
1251 ; CHECK-NEXT:    [[TMP7:%.*]] = fmul <2 x float> [[TMP6]], <float 3.000000e+00, float 3.000000e+00>
1252 ; CHECK-NEXT:    store <2 x float> [[TMP7]], ptr [[ARG_3]], align 4
1253 ; CHECK-NEXT:    br label [[BB41:%.*]]
1254 ; CHECK:       bb41:
1255 ; CHECK-NEXT:    ret void
1257 entry:
1258   %t19 = load ptr, ptr %arg
1259   %t20 = load float, ptr %arg.3, align 4
1260   br i1 %c, label %bb22, label %bb30
1262 bb22:
1263   %t23 = fmul float %t20, 99.0
1264   %t24 = fmul float %t23, 99.0
1265   %t25 = getelementptr inbounds float, ptr %t19, i64 2
1266   %t26 = fmul float %t23, 10.0
1267   store float %t26, ptr %t25, align 4
1268   %t27 = load float, ptr %arg.2, align 8
1269   %t28 = fadd float %t24, 20.0
1270   %t29 = fadd float %t26, 20.0
1271   br label %bb30
1273 bb30:
1274   %t31 = phi float [ %t28, %bb22 ], [ 0.0, %entry ]
1275   %t32 = phi float [ %t29, %bb22 ], [ %t20, %entry ]
1276   br label %bb36
1278 bb36:
1279   %t37 = fmul float %t31, 3.0
1280   store float %t37, ptr %arg.3, align 4
1281   %t39 = fmul float %t32, 3.0
1282   %t40 = getelementptr inbounds float, ptr %arg.3, i64 1
1283   store float %t39, ptr %t40, align 4
1284   br label %bb41
1286 bb41:
1287   ret void