xref: /llvm-project/llvm/test/Transforms/Attributor/align.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
4
5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6
7; Test cases specifically designed for "align" attribute.
8; We use FIXME's to indicate problems and missing attributes.
9
10
11; TEST 1
12;;
13;.
14; CHECK: @a1 = common global i8 0, align 8
15; CHECK: @a2 = common global i8 0, align 16
16; CHECK: @cnd = external global i1
17; CHECK: @G = global i8 0, align 32
18;.
19define ptr @test1(ptr align 8 %0) #0 {
20; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
21; CHECK-LABEL: define {{[^@]+}}@test1
22; CHECK-SAME: (ptr nofree readnone returned align 8 "no-capture-maybe-returned" [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
23; CHECK-NEXT:    ret ptr [[TMP0]]
24;
25  ret ptr %0
26}
27
28; TEST 2
29define ptr @test2(ptr %0) #0 {
30; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
31; CHECK-LABEL: define {{[^@]+}}@test2
32; CHECK-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[TMP0:%.*]]) #[[ATTR0]] {
33; CHECK-NEXT:    ret ptr [[TMP0]]
34;
35  ret ptr %0
36}
37
38; TEST 3
39define ptr @test3(ptr align 8 %0, ptr align 4 %1, i1 %2) #0 {
40; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
41; CHECK-LABEL: define {{[^@]+}}@test3
42; CHECK-SAME: (ptr nofree readnone align 8 "no-capture-maybe-returned" [[TMP0:%.*]], ptr nofree readnone align 4 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) #[[ATTR0]] {
43; CHECK-NEXT:    [[RET:%.*]] = select i1 [[TMP2]], ptr [[TMP0]], ptr [[TMP1]]
44; CHECK-NEXT:    ret ptr [[RET]]
45;
46  %ret = select i1 %2, ptr %0, ptr %1
47  ret ptr %ret
48}
49
50; TEST 4
51define ptr @test4(ptr align 32 %0, ptr align 32 %1, i1 %2) #0 {
52; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
53; CHECK-LABEL: define {{[^@]+}}@test4
54; CHECK-SAME: (ptr nofree readnone align 32 "no-capture-maybe-returned" [[TMP0:%.*]], ptr nofree readnone align 32 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) #[[ATTR0]] {
55; CHECK-NEXT:    [[RET:%.*]] = select i1 [[TMP2]], ptr [[TMP0]], ptr [[TMP1]]
56; CHECK-NEXT:    ret ptr [[RET]]
57;
58  %ret = select i1 %2, ptr %0, ptr %1
59  ret ptr %ret
60}
61
62; TEST 5
63declare ptr @unknown()
64declare align 8 ptr @align8()
65
66
67define ptr @test5_1() {
68; CHECK-LABEL: define {{[^@]+}}@test5_1() {
69; CHECK-NEXT:    [[RET:%.*]] = tail call align 8 ptr @unknown()
70; CHECK-NEXT:    ret ptr [[RET]]
71;
72  %ret = tail call align 8 ptr @unknown()
73  ret ptr %ret
74}
75
76define ptr @test5_2() {
77; CHECK-LABEL: define {{[^@]+}}@test5_2() {
78; CHECK-NEXT:    [[RET:%.*]] = tail call align 8 ptr @align8()
79; CHECK-NEXT:    ret ptr [[RET]]
80;
81  %ret = tail call ptr @align8()
82  ret ptr %ret
83}
84
85; TEST 6
86; SCC
87define ptr @test6_1() #0 {
88; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
89; TUNIT-LABEL: define {{[^@]+}}@test6_1
90; TUNIT-SAME: () #[[ATTR1:[0-9]+]] {
91; TUNIT-NEXT:    ret ptr undef
92;
93; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
94; CGSCC-LABEL: define {{[^@]+}}@test6_1
95; CGSCC-SAME: () #[[ATTR0]] {
96; CGSCC-NEXT:    ret ptr undef
97;
98  %ret = tail call ptr @test6_2()
99  ret ptr %ret
100}
101
102define ptr @test6_2() #0 {
103; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
104; TUNIT-LABEL: define {{[^@]+}}@test6_2
105; TUNIT-SAME: () #[[ATTR1]] {
106; TUNIT-NEXT:    ret ptr undef
107;
108; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
109; CGSCC-LABEL: define {{[^@]+}}@test6_2
110; CGSCC-SAME: () #[[ATTR0]] {
111; CGSCC-NEXT:    ret ptr undef
112;
113  %ret = tail call ptr @test6_1()
114  ret ptr %ret
115}
116
117
118; char a1 __attribute__((aligned(8)));
119; char a2 __attribute__((aligned(16)));
120;
121; char* f1(char* a ){
122;     return a?a:f2(&a1);
123; }
124; char* f2(char* a){
125;     return a?f1(a):f3(&a2);
126; }
127;
128; char* f3(char* a){
129;     return a?&a1: f1(&a2);
130; }
131
132@a1 = common global i8 0, align 8
133@a2 = common global i8 0, align 16
134
135; Function Attrs: nounwind readnone ssp uwtable
136define internal ptr @f1(ptr readnone %0) local_unnamed_addr #0 {
137; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
138; CGSCC-LABEL: define {{[^@]+}}@f1
139; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] {
140; CGSCC-NEXT:    br label [[TMP2:%.*]]
141; CGSCC:       1:
142; CGSCC-NEXT:    unreachable
143; CGSCC:       2:
144; CGSCC-NEXT:    ret ptr @a1
145;
146  %2 = icmp eq ptr %0, null
147  br i1 %2, label %3, label %5
148
149; <label>:3:                                      ; preds = %1
150  %4 = tail call ptr @f2(ptr nonnull @a1)
151  %l = load i8, ptr %4
152  br label %5
153
154; <label>:5:                                      ; preds = %1, %3
155  %6 = phi ptr [ %4, %3 ], [ %0, %1 ]
156  ret ptr %6
157}
158
159; Function Attrs: nounwind readnone ssp uwtable
160define ptr @f2(ptr readnone %0) local_unnamed_addr #0 {
161; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
162; TUNIT-LABEL: define {{[^@]+}}@f2
163; TUNIT-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] {
164; TUNIT-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
165; TUNIT-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
166; TUNIT:       3:
167; TUNIT-NEXT:    br label [[TMP5:%.*]]
168; TUNIT:       4:
169; TUNIT-NEXT:    br label [[TMP5]]
170; TUNIT:       5:
171; TUNIT-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ]
172; TUNIT-NEXT:    ret ptr [[TMP6]]
173;
174; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
175; CGSCC-LABEL: define {{[^@]+}}@f2
176; CGSCC-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] {
177; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
178; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
179; CGSCC:       3:
180; CGSCC-NEXT:    br label [[TMP5:%.*]]
181; CGSCC:       4:
182; CGSCC-NEXT:    br label [[TMP5]]
183; CGSCC:       5:
184; CGSCC-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ]
185; CGSCC-NEXT:    ret ptr [[TMP6]]
186;
187  %2 = icmp eq ptr %0, null
188  br i1 %2, label %5, label %3
189
190; <label>:3:                                      ; preds = %1
191
192  %4 = tail call ptr @f1(ptr nonnull %0)
193  br label %7
194
195; <label>:5:                                      ; preds = %1
196  %6 = tail call ptr @f3(ptr nonnull @a2)
197  br label %7
198
199; <label>:7:                                      ; preds = %5, %3
200  %8 = phi ptr [ %4, %3 ], [ %6, %5 ]
201  ret ptr %8
202}
203
204; Function Attrs: nounwind readnone ssp uwtable
205define internal ptr @f3(ptr readnone %0) local_unnamed_addr #0 {
206; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
207; CGSCC-LABEL: define {{[^@]+}}@f3
208; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] {
209; CGSCC-NEXT:    br label [[TMP2:%.*]]
210; CGSCC:       1:
211; CGSCC-NEXT:    unreachable
212; CGSCC:       2:
213; CGSCC-NEXT:    ret ptr undef
214;
215  %2 = icmp eq ptr %0, null
216  br i1 %2, label %3, label %5
217
218; <label>:3:                                      ; preds = %1
219  %4 = tail call ptr @f1(ptr nonnull @a2)
220  br label %5
221
222; <label>:5:                                      ; preds = %1, %3
223  %6 = phi ptr [ %4, %3 ], [ @a1, %1 ]
224  ret ptr %6
225}
226
227; TEST 7
228; Better than IR information
229define align 4 ptr @test7() #0 {
230; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
231; TUNIT-LABEL: define {{[^@]+}}@test7
232; TUNIT-SAME: () #[[ATTR0]] {
233; TUNIT-NEXT:    ret ptr @a1
234;
235; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
236; CGSCC-LABEL: define {{[^@]+}}@test7
237; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
238; CGSCC-NEXT:    [[C:%.*]] = tail call noundef nonnull align 8 dereferenceable(1) ptr @f1() #[[ATTR15:[0-9]+]]
239; CGSCC-NEXT:    ret ptr [[C]]
240;
241  %c = tail call ptr @f1(ptr align 8 dereferenceable(1) @a1)
242  ret ptr %c
243}
244
245; TEST 7b
246; Function Attrs: nounwind readnone ssp uwtable
247define internal ptr @f1b(ptr readnone %0) local_unnamed_addr #0 {
248; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
249; CGSCC-LABEL: define {{[^@]+}}@f1b
250; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] {
251; CGSCC-NEXT:    br label [[TMP2:%.*]]
252; CGSCC:       1:
253; CGSCC-NEXT:    unreachable
254; CGSCC:       2:
255; CGSCC-NEXT:    ret ptr undef
256;
257  %2 = icmp eq ptr %0, null
258  br i1 %2, label %3, label %5
259
260; <label>:3:                                      ; preds = %1
261  %4 = tail call ptr @f2b(ptr nonnull @a1)
262  %l = load i8, ptr %4
263  store i8 %l, ptr @a1
264  br label %5
265
266; <label>:5:                                      ; preds = %1, %3
267  %6 = phi ptr [ %4, %3 ], [ %0, %1 ]
268  ret ptr %6
269}
270
271; Function Attrs: nounwind readnone ssp uwtable
272define internal ptr @f2b(ptr readnone %0) local_unnamed_addr #0 {
273;
274; CGSCC: Function Attrs: noinline nounwind uwtable
275; CGSCC-LABEL: define {{[^@]+}}@f2b
276; CGSCC-SAME: (ptr readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
277; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
278; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
279; CGSCC:       3:
280; CGSCC-NEXT:    [[TMP4:%.*]] = tail call ptr @f1b()
281; CGSCC-NEXT:    br label [[TMP7:%.*]]
282; CGSCC:       5:
283; CGSCC-NEXT:    [[TMP6:%.*]] = tail call ptr @f3b()
284; CGSCC-NEXT:    br label [[TMP7]]
285; CGSCC:       7:
286; CGSCC-NEXT:    [[TMP8:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
287; CGSCC-NEXT:    ret ptr [[TMP8]]
288;
289  %2 = icmp eq ptr %0, null
290  br i1 %2, label %5, label %3
291
292; <label>:3:                                      ; preds = %1
293
294  %4 = tail call ptr @f1b(ptr nonnull %0)
295  br label %7
296
297; <label>:5:                                      ; preds = %1
298  %6 = tail call ptr @f3b(ptr nonnull @a2)
299  br label %7
300
301; <label>:7:                                      ; preds = %5, %3
302  %8 = phi ptr [ %4, %3 ], [ %6, %5 ]
303  ret ptr %8
304}
305
306; Function Attrs: nounwind readnone ssp uwtable
307define internal ptr @f3b(ptr readnone %0) local_unnamed_addr #0 {
308;
309; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
310; CGSCC-LABEL: define {{[^@]+}}@f3b
311; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] {
312; CGSCC-NEXT:    br label [[TMP2:%.*]]
313; CGSCC:       1:
314; CGSCC-NEXT:    unreachable
315; CGSCC:       2:
316; CGSCC-NEXT:    ret ptr @a1
317;
318  %2 = icmp eq ptr %0, null
319  br i1 %2, label %3, label %5
320
321; <label>:3:                                      ; preds = %1
322  %4 = tail call ptr @f1b(ptr nonnull @a2)
323  br label %5
324
325; <label>:5:                                      ; preds = %1, %3
326  %6 = phi ptr [ %4, %3 ], [ @a1, %1 ]
327  ret ptr %6
328}
329
330define align 4 ptr @test7b(ptr align 32 %p) #0 {
331; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
332; TUNIT-LABEL: define {{[^@]+}}@test7b
333; TUNIT-SAME: (ptr nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR0]] {
334; TUNIT-NEXT:    ret ptr [[P]]
335;
336; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
337; CGSCC-LABEL: define {{[^@]+}}@test7b
338; CGSCC-SAME: (ptr nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {
339; CGSCC-NEXT:    ret ptr [[P]]
340;
341  tail call ptr @f1b(ptr align 8 dereferenceable(1) @a1)
342  ret ptr %p
343}
344
345; TEST 8
346define void @test8_helper() {
347; TUNIT-LABEL: define {{[^@]+}}@test8_helper() {
348; TUNIT-NEXT:    [[PTR0:%.*]] = tail call ptr @unknown()
349; TUNIT-NEXT:    [[PTR1:%.*]] = tail call align 4 ptr @unknown()
350; TUNIT-NEXT:    [[PTR2:%.*]] = tail call align 8 ptr @unknown()
351; TUNIT-NEXT:    tail call void @test8(ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone captures(none) [[PTR0]]) #[[ATTR2:[0-9]+]]
352; TUNIT-NEXT:    tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR2]]
353; TUNIT-NEXT:    tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR2]]
354; TUNIT-NEXT:    ret void
355;
356; CGSCC-LABEL: define {{[^@]+}}@test8_helper() {
357; CGSCC-NEXT:    [[PTR0:%.*]] = tail call ptr @unknown()
358; CGSCC-NEXT:    [[PTR1:%.*]] = tail call align 4 ptr @unknown()
359; CGSCC-NEXT:    [[PTR2:%.*]] = tail call align 8 ptr @unknown()
360; CGSCC-NEXT:    tail call void @test8(ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone captures(none) [[PTR0]]) #[[ATTR3:[0-9]+]]
361; CGSCC-NEXT:    tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR3]]
362; CGSCC-NEXT:    tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR3]]
363; CGSCC-NEXT:    ret void
364;
365  %ptr0 = tail call ptr @unknown()
366  %ptr1 = tail call align 4 ptr @unknown()
367  %ptr2 = tail call align 8 ptr @unknown()
368
369  tail call void @test8(ptr %ptr1, ptr %ptr1, ptr %ptr0)
370  tail call void @test8(ptr %ptr2, ptr %ptr1, ptr %ptr1)
371  tail call void @test8(ptr %ptr2, ptr %ptr1, ptr %ptr1)
372  ret void
373}
374
375declare void @user_i32_ptr(ptr nocapture readnone) nounwind
376define internal void @test8(ptr %a, ptr %b, ptr %c) {
377; TUNIT: Function Attrs: nounwind
378; TUNIT-LABEL: define {{[^@]+}}@test8
379; TUNIT-SAME: (ptr noalias nofree readnone align 4 captures(none) [[A:%.*]], ptr noalias nofree readnone align 4 captures(none) [[B:%.*]], ptr noalias nofree readnone captures(none) [[C:%.*]]) #[[ATTR2]] {
380; TUNIT-NEXT:    call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[A]]) #[[ATTR2]]
381; TUNIT-NEXT:    call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[B]]) #[[ATTR2]]
382; TUNIT-NEXT:    call void @user_i32_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR2]]
383; TUNIT-NEXT:    ret void
384;
385; CGSCC: Function Attrs: nounwind
386; CGSCC-LABEL: define {{[^@]+}}@test8
387; CGSCC-SAME: (ptr noalias nofree readnone align 4 captures(none) [[A:%.*]], ptr noalias nofree readnone align 4 captures(none) [[B:%.*]], ptr noalias nofree readnone captures(none) [[C:%.*]]) #[[ATTR3]] {
388; CGSCC-NEXT:    call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[A]]) #[[ATTR3]]
389; CGSCC-NEXT:    call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[B]]) #[[ATTR3]]
390; CGSCC-NEXT:    call void @user_i32_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR3]]
391; CGSCC-NEXT:    ret void
392;
393  call void @user_i32_ptr(ptr %a)
394  call void @user_i32_ptr(ptr %b)
395  call void @user_i32_ptr(ptr %c)
396  ret void
397}
398
399declare void @test9_helper(ptr %A)
400define void @test9_traversal(i1 %cnd, ptr align 4 %B, ptr align 8 %C) {
401; CHECK-LABEL: define {{[^@]+}}@test9_traversal
402; CHECK-SAME: (i1 [[CND:%.*]], ptr align 4 [[B:%.*]], ptr align 8 [[C:%.*]]) {
403; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CND]], ptr [[B]], ptr [[C]]
404; CHECK-NEXT:    call void @test9_helper(ptr align 4 [[SEL]])
405; CHECK-NEXT:    ret void
406;
407  %sel = select i1 %cnd, ptr %B, ptr %C
408  call void @test9_helper(ptr %sel)
409  ret void
410}
411
412; FIXME: This will work with an upcoming patch (D66618 or similar)
413;             define align 32 ptr @test10a(ptr align 32 "no-capture-maybe-returned" %p)
414; FIXME: This will work with an upcoming patch (D66618 or similar)
415;             store i32 1, ptr %r, align 32
416; FIXME: This will work with an upcoming patch (D66618 or similar)
417;             store i32 -1, ptr %g1, align 32
418define ptr @test10a(ptr align 32 %p) {
419; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
420; TUNIT-LABEL: define {{[^@]+}}@test10a
421; TUNIT-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3:[0-9]+]] {
422; TUNIT-NEXT:    [[L:%.*]] = load i32, ptr [[P]], align 32
423; TUNIT-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 0
424; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
425; TUNIT:       t:
426; TUNIT-NEXT:    [[R:%.*]] = call align 32 ptr @test10a(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR13:[0-9]+]]
427; TUNIT-NEXT:    store i32 1, ptr [[R]], align 32
428; TUNIT-NEXT:    [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8
429; TUNIT-NEXT:    br label [[E:%.*]]
430; TUNIT:       f:
431; TUNIT-NEXT:    [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 8
432; TUNIT-NEXT:    store i32 -1, ptr [[G1]], align 32
433; TUNIT-NEXT:    br label [[E]]
434; TUNIT:       e:
435; TUNIT-NEXT:    [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
436; TUNIT-NEXT:    ret ptr [[PHI]]
437;
438; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
439; CGSCC-LABEL: define {{[^@]+}}@test10a
440; CGSCC-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4:[0-9]+]] {
441; CGSCC-NEXT:    [[L:%.*]] = load i32, ptr [[P]], align 32
442; CGSCC-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 0
443; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
444; CGSCC:       t:
445; CGSCC-NEXT:    [[R:%.*]] = call align 32 ptr @test10a(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR16:[0-9]+]]
446; CGSCC-NEXT:    store i32 1, ptr [[R]], align 32
447; CGSCC-NEXT:    [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8
448; CGSCC-NEXT:    br label [[E:%.*]]
449; CGSCC:       f:
450; CGSCC-NEXT:    [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 8
451; CGSCC-NEXT:    store i32 -1, ptr [[G1]], align 32
452; CGSCC-NEXT:    br label [[E]]
453; CGSCC:       e:
454; CGSCC-NEXT:    [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
455; CGSCC-NEXT:    ret ptr [[PHI]]
456;
457  %l = load i32, ptr %p
458  %c = icmp eq i32 %l, 0
459  br i1 %c, label %t, label %f
460t:
461  %r = call ptr @test10a(ptr %p)
462  store i32 1, ptr %r
463  %g0 = getelementptr i32, ptr %p, i32 8
464  br label %e
465f:
466  %g1 = getelementptr i32, ptr %p, i32 8
467  store i32 -1, ptr %g1
468  br label %e
469e:
470  %phi = phi ptr [%g0, %t], [%g1, %f]
471  ret ptr %phi
472}
473
474; FIXME: This will work with an upcoming patch (D66618 or similar)
475;             define align 32 ptr @test10b(ptr align 32 "no-capture-maybe-returned" %p)
476; FIXME: This will work with an upcoming patch (D66618 or similar)
477;             store i32 1, ptr %r, align 32
478; FIXME: This will work with an upcoming patch (D66618 or similar)
479;             store i32 -1, ptr %g1, align 32
480define ptr @test10b(ptr align 32 %p) {
481; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
482; TUNIT-LABEL: define {{[^@]+}}@test10b
483; TUNIT-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] {
484; TUNIT-NEXT:    [[L:%.*]] = load i32, ptr [[P]], align 32
485; TUNIT-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 0
486; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
487; TUNIT:       t:
488; TUNIT-NEXT:    [[R:%.*]] = call align 32 ptr @test10b(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR13]]
489; TUNIT-NEXT:    store i32 1, ptr [[R]], align 32
490; TUNIT-NEXT:    [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8
491; TUNIT-NEXT:    br label [[E:%.*]]
492; TUNIT:       f:
493; TUNIT-NEXT:    [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 -8
494; TUNIT-NEXT:    store i32 -1, ptr [[G1]], align 32
495; TUNIT-NEXT:    br label [[E]]
496; TUNIT:       e:
497; TUNIT-NEXT:    [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
498; TUNIT-NEXT:    ret ptr [[PHI]]
499;
500; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
501; CGSCC-LABEL: define {{[^@]+}}@test10b
502; CGSCC-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] {
503; CGSCC-NEXT:    [[L:%.*]] = load i32, ptr [[P]], align 32
504; CGSCC-NEXT:    [[C:%.*]] = icmp eq i32 [[L]], 0
505; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
506; CGSCC:       t:
507; CGSCC-NEXT:    [[R:%.*]] = call align 32 ptr @test10b(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR16]]
508; CGSCC-NEXT:    store i32 1, ptr [[R]], align 32
509; CGSCC-NEXT:    [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8
510; CGSCC-NEXT:    br label [[E:%.*]]
511; CGSCC:       f:
512; CGSCC-NEXT:    [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 -8
513; CGSCC-NEXT:    store i32 -1, ptr [[G1]], align 32
514; CGSCC-NEXT:    br label [[E]]
515; CGSCC:       e:
516; CGSCC-NEXT:    [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
517; CGSCC-NEXT:    ret ptr [[PHI]]
518;
519  %l = load i32, ptr %p
520  %c = icmp eq i32 %l, 0
521  br i1 %c, label %t, label %f
522t:
523  %r = call ptr @test10b(ptr %p)
524  store i32 1, ptr %r
525  %g0 = getelementptr i32, ptr %p, i32 8
526  br label %e
527f:
528  %g1 = getelementptr i32, ptr %p, i32 -8
529  store i32 -1, ptr %g1
530  br label %e
531e:
532  %phi = phi ptr [%g0, %t], [%g1, %f]
533  ret ptr %phi
534}
535
536
537define i64 @test11(ptr %p) {
538; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
539; TUNIT-LABEL: define {{[^@]+}}@test11
540; TUNIT-SAME: (ptr nofree nonnull readonly align 8 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR4:[0-9]+]] {
541; TUNIT-NEXT:    [[RET:%.*]] = load i64, ptr [[P]], align 8
542; TUNIT-NEXT:    ret i64 [[RET]]
543;
544; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
545; CGSCC-LABEL: define {{[^@]+}}@test11
546; CGSCC-SAME: (ptr nofree nonnull readonly align 8 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR5:[0-9]+]] {
547; CGSCC-NEXT:    [[RET:%.*]] = load i64, ptr [[P]], align 8
548; CGSCC-NEXT:    ret i64 [[RET]]
549;
550  %p-cast = bitcast ptr %p to ptr
551  %ret = load i64, ptr %p-cast, align 8
552  ret i64 %ret
553}
554
555; TEST 12
556; Test for deduction using must-be-executed-context and GEP instruction
557
558; FXIME: %p should have nonnull
559define i64 @test12-1(ptr align 4 %p) {
560; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
561; TUNIT-LABEL: define {{[^@]+}}@test12-1
562; TUNIT-SAME: (ptr nofree readonly align 16 captures(none) [[P:%.*]]) #[[ATTR4]] {
563; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
564; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
565; TUNIT-NEXT:    [[RET:%.*]] = load i64, ptr [[ARRAYIDX1]], align 16
566; TUNIT-NEXT:    ret i64 [[RET]]
567;
568; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
569; CGSCC-LABEL: define {{[^@]+}}@test12-1
570; CGSCC-SAME: (ptr nofree readonly align 16 captures(none) [[P:%.*]]) #[[ATTR5]] {
571; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
572; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
573; CGSCC-NEXT:    [[RET:%.*]] = load i64, ptr [[ARRAYIDX1]], align 16
574; CGSCC-NEXT:    ret i64 [[RET]]
575;
576  %p-cast = bitcast ptr %p to ptr
577  %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1
578  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
579  %ret = load i64, ptr %arrayidx1, align 16
580  ret i64 %ret
581}
582
583define i64 @test12-2(ptr align 4 %p) {
584; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
585; TUNIT-LABEL: define {{[^@]+}}@test12-2
586; TUNIT-SAME: (ptr nofree nonnull readonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR4]] {
587; TUNIT-NEXT:    [[RET:%.*]] = load i64, ptr [[P]], align 16
588; TUNIT-NEXT:    ret i64 [[RET]]
589;
590; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
591; CGSCC-LABEL: define {{[^@]+}}@test12-2
592; CGSCC-SAME: (ptr nofree nonnull readonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR5]] {
593; CGSCC-NEXT:    [[RET:%.*]] = load i64, ptr [[P]], align 16
594; CGSCC-NEXT:    ret i64 [[RET]]
595;
596  %p-cast = bitcast ptr %p to ptr
597  %ret = load i64, ptr %p-cast, align 16
598  ret i64 %ret
599}
600
601; FXIME: %p should have nonnull
602define void @test12-3(ptr align 4 %p) {
603; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
604; TUNIT-LABEL: define {{[^@]+}}@test12-3
605; TUNIT-SAME: (ptr nofree writeonly align 16 captures(none) [[P:%.*]]) #[[ATTR5:[0-9]+]] {
606; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
607; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
608; TUNIT-NEXT:    store i64 0, ptr [[ARRAYIDX1]], align 16
609; TUNIT-NEXT:    ret void
610;
611; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
612; CGSCC-LABEL: define {{[^@]+}}@test12-3
613; CGSCC-SAME: (ptr nofree writeonly align 16 captures(none) [[P:%.*]]) #[[ATTR6:[0-9]+]] {
614; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
615; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
616; CGSCC-NEXT:    store i64 0, ptr [[ARRAYIDX1]], align 16
617; CGSCC-NEXT:    ret void
618;
619  %p-cast = bitcast ptr %p to ptr
620  %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1
621  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
622  store i64 0, ptr %arrayidx1, align 16
623  ret void
624}
625
626define void @test12-4(ptr align 4 %p) {
627; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
628; TUNIT-LABEL: define {{[^@]+}}@test12-4
629; TUNIT-SAME: (ptr nofree nonnull writeonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR5]] {
630; TUNIT-NEXT:    store i64 0, ptr [[P]], align 16
631; TUNIT-NEXT:    ret void
632;
633; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
634; CGSCC-LABEL: define {{[^@]+}}@test12-4
635; CGSCC-SAME: (ptr nofree nonnull writeonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR6]] {
636; CGSCC-NEXT:    store i64 0, ptr [[P]], align 16
637; CGSCC-NEXT:    ret void
638;
639  %p-cast = bitcast ptr %p to ptr
640  store i64 0, ptr %p-cast, align 16
641  ret void
642}
643
644declare void @use(ptr) willreturn nounwind
645
646define void @test12-5(ptr align 4 %p) {
647; TUNIT: Function Attrs: mustprogress nounwind willreturn
648; TUNIT-LABEL: define {{[^@]+}}@test12-5
649; TUNIT-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR7:[0-9]+]] {
650; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
651; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
652; TUNIT-NEXT:    tail call void @use(ptr align 16 [[ARRAYIDX1]]) #[[ATTR6:[0-9]+]]
653; TUNIT-NEXT:    ret void
654;
655; CGSCC: Function Attrs: mustprogress nounwind willreturn
656; CGSCC-LABEL: define {{[^@]+}}@test12-5
657; CGSCC-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR8:[0-9]+]] {
658; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
659; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
660; CGSCC-NEXT:    tail call void @use(ptr align 16 [[ARRAYIDX1]]) #[[ATTR7:[0-9]+]]
661; CGSCC-NEXT:    ret void
662;
663  %p-cast = bitcast ptr %p to ptr
664  %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1
665  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
666  tail call void @use(ptr align 16 %arrayidx1)
667  ret void
668}
669
670define void @test12-6(ptr align 4 %p) {
671; TUNIT: Function Attrs: mustprogress nounwind willreturn
672; TUNIT-LABEL: define {{[^@]+}}@test12-6
673; TUNIT-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR7]] {
674; TUNIT-NEXT:    tail call void @use(ptr align 16 [[P]]) #[[ATTR6]]
675; TUNIT-NEXT:    ret void
676;
677; CGSCC: Function Attrs: mustprogress nounwind willreturn
678; CGSCC-LABEL: define {{[^@]+}}@test12-6
679; CGSCC-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR8]] {
680; CGSCC-NEXT:    tail call void @use(ptr align 16 [[P]]) #[[ATTR7]]
681; CGSCC-NEXT:    ret void
682;
683  %p-cast = bitcast ptr %p to ptr
684  tail call void @use(ptr align 16 %p-cast)
685  ret void
686}
687
688define void @test13(i1 %c, ptr align 32 %dst) #0 {
689; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable
690; TUNIT-LABEL: define {{[^@]+}}@test13
691; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR8:[0-9]+]] {
692; TUNIT-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
693; TUNIT:       truebb:
694; TUNIT-NEXT:    br label [[END:%.*]]
695; TUNIT:       falsebb:
696; TUNIT-NEXT:    br label [[END]]
697; TUNIT:       end:
698; TUNIT-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ]
699; TUNIT-NEXT:    store i32 0, ptr [[PTR]], align 32
700; TUNIT-NEXT:    ret void
701;
702; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable
703; CGSCC-LABEL: define {{[^@]+}}@test13
704; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9:[0-9]+]] {
705; CGSCC-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
706; CGSCC:       truebb:
707; CGSCC-NEXT:    br label [[END:%.*]]
708; CGSCC:       falsebb:
709; CGSCC-NEXT:    br label [[END]]
710; CGSCC:       end:
711; CGSCC-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ]
712; CGSCC-NEXT:    store i32 0, ptr [[PTR]], align 32
713; CGSCC-NEXT:    ret void
714;
715  br i1 %c, label %truebb, label %falsebb
716truebb:
717  br label %end
718falsebb:
719  br label %end
720end:
721  %ptr = phi ptr [ %dst, %truebb ], [ null, %falsebb ]
722  store i32 0, ptr %ptr
723  ret void
724}
725
726define void @test13-1(i1 %c, ptr align 32 %dst) {
727; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
728; TUNIT-LABEL: define {{[^@]+}}@test13-1
729; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9:[0-9]+]] {
730; TUNIT-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
731; TUNIT:       truebb:
732; TUNIT-NEXT:    br label [[END:%.*]]
733; TUNIT:       falsebb:
734; TUNIT-NEXT:    br label [[END]]
735; TUNIT:       end:
736; TUNIT-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to ptr), [[FALSEBB]] ]
737; TUNIT-NEXT:    store i32 0, ptr [[PTR]], align 16
738; TUNIT-NEXT:    ret void
739;
740; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
741; CGSCC-LABEL: define {{[^@]+}}@test13-1
742; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR10:[0-9]+]] {
743; CGSCC-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
744; CGSCC:       truebb:
745; CGSCC-NEXT:    br label [[END:%.*]]
746; CGSCC:       falsebb:
747; CGSCC-NEXT:    br label [[END]]
748; CGSCC:       end:
749; CGSCC-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to ptr), [[FALSEBB]] ]
750; CGSCC-NEXT:    store i32 0, ptr [[PTR]], align 16
751; CGSCC-NEXT:    ret void
752;
753  br i1 %c, label %truebb, label %falsebb
754truebb:
755  br label %end
756falsebb:
757  br label %end
758end:
759  %ptr = phi ptr [ %dst, %truebb ], [ inttoptr (i64 48 to ptr), %falsebb ]
760  store i32 0, ptr %ptr
761  ret void
762}
763
764define void @test13-2(i1 %c, ptr align 32 %dst) {
765; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
766; TUNIT-LABEL: define {{[^@]+}}@test13-2
767; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9]] {
768; TUNIT-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
769; TUNIT:       truebb:
770; TUNIT-NEXT:    br label [[END:%.*]]
771; TUNIT:       falsebb:
772; TUNIT-NEXT:    br label [[END]]
773; TUNIT:       end:
774; TUNIT-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to ptr), [[FALSEBB]] ]
775; TUNIT-NEXT:    store i32 0, ptr [[PTR]], align 32
776; TUNIT-NEXT:    ret void
777;
778; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
779; CGSCC-LABEL: define {{[^@]+}}@test13-2
780; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR10]] {
781; CGSCC-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
782; CGSCC:       truebb:
783; CGSCC-NEXT:    br label [[END:%.*]]
784; CGSCC:       falsebb:
785; CGSCC-NEXT:    br label [[END]]
786; CGSCC:       end:
787; CGSCC-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to ptr), [[FALSEBB]] ]
788; CGSCC-NEXT:    store i32 0, ptr [[PTR]], align 32
789; CGSCC-NEXT:    ret void
790;
791  br i1 %c, label %truebb, label %falsebb
792truebb:
793  br label %end
794falsebb:
795  br label %end
796end:
797  %ptr = phi ptr [ %dst, %truebb ], [ inttoptr (i64 160 to ptr), %falsebb ]
798  store i32 0, ptr %ptr
799  ret void
800}
801
802define void @test13-3(i1 %c, ptr align 32 %dst) {
803; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
804; TUNIT-LABEL: define {{[^@]+}}@test13-3
805; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9]] {
806; TUNIT-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
807; TUNIT:       truebb:
808; TUNIT-NEXT:    br label [[END:%.*]]
809; TUNIT:       falsebb:
810; TUNIT-NEXT:    br label [[END]]
811; TUNIT:       end:
812; TUNIT-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to ptr), [[FALSEBB]] ]
813; TUNIT-NEXT:    store i32 0, ptr [[PTR]], align 32
814; TUNIT-NEXT:    ret void
815;
816; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
817; CGSCC-LABEL: define {{[^@]+}}@test13-3
818; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR10]] {
819; CGSCC-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
820; CGSCC:       truebb:
821; CGSCC-NEXT:    br label [[END:%.*]]
822; CGSCC:       falsebb:
823; CGSCC-NEXT:    br label [[END]]
824; CGSCC:       end:
825; CGSCC-NEXT:    [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to ptr), [[FALSEBB]] ]
826; CGSCC-NEXT:    store i32 0, ptr [[PTR]], align 32
827; CGSCC-NEXT:    ret void
828;
829  br i1 %c, label %truebb, label %falsebb
830truebb:
831  br label %end
832falsebb:
833  br label %end
834end:
835  %ptr = phi ptr [ %dst, %truebb ], [ inttoptr (i64 128 to ptr), %falsebb ]
836  store i32 0, ptr %ptr
837  ret void
838}
839
840; Don't crash on ptr2int/int2ptr uses.
841define i64 @ptr2int(ptr %p) {
842; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
843; TUNIT-LABEL: define {{[^@]+}}@ptr2int
844; TUNIT-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR10:[0-9]+]] {
845; TUNIT-NEXT:    [[P2I:%.*]] = ptrtoint ptr [[P]] to i64
846; TUNIT-NEXT:    ret i64 [[P2I]]
847;
848; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
849; CGSCC-LABEL: define {{[^@]+}}@ptr2int
850; CGSCC-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR11:[0-9]+]] {
851; CGSCC-NEXT:    [[P2I:%.*]] = ptrtoint ptr [[P]] to i64
852; CGSCC-NEXT:    ret i64 [[P2I]]
853;
854  %p2i = ptrtoint ptr %p to i64
855  ret i64 %p2i
856}
857define ptr @int2ptr(i64 %i) {
858; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
859; TUNIT-LABEL: define {{[^@]+}}@int2ptr
860; TUNIT-SAME: (i64 [[I:%.*]]) #[[ATTR10]] {
861; TUNIT-NEXT:    [[I2P:%.*]] = inttoptr i64 [[I]] to ptr
862; TUNIT-NEXT:    ret ptr [[I2P]]
863;
864; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
865; CGSCC-LABEL: define {{[^@]+}}@int2ptr
866; CGSCC-SAME: (i64 [[I:%.*]]) #[[ATTR11]] {
867; CGSCC-NEXT:    [[I2P:%.*]] = inttoptr i64 [[I]] to ptr
868; CGSCC-NEXT:    ret ptr [[I2P]]
869;
870  %i2p = inttoptr i64 %i to ptr
871  ret ptr %i2p
872}
873
874; Use the store alignment only for the pointer operand.
875define void @aligned_store(ptr %Value, ptr %Ptr) {
876; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
877; TUNIT-LABEL: define {{[^@]+}}@aligned_store
878; TUNIT-SAME: (ptr nofree writeonly [[VALUE:%.*]], ptr nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(8) [[PTR:%.*]]) #[[ATTR5]] {
879; TUNIT-NEXT:    store ptr [[VALUE]], ptr [[PTR]], align 32
880; TUNIT-NEXT:    ret void
881;
882; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
883; CGSCC-LABEL: define {{[^@]+}}@aligned_store
884; CGSCC-SAME: (ptr nofree writeonly [[VALUE:%.*]], ptr nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(8) [[PTR:%.*]]) #[[ATTR6]] {
885; CGSCC-NEXT:    store ptr [[VALUE]], ptr [[PTR]], align 32
886; CGSCC-NEXT:    ret void
887;
888  store ptr %Value, ptr %Ptr, align 32
889  ret void
890}
891
892declare ptr @some_func(ptr)
893define void @align_call_op_not_store(ptr align 2048 %arg) {
894; CHECK-LABEL: define {{[^@]+}}@align_call_op_not_store
895; CHECK-SAME: (ptr align 2048 [[ARG:%.*]]) {
896; CHECK-NEXT:    [[UNKNOWN:%.*]] = call ptr @some_func(ptr align 2048 [[ARG]])
897; CHECK-NEXT:    store i8 0, ptr [[UNKNOWN]], align 1
898; CHECK-NEXT:    ret void
899;
900  %unknown = call ptr @some_func(ptr %arg)
901  store i8 0, ptr %unknown
902  ret void
903}
904define void @align_store_after_bc(ptr align 2048 %arg) {
905;
906; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
907; TUNIT-LABEL: define {{[^@]+}}@align_store_after_bc
908; TUNIT-SAME: (ptr nofree nonnull writeonly align 2048 captures(none) dereferenceable(1) [[ARG:%.*]]) #[[ATTR5]] {
909; TUNIT-NEXT:    store i8 0, ptr [[ARG]], align 2048
910; TUNIT-NEXT:    ret void
911;
912; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
913; CGSCC-LABEL: define {{[^@]+}}@align_store_after_bc
914; CGSCC-SAME: (ptr nofree nonnull writeonly align 2048 captures(none) dereferenceable(1) [[ARG:%.*]]) #[[ATTR6]] {
915; CGSCC-NEXT:    store i8 0, ptr [[ARG]], align 2048
916; CGSCC-NEXT:    ret void
917;
918  %bc = bitcast ptr %arg to ptr
919  store i8 0, ptr %bc
920  ret void
921}
922
923; Make sure we do not annotate the callee of a must-tail call with an alignment
924; we cannot also put on the caller.
925@cnd = external global i1
926define i32 @musttail_callee_1(ptr %p) {
927; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
928; TUNIT-LABEL: define {{[^@]+}}@musttail_callee_1
929; TUNIT-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR4]] {
930; TUNIT-NEXT:    [[V:%.*]] = load i32, ptr [[P]], align 32
931; TUNIT-NEXT:    ret i32 [[V]]
932;
933; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
934; CGSCC-LABEL: define {{[^@]+}}@musttail_callee_1
935; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR5]] {
936; CGSCC-NEXT:    [[V:%.*]] = load i32, ptr [[P]], align 32
937; CGSCC-NEXT:    ret i32 [[V]]
938;
939  %v = load i32, ptr %p, align 32
940  ret i32 %v
941}
942define i32 @musttail_caller_1(ptr %p) {
943; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
944; TUNIT-LABEL: define {{[^@]+}}@musttail_caller_1
945; TUNIT-SAME: (ptr nofree readonly captures(none) [[P:%.*]]) #[[ATTR11:[0-9]+]] {
946; TUNIT-NEXT:    [[C:%.*]] = load i1, ptr @cnd, align 1
947; TUNIT-NEXT:    br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]]
948; TUNIT:       mt:
949; TUNIT-NEXT:    [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nofree noundef readonly captures(none) [[P]]) #[[ATTR14:[0-9]+]]
950; TUNIT-NEXT:    ret i32 [[V]]
951; TUNIT:       exit:
952; TUNIT-NEXT:    ret i32 0
953;
954; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
955; CGSCC-LABEL: define {{[^@]+}}@musttail_caller_1
956; CGSCC-SAME: (ptr nofree readonly captures(none) [[P:%.*]]) #[[ATTR12:[0-9]+]] {
957; CGSCC-NEXT:    [[C:%.*]] = load i1, ptr @cnd, align 1
958; CGSCC-NEXT:    br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]]
959; CGSCC:       mt:
960; CGSCC-NEXT:    [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nofree noundef nonnull readonly captures(none) dereferenceable(4) [[P]]) #[[ATTR17:[0-9]+]]
961; CGSCC-NEXT:    ret i32 [[V]]
962; CGSCC:       exit:
963; CGSCC-NEXT:    ret i32 0
964;
965  %c = load i1, ptr @cnd
966  br i1 %c, label %mt, label %exit
967mt:
968  %v = musttail call i32 @musttail_callee_1(ptr %p)
969  ret i32 %v
970exit:
971  ret i32 0
972}
973
974define ptr @checkAndAdvance(ptr align(16) %p) {
975; TUNIT: Function Attrs: nounwind
976; TUNIT-LABEL: define {{[^@]+}}@checkAndAdvance
977; TUNIT-SAME: (ptr nofree noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR2]] {
978; TUNIT-NEXT:  entry:
979; TUNIT-NEXT:    [[TMP0:%.*]] = load i32, ptr [[P]], align 16
980; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
981; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
982; TUNIT:       if.then:
983; TUNIT-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 4
984; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @checkAndAdvance(ptr nofree noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR2]]
985; TUNIT-NEXT:    br label [[RETURN]]
986; TUNIT:       return:
987; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ]
988; TUNIT-NEXT:    call void @user_i32_ptr(ptr noalias nofree nonnull readnone align 16 captures(none) [[RETVAL_0]]) #[[ATTR2]]
989; TUNIT-NEXT:    ret ptr [[RETVAL_0]]
990;
991; CGSCC: Function Attrs: nounwind
992; CGSCC-LABEL: define {{[^@]+}}@checkAndAdvance
993; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] {
994; CGSCC-NEXT:  entry:
995; CGSCC-NEXT:    [[TMP0:%.*]] = load i32, ptr [[P]], align 16
996; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
997; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
998; CGSCC:       if.then:
999; CGSCC-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 4
1000; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @checkAndAdvance(ptr nofree noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR3]]
1001; CGSCC-NEXT:    br label [[RETURN]]
1002; CGSCC:       return:
1003; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ]
1004; CGSCC-NEXT:    call void @user_i32_ptr(ptr noalias nofree nonnull readnone align 16 captures(none) [[RETVAL_0]]) #[[ATTR3]]
1005; CGSCC-NEXT:    ret ptr [[RETVAL_0]]
1006;
1007entry:
1008  %0 = load i32, ptr %p, align 4
1009  %cmp = icmp eq i32 %0, 0
1010  br i1 %cmp, label %if.then, label %return
1011
1012if.then:                                          ; preds = %entry
1013  %add.ptr = getelementptr inbounds i32, ptr %p, i64 4
1014  %call = call ptr @checkAndAdvance(ptr nonnull %add.ptr)
1015  br label %return
1016
1017return:                                           ; preds = %entry, %if.then
1018  %retval.0 = phi ptr [ %call, %if.then ], [ %p, %entry ]
1019  call void @user_i32_ptr(ptr %retval.0)
1020  ret ptr %retval.0
1021}
1022
1023; FIXME: align 4 should not be propagated to the caller's p unless there is noundef
1024define void @align4_caller(ptr %p) {
1025; CHECK-LABEL: define {{[^@]+}}@align4_caller
1026; CHECK-SAME: (ptr align 4 [[P:%.*]]) {
1027; CHECK-NEXT:    call void @align4_callee(ptr align 4 [[P]])
1028; CHECK-NEXT:    ret void
1029;
1030  call void @align4_callee(ptr %p)
1031  ret void
1032}
1033
1034declare void @align4_callee(ptr align(4) %p)
1035
1036@G = global i8 0, align 32
1037
1038define internal ptr @aligned_8_return(ptr %a, i1 %c1, i1 %c2) norecurse {
1039; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1040; TUNIT-LABEL: define {{[^@]+}}@aligned_8_return
1041; TUNIT-SAME: (ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR10]] {
1042; TUNIT-NEXT:    [[STACK:%.*]] = alloca ptr, align 8
1043; TUNIT-NEXT:    br i1 [[C1]], label [[T:%.*]], label [[F:%.*]]
1044; TUNIT:       t:
1045; TUNIT-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr @G, i32 8
1046; TUNIT-NEXT:    [[SEL:%.*]] = select i1 [[C2]], ptr [[A]], ptr [[GEP]]
1047; TUNIT-NEXT:    store ptr [[SEL]], ptr [[STACK]], align 8
1048; TUNIT-NEXT:    br label [[END:%.*]]
1049; TUNIT:       f:
1050; TUNIT-NEXT:    store ptr @G, ptr [[STACK]], align 8
1051; TUNIT-NEXT:    br label [[END]]
1052; TUNIT:       end:
1053; TUNIT-NEXT:    [[L:%.*]] = load ptr, ptr [[STACK]], align 8
1054; TUNIT-NEXT:    ret ptr [[L]]
1055;
1056; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1057; CGSCC-LABEL: define {{[^@]+}}@aligned_8_return
1058; CGSCC-SAME: (ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR11]] {
1059; CGSCC-NEXT:    [[STACK:%.*]] = alloca ptr, align 8
1060; CGSCC-NEXT:    br i1 [[C1]], label [[T:%.*]], label [[F:%.*]]
1061; CGSCC:       t:
1062; CGSCC-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr @G, i32 8
1063; CGSCC-NEXT:    [[SEL:%.*]] = select i1 [[C2]], ptr [[A]], ptr [[GEP]]
1064; CGSCC-NEXT:    store ptr [[SEL]], ptr [[STACK]], align 8
1065; CGSCC-NEXT:    br label [[END:%.*]]
1066; CGSCC:       f:
1067; CGSCC-NEXT:    store ptr @G, ptr [[STACK]], align 8
1068; CGSCC-NEXT:    br label [[END]]
1069; CGSCC:       end:
1070; CGSCC-NEXT:    [[L:%.*]] = load ptr, ptr [[STACK]], align 8
1071; CGSCC-NEXT:    ret ptr [[L]]
1072;
1073  %stack = alloca ptr
1074  br i1 %c1, label %t, label %f
1075t:
1076  %gep = getelementptr i8, ptr @G, i32 8
1077  %sel = select i1 %c2, ptr %a, ptr %gep
1078  store ptr %sel, ptr %stack
1079  br label %end
1080f:
1081  store ptr @G, ptr %stack
1082  br label %end
1083end:
1084  %l = load ptr, ptr %stack
1085  ret ptr %l
1086}
1087
1088define ptr @aligned_8_return_caller(ptr align(16) %a, i1 %c1, i1 %c2) {
1089; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1090; TUNIT-LABEL: define {{[^@]+}}@aligned_8_return_caller
1091; TUNIT-SAME: (ptr nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR10]] {
1092; TUNIT-NEXT:    [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR15:[0-9]+]]
1093; TUNIT-NEXT:    ret ptr [[R]]
1094;
1095; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
1096; CGSCC-LABEL: define {{[^@]+}}@aligned_8_return_caller
1097; CGSCC-SAME: (ptr nofree readnone align 16 [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR13:[0-9]+]] {
1098; CGSCC-NEXT:    [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR15]]
1099; CGSCC-NEXT:    ret ptr [[R]]
1100;
1101  %r = call ptr @aligned_8_return(ptr %a, i1 %c1, i1 %c2)
1102  ret ptr %r
1103}
1104
1105define i32 @implicit_cast_caller(ptr %ptr) {
1106; CHECK-LABEL: define {{[^@]+}}@implicit_cast_caller
1107; CHECK-SAME: (ptr [[PTR:%.*]]) {
1108; CHECK-NEXT:  entry:
1109; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @implicit_cast_callee(ptr [[PTR]])
1110; CHECK-NEXT:    ret i32 0
1111;
1112entry:
1113  %call = tail call i32 @implicit_cast_callee(ptr %ptr)
1114  ret i32 0
1115}
1116
1117define i64 @infer_align_atomicrmw(ptr align 4 %p) {
1118; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1119; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw
1120; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR12:[0-9]+]] {
1121; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1122; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1123; TUNIT-NEXT:    [[RET:%.*]] = atomicrmw add ptr [[ARRAYIDX1]], i64 4 seq_cst, align 16
1124; TUNIT-NEXT:    ret i64 [[RET]]
1125;
1126; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1127; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw
1128; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR14:[0-9]+]] {
1129; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1130; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1131; CGSCC-NEXT:    [[RET:%.*]] = atomicrmw add ptr [[ARRAYIDX1]], i64 4 seq_cst, align 16
1132; CGSCC-NEXT:    ret i64 [[RET]]
1133;
1134  %arrayidx0 = getelementptr i64, ptr %p, i64 1
1135  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
1136  %ret = atomicrmw add ptr %arrayidx1, i64 4 seq_cst, align 16
1137  ret i64 %ret
1138}
1139
1140define ptr @infer_align_atomicrmw_ptr(ptr align 4 %p, ptr %val) {
1141; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1142; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr
1143; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr nofree [[VAL:%.*]]) #[[ATTR12]] {
1144; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1145; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1146; TUNIT-NEXT:    [[RET:%.*]] = atomicrmw xchg ptr [[ARRAYIDX1]], ptr [[VAL]] seq_cst, align 16
1147; TUNIT-NEXT:    ret ptr [[RET]]
1148;
1149; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1150; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr
1151; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr nofree [[VAL:%.*]]) #[[ATTR14]] {
1152; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1153; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1154; CGSCC-NEXT:    [[RET:%.*]] = atomicrmw xchg ptr [[ARRAYIDX1]], ptr [[VAL]] seq_cst, align 16
1155; CGSCC-NEXT:    ret ptr [[RET]]
1156;
1157  %arrayidx0 = getelementptr i64, ptr %p, i64 1
1158  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
1159  %ret = atomicrmw xchg ptr %arrayidx1, ptr %val seq_cst, align 16
1160  ret ptr %ret
1161}
1162
1163define i64 @infer_align_cmpxchg(ptr align 4 %p) {
1164; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1165; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg
1166; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR12]] {
1167; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1168; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1169; TUNIT-NEXT:    [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], i64 4, i64 1 seq_cst seq_cst, align 16
1170; TUNIT-NEXT:    [[RET:%.*]] = extractvalue { i64, i1 } [[CMPX]], 0
1171; TUNIT-NEXT:    ret i64 [[RET]]
1172;
1173; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1174; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg
1175; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR14]] {
1176; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1177; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1178; CGSCC-NEXT:    [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], i64 4, i64 1 seq_cst seq_cst, align 16
1179; CGSCC-NEXT:    [[RET:%.*]] = extractvalue { i64, i1 } [[CMPX]], 0
1180; CGSCC-NEXT:    ret i64 [[RET]]
1181;
1182  %arrayidx0 = getelementptr i64, ptr %p, i64 1
1183  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
1184  %cmpx = cmpxchg ptr %arrayidx1, i64 4, i64 1 seq_cst seq_cst, align 16
1185  %ret = extractvalue { i64, i1 } %cmpx, 0
1186  ret i64 %ret
1187}
1188
1189define ptr @infer_align_cmpxchg_ptr(ptr align 4 %p, ptr %cmp0, ptr %cmp1) {
1190; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1191; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr
1192; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr nofree [[CMP0:%.*]], ptr nofree [[CMP1:%.*]]) #[[ATTR12]] {
1193; TUNIT-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1194; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1195; TUNIT-NEXT:    [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], ptr [[CMP0]], ptr [[CMP1]] seq_cst seq_cst, align 16
1196; TUNIT-NEXT:    [[RET:%.*]] = extractvalue { ptr, i1 } [[CMPX]], 0
1197; TUNIT-NEXT:    ret ptr [[RET]]
1198;
1199; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
1200; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr
1201; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr nofree [[CMP0:%.*]], ptr nofree [[CMP1:%.*]]) #[[ATTR14]] {
1202; CGSCC-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1
1203; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3
1204; CGSCC-NEXT:    [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], ptr [[CMP0]], ptr [[CMP1]] seq_cst seq_cst, align 16
1205; CGSCC-NEXT:    [[RET:%.*]] = extractvalue { ptr, i1 } [[CMPX]], 0
1206; CGSCC-NEXT:    ret ptr [[RET]]
1207;
1208  %arrayidx0 = getelementptr i64, ptr %p, i64 1
1209  %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3
1210  %cmpx = cmpxchg ptr %arrayidx1, ptr %cmp0, ptr %cmp1 seq_cst seq_cst, align 16
1211  %ret = extractvalue { ptr, i1 } %cmpx, 0
1212  ret ptr %ret
1213}
1214
1215declare void @implicit_cast_callee(i64)
1216
1217attributes #0 = { nounwind uwtable noinline }
1218attributes #1 = { uwtable noinline }
1219attributes #2 = { null_pointer_is_valid }
1220;.
1221; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
1222; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
1223; TUNIT: attributes #[[ATTR2]] = { nounwind }
1224; TUNIT: attributes #[[ATTR3]] = { nofree nosync nounwind memory(argmem: readwrite) }
1225; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
1226; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
1227; TUNIT: attributes #[[ATTR6]] = { nounwind willreturn }
1228; TUNIT: attributes #[[ATTR7]] = { mustprogress nounwind willreturn }
1229; TUNIT: attributes #[[ATTR8]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable }
1230; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
1231; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
1232; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) }
1233; TUNIT: attributes #[[ATTR12]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
1234; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind }
1235; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn memory(read) }
1236; TUNIT: attributes #[[ATTR15]] = { nofree nosync nounwind willreturn }
1237;.
1238; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
1239; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
1240; CGSCC: attributes #[[ATTR2]] = { noinline nounwind uwtable }
1241; CGSCC: attributes #[[ATTR3]] = { nounwind }
1242; CGSCC: attributes #[[ATTR4]] = { nofree nosync nounwind memory(argmem: readwrite) }
1243; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
1244; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
1245; CGSCC: attributes #[[ATTR7]] = { nounwind willreturn }
1246; CGSCC: attributes #[[ATTR8]] = { mustprogress nounwind willreturn }
1247; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable }
1248; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
1249; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
1250; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree nosync nounwind willreturn memory(read) }
1251; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
1252; CGSCC: attributes #[[ATTR14]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
1253; CGSCC: attributes #[[ATTR15]] = { nofree nosync willreturn }
1254; CGSCC: attributes #[[ATTR16]] = { nofree nosync nounwind }
1255; CGSCC: attributes #[[ATTR17]] = { nofree willreturn memory(read) }
1256;.
1257