134de63c3SArthur Eubanks; RUN: opt -disable-output -passes='print-access-info' %s 2>&1 | FileCheck %s 2db8fcb2cSGraham Hunter; RUN: opt -disable-output -passes='print-access-info' -max-forked-scev-depth=2 %s 2>&1 | FileCheck -check-prefix=RECURSE %s 3dee810e1SGraham Hunter 4dee810e1SGraham Huntertarget datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 5dee810e1SGraham Hunter 63c148360SFlorian Hahn; CHECK-LABEL: function 'forked_ptrs_simple': 73c148360SFlorian Hahn; CHECK-NEXT: loop: 8e9cced27SFlorian Hahn; CHECK-NEXT: Memory dependences are safe with run-time checks 93c148360SFlorian Hahn; CHECK-NEXT: Dependences: 103c148360SFlorian Hahn; CHECK-NEXT: Run-time memory checks: 11e9cced27SFlorian Hahn; CHECK-NEXT: Check 0: 12e9cced27SFlorian Hahn; CHECK-NEXT: Comparing group ([[G1:.+]]): 13a19cf47dSGraham Hunter; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 14a19cf47dSGraham Hunter; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 15e9cced27SFlorian Hahn; CHECK-NEXT: Against group ([[G2:.+]]): 16a19cf47dSGraham Hunter; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 17e9cced27SFlorian Hahn; CHECK-NEXT: Check 1: 18e9cced27SFlorian Hahn; CHECK-NEXT: Comparing group ([[G1]]): 19a19cf47dSGraham Hunter; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 20a19cf47dSGraham Hunter; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 21e9cced27SFlorian Hahn; CHECK-NEXT: Against group ([[G3:.+]]): 22a19cf47dSGraham Hunter; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 233c148360SFlorian Hahn; CHECK-NEXT: Grouped accesses: 24e9cced27SFlorian Hahn; CHECK-NEXT: Group [[G1]] 25e9cced27SFlorian Hahn; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) 26e9cced27SFlorian Hahn; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%loop> 27e9cced27SFlorian Hahn; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%loop> 28e9cced27SFlorian Hahn; CHECK-NEXT: Group [[G2]]: 29e9cced27SFlorian Hahn; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1)) 30e9cced27SFlorian Hahn; CHECK-NEXT: Member: {%Base1,+,4}<nw><%loop> 31e9cced27SFlorian Hahn; CHECK-NEXT: Group [[G3]]: 32e9cced27SFlorian Hahn; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2)) 33e9cced27SFlorian Hahn; CHECK-NEXT: Member: {%Base2,+,4}<nw><%loop> 343c148360SFlorian Hahn; CHECK-EMPTY: 353c148360SFlorian Hahn; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 363c148360SFlorian Hahn; CHECK-NEXT: SCEV assumptions: 373c148360SFlorian Hahn; CHECK-EMPTY: 383c148360SFlorian Hahn; CHECK-NEXT: Expressions re-written: 393c148360SFlorian Hahn 40a19cf47dSGraham Hunterdefine void @forked_ptrs_simple(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr %Dest) { 413c148360SFlorian Hahnentry: 423c148360SFlorian Hahn br label %loop 433c148360SFlorian Hahn 443c148360SFlorian Hahnloop: 453c148360SFlorian Hahn %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 46a19cf47dSGraham Hunter %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 47a19cf47dSGraham Hunter %l.Dest = load float, ptr %gep.Dest 483c148360SFlorian Hahn %cmp = fcmp une float %l.Dest, 0.0 49a19cf47dSGraham Hunter %gep.1 = getelementptr inbounds float, ptr %Base1, i64 %iv 50a19cf47dSGraham Hunter %gep.2 = getelementptr inbounds float, ptr %Base2, i64 %iv 51a19cf47dSGraham Hunter %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 52a19cf47dSGraham Hunter %sink = load float, ptr %select, align 4 53a19cf47dSGraham Hunter store float %sink, ptr %gep.Dest, align 4 543c148360SFlorian Hahn %iv.next = add nuw nsw i64 %iv, 1 553c148360SFlorian Hahn %exitcond.not = icmp eq i64 %iv.next, 100 563c148360SFlorian Hahn br i1 %exitcond.not, label %exit, label %loop 573c148360SFlorian Hahn 583c148360SFlorian Hahnexit: 593c148360SFlorian Hahn ret void 603c148360SFlorian Hahn} 613c148360SFlorian Hahn 62dee810e1SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset': 63dee810e1SGraham Hunter; CHECK-NEXT: for.body: 64db8fcb2cSGraham Hunter; CHECK-NEXT: Memory dependences are safe with run-time checks 65dee810e1SGraham Hunter; CHECK-NEXT: Dependences: 66dee810e1SGraham Hunter; CHECK-NEXT: Run-time memory checks: 67db8fcb2cSGraham Hunter; CHECK-NEXT: Check 0: 68db8fcb2cSGraham Hunter; CHECK-NEXT: Comparing group ([[G1:.+]]): 69db8fcb2cSGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 70db8fcb2cSGraham Hunter; CHECK-NEXT: Against group ([[G2:.+]]): 71db8fcb2cSGraham Hunter; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 72db8fcb2cSGraham Hunter; CHECK-NEXT: Check 1: 73db8fcb2cSGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 74db8fcb2cSGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 75db8fcb2cSGraham Hunter; CHECK-NEXT: Against group ([[G3:.+]]): 76db8fcb2cSGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 77db8fcb2cSGraham Hunter; CHECK-NEXT: Check 2: 78db8fcb2cSGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 79db8fcb2cSGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 80db8fcb2cSGraham Hunter; CHECK-NEXT: Against group ([[G4:.+]]): 81db8fcb2cSGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 82dee810e1SGraham Hunter; CHECK-NEXT: Grouped accesses: 83db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G1]]: 84db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) 85db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%for.body> 86db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G2]]: 87db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 88db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 89db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G3]]: 90db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2)) 91db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Base2,+,4}<nw><%for.body> 92db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G4]]: 93db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1)) 94db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Base1,+,4}<nw><%for.body> 95dee810e1SGraham Hunter; CHECK-EMPTY: 96dee810e1SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 97dee810e1SGraham Hunter; CHECK-NEXT: SCEV assumptions: 98dee810e1SGraham Hunter; CHECK-EMPTY: 99dee810e1SGraham Hunter; CHECK-NEXT: Expressions re-written: 100dee810e1SGraham Hunter 101db8fcb2cSGraham Hunter;; We have a limit on the recursion depth for finding a loop invariant or 102db8fcb2cSGraham Hunter;; addrec term; confirm we won't exceed that depth by forcing a lower 103db8fcb2cSGraham Hunter;; limit via -max-forked-scev-depth=2 104db8fcb2cSGraham Hunter; RECURSE-LABEL: Loop access info in function 'forked_ptrs_same_base_different_offset': 105db8fcb2cSGraham Hunter; RECURSE-NEXT: for.body: 106db8fcb2cSGraham Hunter; RECURSE-NEXT: Report: cannot identify array bounds 107db8fcb2cSGraham Hunter; RECURSE-NEXT: Dependences: 108db8fcb2cSGraham Hunter; RECURSE-NEXT: Run-time memory checks: 109db8fcb2cSGraham Hunter; RECURSE-NEXT: Grouped accesses: 110db8fcb2cSGraham Hunter; RECURSE-EMPTY: 111db8fcb2cSGraham Hunter; RECURSE-NEXT: Non vectorizable stores to invariant address were not found in loop. 112db8fcb2cSGraham Hunter; RECURSE-NEXT: SCEV assumptions: 113db8fcb2cSGraham Hunter; RECURSE-EMPTY: 114db8fcb2cSGraham Hunter; RECURSE-NEXT: Expressions re-written: 115db8fcb2cSGraham Hunter 116dee810e1SGraham Hunter;;;; Derived from the following C code 117dee810e1SGraham Hunter;; void forked_ptrs_different_base_same_offset(float *A, float *B, float *C, int *D) { 118dee810e1SGraham Hunter;; for (int i=0; i<100; i++) { 119dee810e1SGraham Hunter;; if (D[i] != 0) { 120dee810e1SGraham Hunter;; C[i] = A[i]; 121dee810e1SGraham Hunter;; } else { 122dee810e1SGraham Hunter;; C[i] = B[i]; 123dee810e1SGraham Hunter;; } 124dee810e1SGraham Hunter;; } 125dee810e1SGraham Hunter;; } 126dee810e1SGraham Hunter 127a19cf47dSGraham Hunterdefine dso_local void @forked_ptrs_different_base_same_offset(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 128dee810e1SGraham Hunterentry: 129dee810e1SGraham Hunter br label %for.body 130dee810e1SGraham Hunter 131dee810e1SGraham Hunterfor.cond.cleanup: 132dee810e1SGraham Hunter ret void 133dee810e1SGraham Hunter 134dee810e1SGraham Hunterfor.body: 135dee810e1SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 136a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 137a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 138dee810e1SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 139a19cf47dSGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 140a19cf47dSGraham Hunter %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 141a19cf47dSGraham Hunter %.sink = load float, ptr %.sink.in, align 4 142a19cf47dSGraham Hunter %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 143a19cf47dSGraham Hunter store float %.sink, ptr %1, align 4 144a19cf47dSGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 145a19cf47dSGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 146a19cf47dSGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 147a19cf47dSGraham Hunter} 148a19cf47dSGraham Hunter 149*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset_64b': 150*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 151*0a715c11SGraham Hunter; CHECK-NEXT: Memory dependences are safe with run-time checks 152*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 153*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 154*0a715c11SGraham Hunter; CHECK-NEXT: Check 0: 155*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1:.+]]): 156*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv 157*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G2:.+]]): 158*0a715c11SGraham Hunter; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 159*0a715c11SGraham Hunter; CHECK-NEXT: Check 1: 160*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 161*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv 162*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G3:.+]]): 163*0a715c11SGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv 164*0a715c11SGraham Hunter; CHECK-NEXT: Check 2: 165*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 166*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv 167*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G4:.+]]): 168*0a715c11SGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv 169*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 170*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G1]]: 171*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Dest High: (800 + %Dest)) 172*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Dest,+,8}<nuw><%for.body> 173*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G2]]: 174*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 175*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 176*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G3]]: 177*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Base2 High: (800 + %Base2)) 178*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Base2,+,8}<nw><%for.body> 179*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G4]]: 180*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Base1 High: (800 + %Base1)) 181*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Base1,+,8}<nw><%for.body> 182*0a715c11SGraham Hunter; CHECK-EMPTY: 183*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 184*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 185*0a715c11SGraham Hunter; CHECK-EMPTY: 186*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 187*0a715c11SGraham Hunter 188*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_different_base_same_offset_64b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 189*0a715c11SGraham Hunterentry: 190*0a715c11SGraham Hunter br label %for.body 191*0a715c11SGraham Hunter 192*0a715c11SGraham Hunterfor.cond.cleanup: 193*0a715c11SGraham Hunter ret void 194*0a715c11SGraham Hunter 195*0a715c11SGraham Hunterfor.body: 196*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 197*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 198*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 199*0a715c11SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 200*0a715c11SGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 201*0a715c11SGraham Hunter %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv 202*0a715c11SGraham Hunter %.sink = load double, ptr %.sink.in, align 8 203*0a715c11SGraham Hunter %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv 204*0a715c11SGraham Hunter store double %.sink, ptr %1, align 8 205*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 206*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 207*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 208*0a715c11SGraham Hunter} 209*0a715c11SGraham Hunter 210*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset_23b': 211*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 212*0a715c11SGraham Hunter; CHECK-NEXT: Memory dependences are safe with run-time checks 213*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 214*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 215*0a715c11SGraham Hunter; CHECK-NEXT: Check 0: 216*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1:.+]]): 217*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv 218*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G2:.+]]): 219*0a715c11SGraham Hunter; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 220*0a715c11SGraham Hunter; CHECK-NEXT: Check 1: 221*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 222*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv 223*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G3:.+]]): 224*0a715c11SGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv 225*0a715c11SGraham Hunter; CHECK-NEXT: Check 2: 226*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 227*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv 228*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G4:.+]]): 229*0a715c11SGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv 230*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 231*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G1]]: 232*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Dest High: (399 + %Dest)) 233*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%for.body> 234*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G2]]: 235*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 236*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 237*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G3]]: 238*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Base2 High: (399 + %Base2)) 239*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Base2,+,4}<nw><%for.body> 240*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G4]]: 241*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Base1 High: (399 + %Base1)) 242*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Base1,+,4}<nw><%for.body> 243*0a715c11SGraham Hunter; CHECK-EMPTY: 244*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 245*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 246*0a715c11SGraham Hunter; CHECK-EMPTY: 247*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 248*0a715c11SGraham Hunter 249*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_different_base_same_offset_23b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 250*0a715c11SGraham Hunterentry: 251*0a715c11SGraham Hunter br label %for.body 252*0a715c11SGraham Hunter 253*0a715c11SGraham Hunterfor.cond.cleanup: 254*0a715c11SGraham Hunter ret void 255*0a715c11SGraham Hunter 256*0a715c11SGraham Hunterfor.body: 257*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 258*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 259*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 260*0a715c11SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 261*0a715c11SGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 262*0a715c11SGraham Hunter %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv 263*0a715c11SGraham Hunter %.sink = load i23, ptr %.sink.in 264*0a715c11SGraham Hunter %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv 265*0a715c11SGraham Hunter store i23 %.sink, ptr %1 266*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 267*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 268*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 269*0a715c11SGraham Hunter} 270*0a715c11SGraham Hunter 271*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset_6b': 272*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 273*0a715c11SGraham Hunter; CHECK-NEXT: Memory dependences are safe with run-time checks 274*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 275*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 276*0a715c11SGraham Hunter; CHECK-NEXT: Check 0: 277*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1:.+]]): 278*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv 279*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G2:.+]]): 280*0a715c11SGraham Hunter; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 281*0a715c11SGraham Hunter; CHECK-NEXT: Check 1: 282*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 283*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv 284*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G3:.+]]): 285*0a715c11SGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv 286*0a715c11SGraham Hunter; CHECK-NEXT: Check 2: 287*0a715c11SGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 288*0a715c11SGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv 289*0a715c11SGraham Hunter; CHECK-NEXT: Against group ([[G4:.+]]): 290*0a715c11SGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv 291*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 292*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G1]]: 293*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Dest High: (100 + %Dest)) 294*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Dest,+,1}<nuw><%for.body> 295*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G2]]: 296*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 297*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 298*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G3]]: 299*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Base2 High: (100 + %Base2)) 300*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Base2,+,1}<nw><%for.body> 301*0a715c11SGraham Hunter; CHECK-NEXT: Group [[G4]]: 302*0a715c11SGraham Hunter; CHECK-NEXT: (Low: %Base1 High: (100 + %Base1)) 303*0a715c11SGraham Hunter; CHECK-NEXT: Member: {%Base1,+,1}<nw><%for.body> 304*0a715c11SGraham Hunter; CHECK-EMPTY: 305*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 306*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 307*0a715c11SGraham Hunter; CHECK-EMPTY: 308*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 309*0a715c11SGraham Hunter 310*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_different_base_same_offset_6b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 311*0a715c11SGraham Hunterentry: 312*0a715c11SGraham Hunter br label %for.body 313*0a715c11SGraham Hunter 314*0a715c11SGraham Hunterfor.cond.cleanup: 315*0a715c11SGraham Hunter ret void 316*0a715c11SGraham Hunter 317*0a715c11SGraham Hunterfor.body: 318*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 319*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 320*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 321*0a715c11SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 322*0a715c11SGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 323*0a715c11SGraham Hunter %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv 324*0a715c11SGraham Hunter %.sink = load i6, ptr %.sink.in 325*0a715c11SGraham Hunter %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv 326*0a715c11SGraham Hunter store i6 %.sink, ptr %1 327*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 328*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 329*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 330*0a715c11SGraham Hunter} 331*0a715c11SGraham Hunter 332a19cf47dSGraham Hunter; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset_possible_poison': 333a19cf47dSGraham Hunter; CHECK-NEXT: for.body: 334db8fcb2cSGraham Hunter; CHECK-NEXT: Memory dependences are safe with run-time checks 335a19cf47dSGraham Hunter; CHECK-NEXT: Dependences: 336a19cf47dSGraham Hunter; CHECK-NEXT: Run-time memory checks: 337db8fcb2cSGraham Hunter; CHECK-NEXT: Check 0: 338db8fcb2cSGraham Hunter; CHECK-NEXT: Comparing group ([[G1:.+]]): 339db8fcb2cSGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 340db8fcb2cSGraham Hunter; CHECK-NEXT: Against group ([[G2:.+]]): 341db8fcb2cSGraham Hunter; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 342db8fcb2cSGraham Hunter; CHECK-NEXT: Check 1: 343db8fcb2cSGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 344db8fcb2cSGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 345db8fcb2cSGraham Hunter; CHECK-NEXT: Against group ([[G3:.+]]): 346db8fcb2cSGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 347db8fcb2cSGraham Hunter; CHECK-NEXT: Check 2: 348db8fcb2cSGraham Hunter; CHECK-NEXT: Comparing group ([[G1]]): 349db8fcb2cSGraham Hunter; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 350db8fcb2cSGraham Hunter; CHECK-NEXT: Against group ([[G4:.+]]): 351db8fcb2cSGraham Hunter; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 352a19cf47dSGraham Hunter; CHECK-NEXT: Grouped accesses: 353db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G1]]: 354db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) 355db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Dest,+,4}<nw><%for.body> 356db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G2]]: 357db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 358db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 359db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G3]]: 360db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2)) 361db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Base2,+,4}<nw><%for.body> 362db8fcb2cSGraham Hunter; CHECK-NEXT: Group [[G4]]: 363db8fcb2cSGraham Hunter; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1)) 364db8fcb2cSGraham Hunter; CHECK-NEXT: Member: {%Base1,+,4}<nw><%for.body> 365a19cf47dSGraham Hunter; CHECK-EMPTY: 366a19cf47dSGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 367a19cf47dSGraham Hunter; CHECK-NEXT: SCEV assumptions: 368a19cf47dSGraham Hunter; CHECK-EMPTY: 369a19cf47dSGraham Hunter; CHECK-NEXT: Expressions re-written: 370a19cf47dSGraham Hunter 371a19cf47dSGraham Hunterdefine dso_local void @forked_ptrs_different_base_same_offset_possible_poison(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds, i1 %c) { 372a19cf47dSGraham Hunterentry: 373a19cf47dSGraham Hunter br label %for.body 374a19cf47dSGraham Hunter 375a19cf47dSGraham Hunterfor.cond.cleanup: 376a19cf47dSGraham Hunter ret void 377a19cf47dSGraham Hunter 378a19cf47dSGraham Hunterfor.body: 379a19cf47dSGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %latch ] 380a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 381a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 382a19cf47dSGraham Hunter %cmp1.not = icmp eq i32 %0, 0 383a19cf47dSGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 384a19cf47dSGraham Hunter %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 385a19cf47dSGraham Hunter %.sink = load float, ptr %.sink.in, align 4 386a19cf47dSGraham Hunter %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 387a19cf47dSGraham Hunter br i1 %c, label %then, label %latch 388a19cf47dSGraham Hunter 389a19cf47dSGraham Hunterthen: 390a19cf47dSGraham Hunter store float %.sink, ptr %1, align 4 391a19cf47dSGraham Hunter br label %latch 392a19cf47dSGraham Hunter 393a19cf47dSGraham Hunterlatch: 394dee810e1SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 395dee810e1SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 396dee810e1SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 397dee810e1SGraham Hunter} 398dee810e1SGraham Hunter 399dee810e1SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_same_base_different_offset': 400dee810e1SGraham Hunter; CHECK-NEXT: for.body: 401dee810e1SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 402dee810e1SGraham Hunter; CHECK-NEXT: Dependences: 403dee810e1SGraham Hunter; CHECK-NEXT: Run-time memory checks: 404dee810e1SGraham Hunter; CHECK-NEXT: Grouped accesses: 405dee810e1SGraham Hunter; CHECK-EMPTY: 406dee810e1SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 407dee810e1SGraham Hunter; CHECK-NEXT: SCEV assumptions: 408dee810e1SGraham Hunter; CHECK-EMPTY: 409dee810e1SGraham Hunter; CHECK-NEXT: Expressions re-written: 410dee810e1SGraham Hunter 411dee810e1SGraham Hunter;;;; Derived from the following C code 412dee810e1SGraham Hunter;; void forked_ptrs_same_base_different_offset(float *A, float *B, int *C) { 413dee810e1SGraham Hunter;; int offset; 414dee810e1SGraham Hunter;; for (int i = 0; i < 100; i++) { 415dee810e1SGraham Hunter;; if (C[i] != 0) 416dee810e1SGraham Hunter;; offset = i; 417dee810e1SGraham Hunter;; else 418dee810e1SGraham Hunter;; offset = i+1; 419dee810e1SGraham Hunter;; B[i] = A[offset]; 420dee810e1SGraham Hunter;; } 421dee810e1SGraham Hunter;; } 422dee810e1SGraham Hunter 423a19cf47dSGraham Hunterdefine dso_local void @forked_ptrs_same_base_different_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 424dee810e1SGraham Hunterentry: 425dee810e1SGraham Hunter br label %for.body 426dee810e1SGraham Hunter 427dee810e1SGraham Hunterfor.cond.cleanup: ; preds = %for.body 428dee810e1SGraham Hunter ret void 429dee810e1SGraham Hunter 430dee810e1SGraham Hunterfor.body: ; preds = %entry, %for.body 431dee810e1SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 432dee810e1SGraham Hunter %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 433a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 434a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 435dee810e1SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 436dee810e1SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 437dee810e1SGraham Hunter %add = add nuw nsw i32 %i.014, 1 438dee810e1SGraham Hunter %1 = trunc i64 %indvars.iv to i32 439dee810e1SGraham Hunter %offset.0 = select i1 %cmp1.not, i32 %add, i32 %1 440dee810e1SGraham Hunter %idxprom213 = zext i32 %offset.0 to i64 441a19cf47dSGraham Hunter %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %idxprom213 442a19cf47dSGraham Hunter %2 = load float, ptr %arrayidx3, align 4 443a19cf47dSGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 444a19cf47dSGraham Hunter store float %2, ptr %arrayidx5, align 4 445dee810e1SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 446dee810e1SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 447dee810e1SGraham Hunter} 448dee810e1SGraham Hunter 449*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_add_to_offset' 450*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 451*0a715c11SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 452*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 453*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 454*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 455*0a715c11SGraham Hunter; CHECK-EMPTY: 456*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 457*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 458*0a715c11SGraham Hunter; CHECK-EMPTY: 459*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 460*0a715c11SGraham Hunter 461*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_add_to_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %extra_offset) { 462*0a715c11SGraham Hunterentry: 463*0a715c11SGraham Hunter br label %for.body 464*0a715c11SGraham Hunter 465*0a715c11SGraham Hunterfor.cond.cleanup: ; preds = %for.body 466*0a715c11SGraham Hunter ret void 467*0a715c11SGraham Hunter 468*0a715c11SGraham Hunterfor.body: ; preds = %entry, %for.body 469*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 470*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 471*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 472*0a715c11SGraham Hunter %cmp.not = icmp eq i32 %0, 0 473*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 474*0a715c11SGraham Hunter %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv 475*0a715c11SGraham Hunter %offset = add nuw nsw i64 %sel, %extra_offset 476*0a715c11SGraham Hunter %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset 477*0a715c11SGraham Hunter %1 = load float, ptr %arrayidx3, align 4 478*0a715c11SGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 479*0a715c11SGraham Hunter store float %1, ptr %arrayidx5, align 4 480*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 481*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 482*0a715c11SGraham Hunter} 483*0a715c11SGraham Hunter 484*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_sub_from_offset' 485*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 486*0a715c11SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 487*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 488*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 489*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 490*0a715c11SGraham Hunter; CHECK-EMPTY: 491*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 492*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 493*0a715c11SGraham Hunter; CHECK-EMPTY: 494*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 495*0a715c11SGraham Hunter 496*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_sub_from_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %extra_offset) { 497*0a715c11SGraham Hunterentry: 498*0a715c11SGraham Hunter br label %for.body 499*0a715c11SGraham Hunter 500*0a715c11SGraham Hunterfor.cond.cleanup: ; preds = %for.body 501*0a715c11SGraham Hunter ret void 502*0a715c11SGraham Hunter 503*0a715c11SGraham Hunterfor.body: ; preds = %entry, %for.body 504*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 505*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 506*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 507*0a715c11SGraham Hunter %cmp.not = icmp eq i32 %0, 0 508*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 509*0a715c11SGraham Hunter %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv 510*0a715c11SGraham Hunter %offset = sub nuw nsw i64 %sel, %extra_offset 511*0a715c11SGraham Hunter %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset 512*0a715c11SGraham Hunter %1 = load float, ptr %arrayidx3, align 4 513*0a715c11SGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 514*0a715c11SGraham Hunter store float %1, ptr %arrayidx5, align 4 515*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 516*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 517*0a715c11SGraham Hunter} 518*0a715c11SGraham Hunter 519*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_add_sub_offset' 520*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 521*0a715c11SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 522*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 523*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 524*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 525*0a715c11SGraham Hunter; CHECK-EMPTY: 526*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 527*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 528*0a715c11SGraham Hunter; CHECK-EMPTY: 529*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 530*0a715c11SGraham Hunter 531*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_add_sub_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %to_add, i64 %to_sub) { 532*0a715c11SGraham Hunterentry: 533*0a715c11SGraham Hunter br label %for.body 534*0a715c11SGraham Hunter 535*0a715c11SGraham Hunterfor.cond.cleanup: ; preds = %for.body 536*0a715c11SGraham Hunter ret void 537*0a715c11SGraham Hunter 538*0a715c11SGraham Hunterfor.body: ; preds = %entry, %for.body 539*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 540*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 541*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 542*0a715c11SGraham Hunter %cmp.not = icmp eq i32 %0, 0 543*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 544*0a715c11SGraham Hunter %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv 545*0a715c11SGraham Hunter %add = add nuw nsw i64 %sel, %to_add 546*0a715c11SGraham Hunter %offset = sub nuw nsw i64 %add, %to_sub 547*0a715c11SGraham Hunter %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset 548*0a715c11SGraham Hunter %1 = load float, ptr %arrayidx3, align 4 549*0a715c11SGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 550*0a715c11SGraham Hunter store float %1, ptr %arrayidx5, align 4 551*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 552*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 553*0a715c11SGraham Hunter} 554*0a715c11SGraham Hunter 555dee810e1SGraham Hunter;;;; Cases that can be handled by a forked pointer but are not currently allowed. 556dee810e1SGraham Hunter 557*0a715c11SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_mul_by_offset' 558*0a715c11SGraham Hunter; CHECK-NEXT: for.body: 559*0a715c11SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 560*0a715c11SGraham Hunter; CHECK-NEXT: Dependences: 561*0a715c11SGraham Hunter; CHECK-NEXT: Run-time memory checks: 562*0a715c11SGraham Hunter; CHECK-NEXT: Grouped accesses: 563*0a715c11SGraham Hunter; CHECK-EMPTY: 564*0a715c11SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 565*0a715c11SGraham Hunter; CHECK-NEXT: SCEV assumptions: 566*0a715c11SGraham Hunter; CHECK-EMPTY: 567*0a715c11SGraham Hunter; CHECK-NEXT: Expressions re-written: 568*0a715c11SGraham Hunter 569*0a715c11SGraham Hunterdefine dso_local void @forked_ptrs_mul_by_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %extra_offset) { 570*0a715c11SGraham Hunterentry: 571*0a715c11SGraham Hunter br label %for.body 572*0a715c11SGraham Hunter 573*0a715c11SGraham Hunterfor.cond.cleanup: ; preds = %for.body 574*0a715c11SGraham Hunter ret void 575*0a715c11SGraham Hunter 576*0a715c11SGraham Hunterfor.body: ; preds = %entry, %for.body 577*0a715c11SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 578*0a715c11SGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 579*0a715c11SGraham Hunter %0 = load i32, ptr %arrayidx, align 4 580*0a715c11SGraham Hunter %cmp.not = icmp eq i32 %0, 0 581*0a715c11SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 582*0a715c11SGraham Hunter %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv 583*0a715c11SGraham Hunter %offset = mul nuw nsw i64 %sel, %extra_offset 584*0a715c11SGraham Hunter %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset 585*0a715c11SGraham Hunter %1 = load float, ptr %arrayidx3, align 4 586*0a715c11SGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 587*0a715c11SGraham Hunter store float %1, ptr %arrayidx5, align 4 588*0a715c11SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 589*0a715c11SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 590*0a715c11SGraham Hunter} 591*0a715c11SGraham Hunter 592dee810e1SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_uniform_and_strided_forks': 593dee810e1SGraham Hunter; CHECK-NEXT: for.body: 594dee810e1SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 595dee810e1SGraham Hunter; CHECK-NEXT: Dependences: 596dee810e1SGraham Hunter; CHECK-NEXT: Run-time memory checks: 597dee810e1SGraham Hunter; CHECK-NEXT: Grouped accesses: 598dee810e1SGraham Hunter; CHECK-EMPTY: 599dee810e1SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 600dee810e1SGraham Hunter; CHECK-NEXT: SCEV assumptions: 601dee810e1SGraham Hunter; CHECK-EMPTY: 602dee810e1SGraham Hunter; CHECK-NEXT: Expressions re-written: 603dee810e1SGraham Hunter 604dee810e1SGraham Hunter;;;; Derived from forked_ptrs_same_base_different_offset with a manually 605dee810e1SGraham Hunter;;;; added uniform offset and a mul to provide a stride 606dee810e1SGraham Hunter 607dee810e1SGraham Hunterdefine dso_local void @forked_ptrs_uniform_and_strided_forks(float* nocapture readonly %Base, float* nocapture %Dest, i32* nocapture readonly %Preds) { 608dee810e1SGraham Hunterentry: 609dee810e1SGraham Hunter br label %for.body 610dee810e1SGraham Hunter 611dee810e1SGraham Hunterfor.cond.cleanup: ; preds = %for.body 612dee810e1SGraham Hunter ret void 613dee810e1SGraham Hunter 614dee810e1SGraham Hunterfor.body: ; preds = %entry, %for.body 615dee810e1SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 616dee810e1SGraham Hunter %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 617a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 618a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 619dee810e1SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 620dee810e1SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 621dee810e1SGraham Hunter %add = add nuw nsw i32 %i.014, 1 622dee810e1SGraham Hunter %1 = trunc i64 %indvars.iv to i32 623dee810e1SGraham Hunter %mul = mul i32 %1, 3 624dee810e1SGraham Hunter %offset.0 = select i1 %cmp1.not, i32 4, i32 %mul 625dee810e1SGraham Hunter %idxprom213 = sext i32 %offset.0 to i64 626a19cf47dSGraham Hunter %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %idxprom213 627a19cf47dSGraham Hunter %2 = load float, ptr %arrayidx3, align 4 628a19cf47dSGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 629a19cf47dSGraham Hunter store float %2, ptr %arrayidx5, align 4 630dee810e1SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 631dee810e1SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 632dee810e1SGraham Hunter} 633dee810e1SGraham Hunter 634dee810e1SGraham Hunter; CHECK-LABEL: function 'forked_ptrs_gather_and_contiguous_forks': 635dee810e1SGraham Hunter; CHECK-NEXT: for.body: 636dee810e1SGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 637dee810e1SGraham Hunter; CHECK-NEXT: Dependences: 638dee810e1SGraham Hunter; CHECK-NEXT: Run-time memory checks: 639dee810e1SGraham Hunter; CHECK-NEXT: Grouped accesses: 640dee810e1SGraham Hunter; CHECK-EMPTY: 641dee810e1SGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 642dee810e1SGraham Hunter; CHECK-NEXT: SCEV assumptions: 643dee810e1SGraham Hunter; CHECK-EMPTY: 644dee810e1SGraham Hunter; CHECK-NEXT: Expressions re-written: 645dee810e1SGraham Hunter 646dee810e1SGraham Hunter;;;; Derived from forked_ptrs_same_base_different_offset with a gather 647dee810e1SGraham Hunter;;;; added using Preds as an index array in addition to the per-iteration 648dee810e1SGraham Hunter;;;; condition. 649dee810e1SGraham Hunter 650a19cf47dSGraham Hunterdefine dso_local void @forked_ptrs_gather_and_contiguous_forks(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 651dee810e1SGraham Hunterentry: 652dee810e1SGraham Hunter br label %for.body 653dee810e1SGraham Hunter 654dee810e1SGraham Hunterfor.cond.cleanup: ; preds = %for.body 655dee810e1SGraham Hunter ret void 656dee810e1SGraham Hunter 657dee810e1SGraham Hunterfor.body: ; preds = %entry, %for.body 658dee810e1SGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 659a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 660a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 661dee810e1SGraham Hunter %cmp1.not = icmp eq i32 %0, 0 662a19cf47dSGraham Hunter %arrayidx9 = getelementptr inbounds float, ptr %Base2, i64 %indvars.iv 663dee810e1SGraham Hunter %idxprom4 = sext i32 %0 to i64 664a19cf47dSGraham Hunter %arrayidx5 = getelementptr inbounds float, ptr %Base1, i64 %idxprom4 665a19cf47dSGraham Hunter %.sink.in = select i1 %cmp1.not, ptr %arrayidx9, ptr %arrayidx5 666a19cf47dSGraham Hunter %.sink = load float, ptr %.sink.in, align 4 667a19cf47dSGraham Hunter %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 668a19cf47dSGraham Hunter store float %.sink, ptr %1, align 4 669dee810e1SGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 670dee810e1SGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 671dee810e1SGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 672dee810e1SGraham Hunter} 673a19cf47dSGraham Hunter 674a19cf47dSGraham Hunter;; We don't currently handle a fork in both the base and the offset of a 675a19cf47dSGraham Hunter;; GEP instruction. 676a19cf47dSGraham Hunter 677a19cf47dSGraham Hunter; CHECK-LABEL: Loop access info in function 'forked_ptrs_two_forks_gep': 678a19cf47dSGraham Hunter; CHECK-NEXT: for.body: 679a19cf47dSGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 680a19cf47dSGraham Hunter; CHECK-NEXT: Dependences: 681a19cf47dSGraham Hunter; CHECK-NEXT: Run-time memory checks: 682a19cf47dSGraham Hunter; CHECK-NEXT: Grouped accesses: 683a19cf47dSGraham Hunter; CHECK-EMPTY: 684a19cf47dSGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 685a19cf47dSGraham Hunter; CHECK-NEXT: SCEV assumptions: 686a19cf47dSGraham Hunter; CHECK-EMPTY: 687a19cf47dSGraham Hunter; CHECK-NEXT: Expressions re-written: 688a19cf47dSGraham Hunter 689a19cf47dSGraham Hunterdefine dso_local void @forked_ptrs_two_forks_gep(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 690a19cf47dSGraham Hunterentry: 691a19cf47dSGraham Hunter br label %for.body 692a19cf47dSGraham Hunter 693a19cf47dSGraham Hunterfor.cond.cleanup: 694a19cf47dSGraham Hunter ret void 695a19cf47dSGraham Hunter 696a19cf47dSGraham Hunterfor.body: 697a19cf47dSGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 698a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 699a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 700a19cf47dSGraham Hunter %cmp1.not = icmp eq i32 %0, 0 701a19cf47dSGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 702a19cf47dSGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 703a19cf47dSGraham Hunter %offset = select i1 %cmp1.not, i64 %indvars.iv.next, i64 %indvars.iv 704a19cf47dSGraham Hunter %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %offset 705a19cf47dSGraham Hunter %.sink = load float, ptr %.sink.in, align 4 706a19cf47dSGraham Hunter %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 707a19cf47dSGraham Hunter store float %.sink, ptr %1, align 4 708a19cf47dSGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 709a19cf47dSGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 710a19cf47dSGraham Hunter} 711a19cf47dSGraham Hunter 712a19cf47dSGraham Hunter;; We don't handle forks as children of a select 713a19cf47dSGraham Hunter 714a19cf47dSGraham Hunter; CHECK-LABEL: Loop access info in function 'forked_ptrs_two_select': 715a19cf47dSGraham Hunter; CHECK-NEXT: loop: 716a19cf47dSGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 717a19cf47dSGraham Hunter; CHECK-NEXT: Dependences: 718a19cf47dSGraham Hunter; CHECK-NEXT: Run-time memory checks: 719a19cf47dSGraham Hunter; CHECK-NEXT: Grouped accesses: 720a19cf47dSGraham Hunter; CHECK-EMPTY: 721a19cf47dSGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 722a19cf47dSGraham Hunter; CHECK-NEXT: SCEV assumptions: 723a19cf47dSGraham Hunter; CHECK-EMPTY: 724a19cf47dSGraham Hunter; CHECK-NEXT: Expressions re-written: 725a19cf47dSGraham Hunter 726a19cf47dSGraham Hunterdefine void @forked_ptrs_two_select(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture readonly %Base3, ptr %Dest) { 727a19cf47dSGraham Hunterentry: 728a19cf47dSGraham Hunter br label %loop 729a19cf47dSGraham Hunter 730a19cf47dSGraham Hunterloop: 731a19cf47dSGraham Hunter %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 732a19cf47dSGraham Hunter %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 733a19cf47dSGraham Hunter %l.Dest = load float, ptr %gep.Dest 734a19cf47dSGraham Hunter %cmp = fcmp une float %l.Dest, 0.0 735a19cf47dSGraham Hunter %cmp1 = fcmp une float %l.Dest, 1.0 736a19cf47dSGraham Hunter %gep.1 = getelementptr inbounds float, ptr %Base1, i64 %iv 737a19cf47dSGraham Hunter %gep.2 = getelementptr inbounds float, ptr %Base2, i64 %iv 738a19cf47dSGraham Hunter %gep.3 = getelementptr inbounds float, ptr %Base3, i64 %iv 739a19cf47dSGraham Hunter %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 740a19cf47dSGraham Hunter %select1 = select i1 %cmp1, ptr %select, ptr %gep.3 741a19cf47dSGraham Hunter %sink = load float, ptr %select1, align 4 742a19cf47dSGraham Hunter store float %sink, ptr %gep.Dest, align 4 743a19cf47dSGraham Hunter %iv.next = add nuw nsw i64 %iv, 1 744a19cf47dSGraham Hunter %exitcond.not = icmp eq i64 %iv.next, 100 745a19cf47dSGraham Hunter br i1 %exitcond.not, label %exit, label %loop 746a19cf47dSGraham Hunter 747a19cf47dSGraham Hunterexit: 748a19cf47dSGraham Hunter ret void 749a19cf47dSGraham Hunter} 750a19cf47dSGraham Hunter 751a19cf47dSGraham Hunter;; We don't yet handle geps with more than 2 operands 752a19cf47dSGraham Hunter; CHECK-LABEL: Loop access info in function 'forked_ptrs_too_many_gep_ops': 753a19cf47dSGraham Hunter; CHECK-NEXT: for.body: 754a19cf47dSGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 755a19cf47dSGraham Hunter; CHECK-NEXT: Dependences: 756a19cf47dSGraham Hunter; CHECK-NEXT: Run-time memory checks: 757a19cf47dSGraham Hunter; CHECK-NEXT: Grouped accesses: 758a19cf47dSGraham Hunter; CHECK-EMPTY: 759a19cf47dSGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 760a19cf47dSGraham Hunter; CHECK-NEXT: SCEV assumptions: 761a19cf47dSGraham Hunter; CHECK-EMPTY: 762a19cf47dSGraham Hunter; CHECK-NEXT: Expressions re-written: 763a19cf47dSGraham Hunter 764a19cf47dSGraham Hunterdefine void @forked_ptrs_too_many_gep_ops(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 765a19cf47dSGraham Hunterentry: 766a19cf47dSGraham Hunter br label %for.body 767a19cf47dSGraham Hunter 768a19cf47dSGraham Hunterfor.body: 769a19cf47dSGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 770a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 771a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 772a19cf47dSGraham Hunter %cmp1.not = icmp eq i32 %0, 0 773a19cf47dSGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 774a19cf47dSGraham Hunter %.sink.in = getelementptr inbounds [1000 x float], ptr %spec.select, i64 0, i64 %indvars.iv 775a19cf47dSGraham Hunter %.sink = load float, ptr %.sink.in, align 4 776a19cf47dSGraham Hunter %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 777a19cf47dSGraham Hunter store float %.sink, ptr %1, align 4 778a19cf47dSGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 779a19cf47dSGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 780a19cf47dSGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 781a19cf47dSGraham Hunter 782a19cf47dSGraham Hunterfor.cond.cleanup: 783a19cf47dSGraham Hunter ret void 784a19cf47dSGraham Hunter} 785a19cf47dSGraham Hunter 786a19cf47dSGraham Hunter;; We don't currently handle vector GEPs 787a19cf47dSGraham Hunter; CHECK-LABEL: Loop access info in function 'forked_ptrs_vector_gep': 788a19cf47dSGraham Hunter; CHECK-NEXT: for.body: 789a19cf47dSGraham Hunter; CHECK-NEXT: Report: cannot identify array bounds 790a19cf47dSGraham Hunter; CHECK-NEXT: Dependences: 791a19cf47dSGraham Hunter; CHECK-NEXT: Run-time memory checks: 792a19cf47dSGraham Hunter; CHECK-NEXT: Grouped accesses: 793a19cf47dSGraham Hunter; CHECK-EMPTY: 794a19cf47dSGraham Hunter; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 795a19cf47dSGraham Hunter; CHECK-NEXT: SCEV assumptions: 796a19cf47dSGraham Hunter; CHECK-EMPTY: 797a19cf47dSGraham Hunter; CHECK-NEXT: Expressions re-written: 798a19cf47dSGraham Hunter 799a19cf47dSGraham Hunterdefine void @forked_ptrs_vector_gep(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 800a19cf47dSGraham Hunterentry: 801a19cf47dSGraham Hunter br label %for.body 802a19cf47dSGraham Hunter 803a19cf47dSGraham Hunterfor.body: 804a19cf47dSGraham Hunter %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 805a19cf47dSGraham Hunter %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 806a19cf47dSGraham Hunter %0 = load i32, ptr %arrayidx, align 4 807a19cf47dSGraham Hunter %cmp1.not = icmp eq i32 %0, 0 808a19cf47dSGraham Hunter %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 809a19cf47dSGraham Hunter %.sink.in = getelementptr inbounds <4 x float>, ptr %spec.select, i64 %indvars.iv 810a19cf47dSGraham Hunter %.sink = load <4 x float>, ptr %.sink.in, align 4 811a19cf47dSGraham Hunter %1 = getelementptr inbounds <4 x float>, ptr %Dest, i64 %indvars.iv 812a19cf47dSGraham Hunter store <4 x float> %.sink, ptr %1, align 4 813a19cf47dSGraham Hunter %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4 814a19cf47dSGraham Hunter %exitcond.not = icmp eq i64 %indvars.iv.next, 100 815a19cf47dSGraham Hunter br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 816a19cf47dSGraham Hunter 817a19cf47dSGraham Hunterfor.cond.cleanup: 818a19cf47dSGraham Hunter ret void 819a19cf47dSGraham Hunter} 820