1target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
2; RUN: opt < %s -passes=alignment-from-assumptions -S | FileCheck %s
3
4define i32 @foo(ptr nocapture %a) nounwind uwtable readonly {
5entry:
6  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32)]
7  %0 = load i32, ptr %a, align 4
8  ret i32 %0
9
10; CHECK-LABEL: @foo
11; CHECK: load i32, ptr {{[^,]+}}, align 32
12; CHECK: ret i32
13}
14
15define i32 @foo2(ptr nocapture %a) nounwind uwtable readonly {
16entry:
17  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32, i32 24)]
18  %arrayidx = getelementptr inbounds i32, ptr %a, i64 -2
19  %0 = load i32, ptr %arrayidx, align 4
20  ret i32 %0
21
22; CHECK-LABEL: @foo2
23; CHECK: load i32, ptr {{[^,]+}}, align 16
24; CHECK: ret i32
25}
26
27define i32 @foo2a(ptr nocapture %a) nounwind uwtable readonly {
28entry:
29  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32, i32 28)]
30  %arrayidx = getelementptr inbounds i32, ptr %a, i64 1
31  %0 = load i32, ptr %arrayidx, align 4
32  ret i32 %0
33
34; CHECK-LABEL: @foo2a
35; CHECK: load i32, ptr {{[^,]+}}, align 32
36; CHECK: ret i32
37}
38
39; TODO: this can be 8-bytes aligned
40define i32 @foo2b(ptr nocapture %a) nounwind uwtable readonly {
41entry:
42  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32, i32 28)]
43  %arrayidx = getelementptr inbounds i32, ptr %a, i64 -1
44  %0 = load i32, ptr %arrayidx, align 4
45  ret i32 %0
46
47; CHECK-LABEL: @foo2b
48; CHECK: load i32, ptr {{[^,]+}}, align 4
49; CHECK: ret i32
50}
51
52define i32 @goo(ptr nocapture %a) nounwind uwtable readonly {
53entry:
54  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32, i32 0)]
55  %0 = load i32, ptr %a, align 4
56  ret i32 %0
57
58; CHECK-LABEL: @goo
59; CHECK: load i32, ptr {{[^,]+}}, align 32
60; CHECK: ret i32
61}
62
63define i32 @hoo(ptr nocapture %a) nounwind uwtable readonly {
64entry:
65  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i64 32, i32 0)]
66  br label %for.body
67
68for.body:                                         ; preds = %entry, %for.body
69  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
70  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
71  %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
72  %0 = load i32, ptr %arrayidx, align 4
73  %add = add nsw i32 %0, %r.06
74  %indvars.iv.next = add i64 %indvars.iv, 8
75  %1 = trunc i64 %indvars.iv.next to i32
76  %cmp = icmp slt i32 %1, 2048
77  br i1 %cmp, label %for.body, label %for.end
78
79for.end:                                          ; preds = %for.body
80  %add.lcssa = phi i32 [ %add, %for.body ]
81  ret i32 %add.lcssa
82
83; CHECK-LABEL: @hoo
84; CHECK: load i32, ptr %arrayidx, align 32
85; CHECK: ret i32 %add.lcssa
86}
87
88; test D66575
89; def hoo2(a, id, num):
90;   for i0 in range(id*64, 4096, num*64):
91;     for i1 in range(0, 4096, 32):
92;       for i2 in range(0, 4096, 32):
93;         load(a, i0+i1+i2+32)
94define void @hoo2(ptr nocapture %a, i64 %id, i64 %num) nounwind uwtable readonly {
95entry:
96  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i8 32, i64 0)]
97  %id.mul = shl nsw i64 %id, 6
98  %num.mul = shl nsw i64 %num, 6
99  br label %for0.body
100
101for0.body:
102  %i0 = phi i64 [ %id.mul, %entry ], [ %i0.next, %for0.end ]
103  br label %for1.body
104
105for1.body:
106  %i1 = phi i64 [ 0, %for0.body ], [ %i1.next, %for1.end ]
107  br label %for2.body
108
109for2.body:
110  %i2 = phi i64 [ 0, %for1.body ], [ %i2.next, %for2.body ]
111
112  %t1 = add nuw nsw i64 %i0, %i1
113  %t2 = add nuw nsw i64 %t1, %i2
114  %t3 = add nuw nsw i64 %t2, 32
115  %arrayidx = getelementptr inbounds i32, ptr %a, i64 %t3
116  %x = load i32, ptr %arrayidx, align 4
117
118  %i2.next = add nuw nsw i64 %i2, 32
119  %cmp2 = icmp ult i64 %i2.next, 4096
120  br i1 %cmp2, label %for2.body, label %for1.end
121
122for1.end:
123  %i1.next = add nuw nsw i64 %i1, 32
124  %cmp1 = icmp ult i64 %i1.next, 4096
125  br i1 %cmp1, label %for1.body, label %for0.end
126
127for0.end:
128  %i0.next = add nuw nsw i64 %i0, %num.mul
129  %cmp0 = icmp ult i64 %i0.next, 4096
130  br i1 %cmp0, label %for0.body, label %return
131
132return:
133  ret void
134
135; CHECK-LABEL: @hoo2
136; CHECK: load i32, ptr %arrayidx, align 32
137; CHECK: ret void
138}
139
140define i32 @joo(ptr nocapture %a) nounwind uwtable readonly {
141entry:
142  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i8 32, i8 0)]
143  br label %for.body
144
145for.body:                                         ; preds = %entry, %for.body
146  %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ]
147  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
148  %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
149  %0 = load i32, ptr %arrayidx, align 4
150  %add = add nsw i32 %0, %r.06
151  %indvars.iv.next = add i64 %indvars.iv, 8
152  %1 = trunc i64 %indvars.iv.next to i32
153  %cmp = icmp slt i32 %1, 2048
154  br i1 %cmp, label %for.body, label %for.end
155
156for.end:                                          ; preds = %for.body
157  %add.lcssa = phi i32 [ %add, %for.body ]
158  ret i32 %add.lcssa
159
160; CHECK-LABEL: @joo
161; CHECK: load i32, ptr %arrayidx, align 16
162; CHECK: ret i32 %add.lcssa
163}
164
165define i32 @koo(ptr nocapture %a) nounwind uwtable readonly {
166entry:
167  br label %for.body
168
169for.body:                                         ; preds = %entry, %for.body
170  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
171  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
172  %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
173  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i8 32, i8 0)]
174  %0 = load i32, ptr %arrayidx, align 4
175  %add = add nsw i32 %0, %r.06
176  %indvars.iv.next = add i64 %indvars.iv, 4
177  %1 = trunc i64 %indvars.iv.next to i32
178  %cmp = icmp slt i32 %1, 2048
179  br i1 %cmp, label %for.body, label %for.end
180
181for.end:                                          ; preds = %for.body
182  %add.lcssa = phi i32 [ %add, %for.body ]
183  ret i32 %add.lcssa
184
185; CHECK-LABEL: @koo
186; CHECK: load i32, ptr %arrayidx, align 16
187; CHECK: ret i32 %add.lcssa
188}
189
190define i32 @koo2(ptr nocapture %a) nounwind uwtable readonly {
191entry:
192  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i128 32, i128 0)]
193  br label %for.body
194
195for.body:                                         ; preds = %entry, %for.body
196  %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ]
197  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
198  %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
199  %0 = load i32, ptr %arrayidx, align 4
200  %add = add nsw i32 %0, %r.06
201  %indvars.iv.next = add i64 %indvars.iv, 4
202  %1 = trunc i64 %indvars.iv.next to i32
203  %cmp = icmp slt i32 %1, 2048
204  br i1 %cmp, label %for.body, label %for.end
205
206for.end:                                          ; preds = %for.body
207  %add.lcssa = phi i32 [ %add, %for.body ]
208  ret i32 %add.lcssa
209
210; CHECK-LABEL: @koo2
211; CHECK: load i32, ptr %arrayidx, align 16
212; CHECK: ret i32 %add.lcssa
213}
214
215define i32 @moo(ptr nocapture %a) nounwind uwtable {
216entry:
217  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i16 32)]
218  tail call void @llvm.memset.p0.i64(ptr align 4 %a, i8 0, i64 64, i1 false)
219  ret i32 undef
220
221; CHECK-LABEL: @moo
222; CHECK: @llvm.memset.p0.i64(ptr align 32 %a, i8 0, i64 64, i1 false)
223; CHECK: ret i32 undef
224}
225
226define i32 @moo2(ptr nocapture %a, ptr nocapture %b) nounwind uwtable {
227entry:
228  tail call void @llvm.assume(i1 true) ["align"(ptr %b, i32 128)]
229  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i16 32)]
230  tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %b, i64 64, i1 false)
231  ret i32 undef
232
233; CHECK-LABEL: @moo2
234; CHECK: @llvm.memcpy.p0.p0.i64(ptr align 32 %a, ptr align 128 %b, i64 64, i1 false)
235; CHECK: ret i32 undef
236}
237
238define i32 @moo3(ptr nocapture %a, ptr nocapture %b) nounwind uwtable {
239entry:
240  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i16 32), "align"(ptr %b, i32 128)]
241  tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %b, i64 64, i1 false)
242  ret i32 undef
243
244; CHECK-LABEL: @moo3
245; CHECK: @llvm.memcpy.p0.p0.i64(ptr align 32 %a, ptr align 128 %b, i64 64, i1 false)
246; CHECK: ret i32 undef
247}
248
249
250; Variable alignments appear to be legal, don't crash
251define i32 @pr51680(ptr nocapture %a, i32 %align) nounwind uwtable readonly {
252entry:
253  tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 %align)]
254  %0 = load i32, ptr %a, align 4
255  ret i32 %0
256
257; CHECK-LABEL: @pr51680
258; CHECK: load i32, ptr {{[^,]+}}, align 4
259; CHECK: ret i32
260}
261
262declare void @llvm.assume(i1) nounwind
263
264declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
265declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
266
267