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