1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes="loop-reduce,loop-term-fold" -S | FileCheck %s 3 4target datalayout = "e-p:64:64:64-n64" 5 6define void @const_tripcount(ptr %a) { 7; CHECK-LABEL: @const_tripcount( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 10; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600 11; CHECK-NEXT: br label [[FOR_BODY:%.*]] 12; CHECK: for.body: 13; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 14; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 15; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 16; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 17; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 18; CHECK: for.end: 19; CHECK-NEXT: ret void 20; 21entry: 22 %uglygep = getelementptr i8, ptr %a, i64 84 23 br label %for.body 24 25for.body: ; preds = %for.body, %entry 26 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 27 %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ 379, %entry ] 28 store i32 1, ptr %lsr.iv1, align 4 29 %lsr.iv.next = add nsw i64 %lsr.iv, -1 30 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 31 %exitcond.not = icmp eq i64 %lsr.iv.next, 0 32 br i1 %exitcond.not, label %for.end, label %for.body 33 34for.end: ; preds = %for.body 35 ret void 36} 37 38define void @runtime_tripcount(ptr %a, i32 %N) { 39; CHECK-LABEL: @runtime_tripcount( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84 42; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[N:%.*]], -1 43; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 44; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 2 45; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 88 46; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP3]] 47; CHECK-NEXT: br label [[FOR_BODY:%.*]] 48; CHECK: for.body: 49; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 50; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 51; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 52; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 53; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 54; CHECK: for.end: 55; CHECK-NEXT: ret void 56; 57entry: 58 %uglygep = getelementptr i8, ptr %a, i32 84 59 br label %for.body 60 61for.body: ; preds = %for.body, %entry 62 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 63 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ %N, %entry ] 64 store i32 1, ptr %lsr.iv1, align 4 65 %lsr.iv.next = add nsw i32 %lsr.iv, -1 66 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 67 %exitcond.not = icmp eq i32 %lsr.iv.next, 0 68 br i1 %exitcond.not, label %for.end, label %for.body 69 70for.end: ; preds = %for.body 71 ret void 72} 73 74; In this case, the i8 IVs increment *isn't* nsw. As a result, a N of 0 75; is well defined, and thus the post-inc starts at 255. 76define void @wrap_around(ptr %a, i8 %N) { 77; CHECK-LABEL: @wrap_around( 78; CHECK-NEXT: entry: 79; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N:%.*]], -1 80; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i64 81; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 2 82; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 4 83; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP3]] 84; CHECK-NEXT: br label [[FOR_BODY:%.*]] 85; CHECK: for.body: 86; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ] 87; CHECK-NEXT: store i8 1, ptr [[LSR_IV1]], align 4 88; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 89; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 90; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 91; CHECK: for.end: 92; CHECK-NEXT: ret void 93; 94entry: 95 br label %for.body 96 97for.body: ; preds = %for.body, %entry 98 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ] 99 %lsr.iv = phi i8 [ %lsr.iv.next, %for.body ], [ %N, %entry ] 100 store i8 1, ptr %lsr.iv1, align 4 101 %lsr.iv.next = add i8 %lsr.iv, -1 102 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 103 %exitcond.not = icmp eq i8 %lsr.iv.next, 0 104 br i1 %exitcond.not, label %for.end, label %for.body 105 106for.end: ; preds = %for.body 107 ret void 108} 109 110; The replacing AddRec IV is a complicated AddRec. This tests whether 111; the fold terminating condition transformation is writing new terminating 112; condition in the correct type. 113define void @ptr_of_ptr_addrec(ptr %ptrptr, i32 %length) { 114; CHECK-LABEL: @ptr_of_ptr_addrec( 115; CHECK-NEXT: entry: 116; CHECK-NEXT: [[START_PTRPTR1:%.*]] = getelementptr inbounds ptr, ptr [[START_PTRPTR:%.*]] 117; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 118; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 119; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 3 120; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 8 121; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[START_PTRPTR]], i64 [[TMP3]] 122; CHECK-NEXT: br label [[FOR_BODY:%.*]] 123; CHECK: for.body: 124; CHECK-NEXT: [[IT_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[START_PTRPTR1]], [[ENTRY:%.*]] ] 125; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[IT_04]], align 8 126; CHECK-NEXT: tail call void @foo(ptr [[TMP4]]) 127; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr ptr, ptr [[IT_04]], i64 1 128; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[SCEVGEP]] 129; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 130; CHECK: for.end: 131; CHECK-NEXT: ret void 132; 133entry: 134 %start.ptrptr = getelementptr inbounds ptr, ptr %ptrptr 135 br label %for.body 136 137for.body: ; preds = %entry, %for.body 138 %i.05 = phi i32 [ %dec, %for.body ], [ %length, %entry ] 139 %it.04 = phi ptr [ %incdec.ptr, %for.body ], [ %start.ptrptr, %entry ] 140 %0 = load ptr, ptr %it.04, align 8 141 tail call void @foo(ptr %0) 142 %incdec.ptr = getelementptr inbounds ptr, ptr %it.04, i64 1 143 %dec = add nsw i32 %i.05, -1 144 %tobool.not = icmp eq i32 %dec, 0 145 br i1 %tobool.not, label %for.end, label %for.body 146 147for.end: ; preds = %for.body 148 ret void 149} 150 151declare void @foo(ptr) 152 153define void @iv_start_non_preheader(ptr %mark, i32 signext %length) { 154; CHECK-LABEL: @iv_start_non_preheader( 155; CHECK-NEXT: entry: 156; CHECK-NEXT: [[TOBOOL_NOT3:%.*]] = icmp eq i32 [[LENGTH:%.*]], 0 157; CHECK-NEXT: br i1 [[TOBOOL_NOT3]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 158; CHECK: for.body.preheader: 159; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH]], -1 160; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 161; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 3 162; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 8 163; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[MARK:%.*]], i64 [[TMP3]] 164; CHECK-NEXT: br label [[FOR_BODY:%.*]] 165; CHECK: for.cond.cleanup.loopexit: 166; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 167; CHECK: for.cond.cleanup: 168; CHECK-NEXT: ret void 169; CHECK: for.body: 170; CHECK-NEXT: [[DST_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[MARK]], [[FOR_BODY_PREHEADER]] ] 171; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DST_04]], align 8 172; CHECK-NEXT: [[TMP5:%.*]] = call ptr @foo(ptr [[TMP4]]) 173; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr ptr, ptr [[DST_04]], i64 1 174; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[SCEVGEP]] 175; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] 176; 177entry: 178 %tobool.not3 = icmp eq i32 %length, 0 179 br i1 %tobool.not3, label %for.cond.cleanup, label %for.body 180 181for.cond.cleanup: ; preds = %for.body, %entry 182 ret void 183 184for.body: ; preds = %entry, %for.body 185 %i.05 = phi i32 [ %dec, %for.body ], [ %length, %entry ] 186 %dst.04 = phi ptr [ %incdec.ptr, %for.body ], [ %mark, %entry ] 187 %0 = load ptr, ptr %dst.04, align 8 188 call ptr @foo(ptr %0) 189 %incdec.ptr = getelementptr inbounds ptr, ptr %dst.04, i64 1 190 %dec = add nsw i32 %i.05, -1 191 %tobool.not = icmp eq i32 %dec, 0 192 br i1 %tobool.not, label %for.cond.cleanup, label %for.body 193} 194 195; Consider the case where %a points to a buffer exactly 17 bytes long. The 196; loop below will access bytes: 0, 4, 8, and 16. The key bit is that we 197; advance the pointer IV by *4* each time, and thus on the iteration we write 198; byte 16, %uglygep2 (the pointer increment) is past the end of the underlying 199; storage and thus violates the inbounds requirements. As a result, %uglygep2 200; is poison on the final iteration. If we insert a branch on that value 201; (without stripping the poison flag), we have inserted undefined behavior 202; where it did not previously exist. 203define void @inbounds_poison_use(ptr %a) { 204; CHECK-LABEL: @inbounds_poison_use( 205; CHECK-NEXT: entry: 206; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 16 207; CHECK-NEXT: br label [[FOR_BODY:%.*]] 208; CHECK: for.body: 209; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ] 210; CHECK-NEXT: store i8 1, ptr [[LSR_IV1]], align 4 211; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 212; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 213; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 214; CHECK: for.end: 215; CHECK-NEXT: ret void 216; 217entry: 218 br label %for.body 219 220for.body: ; preds = %for.body, %entry 221 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ] 222 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 4, %entry ] 223 store i8 1, ptr %lsr.iv1, align 4 224 %lsr.iv.next = add nsw i32 %lsr.iv, -1 225 %uglygep2 = getelementptr inbounds i8, ptr %lsr.iv1, i64 4 226 %exitcond.not = icmp eq i32 %lsr.iv.next, 0 227 br i1 %exitcond.not, label %for.end, label %for.body 228 229for.end: ; preds = %for.body 230 ret void 231} 232 233; In this case, the integer IV has a larger bitwidth than the pointer IV. 234; This means that the smaller IV may wrap around multiple times before 235; the original loop exit is taken. 236define void @iv_size(ptr %a, i128 %N) { 237; CHECK-LABEL: @iv_size( 238; CHECK-NEXT: entry: 239; CHECK-NEXT: br label [[FOR_BODY:%.*]] 240; CHECK: for.body: 241; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A:%.*]], [[ENTRY:%.*]] ] 242; CHECK-NEXT: [[LSR_IV:%.*]] = phi i128 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[N:%.*]], [[ENTRY]] ] 243; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 244; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i128 [[LSR_IV]], -1 245; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 246; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i128 [[LSR_IV_NEXT]], 0 247; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 248; CHECK: for.end: 249; CHECK-NEXT: ret void 250; 251entry: 252 br label %for.body 253 254for.body: ; preds = %for.body, %entry 255 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %a, %entry ] 256 %lsr.iv = phi i128 [ %lsr.iv.next, %for.body ], [ %N, %entry ] 257 store i32 1, ptr %lsr.iv1, align 4 258 %lsr.iv.next = add nsw i128 %lsr.iv, -1 259 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 260 %exitcond.not = icmp eq i128 %lsr.iv.next, 0 261 br i1 %exitcond.not, label %for.end, label %for.body 262 263for.end: ; preds = %for.body 264 ret void 265} 266 267; To check correct folding not equality terminating condition 268; Due to SLE offset must be - 1600 269define void @IcmpSle(ptr %a) { 270; CHECK-LABEL: @IcmpSle( 271; CHECK-NEXT: entry: 272; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84 273; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600 274; CHECK-NEXT: br label [[FOR_BODY:%.*]] 275; CHECK: for.body: 276; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 277; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 278; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4 279; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 280; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 281; CHECK: for.end: 282; CHECK-NEXT: ret void 283; 284entry: 285 %uglygep = getelementptr i8, ptr %a, i32 84 286 br label %for.body 287 288for.body: ; preds = %for.body, %entry 289 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 290 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 379, %entry ] 291 store i32 1, ptr %lsr.iv1, align 4 292 %lsr.iv.next = add nsw i32 %lsr.iv, -1 293 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4 294 %exitcond.not = icmp sle i32 %lsr.iv.next, 0 295 br i1 %exitcond.not, label %for.end, label %for.body 296 297for.end: ; preds = %for.body 298 ret void 299} 300 301; Due to SLT offset must be - 1604 302define void @IcmpSlt(ptr %a) { 303; CHECK-LABEL: @IcmpSlt( 304; CHECK-NEXT: entry: 305; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84 306; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1604 307; CHECK-NEXT: br label [[FOR_BODY:%.*]] 308; CHECK: for.body: 309; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 310; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 311; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4 312; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 313; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 314; CHECK: for.end: 315; CHECK-NEXT: ret void 316; 317entry: 318 %uglygep = getelementptr i8, ptr %a, i32 84 319 br label %for.body 320 321for.body: ; preds = %for.body, %entry 322 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 323 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 379, %entry ] 324 store i32 1, ptr %lsr.iv1, align 4 325 %lsr.iv.next = add nsw i32 %lsr.iv, -1 326 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4 327 %exitcond.not = icmp slt i32 %lsr.iv.next, 0 328 br i1 %exitcond.not, label %for.end, label %for.body 329 330for.end: ; preds = %for.body 331 ret void 332} 333 334; Invert predicate and branches 335define void @IcmpSgt(ptr %a) { 336; CHECK-LABEL: @IcmpSgt( 337; CHECK-NEXT: entry: 338; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84 339; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600 340; CHECK-NEXT: br label [[FOR_BODY:%.*]] 341; CHECK: for.body: 342; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 343; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 344; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4 345; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 346; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 347; CHECK: for.end: 348; CHECK-NEXT: ret void 349; 350entry: 351 %uglygep = getelementptr i8, ptr %a, i32 84 352 br label %for.body 353 354for.body: ; preds = %for.body, %entry 355 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 356 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 379, %entry ] 357 store i32 1, ptr %lsr.iv1, align 4 358 %lsr.iv.next = add nsw i32 %lsr.iv, -1 359 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4 360 %exitcond.not = icmp sgt i32 %lsr.iv.next, 0 361 br i1 %exitcond.not, label %for.body, label %for.end 362 363for.end: ; preds = %for.body 364 ret void 365} 366 367; Invert predicate and branches 368define void @SeveralLoopLatch(ptr %a) { 369; CHECK-LABEL: @SeveralLoopLatch( 370; CHECK-NEXT: entry: 371; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84 372; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600 373; CHECK-NEXT: br label [[FOR_BODY:%.*]] 374; CHECK: for.body: 375; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[ANOTHER_BRANCH:%.*]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 376; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 377; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4 378; CHECK-NEXT: br label [[ANOTHER_BRANCH]] 379; CHECK: another.branch: 380; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 381; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 382; CHECK: for.end: 383; CHECK-NEXT: ret void 384; 385entry: 386 %uglygep = getelementptr i8, ptr %a, i32 84 387 br label %for.body 388 389for.body: ; preds = %another.branch, %entry 390 %lsr.iv1 = phi ptr [ %uglygep2, %another.branch ], [ %uglygep, %entry ] 391 %lsr.iv = phi i32 [ %lsr.iv.next, %another.branch ], [ 379, %entry ] 392 store i32 1, ptr %lsr.iv1, align 4 393 %lsr.iv.next = add nsw i32 %lsr.iv, -1 394 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4 395 br label %another.branch 396 397another.branch: 398 %exitcond.not = icmp sgt i32 %lsr.iv.next, 0 399 br i1 %exitcond.not, label %for.body, label %for.end 400 401for.end: ; preds = %for.body 402 ret void 403} 404 405; Invert branch in SeveralLoopLatch 406define void @SeveralLoopLatch2(ptr %a) { 407; CHECK-LABEL: @SeveralLoopLatch2( 408; CHECK-NEXT: entry: 409; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84 410; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600 411; CHECK-NEXT: br label [[FOR_BODY:%.*]] 412; CHECK: for.body: 413; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[ANOTHER_BRANCH:%.*]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 414; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 415; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 4 416; CHECK-NEXT: br label [[ANOTHER_BRANCH]] 417; CHECK: another.branch: 418; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 419; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 420; CHECK: for.end: 421; CHECK-NEXT: ret void 422; 423entry: 424 %uglygep = getelementptr i8, ptr %a, i32 84 425 br label %for.body 426 427for.body: ; preds = %another.branch, %entry 428 %lsr.iv1 = phi ptr [ %uglygep2, %another.branch ], [ %uglygep, %entry ] 429 %lsr.iv = phi i32 [ %lsr.iv.next, %another.branch ], [ 379, %entry ] 430 store i32 1, ptr %lsr.iv1, align 4 431 %lsr.iv.next = add nsw i32 %lsr.iv, -1 432 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 4 433 br label %another.branch 434 435another.branch: 436 %exitcond.not = icmp sle i32 %lsr.iv.next, 0 437 br i1 %exitcond.not, label %for.end, label %for.body 438 439for.end: ; preds = %for.body 440 ret void 441} 442 443 444define void @non_branch_terminator(ptr %a) { 445; CHECK-LABEL: @non_branch_terminator( 446; CHECK-NEXT: entry: 447; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 448; CHECK-NEXT: br label [[FOR_BODY:%.*]] 449; CHECK: for.body: 450; CHECK-NEXT: [[LSR_IV2:%.*]] = phi i64 [ [[LSR_IV_NEXT3:%.*]], [[FOR_BODY]] ], [ 378, [[ENTRY:%.*]] ] 451; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY]] ] 452; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 453; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 454; CHECK-NEXT: [[LSR_IV_NEXT3]] = add nsw i64 [[LSR_IV2]], -1 455; CHECK-NEXT: switch i64 [[LSR_IV2]], label [[FOR_BODY]] [ 456; CHECK-NEXT: i64 0, label [[FOR_END:%.*]] 457; CHECK-NEXT: ] 458; CHECK: for.end: 459; CHECK-NEXT: ret void 460; 461entry: 462 %uglygep = getelementptr i8, ptr %a, i64 84 463 br label %for.body 464 465for.body: ; preds = %for.body, %entry 466 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 467 %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ 379, %entry ] 468 store i32 1, ptr %lsr.iv1, align 4 469 %lsr.iv.next = add nsw i64 %lsr.iv, -1 470 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 471 switch i64 %lsr.iv.next, label %for.body [i64 0, label %for.end] 472 473for.end: ; preds = %for.body 474 ret void 475} 476 477;; The next step of tests exercise various cases with the expansion 478;; budget and different trip counts or estimated trip counts. 479 480define void @profiled_short_tc(ptr %a, i32 %offset, i32 %n) { 481; CHECK-LABEL: @profiled_short_tc( 482; CHECK-NEXT: entry: 483; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 484; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 485; CHECK-NEXT: br label [[FOR_BODY:%.*]] 486; CHECK: for.body: 487; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 488; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ] 489; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 490; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], 1 491; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 492; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], [[N:%.*]] 493; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]], !prof [[PROF0:![0-9]+]] 494; CHECK: for.end: 495; CHECK-NEXT: ret void 496; 497entry: 498 %offset.nonzero = or i32 %offset, 1 499 %uglygep = getelementptr i8, ptr %a, i64 84 500 br label %for.body 501 502for.body: ; preds = %for.body, %entry 503 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 504 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 505 store i32 1, ptr %lsr.iv1, align 4 506 %lsr.iv.next = add nsw i32 %lsr.iv, 1 507 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 508 %exitcond.not = icmp eq i32 %lsr.iv.next, %n 509 br i1 %exitcond.not, label %for.end, label %for.body, !prof !{!"branch_weights", i32 1, i32 3} 510 511for.end: ; preds = %for.body 512 ret void 513} 514 515define void @profiled_long_tc(ptr %a, i32 %offset, i32 %n) { 516; CHECK-LABEL: @profiled_long_tc( 517; CHECK-NEXT: entry: 518; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 519; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 520; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1 521; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 522; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 523; CHECK-NEXT: [[TMP3:%.*]] = sext i32 [[OFFSET_NONZERO]] to i64 524; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[TMP2]], [[TMP3]] 525; CHECK-NEXT: [[TMP5:%.*]] = add nsw i64 [[TMP4]], 84 526; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP5]] 527; CHECK-NEXT: br label [[FOR_BODY:%.*]] 528; CHECK: for.body: 529; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 530; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 531; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 532; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 533; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]], !prof [[PROF1:![0-9]+]] 534; CHECK: for.end: 535; CHECK-NEXT: ret void 536; 537entry: 538 %offset.nonzero = or i32 %offset, 1 539 %uglygep = getelementptr i8, ptr %a, i64 84 540 br label %for.body 541 542for.body: ; preds = %for.body, %entry 543 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 544 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 545 store i32 1, ptr %lsr.iv1, align 4 546 %lsr.iv.next = add nsw i32 %lsr.iv, 1 547 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 548 %exitcond.not = icmp eq i32 %lsr.iv.next, %n 549 br i1 %exitcond.not, label %for.end, label %for.body, !prof !{!"branch_weights", i32 1, i32 300} 550 551for.end: ; preds = %for.body 552 ret void 553} 554 555define void @unknown_tc(ptr %a, i32 %offset, i32 %n) { 556; CHECK-LABEL: @unknown_tc( 557; CHECK-NEXT: entry: 558; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 559; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 560; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1 561; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 562; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 563; CHECK-NEXT: [[TMP3:%.*]] = sext i32 [[OFFSET_NONZERO]] to i64 564; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[TMP2]], [[TMP3]] 565; CHECK-NEXT: [[TMP5:%.*]] = add nsw i64 [[TMP4]], 84 566; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP5]] 567; CHECK-NEXT: br label [[FOR_BODY:%.*]] 568; CHECK: for.body: 569; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 570; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 571; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 572; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 573; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 574; CHECK: for.end: 575; CHECK-NEXT: ret void 576; 577entry: 578 %offset.nonzero = or i32 %offset, 1 579 %uglygep = getelementptr i8, ptr %a, i64 84 580 br label %for.body 581 582for.body: ; preds = %for.body, %entry 583 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 584 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 585 store i32 1, ptr %lsr.iv1, align 4 586 %lsr.iv.next = add nsw i32 %lsr.iv, 1 587 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 588 %exitcond.not = icmp eq i32 %lsr.iv.next, %n 589 br i1 %exitcond.not, label %for.end, label %for.body 590 591for.end: ; preds = %for.body 592 ret void 593} 594 595define void @unknown_tc2(ptr %a, i32 %offset, i32 %n, i32 %step) mustprogress { 596; CHECK-LABEL: @unknown_tc2( 597; CHECK-NEXT: entry: 598; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 599; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 600; CHECK-NEXT: br label [[FOR_BODY:%.*]] 601; CHECK: for.body: 602; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 603; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ] 604; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 605; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], [[STEP:%.*]] 606; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 607; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp sge i32 [[LSR_IV_NEXT]], [[N:%.*]] 608; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 609; CHECK: for.end: 610; CHECK-NEXT: ret void 611; 612entry: 613 %offset.nonzero = or i32 %offset, 1 614 %uglygep = getelementptr i8, ptr %a, i64 84 615 br label %for.body 616 617for.body: ; preds = %for.body, %entry 618 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 619 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 620 store i32 1, ptr %lsr.iv1, align 4 621 %lsr.iv.next = add nsw i32 %lsr.iv, %step 622 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 623 %exitcond.not = icmp sge i32 %lsr.iv.next, %n 624 br i1 %exitcond.not, label %for.end, label %for.body 625 626for.end: ; preds = %for.body 627 ret void 628} 629 630define void @small_tc_trivial_loop(ptr %a, i32 %offset) { 631; CHECK-LABEL: @small_tc_trivial_loop( 632; CHECK-NEXT: entry: 633; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 634; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 635; CHECK-NEXT: br label [[FOR_BODY:%.*]] 636; CHECK: for.body: 637; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 638; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ] 639; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 640; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], 1 641; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 642; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 1 643; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 644; CHECK: for.end: 645; CHECK-NEXT: ret void 646; 647entry: 648 %offset.nonzero = or i32 %offset, 1 649 %uglygep = getelementptr i8, ptr %a, i64 84 650 br label %for.body 651 652for.body: ; preds = %for.body, %entry 653 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 654 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 655 store i32 1, ptr %lsr.iv1, align 4 656 %lsr.iv.next = add nsw i32 %lsr.iv, 1 657 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 658 %exitcond.not = icmp eq i32 %lsr.iv.next, 1 659 br i1 %exitcond.not, label %for.end, label %for.body 660 661for.end: ; preds = %for.body 662 ret void 663} 664 665define void @small_tc_below_threshold(ptr %a, i32 %offset) { 666; CHECK-LABEL: @small_tc_below_threshold( 667; CHECK-NEXT: entry: 668; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 669; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 670; CHECK-NEXT: br label [[FOR_BODY:%.*]] 671; CHECK: for.body: 672; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 673; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ] 674; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 675; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], 1 676; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 677; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 2 678; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 679; CHECK: for.end: 680; CHECK-NEXT: ret void 681; 682entry: 683 %offset.nonzero = or i32 %offset, 1 684 %uglygep = getelementptr i8, ptr %a, i64 84 685 br label %for.body 686 687for.body: ; preds = %for.body, %entry 688 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 689 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 690 store i32 1, ptr %lsr.iv1, align 4 691 %lsr.iv.next = add nsw i32 %lsr.iv, 1 692 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 693 %exitcond.not = icmp eq i32 %lsr.iv.next, 2 694 br i1 %exitcond.not, label %for.end, label %for.body 695 696for.end: ; preds = %for.body 697 ret void 698} 699 700define void @small_tc_above_threshold(ptr %a, i32 %offset) { 701; CHECK-LABEL: @small_tc_above_threshold( 702; CHECK-NEXT: entry: 703; CHECK-NEXT: [[OFFSET_NONZERO:%.*]] = or i32 [[OFFSET:%.*]], 1 704; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 705; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[OFFSET_NONZERO]] to i64 706; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i64 [[TMP0]], 10 707; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[TMP1]], 84 708; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]] 709; CHECK-NEXT: br label [[FOR_BODY:%.*]] 710; CHECK: for.body: 711; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] 712; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 713; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i32 [[OFFSET_NONZERO]] 714; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]] 715; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 716; CHECK: for.end: 717; CHECK-NEXT: ret void 718; 719entry: 720 %offset.nonzero = or i32 %offset, 1 721 %uglygep = getelementptr i8, ptr %a, i64 84 722 br label %for.body 723 724for.body: ; preds = %for.body, %entry 725 %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] 726 %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 0, %entry ] 727 store i32 1, ptr %lsr.iv1, align 4 728 %lsr.iv.next = add nsw i32 %lsr.iv, 1 729 %uglygep2 = getelementptr i8, ptr %lsr.iv1, i32 %offset.nonzero 730 %exitcond.not = icmp eq i32 %lsr.iv.next, 10 731 br i1 %exitcond.not, label %for.end, label %for.body 732 733for.end: ; preds = %for.body 734 ret void 735} 736