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_struct_type(ptr %start, i16 %len) { 13; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type( 14; CHECK-NEXT: entry: 15; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, 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 {i16, i8, i8}, 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_struct_type_offset_0(ptr %start, i16 %len) { 63; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_0( 64; CHECK-NEXT: entry: 65; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 0 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 [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 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 {i16, i8, i8}, ptr %start, i16 %len, i32 0 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 [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 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_struct_type_offset_16(ptr %start, i16 %len) { 113; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_16( 114; CHECK-NEXT: entry: 115; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1 116; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 117; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 118; CHECK: loop.ph: 119; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 120; CHECK: loop.header: 121; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 122; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 123; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 124; CHECK: for.body: 125; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 126; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 127; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 128; CHECK: loop.latch: 129; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 130; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 131; CHECK-NEXT: br label [[LOOP_HEADER]] 132; CHECK: exit: 133; CHECK-NEXT: ret void 134; 135entry: 136 %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 1 137 %len.neg = icmp slt i16 %len, 0 138 br i1 %len.neg, label %exit, label %loop.ph 139 140loop.ph: 141 br label %loop.header 142 143loop.header: 144 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 145 %c = icmp eq ptr %ptr.iv, %upper 146 br i1 %c, label %exit, label %for.body 147 148for.body: 149 %t.1 = icmp uge ptr %ptr.iv, %start 150 %t.2 = icmp ult ptr %ptr.iv, %upper 151 %and = and i1 %t.1, %t.2 152 br i1 %and, label %loop.latch, label %exit 153 154loop.latch: 155 call void @use(ptr %ptr.iv) 156 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 157 br label %loop.header 158 159exit: 160 ret void 161} 162 163define void @test_monotonic_ptr_iv_inc_1_struct_type_with_early_exit(ptr %start, i16 %len) { 164; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_with_early_exit( 165; CHECK-NEXT: entry: 166; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 0 167; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 168; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 169; CHECK: loop.ph: 170; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 171; CHECK: loop.header: 172; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 173; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 174; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 175; CHECK: for.body: 176; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 177; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 178; CHECK: loop.next: 179; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 180; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 181; CHECK: loop.latch: 182; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 183; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 184; CHECK-NEXT: br label [[LOOP_HEADER]] 185; CHECK: exit: 186; CHECK-NEXT: ret void 187; 188entry: 189 %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 0 190 %len.neg = icmp slt i16 %len, 0 191 br i1 %len.neg, label %exit, label %loop.ph 192 193loop.ph: 194 br label %loop.header 195 196loop.header: 197 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 198 %c = icmp eq ptr %ptr.iv, %upper 199 br i1 %c, label %exit, label %for.body 200 201for.body: 202 %c.1 = call i1 @cond() 203 br i1 %c.1, label %loop.next, label %exit 204 205loop.next: 206 %t.1 = icmp uge ptr %ptr.iv, %start 207 %t.2 = icmp ult ptr %ptr.iv, %upper 208 %and = and i1 %t.1, %t.2 209 br i1 %and, label %loop.latch, label %exit 210 211loop.latch: 212 call void @use(ptr %ptr.iv) 213 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 214 br label %loop.header 215 216exit: 217 ret void 218} 219 220define void @test_monotonic_ptr_iv_inc_1_struct_type_offset_0_with_early_exit(ptr %start, i16 %len) { 221; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_0_with_early_exit( 222; CHECK-NEXT: entry: 223; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 0 224; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 225; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 226; CHECK: loop.ph: 227; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 228; CHECK: loop.header: 229; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 230; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 231; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 232; CHECK: for.body: 233; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 234; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 235; CHECK: loop.next: 236; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 237; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 238; CHECK: loop.latch: 239; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 240; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 241; CHECK-NEXT: br label [[LOOP_HEADER]] 242; CHECK: exit: 243; CHECK-NEXT: ret void 244; 245entry: 246 %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 0 247 %len.neg = icmp slt i16 %len, 0 248 br i1 %len.neg, label %exit, label %loop.ph 249 250loop.ph: 251 br label %loop.header 252 253loop.header: 254 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 255 %c = icmp eq ptr %ptr.iv, %upper 256 br i1 %c, label %exit, label %for.body 257 258for.body: 259 %c.1 = call i1 @cond() 260 br i1 %c.1, label %loop.next, label %exit 261 262loop.next: 263 %t.1 = icmp uge ptr %ptr.iv, %start 264 %t.2 = icmp ult ptr %ptr.iv, %upper 265 %and = and i1 %t.1, %t.2 266 br i1 %and, label %loop.latch, label %exit 267 268loop.latch: 269 call void @use(ptr %ptr.iv) 270 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 271 br label %loop.header 272 273exit: 274 ret void 275} 276 277define void @test_monotonic_ptr_iv_inc_1_struct_type_offset_16_with_early_exit(ptr %start, i16 %len) { 278; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_16_with_early_exit( 279; CHECK-NEXT: entry: 280; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1 281; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 282; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 283; CHECK: loop.ph: 284; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 285; CHECK: loop.header: 286; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 287; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 288; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 289; CHECK: for.body: 290; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 291; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 292; CHECK: loop.next: 293; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 294; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 295; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 296; CHECK: loop.latch: 297; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 298; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 299; CHECK-NEXT: br label [[LOOP_HEADER]] 300; CHECK: exit: 301; CHECK-NEXT: ret void 302; 303entry: 304 %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 1 305 %len.neg = icmp slt i16 %len, 0 306 br i1 %len.neg, label %exit, label %loop.ph 307 308loop.ph: 309 br label %loop.header 310 311loop.header: 312 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 313 %c = icmp eq ptr %ptr.iv, %upper 314 br i1 %c, label %exit, label %for.body 315 316for.body: 317 %c.1 = call i1 @cond() 318 br i1 %c.1, label %loop.next, label %exit 319 320loop.next: 321 %t.1 = icmp uge ptr %ptr.iv, %start 322 %t.2 = icmp ult ptr %ptr.iv, %upper 323 %and = and i1 %t.1, %t.2 324 br i1 %and, label %loop.latch, label %exit 325 326loop.latch: 327 call void @use(ptr %ptr.iv) 328 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 329 br label %loop.header 330 331exit: 332 ret void 333} 334 335define void @test_monotonic_ptr_iv_inc_2_struct_type_with_early_exit(ptr %start, i16 %len) { 336; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_struct_type_with_early_exit( 337; CHECK-NEXT: entry: 338; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 339; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 340; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 341; CHECK: loop.ph: 342; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 343; CHECK: loop.header: 344; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 345; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 346; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 347; CHECK: for.body: 348; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 349; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 350; CHECK: loop.next: 351; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 352; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 353; CHECK: loop.latch: 354; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 355; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i8, i8 }, ptr [[PTR_IV]], i16 1 356; CHECK-NEXT: br label [[LOOP_HEADER]] 357; CHECK: exit: 358; CHECK-NEXT: ret void 359; 360entry: 361 %upper = getelementptr inbounds i32, ptr %start, i16 %len 362 %len.neg = icmp slt i16 %len, 0 363 br i1 %len.neg, label %exit, label %loop.ph 364 365loop.ph: 366 br label %loop.header 367 368loop.header: 369 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 370 %c = icmp eq ptr %ptr.iv, %upper 371 br i1 %c, label %exit, label %for.body 372 373for.body: 374 %c.1 = call i1 @cond() 375 br i1 %c.1, label %loop.next, label %exit 376 377loop.next: 378 %t.1 = icmp uge ptr %ptr.iv, %start 379 %t.2 = icmp ult ptr %ptr.iv, %upper 380 %and = and i1 %t.1, %t.2 381 br i1 %and, label %loop.latch, label %exit 382 383loop.latch: 384 call void @use(ptr %ptr.iv) 385 %ptr.iv.next = getelementptr inbounds {i16, i8, i8}, ptr %ptr.iv, i16 1 386 br label %loop.header 387 388exit: 389 ret void 390} 391 392define void @test_monotonic_ptr_iv_inc_2_struct_type_offset_0_with_early_exit(ptr %start, i16 %len) { 393; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_struct_type_offset_0_with_early_exit( 394; CHECK-NEXT: entry: 395; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 396; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 397; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 398; CHECK: loop.ph: 399; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 400; CHECK: loop.header: 401; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 402; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 403; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 404; CHECK: for.body: 405; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 406; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 407; CHECK: loop.next: 408; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 409; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 410; CHECK: loop.latch: 411; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 412; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i8, i8 }, ptr [[PTR_IV]], i16 1, i32 0 413; CHECK-NEXT: br label [[LOOP_HEADER]] 414; CHECK: exit: 415; CHECK-NEXT: ret void 416; 417entry: 418 %upper = getelementptr inbounds i32, ptr %start, i16 %len 419 %len.neg = icmp slt i16 %len, 0 420 br i1 %len.neg, label %exit, label %loop.ph 421 422loop.ph: 423 br label %loop.header 424 425loop.header: 426 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 427 %c = icmp eq ptr %ptr.iv, %upper 428 br i1 %c, label %exit, label %for.body 429 430for.body: 431 %c.1 = call i1 @cond() 432 br i1 %c.1, label %loop.next, label %exit 433 434loop.next: 435 %t.1 = icmp uge ptr %ptr.iv, %start 436 %t.2 = icmp ult ptr %ptr.iv, %upper 437 %and = and i1 %t.1, %t.2 438 br i1 %and, label %loop.latch, label %exit 439 440loop.latch: 441 call void @use(ptr %ptr.iv) 442 %ptr.iv.next = getelementptr inbounds {i16, i8, i8}, ptr %ptr.iv, i16 1, i32 0 443 br label %loop.header 444 445exit: 446 ret void 447} 448 449define void @test_monotonic_ptr_iv_inc_2_struct_type_offset_16_with_early_exit(ptr %start, i16 %len) { 450; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_struct_type_offset_16_with_early_exit( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]] 453; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 454; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 455; CHECK: loop.ph: 456; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 457; CHECK: loop.header: 458; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 459; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 460; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 461; CHECK: for.body: 462; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 463; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 464; CHECK: loop.next: 465; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 466; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 467; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 468; CHECK: loop.latch: 469; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 470; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i8, i8 }, ptr [[PTR_IV]], i16 1, i32 1 471; CHECK-NEXT: br label [[LOOP_HEADER]] 472; CHECK: exit: 473; CHECK-NEXT: ret void 474; 475entry: 476 %upper = getelementptr inbounds i32, ptr %start, i16 %len 477 %len.neg = icmp slt i16 %len, 0 478 br i1 %len.neg, label %exit, label %loop.ph 479 480loop.ph: 481 br label %loop.header 482 483loop.header: 484 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 485 %c = icmp eq ptr %ptr.iv, %upper 486 br i1 %c, label %exit, label %for.body 487 488for.body: 489 %c.1 = call i1 @cond() 490 br i1 %c.1, label %loop.next, label %exit 491 492loop.next: 493 %t.1 = icmp uge ptr %ptr.iv, %start 494 %t.2 = icmp ult ptr %ptr.iv, %upper 495 %and = and i1 %t.1, %t.2 496 br i1 %and, label %loop.latch, label %exit 497 498loop.latch: 499 call void @use(ptr %ptr.iv) 500 %ptr.iv.next = getelementptr inbounds {i16, i8, i8}, ptr %ptr.iv, i16 1, i32 1 501 br label %loop.header 502 503exit: 504 ret void 505} 506 507define void @test_monotonic_ptr_iv_inc_1_nested_struct(ptr %start, i16 %len) { 508; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct( 509; CHECK-NEXT: entry: 510; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]] 511; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 512; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 513; CHECK: loop.ph: 514; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 515; CHECK: loop.header: 516; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 517; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 518; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 519; CHECK: for.body: 520; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 521; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 522; CHECK: loop.next: 523; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 524; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 525; CHECK: loop.latch: 526; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 527; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i16 1 528; CHECK-NEXT: br label [[LOOP_HEADER]] 529; CHECK: exit: 530; CHECK-NEXT: ret void 531; 532entry: 533 %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len 534 %len.neg = icmp slt i16 %len, 0 535 br i1 %len.neg, label %exit, label %loop.ph 536 537loop.ph: 538 br label %loop.header 539 540loop.header: 541 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 542 %c = icmp eq ptr %ptr.iv, %upper 543 br i1 %c, label %exit, label %for.body 544 545for.body: 546 %c.1 = call i1 @cond() 547 br i1 %c.1, label %loop.next, label %exit 548 549loop.next: 550 %t.1 = icmp uge ptr %ptr.iv, %start 551 %t.2 = icmp ult ptr %ptr.iv, %upper 552 %and = and i1 %t.1, %t.2 553 br i1 %and, label %loop.latch, label %exit 554 555loop.latch: 556 call void @use(ptr %ptr.iv) 557 %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i16 1 558 br label %loop.header 559 560exit: 561 ret void 562} 563 564define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_64(ptr %start, i16 %len) { 565; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_64( 566; CHECK-NEXT: entry: 567; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i32 1 568; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 569; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 570; CHECK: loop.ph: 571; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 572; CHECK: loop.header: 573; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 574; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 575; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 576; CHECK: for.body: 577; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 578; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 579; CHECK: loop.next: 580; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 581; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 582; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 583; CHECK: loop.latch: 584; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 585; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i16 1 586; CHECK-NEXT: br label [[LOOP_HEADER]] 587; CHECK: exit: 588; CHECK-NEXT: ret void 589; 590entry: 591 %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len, i32 1, i32 1 592 %len.neg = icmp slt i16 %len, 0 593 br i1 %len.neg, label %exit, label %loop.ph 594 595loop.ph: 596 br label %loop.header 597 598loop.header: 599 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 600 %c = icmp eq ptr %ptr.iv, %upper 601 br i1 %c, label %exit, label %for.body 602 603for.body: 604 %c.1 = call i1 @cond() 605 br i1 %c.1, label %loop.next, label %exit 606 607loop.next: 608 %t.1 = icmp uge ptr %ptr.iv, %start 609 %t.2 = icmp ult ptr %ptr.iv, %upper 610 %and = and i1 %t.1, %t.2 611 br i1 %and, label %loop.latch, label %exit 612 613loop.latch: 614 call void @use(ptr %ptr.iv) 615 %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i16 1 616 br label %loop.header 617 618exit: 619 ret void 620} 621 622define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_32(ptr %start, i16 %len) { 623; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_32( 624; CHECK-NEXT: entry: 625; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i32 1 626; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 627; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 628; CHECK: loop.ph: 629; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 630; CHECK: loop.header: 631; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 632; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 633; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 634; CHECK: for.body: 635; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 636; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 637; CHECK: loop.next: 638; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 639; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 640; CHECK: loop.latch: 641; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 642; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 643; CHECK-NEXT: br label [[LOOP_HEADER]] 644; CHECK: exit: 645; CHECK-NEXT: ret void 646; 647entry: 648 %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len, i32 1, i32 1 649 %len.neg = icmp slt i16 %len, 0 650 br i1 %len.neg, label %exit, label %loop.ph 651 652loop.ph: 653 br label %loop.header 654 655loop.header: 656 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 657 %c = icmp eq ptr %ptr.iv, %upper 658 br i1 %c, label %exit, label %for.body 659 660for.body: 661 %c.1 = call i1 @cond() 662 br i1 %c.1, label %loop.next, label %exit 663 664loop.next: 665 %t.1 = icmp uge ptr %ptr.iv, %start 666 %t.2 = icmp ult ptr %ptr.iv, %upper 667 %and = and i1 %t.1, %t.2 668 br i1 %and, label %loop.latch, label %exit 669 670loop.latch: 671 call void @use(ptr %ptr.iv) 672 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 673 br label %loop.header 674 675exit: 676 ret void 677} 678 679define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_16(ptr %start, i16 %len) { 680; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_16( 681; CHECK-NEXT: entry: 682; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i32 1 683; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 684; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 685; CHECK: loop.ph: 686; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 687; CHECK: loop.header: 688; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 689; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 690; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 691; CHECK: for.body: 692; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 693; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 694; CHECK: loop.next: 695; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 696; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 697; CHECK: loop.latch: 698; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 699; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1 700; CHECK-NEXT: br label [[LOOP_HEADER]] 701; CHECK: exit: 702; CHECK-NEXT: ret void 703; 704entry: 705 %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len, i32 1, i32 1 706 %len.neg = icmp slt i16 %len, 0 707 br i1 %len.neg, label %exit, label %loop.ph 708 709loop.ph: 710 br label %loop.header 711 712loop.header: 713 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 714 %c = icmp eq ptr %ptr.iv, %upper 715 br i1 %c, label %exit, label %for.body 716 717for.body: 718 %c.1 = call i1 @cond() 719 br i1 %c.1, label %loop.next, label %exit 720 721loop.next: 722 %t.1 = icmp uge ptr %ptr.iv, %start 723 %t.2 = icmp ult ptr %ptr.iv, %upper 724 %and = and i1 %t.1, %t.2 725 br i1 %and, label %loop.latch, label %exit 726 727loop.latch: 728 call void @use(ptr %ptr.iv) 729 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1 730 br label %loop.header 731 732exit: 733 ret void 734} 735 736define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16(ptr %start, i16 %len) { 737; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16( 738; CHECK-NEXT: entry: 739; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]] 740; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 741; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 742; CHECK: loop.ph: 743; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 744; CHECK: loop.header: 745; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 746; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 747; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 748; CHECK: for.body: 749; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 750; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 751; CHECK: loop.next: 752; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 753; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 754; CHECK: loop.latch: 755; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 756; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1 757; CHECK-NEXT: br label [[LOOP_HEADER]] 758; CHECK: exit: 759; CHECK-NEXT: ret void 760; 761entry: 762 %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len 763 %len.neg = icmp slt i16 %len, 0 764 br i1 %len.neg, label %exit, label %loop.ph 765 766loop.ph: 767 br label %loop.header 768 769loop.header: 770 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 771 %c = icmp eq ptr %ptr.iv, %upper 772 br i1 %c, label %exit, label %for.body 773 774for.body: 775 %c.1 = call i1 @cond() 776 br i1 %c.1, label %loop.next, label %exit 777 778loop.next: 779 %t.1 = icmp uge ptr %ptr.iv, %start 780 %t.2 = icmp ult ptr %ptr.iv, %upper 781 %and = and i1 %t.1, %t.2 782 br i1 %and, label %loop.latch, label %exit 783 784loop.latch: 785 call void @use(ptr %ptr.iv) 786 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1 787 br label %loop.header 788 789exit: 790 ret void 791} 792 793define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16_2(ptr %start, i16 %len) { 794; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16_2( 795; CHECK-NEXT: entry: 796; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]] 797; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 798; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 799; CHECK: loop.ph: 800; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 801; CHECK: loop.header: 802; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 803; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 804; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 805; CHECK: for.body: 806; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 807; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 808; CHECK: loop.next: 809; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 810; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 811; CHECK: loop.latch: 812; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 813; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 2 814; CHECK-NEXT: br label [[LOOP_HEADER]] 815; CHECK: exit: 816; CHECK-NEXT: ret void 817; 818entry: 819 %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len 820 %len.neg = icmp slt i16 %len, 0 821 br i1 %len.neg, label %exit, label %loop.ph 822 823loop.ph: 824 br label %loop.header 825 826loop.header: 827 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 828 %c = icmp eq ptr %ptr.iv, %upper 829 br i1 %c, label %exit, label %for.body 830 831for.body: 832 %c.1 = call i1 @cond() 833 br i1 %c.1, label %loop.next, label %exit 834 835loop.next: 836 %t.1 = icmp uge ptr %ptr.iv, %start 837 %t.2 = icmp ult ptr %ptr.iv, %upper 838 %and = and i1 %t.1, %t.2 839 br i1 %and, label %loop.latch, label %exit 840 841loop.latch: 842 call void @use(ptr %ptr.iv) 843 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 2 844 br label %loop.header 845 846exit: 847 ret void 848} 849 850define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32(ptr %start, i16 %len) { 851; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32( 852; CHECK-NEXT: entry: 853; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]] 854; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 855; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 856; CHECK: loop.ph: 857; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 858; CHECK: loop.header: 859; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 860; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 861; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 862; CHECK: for.body: 863; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 864; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 865; CHECK: loop.next: 866; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 867; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 868; CHECK: loop.latch: 869; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 870; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1 871; CHECK-NEXT: br label [[LOOP_HEADER]] 872; CHECK: exit: 873; CHECK-NEXT: ret void 874; 875entry: 876 %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len 877 %len.neg = icmp slt i16 %len, 0 878 br i1 %len.neg, label %exit, label %loop.ph 879 880loop.ph: 881 br label %loop.header 882 883loop.header: 884 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 885 %c = icmp eq ptr %ptr.iv, %upper 886 br i1 %c, label %exit, label %for.body 887 888for.body: 889 %c.1 = call i1 @cond() 890 br i1 %c.1, label %loop.next, label %exit 891 892loop.next: 893 %t.1 = icmp uge ptr %ptr.iv, %start 894 %t.2 = icmp ult ptr %ptr.iv, %upper 895 %and = and i1 %t.1, %t.2 896 br i1 %and, label %loop.latch, label %exit 897 898loop.latch: 899 call void @use(ptr %ptr.iv) 900 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1 901 br label %loop.header 902 903exit: 904 ret void 905} 906 907define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32_2(ptr %start, i16 %len) { 908; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32_2( 909; CHECK-NEXT: entry: 910; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]] 911; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 912; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 913; CHECK: loop.ph: 914; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 915; CHECK: loop.header: 916; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 917; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 918; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 919; CHECK: for.body: 920; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 921; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 922; CHECK: loop.next: 923; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 924; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 925; CHECK: loop.latch: 926; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 927; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 2 928; CHECK-NEXT: br label [[LOOP_HEADER]] 929; CHECK: exit: 930; CHECK-NEXT: ret void 931; 932entry: 933 %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len 934 %len.neg = icmp slt i16 %len, 0 935 br i1 %len.neg, label %exit, label %loop.ph 936 937loop.ph: 938 br label %loop.header 939 940loop.header: 941 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 942 %c = icmp eq ptr %ptr.iv, %upper 943 br i1 %c, label %exit, label %for.body 944 945for.body: 946 %c.1 = call i1 @cond() 947 br i1 %c.1, label %loop.next, label %exit 948 949loop.next: 950 %t.1 = icmp uge ptr %ptr.iv, %start 951 %t.2 = icmp ult ptr %ptr.iv, %upper 952 %and = and i1 %t.1, %t.2 953 br i1 %and, label %loop.latch, label %exit 954 955loop.latch: 956 call void @use(ptr %ptr.iv) 957 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 2 958 br label %loop.header 959 960exit: 961 ret void 962} 963 964define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_64(ptr %start, i16 %len) { 965; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_64( 966; CHECK-NEXT: entry: 967; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]] 968; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 969; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 970; CHECK: loop.ph: 971; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 972; CHECK: loop.header: 973; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 974; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 975; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 976; CHECK: for.body: 977; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 978; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 979; CHECK: loop.next: 980; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 981; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 982; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 983; CHECK: loop.latch: 984; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 985; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i16 1 986; CHECK-NEXT: br label [[LOOP_HEADER]] 987; CHECK: exit: 988; CHECK-NEXT: ret void 989; 990entry: 991 %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len 992 %len.neg = icmp slt i16 %len, 0 993 br i1 %len.neg, label %exit, label %loop.ph 994 995loop.ph: 996 br label %loop.header 997 998loop.header: 999 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 1000 %c = icmp eq ptr %ptr.iv, %upper 1001 br i1 %c, label %exit, label %for.body 1002 1003for.body: 1004 %c.1 = call i1 @cond() 1005 br i1 %c.1, label %loop.next, label %exit 1006 1007loop.next: 1008 %t.1 = icmp uge ptr %ptr.iv, %start 1009 %t.2 = icmp ult ptr %ptr.iv, %upper 1010 %and = and i1 %t.1, %t.2 1011 br i1 %and, label %loop.latch, label %exit 1012 1013loop.latch: 1014 call void @use(ptr %ptr.iv) 1015 %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i16 1 1016 br label %loop.header 1017 1018exit: 1019 ret void 1020} 1021 1022define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_var(ptr %start, i16 %len, i16 %step) { 1023; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_var( 1024; CHECK-NEXT: entry: 1025; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]] 1026; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 1027; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 1028; CHECK: loop.ph: 1029; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1030; CHECK: loop.header: 1031; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1032; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 1033; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 1034; CHECK: for.body: 1035; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 1036; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 1037; CHECK: loop.next: 1038; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]] 1039; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 1040; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]] 1041; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 1042; CHECK: loop.latch: 1043; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 1044; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 [[STEP:%.*]] 1045; CHECK-NEXT: br label [[LOOP_HEADER]] 1046; CHECK: exit: 1047; CHECK-NEXT: ret void 1048; 1049entry: 1050 %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len 1051 %len.neg = icmp slt i16 %len, 0 1052 br i1 %len.neg, label %exit, label %loop.ph 1053 1054loop.ph: 1055 br label %loop.header 1056 1057loop.header: 1058 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 1059 %c = icmp eq ptr %ptr.iv, %upper 1060 br i1 %c, label %exit, label %for.body 1061 1062for.body: 1063 %c.1 = call i1 @cond() 1064 br i1 %c.1, label %loop.next, label %exit 1065 1066loop.next: 1067 %t.1 = icmp uge ptr %ptr.iv, %start 1068 %t.2 = icmp ult ptr %ptr.iv, %upper 1069 %and = and i1 %t.1, %t.2 1070 br i1 %and, label %loop.latch, label %exit 1071 1072loop.latch: 1073 call void @use(ptr %ptr.iv) 1074 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 %step 1075 br label %loop.header 1076 1077exit: 1078 ret void 1079} 1080 1081define void @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_48(ptr %start, i16 %len) { 1082; CHECK-LABEL: @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_48( 1083; CHECK-NEXT: entry: 1084; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]] 1085; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 1086; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 1087; CHECK: loop.ph: 1088; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1089; CHECK: loop.header: 1090; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1091; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 1092; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 1093; CHECK: for.body: 1094; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 1095; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 1096; CHECK: loop.next: 1097; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 1098; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 1099; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 1100; CHECK: loop.latch: 1101; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 1102; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i16, i16 }, ptr [[PTR_IV]], i16 1, i32 0 1103; CHECK-NEXT: br label [[LOOP_HEADER]] 1104; CHECK: exit: 1105; CHECK-NEXT: ret void 1106; 1107entry: 1108 %upper = getelementptr inbounds i64, ptr %start, i16 %len 1109 %len.neg = icmp slt i16 %len, 0 1110 br i1 %len.neg, label %exit, label %loop.ph 1111 1112loop.ph: 1113 br label %loop.header 1114 1115loop.header: 1116 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 1117 %c = icmp eq ptr %ptr.iv, %upper 1118 br i1 %c, label %exit, label %for.body 1119 1120for.body: 1121 %c.1 = call i1 @cond() 1122 br i1 %c.1, label %loop.next, label %exit 1123 1124loop.next: 1125 %t.1 = icmp uge ptr %ptr.iv, %start 1126 %t.2 = icmp ult ptr %ptr.iv, %upper 1127 %and = and i1 %t.1, %t.2 1128 br i1 %and, label %loop.latch, label %exit 1129 1130loop.latch: 1131 call void @use(ptr %ptr.iv) 1132 %ptr.iv.next = getelementptr inbounds { i16, i16, i16 }, ptr %ptr.iv, i16 1, i32 0 1133 br label %loop.header 1134 1135exit: 1136 ret void 1137} 1138 1139define void @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_64(ptr %start, i16 %len) { 1140; CHECK-LABEL: @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_64( 1141; CHECK-NEXT: entry: 1142; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]] 1143; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 1144; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 1145; CHECK: loop.ph: 1146; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1147; CHECK: loop.header: 1148; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1149; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 1150; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 1151; CHECK: for.body: 1152; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 1153; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 1154; CHECK: loop.next: 1155; CHECK-NEXT: [[AND:%.*]] = and i1 true, true 1156; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 1157; CHECK: loop.latch: 1158; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 1159; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i16, i16 }, ptr [[PTR_IV]], i16 1, i32 1 1160; CHECK-NEXT: br label [[LOOP_HEADER]] 1161; CHECK: exit: 1162; CHECK-NEXT: ret void 1163; 1164entry: 1165 %upper = getelementptr inbounds i64, ptr %start, i16 %len 1166 %len.neg = icmp slt i16 %len, 0 1167 br i1 %len.neg, label %exit, label %loop.ph 1168 1169loop.ph: 1170 br label %loop.header 1171 1172loop.header: 1173 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 1174 %c = icmp eq ptr %ptr.iv, %upper 1175 br i1 %c, label %exit, label %for.body 1176 1177for.body: 1178 %c.1 = call i1 @cond() 1179 br i1 %c.1, label %loop.next, label %exit 1180 1181loop.next: 1182 %t.1 = icmp uge ptr %ptr.iv, %start 1183 %t.2 = icmp ult ptr %ptr.iv, %upper 1184 %and = and i1 %t.1, %t.2 1185 br i1 %and, label %loop.latch, label %exit 1186 1187loop.latch: 1188 call void @use(ptr %ptr.iv) 1189 %ptr.iv.next = getelementptr inbounds { i16, i16, i16 }, ptr %ptr.iv, i16 1, i32 1 1190 br label %loop.header 1191 1192exit: 1193 ret void 1194} 1195 1196define void @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_80(ptr %start, i16 %len) { 1197; CHECK-LABEL: @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_80( 1198; CHECK-NEXT: entry: 1199; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]] 1200; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0 1201; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]] 1202; CHECK: loop.ph: 1203; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 1204; CHECK: loop.header: 1205; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 1206; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]] 1207; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]] 1208; CHECK: for.body: 1209; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() 1210; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]] 1211; CHECK: loop.next: 1212; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]] 1213; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]] 1214; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]] 1215; CHECK: loop.latch: 1216; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) 1217; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i16, i16 }, ptr [[PTR_IV]], i16 1, i32 2 1218; CHECK-NEXT: br label [[LOOP_HEADER]] 1219; CHECK: exit: 1220; CHECK-NEXT: ret void 1221; 1222entry: 1223 %upper = getelementptr inbounds i64, ptr %start, i16 %len 1224 %len.neg = icmp slt i16 %len, 0 1225 br i1 %len.neg, label %exit, label %loop.ph 1226 1227loop.ph: 1228 br label %loop.header 1229 1230loop.header: 1231 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ] 1232 %c = icmp eq ptr %ptr.iv, %upper 1233 br i1 %c, label %exit, label %for.body 1234 1235for.body: 1236 %c.1 = call i1 @cond() 1237 br i1 %c.1, label %loop.next, label %exit 1238 1239loop.next: 1240 %t.1 = icmp uge ptr %ptr.iv, %start 1241 %t.2 = icmp ult ptr %ptr.iv, %upper 1242 %and = and i1 %t.1, %t.2 1243 br i1 %and, label %loop.latch, label %exit 1244 1245loop.latch: 1246 call void @use(ptr %ptr.iv) 1247 %ptr.iv.next = getelementptr inbounds { i16, i16, i16 }, ptr %ptr.iv, i16 1, i32 2 1248 br label %loop.header 1249 1250exit: 1251 ret void 1252} 1253