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