[llvm] 2a26d47 - [LoopBoundSplit] Check the start value of split cond AddRec
Jingu Kang via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 13 02:33:31 PDT 2021
Author: Jingu Kang
Date: 2021-09-13T10:32:35+01:00
New Revision: 2a26d47a2d8295f4555f615feb86d599ae2c3af7
URL: https://github.com/llvm/llvm-project/commit/2a26d47a2d8295f4555f615feb86d599ae2c3af7
DIFF: https://github.com/llvm/llvm-project/commit/2a26d47a2d8295f4555f615feb86d599ae2c3af7.diff
LOG: [LoopBoundSplit] Check the start value of split cond AddRec
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.
Differential Revision: https://reviews.llvm.org/D109354
Added:
Modified:
llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp
llvm/test/Transforms/LoopBoundSplit/bug51766.ll
llvm/test/Transforms/LoopBoundSplit/loop-bound-split.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp b/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp
index a89f0aa9e9e7d..00973a99737e1 100644
--- a/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopBoundSplit.cpp
@@ -265,6 +265,15 @@ static BranchInst *findSplitCandidate(const Loop &L, ScalarEvolution &SE,
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<SCEVAddRecExpr>(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
index a243a3da42de7..e2218a5f7cff7 100644
--- 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 @@ define i16 @main(i16 %qqq) {
; 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
index 1ad93f550e13d..eb1e3270e7708 100644
--- 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 @@ define void @split_loop_bound_inc_with_sgt(i64 %a, i64* noalias %src, i64* noali
; 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.ph:
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 @@ exit:
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 @@ define void @split_loop_bound_inc_with_eq(i64 %a, i64* noalias %src, i64* noalia
; 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.ph:
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 @@ exit:
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 @@ define void @split_loop_bound_inc_with_sge(i64 %a, i64* noalias %src, i64* noali
; 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.ph:
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 @@ exit:
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 @@ define void @split_loop_bound_inc_with_step_is_not_one(i64 %a, i64* noalias %src
; 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.ph:
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 @@ exit:
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.ph:
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 @@ exit:
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.ph:
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 @@ exit:
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.ph:
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 @@ exit:
}
; 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 @@ define void @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi(i64 %a, i64*
; 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.ph:
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 @@ exit:
ret void
}
+declare i64 @llvm.umax.i64(i64, i64)
More information about the llvm-commits
mailing list