1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4define void @int_iv_nuw(i64 %base, i64 %end) { 5; CHECK-LABEL: define void @int_iv_nuw( 6; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 7; CHECK-NEXT: entry: 8; CHECK-NEXT: br label [[LOOP:%.*]] 9; CHECK: loop: 10; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 11; CHECK-NEXT: [[IV2:%.*]] = add nuw i64 [[IV]], [[BASE]] 12; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 13; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 14; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 15; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 16; CHECK: exit: 17; CHECK-NEXT: ret void 18; 19entry: 20 br label %loop 21 22loop: 23 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 24 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 25 call void @use.i64(i64 %iv2) 26 %iv.next = add nuw nsw i64 %iv, 4 27 %iv2.next = add nuw i64 %iv.next, %base 28 %cmp = icmp eq i64 %iv.next, %end 29 br i1 %cmp, label %exit, label %loop 30 31exit: 32 ret void 33} 34 35define void @int_iv_nsw(i64 %base, i64 %end) { 36; CHECK-LABEL: define void @int_iv_nsw( 37; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 38; CHECK-NEXT: entry: 39; CHECK-NEXT: br label [[LOOP:%.*]] 40; CHECK: loop: 41; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 42; CHECK-NEXT: [[IV2:%.*]] = add nsw i64 [[IV]], [[BASE]] 43; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 44; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 45; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 46; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 47; CHECK: exit: 48; CHECK-NEXT: ret void 49; 50entry: 51 br label %loop 52 53loop: 54 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 55 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 56 call void @use.i64(i64 %iv2) 57 %iv.next = add nuw nsw i64 %iv, 4 58 %iv2.next = add nsw i64 %iv.next, %base 59 %cmp = icmp eq i64 %iv.next, %end 60 br i1 %cmp, label %exit, label %loop 61 62exit: 63 ret void 64} 65 66define void @int_iv_commuted_add(i64 %base, i64 %end) { 67; CHECK-LABEL: define void @int_iv_commuted_add( 68; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 69; CHECK-NEXT: entry: 70; CHECK-NEXT: [[BASE2:%.*]] = mul i64 [[BASE]], 42 71; CHECK-NEXT: br label [[LOOP:%.*]] 72; CHECK: loop: 73; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 74; CHECK-NEXT: [[IV2:%.*]] = add i64 [[IV]], [[BASE2]] 75; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 76; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 77; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 78; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 79; CHECK: exit: 80; CHECK-NEXT: ret void 81; 82entry: 83 %base2 = mul i64 %base, 42 ; thwart complexity-based canonicalization 84 br label %loop 85 86loop: 87 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base2, %entry ] 88 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 89 call void @use.i64(i64 %iv2) 90 %iv.next = add nuw nsw i64 %iv, 4 91 %iv2.next = add i64 %base2, %iv.next 92 %cmp = icmp eq i64 %iv.next, %end 93 br i1 %cmp, label %exit, label %loop 94 95exit: 96 ret void 97} 98 99define void @int_iv_commuted_phi1(i64 %base, i64 %end) { 100; CHECK-LABEL: define void @int_iv_commuted_phi1( 101; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 102; CHECK-NEXT: entry: 103; CHECK-NEXT: br label [[LOOP:%.*]] 104; CHECK: loop: 105; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 106; CHECK-NEXT: [[IV2:%.*]] = add i64 [[IV]], [[BASE]] 107; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 108; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 109; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 110; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 111; CHECK: exit: 112; CHECK-NEXT: ret void 113; 114entry: 115 br label %loop 116 117loop: 118 %iv2 = phi i64 [ %base, %entry ], [ %iv2.next, %loop ] 119 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 120 call void @use.i64(i64 %iv2) 121 %iv.next = add nuw nsw i64 %iv, 4 122 %iv2.next = add i64 %iv.next, %base 123 %cmp = icmp eq i64 %iv.next, %end 124 br i1 %cmp, label %exit, label %loop 125 126exit: 127 ret void 128} 129 130define void @int_iv_commuted_phi2(i64 %base, i64 %end) { 131; CHECK-LABEL: define void @int_iv_commuted_phi2( 132; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 133; CHECK-NEXT: entry: 134; CHECK-NEXT: br label [[LOOP:%.*]] 135; CHECK: loop: 136; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 137; CHECK-NEXT: [[IV2:%.*]] = add i64 [[IV]], [[BASE]] 138; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 139; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 140; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 141; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 142; CHECK: exit: 143; CHECK-NEXT: ret void 144; 145entry: 146 br label %loop 147 148loop: 149 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 150 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 151 call void @use.i64(i64 %iv2) 152 %iv.next = add nuw nsw i64 %iv, 4 153 %iv2.next = add i64 %iv.next, %base 154 %cmp = icmp eq i64 %iv.next, %end 155 br i1 %cmp, label %exit, label %loop 156 157exit: 158 ret void 159} 160 161define void @int_iv_vector(<2 x i64> %base) { 162; CHECK-LABEL: define void @int_iv_vector( 163; CHECK-SAME: <2 x i64> [[BASE:%.*]]) { 164; CHECK-NEXT: entry: 165; CHECK-NEXT: br label [[LOOP:%.*]] 166; CHECK: loop: 167; CHECK-NEXT: [[IV:%.*]] = phi <2 x i64> [ [[IV_NEXT:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ] 168; CHECK-NEXT: [[IV2:%.*]] = add <2 x i64> [[IV]], [[BASE]] 169; CHECK-NEXT: call void @use.v2i64(<2 x i64> [[IV2]]) 170; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw <2 x i64> [[IV]], splat (i64 4) 171; CHECK-NEXT: [[CMP:%.*]] = call i1 @get.i1() 172; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 173; CHECK: exit: 174; CHECK-NEXT: ret void 175; 176entry: 177 br label %loop 178 179loop: 180 %iv2 = phi <2 x i64> [ %iv2.next, %loop ], [ %base, %entry ] 181 %iv = phi <2 x i64> [ %iv.next, %loop ], [ zeroinitializer, %entry ] 182 call void @use.v2i64(<2 x i64> %iv2) 183 %iv.next = add nuw nsw <2 x i64> %iv, <i64 4, i64 4> 184 %iv2.next = add <2 x i64> %iv.next, %base 185 %cmp = call i1 @get.i1() 186 br i1 %cmp, label %exit, label %loop 187 188exit: 189 ret void 190} 191 192define void @int_iv_vector_poison_invalid(<2 x i64> %base) { 193; CHECK-LABEL: define void @int_iv_vector_poison_invalid( 194; CHECK-SAME: <2 x i64> [[BASE:%.*]]) { 195; CHECK-NEXT: entry: 196; CHECK-NEXT: br label [[LOOP:%.*]] 197; CHECK: loop: 198; CHECK-NEXT: [[IV2:%.*]] = phi <2 x i64> [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ] 199; CHECK-NEXT: [[IV:%.*]] = phi <2 x i64> [ [[IV_NEXT:%.*]], [[LOOP]] ], [ <i64 0, i64 poison>, [[ENTRY]] ] 200; CHECK-NEXT: call void @use.v2i64(<2 x i64> [[IV2]]) 201; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw <2 x i64> [[IV]], splat (i64 4) 202; CHECK-NEXT: [[IV2_NEXT]] = add <2 x i64> [[IV_NEXT]], [[BASE]] 203; CHECK-NEXT: [[CMP:%.*]] = call i1 @get.i1() 204; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 205; CHECK: exit: 206; CHECK-NEXT: ret void 207; 208entry: 209 br label %loop 210 211loop: 212 %iv2 = phi <2 x i64> [ %iv2.next, %loop ], [ %base, %entry ] 213 %iv = phi <2 x i64> [ %iv.next, %loop ], [ <i64 0, i64 poison>, %entry ] 214 call void @use.v2i64(<2 x i64> %iv2) 215 %iv.next = add nuw nsw <2 x i64> %iv, <i64 4, i64 4> 216 %iv2.next = add <2 x i64> %iv.next, %base 217 %cmp = call i1 @get.i1() 218 br i1 %cmp, label %exit, label %loop 219 220exit: 221 ret void 222} 223 224define void @int_iv_loop_variant_step(i64 %base, i64 %end) { 225; CHECK-LABEL: define void @int_iv_loop_variant_step( 226; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 227; CHECK-NEXT: entry: 228; CHECK-NEXT: br label [[LOOP:%.*]] 229; CHECK: loop: 230; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 231; CHECK-NEXT: [[IV2:%.*]] = add nuw i64 [[IV]], [[BASE]] 232; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 233; CHECK-NEXT: [[STEP:%.*]] = call i64 @get.i64() 234; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], [[STEP]] 235; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 236; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 237; CHECK: exit: 238; CHECK-NEXT: ret void 239; 240entry: 241 br label %loop 242 243loop: 244 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 245 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 246 call void @use.i64(i64 %iv2) 247 %step = call i64 @get.i64() 248 %iv.next = add nuw nsw i64 %iv, %step 249 %iv2.next = add nuw i64 %iv.next, %base 250 %cmp = icmp eq i64 %iv.next, %end 251 br i1 %cmp, label %exit, label %loop 252 253exit: 254 ret void 255} 256 257define void @int_iv_xor(i64 %base, i64 %end) { 258; CHECK-LABEL: define void @int_iv_xor( 259; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 260; CHECK-NEXT: entry: 261; CHECK-NEXT: br label [[LOOP:%.*]] 262; CHECK: loop: 263; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 264; CHECK-NEXT: [[IV2:%.*]] = xor i64 [[IV]], [[BASE]] 265; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 266; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 267; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 268; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 269; CHECK: exit: 270; CHECK-NEXT: ret void 271; 272entry: 273 br label %loop 274 275loop: 276 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 277 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 278 call void @use.i64(i64 %iv2) 279 %iv.next = add nuw nsw i64 %iv, 4 280 %iv2.next = xor i64 %iv.next, %base 281 %cmp = icmp eq i64 %iv.next, %end 282 br i1 %cmp, label %exit, label %loop 283 284exit: 285 ret void 286} 287 288define void @int_iv_or(i64 %base, i64 %end) { 289; CHECK-LABEL: define void @int_iv_or( 290; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 291; CHECK-NEXT: entry: 292; CHECK-NEXT: br label [[LOOP:%.*]] 293; CHECK: loop: 294; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 295; CHECK-NEXT: [[IV2:%.*]] = or i64 [[IV]], [[BASE]] 296; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 297; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 298; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 299; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 300; CHECK: exit: 301; CHECK-NEXT: ret void 302; 303entry: 304 br label %loop 305 306loop: 307 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 308 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 309 call void @use.i64(i64 %iv2) 310 %iv.next = add nuw nsw i64 %iv, 4 311 %iv2.next = or i64 %iv.next, %base 312 %cmp = icmp eq i64 %iv.next, %end 313 br i1 %cmp, label %exit, label %loop 314 315exit: 316 ret void 317} 318 319define void @int_iv_or_disjoint(i64 %base, i64 %end) { 320; CHECK-LABEL: define void @int_iv_or_disjoint( 321; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 322; CHECK-NEXT: entry: 323; CHECK-NEXT: br label [[LOOP:%.*]] 324; CHECK: loop: 325; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 326; CHECK-NEXT: [[IV2:%.*]] = or disjoint i64 [[IV]], [[BASE]] 327; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 328; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 329; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 330; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 331; CHECK: exit: 332; CHECK-NEXT: ret void 333; 334entry: 335 br label %loop 336 337loop: 338 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 339 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 340 call void @use.i64(i64 %iv2) 341 %iv.next = add nuw nsw i64 %iv, 4 342 %iv2.next = or disjoint i64 %iv.next, %base 343 %cmp = icmp eq i64 %iv.next, %end 344 br i1 %cmp, label %exit, label %loop 345 346exit: 347 ret void 348} 349 350define void @int_iv_and(i64 %base, i64 %end) { 351; CHECK-LABEL: define void @int_iv_and( 352; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 353; CHECK-NEXT: entry: 354; CHECK-NEXT: br label [[LOOP:%.*]] 355; CHECK: loop: 356; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ -1, [[ENTRY:%.*]] ] 357; CHECK-NEXT: [[IV2:%.*]] = and i64 [[IV]], [[BASE]] 358; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 359; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 360; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 361; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 362; CHECK: exit: 363; CHECK-NEXT: ret void 364; 365entry: 366 br label %loop 367 368loop: 369 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 370 %iv = phi i64 [ %iv.next, %loop ], [ -1, %entry ] 371 call void @use.i64(i64 %iv2) 372 %iv.next = add nuw nsw i64 %iv, 4 373 %iv2.next = and i64 %iv.next, %base 374 %cmp = icmp eq i64 %iv.next, %end 375 br i1 %cmp, label %exit, label %loop 376 377exit: 378 ret void 379} 380 381define void @int_iv_sub(i64 %base, i64 %end) { 382; CHECK-LABEL: define void @int_iv_sub( 383; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 384; CHECK-NEXT: entry: 385; CHECK-NEXT: br label [[LOOP:%.*]] 386; CHECK: loop: 387; CHECK-NEXT: [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ] 388; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ] 389; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 390; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 391; CHECK-NEXT: [[IV2_NEXT]] = sub i64 [[BASE]], [[IV_NEXT]] 392; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 393; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 394; CHECK: exit: 395; CHECK-NEXT: ret void 396; 397entry: 398 br label %loop 399 400loop: 401 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 402 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 403 call void @use.i64(i64 %iv2) 404 %iv.next = add nuw nsw i64 %iv, 4 405 %iv2.next = sub i64 %base, %iv.next 406 %cmp = icmp eq i64 %iv.next, %end 407 br i1 %cmp, label %exit, label %loop 408 409exit: 410 ret void 411} 412 413define void @int_iv_sub_invalid_order(i64 %base, i64 %end) { 414; CHECK-LABEL: define void @int_iv_sub_invalid_order( 415; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 416; CHECK-NEXT: entry: 417; CHECK-NEXT: br label [[LOOP:%.*]] 418; CHECK: loop: 419; CHECK-NEXT: [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ] 420; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ] 421; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 422; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 423; CHECK-NEXT: [[IV2_NEXT]] = sub i64 [[IV_NEXT]], [[BASE]] 424; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 425; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 426; CHECK: exit: 427; CHECK-NEXT: ret void 428; 429entry: 430 br label %loop 431 432loop: 433 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 434 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 435 call void @use.i64(i64 %iv2) 436 %iv.next = add nuw nsw i64 %iv, 4 437 %iv2.next = sub i64 %iv.next, %base 438 %cmp = icmp eq i64 %iv.next, %end 439 br i1 %cmp, label %exit, label %loop 440 441exit: 442 ret void 443} 444 445define void @int_iv_add_wrong_start(i64 %base, i64 %end) { 446; CHECK-LABEL: define void @int_iv_add_wrong_start( 447; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 448; CHECK-NEXT: entry: 449; CHECK-NEXT: br label [[LOOP:%.*]] 450; CHECK: loop: 451; CHECK-NEXT: [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ] 452; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 1, [[ENTRY]] ] 453; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 454; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 455; CHECK-NEXT: [[IV2_NEXT]] = add i64 [[BASE]], [[IV_NEXT]] 456; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 457; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 458; CHECK: exit: 459; CHECK-NEXT: ret void 460; 461entry: 462 br label %loop 463 464loop: 465 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 466 %iv = phi i64 [ %iv.next, %loop ], [ 1, %entry ] 467 call void @use.i64(i64 %iv2) 468 %iv.next = add nuw nsw i64 %iv, 4 469 %iv2.next = add i64 %base, %iv.next 470 %cmp = icmp eq i64 %iv.next, %end 471 br i1 %cmp, label %exit, label %loop 472 473exit: 474 ret void 475} 476 477define void @int_iv_and_wrong_start(i64 %base, i64 %end) { 478; CHECK-LABEL: define void @int_iv_and_wrong_start( 479; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) { 480; CHECK-NEXT: entry: 481; CHECK-NEXT: br label [[LOOP:%.*]] 482; CHECK: loop: 483; CHECK-NEXT: [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ] 484; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ] 485; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 486; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 487; CHECK-NEXT: [[IV2_NEXT]] = and i64 [[IV_NEXT]], [[BASE]] 488; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 489; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 490; CHECK: exit: 491; CHECK-NEXT: ret void 492; 493entry: 494 br label %loop 495 496loop: 497 %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ] 498 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 499 call void @use.i64(i64 %iv2) 500 %iv.next = add nuw nsw i64 %iv, 4 501 %iv2.next = and i64 %iv.next, %base 502 %cmp = icmp eq i64 %iv.next, %end 503 br i1 %cmp, label %exit, label %loop 504 505exit: 506 ret void 507} 508 509define void @ptr_iv_inbounds(ptr %base, i64 %end) { 510; CHECK-LABEL: define void @ptr_iv_inbounds( 511; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) { 512; CHECK-NEXT: entry: 513; CHECK-NEXT: br label [[LOOP:%.*]] 514; CHECK: loop: 515; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 516; CHECK-NEXT: [[IV_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE]], i64 [[IV]] 517; CHECK-NEXT: call void @use.p0(ptr [[IV_PTR]]) 518; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 519; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 520; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 521; CHECK: exit: 522; CHECK-NEXT: ret void 523; 524entry: 525 br label %loop 526 527loop: 528 %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ] 529 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 530 call void @use.p0(ptr %iv.ptr) 531 %iv.next = add nuw nsw i64 %iv, 4 532 %iv.ptr.next = getelementptr inbounds i8, ptr %base, i64 %iv.next 533 %cmp = icmp eq i64 %iv.next, %end 534 br i1 %cmp, label %exit, label %loop 535 536exit: 537 ret void 538} 539 540define void @ptr_iv_nuw(ptr %base, i64 %end) { 541; CHECK-LABEL: define void @ptr_iv_nuw( 542; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) { 543; CHECK-NEXT: entry: 544; CHECK-NEXT: br label [[LOOP:%.*]] 545; CHECK: loop: 546; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 547; CHECK-NEXT: [[IV_PTR:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 [[IV]] 548; CHECK-NEXT: call void @use.p0(ptr [[IV_PTR]]) 549; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 550; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 551; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 552; CHECK: exit: 553; CHECK-NEXT: ret void 554; 555entry: 556 br label %loop 557 558loop: 559 %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ] 560 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 561 call void @use.p0(ptr %iv.ptr) 562 %iv.next = add nuw nsw i64 %iv, 4 563 %iv.ptr.next = getelementptr nuw i8, ptr %base, i64 %iv.next 564 %cmp = icmp eq i64 %iv.next, %end 565 br i1 %cmp, label %exit, label %loop 566 567exit: 568 ret void 569} 570 571define void @ptr_iv_no_flags(ptr %base, i64 %end) { 572; CHECK-LABEL: define void @ptr_iv_no_flags( 573; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) { 574; CHECK-NEXT: entry: 575; CHECK-NEXT: br label [[LOOP:%.*]] 576; CHECK: loop: 577; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 578; CHECK-NEXT: [[IV_PTR:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[IV]] 579; CHECK-NEXT: call void @use.p0(ptr [[IV_PTR]]) 580; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 581; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 582; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 583; CHECK: exit: 584; CHECK-NEXT: ret void 585; 586entry: 587 br label %loop 588 589loop: 590 %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ] 591 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 592 call void @use.p0(ptr %iv.ptr) 593 %iv.next = add nuw nsw i64 %iv, 4 594 %iv.ptr.next = getelementptr i8, ptr %base, i64 %iv.next 595 %cmp = icmp eq i64 %iv.next, %end 596 br i1 %cmp, label %exit, label %loop 597 598exit: 599 ret void 600} 601 602define void @ptr_iv_non_i8_type(ptr %base, i64 %end) { 603; CHECK-LABEL: define void @ptr_iv_non_i8_type( 604; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) { 605; CHECK-NEXT: entry: 606; CHECK-NEXT: br label [[LOOP:%.*]] 607; CHECK: loop: 608; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 609; CHECK-NEXT: [[IV_PTR:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[IV]] 610; CHECK-NEXT: call void @use.p0(ptr [[IV_PTR]]) 611; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 612; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 613; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 614; CHECK: exit: 615; CHECK-NEXT: ret void 616; 617entry: 618 br label %loop 619 620loop: 621 %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ] 622 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 623 call void @use.p0(ptr %iv.ptr) 624 %iv.next = add nuw nsw i64 %iv, 4 625 %iv.ptr.next = getelementptr i32, ptr %base, i64 %iv.next 626 %cmp = icmp eq i64 %iv.next, %end 627 br i1 %cmp, label %exit, label %loop 628 629exit: 630 ret void 631} 632 633define void @ptr_iv_vector(<2 x ptr> %base, i64 %end) { 634; CHECK-LABEL: define void @ptr_iv_vector( 635; CHECK-SAME: <2 x ptr> [[BASE:%.*]], i64 [[END:%.*]]) { 636; CHECK-NEXT: entry: 637; CHECK-NEXT: br label [[LOOP:%.*]] 638; CHECK: loop: 639; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 640; CHECK-NEXT: [[IV_PTR:%.*]] = getelementptr inbounds i8, <2 x ptr> [[BASE]], i64 [[IV]] 641; CHECK-NEXT: call void @use.v2p0(<2 x ptr> [[IV_PTR]]) 642; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 643; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]] 644; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 645; CHECK: exit: 646; CHECK-NEXT: ret void 647; 648entry: 649 br label %loop 650 651loop: 652 %iv.ptr = phi <2 x ptr> [ %iv.ptr.next, %loop ], [ %base, %entry ] 653 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 654 call void @use.v2p0(<2 x ptr> %iv.ptr) 655 %iv.next = add nuw nsw i64 %iv, 4 656 %iv.ptr.next = getelementptr inbounds i8, <2 x ptr> %base, i64 %iv.next 657 %cmp = icmp eq i64 %iv.next, %end 658 br i1 %cmp, label %exit, label %loop 659 660exit: 661 ret void 662} 663 664define void @ptr_iv_vector2(<2 x ptr> %base) { 665; CHECK-LABEL: define void @ptr_iv_vector2( 666; CHECK-SAME: <2 x ptr> [[BASE:%.*]]) { 667; CHECK-NEXT: entry: 668; CHECK-NEXT: br label [[LOOP:%.*]] 669; CHECK: loop: 670; CHECK-NEXT: [[IV:%.*]] = phi <2 x i64> [ [[IV_NEXT:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ] 671; CHECK-NEXT: [[IV_PTR:%.*]] = getelementptr i8, <2 x ptr> [[BASE]], <2 x i64> [[IV]] 672; CHECK-NEXT: call void @use.v2p0(<2 x ptr> [[IV_PTR]]) 673; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw <2 x i64> [[IV]], splat (i64 4) 674; CHECK-NEXT: [[CMP:%.*]] = call i1 @get.i1() 675; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 676; CHECK: exit: 677; CHECK-NEXT: ret void 678; 679entry: 680 br label %loop 681 682loop: 683 %iv.ptr = phi <2 x ptr> [ %iv.ptr.next, %loop ], [ %base, %entry ] 684 %iv = phi <2 x i64> [ %iv.next, %loop ], [ zeroinitializer, %entry ] 685 call void @use.v2p0(<2 x ptr> %iv.ptr) 686 %iv.next = add nuw nsw <2 x i64> %iv, <i64 4, i64 4> 687 %iv.ptr.next = getelementptr i8, <2 x ptr> %base, <2 x i64> %iv.next 688 %cmp = call i1 @get.i1() 689 br i1 %cmp, label %exit, label %loop 690 691exit: 692 ret void 693} 694 695define void @different_loops(i64 %base) { 696; CHECK-LABEL: define void @different_loops( 697; CHECK-SAME: i64 [[BASE:%.*]]) { 698; CHECK-NEXT: entry: 699; CHECK-NEXT: br label [[LOOP1:%.*]] 700; CHECK: loop1: 701; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP1]] ], [ 0, [[ENTRY:%.*]] ] 702; CHECK-NEXT: call void @use.i64(i64 [[IV]]) 703; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4 704; CHECK-NEXT: [[CMP:%.*]] = call i1 @get.i1() 705; CHECK-NEXT: br i1 [[CMP]], label [[LOOP2:%.*]], label [[LOOP1]] 706; CHECK: loop2: 707; CHECK-NEXT: [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP2]] ], [ [[BASE]], [[LOOP1]] ] 708; CHECK-NEXT: call void @use.i64(i64 [[IV2]]) 709; CHECK-NEXT: [[IV2_NEXT]] = add nuw i64 [[BASE]], [[IV_NEXT]] 710; CHECK-NEXT: [[CMP2:%.*]] = call i1 @get.i1() 711; CHECK-NEXT: br i1 [[CMP2]], label [[EXIT:%.*]], label [[LOOP2]] 712; CHECK: exit: 713; CHECK-NEXT: ret void 714; 715entry: 716 br label %loop1 717 718loop1: 719 %iv = phi i64 [ %iv.next, %loop1 ], [ 0, %entry ] 720 call void @use.i64(i64 %iv) 721 %iv.next = add nuw nsw i64 %iv, 4 722 %cmp = call i1 @get.i1() 723 br i1 %cmp, label %loop2, label %loop1 724 725loop2: 726 %iv2 = phi i64 [ %iv2.next, %loop2 ], [ %base, %loop1 ] 727 call void @use.i64(i64 %iv2) 728 %iv2.next = add nuw i64 %base, %iv.next 729 %cmp2 = call i1 @get.i1() 730 br i1 %cmp2, label %exit, label %loop2 731 732exit: 733 ret void 734} 735 736declare void @use.p0(ptr) 737declare void @use.v2p0(<2 x ptr>) 738declare void @use.i64(i64) 739declare void @use.v2i64(<2 x i64>) 740declare i1 @get.i1() 741declare i64 @get.i64() 742