1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=loop-bound-split -S < %s | FileCheck %s 3 4define void @split_loop_bound_inc_with_sgt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 5; CHECK-LABEL: @split_loop_bound_inc_with_sgt( 6; CHECK-NEXT: loop.ph: 7; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 8; CHECK: loop.ph.split: 9; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) 10; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[SMAX]]) 11; CHECK-NEXT: br label [[LOOP:%.*]] 12; CHECK: loop: 13; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 14; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] 15; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 16; CHECK: if.then: 17; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 18; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 19; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 20; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 21; CHECK-NEXT: br label [[FOR_INC]] 22; CHECK: if.else: 23; CHECK-NEXT: br label [[FOR_INC]] 24; CHECK: for.inc: 25; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 26; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 27; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 28; CHECK: loop.ph.split.split: 29; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 30; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]] 31; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 32; CHECK: loop.split.preheader: 33; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 34; CHECK: loop.split: 35; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] 36; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] 37; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 38; CHECK: if.else.split: 39; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 40; CHECK: if.then.split: 41; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]] 42; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4 43; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]] 44; CHECK-NEXT: store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4 45; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 46; CHECK: for.inc.split: 47; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 48; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 49; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 50; CHECK: exit.loopexit: 51; CHECK-NEXT: br label [[EXIT]] 52; CHECK: exit: 53; CHECK-NEXT: ret void 54; 55loop.ph: 56 br label %loop 57 58loop: 59 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 60 %cmp = icmp slt i64 %iv, %a 61 br i1 %cmp, label %if.then, label %if.else 62 63if.then: 64 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 65 %val = load i64, i64* %src.arrayidx 66 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 67 store i64 %val, i64* %dst.arrayidx 68 br label %for.inc 69 70if.else: 71 br label %for.inc 72 73for.inc: 74 %inc = add nuw nsw i64 %iv, 1 75 %cond = icmp sgt i64 %inc, %n 76 br i1 %cond, label %exit, label %loop 77 78exit: 79 ret void 80} 81 82define void @split_loop_bound_inc_with_eq(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 83; CHECK-LABEL: @split_loop_bound_inc_with_eq( 84; CHECK-NEXT: loop.ph: 85; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 86; CHECK: loop.ph.split: 87; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1 88; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.umin.i64(i64 [[A:%.*]], i64 [[TMP0]]) 89; CHECK-NEXT: br label [[LOOP:%.*]] 90; CHECK: loop: 91; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 92; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] 93; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 94; CHECK: if.then: 95; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 96; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 97; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 98; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 99; CHECK-NEXT: br label [[FOR_INC]] 100; CHECK: if.else: 101; CHECK-NEXT: br label [[FOR_INC]] 102; CHECK: for.inc: 103; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 104; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INC]], [[NEW_BOUND]] 105; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 106; CHECK: loop.ph.split.split: 107; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 108; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]] 109; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 110; CHECK: loop.split.preheader: 111; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 112; CHECK: loop.split: 113; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] 114; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] 115; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 116; CHECK: if.else.split: 117; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 118; CHECK: if.then.split: 119; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]] 120; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4 121; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]] 122; CHECK-NEXT: store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4 123; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 124; CHECK: for.inc.split: 125; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 126; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp eq i64 [[INC_SPLIT]], [[N]] 127; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 128; CHECK: exit.loopexit: 129; CHECK-NEXT: br label [[EXIT]] 130; CHECK: exit: 131; CHECK-NEXT: ret void 132; 133loop.ph: 134 br label %loop 135 136loop: 137 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 138 %cmp = icmp slt i64 %iv, %a 139 br i1 %cmp, label %if.then, label %if.else 140 141if.then: 142 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 143 %val = load i64, i64* %src.arrayidx 144 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 145 store i64 %val, i64* %dst.arrayidx 146 br label %for.inc 147 148if.else: 149 br label %for.inc 150 151for.inc: 152 %inc = add nuw nsw i64 %iv, 1 153 %cond = icmp eq i64 %inc, %n 154 br i1 %cond, label %exit, label %loop 155 156exit: 157 ret void 158} 159 160define void @split_loop_bound_inc_with_sge(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 161; CHECK-LABEL: @split_loop_bound_inc_with_sge( 162; CHECK-NEXT: loop.ph: 163; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 164; CHECK: loop.ph.split: 165; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1) 166; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1 167; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[TMP0]]) 168; CHECK-NEXT: br label [[LOOP:%.*]] 169; CHECK: loop: 170; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 171; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] 172; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 173; CHECK: if.then: 174; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 175; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 176; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 177; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 178; CHECK-NEXT: br label [[FOR_INC]] 179; CHECK: if.else: 180; CHECK-NEXT: br label [[FOR_INC]] 181; CHECK: for.inc: 182; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 183; CHECK-NEXT: [[COND:%.*]] = icmp sge i64 [[INC]], [[NEW_BOUND]] 184; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 185; CHECK: loop.ph.split.split: 186; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 187; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]] 188; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 189; CHECK: loop.split.preheader: 190; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 191; CHECK: loop.split: 192; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] 193; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] 194; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 195; CHECK: if.else.split: 196; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 197; CHECK: if.then.split: 198; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]] 199; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4 200; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]] 201; CHECK-NEXT: store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4 202; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 203; CHECK: for.inc.split: 204; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 205; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sge i64 [[INC_SPLIT]], [[N]] 206; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 207; CHECK: exit.loopexit: 208; CHECK-NEXT: br label [[EXIT]] 209; CHECK: exit: 210; CHECK-NEXT: ret void 211; 212loop.ph: 213 br label %loop 214 215loop: 216 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 217 %cmp = icmp slt i64 %iv, %a 218 br i1 %cmp, label %if.then, label %if.else 219 220if.then: 221 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 222 %val = load i64, i64* %src.arrayidx 223 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 224 store i64 %val, i64* %dst.arrayidx 225 br label %for.inc 226 227if.else: 228 br label %for.inc 229 230for.inc: 231 %inc = add nuw nsw i64 %iv, 1 232 %cond = icmp sge i64 %inc, %n 233 br i1 %cond, label %exit, label %loop 234 235exit: 236 ret void 237} 238 239define void @split_loop_bound_inc_with_step_is_not_one(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 240; CHECK-LABEL: @split_loop_bound_inc_with_step_is_not_one( 241; CHECK-NEXT: loop.ph: 242; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 243; CHECK: loop.ph.split: 244; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1) 245; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[SMAX]], 1 246; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[TMP0]]) 247; CHECK-NEXT: br label [[LOOP:%.*]] 248; CHECK: loop: 249; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 250; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] 251; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 252; CHECK: if.then: 253; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 254; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 255; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 256; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 257; CHECK-NEXT: br label [[FOR_INC]] 258; CHECK: if.else: 259; CHECK-NEXT: br label [[FOR_INC]] 260; CHECK: for.inc: 261; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 2 262; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 263; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 264; CHECK: loop.ph.split.split: 265; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 266; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]] 267; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 268; CHECK: loop.split.preheader: 269; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 270; CHECK: loop.split: 271; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] 272; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] 273; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 274; CHECK: if.else.split: 275; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 276; CHECK: if.then.split: 277; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]] 278; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4 279; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]] 280; CHECK-NEXT: store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4 281; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 282; CHECK: for.inc.split: 283; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 2 284; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 285; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 286; CHECK: exit.loopexit: 287; CHECK-NEXT: br label [[EXIT]] 288; CHECK: exit: 289; CHECK-NEXT: ret void 290; 291loop.ph: 292 br label %loop 293 294loop: 295 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 296 %cmp = icmp slt i64 %iv, %a 297 br i1 %cmp, label %if.then, label %if.else 298 299if.then: 300 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 301 %val = load i64, i64* %src.arrayidx 302 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 303 store i64 %val, i64* %dst.arrayidx 304 br label %for.inc 305 306if.else: 307 br label %for.inc 308 309for.inc: 310 %inc = add nuw nsw i64 %iv, 2 311 %cond = icmp sgt i64 %inc, %n 312 br i1 %cond, label %exit, label %loop 313 314exit: 315 ret void 316} 317 318define void @split_loop_bound_inc_with_ne(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 319; CHECK-LABEL: @split_loop_bound_inc_with_ne( 320; CHECK-NEXT: loop.ph: 321; CHECK-NEXT: br label [[LOOP:%.*]] 322; CHECK: loop: 323; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 324; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]] 325; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]] 326; CHECK: if.then: 327; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 328; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 329; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 330; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 331; CHECK-NEXT: br label [[FOR_INC]] 332; CHECK: for.inc: 333; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 334; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]] 335; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 336; CHECK: exit: 337; CHECK-NEXT: ret void 338; 339loop.ph: 340 br label %loop 341 342loop: 343 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 344 %cmp = icmp slt i64 %iv, %a 345 br i1 %cmp, label %if.then, label %for.inc 346 347if.then: 348 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 349 %val = load i64, i64* %src.arrayidx 350 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 351 store i64 %val, i64* %dst.arrayidx 352 br label %for.inc 353 354for.inc: 355 %inc = add nuw nsw i64 %iv, 1 356 %cond = icmp ne i64 %inc, %n 357 br i1 %cond, label %exit, label %loop 358 359exit: 360 ret void 361} 362 363define void @split_loop_bound_dec_with_slt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 364; CHECK-LABEL: @split_loop_bound_dec_with_slt( 365; CHECK-NEXT: loop.ph: 366; CHECK-NEXT: br label [[LOOP:%.*]] 367; CHECK: loop: 368; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 369; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]] 370; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] 371; CHECK: if.then: 372; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 373; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 374; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 375; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 376; CHECK-NEXT: br label [[FOR_DEC]] 377; CHECK: for.dec: 378; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 379; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]] 380; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 381; CHECK: exit: 382; CHECK-NEXT: ret void 383; 384loop.ph: 385 br label %loop 386 387loop: 388 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] 389 %cmp = icmp slt i64 %iv, %a 390 br i1 %cmp, label %if.then, label %for.dec 391 392if.then: 393 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 394 %val = load i64, i64* %src.arrayidx 395 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 396 store i64 %val, i64* %dst.arrayidx 397 br label %for.dec 398 399for.dec: 400 %dec = sub nuw nsw i64 %iv, 1 401 %cond = icmp slt i64 %dec, %n 402 br i1 %cond, label %exit, label %loop 403 404exit: 405 ret void 406} 407 408define void @split_loop_bound_dec_with_sle(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 409; CHECK-LABEL: @split_loop_bound_dec_with_sle( 410; CHECK-NEXT: loop.ph: 411; CHECK-NEXT: br label [[LOOP:%.*]] 412; CHECK: loop: 413; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 414; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]] 415; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] 416; CHECK: if.then: 417; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 418; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 419; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 420; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 421; CHECK-NEXT: br label [[FOR_DEC]] 422; CHECK: for.dec: 423; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 424; CHECK-NEXT: [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]] 425; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 426; CHECK: exit: 427; CHECK-NEXT: ret void 428; 429loop.ph: 430 br label %loop 431 432loop: 433 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] 434 %cmp = icmp slt i64 %iv, %a 435 br i1 %cmp, label %if.then, label %for.dec 436 437if.then: 438 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 439 %val = load i64, i64* %src.arrayidx 440 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 441 store i64 %val, i64* %dst.arrayidx 442 br label %for.dec 443 444for.dec: 445 %dec = sub nuw nsw i64 %iv, 1 446 %cond = icmp sle i64 %dec, %n 447 br i1 %cond, label %exit, label %loop 448 449exit: 450 ret void 451} 452 453; LoopBoundSplit pass should ignore phi which is not scevable phi. 454define void @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { 455; CHECK-LABEL: @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi( 456; CHECK-NEXT: loop.ph: 457; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 458; CHECK: loop.ph.split: 459; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) 460; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[SMAX]]) 461; CHECK-NEXT: br label [[LOOP:%.*]] 462; CHECK: loop: 463; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI:%.*]] = phi double [ 1.000000e+00, [[FOR_INC:%.*]] ], [ 2.000000e+00, [[LOOP_PH_SPLIT]] ] 464; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC]] ], [ 0, [[LOOP_PH_SPLIT]] ] 465; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] 466; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 467; CHECK: if.then: 468; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] 469; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 470; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] 471; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 472; CHECK-NEXT: br label [[FOR_INC]] 473; CHECK: if.else: 474; CHECK-NEXT: br label [[FOR_INC]] 475; CHECK: for.inc: 476; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 477; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 478; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 479; CHECK: loop.ph.split.split: 480; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 481; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]] 482; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 483; CHECK: loop.split.preheader: 484; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 485; CHECK: loop.split: 486; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI_SPLIT:%.*]] = phi double [ 1.000000e+00, [[FOR_INC_SPLIT:%.*]] ], [ 2.000000e+00, [[LOOP_SPLIT_PREHEADER]] ] 487; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] 488; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] 489; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 490; CHECK: if.else.split: 491; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 492; CHECK: if.then.split: 493; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]] 494; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4 495; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]] 496; CHECK-NEXT: store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4 497; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 498; CHECK: for.inc.split: 499; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 500; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 501; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 502; CHECK: exit.loopexit: 503; CHECK-NEXT: br label [[EXIT]] 504; CHECK: exit: 505; CHECK-NEXT: ret void 506; 507loop.ph: 508 br label %loop 509 510loop: 511 %is_not_scevable_phi = phi double [ 1.0, %for.inc ], [ 2.0, %loop.ph ] 512 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 513 %cmp = icmp slt i64 %iv, %a 514 br i1 %cmp, label %if.then, label %if.else 515 516if.then: 517 %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv 518 %val = load i64, i64* %src.arrayidx 519 %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv 520 store i64 %val, i64* %dst.arrayidx 521 br label %for.inc 522 523if.else: 524 br label %for.inc 525 526for.inc: 527 %inc = add nuw nsw i64 %iv, 1 528 %cond = icmp sgt i64 %inc, %n 529 br i1 %cond, label %exit, label %loop 530 531exit: 532 ret void 533} 534 535