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