1; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s 3 4target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 5 6declare void @llvm.assume(i1) 7 8define void @different_non_constant_strides_known_forward(ptr %A) { 9; CHECK-LABEL: 'different_non_constant_strides_known_forward' 10; CHECK-NEXT: loop: 11; CHECK-NEXT: Memory dependences are safe 12; CHECK-NEXT: Dependences: 13; CHECK-NEXT: Forward: 14; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 15; CHECK-NEXT: store i32 %add, ptr %gep, align 4 16; CHECK-EMPTY: 17; CHECK-NEXT: Run-time memory checks: 18; CHECK-NEXT: Grouped accesses: 19; CHECK-EMPTY: 20; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 21; CHECK-NEXT: SCEV assumptions: 22; CHECK-EMPTY: 23; CHECK-NEXT: Expressions re-written: 24; 25entry: 26 br label %loop 27 28loop: 29 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 30 %iv.mul.2 = shl nuw nsw i64 %iv, 1 31 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 32 %l = load i32, ptr %gep.mul.2, align 4 33 %add = add nsw i32 %l, 5 34 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 35 store i32 %add, ptr %gep, align 4 36 %iv.next = add nuw nsw i64 %iv, 1 37 %exitcond.not = icmp eq i64 %iv.next, 256 38 br i1 %exitcond.not, label %exit, label %loop 39 40exit: 41 ret void 42} 43 44define void @different_non_constant_strides_known_forward_min_distance_3(ptr %A) { 45; CHECK-LABEL: 'different_non_constant_strides_known_forward_min_distance_3' 46; CHECK-NEXT: loop: 47; CHECK-NEXT: Memory dependences are safe 48; CHECK-NEXT: Dependences: 49; CHECK-NEXT: Forward: 50; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 51; CHECK-NEXT: store i32 %add, ptr %gep, align 4 52; CHECK-EMPTY: 53; CHECK-NEXT: Run-time memory checks: 54; CHECK-NEXT: Grouped accesses: 55; CHECK-EMPTY: 56; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 57; CHECK-NEXT: SCEV assumptions: 58; CHECK-EMPTY: 59; CHECK-NEXT: Expressions re-written: 60; 61entry: 62 %A.3 = getelementptr inbounds i8, ptr %A, i64 3 63 br label %loop 64 65loop: 66 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 67 %iv.mul.2 = shl nuw nsw i64 %iv, 1 68 %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2 69 %l = load i32, ptr %gep.mul.2, align 4 70 %add = add nsw i32 %l, 5 71 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 72 store i32 %add, ptr %gep, align 4 73 %iv.next = add nuw nsw i64 %iv, 1 74 %exitcond.not = icmp eq i64 %iv.next, 256 75 br i1 %exitcond.not, label %exit, label %loop 76 77exit: 78 ret void 79} 80 81define void @different_non_constant_strides_known_forward_via_assume(ptr %A, i64 %scale) { 82; CHECK-LABEL: 'different_non_constant_strides_known_forward_via_assume' 83; CHECK-NEXT: loop: 84; CHECK-NEXT: Report: cannot identify array bounds 85; CHECK-NEXT: Dependences: 86; CHECK-NEXT: Run-time memory checks: 87; CHECK-NEXT: Grouped accesses: 88; CHECK-EMPTY: 89; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 90; CHECK-NEXT: SCEV assumptions: 91; CHECK-EMPTY: 92; CHECK-NEXT: Expressions re-written: 93; 94entry: 95 %c = icmp sgt i64 %scale, 0 96 call void @llvm.assume(i1 %c) 97 br label %loop 98 99loop: 100 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 101 %iv.mul.2 = shl nuw nsw i64 %iv, %scale 102 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 103 %l = load i32, ptr %gep.mul.2, align 4 104 %add = add nsw i32 %l, 5 105 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 106 store i32 %add, ptr %gep, align 4 107 %iv.next = add nuw nsw i64 %iv, 1 108 %exitcond.not = icmp eq i64 %iv.next, 256 109 br i1 %exitcond.not, label %exit, label %loop 110 111exit: 112 ret void 113} 114 115define void @different_non_constant_strides_known_forward_via_assume_min_distance_3(ptr %A, i64 %scale) { 116; CHECK-LABEL: 'different_non_constant_strides_known_forward_via_assume_min_distance_3' 117; CHECK-NEXT: loop: 118; CHECK-NEXT: Report: cannot identify array bounds 119; CHECK-NEXT: Dependences: 120; CHECK-NEXT: Run-time memory checks: 121; CHECK-NEXT: Grouped accesses: 122; CHECK-EMPTY: 123; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 124; CHECK-NEXT: SCEV assumptions: 125; CHECK-EMPTY: 126; CHECK-NEXT: Expressions re-written: 127; 128entry: 129 %A.3 = getelementptr inbounds i8, ptr %A, i64 3 130 %c = icmp sgt i64 %scale, 0 131 call void @llvm.assume(i1 %c) 132 br label %loop 133 134loop: 135 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 136 %iv.mul.2 = shl nuw nsw i64 %iv, %scale 137 %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2 138 %l = load i32, ptr %gep.mul.2, align 4 139 %add = add nsw i32 %l, 5 140 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 141 store i32 %add, ptr %gep, align 4 142 %iv.next = add nuw nsw i64 %iv, 1 143 %exitcond.not = icmp eq i64 %iv.next, 256 144 br i1 %exitcond.not, label %exit, label %loop 145 146exit: 147 ret void 148} 149 150define void @different_non_constant_strides_not_known_forward(ptr %A, i64 %scale) { 151; CHECK-LABEL: 'different_non_constant_strides_not_known_forward' 152; CHECK-NEXT: loop: 153; CHECK-NEXT: Report: cannot identify array bounds 154; CHECK-NEXT: Dependences: 155; CHECK-NEXT: Run-time memory checks: 156; CHECK-NEXT: Grouped accesses: 157; CHECK-EMPTY: 158; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 159; CHECK-NEXT: SCEV assumptions: 160; CHECK-EMPTY: 161; CHECK-NEXT: Expressions re-written: 162; 163entry: 164 br label %loop 165 166loop: 167 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 168 %iv.mul.2 = shl nuw nsw i64 %iv, %scale 169 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 170 %l = load i32, ptr %gep.mul.2, align 4 171 %add = add nsw i32 %l, 5 172 %gep = getelementptr inbounds i32, ptr %A, i64 %iv 173 store i32 %add, ptr %gep, align 4 174 %iv.next = add nuw nsw i64 %iv, 1 175 %exitcond.not = icmp eq i64 %iv.next, 256 176 br i1 %exitcond.not, label %exit, label %loop 177 178exit: 179 ret void 180} 181 182; Tests with accesses with strides with different signs. 183define void @strides_with_different_directions_1(ptr %A) { 184; CHECK-LABEL: 'strides_with_different_directions_1' 185; CHECK-NEXT: loop: 186; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 187; CHECK-NEXT: Unknown data dependence. 188; CHECK-NEXT: Dependences: 189; CHECK-NEXT: Unknown: 190; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 191; CHECK-NEXT: store i32 %add, ptr %gep, align 4 192; CHECK-EMPTY: 193; CHECK-NEXT: Run-time memory checks: 194; CHECK-NEXT: Grouped accesses: 195; CHECK-EMPTY: 196; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 197; CHECK-NEXT: SCEV assumptions: 198; CHECK-EMPTY: 199; CHECK-NEXT: Expressions re-written: 200; 201entry: 202 br label %loop 203 204loop: 205 %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] 206 %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] 207 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.1 208 %l = load i32, ptr %gep.mul.2, align 4 209 %add = add nsw i32 %l, 5 210 %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2 211 store i32 %add, ptr %gep, align 4 212 %iv.1.next = add nuw nsw i64 %iv.1, 1 213 %iv.2.next = add nsw i64 %iv.2, -1 214 %exitcond.not = icmp eq i64 %iv.1.next, 256 215 br i1 %exitcond.not, label %exit, label %loop 216 217exit: 218 ret void 219} 220 221define void @strides_with_different_directions_2(ptr %A) { 222; CHECK-LABEL: 'strides_with_different_directions_2' 223; CHECK-NEXT: loop: 224; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 225; CHECK-NEXT: Unknown data dependence. 226; CHECK-NEXT: Dependences: 227; CHECK-NEXT: Unknown: 228; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 229; CHECK-NEXT: store i32 %add, ptr %gep, align 4 230; CHECK-EMPTY: 231; CHECK-NEXT: Run-time memory checks: 232; CHECK-NEXT: Grouped accesses: 233; CHECK-EMPTY: 234; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 235; CHECK-NEXT: SCEV assumptions: 236; CHECK-EMPTY: 237; CHECK-NEXT: Expressions re-written: 238; 239entry: 240 br label %loop 241 242loop: 243 %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] 244 %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] 245 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.2 246 %l = load i32, ptr %gep.mul.2, align 4 247 %add = add nsw i32 %l, 5 248 %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1 249 store i32 %add, ptr %gep, align 4 250 %iv.1.next = add nuw nsw i64 %iv.1, 1 251 %iv.2.next = add nsw i64 %iv.2, -1 252 %exitcond.not = icmp eq i64 %iv.1.next, 256 253 br i1 %exitcond.not, label %exit, label %loop 254 255exit: 256 ret void 257} 258 259define void @strides_with_different_directions_3(ptr %A) { 260; CHECK-LABEL: 'strides_with_different_directions_3' 261; CHECK-NEXT: loop: 262; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 263; CHECK-NEXT: Unknown data dependence. 264; CHECK-NEXT: Dependences: 265; CHECK-NEXT: Unknown: 266; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 267; CHECK-NEXT: store i32 %add, ptr %gep, align 4 268; CHECK-EMPTY: 269; CHECK-NEXT: Run-time memory checks: 270; CHECK-NEXT: Grouped accesses: 271; CHECK-EMPTY: 272; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 273; CHECK-NEXT: SCEV assumptions: 274; CHECK-EMPTY: 275; CHECK-NEXT: Expressions re-written: 276; 277entry: 278 br label %loop 279 280loop: 281 %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] 282 %iv.2 = phi i64 [ 600, %entry ], [ %iv.2.next, %loop ] 283 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.1 284 %l = load i32, ptr %gep.mul.2, align 4 285 %add = add nsw i32 %l, 5 286 %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2 287 store i32 %add, ptr %gep, align 4 288 %iv.1.next = add nuw nsw i64 %iv.1, 1 289 %iv.2.next = add nsw i64 %iv.2, -2 290 %exitcond.not = icmp eq i64 %iv.1.next, 256 291 br i1 %exitcond.not, label %exit, label %loop 292 293exit: 294 ret void 295} 296 297define void @strides_with_different_directions_4(ptr %A) { 298; CHECK-LABEL: 'strides_with_different_directions_4' 299; CHECK-NEXT: loop: 300; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 301; CHECK-NEXT: Unknown data dependence. 302; CHECK-NEXT: Dependences: 303; CHECK-NEXT: Unknown: 304; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 305; CHECK-NEXT: store i32 %add, ptr %gep, align 4 306; CHECK-EMPTY: 307; CHECK-NEXT: Run-time memory checks: 308; CHECK-NEXT: Grouped accesses: 309; CHECK-EMPTY: 310; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 311; CHECK-NEXT: SCEV assumptions: 312; CHECK-EMPTY: 313; CHECK-NEXT: Expressions re-written: 314; 315entry: 316 br label %loop 317 318loop: 319 %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] 320 %iv.2 = phi i64 [ 600, %entry ], [ %iv.2.next, %loop ] 321 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.2 322 %l = load i32, ptr %gep.mul.2, align 4 323 %add = add nsw i32 %l, 5 324 %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1 325 store i32 %add, ptr %gep, align 4 326 %iv.1.next = add nuw nsw i64 %iv.1, 1 327 %iv.2.next = add nsw i64 %iv.2, -2 328 %exitcond.not = icmp eq i64 %iv.1.next, 256 329 br i1 %exitcond.not, label %exit, label %loop 330 331exit: 332 ret void 333} 334 335define void @non_constant_strides_with_different_directions_1(ptr %A) { 336; CHECK-LABEL: 'non_constant_strides_with_different_directions_1' 337; CHECK-NEXT: loop: 338; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 339; CHECK-NEXT: Unknown data dependence. 340; CHECK-NEXT: Dependences: 341; CHECK-NEXT: Unknown: 342; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 343; CHECK-NEXT: store i32 %add, ptr %gep, align 4 344; CHECK-EMPTY: 345; CHECK-NEXT: Run-time memory checks: 346; CHECK-NEXT: Grouped accesses: 347; CHECK-EMPTY: 348; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 349; CHECK-NEXT: SCEV assumptions: 350; CHECK-EMPTY: 351; CHECK-NEXT: Expressions re-written: 352; 353entry: 354 br label %loop 355 356loop: 357 %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] 358 %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] 359 %iv.mul.2 = shl nuw nsw i64 %iv.1, 1 360 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 361 %l = load i32, ptr %gep.mul.2, align 4 362 %add = add nsw i32 %l, 5 363 %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2 364 store i32 %add, ptr %gep, align 4 365 %iv.1.next = add nuw nsw i64 %iv.1, 1 366 %iv.2.next = add nsw i64 %iv.2, -1 367 %exitcond.not = icmp eq i64 %iv.1.next, 256 368 br i1 %exitcond.not, label %exit, label %loop 369 370exit: 371 ret void 372} 373 374define void @non_constant_strides_with_different_directions_2(ptr %A) { 375; CHECK-LABEL: 'non_constant_strides_with_different_directions_2' 376; CHECK-NEXT: loop: 377; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 378; CHECK-NEXT: Unknown data dependence. 379; CHECK-NEXT: Dependences: 380; CHECK-NEXT: Unknown: 381; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> 382; CHECK-NEXT: store i32 %add, ptr %gep, align 4 383; CHECK-EMPTY: 384; CHECK-NEXT: Run-time memory checks: 385; CHECK-NEXT: Grouped accesses: 386; CHECK-EMPTY: 387; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. 388; CHECK-NEXT: SCEV assumptions: 389; CHECK-EMPTY: 390; CHECK-NEXT: Expressions re-written: 391; 392entry: 393 br label %loop 394 395loop: 396 %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] 397 %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] 398 %iv.mul.2 = shl nuw nsw i64 %iv.2, 1 399 %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 400 %l = load i32, ptr %gep.mul.2, align 4 401 %add = add nsw i32 %l, 5 402 %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1 403 store i32 %add, ptr %gep, align 4 404 %iv.1.next = add nuw nsw i64 %iv.1, 1 405 %iv.2.next = add nsw i64 %iv.2, -1 406 %exitcond.not = icmp eq i64 %iv.1.next, 256 407 br i1 %exitcond.not, label %exit, label %loop 408 409exit: 410 ret void 411} 412