1; RUN: opt -disable-output -passes='print-access-info' %s 2>&1 | FileCheck %s 2 3target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 5; CHECK-LABEL: function 'forked_ptrs_simple': 6; CHECK-NEXT: loop: 7; CHECK-NEXT: Report: cannot identify array bounds 8; CHECK-NEXT: Dependences: 9; CHECK-NEXT: Run-time memory checks: 10; CHECK-NEXT: Grouped accesses: 11; CHECK-EMPTY: 12; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 13; CHECK-NEXT: SCEV assumptions: 14; CHECK-EMPTY: 15; CHECK-NEXT: Expressions re-written: 16 17define void @forked_ptrs_simple(float* nocapture readonly %Base1, float* nocapture readonly %Base2, float* %Dest) { 18entry: 19 br label %loop 20 21loop: 22 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 23 %gep.Dest = getelementptr inbounds float, float* %Dest, i64 %iv 24 %l.Dest = load float, float* %gep.Dest 25 %cmp = fcmp une float %l.Dest, 0.0 26 %gep.1 = getelementptr inbounds float, float* %Base1, i64 %iv 27 %gep.2 = getelementptr inbounds float, float* %Base2, i64 %iv 28 %select = select i1 %cmp, float* %gep.1, float* %gep.2 29 %sink = load float, float* %select, align 4 30 store float %sink, float* %gep.Dest, align 4 31 %iv.next = add nuw nsw i64 %iv, 1 32 %exitcond.not = icmp eq i64 %iv.next, 100 33 br i1 %exitcond.not, label %exit, label %loop 34 35exit: 36 ret void 37} 38 39 40; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset': 41; CHECK-NEXT: for.body: 42; CHECK-NEXT: Report: cannot identify array bounds 43; CHECK-NEXT: Dependences: 44; CHECK-NEXT: Run-time memory checks: 45; CHECK-NEXT: Grouped accesses: 46; CHECK-EMPTY: 47; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 48; CHECK-NEXT: SCEV assumptions: 49; CHECK-EMPTY: 50; CHECK-NEXT: Expressions re-written: 51 52;;;; Derived from the following C code 53;; void forked_ptrs_different_base_same_offset(float *A, float *B, float *C, int *D) { 54;; for (int i=0; i<100; i++) { 55;; if (D[i] != 0) { 56;; C[i] = A[i]; 57;; } else { 58;; C[i] = B[i]; 59;; } 60;; } 61;; } 62 63define dso_local void @forked_ptrs_different_base_same_offset(float* nocapture readonly %Base1, float* nocapture readonly %Base2, float* nocapture %Dest, i32* nocapture readonly %Preds) { 64entry: 65 br label %for.body 66 67for.cond.cleanup: 68 ret void 69 70for.body: 71 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 72 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 73 %0 = load i32, i32* %arrayidx, align 4 74 %cmp1.not = icmp eq i32 %0, 0 75 %spec.select = select i1 %cmp1.not, float* %Base2, float* %Base1 76 %.sink.in = getelementptr inbounds float, float* %spec.select, i64 %indvars.iv 77 %.sink = load float, float* %.sink.in, align 4 78 %1 = getelementptr inbounds float, float* %Dest, i64 %indvars.iv 79 store float %.sink, float* %1, align 4 80 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 81 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 82 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 83} 84 85; CHECK-LABEL: function 'forked_ptrs_same_base_different_offset': 86; CHECK-NEXT: for.body: 87; CHECK-NEXT: Report: cannot identify array bounds 88; CHECK-NEXT: Dependences: 89; CHECK-NEXT: Run-time memory checks: 90; CHECK-NEXT: Grouped accesses: 91; CHECK-EMPTY: 92; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 93; CHECK-NEXT: SCEV assumptions: 94; CHECK-EMPTY: 95; CHECK-NEXT: Expressions re-written: 96 97;;;; Derived from the following C code 98;; void forked_ptrs_same_base_different_offset(float *A, float *B, int *C) { 99;; int offset; 100;; for (int i = 0; i < 100; i++) { 101;; if (C[i] != 0) 102;; offset = i; 103;; else 104;; offset = i+1; 105;; B[i] = A[offset]; 106;; } 107;; } 108 109define dso_local void @forked_ptrs_same_base_different_offset(float* nocapture readonly %Base, float* nocapture %Dest, i32* nocapture readonly %Preds) { 110entry: 111 br label %for.body 112 113for.cond.cleanup: ; preds = %for.body 114 ret void 115 116for.body: ; preds = %entry, %for.body 117 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 118 %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 119 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 120 %0 = load i32, i32* %arrayidx, align 4 121 %cmp1.not = icmp eq i32 %0, 0 122 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 123 %add = add nuw nsw i32 %i.014, 1 124 %1 = trunc i64 %indvars.iv to i32 125 %offset.0 = select i1 %cmp1.not, i32 %add, i32 %1 126 %idxprom213 = zext i32 %offset.0 to i64 127 %arrayidx3 = getelementptr inbounds float, float* %Base, i64 %idxprom213 128 %2 = load float, float* %arrayidx3, align 4 129 %arrayidx5 = getelementptr inbounds float, float* %Dest, i64 %indvars.iv 130 store float %2, float* %arrayidx5, align 4 131 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 132 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 133} 134 135;;;; Cases that can be handled by a forked pointer but are not currently allowed. 136 137; CHECK-LABEL: function 'forked_ptrs_uniform_and_strided_forks': 138; CHECK-NEXT: for.body: 139; CHECK-NEXT: Report: cannot identify array bounds 140; CHECK-NEXT: Dependences: 141; CHECK-NEXT: Run-time memory checks: 142; CHECK-NEXT: Grouped accesses: 143; CHECK-EMPTY: 144; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 145; CHECK-NEXT: SCEV assumptions: 146; CHECK-EMPTY: 147; CHECK-NEXT: Expressions re-written: 148 149;;;; Derived from forked_ptrs_same_base_different_offset with a manually 150;;;; added uniform offset and a mul to provide a stride 151 152define dso_local void @forked_ptrs_uniform_and_strided_forks(float* nocapture readonly %Base, float* nocapture %Dest, i32* nocapture readonly %Preds) { 153entry: 154 br label %for.body 155 156for.cond.cleanup: ; preds = %for.body 157 ret void 158 159for.body: ; preds = %entry, %for.body 160 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 161 %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 162 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 163 %0 = load i32, i32* %arrayidx, align 4 164 %cmp1.not = icmp eq i32 %0, 0 165 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 166 %add = add nuw nsw i32 %i.014, 1 167 %1 = trunc i64 %indvars.iv to i32 168 %mul = mul i32 %1, 3 169 %offset.0 = select i1 %cmp1.not, i32 4, i32 %mul 170 %idxprom213 = sext i32 %offset.0 to i64 171 %arrayidx3 = getelementptr inbounds float, float* %Base, i64 %idxprom213 172 %2 = load float, float* %arrayidx3, align 4 173 %arrayidx5 = getelementptr inbounds float, float* %Dest, i64 %indvars.iv 174 store float %2, float* %arrayidx5, align 4 175 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 176 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 177} 178 179; CHECK-LABEL: function 'forked_ptrs_gather_and_contiguous_forks': 180; CHECK-NEXT: for.body: 181; CHECK-NEXT: Report: cannot identify array bounds 182; CHECK-NEXT: Dependences: 183; CHECK-NEXT: Run-time memory checks: 184; CHECK-NEXT: Grouped accesses: 185; CHECK-EMPTY: 186; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 187; CHECK-NEXT: SCEV assumptions: 188; CHECK-EMPTY: 189; CHECK-NEXT: Expressions re-written: 190 191;;;; Derived from forked_ptrs_same_base_different_offset with a gather 192;;;; added using Preds as an index array in addition to the per-iteration 193;;;; condition. 194 195define dso_local void @forked_ptrs_gather_and_contiguous_forks(float* nocapture readonly %Base1, float* nocapture readonly %Base2, float* nocapture %Dest, i32* nocapture readonly %Preds) { 196entry: 197 br label %for.body 198 199for.cond.cleanup: ; preds = %for.body 200 ret void 201 202for.body: ; preds = %entry, %for.body 203 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 204 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 205 %0 = load i32, i32* %arrayidx, align 4 206 %cmp1.not = icmp eq i32 %0, 0 207 %arrayidx9 = getelementptr inbounds float, float* %Base2, i64 %indvars.iv 208 %idxprom4 = sext i32 %0 to i64 209 %arrayidx5 = getelementptr inbounds float, float* %Base1, i64 %idxprom4 210 %.sink.in = select i1 %cmp1.not, float* %arrayidx9, float* %arrayidx5 211 %.sink = load float, float* %.sink.in, align 4 212 %1 = getelementptr inbounds float, float* %Dest, i64 %indvars.iv 213 store float %.sink, float* %1, align 4 214 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 215 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 216 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 217} 218