1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
3; RUN: opt < %s -alignment-from-assumptions -S | FileCheck %s
4; RUN: opt < %s -passes=alignment-from-assumptions -S | FileCheck %s
5
6define i32 @foo(i32* nocapture %a) nounwind uwtable readonly {
7; CHECK-LABEL: define {{[^@]+}}@foo
8; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
11; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
12; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
13; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
14; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A]], align 32
15; CHECK-NEXT:    ret i32 [[TMP0]]
16;
17entry:
18  %ptrint = ptrtoint i32* %a to i64
19  %maskedptr = and i64 %ptrint, 31
20  %maskcond = icmp eq i64 %maskedptr, 0
21  tail call void @llvm.assume(i1 %maskcond)
22  %0 = load i32, i32* %a, align 4
23  ret i32 %0
24
25}
26
27define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly {
28; CHECK-LABEL: define {{[^@]+}}@foo2
29; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
30; CHECK-NEXT:  entry:
31; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
32; CHECK-NEXT:    [[OFFSETPTR:%.*]] = add i64 [[PTRINT]], 24
33; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31
34; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
35; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
36; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 2
37; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
38; CHECK-NEXT:    ret i32 [[TMP0]]
39;
40entry:
41  %ptrint = ptrtoint i32* %a to i64
42  %offsetptr = add i64 %ptrint, 24
43  %maskedptr = and i64 %offsetptr, 31
44  %maskcond = icmp eq i64 %maskedptr, 0
45  tail call void @llvm.assume(i1 %maskcond)
46  %arrayidx = getelementptr inbounds i32, i32* %a, i64 2
47  %0 = load i32, i32* %arrayidx, align 4
48  ret i32 %0
49
50}
51
52define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly {
53; CHECK-LABEL: define {{[^@]+}}@foo2a
54; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
55; CHECK-NEXT:  entry:
56; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
57; CHECK-NEXT:    [[OFFSETPTR:%.*]] = add i64 [[PTRINT]], 28
58; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31
59; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
60; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
61; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 -1
62; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32
63; CHECK-NEXT:    ret i32 [[TMP0]]
64;
65entry:
66  %ptrint = ptrtoint i32* %a to i64
67  %offsetptr = add i64 %ptrint, 28
68  %maskedptr = and i64 %offsetptr, 31
69  %maskcond = icmp eq i64 %maskedptr, 0
70  tail call void @llvm.assume(i1 %maskcond)
71  %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1
72  %0 = load i32, i32* %arrayidx, align 4
73  ret i32 %0
74
75}
76
77define i32 @goo(i32* nocapture %a) nounwind uwtable readonly {
78; CHECK-LABEL: define {{[^@]+}}@goo
79; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
80; CHECK-NEXT:  entry:
81; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
82; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
83; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
84; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
85; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A]], align 32
86; CHECK-NEXT:    ret i32 [[TMP0]]
87;
88entry:
89  %ptrint = ptrtoint i32* %a to i64
90  %maskedptr = and i64 %ptrint, 31
91  %maskcond = icmp eq i64 %maskedptr, 0
92  tail call void @llvm.assume(i1 %maskcond)
93  %0 = load i32, i32* %a, align 4
94  ret i32 %0
95
96}
97
98define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly {
99; CHECK-LABEL: define {{[^@]+}}@hoo
100; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
101; CHECK-NEXT:  entry:
102; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
103; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
104; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
105; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
106; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
107; CHECK:       for.body:
108; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
109; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
110; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
111; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32
112; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
113; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 8
114; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
115; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
116; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
117; CHECK:       for.end:
118; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
119; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
120;
121entry:
122  %ptrint = ptrtoint i32* %a to i64
123  %maskedptr = and i64 %ptrint, 31
124  %maskcond = icmp eq i64 %maskedptr, 0
125  tail call void @llvm.assume(i1 %maskcond)
126  br label %for.body
127
128for.body:                                         ; preds = %entry, %for.body
129  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
130  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
131  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
132  %0 = load i32, i32* %arrayidx, align 4
133  %add = add nsw i32 %0, %r.06
134  %indvars.iv.next = add i64 %indvars.iv, 8
135  %1 = trunc i64 %indvars.iv.next to i32
136  %cmp = icmp slt i32 %1, 2048
137  br i1 %cmp, label %for.body, label %for.end
138
139for.end:                                          ; preds = %for.body
140  %add.lcssa = phi i32 [ %add, %for.body ]
141  ret i32 %add.lcssa
142
143}
144
145define i32 @joo(i32* nocapture %a) nounwind uwtable readonly {
146; CHECK-LABEL: define {{[^@]+}}@joo
147; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
148; CHECK-NEXT:  entry:
149; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
150; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
151; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
152; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
153; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
154; CHECK:       for.body:
155; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
156; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
157; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
158; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
159; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
160; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 8
161; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
162; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
163; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
164; CHECK:       for.end:
165; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
166; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
167;
168entry:
169  %ptrint = ptrtoint i32* %a to i64
170  %maskedptr = and i64 %ptrint, 31
171  %maskcond = icmp eq i64 %maskedptr, 0
172  tail call void @llvm.assume(i1 %maskcond)
173  br label %for.body
174
175for.body:                                         ; preds = %entry, %for.body
176  %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ]
177  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
178  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
179  %0 = load i32, i32* %arrayidx, align 4
180  %add = add nsw i32 %0, %r.06
181  %indvars.iv.next = add i64 %indvars.iv, 8
182  %1 = trunc i64 %indvars.iv.next to i32
183  %cmp = icmp slt i32 %1, 2048
184  br i1 %cmp, label %for.body, label %for.end
185
186for.end:                                          ; preds = %for.body
187  %add.lcssa = phi i32 [ %add, %for.body ]
188  ret i32 %add.lcssa
189
190}
191
192define i32 @koo(i32* nocapture %a) nounwind uwtable readonly {
193; CHECK-LABEL: define {{[^@]+}}@koo
194; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
195; CHECK-NEXT:  entry:
196; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
197; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
198; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
199; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
200; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
201; CHECK:       for.body:
202; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
203; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
204; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
205; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
206; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
207; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 4
208; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
209; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
210; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
211; CHECK:       for.end:
212; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
213; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
214;
215entry:
216  %ptrint = ptrtoint i32* %a to i64
217  %maskedptr = and i64 %ptrint, 31
218  %maskcond = icmp eq i64 %maskedptr, 0
219  tail call void @llvm.assume(i1 %maskcond)
220  br label %for.body
221
222for.body:                                         ; preds = %entry, %for.body
223  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
224  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
225  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
226  %0 = load i32, i32* %arrayidx, align 4
227  %add = add nsw i32 %0, %r.06
228  %indvars.iv.next = add i64 %indvars.iv, 4
229  %1 = trunc i64 %indvars.iv.next to i32
230  %cmp = icmp slt i32 %1, 2048
231  br i1 %cmp, label %for.body, label %for.end
232
233for.end:                                          ; preds = %for.body
234  %add.lcssa = phi i32 [ %add, %for.body ]
235  ret i32 %add.lcssa
236
237}
238
239define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly {
240; CHECK-LABEL: define {{[^@]+}}@koo2
241; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
242; CHECK-NEXT:  entry:
243; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
244; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
245; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
246; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
247; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
248; CHECK:       for.body:
249; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ -4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
250; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
251; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
252; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
253; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
254; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 4
255; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
256; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
257; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
258; CHECK:       for.end:
259; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
260; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
261;
262entry:
263  %ptrint = ptrtoint i32* %a to i64
264  %maskedptr = and i64 %ptrint, 31
265  %maskcond = icmp eq i64 %maskedptr, 0
266  tail call void @llvm.assume(i1 %maskcond)
267  br label %for.body
268
269for.body:                                         ; preds = %entry, %for.body
270  %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ]
271  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
272  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
273  %0 = load i32, i32* %arrayidx, align 4
274  %add = add nsw i32 %0, %r.06
275  %indvars.iv.next = add i64 %indvars.iv, 4
276  %1 = trunc i64 %indvars.iv.next to i32
277  %cmp = icmp slt i32 %1, 2048
278  br i1 %cmp, label %for.body, label %for.end
279
280for.end:                                          ; preds = %for.body
281  %add.lcssa = phi i32 [ %add, %for.body ]
282  ret i32 %add.lcssa
283
284}
285
286define i32 @moo(i32* nocapture %a) nounwind uwtable {
287; CHECK-LABEL: define {{[^@]+}}@moo
288; CHECK-SAME: (i32* nocapture [[A:%.*]]) #1
289; CHECK-NEXT:  entry:
290; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
291; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
292; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
293; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
294; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32* [[A]] to i8*
295; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP0]], i8 0, i64 64, i1 false)
296; CHECK-NEXT:    ret i32 undef
297;
298entry:
299  %ptrint = ptrtoint i32* %a to i64
300  %maskedptr = and i64 %ptrint, 31
301  %maskcond = icmp eq i64 %maskedptr, 0
302  tail call void @llvm.assume(i1 %maskcond)
303  %0 = bitcast i32* %a to i8*
304  tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false)
305  ret i32 undef
306
307}
308
309define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable {
310; CHECK-LABEL: define {{[^@]+}}@moo2
311; CHECK-SAME: (i32* nocapture [[A:%.*]], i32* nocapture [[B:%.*]]) #1
312; CHECK-NEXT:  entry:
313; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64
314; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
315; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
316; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
317; CHECK-NEXT:    [[PTRINT1:%.*]] = ptrtoint i32* [[B]] to i64
318; CHECK-NEXT:    [[MASKEDPTR3:%.*]] = and i64 [[PTRINT1]], 127
319; CHECK-NEXT:    [[MASKCOND4:%.*]] = icmp eq i64 [[MASKEDPTR3]], 0
320; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND4]])
321; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32* [[A]] to i8*
322; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i32* [[B]] to i8*
323; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[TMP0]], i8* align 128 [[TMP1]], i64 64, i1 false)
324; CHECK-NEXT:    ret i32 undef
325;
326entry:
327  %ptrint = ptrtoint i32* %a to i64
328  %maskedptr = and i64 %ptrint, 31
329  %maskcond = icmp eq i64 %maskedptr, 0
330  tail call void @llvm.assume(i1 %maskcond)
331  %ptrint1 = ptrtoint i32* %b to i64
332  %maskedptr3 = and i64 %ptrint1, 127
333  %maskcond4 = icmp eq i64 %maskedptr3, 0
334  tail call void @llvm.assume(i1 %maskcond4)
335  %0 = bitcast i32* %a to i8*
336  %1 = bitcast i32* %b to i8*
337  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false)
338  ret i32 undef
339
340}
341
342declare void @llvm.assume(i1) nounwind
343
344declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
345declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
346
347