xref: /llvm-project/llvm/test/Transforms/SLPVectorizer/AArch64/memory-runtime-checks.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
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
3
4define 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
16;
17entry:
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
27}
28
29define 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
51;
52entry:
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
71
72  ret void
73}
74
75define 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
108;
109entry:
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
139
140  ret void
141}
142
143declare void @use(i32)
144
145declare void @bar()
146
147define 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
173;
174entry:
175  call void @bar()
176  call void @bar()
177  call void @bar()
178
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
197
198  call void @bar()
199  ret void
200}
201
202define 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
231;
232entry:
233  br i1 %c, label %then, label %exit
234
235then:
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
258
259exit:
260  ret void
261}
262
263define 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
292;
293entry:
294  br i1 %c, label %then, label %exit
295
296then:
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
319
320exit:
321  ret void
322}
323
324define 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]], splat (i32 16)
329; CHECK-NEXT:    store <2 x i32> [[TMP1]], ptr [[DST:%.*]], align 4
330; CHECK-NEXT:    ret void
331;
332entry:
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
342}
343
344define 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
370;
371entry:
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
395}
396
397define 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]]
411;
412entry:
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
422
423exit:
424  ret i32 %r.0
425}
426
427define 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]]
440;
441entry:
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
452}
453define 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
469;
470entry:
471  br i1 %c.1, label %then, label %else
472
473then:
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
483
484
485else:
486  ret i32 0
487}
488
489define 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
502;
503entry:
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
514}
515
516define 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
526;
527entry:
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
535}
536
537declare void @clobber()
538
539define 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
549;
550bb:
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
558}
559
560define 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]]
577;
578bb1:                                              ; 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
591
592bb15:                                             ; preds = %bb15, %bb14
593  br label %bb15
594}
595
596%struct = type { i32, i32, float, float }
597
598; Some points we collected as candidates for runtime checks have been removed
599; before generating runtime checks. Make sure versioning is skipped.
600define 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
619;
620entry:
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
636
637bb14:
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
648
649bb23:
650  ret void
651}
652
653; In this test there's a single bound, do not generate runtime checks.
654define 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
669;
670entry:
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
678
679bb15:
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
685}
686
687%struct.2 = type { [4 x float] }
688
689; Make sure we do not crash when we encounter a SCEVCouldNotCompute.
690define 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
721;
722bb:
723  br label %loop
724
725loop:
726  %ptr.phi = phi ptr [ %A, %bb ], [ null, %loop ]
727  br i1 %c, label %exit, label %loop
728
729exit:
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
753}
754
755; Make sure lcssa phis as pointer bases are handled properly.
756define 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
788;
789bb:
790  br label %loop
791
792loop:
793  %ptr.phi = phi ptr [ %A, %bb ], [ null, %loop ]
794  br i1 %c, label %exit, label %loop
795
796exit:
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
821}
822
823%struct.spam = type { [60 x i32], i32, [12 x i8] }
824
825declare void @foo(ptr)
826
827; Test case with a basic block where parts can be vectorized without versioning.
828define 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
932;
933bb:
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
1058
1059
1060  %t21 = getelementptr inbounds i8, ptr %arg3, i64 15
1061
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
1143}
1144
1145; A test case where instructions required to compute the pointer bounds get
1146; vectorized before versioning. Make sure there is no crash.
1147define 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
1181;
1182bb:
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
1197
1198bb18:                                             ; 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
1225}
1226
1227; A test case where there are no instructions accessing a tracked object in a
1228; block for which versioning was requested.
1229define 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:    [[T26:%.*]] = fmul float [[T23]], 1.000000e+01
1240; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[T23]], i32 0
1241; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer
1242; CHECK-NEXT:    [[TMP3:%.*]] = fmul <2 x float> [[TMP2]], <float 9.900000e+01, float 1.000000e+01>
1243; CHECK-NEXT:    store float [[T26]], ptr [[T25]], align 4
1244; CHECK-NEXT:    [[T27:%.*]] = load float, ptr [[ARG_2:%.*]], align 8
1245; CHECK-NEXT:    [[TMP4:%.*]] = fadd <2 x float> [[TMP3]], splat (float 2.000000e+01)
1246; CHECK-NEXT:    br label [[BB30]]
1247; CHECK:       bb30:
1248; CHECK-NEXT:    [[TMP5:%.*]] = phi <2 x float> [ [[TMP4]], [[BB22]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
1249; CHECK-NEXT:    br label [[BB36:%.*]]
1250; CHECK:       bb36:
1251; CHECK-NEXT:    [[TMP6:%.*]] = fmul <2 x float> [[TMP5]], splat (float 3.000000e+00)
1252; CHECK-NEXT:    store <2 x float> [[TMP6]], ptr [[ARG_3]], align 4
1253; CHECK-NEXT:    br label [[BB41:%.*]]
1254; CHECK:       bb41:
1255; CHECK-NEXT:    ret void
1256;
1257entry:
1258  %t19 = load ptr, ptr %arg
1259  %t20 = load float, ptr %arg.3, align 4
1260  br i1 %c, label %bb22, label %bb30
1261
1262bb22:
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
1272
1273bb30:
1274  %t31 = phi float [ %t28, %bb22 ], [ 0.0, %entry ]
1275  %t32 = phi float [ %t29, %bb22 ], [ %t20, %entry ]
1276  br label %bb36
1277
1278bb36:
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
1285
1286bb41:
1287  ret void
1288}
1289