blob: 2bae4867870a109f374e254d16369a48986cf1a3 [file] [log] [blame]
Silviu Baranga98a13712015-06-08 10:27:06 +00001; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
Sean Silva284b0322016-07-07 01:01:53 +00002; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s
Silviu Baranga98a13712015-06-08 10:27:06 +00003
Silviu Baranga98a13712015-06-08 10:27:06 +00004target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
5target triple = "aarch64--linux-gnueabi"
6
Silviu Baranga1b6b50a2015-07-08 09:16:33 +00007; 3 reads and 3 writes should need 12 memchecks
8; CHECK: function 'testf':
Silviu Baranga98a13712015-06-08 10:27:06 +00009; CHECK: Memory dependences are safe with run-time checks
Silviu Baranga1b6b50a2015-07-08 09:16:33 +000010
11; Memory dependencies have labels starting from 0, so in
Silviu Baranga98a13712015-06-08 10:27:06 +000012; order to verify that we have n checks, we look for
13; (n-1): and not n:.
14
15; CHECK: Run-time memory checks:
Silviu Baranga1b6b50a2015-07-08 09:16:33 +000016; CHECK-NEXT: Check 0:
17; CHECK: Check 11:
18; CHECK-NOT: Check 12:
Silviu Baranga98a13712015-06-08 10:27:06 +000019
20define void @testf(i16* %a,
21 i16* %b,
22 i16* %c,
23 i16* %d,
24 i16* %e,
25 i16* %f) {
26entry:
27 br label %for.body
28
29for.body: ; preds = %for.body, %entry
30 %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
31
32 %add = add nuw nsw i64 %ind, 1
33
34 %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind
35 %loadA = load i16, i16* %arrayidxA, align 2
36
37 %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind
38 %loadB = load i16, i16* %arrayidxB, align 2
39
40 %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %ind
41 %loadC = load i16, i16* %arrayidxC, align 2
42
43 %mul = mul i16 %loadB, %loadA
44 %mul1 = mul i16 %mul, %loadC
45
46 %arrayidxD = getelementptr inbounds i16, i16* %d, i64 %ind
47 store i16 %mul1, i16* %arrayidxD, align 2
48
49 %arrayidxE = getelementptr inbounds i16, i16* %e, i64 %ind
50 store i16 %mul, i16* %arrayidxE, align 2
51
52 %arrayidxF = getelementptr inbounds i16, i16* %f, i64 %ind
53 store i16 %mul1, i16* %arrayidxF, align 2
54
55 %exitcond = icmp eq i64 %add, 20
56 br i1 %exitcond, label %for.end, label %for.body
57
58for.end: ; preds = %for.body
59 ret void
60}
Silviu Baranga1b6b50a2015-07-08 09:16:33 +000061
62; The following (testg and testh) check that we can group
63; memory checks of accesses which differ by a constant value.
64; Both tests are based on the following C code:
65;
66; void testh(short *a, short *b, short *c) {
67; unsigned long ind = 0;
68; for (unsigned long ind = 0; ind < 20; ++ind) {
69; c[2 * ind] = a[ind] * a[ind + 1];
70; c[2 * ind + 1] = a[ind] * a[ind + 1] * b[ind];
71; }
72; }
73;
74; It is sufficient to check the intervals
75; [a, a + 21], [b, b + 20] against [c, c + 41].
76
77; 3 reads and 2 writes - two of the reads can be merged,
78; and the writes can be merged as well. This gives us a
79; total of 2 memory checks.
80
81; CHECK: function 'testg':
82
83; CHECK: Run-time memory checks:
84; CHECK-NEXT: Check 0:
Adam Nemet54f0b832015-07-27 23:54:41 +000085; CHECK-NEXT: Comparing group ([[ZERO:.+]]):
Silviu Barangace3877f2015-07-09 15:18:25 +000086; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
Silviu Barangaa647c302015-07-13 14:48:24 +000087; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
Adam Nemet54f0b832015-07-27 23:54:41 +000088; CHECK-NEXT: Against group ([[ONE:.+]]):
Silviu Barangace3877f2015-07-09 15:18:25 +000089; CHECK-NEXT: %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add
Silviu Barangaa647c302015-07-13 14:48:24 +000090; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind
Silviu Baranga1b6b50a2015-07-08 09:16:33 +000091; CHECK-NEXT: Check 1:
Adam Nemet54f0b832015-07-27 23:54:41 +000092; CHECK-NEXT: Comparing group ({{.*}}[[ZERO]]):
Silviu Barangace3877f2015-07-09 15:18:25 +000093; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
Silviu Barangaa647c302015-07-13 14:48:24 +000094; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
Adam Nemet54f0b832015-07-27 23:54:41 +000095; CHECK-NEXT: Against group ([[TWO:.+]]):
Silviu Barangace3877f2015-07-09 15:18:25 +000096; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind
Silviu Baranga1b6b50a2015-07-08 09:16:33 +000097; CHECK-NEXT: Grouped accesses:
Adam Nemet54f0b832015-07-27 23:54:41 +000098; CHECK-NEXT: Group {{.*}}[[ZERO]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +000099; CHECK-NEXT: (Low: %c High: (80 + %c))
Oleg Ranevskyyeb4ecca2016-05-25 13:01:33 +0000100; CHECK-NEXT: Member: {(2 + %c)<nsw>,+,4}
Silviu Barangaa647c302015-07-13 14:48:24 +0000101; CHECK-NEXT: Member: {%c,+,4}
Adam Nemet54f0b832015-07-27 23:54:41 +0000102; CHECK-NEXT: Group {{.*}}[[ONE]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000103; CHECK-NEXT: (Low: %a High: (42 + %a))
Oleg Ranevskyyeb4ecca2016-05-25 13:01:33 +0000104; CHECK-NEXT: Member: {(2 + %a)<nsw>,+,2}
Silviu Barangaa647c302015-07-13 14:48:24 +0000105; CHECK-NEXT: Member: {%a,+,2}
Adam Nemet54f0b832015-07-27 23:54:41 +0000106; CHECK-NEXT: Group {{.*}}[[TWO]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000107; CHECK-NEXT: (Low: %b High: (40 + %b))
Silviu Baranga1b6b50a2015-07-08 09:16:33 +0000108; CHECK-NEXT: Member: {%b,+,2}
Silviu Baranga1b6b50a2015-07-08 09:16:33 +0000109
110define void @testg(i16* %a,
111 i16* %b,
112 i16* %c) {
113entry:
114 br label %for.body
115
116for.body: ; preds = %for.body, %entry
117 %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
118 %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]
119
120 %add = add nuw nsw i64 %ind, 1
121 %store_ind_inc = add nuw nsw i64 %store_ind, 1
122 %store_ind_next = add nuw nsw i64 %store_ind_inc, 1
123
124 %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind
125 %loadA = load i16, i16* %arrayidxA, align 2
126
127 %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add
128 %loadA1 = load i16, i16* %arrayidxA1, align 2
129
130 %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind
131 %loadB = load i16, i16* %arrayidxB, align 2
132
133 %mul = mul i16 %loadA, %loadA1
134 %mul1 = mul i16 %mul, %loadB
135
136 %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
137 store i16 %mul1, i16* %arrayidxC, align 2
138
139 %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
140 store i16 %mul, i16* %arrayidxC1, align 2
141
142 %exitcond = icmp eq i64 %add, 20
143 br i1 %exitcond, label %for.end, label %for.body
144
145for.end: ; preds = %for.body
146 ret void
147}
148
149; 3 reads and 2 writes - the writes can be merged into a single
150; group, but the GEPs used for the reads are not marked as inbounds.
151; We can still merge them because we are using a unit stride for
152; accesses, so we cannot overflow the GEPs.
153
154; CHECK: function 'testh':
155; CHECK: Run-time memory checks:
156; CHECK-NEXT: Check 0:
Adam Nemet54f0b832015-07-27 23:54:41 +0000157; CHECK-NEXT: Comparing group ([[ZERO:.+]]):
Silviu Barangace3877f2015-07-09 15:18:25 +0000158; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
Silviu Barangaa647c302015-07-13 14:48:24 +0000159; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
Adam Nemet54f0b832015-07-27 23:54:41 +0000160; CHECK-NEXT: Against group ([[ONE:.+]]):
Silviu Barangace3877f2015-07-09 15:18:25 +0000161; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %add
Silviu Barangaa647c302015-07-13 14:48:24 +0000162; CHECK-NEXT: %arrayidxA = getelementptr i16, i16* %a, i64 %ind
Silviu Baranga1b6b50a2015-07-08 09:16:33 +0000163; CHECK-NEXT: Check 1:
Adam Nemet54f0b832015-07-27 23:54:41 +0000164; CHECK-NEXT: Comparing group ({{.*}}[[ZERO]]):
Silviu Barangace3877f2015-07-09 15:18:25 +0000165; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
Silviu Barangaa647c302015-07-13 14:48:24 +0000166; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
Adam Nemet54f0b832015-07-27 23:54:41 +0000167; CHECK-NEXT: Against group ([[TWO:.+]]):
Silviu Barangace3877f2015-07-09 15:18:25 +0000168; CHECK-NEXT: %arrayidxB = getelementptr i16, i16* %b, i64 %ind
Silviu Baranga1b6b50a2015-07-08 09:16:33 +0000169; CHECK-NEXT: Grouped accesses:
Adam Nemet54f0b832015-07-27 23:54:41 +0000170; CHECK-NEXT: Group {{.*}}[[ZERO]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000171; CHECK-NEXT: (Low: %c High: (80 + %c))
Oleg Ranevskyyeb4ecca2016-05-25 13:01:33 +0000172; CHECK-NEXT: Member: {(2 + %c)<nsw>,+,4}
Silviu Barangaa647c302015-07-13 14:48:24 +0000173; CHECK-NEXT: Member: {%c,+,4}
Adam Nemet54f0b832015-07-27 23:54:41 +0000174; CHECK-NEXT: Group {{.*}}[[ONE]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000175; CHECK-NEXT: (Low: %a High: (42 + %a))
Silviu Barangace3877f2015-07-09 15:18:25 +0000176; CHECK-NEXT: Member: {(2 + %a),+,2}
Silviu Barangaa647c302015-07-13 14:48:24 +0000177; CHECK-NEXT: Member: {%a,+,2}
Adam Nemet54f0b832015-07-27 23:54:41 +0000178; CHECK-NEXT: Group {{.*}}[[TWO]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000179; CHECK-NEXT: (Low: %b High: (40 + %b))
Silviu Baranga1b6b50a2015-07-08 09:16:33 +0000180; CHECK-NEXT: Member: {%b,+,2}
Silviu Baranga1b6b50a2015-07-08 09:16:33 +0000181
182define void @testh(i16* %a,
183 i16* %b,
184 i16* %c) {
185entry:
186 br label %for.body
187
188for.body: ; preds = %for.body, %entry
189 %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
190 %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]
191
192 %add = add nuw nsw i64 %ind, 1
193 %store_ind_inc = add nuw nsw i64 %store_ind, 1
194 %store_ind_next = add nuw nsw i64 %store_ind_inc, 1
195
196 %arrayidxA = getelementptr i16, i16* %a, i64 %ind
197 %loadA = load i16, i16* %arrayidxA, align 2
198
199 %arrayidxA1 = getelementptr i16, i16* %a, i64 %add
200 %loadA1 = load i16, i16* %arrayidxA1, align 2
201
202 %arrayidxB = getelementptr i16, i16* %b, i64 %ind
203 %loadB = load i16, i16* %arrayidxB, align 2
204
205 %mul = mul i16 %loadA, %loadA1
206 %mul1 = mul i16 %mul, %loadB
207
208 %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
209 store i16 %mul1, i16* %arrayidxC, align 2
210
211 %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
212 store i16 %mul, i16* %arrayidxC1, align 2
213
214 %exitcond = icmp eq i64 %add, 20
215 br i1 %exitcond, label %for.end, label %for.body
216
217for.end: ; preds = %for.body
218 ret void
219}
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000220
Silviu Baranga48250602015-07-28 13:44:08 +0000221; Don't merge pointers if we need to perform a check against a pointer
222; to the same underlying object (doing so would emit a check that could be
223; falsely invalidated) For example, in the following loop:
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000224;
225; for (i = 0; i < 5000; ++i)
226; a[i + offset] = a[i] + a[i + 10000]
227;
228; we should not merge the intervals associated with the reads (0,5000) and
229; (10000, 15000) into (0, 15000) as this will pottentially fail the check
230; against the interval associated with the write.
Silviu Baranga48250602015-07-28 13:44:08 +0000231;
232; We cannot have this check unless ShouldRetryWithRuntimeCheck is set,
233; and therefore the grouping algorithm would create a separate group for
234; each pointer.
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000235
236; CHECK: function 'testi':
237; CHECK: Run-time memory checks:
238; CHECK-NEXT: Check 0:
Adam Nemet54f0b832015-07-27 23:54:41 +0000239; CHECK-NEXT: Comparing group ([[ZERO:.+]]):
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000240; CHECK-NEXT: %storeidx = getelementptr inbounds i16, i16* %a, i64 %store_ind
Adam Nemet54f0b832015-07-27 23:54:41 +0000241; CHECK-NEXT: Against group ([[ONE:.+]]):
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000242; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %ind
243; CHECK-NEXT: Check 1:
Adam Nemet54f0b832015-07-27 23:54:41 +0000244; CHECK-NEXT: Comparing group ({{.*}}[[ZERO]]):
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000245; CHECK-NEXT: %storeidx = getelementptr inbounds i16, i16* %a, i64 %store_ind
Adam Nemet54f0b832015-07-27 23:54:41 +0000246; CHECK-NEXT: Against group ([[TWO:.+]]):
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000247; CHECK-NEXT: %arrayidxA2 = getelementptr i16, i16* %a, i64 %ind2
248; CHECK-NEXT: Grouped accesses:
Adam Nemet54f0b832015-07-27 23:54:41 +0000249; CHECK-NEXT: Group {{.*}}[[ZERO]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000250; CHECK-NEXT: (Low: ((2 * %offset) + %a)<nsw> High: (10000 + (2 * %offset) + %a))
Oleg Ranevskyyeb4ecca2016-05-25 13:01:33 +0000251; CHECK-NEXT: Member: {((2 * %offset) + %a)<nsw>,+,2}<nsw><%for.body>
Adam Nemet54f0b832015-07-27 23:54:41 +0000252; CHECK-NEXT: Group {{.*}}[[ONE]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000253; CHECK-NEXT: (Low: %a High: (10000 + %a))
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000254; CHECK-NEXT: Member: {%a,+,2}<%for.body>
Adam Nemet54f0b832015-07-27 23:54:41 +0000255; CHECK-NEXT: Group {{.*}}[[TWO]]:
Elena Demikhovsky3622fbf2016-08-28 08:53:53 +0000256; CHECK-NEXT: (Low: (20000 + %a) High: (30000 + %a))
Silviu Baranga3e3095c2015-07-09 16:40:25 +0000257; CHECK-NEXT: Member: {(20000 + %a),+,2}<%for.body>
258
259define void @testi(i16* %a,
260 i64 %offset) {
261entry:
262 br label %for.body
263
264for.body: ; preds = %for.body, %entry
265 %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
266 %store_ind = phi i64 [ %offset, %entry ], [ %store_ind_inc, %for.body ]
267
268 %add = add nuw nsw i64 %ind, 1
269 %store_ind_inc = add nuw nsw i64 %store_ind, 1
270
271 %arrayidxA1 = getelementptr i16, i16* %a, i64 %ind
272 %ind2 = add nuw nsw i64 %ind, 10000
273 %arrayidxA2 = getelementptr i16, i16* %a, i64 %ind2
274
275 %loadA1 = load i16, i16* %arrayidxA1, align 2
276 %loadA2 = load i16, i16* %arrayidxA2, align 2
277
278 %addres = add i16 %loadA1, %loadA2
279
280 %storeidx = getelementptr inbounds i16, i16* %a, i64 %store_ind
281 store i16 %addres, i16* %storeidx, align 2
282
283 %exitcond = icmp eq i64 %add, 5000
284 br i1 %exitcond, label %for.end, label %for.body
285
286for.end: ; preds = %for.body
287 ret void
288}