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