1; RUN: opt -disable-output -passes='print-access-info' %s 2>&1 | FileCheck %s 2; RUN: opt -disable-output -passes='print-access-info' -max-forked-scev-depth=2 %s 2>&1 | FileCheck -check-prefix=RECURSE %s 3 4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 5 6; CHECK-LABEL: function 'forked_ptrs_simple': 7; CHECK-NEXT: loop: 8; CHECK-NEXT: Memory dependences are safe with run-time checks 9; CHECK-NEXT: Dependences: 10; CHECK-NEXT: Run-time memory checks: 11; CHECK-NEXT: Check 0: 12; CHECK-NEXT: Comparing group ([[G1:.+]]): 13; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 14; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 15; CHECK-NEXT: Against group ([[G2:.+]]): 16; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 17; CHECK-NEXT: Check 1: 18; CHECK-NEXT: Comparing group ([[G1]]): 19; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 20; CHECK-NEXT: %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 21; CHECK-NEXT: Against group ([[G3:.+]]): 22; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 23; CHECK-NEXT: Grouped accesses: 24; CHECK-NEXT: Group [[G1]] 25; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) 26; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%loop> 27; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%loop> 28; CHECK-NEXT: Group [[G2]]: 29; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1)) 30; CHECK-NEXT: Member: {%Base1,+,4}<nw><%loop> 31; CHECK-NEXT: Group [[G3]]: 32; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2)) 33; CHECK-NEXT: Member: {%Base2,+,4}<nw><%loop> 34; CHECK-EMPTY: 35; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 36; CHECK-NEXT: SCEV assumptions: 37; CHECK-EMPTY: 38; CHECK-NEXT: Expressions re-written: 39 40define void @forked_ptrs_simple(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr %Dest) { 41entry: 42 br label %loop 43 44loop: 45 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 46 %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 47 %l.Dest = load float, ptr %gep.Dest 48 %cmp = fcmp une float %l.Dest, 0.0 49 %gep.1 = getelementptr inbounds float, ptr %Base1, i64 %iv 50 %gep.2 = getelementptr inbounds float, ptr %Base2, i64 %iv 51 %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 52 %sink = load float, ptr %select, align 4 53 store float %sink, ptr %gep.Dest, align 4 54 %iv.next = add nuw nsw i64 %iv, 1 55 %exitcond.not = icmp eq i64 %iv.next, 100 56 br i1 %exitcond.not, label %exit, label %loop 57 58exit: 59 ret void 60} 61 62; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset': 63; CHECK-NEXT: for.body: 64; CHECK-NEXT: Memory dependences are safe with run-time checks 65; CHECK-NEXT: Dependences: 66; CHECK-NEXT: Run-time memory checks: 67; CHECK-NEXT: Check 0: 68; CHECK-NEXT: Comparing group ([[G1:.+]]): 69; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 70; CHECK-NEXT: Against group ([[G2:.+]]): 71; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 72; CHECK-NEXT: Check 1: 73; CHECK-NEXT: Comparing group ([[G1]]): 74; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 75; CHECK-NEXT: Against group ([[G3:.+]]): 76; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 77; CHECK-NEXT: Check 2: 78; CHECK-NEXT: Comparing group ([[G1]]): 79; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 80; CHECK-NEXT: Against group ([[G4:.+]]): 81; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 82; CHECK-NEXT: Grouped accesses: 83; CHECK-NEXT: Group [[G1]]: 84; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) 85; CHECK-NEXT: Member: {%Dest,+,4}<nuw><%for.body> 86; CHECK-NEXT: Group [[G2]]: 87; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 88; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 89; CHECK-NEXT: Group [[G3]]: 90; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2)) 91; CHECK-NEXT: Member: {%Base2,+,4}<nw><%for.body> 92; CHECK-NEXT: Group [[G4]]: 93; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1)) 94; CHECK-NEXT: Member: {%Base1,+,4}<nw><%for.body> 95; CHECK-EMPTY: 96; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 97; CHECK-NEXT: SCEV assumptions: 98; CHECK-EMPTY: 99; CHECK-NEXT: Expressions re-written: 100 101;; We have a limit on the recursion depth for finding a loop invariant or 102;; addrec term; confirm we won't exceed that depth by forcing a lower 103;; limit via -max-forked-scev-depth=2 104; RECURSE-LABEL: Loop access info in function 'forked_ptrs_same_base_different_offset': 105; RECURSE-NEXT: for.body: 106; RECURSE-NEXT: Report: cannot identify array bounds 107; RECURSE-NEXT: Dependences: 108; RECURSE-NEXT: Run-time memory checks: 109; RECURSE-NEXT: Grouped accesses: 110; RECURSE-EMPTY: 111; RECURSE-NEXT: Non vectorizable stores to invariant address were not found in loop. 112; RECURSE-NEXT: SCEV assumptions: 113; RECURSE-EMPTY: 114; RECURSE-NEXT: Expressions re-written: 115 116;;;; Derived from the following C code 117;; void forked_ptrs_different_base_same_offset(float *A, float *B, float *C, int *D) { 118;; for (int i=0; i<100; i++) { 119;; if (D[i] != 0) { 120;; C[i] = A[i]; 121;; } else { 122;; C[i] = B[i]; 123;; } 124;; } 125;; } 126 127define 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) { 128entry: 129 br label %for.body 130 131for.cond.cleanup: 132 ret void 133 134for.body: 135 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 136 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 137 %0 = load i32, ptr %arrayidx, align 4 138 %cmp1.not = icmp eq i32 %0, 0 139 %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 140 %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 141 %.sink = load float, ptr %.sink.in, align 4 142 %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 143 store float %.sink, ptr %1, align 4 144 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 145 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 146 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 147} 148 149; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset_possible_poison': 150; CHECK-NEXT: for.body: 151; CHECK-NEXT: Memory dependences are safe with run-time checks 152; CHECK-NEXT: Dependences: 153; CHECK-NEXT: Run-time memory checks: 154; CHECK-NEXT: Check 0: 155; CHECK-NEXT: Comparing group ([[G1:.+]]): 156; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 157; CHECK-NEXT: Against group ([[G2:.+]]): 158; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 159; CHECK-NEXT: Check 1: 160; CHECK-NEXT: Comparing group ([[G1]]): 161; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 162; CHECK-NEXT: Against group ([[G3:.+]]): 163; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 164; CHECK-NEXT: Check 2: 165; CHECK-NEXT: Comparing group ([[G1]]): 166; CHECK-NEXT: %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 167; CHECK-NEXT: Against group ([[G4:.+]]): 168; CHECK-NEXT: %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 169; CHECK-NEXT: Grouped accesses: 170; CHECK-NEXT: Group [[G1]]: 171; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) 172; CHECK-NEXT: Member: {%Dest,+,4}<nw><%for.body> 173; CHECK-NEXT: Group [[G2]]: 174; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) 175; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%for.body> 176; CHECK-NEXT: Group [[G3]]: 177; CHECK-NEXT: (Low: %Base2 High: (400 + %Base2)) 178; CHECK-NEXT: Member: {%Base2,+,4}<nw><%for.body> 179; CHECK-NEXT: Group [[G4]]: 180; CHECK-NEXT: (Low: %Base1 High: (400 + %Base1)) 181; CHECK-NEXT: Member: {%Base1,+,4}<nw><%for.body> 182; CHECK-EMPTY: 183; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 184; CHECK-NEXT: SCEV assumptions: 185; CHECK-EMPTY: 186; CHECK-NEXT: Expressions re-written: 187 188define 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) { 189entry: 190 br label %for.body 191 192for.cond.cleanup: 193 ret void 194 195for.body: 196 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %latch ] 197 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 198 %0 = load i32, ptr %arrayidx, align 4 199 %cmp1.not = icmp eq i32 %0, 0 200 %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 201 %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv 202 %.sink = load float, ptr %.sink.in, align 4 203 %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 204 br i1 %c, label %then, label %latch 205 206then: 207 store float %.sink, ptr %1, align 4 208 br label %latch 209 210latch: 211 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 212 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 213 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 214} 215 216; CHECK-LABEL: function 'forked_ptrs_same_base_different_offset': 217; CHECK-NEXT: for.body: 218; CHECK-NEXT: Report: cannot identify array bounds 219; CHECK-NEXT: Dependences: 220; CHECK-NEXT: Run-time memory checks: 221; CHECK-NEXT: Grouped accesses: 222; CHECK-EMPTY: 223; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 224; CHECK-NEXT: SCEV assumptions: 225; CHECK-EMPTY: 226; CHECK-NEXT: Expressions re-written: 227 228;;;; Derived from the following C code 229;; void forked_ptrs_same_base_different_offset(float *A, float *B, int *C) { 230;; int offset; 231;; for (int i = 0; i < 100; i++) { 232;; if (C[i] != 0) 233;; offset = i; 234;; else 235;; offset = i+1; 236;; B[i] = A[offset]; 237;; } 238;; } 239 240define dso_local void @forked_ptrs_same_base_different_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 241entry: 242 br label %for.body 243 244for.cond.cleanup: ; preds = %for.body 245 ret void 246 247for.body: ; preds = %entry, %for.body 248 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 249 %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 250 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 251 %0 = load i32, ptr %arrayidx, align 4 252 %cmp1.not = icmp eq i32 %0, 0 253 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 254 %add = add nuw nsw i32 %i.014, 1 255 %1 = trunc i64 %indvars.iv to i32 256 %offset.0 = select i1 %cmp1.not, i32 %add, i32 %1 257 %idxprom213 = zext i32 %offset.0 to i64 258 %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %idxprom213 259 %2 = load float, ptr %arrayidx3, align 4 260 %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 261 store float %2, ptr %arrayidx5, align 4 262 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 263 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 264} 265 266;;;; Cases that can be handled by a forked pointer but are not currently allowed. 267 268; CHECK-LABEL: function 'forked_ptrs_uniform_and_strided_forks': 269; CHECK-NEXT: for.body: 270; CHECK-NEXT: Report: cannot identify array bounds 271; CHECK-NEXT: Dependences: 272; CHECK-NEXT: Run-time memory checks: 273; CHECK-NEXT: Grouped accesses: 274; CHECK-EMPTY: 275; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 276; CHECK-NEXT: SCEV assumptions: 277; CHECK-EMPTY: 278; CHECK-NEXT: Expressions re-written: 279 280;;;; Derived from forked_ptrs_same_base_different_offset with a manually 281;;;; added uniform offset and a mul to provide a stride 282 283define dso_local void @forked_ptrs_uniform_and_strided_forks(float* nocapture readonly %Base, float* nocapture %Dest, i32* nocapture readonly %Preds) { 284entry: 285 br label %for.body 286 287for.cond.cleanup: ; preds = %for.body 288 ret void 289 290for.body: ; preds = %entry, %for.body 291 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 292 %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 293 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 294 %0 = load i32, ptr %arrayidx, align 4 295 %cmp1.not = icmp eq i32 %0, 0 296 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 297 %add = add nuw nsw i32 %i.014, 1 298 %1 = trunc i64 %indvars.iv to i32 299 %mul = mul i32 %1, 3 300 %offset.0 = select i1 %cmp1.not, i32 4, i32 %mul 301 %idxprom213 = sext i32 %offset.0 to i64 302 %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %idxprom213 303 %2 = load float, ptr %arrayidx3, align 4 304 %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 305 store float %2, ptr %arrayidx5, align 4 306 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 307 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 308} 309 310; CHECK-LABEL: function 'forked_ptrs_gather_and_contiguous_forks': 311; CHECK-NEXT: for.body: 312; CHECK-NEXT: Report: cannot identify array bounds 313; CHECK-NEXT: Dependences: 314; CHECK-NEXT: Run-time memory checks: 315; CHECK-NEXT: Grouped accesses: 316; CHECK-EMPTY: 317; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 318; CHECK-NEXT: SCEV assumptions: 319; CHECK-EMPTY: 320; CHECK-NEXT: Expressions re-written: 321 322;;;; Derived from forked_ptrs_same_base_different_offset with a gather 323;;;; added using Preds as an index array in addition to the per-iteration 324;;;; condition. 325 326define dso_local void @forked_ptrs_gather_and_contiguous_forks(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 327entry: 328 br label %for.body 329 330for.cond.cleanup: ; preds = %for.body 331 ret void 332 333for.body: ; preds = %entry, %for.body 334 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 335 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 336 %0 = load i32, ptr %arrayidx, align 4 337 %cmp1.not = icmp eq i32 %0, 0 338 %arrayidx9 = getelementptr inbounds float, ptr %Base2, i64 %indvars.iv 339 %idxprom4 = sext i32 %0 to i64 340 %arrayidx5 = getelementptr inbounds float, ptr %Base1, i64 %idxprom4 341 %.sink.in = select i1 %cmp1.not, ptr %arrayidx9, ptr %arrayidx5 342 %.sink = load float, ptr %.sink.in, align 4 343 %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 344 store float %.sink, ptr %1, align 4 345 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 346 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 347 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 348} 349 350;; We don't currently handle a fork in both the base and the offset of a 351;; GEP instruction. 352 353; CHECK-LABEL: Loop access info in function 'forked_ptrs_two_forks_gep': 354; CHECK-NEXT: for.body: 355; CHECK-NEXT: Report: cannot identify array bounds 356; CHECK-NEXT: Dependences: 357; CHECK-NEXT: Run-time memory checks: 358; CHECK-NEXT: Grouped accesses: 359; CHECK-EMPTY: 360; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 361; CHECK-NEXT: SCEV assumptions: 362; CHECK-EMPTY: 363; CHECK-NEXT: Expressions re-written: 364 365define dso_local void @forked_ptrs_two_forks_gep(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 366entry: 367 br label %for.body 368 369for.cond.cleanup: 370 ret void 371 372for.body: 373 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 374 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 375 %0 = load i32, ptr %arrayidx, align 4 376 %cmp1.not = icmp eq i32 %0, 0 377 %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 378 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 379 %offset = select i1 %cmp1.not, i64 %indvars.iv.next, i64 %indvars.iv 380 %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %offset 381 %.sink = load float, ptr %.sink.in, align 4 382 %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 383 store float %.sink, ptr %1, align 4 384 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 385 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 386} 387 388;; We don't handle forks as children of a select 389 390; CHECK-LABEL: Loop access info in function 'forked_ptrs_two_select': 391; CHECK-NEXT: loop: 392; CHECK-NEXT: Report: cannot identify array bounds 393; CHECK-NEXT: Dependences: 394; CHECK-NEXT: Run-time memory checks: 395; CHECK-NEXT: Grouped accesses: 396; CHECK-EMPTY: 397; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 398; CHECK-NEXT: SCEV assumptions: 399; CHECK-EMPTY: 400; CHECK-NEXT: Expressions re-written: 401 402define void @forked_ptrs_two_select(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture readonly %Base3, ptr %Dest) { 403entry: 404 br label %loop 405 406loop: 407 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 408 %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv 409 %l.Dest = load float, ptr %gep.Dest 410 %cmp = fcmp une float %l.Dest, 0.0 411 %cmp1 = fcmp une float %l.Dest, 1.0 412 %gep.1 = getelementptr inbounds float, ptr %Base1, i64 %iv 413 %gep.2 = getelementptr inbounds float, ptr %Base2, i64 %iv 414 %gep.3 = getelementptr inbounds float, ptr %Base3, i64 %iv 415 %select = select i1 %cmp, ptr %gep.1, ptr %gep.2 416 %select1 = select i1 %cmp1, ptr %select, ptr %gep.3 417 %sink = load float, ptr %select1, align 4 418 store float %sink, ptr %gep.Dest, align 4 419 %iv.next = add nuw nsw i64 %iv, 1 420 %exitcond.not = icmp eq i64 %iv.next, 100 421 br i1 %exitcond.not, label %exit, label %loop 422 423exit: 424 ret void 425} 426 427;; We don't yet handle geps with more than 2 operands 428; CHECK-LABEL: Loop access info in function 'forked_ptrs_too_many_gep_ops': 429; CHECK-NEXT: for.body: 430; CHECK-NEXT: Report: cannot identify array bounds 431; CHECK-NEXT: Dependences: 432; CHECK-NEXT: Run-time memory checks: 433; CHECK-NEXT: Grouped accesses: 434; CHECK-EMPTY: 435; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 436; CHECK-NEXT: SCEV assumptions: 437; CHECK-EMPTY: 438; CHECK-NEXT: Expressions re-written: 439 440define void @forked_ptrs_too_many_gep_ops(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 441entry: 442 br label %for.body 443 444for.body: 445 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 446 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 447 %0 = load i32, ptr %arrayidx, align 4 448 %cmp1.not = icmp eq i32 %0, 0 449 %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 450 %.sink.in = getelementptr inbounds [1000 x float], ptr %spec.select, i64 0, i64 %indvars.iv 451 %.sink = load float, ptr %.sink.in, align 4 452 %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv 453 store float %.sink, ptr %1, align 4 454 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 455 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 456 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 457 458for.cond.cleanup: 459 ret void 460} 461 462;; We don't currently handle vector GEPs 463; CHECK-LABEL: Loop access info in function 'forked_ptrs_vector_gep': 464; CHECK-NEXT: for.body: 465; CHECK-NEXT: Report: cannot identify array bounds 466; CHECK-NEXT: Dependences: 467; CHECK-NEXT: Run-time memory checks: 468; CHECK-NEXT: Grouped accesses: 469; CHECK-EMPTY: 470; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 471; CHECK-NEXT: SCEV assumptions: 472; CHECK-EMPTY: 473; CHECK-NEXT: Expressions re-written: 474 475define void @forked_ptrs_vector_gep(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) { 476entry: 477 br label %for.body 478 479for.body: 480 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 481 %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv 482 %0 = load i32, ptr %arrayidx, align 4 483 %cmp1.not = icmp eq i32 %0, 0 484 %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1 485 %.sink.in = getelementptr inbounds <4 x float>, ptr %spec.select, i64 %indvars.iv 486 %.sink = load <4 x float>, ptr %.sink.in, align 4 487 %1 = getelementptr inbounds <4 x float>, ptr %Dest, i64 %indvars.iv 488 store <4 x float> %.sink, ptr %1, align 4 489 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4 490 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 491 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 492 493for.cond.cleanup: 494 ret void 495} 496