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:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
11; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A]], align 32
12; CHECK-NEXT:    ret i32 [[TMP0]]
13;
14entry:
15  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
16  %0 = load i32, i32* %a, align 4
17  ret i32 %0
18
19}
20
21define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly {
22; CHECK-LABEL: define {{[^@]+}}@foo2
23; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
24; CHECK-NEXT:  entry:
25; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 24) ]
26; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 -2
27; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
28; CHECK-NEXT:    ret i32 [[TMP0]]
29;
30entry:
31  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 24)]
32  %arrayidx = getelementptr inbounds i32, i32* %a, i64 -2
33  %0 = load i32, i32* %arrayidx, align 4
34  ret i32 %0
35
36}
37
38define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly {
39; CHECK-LABEL: define {{[^@]+}}@foo2a
40; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
41; CHECK-NEXT:  entry:
42; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 28) ]
43; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 1
44; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32
45; CHECK-NEXT:    ret i32 [[TMP0]]
46;
47entry:
48  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 28)]
49  %arrayidx = getelementptr inbounds i32, i32* %a, i64 1
50  %0 = load i32, i32* %arrayidx, align 4
51  ret i32 %0
52
53}
54
55; TODO: this can be 8-bytes aligned
56define i32 @foo2b(i32* nocapture %a) nounwind uwtable readonly {
57; CHECK-LABEL: define {{[^@]+}}@foo2b
58; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
59; CHECK-NEXT:  entry:
60; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 28) ]
61; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 -1
62; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
63; CHECK-NEXT:    ret i32 [[TMP0]]
64;
65entry:
66  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 28)]
67  %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1
68  %0 = load i32, i32* %arrayidx, align 4
69  ret i32 %0
70
71}
72
73define i32 @goo(i32* nocapture %a) nounwind uwtable readonly {
74; CHECK-LABEL: define {{[^@]+}}@goo
75; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
76; CHECK-NEXT:  entry:
77; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
78; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A]], align 32
79; CHECK-NEXT:    ret i32 [[TMP0]]
80;
81entry:
82  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
83  %0 = load i32, i32* %a, align 4
84  ret i32 %0
85
86}
87
88define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly {
89; CHECK-LABEL: define {{[^@]+}}@hoo
90; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
91; CHECK-NEXT:  entry:
92; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
93; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
94; CHECK:       for.body:
95; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
96; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
97; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
98; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32
99; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
100; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 8
101; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
102; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
103; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
104; CHECK:       for.end:
105; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
106; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
107;
108entry:
109  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
110  br label %for.body
111
112for.body:                                         ; preds = %entry, %for.body
113  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
114  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
115  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
116  %0 = load i32, i32* %arrayidx, align 4
117  %add = add nsw i32 %0, %r.06
118  %indvars.iv.next = add i64 %indvars.iv, 8
119  %1 = trunc i64 %indvars.iv.next to i32
120  %cmp = icmp slt i32 %1, 2048
121  br i1 %cmp, label %for.body, label %for.end
122
123for.end:                                          ; preds = %for.body
124  %add.lcssa = phi i32 [ %add, %for.body ]
125  ret i32 %add.lcssa
126
127}
128
129define i32 @joo(i32* nocapture %a) nounwind uwtable readonly {
130; CHECK-LABEL: define {{[^@]+}}@joo
131; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
132; CHECK-NEXT:  entry:
133; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
134; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
135; CHECK:       for.body:
136; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
137; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
138; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
139; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
140; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
141; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 8
142; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
143; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
144; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
145; CHECK:       for.end:
146; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
147; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
148;
149entry:
150  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
151  br label %for.body
152
153for.body:                                         ; preds = %entry, %for.body
154  %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ]
155  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
156  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
157  %0 = load i32, i32* %arrayidx, align 4
158  %add = add nsw i32 %0, %r.06
159  %indvars.iv.next = add i64 %indvars.iv, 8
160  %1 = trunc i64 %indvars.iv.next to i32
161  %cmp = icmp slt i32 %1, 2048
162  br i1 %cmp, label %for.body, label %for.end
163
164for.end:                                          ; preds = %for.body
165  %add.lcssa = phi i32 [ %add, %for.body ]
166  ret i32 %add.lcssa
167
168}
169
170define i32 @koo(i32* nocapture %a) nounwind uwtable readonly {
171; CHECK-LABEL: define {{[^@]+}}@koo
172; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
173; CHECK-NEXT:  entry:
174; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
175; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
176; CHECK:       for.body:
177; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
178; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
179; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
180; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
181; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
182; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 4
183; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
184; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
185; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
186; CHECK:       for.end:
187; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
188; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
189;
190entry:
191  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
192  br label %for.body
193
194for.body:                                         ; preds = %entry, %for.body
195  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
196  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
197  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
198  %0 = load i32, i32* %arrayidx, align 4
199  %add = add nsw i32 %0, %r.06
200  %indvars.iv.next = add i64 %indvars.iv, 4
201  %1 = trunc i64 %indvars.iv.next to i32
202  %cmp = icmp slt i32 %1, 2048
203  br i1 %cmp, label %for.body, label %for.end
204
205for.end:                                          ; preds = %for.body
206  %add.lcssa = phi i32 [ %add, %for.body ]
207  ret i32 %add.lcssa
208
209}
210
211define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly {
212; CHECK-LABEL: define {{[^@]+}}@koo2
213; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0
214; CHECK-NEXT:  entry:
215; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
216; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
217; CHECK:       for.body:
218; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ -4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
219; CHECK-NEXT:    [[R_06:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
220; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]]
221; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16
222; CHECK-NEXT:    [[ADD]] = add nsw i32 [[TMP0]], [[R_06]]
223; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 4
224; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
225; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2048
226; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
227; CHECK:       for.end:
228; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
229; CHECK-NEXT:    ret i32 [[ADD_LCSSA]]
230;
231entry:
232  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
233  br label %for.body
234
235for.body:                                         ; preds = %entry, %for.body
236  %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ]
237  %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ]
238  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
239  %0 = load i32, i32* %arrayidx, align 4
240  %add = add nsw i32 %0, %r.06
241  %indvars.iv.next = add i64 %indvars.iv, 4
242  %1 = trunc i64 %indvars.iv.next to i32
243  %cmp = icmp slt i32 %1, 2048
244  br i1 %cmp, label %for.body, label %for.end
245
246for.end:                                          ; preds = %for.body
247  %add.lcssa = phi i32 [ %add, %for.body ]
248  ret i32 %add.lcssa
249
250}
251
252define i32 @moo(i32* nocapture %a) nounwind uwtable {
253; CHECK-LABEL: define {{[^@]+}}@moo
254; CHECK-SAME: (i32* nocapture [[A:%.*]]) #1
255; CHECK-NEXT:  entry:
256; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
257; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32* [[A]] to i8*
258; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP0]], i8 0, i64 64, i1 false)
259; CHECK-NEXT:    ret i32 undef
260;
261entry:
262  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
263  %0 = bitcast i32* %a to i8*
264  tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false)
265  ret i32 undef
266
267}
268
269define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable {
270; CHECK-LABEL: define {{[^@]+}}@moo2
271; CHECK-SAME: (i32* nocapture [[A:%.*]], i32* nocapture [[B:%.*]]) #1
272; CHECK-NEXT:  entry:
273; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ]
274; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[B]], i64 128) ]
275; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32* [[A]] to i8*
276; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i32* [[B]] to i8*
277; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[TMP0]], i8* align 128 [[TMP1]], i64 64, i1 false)
278; CHECK-NEXT:    ret i32 undef
279;
280entry:
281  call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)]
282  call void @llvm.assume(i1 true) ["align"(i32* %b, i64 128)]
283  %0 = bitcast i32* %a to i8*
284  %1 = bitcast i32* %b to i8*
285  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false)
286  ret i32 undef
287
288}
289
290declare void @llvm.assume(i1) nounwind
291
292declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
293declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
294
295