1; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s 2 3%s1 = type { [32000 x double], [32000 x double], [32000 x double] } 4 5define i32 @load_with_pointer_phi_no_runtime_checks(%s1* %data) { 6; CHECK-LABEL: load_with_pointer_phi_no_runtime_checks 7; CHECK-NEXT: loop.header: 8; CHECK-NEXT: Memory dependences are safe 9; 10entry: 11 br label %loop.header 12 13loop.header: ; preds = %loop.latch, %entry 14 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 15 %iv.next = add nuw nsw i64 %iv, 1 16 %cmp5 = icmp ult i64 %iv, 15999 17 %arrayidx = getelementptr inbounds %s1, %s1 * %data, i64 0, i32 0, i64 %iv 18 br i1 %cmp5, label %if.then, label %if.else 19 20if.then: ; preds = %loop.header 21 %gep.1 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 1, i64 %iv 22 br label %loop.latch 23 24if.else: ; preds = %loop.header 25 %gep.2 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 2, i64 %iv 26 br label %loop.latch 27 28loop.latch: ; preds = %if.else, %if.then 29 %gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ] 30 %v8 = load double, double* %gep.2.sink, align 8 31 %mul16 = fmul double 3.0, %v8 32 store double %mul16, double* %arrayidx, align 8 33 %exitcond.not = icmp eq i64 %iv.next, 32000 34 br i1 %exitcond.not, label %exit, label %loop.header 35 36exit: ; preds = %loop.latch 37 ret i32 10 38} 39 40define i32 @store_with_pointer_phi_no_runtime_checks(%s1* %data) { 41; CHECK-LABEL: 'store_with_pointer_phi_no_runtime_checks' 42; CHECK-NEXT: loop.header: 43; CHECK-NEXT: Memory dependences are safe 44; 45entry: 46 br label %loop.header 47 48loop.header: ; preds = %loop.latch, %entry 49 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 50 %iv.next = add nuw nsw i64 %iv, 1 51 %cmp5 = icmp ult i64 %iv, 15999 52 %arrayidx = getelementptr inbounds %s1, %s1 * %data, i64 0, i32 0, i64 %iv 53 br i1 %cmp5, label %if.then, label %if.else 54 55if.then: ; preds = %loop.header 56 %gep.1 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 1, i64 %iv 57 br label %loop.latch 58 59if.else: ; preds = %loop.header 60 %gep.2 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 2, i64 %iv 61 br label %loop.latch 62 63loop.latch: ; preds = %if.else, %if.then 64 %gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ] 65 %v8 = load double, double* %arrayidx, align 8 66 %mul16 = fmul double 3.0, %v8 67 store double %mul16, double* %gep.2.sink, align 8 68 %exitcond.not = icmp eq i64 %iv.next, 32000 69 br i1 %exitcond.not, label %exit, label %loop.header 70 71exit: ; preds = %loop.latch 72 ret i32 10 73} 74 75define i32 @store_with_pointer_phi_runtime_checks(double* %A, double* %B, double* %C) { 76; CHECK-LABEL: 'store_with_pointer_phi_runtime_checks' 77; CHECK-NEXT: loop.header: 78; CHECK-NEXT: Memory dependences are safe with run-time checks 79; CHECK: Run-time memory checks: 80; CHECK-NEXT: Check 0: 81; CHECK-NEXT: Comparing group ([[GROUP_B:.+]]): 82; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv 83; CHECK-NEXT: Against group ([[GROUP_C:.+]]): 84; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv 85; CHECK-NEXT: Check 1: 86; CHECK-NEXT: Comparing group ([[GROUP_B]]): 87; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv 88; CHECK-NEXT: Against group ([[GROUP_A:.+]]): 89; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 90; CHECK-NEXT: Check 2: 91; CHECK-NEXT: Comparing group ([[GROUP_C]]): 92; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv 93; CHECK-NEXT: Against group ([[GROUP_A]]): 94; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 95; 96entry: 97 br label %loop.header 98 99loop.header: ; preds = %loop.latch, %entry 100 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 101 %iv.next = add nuw nsw i64 %iv, 1 102 %cmp5 = icmp ult i64 %iv, 15999 103 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 104 br i1 %cmp5, label %if.then, label %if.else 105 106if.then: ; preds = %loop.header 107 %gep.1 = getelementptr inbounds double, double* %B, i64 %iv 108 br label %loop.latch 109 110if.else: ; preds = %loop.header 111 %gep.2 = getelementptr inbounds double, double* %C, i64 %iv 112 br label %loop.latch 113 114loop.latch: ; preds = %if.else, %if.then 115 %gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ] 116 %v8 = load double, double* %arrayidx, align 8 117 %mul16 = fmul double 3.0, %v8 118 store double %mul16, double* %gep.2.sink, align 8 119 %exitcond.not = icmp eq i64 %iv.next, 32000 120 br i1 %exitcond.not, label %exit, label %loop.header 121 122exit: ; preds = %loop.latch 123 ret i32 10 124} 125 126define i32 @load_with_pointer_phi_outside_loop(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) { 127; CHECK-LABEL: 'load_with_pointer_phi_outside_loop' 128; CHECK-NEXT: loop.header: 129; CHECK-NEXT: Report: unsafe dependent memory operations in loop 130; CHECK-NEXT: Dependences: 131; CHECK-NEXT: Unknown: 132; CHECK-NEXT: %v8 = load double, double* %ptr, align 8 -> 133; CHECK-NEXT: store double %mul16, double* %arrayidx, align 8 134; 135entry: 136 br i1 %c.0, label %if.then, label %if.else 137 138if.then: 139 br label %loop.ph 140 141if.else: 142 %ptr.select = select i1 %c.1, double* %C, double* %B 143 br label %loop.ph 144 145loop.ph: 146 %ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ] 147 br label %loop.header 148 149loop.header: ; preds = %loop.latch, %entry 150 %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ] 151 %iv.next = add nuw nsw i64 %iv, 1 152 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 153 %v8 = load double, double* %ptr, align 8 154 %mul16 = fmul double 3.0, %v8 155 store double %mul16, double* %arrayidx, align 8 156 %exitcond.not = icmp eq i64 %iv.next, 32000 157 br i1 %exitcond.not, label %exit, label %loop.header 158 159exit: ; preds = %loop.latch 160 ret i32 10 161} 162 163define i32 @store_with_pointer_phi_outside_loop(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) { 164; CHECK-LABEL: 'store_with_pointer_phi_outside_loop' 165; CHECK-NEXT: loop.header: 166; CHECK-NEXT: Report: unsafe dependent memory operations in loop. 167; CHECK-NEXT: Dependences: 168; CHECK-NEXT: Unknown: 169; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 -> 170; CHECK-NEXT: store double %mul16, double* %ptr, align 8 171; 172entry: 173 br i1 %c.0, label %if.then, label %if.else 174 175if.then: 176 br label %loop.ph 177 178if.else: 179 %ptr.select = select i1 %c.1, double* %C, double* %B 180 br label %loop.ph 181 182loop.ph: 183 %ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ] 184 br label %loop.header 185 186loop.header: ; preds = %loop.latch, %entry 187 %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ] 188 %iv.next = add nuw nsw i64 %iv, 1 189 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 190 %v8 = load double, double* %arrayidx, align 8 191 %mul16 = fmul double 3.0, %v8 192 store double %mul16, double* %ptr, align 8 193 %exitcond.not = icmp eq i64 %iv.next, 32000 194 br i1 %exitcond.not, label %exit, label %loop.header 195 196exit: ; preds = %loop.latch 197 ret i32 10 198} 199 200define i32 @store_with_pointer_phi_incoming_phi(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) { 201; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi' 202; CHECK-NEXT: loop.header: 203; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 204; CHECK-NEXT: Dependences: 205; CHECK-NEXT: Unknown: 206; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 -> 207; CHECK-NEXT: store double %mul16, double* %ptr.2, align 8 208; CHECK-EMPTY: 209; CHECK-NEXT: Run-time memory checks: 210; CHECK-NEXT: Check 0: 211; CHECK-NEXT: Comparing group ([[GROUP_C:.+]]): 212; CHECK-NEXT: double* %C 213; CHECK-NEXT: Against group ([[GROUP_B:.+]]): 214; CHECK-NEXT: double* %B 215; CHECK-NEXT: Check 1: 216; CHECK-NEXT: Comparing group ([[GROUP_C]]): 217; CHECK-NEXT: double* %C 218; CHECK-NEXT: Against group ([[GROUP_A:.+]]): 219; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 220; CHECK-NEXT: double* %A 221; CHECK-NEXT: Check 2: 222; CHECK-NEXT: Comparing group ([[GROUP_B]]): 223; CHECK-NEXT: double* %B 224; CHECK-NEXT: Against group ([[GROUP_A]]): 225; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 226; CHECK-NEXT: double* %A 227; CHECK-NEXT: Grouped accesses: 228; CHECK-NEXT: Group [[GROUP_C]]: 229; CHECK-NEXT: (Low: %C High: (8 + %C)) 230; CHECK-NEXT: Member: %C 231; CHECK-NEXT: Group [[GROUP_B]]: 232; CHECK-NEXT: (Low: %B High: (8 + %B)) 233; CHECK-NEXT: Member: %B 234; CHECK-NEXT: Group [[GROUP_A]]: 235; CHECK-NEXT: (Low: %A High: (256000 + %A)) 236; CHECK-NEXT: Member: {%A,+,8}<nuw><%loop.header> 237; CHECK-NEXT: Member: %A 238; CHECK-EMPTY 239entry: 240 br label %loop.header 241 242loop.header: ; preds = %loop.latch, %entry 243 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 244 %iv.next = add nuw nsw i64 %iv, 1 245 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 246 %v8 = load double, double* %arrayidx, align 8 247 %mul16 = fmul double 3.0, %v8 248 br i1 %c.0, label %loop.then, label %loop.latch 249 250loop.then: 251 br i1 %c.0, label %loop.then.2, label %loop.else.2 252 253loop.then.2: 254 br label %merge.2 255 256loop.else.2: 257 br label %merge.2 258 259 260merge.2: 261 %ptr = phi double* [ %A, %loop.then.2 ], [ %B, %loop.else.2 ] 262 br label %loop.latch 263 264 265loop.latch: 266 %ptr.2 = phi double* [ %ptr, %merge.2], [ %C, %loop.header ] 267 store double %mul16, double* %ptr.2, align 8 268 %exitcond.not = icmp eq i64 %iv.next, 32000 269 br i1 %exitcond.not, label %exit, label %loop.header 270 271exit: ; preds = %loop.latch 272 ret i32 10 273} 274 275; Test cases with pointer phis forming a cycle. 276define i32 @store_with_pointer_phi_incoming_phi_irreducible_cycle(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) { 277; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi_irreducible_cycle' 278; CHECK-NEXT: loop.header: 279; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 280; CHECK-NEXT: Dependences: 281; CHECK-NEXT: Unknown: 282; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 -> 283; CHECK-NEXT: store double %mul16, double* %ptr.3, align 8 284; CHECK-EMPTY: 285; CHECK-NEXT: Run-time memory checks: 286; CHECK-NEXT: Check 0: 287; CHECK-NEXT: Comparing group ([[GROUP_C:.+]]): 288; CHECK-NEXT: double* %C 289; CHECK-NEXT: Against group ([[GROUP_B:.+]]): 290; CHECK-NEXT: double* %B 291; CHECK-NEXT: Check 1: 292; CHECK-NEXT: Comparing group ([[GROUP_C]]): 293; CHECK-NEXT: double* %C 294; CHECK-NEXT: Against group ([[GROUP_A:.+]]): 295; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 296; CHECK-NEXT: double* %A 297; CHECK-NEXT: Check 2: 298; CHECK-NEXT: Comparing group ([[GROUP_B]]): 299; CHECK-NEXT: double* %B 300; CHECK-NEXT: Against group ([[GROUP_A]]): 301; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 302; CHECK-NEXT: double* %A 303; CHECK-NEXT: Grouped accesses: 304; CHECK-NEXT: Group [[GROUP_C]] 305; CHECK-NEXT: (Low: %C High: (8 + %C)) 306; CHECK-NEXT: Member: %C 307; CHECK-NEXT: Group [[GROUP_B]] 308; CHECK-NEXT: (Low: %B High: (8 + %B)) 309; CHECK-NEXT: Member: %B 310; CHECK-NEXT: Group [[GROUP_A]] 311; CHECK-NEXT: (Low: %A High: (256000 + %A)) 312; CHECK-NEXT: Member: {%A,+,8}<nuw><%loop.header> 313; CHECK-NEXT: Member: %A 314; CHECK-EMPTY 315entry: 316 br label %loop.header 317 318loop.header: ; preds = %loop.latch, %entry 319 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] 320 %iv.next = add nuw nsw i64 %iv, 1 321 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 322 %v8 = load double, double* %arrayidx, align 8 323 %mul16 = fmul double 3.0, %v8 324 br i1 %c.0, label %loop.then, label %loop.latch 325 326loop.then: 327 br i1 %c.0, label %BB.A, label %BB.B 328 329BB.A: 330 %ptr = phi double* [ %A, %loop.then ], [ %ptr.2, %BB.B ] 331 br label %BB.B 332 333BB.B: 334 %ptr.2 = phi double* [ %ptr, %BB.A ], [ %B, %loop.then ] 335 br i1 %c.1, label %loop.latch, label %BB.A 336 337loop.latch: 338 %ptr.3 = phi double* [ %ptr.2, %BB.B ], [ %C, %loop.header ] 339 store double %mul16, double* %ptr.3, align 8 340 %exitcond.not = icmp eq i64 %iv.next, 32000 341 br i1 %exitcond.not, label %exit, label %loop.header 342 343exit: ; preds = %loop.latch 344 ret i32 10 345} 346 347define i32 @store_with_pointer_phi_outside_loop_select(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) { 348; CHECK-LABEL: 'store_with_pointer_phi_outside_loop_select' 349; CHECK-NEXT: loop.header: 350; CHECK-NEXT: Report: unsafe dependent memory operations in loop. 351; CHECK-NEXT: Dependences: 352; CHECK-NEXT: Unknown: 353; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 -> 354; CHECK-NEXT: store double %mul16, double* %ptr, align 8 355; 356entry: 357 br i1 %c.0, label %if.then, label %if.else 358 359if.then: 360 br label %loop.ph 361 362if.else: 363 %ptr.select = select i1 %c.1, double* %C, double* %B 364 br label %loop.ph 365 366loop.ph: 367 %ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ] 368 br label %loop.header 369 370loop.header: ; preds = %loop.latch, %entry 371 %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ] 372 %iv.next = add nuw nsw i64 %iv, 1 373 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 374 %v8 = load double, double* %arrayidx, align 8 375 %mul16 = fmul double 3.0, %v8 376 store double %mul16, double* %ptr, align 8 377 %exitcond.not = icmp eq i64 %iv.next, 32000 378 br i1 %exitcond.not, label %exit, label %loop.header 379 380exit: ; preds = %loop.latch 381 ret i32 10 382} 383 384define i32 @store_with_pointer_phi_in_same_bb_use_other_phi(double* %A, double* %B, double* %C, double* %D, i1 %c.0, i1 %c.1) { 385; CHECK-LABEL: Loop access info in function 'store_with_pointer_phi_in_same_bb_use_other_phi': 386; CHECK-NEXT: loop.header: 387; CHECK-NEXT: Report: cannot identify array bounds 388; CHECK-NEXT: Dependences: 389; CHECK-NEXT: Run-time memory checks: 390; CHECK-NEXT: Grouped accesses: 391; CHECK-EMPTY: 392; 393entry: 394 br label %loop.header 395 396loop.header: ; preds = %loop.latch, %entry 397 %ptr.0 = phi double* [ %C, %entry ], [ %D, %loop.header ] 398 %ptr.1 = phi double* [ %B, %entry ], [ %ptr.0, %loop.header ] 399 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.header ] 400 %iv.next = add nuw nsw i64 %iv, 1 401 %arrayidx = getelementptr inbounds double, double* %A, i64 %iv 402 %v8 = load double, double* %arrayidx, align 8 403 %mul16 = fmul double 3.0, %v8 404 store double %mul16, double* %ptr.1, align 8 405 %exitcond.not = icmp eq i64 %iv.next, 32000 406 br i1 %exitcond.not, label %exit, label %loop.header 407 408exit: ; preds = %loop.latch 409 ret i32 10 410} 411 412define void @phi_load_store_memdep_check(i1 %c, i16* %A, i16* %B, i16* %C) { 413; CHECK-LABEL: Loop access info in function 'phi_load_store_memdep_check': 414; CHECK-NEXT: for.body: 415; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop 416; CHECK-NEXT: Dependences: 417; CHECK-NEXT: Unknown: 418; CHECK-NEXT: %lv3 = load i16, i16* %c.sink, align 2 -> 419; CHECK-NEXT: store i16 %add, i16* %c.sink, align 1 420; CHECK-EMPTY: 421; CHECK-NEXT: Unknown: 422; CHECK-NEXT: %lv3 = load i16, i16* %c.sink, align 2 -> 423; CHECK-NEXT: store i16 %add, i16* %c.sink, align 1 424; CHECK-EMPTY: 425; CHECK-NEXT: Unknown: 426; CHECK-NEXT: %lv = load i16, i16* %A, align 1 -> 427; CHECK-NEXT: store i16 %lv, i16* %A, align 1 428; CHECK-EMPTY: 429; CHECK-NEXT: Unknown: 430; CHECK-NEXT: store i16 %lv, i16* %A, align 1 -> 431; CHECK-NEXT: %lv2 = load i16, i16* %A, align 1 432; CHECK-EMPTY: 433; CHECK-NEXT: Run-time memory checks: 434; CHECK-NEXT: Check 0: 435; CHECK-NEXT: Comparing group ([[GROUP_A:.+]]): 436; CHECK-NEXT: i16* %A 437; CHECK-NEXT: i16* %A 438; CHECK-NEXT: Against group ([[GROUP_C:.+]]): 439; CHECK-NEXT: i16* %C 440; CHECK-NEXT: i16* %C 441; CHECK-NEXT: Check 1: 442; CHECK-NEXT: Comparing group ([[GROUP_A]]): 443; CHECK-NEXT: i16* %A 444; CHECK-NEXT: i16* %A 445; CHECK-NEXT: Against group ([[GROUP_B:.+]]): 446; CHECK-NEXT: i16* %B 447; CHECK-NEXT: i16* %B 448; CHECK-NEXT: Check 2: 449; CHECK-NEXT: Comparing group ([[GROUP_C]]): 450; CHECK-NEXT: i16* %C 451; CHECK-NEXT: i16* %C 452; CHECK-NEXT: Against group ([[GROUP_B]]): 453; CHECK-NEXT: i16* %B 454; CHECK-NEXT: i16* %B 455; CHECK-NEXT: Grouped accesses: 456; CHECK-NEXT: Group [[GROUP_A]] 457; CHECK-NEXT: (Low: %A High: (2 + %A)) 458; CHECK-NEXT: Member: %A 459; CHECK-NEXT: Member: %A 460; CHECK-NEXT: Group [[GROUP_C]] 461; CHECK-NEXT: (Low: %C High: (2 + %C)) 462; CHECK-NEXT: Member: %C 463; CHECK-NEXT: Member: %C 464; CHECK-NEXT: Group [[GROUP_B]] 465; CHECK-NEXT: (Low: %B High: (2 + %B)) 466; CHECK-NEXT: Member: %B 467; CHECK-NEXT: Member: %B 468; CHECK-EMPTY: 469; 470entry: 471 br label %for.body 472 473for.body: ; preds = %if.end, %entry 474 %iv = phi i16 [ 0, %entry ], [ %iv.next, %if.end ] 475 %lv = load i16, i16* %A, align 1 476 store i16 %lv, i16* %A, align 1 477 br i1 %c, label %if.then, label %if.end 478 479if.then: ; preds = %for.body 480 %lv2 = load i16, i16* %A, align 1 481 br label %if.end 482 483if.end: ; preds = %if.then, %for.body 484 %c.sink = phi i16* [ %B, %if.then ], [ %C, %for.body ] 485 %lv3 = load i16, i16* %c.sink 486 %add = add i16 %lv3, 10 487 store i16 %add, i16* %c.sink, align 1 488 %iv.next = add nuw nsw i16 %iv, 1 489 %tobool.not = icmp eq i16 %iv.next, 1000 490 br i1 %tobool.not, label %for.end.loopexit, label %for.body 491 492for.end.loopexit: ; preds = %if.end 493 ret void 494} 495