xref: /llvm-project/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll (revision 10f315dc9c96ec2413881ab55a285e35d80def88)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s
3
4target datalayout="p5:32:32-A5"
5
6@g1 = constant [32 x i8] zeroinitializer
7@g2 = addrspace(1) constant [32 x i8] zeroinitializer
8
9define i8 @remove_alloca_use_arg(i1 %cond) {
10; CHECK-LABEL: @remove_alloca_use_arg(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
13; CHECK:       if:
14; CHECK-NEXT:    br label [[SINK:%.*]]
15; CHECK:       else:
16; CHECK-NEXT:    br label [[SINK]]
17; CHECK:       sink:
18; CHECK-NEXT:    [[PTR1:%.*]] = phi ptr [ getelementptr inbounds nuw (i8, ptr @g1, i64 2), [[IF]] ], [ getelementptr inbounds nuw (i8, ptr @g1, i64 1), [[ELSE]] ]
19; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
20; CHECK-NEXT:    ret i8 [[LOAD]]
21;
22entry:
23  %alloca = alloca [32 x i8], align 4, addrspace(1)
24  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false)
25  br i1 %cond, label %if, label %else
26
27if:
28  %val.if = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2
29  br label %sink
30
31else:
32  %val.else = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1
33  br label %sink
34
35sink:
36  %ptr = phi ptr addrspace(1) [ %val.if, %if ], [ %val.else, %else ]
37  %load = load i8, ptr addrspace(1) %ptr
38  ret i8 %load
39}
40
41define i8 @volatile_load_keep_alloca(i1 %cond) {
42; CHECK-LABEL: @volatile_load_keep_alloca(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
45; CHECK-NEXT:    call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false)
46; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
47; CHECK:       if:
48; CHECK-NEXT:    [[VAL_IF:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 1
49; CHECK-NEXT:    br label [[SINK:%.*]]
50; CHECK:       else:
51; CHECK-NEXT:    [[VAL_ELSE:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 2
52; CHECK-NEXT:    br label [[SINK]]
53; CHECK:       sink:
54; CHECK-NEXT:    [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL_IF]], [[IF]] ], [ [[VAL_ELSE]], [[ELSE]] ]
55; CHECK-NEXT:    [[LOAD:%.*]] = load volatile i8, ptr addrspace(1) [[PTR]], align 1
56; CHECK-NEXT:    ret i8 [[LOAD]]
57;
58entry:
59  %alloca = alloca [32 x i8], align 4, addrspace(1)
60  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false)
61  br i1 %cond, label %if, label %else
62
63if:
64  %val.if = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1
65  br label %sink
66
67else:
68  %val.else = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2
69  br label %sink
70
71sink:
72  %ptr = phi ptr addrspace(1) [ %val.if, %if ], [ %val.else, %else ]
73  %load = load volatile i8, ptr addrspace(1) %ptr
74  ret i8 %load
75}
76
77
78define i8 @no_memcpy_keep_alloca(i1 %cond) {
79; CHECK-LABEL: @no_memcpy_keep_alloca(
80; CHECK-NEXT:  entry:
81; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
82; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
83; CHECK:       if:
84; CHECK-NEXT:    [[VAL_IF:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 1
85; CHECK-NEXT:    br label [[SINK:%.*]]
86; CHECK:       else:
87; CHECK-NEXT:    [[VAL_ELSE:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 2
88; CHECK-NEXT:    br label [[SINK]]
89; CHECK:       sink:
90; CHECK-NEXT:    [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL_IF]], [[IF]] ], [ [[VAL_ELSE]], [[ELSE]] ]
91; CHECK-NEXT:    [[LOAD:%.*]] = load volatile i8, ptr addrspace(1) [[PTR]], align 1
92; CHECK-NEXT:    ret i8 [[LOAD]]
93;
94entry:
95  %alloca = alloca [32 x i8], align 4, addrspace(1)
96  br i1 %cond, label %if, label %else
97
98if:
99  %val.if = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1
100  br label %sink
101
102else:
103  %val.else = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2
104  br label %sink
105
106sink:
107  %ptr = phi ptr addrspace(1) [ %val.if, %if ], [ %val.else, %else ]
108  %load = load volatile i8, ptr addrspace(1) %ptr
109  ret i8 %load
110}
111
112define i8 @loop_phi_remove_alloca(i1 %cond) {
113; CHECK-LABEL: @loop_phi_remove_alloca(
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    br label [[BB_0:%.*]]
116; CHECK:       bb.0:
117; CHECK-NEXT:    [[PTR1:%.*]] = phi ptr [ getelementptr inbounds nuw (i8, ptr @g1, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds nuw (i8, ptr @g1, i64 2), [[BB_1:%.*]] ]
118; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]]
119; CHECK:       bb.1:
120; CHECK-NEXT:    br label [[BB_0]]
121; CHECK:       exit:
122; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
123; CHECK-NEXT:    ret i8 [[LOAD]]
124;
125entry:
126  %alloca = alloca [32 x i8], align 4, addrspace(1)
127  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false)
128  %val1 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1
129  br label %bb.0
130
131bb.0:
132  %ptr = phi ptr addrspace(1) [ %val1, %entry ], [ %val2, %bb.1 ]
133  br i1 %cond, label %bb.1, label %exit
134
135bb.1:
136  %val2 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2
137  br label %bb.0
138
139exit:
140  %load = load i8, ptr addrspace(1) %ptr
141  ret i8 %load
142}
143
144define i32 @remove_alloca_ptr_arg(i1 %c, ptr %ptr) {
145; CHECK-LABEL: @remove_alloca_ptr_arg(
146; CHECK-NEXT:  entry:
147; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
148; CHECK:       if:
149; CHECK-NEXT:    br label [[JOIN]]
150; CHECK:       join:
151; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ @g1, [[IF]] ], [ [[PTR:%.*]], [[ENTRY:%.*]] ]
152; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[PHI]], align 4
153; CHECK-NEXT:    ret i32 [[V]]
154;
155entry:
156  %alloca = alloca [32 x i8]
157  call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false)
158  br i1 %c, label %if, label %join
159
160if:
161  br label %join
162
163join:
164  %phi = phi ptr [ %alloca, %if ], [ %ptr, %entry ]
165  %v = load i32, ptr %phi
166  ret i32 %v
167}
168
169define i8 @loop_phi_late_memtransfer_remove_alloca(i1 %cond) {
170; CHECK-LABEL: @loop_phi_late_memtransfer_remove_alloca(
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    br label [[BB_0:%.*]]
173; CHECK:       bb.0:
174; CHECK-NEXT:    [[PTR1:%.*]] = phi ptr [ getelementptr inbounds nuw (i8, ptr @g1, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds nuw (i8, ptr @g1, i64 2), [[BB_1:%.*]] ]
175; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]]
176; CHECK:       bb.1:
177; CHECK-NEXT:    br label [[BB_0]]
178; CHECK:       exit:
179; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
180; CHECK-NEXT:    ret i8 [[LOAD]]
181;
182entry:
183  %alloca = alloca [32 x i8], align 4, addrspace(1)
184  %val1 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1
185  br label %bb.0
186
187bb.0:
188  %ptr = phi ptr addrspace(1) [ %val1, %entry ], [ %val2, %bb.1 ]
189  br i1 %cond, label %bb.1, label %exit
190
191bb.1:
192  %val2 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2
193  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false)
194  br label %bb.0
195
196exit:
197  %load = load i8, ptr addrspace(1) %ptr
198  ret i8 %load
199}
200
201define i32 @test_memcpy_after_phi(i1 %cond, ptr %ptr) {
202; CHECK-LABEL: @test_memcpy_after_phi(
203; CHECK-NEXT:  entry:
204; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1
205; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
206; CHECK:       if:
207; CHECK-NEXT:    br label [[JOIN]]
208; CHECK:       join:
209; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A]], [[IF]] ], [ [[PTR:%.*]], [[ENTRY:%.*]] ]
210; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(32) [[PHI]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false)
211; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[PHI]], align 4
212; CHECK-NEXT:    ret i32 [[V]]
213;
214entry:
215  %a = alloca [32 x i8]
216  br i1 %cond, label %if, label %join
217
218if:
219  br label %join
220
221join:
222  %phi = phi ptr [ %a, %if ], [ %ptr, %entry ]
223  call void @llvm.memcpy.p0.p0.i64(ptr %phi, ptr @g1, i64 32, i1 false)
224  %v = load i32, ptr %phi
225  ret i32 %v
226}
227
228define i32 @addrspace_diff_keep_alloca(i1 %cond, ptr %x) {
229; CHECK-LABEL: @addrspace_diff_keep_alloca(
230; CHECK-NEXT:  entry:
231; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1
232; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[A]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false)
233; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
234; CHECK:       if:
235; CHECK-NEXT:    br label [[JOIN]]
236; CHECK:       join:
237; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A]], [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
238; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[PHI]], align 4
239; CHECK-NEXT:    ret i32 [[V]]
240;
241entry:
242  %a = alloca [32 x i8]
243  call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false)
244  br i1 %cond, label %if, label %join
245
246if:
247  br label %join
248
249join:
250  %phi = phi ptr [ %a, %if ], [ %x, %entry ]
251  %v = load i32, ptr %phi
252  ret i32 %v
253}
254
255define i32 @addrspace_diff_keep_alloca_extra_gep(i1 %cond, ptr %x) {
256; CHECK-LABEL: @addrspace_diff_keep_alloca_extra_gep(
257; CHECK-NEXT:  entry:
258; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1
259; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[A]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false)
260; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
261; CHECK:       if:
262; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4
263; CHECK-NEXT:    br label [[JOIN]]
264; CHECK:       join:
265; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[GEP]], [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
266; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[PHI]], align 4
267; CHECK-NEXT:    ret i32 [[V]]
268;
269entry:
270  %a = alloca [32 x i8]
271  call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false)
272  %gep = getelementptr i8, ptr %a, i64 4
273  br i1 %cond, label %if, label %join
274
275if:
276  br label %join
277
278join:
279  %phi = phi ptr [ %gep, %if ], [ %x, %entry ]
280  %v = load i32, ptr %phi
281  ret i32 %v
282}
283
284define i32 @addrspace_diff_remove_alloca(i1 %cond) {
285; CHECK-LABEL: @addrspace_diff_remove_alloca(
286; CHECK-NEXT:  entry:
287; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
288; CHECK:       if:
289; CHECK-NEXT:    br label [[JOIN]]
290; CHECK:       join:
291; CHECK-NEXT:    [[PHI1:%.*]] = phi ptr addrspace(1) [ @g2, [[IF]] ], [ getelementptr inbounds nuw (i8, ptr addrspace(1) @g2, i64 2), [[ENTRY:%.*]] ]
292; CHECK-NEXT:    [[V:%.*]] = load i32, ptr addrspace(1) [[PHI1]], align 4
293; CHECK-NEXT:    ret i32 [[V]]
294;
295entry:
296  %a = alloca [32 x i8]
297  call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false)
298  %gep = getelementptr inbounds [32 x i8], ptr %a, i32 0, i32 2
299  br i1 %cond, label %if, label %join
300
301if:
302  br label %join
303
304join:
305  %phi = phi ptr [ %a, %if ], [ %gep, %entry ]
306  %v = load i32, ptr %phi
307  ret i32 %v
308}
309
310define i32 @phi_loop(i1 %c) {
311; CHECK-LABEL: @phi_loop(
312; CHECK-NEXT:  entry:
313; CHECK-NEXT:    br label [[LOOP:%.*]]
314; CHECK:       loop:
315; CHECK-NEXT:    [[PTR:%.*]] = phi ptr [ @g1, [[ENTRY:%.*]] ], [ [[PTR_NEXT:%.*]], [[LOOP]] ]
316; CHECK-NEXT:    [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 4
317; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
318; CHECK:       exit:
319; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[PTR]], align 4
320; CHECK-NEXT:    ret i32 [[V]]
321;
322entry:
323  %alloca = alloca [32 x i8]
324  call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false)
325  br label %loop
326
327loop:
328  %ptr = phi ptr [ %alloca, %entry ], [ %ptr.next, %loop ]
329  %ptr.next = getelementptr i8, ptr %ptr, i64 4
330  br i1 %c, label %exit, label %loop
331
332exit:
333  %v = load i32, ptr %ptr
334  ret i32 %v
335}
336
337define i32 @phi_loop_different_addrspace(i1 %c) {
338; CHECK-LABEL: @phi_loop_different_addrspace(
339; CHECK-NEXT:  entry:
340; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1
341; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[ALLOCA]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false)
342; CHECK-NEXT:    br label [[LOOP:%.*]]
343; CHECK:       loop:
344; CHECK-NEXT:    [[PTR:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[PTR_NEXT:%.*]], [[LOOP]] ]
345; CHECK-NEXT:    [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 4
346; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
347; CHECK:       exit:
348; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[PTR]], align 4
349; CHECK-NEXT:    ret i32 [[V]]
350;
351entry:
352  %alloca = alloca [32 x i8]
353  call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false)
354  br label %loop
355
356loop:
357  %ptr = phi ptr [ %alloca, %entry ], [ %ptr.next, %loop ]
358  %ptr.next = getelementptr i8, ptr %ptr, i64 4
359  br i1 %c, label %exit, label %loop
360
361exit:
362  %v = load i32, ptr %ptr
363  ret i32 %v
364}
365
366define i8 @select_same_addrspace_remove_alloca(i1 %cond, ptr %p) {
367; CHECK-LABEL: @select_same_addrspace_remove_alloca(
368; CHECK-NEXT:  entry:
369; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[COND:%.*]], ptr @g1, ptr [[P:%.*]]
370; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR]], align 1
371; CHECK-NEXT:    ret i8 [[LOAD]]
372;
373entry:
374  %alloca = alloca [32 x i8]
375  call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false)
376  %ptr = select i1 %cond, ptr %alloca, ptr %p
377  %load = load i8, ptr %ptr
378  ret i8 %load
379}
380
381define i8 @select_after_memcpy_keep_alloca(i1 %cond, ptr %p) {
382; CHECK-LABEL: @select_after_memcpy_keep_alloca(
383; CHECK-NEXT:  entry:
384; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1
385; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[COND:%.*]], ptr [[ALLOCA]], ptr [[P:%.*]]
386; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(32) [[PTR]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false)
387; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR]], align 1
388; CHECK-NEXT:    ret i8 [[LOAD]]
389;
390entry:
391  %alloca = alloca [32 x i8]
392  %ptr = select i1 %cond, ptr %alloca, ptr %p
393  call void @llvm.memcpy.p0.p0.i64(ptr %ptr, ptr @g1, i64 32, i1 false)
394  %load = load i8, ptr %ptr
395  ret i8 %load
396}
397
398define i8 @select_diff_addrspace_keep_alloca(i1 %cond, ptr addrspace(1) %p) {
399; CHECK-LABEL: @select_diff_addrspace_keep_alloca(
400; CHECK-NEXT:  entry:
401; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1)
402; CHECK-NEXT:    call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false)
403; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[COND:%.*]], ptr addrspace(1) [[ALLOCA]], ptr addrspace(1) [[P:%.*]]
404; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
405; CHECK-NEXT:    ret i8 [[LOAD]]
406;
407entry:
408  %alloca = alloca [32 x i8], addrspace(1)
409  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false)
410  %ptr = select i1 %cond, ptr addrspace(1) %alloca, ptr addrspace(1) %p
411  %load = load i8, ptr addrspace(1) %ptr
412  ret i8 %load
413}
414
415define i8 @select_diff_addrspace_remove_alloca(i1 %cond, ptr %p) {
416; CHECK-LABEL: @select_diff_addrspace_remove_alloca(
417; CHECK-NEXT:  entry:
418; CHECK-NEXT:    ret i8 0
419;
420entry:
421  %alloca = alloca [32 x i8]
422  call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false)
423  %gep = getelementptr inbounds [32 x i8], ptr %alloca, i32 0, i32 2
424  %sel = select i1 %cond, ptr %alloca, ptr %gep
425  %gep2 = getelementptr inbounds i8, ptr %sel, i64 4
426  %load = load i8, ptr %gep2
427  ret i8 %load
428}
429
430define i8 @select_diff_addrspace_remove_alloca_asan(i1 %cond, ptr %p) sanitize_address {
431; CHECK-LABEL: @select_diff_addrspace_remove_alloca_asan(
432; CHECK-NEXT:  entry:
433; CHECK-NEXT:    [[GEP2:%.*]] = select i1 [[COND:%.*]], ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @g2, i64 4), ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @g2, i64 6)
434; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr addrspace(1) [[GEP2]], align 1
435; CHECK-NEXT:    ret i8 [[LOAD]]
436;
437entry:
438  %alloca = alloca [32 x i8]
439  call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false)
440  %gep = getelementptr inbounds [32 x i8], ptr %alloca, i32 0, i32 2
441  %sel = select i1 %cond, ptr %alloca, ptr %gep
442  %gep2 = getelementptr inbounds i8, ptr %sel, i64 4
443  %load = load i8, ptr %gep2
444  ret i8 %load
445}
446
447declare i8 @readonly_callee(ptr readonly nocapture)
448
449; FIXME: This should be able to fold to call i8 @readonly_callee(ptr nonnull @g1)
450define i8 @call_readonly_remove_alloca() {
451; CHECK-LABEL: @call_readonly_remove_alloca(
452; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1)
453; CHECK-NEXT:    call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false)
454; CHECK-NEXT:    [[P:%.*]] = addrspacecast ptr addrspace(1) [[ALLOCA]] to ptr
455; CHECK-NEXT:    [[V:%.*]] = call i8 @readonly_callee(ptr [[P]])
456; CHECK-NEXT:    ret i8 [[V]]
457;
458  %alloca = alloca [32 x i8], addrspace(1)
459  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false)
460  %p = addrspacecast ptr addrspace(1) %alloca to ptr
461  %v = call i8 @readonly_callee(ptr %p)
462  ret i8 %v
463}
464
465define i8 @call_readonly_keep_alloca2() {
466; CHECK-LABEL: @call_readonly_keep_alloca2(
467; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1)
468; CHECK-NEXT:    call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(16) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(16) @g1, i64 16, i1 false)
469; CHECK-NEXT:    [[A1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 16
470; CHECK-NEXT:    call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) noundef nonnull align 1 dereferenceable(16) [[A1]], ptr addrspace(1) noundef align 16 dereferenceable(16) @g2, i64 16, i1 false)
471; CHECK-NEXT:    [[P:%.*]] = addrspacecast ptr addrspace(1) [[ALLOCA]] to ptr
472; CHECK-NEXT:    [[V:%.*]] = call i8 @readonly_callee(ptr [[P]])
473; CHECK-NEXT:    ret i8 [[V]]
474;
475  %alloca = alloca [32 x i8], addrspace(1)
476  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 16, i1 false)
477  %a1 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 16
478  call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %a1, ptr addrspace(1) @g2, i64 16, i1 false)
479  %p = addrspacecast ptr addrspace(1) %alloca to ptr
480  %v = call i8 @readonly_callee(ptr %p)
481  ret i8 %v
482}
483
484declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1), ptr, i64, i1)
485declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
486declare void @llvm.memcpy.p0.p1.i64(ptr, ptr addrspace(1), i64, i1)
487declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1), ptr addrspace(1), i64, i1)
488