1; REQUIRES: asserts
2; RUN: opt -mtriple=s390x-unknown-linux -mcpu=z13 -loop-vectorize \
3; RUN:   -debug-only=loop-vectorize,vectorutils -max-interleave-group-factor=64\
4; RUN:   -disable-output < %s 2>&1 | FileCheck %s
5;
6; Check that some cost estimations for interleave groups make sense.
7
8; This loop is loading four i16 values at indices [0, 1, 2, 3], with a stride
9; of 4. At VF=4, memory interleaving means loading 4 * 4 * 16 bits = 2 vector
10; registers. Each of the 4 vector values must then be constructed from the
11; two vector registers using one vperm each, which gives a cost of 2 + 4 = 6.
12;
13; CHECK: LV: Checking a loop in 'fun0'
14; CHECK: LV: Found an estimated cost of 6 for VF 4 For instruction:   %ld0 = load i16
15; CHECK: LV: Found an estimated cost of 0 for VF 4 For instruction:   %ld1 = load i16
16; CHECK: LV: Found an estimated cost of 0 for VF 4 For instruction:   %ld2 = load i16
17; CHECK: LV: Found an estimated cost of 0 for VF 4 For instruction:   %ld3 = load i16
18define void @fun0(i16 *%ptr, i16 *%dst) {
19entry:
20  br label %for.body
21
22for.body:
23  %ivptr = phi i16* [ %ptr.next, %for.body ], [ %ptr, %entry ]
24  %iv = phi i64 [ %inc, %for.body ], [ 0, %entry ]
25  %inc = add i64 %iv, 4
26  %ptr0 = getelementptr inbounds i16, i16* %ivptr, i64 0
27  %ld0 = load i16, i16* %ptr0
28  %ptr1 = getelementptr inbounds i16, i16* %ivptr, i64 1
29  %ld1 = load i16, i16* %ptr1
30  %ptr2 = getelementptr inbounds i16, i16* %ivptr, i64 2
31  %ld2 = load i16, i16* %ptr2
32  %ptr3 = getelementptr inbounds i16, i16* %ivptr, i64 3
33  %ld3 = load i16, i16* %ptr3
34  %a1 = add i16 %ld0, %ld1
35  %a2 = add i16 %a1, %ld2
36  %a3 = add i16 %a2, %ld3
37  %dstptr = getelementptr inbounds i16, i16* %dst, i64 %iv
38  store i16 %a3, i16* %dstptr
39  %ptr.next = getelementptr inbounds i16, i16* %ivptr, i64 4
40  %cmp = icmp eq i64 %inc, 100
41  br i1 %cmp, label %for.end, label %for.body
42
43for.end:
44  ret void
45}
46
47; This loop loads one i8 value in a stride of 3. At VF=16, this means loading
48; 3 vector registers, and then constructing the vector value with two vperms,
49; which gives a cost of 5.
50;
51; CHECK: LV: Checking a loop in 'fun1'
52; CHECK: LV: Found an estimated cost of 5 for VF 16 For instruction:   %ld0 = load i8
53define void @fun1(i8 *%ptr, i8 *%dst) {
54entry:
55  br label %for.body
56
57for.body:
58  %ivptr = phi i8* [ %ptr.next, %for.body ], [ %ptr, %entry ]
59  %iv = phi i64 [ %inc, %for.body ], [ 0, %entry ]
60  %inc = add i64 %iv, 4
61  %ptr0 = getelementptr inbounds i8, i8* %ivptr, i64 0
62  %ld0 = load i8, i8* %ptr0
63  %dstptr = getelementptr inbounds i8, i8* %dst, i64 %iv
64  store i8 %ld0, i8* %dstptr
65  %ptr.next = getelementptr inbounds i8, i8* %ivptr, i64 3
66  %cmp = icmp eq i64 %inc, 100
67  br i1 %cmp, label %for.end, label %for.body
68
69for.end:
70  ret void
71}
72
73; This loop is loading 4 i8 values at indexes [0, 1, 2, 3], with a stride of
74; 32. At VF=2, this means loading 2 vector registers, and using 4 vperms to
75; produce the vector values, which gives a cost of 6.
76;
77; CHECK: LV: Checking a loop in 'fun2'
78; CHECK: LV: Found an estimated cost of 6 for VF 2 For instruction:   %ld0 = load i8
79; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction:   %ld1 = load i8
80; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction:   %ld2 = load i8
81; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction:   %ld3 = load i8
82define void @fun2(i8 *%ptr, i8 *%dst) {
83entry:
84  br label %for.body
85
86for.body:
87  %ivptr = phi i8* [ %ptr.next, %for.body ], [ %ptr, %entry ]
88  %iv = phi i64 [ %inc, %for.body ], [ 0, %entry ]
89  %inc = add i64 %iv, 4
90  %ptr0 = getelementptr inbounds i8, i8* %ivptr, i64 0
91  %ld0 = load i8, i8* %ptr0
92  %ptr1 = getelementptr inbounds i8, i8* %ivptr, i64 1
93  %ld1 = load i8, i8* %ptr1
94  %ptr2 = getelementptr inbounds i8, i8* %ivptr, i64 2
95  %ld2 = load i8, i8* %ptr2
96  %ptr3 = getelementptr inbounds i8, i8* %ivptr, i64 3
97  %ld3 = load i8, i8* %ptr3
98  %a1 = add i8 %ld0, %ld1
99  %a2 = add i8 %a1, %ld2
100  %a3 = add i8 %a2, %ld3
101  %dstptr = getelementptr inbounds i8, i8* %dst, i64 %iv
102  store i8 %a3, i8* %dstptr
103  %ptr.next = getelementptr inbounds i8, i8* %ivptr, i64 32
104  %cmp = icmp eq i64 %inc, 100
105  br i1 %cmp, label %for.end, label %for.body
106
107for.end:
108  ret void
109}
110
111; This loop is loading 4 i8 values at indexes [0, 1, 2, 3], with a stride of
112; 30. At VF=2, this means loading 3 vector registers, and using 4 vperms to
113; produce the vector values, which gives a cost of 7. This is the same loop
114; as in fun2, except the stride makes the second iterations values overlap a
115; vector register boundary.
116;
117; CHECK: LV: Checking a loop in 'fun3'
118; CHECK: LV: Found an estimated cost of 7 for VF 2 For instruction:   %ld0 = load i8
119; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction:   %ld1 = load i8
120; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction:   %ld2 = load i8
121; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction:   %ld3 = load i8
122define void @fun3(i8 *%ptr, i8 *%dst) {
123entry:
124  br label %for.body
125
126for.body:
127  %ivptr = phi i8* [ %ptr.next, %for.body ], [ %ptr, %entry ]
128  %iv = phi i64 [ %inc, %for.body ], [ 0, %entry ]
129  %inc = add i64 %iv, 4
130  %ptr0 = getelementptr inbounds i8, i8* %ivptr, i64 0
131  %ld0 = load i8, i8* %ptr0
132  %ptr1 = getelementptr inbounds i8, i8* %ivptr, i64 1
133  %ld1 = load i8, i8* %ptr1
134  %ptr2 = getelementptr inbounds i8, i8* %ivptr, i64 2
135  %ld2 = load i8, i8* %ptr2
136  %ptr3 = getelementptr inbounds i8, i8* %ivptr, i64 3
137  %ld3 = load i8, i8* %ptr3
138  %a1 = add i8 %ld0, %ld1
139  %a2 = add i8 %a1, %ld2
140  %a3 = add i8 %a2, %ld3
141  %dstptr = getelementptr inbounds i8, i8* %dst, i64 %iv
142  store i8 %a3, i8* %dstptr
143  %ptr.next = getelementptr inbounds i8, i8* %ivptr, i64 30
144  %cmp = icmp eq i64 %inc, 100
145  br i1 %cmp, label %for.end, label %for.body
146
147for.end:
148  ret void
149}
150