1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --disable --function-signature --scrub-attributes
2; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE
3; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC
4; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE
5; RUN: opt -passes=attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC
6
7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
8
9; Test cases specifically designed for "align" attribute.
10; We use FIXME's to indicate problems and missing attributes.
11
12
13; TEST 1
14; ATTRIBUTOR: define align 8 i32* @test1(i32* nofree readnone returned align 8 "no-capture-maybe-returned" %0)
15define i32* @test1(i32* align 8 %0) #0 {
16  ret i32* %0
17}
18
19; TEST 2
20; ATTRIBUTOR: define i32* @test2(i32* nofree readnone returned "no-capture-maybe-returned" %0)
21define i32* @test2(i32* %0) #0 {
22  ret i32* %0
23}
24
25; TEST 3
26; ATTRIBUTOR: define align 4 i32* @test3(i32* nofree readnone align 8 "no-capture-maybe-returned" %0, i32* nofree readnone align 4 "no-capture-maybe-returned" %1, i1 %2)
27define i32* @test3(i32* align 8 %0, i32* align 4 %1, i1 %2) #0 {
28  %ret = select i1 %2, i32* %0, i32* %1
29  ret i32* %ret
30}
31
32; TEST 4
33; ATTRIBUTOR: define align 32 i32* @test4(i32* nofree readnone align 32 "no-capture-maybe-returned" %0, i32* nofree readnone align 32 "no-capture-maybe-returned" %1, i1 %2)
34define i32* @test4(i32* align 32 %0, i32* align 32 %1, i1 %2) #0 {
35  %ret = select i1 %2, i32* %0, i32* %1
36  ret i32* %ret
37}
38
39; TEST 5
40declare i32* @unknown()
41declare align 8 i32* @align8()
42
43
44; ATTRIBUTOR: define align 8 i32* @test5_1()
45define i32* @test5_1() {
46  %ret = tail call align 8 i32* @unknown()
47  ret i32* %ret
48}
49
50; ATTRIBUTOR: define align 8 i32* @test5_2()
51define i32* @test5_2() {
52  %ret = tail call i32* @align8()
53  ret i32* %ret
54}
55
56; TEST 6
57; SCC
58; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @test6_1()
59define i32* @test6_1() #0 {
60  %ret = tail call i32* @test6_2()
61  ret i32* %ret
62}
63
64; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @test6_2()
65define i32* @test6_2() #0 {
66  %ret = tail call i32* @test6_1()
67  ret i32* %ret
68}
69
70
71; char a1 __attribute__((aligned(8)));
72; char a2 __attribute__((aligned(16)));
73;
74; char* f1(char* a ){
75;     return a?a:f2(&a1);
76; }
77; char* f2(char* a){
78;     return a?f1(a):f3(&a2);
79; }
80;
81; char* f3(char* a){
82;     return a?&a1: f1(&a2);
83; }
84
85@a1 = common global i8 0, align 8
86@a2 = common global i8 0, align 16
87
88; Function Attrs: nounwind readnone ssp uwtable
89define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
90  %2 = icmp eq i8* %0, null
91  br i1 %2, label %3, label %5
92
93; <label>:3:                                      ; preds = %1
94  %4 = tail call i8* @f2(i8* nonnull @a1)
95  %l = load i8, i8* %4
96  br label %5
97
98; <label>:5:                                      ; preds = %1, %3
99  %6 = phi i8* [ %4, %3 ], [ %0, %1 ]
100  ret i8* %6
101}
102
103; Function Attrs: nounwind readnone ssp uwtable
104define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
105  %2 = icmp eq i8* %0, null
106  br i1 %2, label %5, label %3
107
108; <label>:3:                                      ; preds = %1
109
110  %4 = tail call i8* @f1(i8* nonnull %0)
111  br label %7
112
113; <label>:5:                                      ; preds = %1
114  %6 = tail call i8* @f3(i8* nonnull @a2)
115  br label %7
116
117; <label>:7:                                      ; preds = %5, %3
118  %8 = phi i8* [ %4, %3 ], [ %6, %5 ]
119  ret i8* %8
120}
121
122; Function Attrs: nounwind readnone ssp uwtable
123define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
124  %2 = icmp eq i8* %0, null
125  br i1 %2, label %3, label %5
126
127; <label>:3:                                      ; preds = %1
128  %4 = tail call i8* @f1(i8* nonnull @a2)
129  br label %5
130
131; <label>:5:                                      ; preds = %1, %3
132  %6 = phi i8* [ %4, %3 ], [ @a1, %1 ]
133  ret i8* %6
134}
135
136; UTC_ARGS: --enable
137
138; TEST 7
139; Better than IR information
140define align 4 i8* @test7() #0 {
141; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@test7()
142; ATTRIBUTOR_MODULE-NEXT:    [[C:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
143; ATTRIBUTOR_MODULE-NEXT:    ret i8* [[C]]
144;
145; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@test7()
146; ATTRIBUTOR_CGSCC-NEXT:    [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
147; ATTRIBUTOR_CGSCC-NEXT:    ret i8* [[C]]
148;
149  %c = tail call i8* @f1(i8* align 8 dereferenceable(1) @a1)
150  ret i8* %c
151}
152
153; TEST 7b
154; Function Attrs: nounwind readnone ssp uwtable
155define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 {
156; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@f1b
157; ATTRIBUTOR_MODULE-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr
158; ATTRIBUTOR_MODULE-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
159; ATTRIBUTOR_MODULE-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
160; ATTRIBUTOR_MODULE:       3:
161; ATTRIBUTOR_MODULE-NEXT:    [[TMP4:%.*]] = tail call align 8 i8* @f2b()
162; ATTRIBUTOR_MODULE-NEXT:    [[L:%.*]] = load i8, i8* [[TMP4]], align 8
163; ATTRIBUTOR_MODULE-NEXT:    store i8 [[L]], i8* @a1, align 8
164; ATTRIBUTOR_MODULE-NEXT:    br label [[TMP5]]
165; ATTRIBUTOR_MODULE:       5:
166; ATTRIBUTOR_MODULE-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
167; ATTRIBUTOR_MODULE-NEXT:    ret i8* [[TMP6]]
168;
169; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@f1b
170; ATTRIBUTOR_CGSCC-SAME: (i8* nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr
171; ATTRIBUTOR_CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
172; ATTRIBUTOR_CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
173; ATTRIBUTOR_CGSCC:       3:
174; ATTRIBUTOR_CGSCC-NEXT:    [[TMP4:%.*]] = tail call align 8 i8* @f2b()
175; ATTRIBUTOR_CGSCC-NEXT:    [[L:%.*]] = load i8, i8* [[TMP4]], align 8
176; ATTRIBUTOR_CGSCC-NEXT:    store i8 [[L]], i8* @a1, align 8
177; ATTRIBUTOR_CGSCC-NEXT:    br label [[TMP5]]
178; ATTRIBUTOR_CGSCC:       5:
179; ATTRIBUTOR_CGSCC-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
180; ATTRIBUTOR_CGSCC-NEXT:    ret i8* [[TMP6]]
181;
182  %2 = icmp eq i8* %0, null
183  br i1 %2, label %3, label %5
184
185; <label>:3:                                      ; preds = %1
186  %4 = tail call i8* @f2b(i8* nonnull @a1)
187  %l = load i8, i8* %4
188  store i8 %l, i8* @a1
189  br label %5
190
191; <label>:5:                                      ; preds = %1, %3
192  %6 = phi i8* [ %4, %3 ], [ %0, %1 ]
193  ret i8* %6
194}
195
196; Function Attrs: nounwind readnone ssp uwtable
197define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 {
198;
199; ATTRIBUTOR-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr
200; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = icmp eq i8* @a1, null
201; ATTRIBUTOR-NEXT:    br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
202; ATTRIBUTOR:       2:
203; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1)
204; ATTRIBUTOR-NEXT:    br label [[TMP6:%.*]]
205; ATTRIBUTOR:       4:
206; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i8* @f3b()
207; ATTRIBUTOR-NEXT:    br label [[TMP6]]
208; ATTRIBUTOR:       6:
209; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
210; ATTRIBUTOR-NEXT:    ret i8* [[TMP7]]
211;
212  %2 = icmp eq i8* %0, null
213  br i1 %2, label %5, label %3
214
215; <label>:3:                                      ; preds = %1
216
217  %4 = tail call i8* @f1b(i8* nonnull %0)
218  br label %7
219
220; <label>:5:                                      ; preds = %1
221  %6 = tail call i8* @f3b(i8* nonnull @a2)
222  br label %7
223
224; <label>:7:                                      ; preds = %5, %3
225  %8 = phi i8* [ %4, %3 ], [ %6, %5 ]
226  ret i8* %8
227}
228
229; Function Attrs: nounwind readnone ssp uwtable
230define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 {
231;
232; ATTRIBUTOR-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr
233; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = icmp eq i8* @a2, null
234; ATTRIBUTOR-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]]
235; ATTRIBUTOR:       2:
236; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2)
237; ATTRIBUTOR-NEXT:    br label [[TMP4]]
238; ATTRIBUTOR:       4:
239; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ]
240; ATTRIBUTOR-NEXT:    ret i8* [[TMP5]]
241;
242  %2 = icmp eq i8* %0, null
243  br i1 %2, label %3, label %5
244
245; <label>:3:                                      ; preds = %1
246  %4 = tail call i8* @f1b(i8* nonnull @a2)
247  br label %5
248
249; <label>:5:                                      ; preds = %1, %3
250  %6 = phi i8* [ %4, %3 ], [ @a1, %1 ]
251  ret i8* %6
252}
253
254define align 4 i32* @test7b(i32* align 32 %p) #0 {
255; ATTRIBUTOR-LABEL: define {{[^@]+}}@test7b
256; ATTRIBUTOR-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]])
257; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
258; ATTRIBUTOR-NEXT:    ret i32* [[P]]
259;
260  tail call i8* @f1b(i8* align 8 dereferenceable(1) @a1)
261  ret i32* %p
262}
263
264; UTC_ARGS: --disable
265
266; TEST 8
267define void @test8_helper() {
268  %ptr0 = tail call i32* @unknown()
269  %ptr1 = tail call align 4 i32* @unknown()
270  %ptr2 = tail call align 8 i32* @unknown()
271
272  tail call void @test8(i32* %ptr1, i32* %ptr1, i32* %ptr0)
273; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1, i32* noalias readnone %ptr0)
274  tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1)
275; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 8 %ptr2, i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1)
276  tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1)
277; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 8 %ptr2, i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1)
278  ret void
279}
280
281declare void @user_i32_ptr(i32* nocapture readnone) nounwind
282define internal void @test8(i32* %a, i32* %b, i32* %c) {
283; ATTRIBUTOR_MODULE: define internal void @test8(i32* noalias nocapture readnone align 4 %a, i32* noalias nocapture readnone align 4 %b, i32* noalias nocapture readnone %c)
284; ATTRIBUTOR_CGSCC: define internal void @test8(i32* nocapture readnone align 4 %a, i32* nocapture readnone align 4 %b, i32* nocapture readnone %c)
285  call void @user_i32_ptr(i32* %a)
286  call void @user_i32_ptr(i32* %b)
287  call void @user_i32_ptr(i32* %c)
288  ret void
289}
290
291declare void @test9_helper(i32* %A)
292define void @test9_traversal(i1 %c, i32* align 4 %B, i32* align 8 %C) {
293  %sel = select i1 %c, i32* %B, i32* %C
294  call void @test9_helper(i32* %sel)
295  ret void
296}
297
298; FIXME: This will work with an upcoming patch (D66618 or similar)
299;             define align 32 i32* @test10a(i32* align 32 "no-capture-maybe-returned" %p)
300; ATTRIBUTOR: define i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" %p)
301define i32* @test10a(i32* align 32 %p) {
302; ATTRIBUTOR: %l = load i32, i32* %p, align 32
303  %l = load i32, i32* %p
304  %c = icmp eq i32 %l, 0
305  br i1 %c, label %t, label %f
306t:
307  %r = call i32* @test10a(i32* %p)
308; FIXME: This will work with an upcoming patch (D66618 or similar)
309;             store i32 1, i32* %r, align 32
310; ATTRIBUTOR: store i32 1, i32* %r
311  store i32 1, i32* %r
312  %g0 = getelementptr i32, i32* %p, i32 8
313  br label %e
314f:
315  %g1 = getelementptr i32, i32* %p, i32 8
316; FIXME: This will work with an upcoming patch (D66618 or similar)
317;             store i32 -1, i32* %g1, align 32
318; ATTRIBUTOR: store i32 -1, i32* %g1
319  store i32 -1, i32* %g1
320  br label %e
321e:
322  %phi = phi i32* [%g0, %t], [%g1, %f]
323  ret i32* %phi
324}
325
326; FIXME: This will work with an upcoming patch (D66618 or similar)
327;             define align 32 i32* @test10b(i32* align 32 "no-capture-maybe-returned" %p)
328; ATTRIBUTOR: define i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" %p)
329define i32* @test10b(i32* align 32 %p) {
330; ATTRIBUTOR: %l = load i32, i32* %p, align 32
331  %l = load i32, i32* %p
332  %c = icmp eq i32 %l, 0
333  br i1 %c, label %t, label %f
334t:
335  %r = call i32* @test10b(i32* %p)
336; FIXME: This will work with an upcoming patch (D66618 or similar)
337;             store i32 1, i32* %r, align 32
338; ATTRIBUTOR: store i32 1, i32* %r
339  store i32 1, i32* %r
340  %g0 = getelementptr i32, i32* %p, i32 8
341  br label %e
342f:
343  %g1 = getelementptr i32, i32* %p, i32 -8
344; FIXME: This will work with an upcoming patch (D66618 or similar)
345;             store i32 -1, i32* %g1, align 32
346; ATTRIBUTOR: store i32 -1, i32* %g1
347  store i32 -1, i32* %g1
348  br label %e
349e:
350  %phi = phi i32* [%g0, %t], [%g1, %f]
351  ret i32* %phi
352}
353
354
355; ATTRIBUTOR: define i64 @test11(i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) %p)
356define i64 @test11(i32* %p) {
357  %p-cast = bitcast i32* %p to i64*
358  %ret = load i64, i64* %p-cast, align 8
359  ret i64 %ret
360}
361
362; TEST 12
363; Test for deduction using must-be-executed-context and GEP instruction
364
365; FXIME: %p should have nonnull
366; ATTRIBUTOR: define i64 @test12-1(i32* nocapture nofree readonly align 16 %p)
367define i64 @test12-1(i32* align 4 %p) {
368  %p-cast = bitcast i32* %p to i64*
369  %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1
370  %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3
371  %ret = load i64, i64* %arrayidx1, align 16
372  ret i64 %ret
373}
374
375; ATTRIBUTOR: define i64 @test12-2(i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) %p)
376define i64 @test12-2(i32* align 4 %p) {
377  %p-cast = bitcast i32* %p to i64*
378  %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0
379  %ret = load i64, i64* %arrayidx0, align 16
380  ret i64 %ret
381}
382
383; FXIME: %p should have nonnull
384; ATTRIBUTOR: define void @test12-3(i32* nocapture nofree writeonly align 16 %p)
385define void @test12-3(i32* align 4 %p) {
386  %p-cast = bitcast i32* %p to i64*
387  %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1
388  %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3
389  store i64 0, i64* %arrayidx1, align 16
390  ret void
391}
392
393; ATTRIBUTOR: define void @test12-4(i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) %p)
394define void @test12-4(i32* align 4 %p) {
395  %p-cast = bitcast i32* %p to i64*
396  %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0
397  store i64 0, i64* %arrayidx0, align 16
398  ret void
399}
400
401declare void @use(i64*) willreturn nounwind
402
403; ATTRIBUTOR: define void @test12-5(i32* align 16 %p)
404define void @test12-5(i32* align 4 %p) {
405  %p-cast = bitcast i32* %p to i64*
406  %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1
407  %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3
408  tail call void @use(i64* align 16 %arrayidx1)
409  ret void
410}
411
412; ATTRIBUTOR: define void @test12-6(i32* align 16 %p)
413define void @test12-6(i32* align 4 %p) {
414  %p-cast = bitcast i32* %p to i64*
415  %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0
416  tail call void @use(i64* align 16 %arrayidx0)
417  ret void
418}
419
420define void @test13(i1 %c, i32* align 32 %dst) #0 {
421; ATTRIBUTOR-LABEL: define {{[^@]+}}@test13
422; ATTRIBUTOR-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]])
423; ATTRIBUTOR-NEXT:    br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
424; ATTRIBUTOR:       truebb:
425; ATTRIBUTOR-NEXT:    br label [[END:%.*]]
426; ATTRIBUTOR:       falsebb:
427; ATTRIBUTOR-NEXT:    br label [[END]]
428; ATTRIBUTOR:       end:
429; ATTRIBUTOR-NEXT:    [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ]
430; ATTRIBUTOR-NEXT:    store i32 0, i32* [[PTR]], align 32
431; ATTRIBUTOR-NEXT:    ret void
432;
433  br i1 %c, label %truebb, label %falsebb
434truebb:
435  br label %end
436falsebb:
437  br label %end
438end:
439  %ptr = phi i32* [ %dst, %truebb ], [ null, %falsebb ]
440  store i32 0, i32* %ptr
441  ret void
442}
443
444define void @test13-1(i1 %c, i32* align 32 %dst) {
445; ATTRIBUTOR-LABEL: @test13-1(
446; ATTRIBUTOR-NEXT:    br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
447; ATTRIBUTOR:       truebb:
448; ATTRIBUTOR-NEXT:    br label [[END:%.*]]
449; ATTRIBUTOR:       falsebb:
450; ATTRIBUTOR-NEXT:    br label [[END]]
451; ATTRIBUTOR:       end:
452; ATTRIBUTOR-NEXT:    [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ]
453; ATTRIBUTOR-NEXT:    store i32 0, i32* [[PTR]], align 16
454; ATTRIBUTOR-NEXT:    ret void
455;
456  br i1 %c, label %truebb, label %falsebb
457truebb:
458  br label %end
459falsebb:
460  br label %end
461end:
462  %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 48 to i32*), %falsebb ]
463  store i32 0, i32* %ptr
464  ret void
465}
466
467define void @test13-2(i1 %c, i32* align 32 %dst) {
468; ATTRIBUTOR-LABEL: @test13-2(
469; ATTRIBUTOR-NEXT:    br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
470; ATTRIBUTOR:       truebb:
471; ATTRIBUTOR-NEXT:    br label [[END:%.*]]
472; ATTRIBUTOR:       falsebb:
473; ATTRIBUTOR-NEXT:    br label [[END]]
474; ATTRIBUTOR:       end:
475; ATTRIBUTOR-NEXT:    [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ]
476; ATTRIBUTOR-NEXT:    store i32 0, i32* [[PTR]], align 32
477; ATTRIBUTOR-NEXT:    ret void
478;
479  br i1 %c, label %truebb, label %falsebb
480truebb:
481  br label %end
482falsebb:
483  br label %end
484end:
485  %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 160 to i32*), %falsebb ]
486  store i32 0, i32* %ptr
487  ret void
488}
489
490define void @test13-3(i1 %c, i32* align 32 %dst) {
491; ATTRIBUTOR-LABEL: @test13-3(
492; ATTRIBUTOR-NEXT:    br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]]
493; ATTRIBUTOR:       truebb:
494; ATTRIBUTOR-NEXT:    br label [[END:%.*]]
495; ATTRIBUTOR:       falsebb:
496; ATTRIBUTOR-NEXT:    br label [[END]]
497; ATTRIBUTOR:       end:
498; ATTRIBUTOR-NEXT:    [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ]
499; ATTRIBUTOR-NEXT:    store i32 0, i32* [[PTR]], align 32
500; ATTRIBUTOR-NEXT:    ret void
501;
502  br i1 %c, label %truebb, label %falsebb
503truebb:
504  br label %end
505falsebb:
506  br label %end
507end:
508  %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 128 to i32*), %falsebb ]
509  store i32 0, i32* %ptr
510  ret void
511}
512
513; Don't crash on ptr2int/int2ptr uses.
514define i64 @ptr2int(i32* %p) {
515  %p2i = ptrtoint i32* %p to i64
516  ret i64 %p2i
517}
518define i64* @int2ptr(i64 %i) {
519  %i2p = inttoptr i64 %i to i64*
520  ret i64* %i2p
521}
522
523; Use the store alignment only for the pointer operand.
524define void @aligned_store(i8* %Value, i8** %Ptr) {
525; ATTRIBUTOR: define void @aligned_store(i8* nofree writeonly %Value, i8** nocapture nofree nonnull writeonly align 32 dereferenceable(8) %Ptr)
526  store i8* %Value, i8** %Ptr, align 32
527  ret void
528}
529
530; UTC_ARGS: --enable
531declare i8* @some_func(i8*)
532define void @align_call_op_not_store(i8* align 2048 %arg) {
533; ATTRIBUTOR-LABEL: define {{[^@]+}}@align_call_op_not_store
534; ATTRIBUTOR-SAME: (i8* align 2048 [[ARG:%.*]])
535; ATTRIBUTOR-NEXT:    [[UNKNOWN:%.*]] = call i8* @some_func(i8* align 2048 [[ARG]])
536; ATTRIBUTOR-NEXT:    store i8 0, i8* [[UNKNOWN]]
537; ATTRIBUTOR-NEXT:    ret void
538;
539  %unknown = call i8* @some_func(i8* %arg)
540  store i8 0, i8* %unknown
541  ret void
542}
543define void @align_store_after_bc(i32* align 2048 %arg) {
544;
545; ATTRIBUTOR-LABEL: define {{[^@]+}}@align_store_after_bc
546; ATTRIBUTOR-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]])
547; ATTRIBUTOR-NEXT:    [[BC:%.*]] = bitcast i32* [[ARG]] to i8*
548; ATTRIBUTOR-NEXT:    store i8 0, i8* [[BC]], align 2048
549; ATTRIBUTOR-NEXT:    ret void
550;
551  %bc = bitcast i32* %arg to i8*
552  store i8 0, i8* %bc
553  ret void
554}
555
556; Make sure we do not annotate the callee of a must-tail call with an alignment
557; we cannot also put on the caller.
558@cnd = external global i1
559define i32 @musttail_callee_1(i32* %p) {
560  %v = load i32, i32* %p, align 32
561  ret i32 %v
562}
563define i32 @musttail_caller_1(i32* %p) {
564  %c = load i1, i1* @cnd
565  br i1 %c, label %mt, label %exit
566mt:
567  %v = musttail call i32 @musttail_callee_1(i32* %p)
568  ret i32 %v
569exit:
570  ret i32 0
571}
572; UTC_ARGS: --disable
573
574attributes #0 = { nounwind uwtable noinline }
575attributes #1 = { uwtable noinline }
576attributes #2 = { "null-pointer-is-valid"="true" }
577