958 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=loop-bound-split -S < %s | FileCheck %s3 4; The transformation is failed with this test because we can not guarantee the5; 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 417; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]18; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 419; 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]], 124; 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 void28;29loop.ph:30 br label %loop31 32loop:33 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]34 %cmp = icmp ult i64 %iv, %a35 br i1 %cmp, label %if.then, label %if.else36 37if.then:38 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv39 %val = load i64, ptr %src.arrayidx40 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv41 store i64 %val, ptr %dst.arrayidx42 br label %for.inc43 44if.else:45 br label %for.inc46 47for.inc:48 %inc = add nuw nsw i64 %iv, 149 %cond = icmp sgt i64 %inc, %n50 br i1 %cond, label %exit, label %loop51 52exit:53 ret void54}55 56; The transformation works with this test because we can guarantee the split57; 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 474; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]75; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 476; 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]], 181; 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 498; 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 4100; CHECK-NEXT: br label [[FOR_INC_SPLIT]]101; CHECK: for.inc.split:102; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1103; 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 void109;110loop.ph:111 %b = call i64 @llvm.umax.i64(i64 %a, i64 1)112 br label %loop113 114loop:115 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]116 %cmp = icmp ult i64 %iv, %b117 br i1 %cmp, label %if.then, label %if.else118 119if.then:120 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv121 %val = load i64, ptr %src.arrayidx122 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv123 store i64 %val, ptr %dst.arrayidx124 br label %for.inc125 126if.else:127 br label %for.inc128 129for.inc:130 %inc = add nuw nsw i64 %iv, 1131 %cond = icmp sgt i64 %inc, %n132 br i1 %cond, label %exit, label %loop133 134exit:135 ret void136}137 138; The transformation works with this test because we can guarantee the split139; 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]], 10151; 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 4155; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]156; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4157; 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]], 1162; 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]], 10173; 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 4179; 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 4181; CHECK-NEXT: br label [[FOR_INC_SPLIT]]182; CHECK: for.inc.split:183; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1184; 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 void190;191loop.ph:192 br label %loop193 194loop:195 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]196 %cmp = icmp ult i64 %iv, 10197 br i1 %cmp, label %if.then, label %if.else198 199if.then:200 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv201 %val = load i64, ptr %src.arrayidx202 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv203 store i64 %val, ptr %dst.arrayidx204 br label %for.inc205 206if.else:207 br label %for.inc208 209for.inc:210 %inc = add nuw nsw i64 %iv, 1211 %cond = icmp sgt i64 %inc, %n212 br i1 %cond, label %exit, label %loop213 214exit:215 ret void216}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 4229; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]230; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4231; 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]], 1236; 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 void240;241loop.ph:242 br label %loop243 244loop:245 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]246 %cmp = icmp ult i64 %iv, %a247 br i1 %cmp, label %if.then, label %if.else248 249if.then:250 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv251 %val = load i64, ptr %src.arrayidx252 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv253 store i64 %val, ptr %dst.arrayidx254 br label %for.inc255 256if.else:257 br label %for.inc258 259for.inc:260 %inc = add nuw nsw i64 %iv, 1261 %cond = icmp eq i64 %inc, %n262 br i1 %cond, label %exit, label %loop263 264exit:265 ret void266}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:%.*]], -1274; 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]], 10279; 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 4283; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]284; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4285; 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]], 1290; 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]], 10301; 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 4307; 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 4309; CHECK-NEXT: br label [[FOR_INC_SPLIT]]310; CHECK: for.inc.split:311; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1312; 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 void318;319loop.ph:320 br label %loop321 322loop:323 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]324 %cmp = icmp ult i64 %iv, 10325 br i1 %cmp, label %if.then, label %if.else326 327if.then:328 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv329 %val = load i64, ptr %src.arrayidx330 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv331 store i64 %val, ptr %dst.arrayidx332 br label %for.inc333 334if.else:335 br label %for.inc336 337for.inc:338 %inc = add nuw nsw i64 %iv, 1339 %cond = icmp eq i64 %inc, %n340 br i1 %cond, label %exit, label %loop341 342exit:343 ret void344}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 4357; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]358; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4359; 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]], 1364; 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 void368;369loop.ph:370 br label %loop371 372loop:373 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]374 %cmp = icmp ult i64 %iv, %a375 br i1 %cmp, label %if.then, label %if.else376 377if.then:378 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv379 %val = load i64, ptr %src.arrayidx380 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv381 store i64 %val, ptr %dst.arrayidx382 br label %for.inc383 384if.else:385 br label %for.inc386 387for.inc:388 %inc = add nuw nsw i64 %iv, 1389 %cond = icmp sge i64 %inc, %n390 br i1 %cond, label %exit, label %loop391 392exit:393 ret void394}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]], -1403; 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]], 10408; 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 4412; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]413; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4414; 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]], 1419; 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]], 10430; 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 4436; 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 4438; CHECK-NEXT: br label [[FOR_INC_SPLIT]]439; CHECK: for.inc.split:440; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1441; 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 void447;448loop.ph:449 br label %loop450 451loop:452 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]453 %cmp = icmp ult i64 %iv, 10454 br i1 %cmp, label %if.then, label %if.else455 456if.then:457 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv458 %val = load i64, ptr %src.arrayidx459 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv460 store i64 %val, ptr %dst.arrayidx461 br label %for.inc462 463if.else:464 br label %for.inc465 466for.inc:467 %inc = add nuw nsw i64 %iv, 1468 %cond = icmp sge i64 %inc, %n469 br i1 %cond, label %exit, label %loop470 471exit:472 ret void473}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 4486; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]487; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4488; 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]], 2493; 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 void497;498loop.ph:499 br label %loop500 501loop:502 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]503 %cmp = icmp ult i64 %iv, %a504 br i1 %cmp, label %if.then, label %if.else505 506if.then:507 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv508 %val = load i64, ptr %src.arrayidx509 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv510 store i64 %val, ptr %dst.arrayidx511 br label %for.inc512 513if.else:514 br label %for.inc515 516for.inc:517 %inc = add nuw nsw i64 %iv, 2518 %cond = icmp sgt i64 %inc, %n519 br i1 %cond, label %exit, label %loop520 521exit:522 ret void523}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]], 1532; 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]], 10537; 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 4541; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]542; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4543; 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]], 2548; 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]], 10559; 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 4565; 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 4567; CHECK-NEXT: br label [[FOR_INC_SPLIT]]568; CHECK: for.inc.split:569; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 2570; 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 void576;577loop.ph:578 br label %loop579 580loop:581 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]582 %cmp = icmp ult i64 %iv, 10583 br i1 %cmp, label %if.then, label %if.else584 585if.then:586 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv587 %val = load i64, ptr %src.arrayidx588 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv589 store i64 %val, ptr %dst.arrayidx590 br label %for.inc591 592if.else:593 br label %for.inc594 595for.inc:596 %inc = add nuw nsw i64 %iv, 2597 %cond = icmp sgt i64 %inc, %n598 br i1 %cond, label %exit, label %loop599 600exit:601 ret void602}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 4615; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]616; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4617; CHECK-NEXT: br label [[FOR_INC]]618; CHECK: for.inc:619; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1620; 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 void624;625loop.ph:626 br label %loop627 628loop:629 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]630 %cmp = icmp ult i64 %iv, %a631 br i1 %cmp, label %if.then, label %for.inc632 633if.then:634 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv635 %val = load i64, ptr %src.arrayidx636 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv637 store i64 %val, ptr %dst.arrayidx638 br label %for.inc639 640for.inc:641 %inc = add nuw nsw i64 %iv, 1642 %cond = icmp ne i64 %inc, %n643 br i1 %cond, label %exit, label %loop644 645exit:646 ret void647}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]], 10656; 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 4660; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]661; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4662; CHECK-NEXT: br label [[FOR_INC]]663; CHECK: for.inc:664; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1665; 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 void669;670loop.ph:671 br label %loop672 673loop:674 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]675 %cmp = icmp ult i64 %iv, 10676 br i1 %cmp, label %if.then, label %for.inc677 678if.then:679 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv680 %val = load i64, ptr %src.arrayidx681 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv682 store i64 %val, ptr %dst.arrayidx683 br label %for.inc684 685for.inc:686 %inc = add nuw nsw i64 %iv, 1687 %cond = icmp ne i64 %inc, %n688 br i1 %cond, label %exit, label %loop689 690exit:691 ret void692}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 4705; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]706; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4707; CHECK-NEXT: br label [[FOR_DEC]]708; CHECK: for.dec:709; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1710; 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 void714;715loop.ph:716 br label %loop717 718loop:719 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]720 %cmp = icmp ult i64 %iv, %a721 br i1 %cmp, label %if.then, label %for.dec722 723if.then:724 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv725 %val = load i64, ptr %src.arrayidx726 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv727 store i64 %val, ptr %dst.arrayidx728 br label %for.dec729 730for.dec:731 %dec = sub nuw nsw i64 %iv, 1732 %cond = icmp slt i64 %dec, %n733 br i1 %cond, label %exit, label %loop734 735exit:736 ret void737}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]], 10746; 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 4750; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]751; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4752; CHECK-NEXT: br label [[FOR_DEC]]753; CHECK: for.dec:754; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1755; 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 void759;760loop.ph:761 br label %loop762 763loop:764 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]765 %cmp = icmp ult i64 %iv, 10766 br i1 %cmp, label %if.then, label %for.dec767 768if.then:769 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv770 %val = load i64, ptr %src.arrayidx771 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv772 store i64 %val, ptr %dst.arrayidx773 br label %for.dec774 775for.dec:776 %dec = sub nuw nsw i64 %iv, 1777 %cond = icmp slt i64 %dec, %n778 br i1 %cond, label %exit, label %loop779 780exit:781 ret void782}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 4795; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]796; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4797; CHECK-NEXT: br label [[FOR_DEC]]798; CHECK: for.dec:799; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1800; 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 void804;805loop.ph:806 br label %loop807 808loop:809 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]810 %cmp = icmp ult i64 %iv, %a811 br i1 %cmp, label %if.then, label %for.dec812 813if.then:814 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv815 %val = load i64, ptr %src.arrayidx816 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv817 store i64 %val, ptr %dst.arrayidx818 br label %for.dec819 820for.dec:821 %dec = sub nuw nsw i64 %iv, 1822 %cond = icmp sle i64 %dec, %n823 br i1 %cond, label %exit, label %loop824 825exit:826 ret void827}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]], 10836; 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 4840; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]841; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4842; CHECK-NEXT: br label [[FOR_DEC]]843; CHECK: for.dec:844; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1845; 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 void849;850loop.ph:851 br label %loop852 853loop:854 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]855 %cmp = icmp ult i64 %iv, 10856 br i1 %cmp, label %if.then, label %for.dec857 858if.then:859 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv860 %val = load i64, ptr %src.arrayidx861 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv862 store i64 %val, ptr %dst.arrayidx863 br label %for.dec864 865for.dec:866 %dec = sub nuw nsw i64 %iv, 1867 %cond = icmp sle i64 %dec, %n868 br i1 %cond, label %exit, label %loop869 870exit:871 ret void872}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]], 10887; 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 4891; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]892; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4893; 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]], 1898; 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]], 10911; 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 4917; 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 4919; CHECK-NEXT: br label [[FOR_INC_SPLIT]]920; CHECK: for.inc.split:921; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1922; 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 void928;929loop.ph:930 br label %loop931 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, 10936 br i1 %cmp, label %if.then, label %if.else937 938if.then:939 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv940 %val = load i64, ptr %src.arrayidx941 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv942 store i64 %val, ptr %dst.arrayidx943 br label %for.inc944 945if.else:946 br label %for.inc947 948for.inc:949 %inc = add nuw nsw i64 %iv, 1950 %cond = icmp sgt i64 %inc, %n951 br i1 %cond, label %exit, label %loop952 953exit:954 ret void955}956 957declare i64 @llvm.umax.i64(i64, i64)958