1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=loop-bound-split -S < %s | FileCheck %s 3 4; The transformation is failed with this test because we can not guarantee the 5; split condition is always true in pre-loop after transformation. 6define void @variable_split_loop_bound_and_exit_cond_inc_with_sgt(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 7; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_sgt( 8; CHECK-NEXT: loop.ph: 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 12; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 13; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 14; CHECK: if.then: 15; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 16; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 17; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 18; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 19; CHECK-NEXT: br label [[FOR_INC]] 20; CHECK: if.else: 21; CHECK-NEXT: br label [[FOR_INC]] 22; CHECK: for.inc: 23; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 24; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[N:%.*]] 25; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 26; CHECK: exit: 27; CHECK-NEXT: ret void 28; 29loop.ph: 30 br label %loop 31 32loop: 33 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 34 %cmp = icmp ult i64 %iv, %a 35 br i1 %cmp, label %if.then, label %if.else 36 37if.then: 38 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 39 %val = load i64, ptr %src.arrayidx 40 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 41 store i64 %val, ptr %dst.arrayidx 42 br label %for.inc 43 44if.else: 45 br label %for.inc 46 47for.inc: 48 %inc = add nuw nsw i64 %iv, 1 49 %cond = icmp sgt i64 %inc, %n 50 br i1 %cond, label %exit, label %loop 51 52exit: 53 ret void 54} 55 56; The transformation works with this test because we can guarantee the split 57; condition is always true in pre-loop after transformation. 58define void @umax_variable_split_loop_bound_and_exit_cond_inc_with_sgt(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 59; CHECK-LABEL: @umax_variable_split_loop_bound_and_exit_cond_inc_with_sgt( 60; CHECK-NEXT: loop.ph: 61; CHECK-NEXT: [[B:%.*]] = call i64 @llvm.umax.i64(i64 [[A:%.*]], i64 1) 62; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 63; CHECK: loop.ph.split: 64; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) 65; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 [[B]]) 66; CHECK-NEXT: br label [[LOOP:%.*]] 67; CHECK: loop: 68; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 69; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[B]] 70; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 71; CHECK: if.then: 72; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 73; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 74; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 75; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 76; CHECK-NEXT: br label [[FOR_INC]] 77; CHECK: if.else: 78; CHECK-NEXT: br label [[FOR_INC]] 79; CHECK: for.inc: 80; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 81; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 82; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 83; CHECK: loop.ph.split.split: 84; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 85; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]] 86; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 87; CHECK: loop.split.preheader: 88; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 89; CHECK: loop.split: 90; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 91; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], [[B]] 92; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 93; CHECK: if.else.split: 94; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 95; CHECK: if.then.split: 96; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]] 97; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4 98; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]] 99; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4 100; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 101; CHECK: for.inc.split: 102; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 103; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 104; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 105; CHECK: exit.loopexit: 106; CHECK-NEXT: br label [[EXIT]] 107; CHECK: exit: 108; CHECK-NEXT: ret void 109; 110loop.ph: 111 %b = call i64 @llvm.umax.i64(i64 %a, i64 1) 112 br label %loop 113 114loop: 115 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 116 %cmp = icmp ult i64 %iv, %b 117 br i1 %cmp, label %if.then, label %if.else 118 119if.then: 120 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 121 %val = load i64, ptr %src.arrayidx 122 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 123 store i64 %val, ptr %dst.arrayidx 124 br label %for.inc 125 126if.else: 127 br label %for.inc 128 129for.inc: 130 %inc = add nuw nsw i64 %iv, 1 131 %cond = icmp sgt i64 %inc, %n 132 br i1 %cond, label %exit, label %loop 133 134exit: 135 ret void 136} 137 138; The transformation works with this test because we can guarantee the split 139; condition is always true in pre-loop after transformation. 140define void @constant_split_loop_bound_and_exit_cond_inc_with_sgt(ptr noalias %src, ptr noalias %dst, i64 %n) { 141; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sgt( 142; CHECK-NEXT: loop.ph: 143; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 144; CHECK: loop.ph.split: 145; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) 146; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 10) 147; CHECK-NEXT: br label [[LOOP:%.*]] 148; CHECK: loop: 149; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 150; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 151; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 152; CHECK: if.then: 153; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 154; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 155; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 156; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 157; CHECK-NEXT: br label [[FOR_INC]] 158; CHECK: if.else: 159; CHECK-NEXT: br label [[FOR_INC]] 160; CHECK: for.inc: 161; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 162; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 163; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 164; CHECK: loop.ph.split.split: 165; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 166; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]] 167; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 168; CHECK: loop.split.preheader: 169; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 170; CHECK: loop.split: 171; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 172; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 173; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 174; CHECK: if.else.split: 175; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 176; CHECK: if.then.split: 177; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]] 178; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4 179; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]] 180; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4 181; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 182; CHECK: for.inc.split: 183; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 184; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 185; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 186; CHECK: exit.loopexit: 187; CHECK-NEXT: br label [[EXIT]] 188; CHECK: exit: 189; CHECK-NEXT: ret void 190; 191loop.ph: 192 br label %loop 193 194loop: 195 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 196 %cmp = icmp ult i64 %iv, 10 197 br i1 %cmp, label %if.then, label %if.else 198 199if.then: 200 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 201 %val = load i64, ptr %src.arrayidx 202 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 203 store i64 %val, ptr %dst.arrayidx 204 br label %for.inc 205 206if.else: 207 br label %for.inc 208 209for.inc: 210 %inc = add nuw nsw i64 %iv, 1 211 %cond = icmp sgt i64 %inc, %n 212 br i1 %cond, label %exit, label %loop 213 214exit: 215 ret void 216} 217 218define void @variable_split_loop_bound_and_exit_cond_inc_with_eq(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 219; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_eq( 220; CHECK-NEXT: loop.ph: 221; CHECK-NEXT: br label [[LOOP:%.*]] 222; CHECK: loop: 223; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 224; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 225; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 226; CHECK: if.then: 227; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 228; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 229; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 230; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 231; CHECK-NEXT: br label [[FOR_INC]] 232; CHECK: if.else: 233; CHECK-NEXT: br label [[FOR_INC]] 234; CHECK: for.inc: 235; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 236; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INC]], [[N:%.*]] 237; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 238; CHECK: exit: 239; CHECK-NEXT: ret void 240; 241loop.ph: 242 br label %loop 243 244loop: 245 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 246 %cmp = icmp ult i64 %iv, %a 247 br i1 %cmp, label %if.then, label %if.else 248 249if.then: 250 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 251 %val = load i64, ptr %src.arrayidx 252 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 253 store i64 %val, ptr %dst.arrayidx 254 br label %for.inc 255 256if.else: 257 br label %for.inc 258 259for.inc: 260 %inc = add nuw nsw i64 %iv, 1 261 %cond = icmp eq i64 %inc, %n 262 br i1 %cond, label %exit, label %loop 263 264exit: 265 ret void 266} 267 268define void @constant_split_loop_bound_and_exit_cond_inc_with_eq(ptr noalias %src, ptr noalias %dst, i64 %n) { 269; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_eq( 270; CHECK-NEXT: loop.ph: 271; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 272; CHECK: loop.ph.split: 273; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1 274; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP0]], i64 10) 275; CHECK-NEXT: br label [[LOOP:%.*]] 276; CHECK: loop: 277; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 278; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 279; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 280; CHECK: if.then: 281; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 282; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 283; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 284; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 285; CHECK-NEXT: br label [[FOR_INC]] 286; CHECK: if.else: 287; CHECK-NEXT: br label [[FOR_INC]] 288; CHECK: for.inc: 289; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 290; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INC]], [[NEW_BOUND]] 291; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 292; CHECK: loop.ph.split.split: 293; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 294; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]] 295; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 296; CHECK: loop.split.preheader: 297; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 298; CHECK: loop.split: 299; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 300; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 301; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 302; CHECK: if.else.split: 303; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 304; CHECK: if.then.split: 305; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]] 306; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4 307; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]] 308; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4 309; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 310; CHECK: for.inc.split: 311; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 312; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp eq i64 [[INC_SPLIT]], [[N]] 313; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 314; CHECK: exit.loopexit: 315; CHECK-NEXT: br label [[EXIT]] 316; CHECK: exit: 317; CHECK-NEXT: ret void 318; 319loop.ph: 320 br label %loop 321 322loop: 323 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 324 %cmp = icmp ult i64 %iv, 10 325 br i1 %cmp, label %if.then, label %if.else 326 327if.then: 328 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 329 %val = load i64, ptr %src.arrayidx 330 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 331 store i64 %val, ptr %dst.arrayidx 332 br label %for.inc 333 334if.else: 335 br label %for.inc 336 337for.inc: 338 %inc = add nuw nsw i64 %iv, 1 339 %cond = icmp eq i64 %inc, %n 340 br i1 %cond, label %exit, label %loop 341 342exit: 343 ret void 344} 345 346define void @variable_split_loop_bound_and_exit_cond_inc_with_sge(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 347; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_sge( 348; CHECK-NEXT: loop.ph: 349; CHECK-NEXT: br label [[LOOP:%.*]] 350; CHECK: loop: 351; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 352; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 353; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 354; CHECK: if.then: 355; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 356; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 357; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 358; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 359; CHECK-NEXT: br label [[FOR_INC]] 360; CHECK: if.else: 361; CHECK-NEXT: br label [[FOR_INC]] 362; CHECK: for.inc: 363; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 364; CHECK-NEXT: [[COND:%.*]] = icmp sge i64 [[INC]], [[N:%.*]] 365; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 366; CHECK: exit: 367; CHECK-NEXT: ret void 368; 369loop.ph: 370 br label %loop 371 372loop: 373 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 374 %cmp = icmp ult i64 %iv, %a 375 br i1 %cmp, label %if.then, label %if.else 376 377if.then: 378 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 379 %val = load i64, ptr %src.arrayidx 380 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 381 store i64 %val, ptr %dst.arrayidx 382 br label %for.inc 383 384if.else: 385 br label %for.inc 386 387for.inc: 388 %inc = add nuw nsw i64 %iv, 1 389 %cond = icmp sge i64 %inc, %n 390 br i1 %cond, label %exit, label %loop 391 392exit: 393 ret void 394} 395 396define void @constant_split_loop_bound_and_exit_cond_inc_with_sge(ptr noalias %src, ptr noalias %dst, i64 %n) { 397; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sge( 398; CHECK-NEXT: loop.ph: 399; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 400; CHECK: loop.ph.split: 401; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1) 402; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1 403; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 10) 404; CHECK-NEXT: br label [[LOOP:%.*]] 405; CHECK: loop: 406; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 407; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 408; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 409; CHECK: if.then: 410; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 411; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 412; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 413; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 414; CHECK-NEXT: br label [[FOR_INC]] 415; CHECK: if.else: 416; CHECK-NEXT: br label [[FOR_INC]] 417; CHECK: for.inc: 418; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 419; CHECK-NEXT: [[COND:%.*]] = icmp sge i64 [[INC]], [[NEW_BOUND]] 420; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 421; CHECK: loop.ph.split.split: 422; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 423; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]] 424; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 425; CHECK: loop.split.preheader: 426; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 427; CHECK: loop.split: 428; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 429; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 430; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 431; CHECK: if.else.split: 432; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 433; CHECK: if.then.split: 434; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]] 435; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4 436; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]] 437; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4 438; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 439; CHECK: for.inc.split: 440; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 441; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sge i64 [[INC_SPLIT]], [[N]] 442; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 443; CHECK: exit.loopexit: 444; CHECK-NEXT: br label [[EXIT]] 445; CHECK: exit: 446; CHECK-NEXT: ret void 447; 448loop.ph: 449 br label %loop 450 451loop: 452 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 453 %cmp = icmp ult i64 %iv, 10 454 br i1 %cmp, label %if.then, label %if.else 455 456if.then: 457 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 458 %val = load i64, ptr %src.arrayidx 459 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 460 store i64 %val, ptr %dst.arrayidx 461 br label %for.inc 462 463if.else: 464 br label %for.inc 465 466for.inc: 467 %inc = add nuw nsw i64 %iv, 1 468 %cond = icmp sge i64 %inc, %n 469 br i1 %cond, label %exit, label %loop 470 471exit: 472 ret void 473} 474 475define void @variable_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 476; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_step_is_not_one( 477; CHECK-NEXT: loop.ph: 478; CHECK-NEXT: br label [[LOOP:%.*]] 479; CHECK: loop: 480; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 481; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 482; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 483; CHECK: if.then: 484; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 485; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 486; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 487; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 488; CHECK-NEXT: br label [[FOR_INC]] 489; CHECK: if.else: 490; CHECK-NEXT: br label [[FOR_INC]] 491; CHECK: for.inc: 492; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 2 493; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[N:%.*]] 494; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 495; CHECK: exit: 496; CHECK-NEXT: ret void 497; 498loop.ph: 499 br label %loop 500 501loop: 502 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 503 %cmp = icmp ult i64 %iv, %a 504 br i1 %cmp, label %if.then, label %if.else 505 506if.then: 507 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 508 %val = load i64, ptr %src.arrayidx 509 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 510 store i64 %val, ptr %dst.arrayidx 511 br label %for.inc 512 513if.else: 514 br label %for.inc 515 516for.inc: 517 %inc = add nuw nsw i64 %iv, 2 518 %cond = icmp sgt i64 %inc, %n 519 br i1 %cond, label %exit, label %loop 520 521exit: 522 ret void 523} 524 525define void @constant_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(ptr noalias %src, ptr noalias %dst, i64 %n) { 526; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_step_is_not_one( 527; CHECK-NEXT: loop.ph: 528; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 529; CHECK: loop.ph.split: 530; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1) 531; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[SMAX]], 1 532; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 10) 533; CHECK-NEXT: br label [[LOOP:%.*]] 534; CHECK: loop: 535; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] 536; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 537; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 538; CHECK: if.then: 539; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 540; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 541; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 542; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 543; CHECK-NEXT: br label [[FOR_INC]] 544; CHECK: if.else: 545; CHECK-NEXT: br label [[FOR_INC]] 546; CHECK: for.inc: 547; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 2 548; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 549; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 550; CHECK: loop.ph.split.split: 551; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 552; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]] 553; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 554; CHECK: loop.split.preheader: 555; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 556; CHECK: loop.split: 557; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 558; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 559; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 560; CHECK: if.else.split: 561; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 562; CHECK: if.then.split: 563; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]] 564; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4 565; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]] 566; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4 567; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 568; CHECK: for.inc.split: 569; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 2 570; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 571; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 572; CHECK: exit.loopexit: 573; CHECK-NEXT: br label [[EXIT]] 574; CHECK: exit: 575; CHECK-NEXT: ret void 576; 577loop.ph: 578 br label %loop 579 580loop: 581 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 582 %cmp = icmp ult i64 %iv, 10 583 br i1 %cmp, label %if.then, label %if.else 584 585if.then: 586 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 587 %val = load i64, ptr %src.arrayidx 588 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 589 store i64 %val, ptr %dst.arrayidx 590 br label %for.inc 591 592if.else: 593 br label %for.inc 594 595for.inc: 596 %inc = add nuw nsw i64 %iv, 2 597 %cond = icmp sgt i64 %inc, %n 598 br i1 %cond, label %exit, label %loop 599 600exit: 601 ret void 602} 603 604define void @variable_split_loop_bound_and_exit_cond_inc_with_ne(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 605; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_ne( 606; CHECK-NEXT: loop.ph: 607; CHECK-NEXT: br label [[LOOP:%.*]] 608; CHECK: loop: 609; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 610; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 611; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]] 612; CHECK: if.then: 613; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 614; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 615; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 616; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 617; CHECK-NEXT: br label [[FOR_INC]] 618; CHECK: for.inc: 619; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 620; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]] 621; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 622; CHECK: exit: 623; CHECK-NEXT: ret void 624; 625loop.ph: 626 br label %loop 627 628loop: 629 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 630 %cmp = icmp ult i64 %iv, %a 631 br i1 %cmp, label %if.then, label %for.inc 632 633if.then: 634 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 635 %val = load i64, ptr %src.arrayidx 636 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 637 store i64 %val, ptr %dst.arrayidx 638 br label %for.inc 639 640for.inc: 641 %inc = add nuw nsw i64 %iv, 1 642 %cond = icmp ne i64 %inc, %n 643 br i1 %cond, label %exit, label %loop 644 645exit: 646 ret void 647} 648 649define void @constant_split_loop_bound_and_exit_cond_inc_with_ne(ptr noalias %src, ptr noalias %dst, i64 %n) { 650; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_ne( 651; CHECK-NEXT: loop.ph: 652; CHECK-NEXT: br label [[LOOP:%.*]] 653; CHECK: loop: 654; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 655; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 656; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]] 657; CHECK: if.then: 658; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 659; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 660; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 661; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 662; CHECK-NEXT: br label [[FOR_INC]] 663; CHECK: for.inc: 664; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 665; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]] 666; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 667; CHECK: exit: 668; CHECK-NEXT: ret void 669; 670loop.ph: 671 br label %loop 672 673loop: 674 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 675 %cmp = icmp ult i64 %iv, 10 676 br i1 %cmp, label %if.then, label %for.inc 677 678if.then: 679 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 680 %val = load i64, ptr %src.arrayidx 681 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 682 store i64 %val, ptr %dst.arrayidx 683 br label %for.inc 684 685for.inc: 686 %inc = add nuw nsw i64 %iv, 1 687 %cond = icmp ne i64 %inc, %n 688 br i1 %cond, label %exit, label %loop 689 690exit: 691 ret void 692} 693 694define void @varialbe_split_loop_bound_and_exit_cond_dec_with_slt(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 695; CHECK-LABEL: @varialbe_split_loop_bound_and_exit_cond_dec_with_slt( 696; CHECK-NEXT: loop.ph: 697; CHECK-NEXT: br label [[LOOP:%.*]] 698; CHECK: loop: 699; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 700; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 701; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] 702; CHECK: if.then: 703; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 704; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 705; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 706; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 707; CHECK-NEXT: br label [[FOR_DEC]] 708; CHECK: for.dec: 709; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 710; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]] 711; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 712; CHECK: exit: 713; CHECK-NEXT: ret void 714; 715loop.ph: 716 br label %loop 717 718loop: 719 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] 720 %cmp = icmp ult i64 %iv, %a 721 br i1 %cmp, label %if.then, label %for.dec 722 723if.then: 724 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 725 %val = load i64, ptr %src.arrayidx 726 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 727 store i64 %val, ptr %dst.arrayidx 728 br label %for.dec 729 730for.dec: 731 %dec = sub nuw nsw i64 %iv, 1 732 %cond = icmp slt i64 %dec, %n 733 br i1 %cond, label %exit, label %loop 734 735exit: 736 ret void 737} 738 739define void @constant_split_loop_bound_and_exit_cond_dec_with_slt(ptr noalias %src, ptr noalias %dst, i64 %n) { 740; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_dec_with_slt( 741; CHECK-NEXT: loop.ph: 742; CHECK-NEXT: br label [[LOOP:%.*]] 743; CHECK: loop: 744; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 745; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 746; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] 747; CHECK: if.then: 748; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 749; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 750; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 751; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 752; CHECK-NEXT: br label [[FOR_DEC]] 753; CHECK: for.dec: 754; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 755; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]] 756; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 757; CHECK: exit: 758; CHECK-NEXT: ret void 759; 760loop.ph: 761 br label %loop 762 763loop: 764 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] 765 %cmp = icmp ult i64 %iv, 10 766 br i1 %cmp, label %if.then, label %for.dec 767 768if.then: 769 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 770 %val = load i64, ptr %src.arrayidx 771 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 772 store i64 %val, ptr %dst.arrayidx 773 br label %for.dec 774 775for.dec: 776 %dec = sub nuw nsw i64 %iv, 1 777 %cond = icmp slt i64 %dec, %n 778 br i1 %cond, label %exit, label %loop 779 780exit: 781 ret void 782} 783 784define void @variable_split_loop_bound_and_exit_cond_dec_with_sle(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { 785; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_dec_with_sle( 786; CHECK-NEXT: loop.ph: 787; CHECK-NEXT: br label [[LOOP:%.*]] 788; CHECK: loop: 789; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 790; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] 791; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] 792; CHECK: if.then: 793; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 794; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 795; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 796; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 797; CHECK-NEXT: br label [[FOR_DEC]] 798; CHECK: for.dec: 799; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 800; CHECK-NEXT: [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]] 801; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 802; CHECK: exit: 803; CHECK-NEXT: ret void 804; 805loop.ph: 806 br label %loop 807 808loop: 809 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] 810 %cmp = icmp ult i64 %iv, %a 811 br i1 %cmp, label %if.then, label %for.dec 812 813if.then: 814 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 815 %val = load i64, ptr %src.arrayidx 816 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 817 store i64 %val, ptr %dst.arrayidx 818 br label %for.dec 819 820for.dec: 821 %dec = sub nuw nsw i64 %iv, 1 822 %cond = icmp sle i64 %dec, %n 823 br i1 %cond, label %exit, label %loop 824 825exit: 826 ret void 827} 828 829define void @constant_split_loop_bound_and_exit_cond_dec_with_sle(ptr noalias %src, ptr noalias %dst, i64 %n) { 830; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_dec_with_sle( 831; CHECK-NEXT: loop.ph: 832; CHECK-NEXT: br label [[LOOP:%.*]] 833; CHECK: loop: 834; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] 835; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 836; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] 837; CHECK: if.then: 838; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 839; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 840; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 841; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 842; CHECK-NEXT: br label [[FOR_DEC]] 843; CHECK: for.dec: 844; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 845; CHECK-NEXT: [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]] 846; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] 847; CHECK: exit: 848; CHECK-NEXT: ret void 849; 850loop.ph: 851 br label %loop 852 853loop: 854 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] 855 %cmp = icmp ult i64 %iv, 10 856 br i1 %cmp, label %if.then, label %for.dec 857 858if.then: 859 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 860 %val = load i64, ptr %src.arrayidx 861 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 862 store i64 %val, ptr %dst.arrayidx 863 br label %for.dec 864 865for.dec: 866 %dec = sub nuw nsw i64 %iv, 1 867 %cond = icmp sle i64 %dec, %n 868 br i1 %cond, label %exit, label %loop 869 870exit: 871 ret void 872} 873 874; LoopBoundSplit pass should ignore phi which is not scevable phi. 875define void @constant_split_loop_bound_and_exit_cond_inc_with_sgt_and_is_not_scevable_phi(ptr noalias %src, ptr noalias %dst, i64 %n) { 876; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sgt_and_is_not_scevable_phi( 877; CHECK-NEXT: loop.ph: 878; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] 879; CHECK: loop.ph.split: 880; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) 881; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 10) 882; CHECK-NEXT: br label [[LOOP:%.*]] 883; CHECK: loop: 884; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI:%.*]] = phi double [ 1.000000e+00, [[FOR_INC:%.*]] ], [ 2.000000e+00, [[LOOP_PH_SPLIT]] ] 885; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC]] ], [ 0, [[LOOP_PH_SPLIT]] ] 886; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 887; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 888; CHECK: if.then: 889; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]] 890; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4 891; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]] 892; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4 893; CHECK-NEXT: br label [[FOR_INC]] 894; CHECK: if.else: 895; CHECK-NEXT: br label [[FOR_INC]] 896; CHECK: for.inc: 897; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 898; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] 899; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] 900; CHECK: loop.ph.split.split: 901; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI_LCSSA:%.*]] = phi double [ 1.000000e+00, [[FOR_INC]] ] 902; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] 903; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]] 904; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] 905; CHECK: loop.split.preheader: 906; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] 907; CHECK: loop.split: 908; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI_SPLIT:%.*]] = phi double [ 1.000000e+00, [[FOR_INC_SPLIT:%.*]] ], [ [[IS_NOT_SCEVABLE_PHI_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 909; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ] 910; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 911; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] 912; CHECK: if.else.split: 913; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 914; CHECK: if.then.split: 915; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]] 916; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4 917; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]] 918; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4 919; CHECK-NEXT: br label [[FOR_INC_SPLIT]] 920; CHECK: for.inc.split: 921; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 922; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] 923; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] 924; CHECK: exit.loopexit: 925; CHECK-NEXT: br label [[EXIT]] 926; CHECK: exit: 927; CHECK-NEXT: ret void 928; 929loop.ph: 930 br label %loop 931 932loop: 933 %is_not_scevable_phi = phi double [ 1.0, %for.inc ], [ 2.0, %loop.ph ] 934 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] 935 %cmp = icmp ult i64 %iv, 10 936 br i1 %cmp, label %if.then, label %if.else 937 938if.then: 939 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv 940 %val = load i64, ptr %src.arrayidx 941 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv 942 store i64 %val, ptr %dst.arrayidx 943 br label %for.inc 944 945if.else: 946 br label %for.inc 947 948for.inc: 949 %inc = add nuw nsw i64 %iv, 1 950 %cond = icmp sgt i64 %inc, %n 951 br i1 %cond, label %exit, label %loop 952 953exit: 954 ret void 955} 956 957declare i64 @llvm.umax.i64(i64, i64) 958