diff --git a/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp b/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp --- a/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp +++ b/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp @@ -265,6 +265,15 @@ SplitCandidateCond.BoundSCEV->getType()) continue; + // After transformation, we assume the split condition of the pre-loop is + // always true. In order to guarantee it, we need to check the start value + // of the split cond AddRec satisfies the split condition. + const SCEV *SplitAddRecStartSCEV = + cast(SplitCandidateCond.AddRecSCEV)->getStart(); + if (!SE.isKnownPredicate(SplitCandidateCond.Pred, SplitAddRecStartSCEV, + SplitCandidateCond.BoundSCEV)) + continue; + SplitCandidateCond.BI = BI; return BI; } diff --git a/llvm/test/Transforms/LoopBoundSplit/bug51766.ll b/llvm/test/Transforms/LoopBoundSplit/bug51766.ll --- a/llvm/test/Transforms/LoopBoundSplit/bug51766.ll +++ b/llvm/test/Transforms/LoopBoundSplit/bug51766.ll @@ -7,16 +7,13 @@ define i16 @main(i16 %qqq) { ; CHECK-LABEL: @main( ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[ENTRY_SPLIT:%.*]] -; CHECK: entry.split: -; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i16 @llvm.umin.i16(i16 [[QQQ:%.*]], i16 2) ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[T0:%.*]] = phi i16 [ 0, [[ENTRY_SPLIT]] ], [ [[T8:%.*]], [[CONT19:%.*]] ] +; CHECK-NEXT: [[T0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[T8:%.*]], [[CONT19:%.*]] ] ; CHECK-NEXT: [[T1:%.*]] = shl nuw nsw i16 [[T0]], 1 -; CHECK-NEXT: [[T2:%.*]] = add i16 [[T1]], [[QQQ]] +; CHECK-NEXT: [[T2:%.*]] = add i16 [[T1]], [[QQQ:%.*]] ; CHECK-NEXT: [[DOTNOT9:%.*]] = icmp ult i16 [[T2]], [[QQQ]] -; CHECK-NEXT: br i1 true, label [[HANDLER_POINTER_OVERFLOW:%.*]], label [[CONT15_CRITEDGE:%.*]] +; CHECK-NEXT: br i1 [[DOTNOT9]], label [[HANDLER_POINTER_OVERFLOW:%.*]], label [[CONT15_CRITEDGE:%.*]] ; CHECK: handler.pointer_overflow: ; CHECK-NEXT: call void @__ubsan_handle_pointer_overflow() ; CHECK-NEXT: br label [[CONT19]] @@ -24,31 +21,8 @@ ; CHECK-NEXT: br label [[CONT19]] ; CHECK: cont19: ; CHECK-NEXT: [[T8]] = add nuw nsw i16 [[T0]], 1 -; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i16 [[T8]], [[NEW_BOUND]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[FOR_BODY]] -; CHECK: entry.split.split: -; CHECK-NEXT: [[T8_LCSSA:%.*]] = phi i16 [ [[T8]], [[CONT19]] ] -; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i16 [[T8_LCSSA]], 3 -; CHECK-NEXT: br i1 [[TMP0]], label [[FOR_BODY_SPLIT_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] -; CHECK: for.body.split.preheader: -; CHECK-NEXT: br label [[FOR_BODY_SPLIT:%.*]] -; CHECK: for.body.split: -; CHECK-NEXT: [[T0_SPLIT:%.*]] = phi i16 [ [[T8_SPLIT:%.*]], [[CONT19_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[FOR_BODY_SPLIT_PREHEADER]] ] -; CHECK-NEXT: [[T1_SPLIT:%.*]] = shl nuw nsw i16 [[T0_SPLIT]], 1 -; CHECK-NEXT: [[T2_SPLIT:%.*]] = add i16 [[T1_SPLIT]], [[QQQ]] -; CHECK-NEXT: [[DOTNOT9_SPLIT:%.*]] = icmp ult i16 [[T2_SPLIT]], [[QQQ]] -; CHECK-NEXT: br i1 false, label [[HANDLER_POINTER_OVERFLOW_SPLIT:%.*]], label [[CONT15_CRITEDGE_SPLIT:%.*]] -; CHECK: cont15.critedge.split: -; CHECK-NEXT: br label [[CONT19_SPLIT]] -; CHECK: handler.pointer_overflow.split: -; CHECK-NEXT: call void @__ubsan_handle_pointer_overflow() -; CHECK-NEXT: br label [[CONT19_SPLIT]] -; CHECK: cont19.split: -; CHECK-NEXT: [[T8_SPLIT]] = add nuw nsw i16 [[T0_SPLIT]], 1 -; CHECK-NEXT: [[EXITCOND_NOT_SPLIT:%.*]] = icmp eq i16 [[T8_SPLIT]], 3 -; CHECK-NEXT: br i1 [[EXITCOND_NOT_SPLIT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_SPLIT]] -; CHECK: for.cond.cleanup.loopexit: -; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i16 [[T8]], 3 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret i16 0 ; diff --git a/llvm/test/Transforms/LoopBoundSplit/loop-bound-split.ll b/llvm/test/Transforms/LoopBoundSplit/loop-bound-split.ll --- a/llvm/test/Transforms/LoopBoundSplit/loop-bound-split.ll +++ b/llvm/test/Transforms/LoopBoundSplit/loop-bound-split.ll @@ -1,17 +1,153 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -passes=loop-bound-split -S < %s | FileCheck %s -define void @split_loop_bound_inc_with_sgt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_inc_with_sgt( +; The transformation is failed with this test because we can not guarantee the +; split condition is always true in pre-loop after transformation. +define void @variable_split_loop_bound_and_exit_cond_inc_with_sgt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_sgt( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: if.else: +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %a + br i1 %cmp, label %if.then, label %if.else + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.inc + +if.else: + br label %for.inc + +for.inc: + %inc = add nuw nsw i64 %iv, 1 + %cond = icmp sgt i64 %inc, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +; The transformation works with this test because we can guarantee the split +; condition is always true in pre-loop after transformation. +define void @umax_variable_split_loop_bound_and_exit_cond_inc_with_sgt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @umax_variable_split_loop_bound_and_exit_cond_inc_with_sgt( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: [[B:%.*]] = call i64 @llvm.umax.i64(i64 [[A:%.*]], i64 1) +; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] +; CHECK: loop.ph.split: +; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) +; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 [[B]]) +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[B]] +; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: if.else: +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]] +; CHECK: loop.ph.split.split: +; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]] +; CHECK: loop.split.preheader: +; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] +; CHECK: loop.split: +; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] +; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], [[B]] +; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] +; CHECK: if.else.split: +; CHECK-NEXT: br label [[FOR_INC_SPLIT]] +; CHECK: if.then.split: +; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]] +; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]] +; CHECK-NEXT: store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4 +; CHECK-NEXT: br label [[FOR_INC_SPLIT]] +; CHECK: for.inc.split: +; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1 +; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]] +; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]] +; CHECK: exit.loopexit: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + %b = call i64 @llvm.umax.i64(i64 %a, i64 1) + br label %loop + +loop: + %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %b + br i1 %cmp, label %if.then, label %if.else + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.inc + +if.else: + br label %for.inc + +for.inc: + %inc = add nuw nsw i64 %iv, 1 + %cond = icmp sgt i64 %inc, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +; The transformation works with this test because we can guarantee the split +; condition is always true in pre-loop after transformation. +define void @constant_split_loop_bound_and_exit_cond_inc_with_sgt(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sgt( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] ; CHECK: loop.ph.split: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) -; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[SMAX]]) +; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 10) ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -33,7 +169,7 @@ ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] ; CHECK: loop.split: ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] -; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] +; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] ; CHECK: if.else.split: ; CHECK-NEXT: br label [[FOR_INC_SPLIT]] @@ -57,7 +193,7 @@ loop: %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %if.else if.then: @@ -79,17 +215,67 @@ ret void } -define void @split_loop_bound_inc_with_eq(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_inc_with_eq( +define void @variable_split_loop_bound_and_exit_cond_inc_with_eq(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_eq( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: if.else: +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %a + br i1 %cmp, label %if.then, label %if.else + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.inc + +if.else: + br label %for.inc + +for.inc: + %inc = add nuw nsw i64 %iv, 1 + %cond = icmp eq i64 %inc, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +define void @constant_split_loop_bound_and_exit_cond_inc_with_eq(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_eq( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] ; CHECK: loop.ph.split: ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1 -; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.umin.i64(i64 [[A:%.*]], i64 [[TMP0]]) +; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP0]], i64 10) ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -111,7 +297,7 @@ ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] ; CHECK: loop.split: ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] -; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] +; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] ; CHECK: if.else.split: ; CHECK-NEXT: br label [[FOR_INC_SPLIT]] @@ -135,7 +321,7 @@ loop: %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %if.else if.then: @@ -157,18 +343,68 @@ ret void } -define void @split_loop_bound_inc_with_sge(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_inc_with_sge( +define void @variable_split_loop_bound_and_exit_cond_inc_with_sge(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_sge( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: if.else: +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp sge i64 [[INC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %a + br i1 %cmp, label %if.then, label %if.else + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.inc + +if.else: + br label %for.inc + +for.inc: + %inc = add nuw nsw i64 %iv, 1 + %cond = icmp sge i64 %inc, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +define void @constant_split_loop_bound_and_exit_cond_inc_with_sge(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sge( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] ; CHECK: loop.ph.split: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1) ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1 -; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[TMP0]]) +; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 10) ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -190,7 +426,7 @@ ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] ; CHECK: loop.split: ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] -; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] +; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] ; CHECK: if.else.split: ; CHECK-NEXT: br label [[FOR_INC_SPLIT]] @@ -214,7 +450,7 @@ loop: %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %if.else if.then: @@ -236,18 +472,68 @@ ret void } -define void @split_loop_bound_inc_with_step_is_not_one(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_inc_with_step_is_not_one( +define void @variable_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_step_is_not_one( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: if.else: +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 2 +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %a + br i1 %cmp, label %if.then, label %if.else + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.inc + +if.else: + br label %for.inc + +for.inc: + %inc = add nuw nsw i64 %iv, 2 + %cond = icmp sgt i64 %inc, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +define void @constant_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_step_is_not_one( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] ; CHECK: loop.ph.split: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1) ; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[SMAX]], 1 -; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[TMP0]]) +; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 10) ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -269,7 +555,7 @@ ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]] ; CHECK: loop.split: ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] -; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] +; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] ; CHECK: if.else.split: ; CHECK-NEXT: br label [[FOR_INC_SPLIT]] @@ -293,7 +579,7 @@ loop: %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %if.else if.then: @@ -315,13 +601,13 @@ ret void } -define void @split_loop_bound_inc_with_ne(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_inc_with_ne( +define void @variable_split_loop_bound_and_exit_cond_inc_with_ne(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_ne( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -341,7 +627,7 @@ loop: %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, %a br i1 %cmp, label %if.then, label %for.inc if.then: @@ -360,13 +646,103 @@ ret void } -define void @split_loop_bound_dec_with_slt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_dec_with_slt( +define void @constant_split_loop_bound_and_exit_cond_inc_with_ne(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_ne( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, 10 + br i1 %cmp, label %if.then, label %for.inc + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.inc + +for.inc: + %inc = add nuw nsw i64 %iv, 1 + %cond = icmp ne i64 %inc, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +define void @varialbe_split_loop_bound_and_exit_cond_dec_with_slt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @varialbe_split_loop_bound_and_exit_cond_dec_with_slt( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_DEC]] +; CHECK: for.dec: +; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %a + br i1 %cmp, label %if.then, label %for.dec + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.dec + +for.dec: + %dec = sub nuw nsw i64 %iv, 1 + %cond = icmp slt i64 %dec, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +define void @constant_split_loop_bound_and_exit_cond_dec_with_slt(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_dec_with_slt( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -386,7 +762,7 @@ loop: %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %for.dec if.then: @@ -405,13 +781,58 @@ ret void } -define void @split_loop_bound_dec_with_sle(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_dec_with_sle( +define void @variable_split_loop_bound_and_exit_cond_dec_with_sle(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_dec_with_sle( +; CHECK-NEXT: loop.ph: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] +; CHECK: if.then: +; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] +; CHECK-NEXT: [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4 +; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]] +; CHECK-NEXT: store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[FOR_DEC]] +; CHECK: for.dec: +; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +loop.ph: + br label %loop + +loop: + %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] + %cmp = icmp ult i64 %iv, %a + br i1 %cmp, label %if.then, label %for.dec + +if.then: + %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv + %val = load i64, i64* %src.arrayidx + %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv + store i64 %val, i64* %dst.arrayidx + br label %for.dec + +for.dec: + %dec = sub nuw nsw i64 %iv, 1 + %cond = icmp sle i64 %dec, %n + br i1 %cond, label %exit, label %loop + +exit: + ret void +} + +define void @constant_split_loop_bound_and_exit_cond_dec_with_sle(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_dec_with_sle( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -431,7 +852,7 @@ loop: %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %for.dec if.then: @@ -451,18 +872,18 @@ } ; LoopBoundSplit pass should ignore phi which is not scevable phi. -define void @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) { -; CHECK-LABEL: @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi( +define void @constant_split_loop_bound_and_exit_cond_inc_with_sgt_and_is_not_scevable_phi(i64* noalias %src, i64* noalias %dst, i64 %n) { +; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sgt_and_is_not_scevable_phi( ; CHECK-NEXT: loop.ph: ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]] ; CHECK: loop.ph.split: ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0) -; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[SMAX]]) +; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 10) ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI:%.*]] = phi double [ 1.000000e+00, [[FOR_INC:%.*]] ], [ 2.000000e+00, [[LOOP_PH_SPLIT]] ] ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC]] ], [ 0, [[LOOP_PH_SPLIT]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]] @@ -485,7 +906,7 @@ ; CHECK: loop.split: ; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI_SPLIT:%.*]] = phi double [ 1.000000e+00, [[FOR_INC_SPLIT:%.*]] ], [ 2.000000e+00, [[LOOP_SPLIT_PREHEADER]] ] ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ] -; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]] +; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]] ; CHECK: if.else.split: ; CHECK-NEXT: br label [[FOR_INC_SPLIT]] @@ -510,7 +931,7 @@ loop: %is_not_scevable_phi = phi double [ 1.0, %for.inc ], [ 2.0, %loop.ph ] %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] - %cmp = icmp slt i64 %iv, %a + %cmp = icmp ult i64 %iv, 10 br i1 %cmp, label %if.then, label %if.else if.then: @@ -532,3 +953,4 @@ ret void } +declare i64 @llvm.umax.i64(i64, i64)