1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 5 6 7declare void @use(ptr) 8declare void @use.i1(i1) 9declare void @llvm.assume(i1) 10declare i1 @cond() 11 12define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(ptr %start, i16 %len) { 13; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit( 14; CHECK-NEXT: entry: 15; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 16; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 17; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 18; CHECK: loop.ph: 19; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 20; CHECK: loop.header: 21; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 22; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 23; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 24; CHECK: for.body: 25; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 26; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 27; CHECK: loop.next: 28; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 29; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 30; CHECK: loop.latch: 31; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 32; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1 33; CHECK-NEXT: br label [[LOOP_HEADER]] 34; CHECK: exit: 35; CHECK-NEXT: ret void 36; 37entry: 38 %upper = getelementptr inbounds i32, ptr %start, i16 %len 39 %len.neg = icmp slt i16 %len, 0 40 br i1 %len.neg, label %exit, label %loop.ph 41 42loop.ph: 43 br label %loop.header 44 45loop.header: 46 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 47 %c = icmp eq ptr %ptr.iv, %upper 48 br i1 %c, label %exit, label %for.body 49 50for.body: 51 %c.1 = call i1 @cond() 52 br i1 %c.1, label %loop.next, label %exit 53 54loop.next: 55 %t.1 = icmp uge ptr %ptr.iv, %start 56 %t.2 = icmp ult ptr %ptr.iv, %upper 57 %and = and i1 %t.1, %t.2 58 br i1 %and, label %loop.latch, label %exit 59 60loop.latch: 61 call void @use(ptr %ptr.iv) 62 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1 63 br label %loop.header 64 65exit: 66 ret void 67} 68 69define void @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(ptr %start, i16 %len) { 70; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit( 71; CHECK-NEXT: entry: 72; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]] 73; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 74; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 75; CHECK: loop.ph: 76; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 77; CHECK: loop.header: 78; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 79; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 80; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 81; CHECK: for.body: 82; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 83; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 84; CHECK: loop.next: 85; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 86; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 87; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 88; CHECK: loop.latch: 89; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 90; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 91; CHECK-NEXT: br label [[LOOP_HEADER]] 92; CHECK: exit: 93; CHECK-NEXT: ret void 94; 95entry: 96 %upper = getelementptr inbounds i8, ptr %start, i16 %len 97 %len.neg = icmp slt i16 %len, 0 98 br i1 %len.neg, label %exit, label %loop.ph 99 100loop.ph: 101 br label %loop.header 102 103loop.header: 104 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 105 %c = icmp eq ptr %ptr.iv, %upper 106 br i1 %c, label %exit, label %for.body 107 108for.body: 109 %c.1 = call i1 @cond() 110 br i1 %c.1, label %loop.next, label %exit 111 112loop.next: 113 %t.1 = icmp uge ptr %ptr.iv, %start 114 %t.2 = icmp ult ptr %ptr.iv, %upper 115 %and = and i1 %t.1, %t.2 116 br i1 %and, label %loop.latch, label %exit 117 118loop.latch: 119 call void @use(ptr %ptr.iv) 120 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 121 br label %loop.header 122 123exit: 124 ret void 125} 126 127define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) { 128; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit( 129; CHECK-NEXT: entry: 130; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]] 131; CHECK-NEXT: br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 132; CHECK: loop.ph: 133; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 134; CHECK: loop.header: 135; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 136; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]] 137; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 138; CHECK: for.body: 139; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 140; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 141; CHECK: loop.next: 142; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 143; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 144; CHECK: loop.latch: 145; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 146; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1 147; CHECK-NEXT: br label [[LOOP_HEADER]] 148; CHECK: exit: 149; CHECK-NEXT: ret void 150; 151entry: 152 %start.ult.end = icmp uge ptr %start, %end 153 br i1 %start.ult.end, label %exit, label %loop.ph 154 155loop.ph: 156 br label %loop.header 157 158loop.header: 159 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 160 %c = icmp eq ptr %ptr.iv, %end 161 br i1 %c, label %exit, label %for.body 162 163for.body: 164 %c.1 = call i1 @cond() 165 br i1 %c.1, label %loop.next, label %exit 166 167loop.next: 168 %t.1 = icmp uge ptr %ptr.iv, %start 169 %t.2 = icmp ult ptr %ptr.iv, %end 170 %and = and i1 %t.1, %t.2 171 br i1 %and, label %loop.latch, label %exit 172 173loop.latch: 174 call void @use(ptr %ptr.iv) 175 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1 176 br label %loop.header 177 178exit: 179 ret void 180} 181 182define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) { 183; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit( 184; CHECK-NEXT: entry: 185; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]] 186; CHECK-NEXT: br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 187; CHECK: loop.ph: 188; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 189; CHECK: loop.header: 190; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 191; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]] 192; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 193; CHECK: for.body: 194; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 195; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 196; CHECK: loop.next: 197; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]] 198; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 199; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 200; CHECK: loop.latch: 201; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 202; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 203; CHECK-NEXT: br label [[LOOP_HEADER]] 204; CHECK: exit: 205; CHECK-NEXT: ret void 206; 207entry: 208 %start.ult.end = icmp uge ptr %start, %end 209 br i1 %start.ult.end, label %exit, label %loop.ph 210 211loop.ph: 212 br label %loop.header 213 214loop.header: 215 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 216 %c = icmp eq ptr %ptr.iv, %end 217 br i1 %c, label %exit, label %for.body 218 219for.body: 220 %c.1 = call i1 @cond() 221 br i1 %c.1, label %loop.next, label %exit 222 223loop.next: 224 %t.1 = icmp uge ptr %ptr.iv, %start 225 %t.2 = icmp ult ptr %ptr.iv, %end 226 %and = and i1 %t.1, %t.2 227 br i1 %and, label %loop.latch, label %exit 228 229loop.latch: 230 call void @use(ptr %ptr.iv) 231 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 232 br label %loop.header 233 234exit: 235 ret void 236} 237 238define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(ptr %start, ptr %end, i16 %len) { 239; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper( 240; CHECK-NEXT: entry: 241; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[END:%.*]], i16 [[LEN:%.*]] 242; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 243; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 244; CHECK: loop.ph: 245; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp ult ptr [[START:%.*]], [[UPPER]] 246; CHECK-NEXT: call void @llvm.assume(i1 [[START_ULT_END]]) 247; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 248; CHECK: loop.header: 249; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 250; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 251; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 252; CHECK: for.body: 253; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 254; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 255; CHECK: loop.next: 256; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 257; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 258; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 259; CHECK: loop.latch: 260; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 261; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 262; CHECK-NEXT: br label [[LOOP_HEADER]] 263; CHECK: exit: 264; CHECK-NEXT: ret void 265; 266entry: 267 %upper = getelementptr inbounds i32, ptr %end, i16 %len 268 %len.neg = icmp slt i16 %len, 0 269 br i1 %len.neg, label %exit, label %loop.ph 270 271loop.ph: 272 %start.ult.end = icmp ult ptr %start, %upper 273 call void @llvm.assume(i1 %start.ult.end) 274 br label %loop.header 275 276loop.header: 277 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 278 %c = icmp eq ptr %ptr.iv, %upper 279 br i1 %c, label %exit, label %for.body 280 281for.body: 282 %c.1 = call i1 @cond() 283 br i1 %c.1, label %loop.next, label %exit 284 285loop.next: 286 %t.1 = icmp uge ptr %ptr.iv, %start 287 %t.2 = icmp ult ptr %ptr.iv, %upper 288 %and = and i1 %t.1, %t.2 289 br i1 %and, label %loop.latch, label %exit 290 291loop.latch: 292 call void @use(ptr %ptr.iv) 293 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 294 br label %loop.header 295 296exit: 297 ret void 298} 299 300define void @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(ptr %start, i16 %len, i16 %step) { 301; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit( 302; CHECK-NEXT: entry: 303; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0 304; CHECK-NEXT: call void @llvm.assume(i1 [[STEP_POS]]) 305; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 306; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 307; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 308; CHECK: loop.ph: 309; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 310; CHECK: loop.header: 311; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 312; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 313; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 314; CHECK: for.body: 315; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 316; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT]] 317; CHECK: then: 318; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 319; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 320; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]] 321; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 322; CHECK: loop.latch: 323; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 324; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]] 325; CHECK-NEXT: br label [[LOOP_HEADER]] 326; CHECK: exit: 327; CHECK-NEXT: ret void 328; 329entry: 330 %step.pos = icmp sge i16 %step, 0 331 call void @llvm.assume(i1 %step.pos) 332 %upper = getelementptr inbounds i32, ptr %start, i16 %len 333 %len.neg = icmp slt i16 %len, 0 334 br i1 %len.neg, label %exit, label %loop.ph 335 336loop.ph: 337 br label %loop.header 338 339loop.header: 340 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 341 %c = icmp eq ptr %ptr.iv, %upper 342 br i1 %c, label %exit, label %for.body 343 344for.body: 345 %c.1 = call i1 @cond() 346 br i1 %c.1, label %then, label %exit 347 348then: 349 %c.2 = icmp uge ptr %ptr.iv, %start 350 %c.3 = icmp ult ptr %ptr.iv, %upper 351 %and = and i1 %c.2, %c.3 352 br i1 %and, label %loop.latch, label %exit 353 354loop.latch: 355 call void @use(ptr %ptr.iv) 356 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step 357 br label %loop.header 358 359exit: 360 ret void 361} 362 363define void @test_monotonic_ptr_iv_cond_doesnt_control_exit(ptr %start, i16 %len) { 364; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit( 365; CHECK-NEXT: entry: 366; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 367; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 368; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 369; CHECK: loop.ph: 370; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 371; CHECK: loop.header: 372; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 373; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 374; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]] 375; CHECK: for.body: 376; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 377; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]] 378; CHECK: then: 379; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 380; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 381; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]] 382; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 383; CHECK-NEXT: br label [[LOOP_LATCH]] 384; CHECK: loop.latch: 385; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 386; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 387; CHECK-NEXT: br label [[LOOP_HEADER]] 388; CHECK: exit: 389; CHECK-NEXT: ret void 390; 391entry: 392 %upper = getelementptr inbounds i32, ptr %start, i16 %len 393 %len.neg = icmp slt i16 %len, 0 394 br i1 %len.neg, label %exit, label %loop.ph 395 396loop.ph: 397 br label %loop.header 398 399loop.header: 400 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 401 %c.0 = call i1 @cond() 402 br i1 %c.0, label %exit, label %for.body 403 404for.body: 405 %c.1 = icmp ne ptr %ptr.iv, %upper 406 br i1 %c.1, label %then, label %loop.latch 407 408then: 409 %t.1 = icmp uge ptr %ptr.iv, %start 410 %t.2 = icmp ult ptr %ptr.iv, %upper 411 %and = and i1 %t.1, %t.2 412 call void @use.i1(i1 %and) 413 br label %loop.latch 414 415loop.latch: 416 call void @use(ptr %ptr.iv) 417 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 418 br label %loop.header 419 420exit: 421 ret void 422} 423 424define void @test_monotonic_ptr_iv_cond_doesnt_control_exit2(ptr %start, i16 %len) { 425; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit2( 426; CHECK-NEXT: entry: 427; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 428; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 429; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 430; CHECK: loop.ph: 431; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 432; CHECK: loop.header: 433; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 434; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 435; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[FOR_BODY:%.*]] 436; CHECK: for.body: 437; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 438; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[LOOP_LATCH]] 439; CHECK: then: 440; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 441; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 442; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]] 443; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 444; CHECK-NEXT: br label [[LOOP_LATCH]] 445; CHECK: loop.latch: 446; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 447; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 448; CHECK-NEXT: br label [[LOOP_HEADER]] 449; CHECK: exit: 450; CHECK-NEXT: ret void 451; 452entry: 453 %upper = getelementptr inbounds i32, ptr %start, i16 %len 454 %len.neg = icmp slt i16 %len, 0 455 br i1 %len.neg, label %exit, label %loop.ph 456 457loop.ph: 458 br label %loop.header 459 460loop.header: 461 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 462 %c.1 = icmp ne ptr %ptr.iv, %upper 463 br i1 %c.1, label %then, label %for.body 464 465for.body: 466 %c.0 = call i1 @cond() 467 br i1 %c.0, label %exit, label %loop.latch 468 469then: 470 %t.1 = icmp uge ptr %ptr.iv, %start 471 %t.2 = icmp ult ptr %ptr.iv, %upper 472 %and = and i1 %t.1, %t.2 473 call void @use.i1(i1 %and) 474 br label %loop.latch 475 476loop.latch: 477 call void @use(ptr %ptr.iv) 478 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 479 br label %loop.header 480 481exit: 482 ret void 483} 484 485define void @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(ptr %start, i16 %len) { 486; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_dominate_checks( 487; CHECK-NEXT: entry: 488; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 489; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 490; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 491; CHECK: loop.ph: 492; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 493; CHECK: loop.header: 494; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 495; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 496; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]] 497; CHECK: for.body: 498; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 499; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]] 500; CHECK: then: 501; CHECK-NEXT: br label [[LOOP_LATCH]] 502; CHECK: loop.latch: 503; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 504; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 505; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]] 506; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 507; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 508; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 509; CHECK-NEXT: br label [[LOOP_HEADER]] 510; CHECK: exit: 511; CHECK-NEXT: ret void 512; 513entry: 514 %upper = getelementptr inbounds i32, ptr %start, i16 %len 515 %len.neg = icmp slt i16 %len, 0 516 br i1 %len.neg, label %exit, label %loop.ph 517 518loop.ph: 519 br label %loop.header 520 521loop.header: 522 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 523 %c.0 = call i1 @cond() 524 br i1 %c.0, label %exit, label %for.body 525 526for.body: 527 %c.1 = icmp ne ptr %ptr.iv, %upper 528 br i1 %c.1, label %then, label %loop.latch 529 530then: 531 br label %loop.latch 532 533loop.latch: 534 %c.2 = icmp uge ptr %ptr.iv, %start 535 %c.3 = icmp ult ptr %ptr.iv, %upper 536 %and = and i1 %c.2, %c.3 537 call void @use.i1(i1 %and) 538 call void @use(ptr %ptr.iv) 539 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 540 br label %loop.header 541 542exit: 543 ret void 544} 545 546define void @test_monotonic_ptr_iv_step_2_multi_exit(ptr %start, i16 %len) { 547; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_multi_exit( 548; CHECK-NEXT: entry: 549; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 550; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 551; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 552; CHECK: loop.ph: 553; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 554; CHECK: loop.header: 555; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 556; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 557; CHECK-NEXT: br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]] 558; CHECK: for.body: 559; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 560; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]] 561; CHECK: then: 562; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 563; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_3]] 564; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 565; CHECK-NEXT: br label [[LOOP_LATCH]] 566; CHECK: loop.latch: 567; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 568; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2 569; CHECK-NEXT: br label [[LOOP_HEADER]] 570; CHECK: exit: 571; CHECK-NEXT: ret void 572; 573entry: 574 %upper = getelementptr inbounds i32, ptr %start, i16 %len 575 %len.neg = icmp slt i16 %len, 0 576 br i1 %len.neg, label %exit, label %loop.ph 577 578loop.ph: 579 br label %loop.header 580 581loop.header: 582 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 583 %c.1 = icmp eq ptr %ptr.iv, %upper 584 br i1 %c.1, label %exit, label %for.body 585 586for.body: 587 %c.0 = call i1 @cond() 588 br i1 %c.0, label %exit, label %then 589 590then: 591 %c.2 = icmp uge ptr %ptr.iv, %start 592 %c.3 = icmp ult ptr %ptr.iv, %upper 593 %and = and i1 %c.2, %c.3 594 call void @use.i1(i1 %and) 595 br label %loop.latch 596 597loop.latch: 598 call void @use(ptr %ptr.iv) 599 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2 600 br label %loop.header 601 602exit: 603 ret void 604} 605 606define void @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(ptr %start, i16 %len) { 607; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit( 608; CHECK-NEXT: entry: 609; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 610; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 611; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 612; CHECK: loop.ph: 613; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 614; CHECK: loop.header: 615; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 616; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 617; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]] 618; CHECK: for.body: 619; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 620; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]] 621; CHECK: then: 622; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 623; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 624; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]] 625; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 626; CHECK-NEXT: br label [[LOOP_LATCH]] 627; CHECK: loop.latch: 628; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 629; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2 630; CHECK-NEXT: br label [[LOOP_HEADER]] 631; CHECK: exit: 632; CHECK-NEXT: ret void 633; 634entry: 635 %upper = getelementptr inbounds i32, ptr %start, i16 %len 636 %len.neg = icmp slt i16 %len, 0 637 br i1 %len.neg, label %exit, label %loop.ph 638 639loop.ph: 640 br label %loop.header 641 642loop.header: 643 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 644 %c.0 = call i1 @cond() 645 br i1 %c.0, label %exit, label %for.body 646 647for.body: 648 %c.1 = icmp ne ptr %ptr.iv, %upper 649 br i1 %c.1, label %then, label %loop.latch 650 651then: 652 %c.2 = icmp uge ptr %ptr.iv, %start 653 %c.3 = icmp ult ptr %ptr.iv, %upper 654 %and = and i1 %c.2, %c.3 655 call void @use.i1(i1 %and) 656 br label %loop.latch 657 658loop.latch: 659 call void @use(ptr %ptr.iv) 660 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2 661 br label %loop.header 662 663exit: 664 ret void 665} 666 667define void @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(ptr %start, i16 %len) { 668; CHECK-LABEL: @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit( 669; CHECK-NEXT: entry: 670; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]] 671; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 672; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 673; CHECK: loop.ph: 674; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 675; CHECK: loop.header: 676; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 677; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 678; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]] 679; CHECK: for.body: 680; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 681; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]] 682; CHECK: then: 683; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 684; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 685; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]] 686; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 687; CHECK-NEXT: br label [[LOOP_LATCH]] 688; CHECK: loop.latch: 689; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 690; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 4 691; CHECK-NEXT: br label [[LOOP_HEADER]] 692; CHECK: exit: 693; CHECK-NEXT: ret void 694; 695entry: 696 %upper = getelementptr inbounds i64, ptr %start, i16 %len 697 %len.neg = icmp slt i16 %len, 0 698 br i1 %len.neg, label %exit, label %loop.ph 699 700loop.ph: 701 br label %loop.header 702 703loop.header: 704 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 705 %c.0 = call i1 @cond() 706 br i1 %c.0, label %exit, label %for.body 707 708for.body: 709 %c.1 = icmp ne ptr %ptr.iv, %upper 710 br i1 %c.1, label %then, label %loop.latch 711 712then: 713 %c.2 = icmp uge ptr %ptr.iv, %start 714 %c.3 = icmp ult ptr %ptr.iv, %upper 715 %and = and i1 %c.2, %c.3 716 call void @use.i1(i1 %and) 717 br label %loop.latch 718 719loop.latch: 720 call void @use(ptr %ptr.iv) 721 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 4 722 br label %loop.header 723 724exit: 725 ret void 726} 727 728define void @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(ptr %start, i16 %len) { 729; CHECK-LABEL: @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit( 730; CHECK-NEXT: entry: 731; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]] 732; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 733; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 734; CHECK: loop.ph: 735; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 736; CHECK: loop.header: 737; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 738; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 739; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]] 740; CHECK: for.body: 741; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 742; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]] 743; CHECK: then: 744; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 745; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 746; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]] 747; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 748; CHECK-NEXT: br label [[LOOP_LATCH]] 749; CHECK: loop.latch: 750; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 751; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 5 752; CHECK-NEXT: br label [[LOOP_HEADER]] 753; CHECK: exit: 754; CHECK-NEXT: ret void 755; 756entry: 757 %upper = getelementptr inbounds i64, ptr %start, i16 %len 758 %len.neg = icmp slt i16 %len, 0 759 br i1 %len.neg, label %exit, label %loop.ph 760 761loop.ph: 762 br label %loop.header 763 764loop.header: 765 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 766 %c.0 = call i1 @cond() 767 br i1 %c.0, label %exit, label %for.body 768 769for.body: 770 %c.1 = icmp ne ptr %ptr.iv, %upper 771 br i1 %c.1, label %then, label %loop.latch 772 773then: 774 %c.2 = icmp uge ptr %ptr.iv, %start 775 %c.3 = icmp ult ptr %ptr.iv, %upper 776 %and = and i1 %c.2, %c.3 777 call void @use.i1(i1 %and) 778 br label %loop.latch 779 780loop.latch: 781 call void @use(ptr %ptr.iv) 782 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 5 783 br label %loop.header 784 785exit: 786 ret void 787} 788 789define void @test_monotonic_ptr_iv_inc_1_check_outside_loop(ptr %start, i16 %len) { 790; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_check_outside_loop( 791; CHECK-NEXT: entry: 792; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 793; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0 794; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_NEG]]) 795; CHECK-NEXT: br label [[LOOP_PH:%.*]] 796; CHECK: loop.ph: 797; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 798; CHECK: loop.header: 799; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 800; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond() 801; CHECK-NEXT: br i1 [[C_0]], label [[EXIT:%.*]], label [[LOOP_LATCH]] 802; CHECK: loop.latch: 803; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 804; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 805; CHECK-NEXT: br label [[LOOP_HEADER]] 806; CHECK: exit: 807; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]] 808; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT_2:%.*]] 809; CHECK: then: 810; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 811; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 812; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]] 813; CHECK-NEXT: call void @use.i1(i1 [[AND]]) 814; CHECK-NEXT: br label [[EXIT_2]] 815; CHECK: exit.2: 816; CHECK-NEXT: ret void 817; 818entry: 819 %upper = getelementptr inbounds i32, ptr %start, i16 %len 820 %len.neg = icmp sge i16 %len, 0 821 call void @llvm.assume(i1 %len.neg) 822 br label %loop.ph 823 824loop.ph: 825 br label %loop.header 826 827loop.header: 828 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 829 %c.0 = call i1 @cond() 830 br i1 %c.0, label %exit, label %loop.latch 831 832loop.latch: 833 call void @use(ptr %ptr.iv) 834 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 835 br label %loop.header 836 837exit: 838 %c.1 = icmp ne ptr %ptr.iv, %upper 839 br i1 %c.1, label %then, label %exit.2 840 841then: 842 %c.2 = icmp uge ptr %ptr.iv, %start 843 %c.3 = icmp ult ptr %ptr.iv, %upper 844 %and = and i1 %c.2, %c.3 845 call void @use.i1(i1 %and) 846 br label %exit.2 847 848exit.2: 849 ret void 850} 851 852define void @test_step_gep_doesnt_use_ptr_iv_phi(ptr %start, ptr %other, i16 %len) { 853; CHECK-LABEL: @test_step_gep_doesnt_use_ptr_iv_phi( 854; CHECK-NEXT: entry: 855; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]] 856; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 857; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 858; CHECK: loop.ph: 859; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 860; CHECK: loop.header: 861; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 862; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 863; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 864; CHECK: for.body: 865; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 866; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 867; CHECK: loop.next: 868; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 869; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 870; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]] 871; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 872; CHECK: loop.latch: 873; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 874; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[OTHER:%.*]], i16 1 875; CHECK-NEXT: br label [[LOOP_HEADER]] 876; CHECK: exit: 877; CHECK-NEXT: ret void 878; 879entry: 880 %upper = getelementptr inbounds float, ptr %start, i16 %len 881 %len.neg = icmp slt i16 %len, 0 882 br i1 %len.neg, label %exit, label %loop.ph 883 884loop.ph: 885 br label %loop.header 886 887loop.header: 888 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 889 %c = icmp eq ptr %ptr.iv, %upper 890 br i1 %c, label %exit, label %for.body 891 892for.body: 893 %c.1 = call i1 @cond() 894 br i1 %c.1, label %loop.next, label %exit 895 896loop.next: 897 %t.1 = icmp uge ptr %ptr.iv, %start 898 %t.2 = icmp ult ptr %ptr.iv, %upper 899 %and = and i1 %t.1, %t.2 900 br i1 %and, label %loop.latch, label %exit 901 902loop.latch: 903 call void @use(ptr %ptr.iv) 904 %ptr.iv.next = getelementptr inbounds float, ptr %other, i16 1 905 br label %loop.header 906 907exit: 908 ret void 909} 910 911define void @test_step_gep_not_inbounds(ptr %start, ptr %end, i16 %len) { 912; CHECK-LABEL: @test_step_gep_not_inbounds( 913; CHECK-NEXT: entry: 914; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]] 915; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 916; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 917; CHECK: loop.ph: 918; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 919; CHECK: loop.header: 920; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 921; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 922; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 923; CHECK: for.body: 924; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 925; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 926; CHECK: loop.next: 927; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 928; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 929; CHECK: loop.latch: 930; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 931; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr float, ptr [[PTR_IV]], i16 1 932; CHECK-NEXT: br label [[LOOP_HEADER]] 933; CHECK: exit: 934; CHECK-NEXT: ret void 935; 936entry: 937 %upper = getelementptr inbounds float, ptr %start, i16 %len 938 %len.neg = icmp slt i16 %len, 0 939 br i1 %len.neg, label %exit, label %loop.ph 940 941loop.ph: 942 br label %loop.header 943 944loop.header: 945 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 946 %c = icmp eq ptr %ptr.iv, %upper 947 br i1 %c, label %exit, label %for.body 948 949for.body: 950 %c.1 = call i1 @cond() 951 br i1 %c.1, label %loop.next, label %exit 952 953loop.next: 954 %t.1 = icmp uge ptr %ptr.iv, %start 955 %t.2 = icmp ult ptr %ptr.iv, %upper 956 %and = and i1 %t.1, %t.2 957 br i1 %and, label %loop.latch, label %exit 958 959loop.latch: 960 call void @use(ptr %ptr.iv) 961 %ptr.iv.next = getelementptr float, ptr %ptr.iv, i16 1 962 br label %loop.header 963 964exit: 965 ret void 966} 967 968define void @test_upper_gep_not_inbounds(ptr %start, ptr %end, i16 %len) { 969; CHECK-LABEL: @test_upper_gep_not_inbounds( 970; CHECK-NEXT: entry: 971; CHECK-NEXT: [[UPPER:%.*]] = getelementptr float, ptr [[START:%.*]], i16 [[LEN:%.*]] 972; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 973; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 974; CHECK: loop.ph: 975; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 976; CHECK: loop.header: 977; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 978; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 979; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 980; CHECK: for.body: 981; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 982; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 983; CHECK: loop.next: 984; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 985; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 986; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 987; CHECK: loop.latch: 988; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 989; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV]], i16 1 990; CHECK-NEXT: br label [[LOOP_HEADER]] 991; CHECK: exit: 992; CHECK-NEXT: ret void 993; 994entry: 995 %upper = getelementptr float, ptr %start, i16 %len 996 %len.neg = icmp slt i16 %len, 0 997 br i1 %len.neg, label %exit, label %loop.ph 998 999loop.ph: 1000 br label %loop.header 1001 1002loop.header: 1003 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 1004 %c = icmp eq ptr %ptr.iv, %upper 1005 br i1 %c, label %exit, label %for.body 1006 1007for.body: 1008 %c.1 = call i1 @cond() 1009 br i1 %c.1, label %loop.next, label %exit 1010 1011loop.next: 1012 %t.1 = icmp uge ptr %ptr.iv, %start 1013 %t.2 = icmp ult ptr %ptr.iv, %upper 1014 %and = and i1 %t.1, %t.2 1015 br i1 %and, label %loop.latch, label %exit 1016 1017loop.latch: 1018 call void @use(ptr %ptr.iv) 1019 %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv, i16 1 1020 br label %loop.header 1021 1022exit: 1023 ret void 1024} 1025