1; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
2
3; The runtime memory check code and the access grouping
4; algorithm both assume that the start and end values
5; for an access range are ordered (start <= stop).
6; When generating checks for accesses with negative stride
7; we need to take this into account and swap the interval
8; ends.
9;
10;   for (i = 0; i < 10000; i++) {
11;     B[i] = A[15000 - i] * 3;
12;   }
13
14target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
15target triple = "aarch64--linux-gnueabi"
16
17; CHECK: function 'f':
18; CHECK: (Low: (20000 + %a) High: (60000 + %a))
19
20@B = common global i32* null, align 8
21@A = common global i32* null, align 8
22
23define void @f() {
24entry:
25  %a = load i32*, i32** @A, align 8
26  %b = load i32*, i32** @B, align 8
27  br label %for.body
28
29for.body:                                         ; preds = %for.body, %entry
30  %idx = phi i64 [ 0, %entry ], [ %add, %for.body ]
31  %negidx = sub i64 15000, %idx
32
33  %arrayidxA0 = getelementptr inbounds i32, i32* %a, i64 %negidx
34  %loadA0 = load i32, i32* %arrayidxA0, align 2
35
36  %res = mul i32 %loadA0, 3
37
38  %add = add nuw nsw i64 %idx, 1
39
40  %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %idx
41  store i32 %res, i32* %arrayidxB, align 2
42
43  %exitcond = icmp eq i64 %idx, 10000
44  br i1 %exitcond, label %for.end, label %for.body
45
46for.end:                                          ; preds = %for.body
47  ret void
48}
49
50; CHECK: function 'g':
51; When the stride is not constant, we are forced to do umin/umax to get
52; the interval limits.
53
54;   for (i = 0; i < 10000; i++) {
55;     B[i] = A[15000 - step * i] * 3;
56;   }
57
58; Here it is not obvious what the limits are, since 'step' could be negative.
59
60; CHECK: Low: (-1 + (-1 * ((-60001 + (-1 * %a)) umax (-60001 + (40000 * %step) + (-1 * %a)))))
61; CHECK: High: ((60000 + %a) umax (60000 + (-40000 * %step) + %a))
62
63define void @g(i64 %step) {
64entry:
65  %a = load i32*, i32** @A, align 8
66  %b = load i32*, i32** @B, align 8
67  br label %for.body
68
69for.body:                                         ; preds = %for.body, %entry
70  %idx = phi i64 [ 0, %entry ], [ %add, %for.body ]
71  %idx_mul = mul i64 %idx, %step
72  %negidx = sub i64 15000, %idx_mul
73
74  %arrayidxA0 = getelementptr inbounds i32, i32* %a, i64 %negidx
75  %loadA0 = load i32, i32* %arrayidxA0, align 2
76
77  %res = mul i32 %loadA0, 3
78
79  %add = add nuw nsw i64 %idx, 1
80
81  %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %idx
82  store i32 %res, i32* %arrayidxB, align 2
83
84  %exitcond = icmp eq i64 %idx, 10000
85  br i1 %exitcond, label %for.end, label %for.body
86
87for.end:                                          ; preds = %for.body
88  ret void
89}
90