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
40define i32 @goo(i32* nocapture %a) nounwind uwtable readonly {
41entry:
42  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 0)]
43  %0 = load i32, i32* %a, align 4
44  ret i32 %0
45
46; CHECK-LABEL: @goo
47; CHECK: load i32, i32* {{[^,]+}}, align 32
48; CHECK: ret i32
49}
50
51define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly {
52entry:
53  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i32 0)]
54  br label %for.body
55
56for.body:                                         ; preds = %entry, %for.body
57  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
58  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
59  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
60  %0 = load i32, i32* %arrayidx, align 4
61  %add = add nsw i32 %0, %r.06
62  %indvars.iv.next = add i64 %indvars.iv, 8
63  %1 = trunc i64 %indvars.iv.next to i32
64  %cmp = icmp slt i32 %1, 2048
65  br i1 %cmp, label %for.body, label %for.end
66
67for.end:                                          ; preds = %for.body
68  %add.lcssa = phi i32 [ %add, %for.body ]
69  ret i32 %add.lcssa
70
71; CHECK-LABEL: @hoo
72; CHECK: load i32, i32* %arrayidx, align 32
73; CHECK: ret i32 %add.lcssa
74}
75
76; test D66575
77; def hoo2(a, id, num):
78;   for i0 in range(id*64, 4096, num*64):
79;     for i1 in range(0, 4096, 32):
80;       for i2 in range(0, 4096, 32):
81;         load(a, i0+i1+i2+32)
82define void @hoo2(i32* nocapture %a, i64 %id, i64 %num) nounwind uwtable readonly {
83entry:
84  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i64 0)]
85  %id.mul = shl nsw i64 %id, 6
86  %num.mul = shl nsw i64 %num, 6
87  br label %for0.body
88
89for0.body:
90  %i0 = phi i64 [ %id.mul, %entry ], [ %i0.next, %for0.end ]
91  br label %for1.body
92
93for1.body:
94  %i1 = phi i64 [ 0, %for0.body ], [ %i1.next, %for1.end ]
95  br label %for2.body
96
97for2.body:
98  %i2 = phi i64 [ 0, %for1.body ], [ %i2.next, %for2.body ]
99
100  %t1 = add nuw nsw i64 %i0, %i1
101  %t2 = add nuw nsw i64 %t1, %i2
102  %t3 = add nuw nsw i64 %t2, 32
103  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %t3
104  %x = load i32, i32* %arrayidx, align 4
105
106  %i2.next = add nuw nsw i64 %i2, 32
107  %cmp2 = icmp ult i64 %i2.next, 4096
108  br i1 %cmp2, label %for2.body, label %for1.end
109
110for1.end:
111  %i1.next = add nuw nsw i64 %i1, 32
112  %cmp1 = icmp ult i64 %i1.next, 4096
113  br i1 %cmp1, label %for1.body, label %for0.end
114
115for0.end:
116  %i0.next = add nuw nsw i64 %i0, %num.mul
117  %cmp0 = icmp ult i64 %i0.next, 4096
118  br i1 %cmp0, label %for0.body, label %return
119
120return:
121  ret void
122
123; CHECK-LABEL: @hoo2
124; CHECK: load i32, i32* %arrayidx, align 32
125; CHECK: ret void
126}
127
128define i32 @joo(i32* nocapture %a) nounwind uwtable readonly {
129entry:
130  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i8 0)]
131  br label %for.body
132
133for.body:                                         ; preds = %entry, %for.body
134  %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ]
135  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
136  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
137  %0 = load i32, i32* %arrayidx, align 4
138  %add = add nsw i32 %0, %r.06
139  %indvars.iv.next = add i64 %indvars.iv, 8
140  %1 = trunc i64 %indvars.iv.next to i32
141  %cmp = icmp slt i32 %1, 2048
142  br i1 %cmp, label %for.body, label %for.end
143
144for.end:                                          ; preds = %for.body
145  %add.lcssa = phi i32 [ %add, %for.body ]
146  ret i32 %add.lcssa
147
148; CHECK-LABEL: @joo
149; CHECK: load i32, i32* %arrayidx, align 16
150; CHECK: ret i32 %add.lcssa
151}
152
153define i32 @koo(i32* nocapture %a) nounwind uwtable readonly {
154entry:
155  br label %for.body
156
157for.body:                                         ; preds = %entry, %for.body
158  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
159  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
160  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
161  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i8 0)]
162  %0 = load i32, i32* %arrayidx, align 4
163  %add = add nsw i32 %0, %r.06
164  %indvars.iv.next = add i64 %indvars.iv, 4
165  %1 = trunc i64 %indvars.iv.next to i32
166  %cmp = icmp slt i32 %1, 2048
167  br i1 %cmp, label %for.body, label %for.end
168
169for.end:                                          ; preds = %for.body
170  %add.lcssa = phi i32 [ %add, %for.body ]
171  ret i32 %add.lcssa
172
173; CHECK-LABEL: @koo
174; CHECK: load i32, i32* %arrayidx, align 16
175; CHECK: ret i32 %add.lcssa
176}
177
178define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly {
179entry:
180  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i128 32, i128 0)]
181  br label %for.body
182
183for.body:                                         ; preds = %entry, %for.body
184  %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ]
185  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
186  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
187  %0 = load i32, i32* %arrayidx, align 4
188  %add = add nsw i32 %0, %r.06
189  %indvars.iv.next = add i64 %indvars.iv, 4
190  %1 = trunc i64 %indvars.iv.next to i32
191  %cmp = icmp slt i32 %1, 2048
192  br i1 %cmp, label %for.body, label %for.end
193
194for.end:                                          ; preds = %for.body
195  %add.lcssa = phi i32 [ %add, %for.body ]
196  ret i32 %add.lcssa
197
198; CHECK-LABEL: @koo2
199; CHECK: load i32, i32* %arrayidx, align 16
200; CHECK: ret i32 %add.lcssa
201}
202
203define i32 @moo(i32* nocapture %a) nounwind uwtable {
204entry:
205  tail call void @llvm.assume(i1 true) ["align"(i32* %a, i16 32)]
206  %0 = bitcast i32* %a to i8*
207  tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false)
208  ret i32 undef
209
210; CHECK-LABEL: @moo
211; CHECK: @llvm.memset.p0i8.i64(i8* align 32 %0, i8 0, i64 64, i1 false)
212; CHECK: ret i32 undef
213}
214
215define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable {
216entry:
217  tail call void @llvm.assume(i1 true) ["align"(i32* %b, i32 128)]
218  %0 = bitcast i32* %a to i8*
219  tail call void @llvm.assume(i1 true) ["align"(i8* %0, i16 32)]
220  %1 = bitcast i32* %b to i8*
221  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false)
222  ret i32 undef
223
224; CHECK-LABEL: @moo2
225; CHECK: @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 %0, i8* align 128 %1, i64 64, i1 false)
226; CHECK: ret i32 undef
227}
228
229define i32 @moo3(i32* nocapture %a, i32* nocapture %b) nounwind uwtable {
230entry:
231  %0 = bitcast i32* %a to i8*
232  tail call void @llvm.assume(i1 true) ["align"(i8* %0, i16 32), "align"(i32* %b, i32 128)]
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: @moo3
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
242declare void @llvm.assume(i1) nounwind
243
244declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
245declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
246
247