1; RUN: opt -S -slp-vectorizer -slp-threshold=-18 -dce -instcombine -pass-remarks-output=%t < %s | FileCheck %s 2; RUN: cat %t | FileCheck -check-prefix=YAML %s 3; RUN: opt -S -passes='slp-vectorizer,dce,instcombine' -slp-threshold=-18 -pass-remarks-output=%t < %s | FileCheck %s 4; RUN: cat %t | FileCheck -check-prefix=YAML %s 5 6 7target datalayout = "e-m:e-i32:64-i128:128-n32:64-S128" 8target triple = "aarch64--linux-gnu" 9 10; These tests check that we remove from consideration pairs of seed 11; getelementptrs when they are known to have a constant difference. Such pairs 12; are likely not good candidates for vectorization since one can be computed 13; from the other. We use an unprofitable threshold to force vectorization. 14; 15; int getelementptr(int *g, int n, int w, int x, int y, int z) { 16; int sum = 0; 17; for (int i = 0; i < n ; ++i) { 18; sum += g[2*i + w]; sum += g[2*i + x]; 19; sum += g[2*i + y]; sum += g[2*i + z]; 20; } 21; return sum; 22; } 23; 24 25; CHECK-LABEL: @getelementptr_4x32 26; 27; CHECK: [[A:%[a-zA-Z0-9.]+]] = add nsw <4 x i32> 28; CHECK: [[X:%[a-zA-Z0-9.]+]] = extractelement <4 x i32> [[A]] 29; CHECK: sext i32 [[X]] to i64 30 31; YAML: Pass: slp-vectorizer 32; YAML-NEXT: Name: VectorizedList 33; YAML-NEXT: Function: getelementptr_4x32 34; YAML-NEXT: Args: 35; YAML-NEXT: - String: 'SLP vectorized with cost ' 36; YAML-NEXT: - Cost: '11' 37; YAML-NEXT: - String: ' and with tree size ' 38; YAML-NEXT: - TreeSize: '5' 39 40; YAML: Pass: slp-vectorizer 41; YAML-NEXT: Name: VectorizedList 42; YAML-NEXT: Function: getelementptr_4x32 43; YAML-NEXT: Args: 44; YAML-NEXT: - String: 'SLP vectorized with cost ' 45; YAML-NEXT: - Cost: '16' 46; YAML-NEXT: - String: ' and with tree size ' 47; YAML-NEXT: - TreeSize: '3' 48 49define i32 @getelementptr_4x32(i32* nocapture readonly %g, i32 %n, i32 %x, i32 %y, i32 %z) { 50entry: 51 %cmp31 = icmp sgt i32 %n, 0 52 br i1 %cmp31, label %for.body.preheader, label %for.cond.cleanup 53 54for.body.preheader: 55 br label %for.body 56 57for.cond.cleanup.loopexit: 58 br label %for.cond.cleanup 59 60for.cond.cleanup: 61 %sum.0.lcssa = phi i32 [ 0, %entry ], [ %add16, %for.cond.cleanup.loopexit ] 62 ret i32 %sum.0.lcssa 63 64for.body: 65 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 66 %sum.032 = phi i32 [ 0, %for.body.preheader ], [ %add16, %for.body ] 67 %t4 = shl nsw i32 %indvars.iv, 1 68 %t5 = add nsw i32 %t4, 0 69 %arrayidx = getelementptr inbounds i32, i32* %g, i32 %t5 70 %t6 = load i32, i32* %arrayidx, align 4 71 %add1 = add nsw i32 %t6, %sum.032 72 %t7 = add nsw i32 %t4, %x 73 %arrayidx5 = getelementptr inbounds i32, i32* %g, i32 %t7 74 %t8 = load i32, i32* %arrayidx5, align 4 75 %add6 = add nsw i32 %add1, %t8 76 %t9 = add nsw i32 %t4, %y 77 %arrayidx10 = getelementptr inbounds i32, i32* %g, i32 %t9 78 %t10 = load i32, i32* %arrayidx10, align 4 79 %add11 = add nsw i32 %add6, %t10 80 %t11 = add nsw i32 %t4, %z 81 %arrayidx15 = getelementptr inbounds i32, i32* %g, i32 %t11 82 %t12 = load i32, i32* %arrayidx15, align 4 83 %add16 = add nsw i32 %add11, %t12 84 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 85 %exitcond = icmp eq i32 %indvars.iv.next , %n 86 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body 87} 88 89; CHECK-LABEL: @getelementptr_2x32 90; 91; CHECK: [[A:%[a-zA-Z0-9.]+]] = add nsw <2 x i32> 92; CHECK: [[X:%[a-zA-Z0-9.]+]] = extractelement <2 x i32> [[A]] 93; CHECK: sext i32 [[X]] to i64 94 95; YAML: Pass: slp-vectorizer 96; YAML-NEXT: Name: VectorizedList 97; YAML-NEXT: Function: getelementptr_2x32 98; YAML-NEXT: Args: 99; YAML-NEXT: - String: 'SLP vectorized with cost ' 100; YAML-NEXT: - Cost: '11' 101; YAML-NEXT: - String: ' and with tree size ' 102; YAML-NEXT: - TreeSize: '5' 103 104; YAML: Pass: slp-vectorizer 105; YAML-NEXT: Name: VectorizedList 106; YAML-NEXT: Function: getelementptr_2x32 107; YAML-NEXT: Args: 108; YAML-NEXT: - String: 'SLP vectorized with cost ' 109; YAML-NEXT: - Cost: '6' 110; YAML-NEXT: - String: ' and with tree size ' 111; YAML-NEXT: - TreeSize: '3' 112 113define i32 @getelementptr_2x32(i32* nocapture readonly %g, i32 %n, i32 %x, i32 %y, i32 %z) { 114entry: 115 %cmp31 = icmp sgt i32 %n, 0 116 br i1 %cmp31, label %for.body.preheader, label %for.cond.cleanup 117 118for.body.preheader: 119 br label %for.body 120 121for.cond.cleanup.loopexit: 122 br label %for.cond.cleanup 123 124for.cond.cleanup: 125 %sum.0.lcssa = phi i32 [ 0, %entry ], [ %add16, %for.cond.cleanup.loopexit ] 126 ret i32 %sum.0.lcssa 127 128for.body: 129 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 130 %sum.032 = phi i32 [ 0, %for.body.preheader ], [ %add16, %for.body ] 131 %t4 = shl nsw i32 %indvars.iv, 1 132 %t5 = add nsw i32 %t4, 0 133 %arrayidx = getelementptr inbounds i32, i32* %g, i32 %t5 134 %t6 = load i32, i32* %arrayidx, align 4 135 %add1 = add nsw i32 %t6, %sum.032 136 %t7 = add nsw i32 %t4, 1 137 %arrayidx5 = getelementptr inbounds i32, i32* %g, i32 %t7 138 %t8 = load i32, i32* %arrayidx5, align 4 139 %add6 = add nsw i32 %add1, %t8 140 %t9 = add nsw i32 %t4, %y 141 %arrayidx10 = getelementptr inbounds i32, i32* %g, i32 %t9 142 %t10 = load i32, i32* %arrayidx10, align 4 143 %add11 = add nsw i32 %add6, %t10 144 %t11 = add nsw i32 %t4, %z 145 %arrayidx15 = getelementptr inbounds i32, i32* %g, i32 %t11 146 %t12 = load i32, i32* %arrayidx15, align 4 147 %add16 = add nsw i32 %add11, %t12 148 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 149 %exitcond = icmp eq i32 %indvars.iv.next , %n 150 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body 151} 152