llvm-project/llvm/test/Transforms/LoopUnroll/peel-loop-conditions.ll
Serguei Katkov bbdcc82111 [Loop Peeling] Do not close further unroll/peel if profile based peeling was not used.
Current peeling cost model can decide to peel off not all iterations
but only some of them to eliminate conditions on phi. At the same time 
if any peeling happens the door for further unroll/peel optimizations on that
loop closes because the part of the code thinks that if peeling happened
it is profile based peeling and all iterations are peeled off.

To resolve this inconsistency the patch provides the flag which states whether
the full peeling basing on profile is enabled or not and peeling cost model
is able to modify this field like it does not PeelCount.

In a separate patch I will introduce an option to allow/disallow peeling basing
on profile.

To avoid infinite loop peeling the patch tracks the total number of peeled iteration
through llvm.loop.peeled.count loop metadata.

Reviewers: reames, fhahn
Reviewed By: reames
Subscribers: hiraditya, zzheng, dmgreen, llvm-commits
Differential Revision: https://reviews.llvm.org/D64972

llvm-svn: 367647
2019-08-02 04:29:23 +00:00

646 lines
22 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -S -loop-unroll -verify-dom-info | FileCheck %s
declare void @f1()
declare void @f2()
; Check that we can peel off iterations that make conditions true.
define void @test1(i32 %k) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]]
; CHECK: for.body.peel.begin:
; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]]
; CHECK: for.body.peel:
; CHECK-NEXT: [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2
; CHECK-NEXT: br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
; CHECK: if.else.peel:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC_PEEL:%.*]]
; CHECK: if.then.peel:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL]]
; CHECK: for.inc.peel:
; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i32 0, 1
; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%[^,]*]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next:
; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]]
; CHECK: for.body.peel2:
; CHECK-NEXT: [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2
; CHECK-NEXT: br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
; CHECK: if.else.peel4:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC_PEEL6:%.*]]
; CHECK: if.then.peel5:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL6]]
; CHECK: for.inc.peel6:
; CHECK-NEXT: [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1
; CHECK-NEXT: [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]]
; CHECK-NEXT: br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next1:
; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT9:%.*]]
; CHECK: for.body.peel.next9:
; CHECK-NEXT: br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
; CHECK: for.body.lr.ph.peel.newph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC_PEEL7]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: if.else:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !{{.*}}
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp ult i32 %i.05, 2
br i1 %cmp1, label %if.then, label %if.else
if.then:
call void @f1()
br label %for.inc
if.else:
call void @f2()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end, !llvm.loop !1
for.end:
ret void
}
!1 = distinct !{!1}
; Check we peel off the maximum number of iterations that make conditions true.
define void @test2(i32 %k) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]]
; CHECK: for.body.peel.begin:
; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]]
; CHECK: for.body.peel:
; CHECK-NEXT: [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2
; CHECK-NEXT: br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
; CHECK: if.else.peel:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[IF2_PEEL:%.*]]
; CHECK: if.then.peel:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[IF2_PEEL]]
; CHECK: if2.peel:
; CHECK-NEXT: [[CMP2_PEEL:%.*]] = icmp ult i32 0, 4
; CHECK-NEXT: br i1 [[CMP2_PEEL]], label [[IF_THEN2_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]]
; CHECK: if.then2.peel:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL]]
; CHECK: for.inc.peel:
; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i32 0, 1
; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%[^,]*]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next:
; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]]
; CHECK: for.body.peel2:
; CHECK-NEXT: [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2
; CHECK-NEXT: br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
; CHECK: if.else.peel4:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[IF2_PEEL6:%.*]]
; CHECK: if.then.peel5:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[IF2_PEEL6]]
; CHECK: if2.peel6:
; CHECK-NEXT: [[CMP2_PEEL7:%.*]] = icmp ult i32 [[INC_PEEL]], 4
; CHECK-NEXT: br i1 [[CMP2_PEEL7]], label [[IF_THEN2_PEEL8:%.*]], label [[FOR_INC_PEEL9:%.*]]
; CHECK: if.then2.peel8:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL9]]
; CHECK: for.inc.peel9:
; CHECK-NEXT: [[INC_PEEL10:%.*]] = add nsw i32 [[INC_PEEL]], 1
; CHECK-NEXT: [[CMP_PEEL11:%.*]] = icmp slt i32 [[INC_PEEL10]], [[K]]
; CHECK-NEXT: br i1 [[CMP_PEEL11]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next1:
; CHECK-NEXT: br label [[FOR_BODY_PEEL13:%.*]]
; CHECK: for.body.peel13:
; CHECK-NEXT: [[CMP1_PEEL14:%.*]] = icmp ult i32 [[INC_PEEL10]], 2
; CHECK-NEXT: br i1 [[CMP1_PEEL14]], label [[IF_THEN_PEEL16:%.*]], label [[IF_ELSE_PEEL15:%.*]]
; CHECK: if.else.peel15:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[IF2_PEEL17:%.*]]
; CHECK: if.then.peel16:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[IF2_PEEL17]]
; CHECK: if2.peel17:
; CHECK-NEXT: [[CMP2_PEEL18:%.*]] = icmp ult i32 [[INC_PEEL10]], 4
; CHECK-NEXT: br i1 [[CMP2_PEEL18]], label [[IF_THEN2_PEEL19:%.*]], label [[FOR_INC_PEEL20:%.*]]
; CHECK: if.then2.peel19:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL20]]
; CHECK: for.inc.peel20:
; CHECK-NEXT: [[INC_PEEL21:%.*]] = add nsw i32 [[INC_PEEL10]], 1
; CHECK-NEXT: [[CMP_PEEL22:%.*]] = icmp slt i32 [[INC_PEEL21]], [[K]]
; CHECK-NEXT: br i1 [[CMP_PEEL22]], label [[FOR_BODY_PEEL_NEXT12:%.*]], label [[FOR_END]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next12:
; CHECK-NEXT: br label [[FOR_BODY_PEEL24:%.*]]
; CHECK: for.body.peel24:
; CHECK-NEXT: [[CMP1_PEEL25:%.*]] = icmp ult i32 [[INC_PEEL21]], 2
; CHECK-NEXT: br i1 [[CMP1_PEEL25]], label [[IF_THEN_PEEL27:%.*]], label [[IF_ELSE_PEEL26:%.*]]
; CHECK: if.else.peel26:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[IF2_PEEL28:%.*]]
; CHECK: if.then.peel27:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[IF2_PEEL28]]
; CHECK: if2.peel28:
; CHECK-NEXT: [[CMP2_PEEL29:%.*]] = icmp ult i32 [[INC_PEEL21]], 4
; CHECK-NEXT: br i1 [[CMP2_PEEL29]], label [[IF_THEN2_PEEL30:%.*]], label [[FOR_INC_PEEL31:%.*]]
; CHECK: if.then2.peel30:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL31]]
; CHECK: for.inc.peel31:
; CHECK-NEXT: [[INC_PEEL32:%.*]] = add nsw i32 [[INC_PEEL21]], 1
; CHECK-NEXT: [[CMP_PEEL33:%.*]] = icmp slt i32 [[INC_PEEL32]], [[K]]
; CHECK-NEXT: br i1 [[CMP_PEEL33]], label [[FOR_BODY_PEEL_NEXT23:%.*]], label [[FOR_END]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next23:
; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT34:%.*]]
; CHECK: for.body.peel.next34:
; CHECK-NEXT: br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
; CHECK: for.body.lr.ph.peel.newph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC_PEEL32]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[IF2:%.*]]
; CHECK: if.else:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[IF2]]
; CHECK: if2:
; CHECK-NEXT: br i1 false, label [[IF_THEN2:%.*]], label [[FOR_INC]]
; CHECK: if.then2:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !{{.*}}
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp ult i32 %i.05, 2
br i1 %cmp1, label %if.then, label %if.else
if.then:
call void @f1()
br label %if2
if.else:
call void @f2()
br label %if2
if2:
%cmp2 = icmp ult i32 %i.05, 4
br i1 %cmp2, label %if.then2, label %for.inc
if.then2:
call void @f1()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end, !llvm.loop !2
for.end:
ret void
}
!2 = distinct !{!2}
; Check that we can peel off iterations that make a condition false.
define void @test3(i32 %k) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]]
; CHECK: for.body.peel.begin:
; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]]
; CHECK: for.body.peel:
; CHECK-NEXT: [[CMP1_PEEL:%.*]] = icmp ugt i32 0, 2
; CHECK-NEXT: br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
; CHECK: if.else.peel:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC_PEEL:%.*]]
; CHECK: if.then.peel:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL]]
; CHECK: for.inc.peel:
; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i32 0, 1
; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%[^,]*]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next:
; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]]
; CHECK: for.body.peel2:
; CHECK-NEXT: [[CMP1_PEEL3:%.*]] = icmp ugt i32 [[INC_PEEL]], 2
; CHECK-NEXT: br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
; CHECK: if.else.peel4:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC_PEEL6:%.*]]
; CHECK: if.then.peel5:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL6]]
; CHECK: for.inc.peel6:
; CHECK-NEXT: [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1
; CHECK-NEXT: [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]]
; CHECK-NEXT: br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next1:
; CHECK-NEXT: br label [[FOR_BODY_PEEL10:%.*]]
; CHECK: for.body.peel10:
; CHECK-NEXT: [[CMP1_PEEL11:%.*]] = icmp ugt i32 [[INC_PEEL7]], 2
; CHECK-NEXT: br i1 [[CMP1_PEEL11]], label [[IF_THEN_PEEL13:%.*]], label [[IF_ELSE_PEEL12:%.*]]
; CHECK: if.else.peel12:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC_PEEL14:%.*]]
; CHECK: if.then.peel13:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC_PEEL14]]
; CHECK: for.inc.peel14:
; CHECK-NEXT: [[INC_PEEL15:%.*]] = add nsw i32 [[INC_PEEL7]], 1
; CHECK-NEXT: [[CMP_PEEL16:%.*]] = icmp slt i32 [[INC_PEEL15]], [[K]]
; CHECK-NEXT: br i1 [[CMP_PEEL16]], label [[FOR_BODY_PEEL_NEXT9:%.*]], label [[FOR_END]]
; Verify that MD_loop metadata is dropped.
; CHECK-NOT: , !llvm.loop !{{[0-9]*}}
; CHECK: for.body.peel.next9:
; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT17:%.*]]
; CHECK: for.body.peel.next17:
; CHECK-NEXT: br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
; CHECK: for.body.lr.ph.peel.newph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC_PEEL15]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: if.else:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !{{.*}}
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp ugt i32 %i.05, 2
br i1 %cmp1, label %if.then, label %if.else
if.then:
call void @f1()
br label %for.inc
if.else:
call void @f2()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end, !llvm.loop !3
for.end:
ret void
}
!3 = distinct !{!3}
; Test that we only peel off iterations if it simplifies a condition in the
; loop body after peeling at most MaxPeelCount iterations.
define void @test4(i32 %k) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[I_05]], 9999
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp ugt i32 %i.05, 9999
br i1 %cmp1, label %if.then, label %for.inc
if.then:
call void @f1()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
}
; In this case we cannot peel the inner loop, because the condition involves
; the outer induction variable.
define void @test5(i32 %k) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer.header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[J_INC:%.*]], [[OUTER_INC:%.*]] ]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[J]], 2
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: if.else:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[OUTER_INC]]
; CHECK: outer.inc:
; CHECK-NEXT: [[J_INC]] = add nsw i32 [[J]], 1
; CHECK-NEXT: [[OUTER_CMP:%.*]] = icmp slt i32 [[J_INC]], [[K]]
; CHECK-NEXT: br i1 [[OUTER_CMP]], label [[OUTER_HEADER]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %outer.header
outer.header:
%j = phi i32 [ 0, %for.body.lr.ph ], [ %j.inc, %outer.inc ]
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %outer.header ], [ %inc, %for.inc ]
%cmp1 = icmp ult i32 %j, 2
br i1 %cmp1, label %if.then, label %if.else
if.then:
call void @f1()
br label %for.inc
if.else:
call void @f2()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %outer.inc
outer.inc:
%j.inc = add nsw i32 %j, 1
%outer.cmp = icmp slt i32 %j.inc, %k
br i1 %outer.cmp, label %outer.header, label %for.end
for.end:
ret void
}
; In this test, the condition involves 2 AddRecs. Without evaluating both
; AddRecs, we cannot prove that the condition becomes known in the loop body
; after peeling.
define void @test6(i32 %k) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 4, [[ENTRY]] ], [ [[J_INC:%.*]], [[FOR_INC]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[I_05]], [[J]]
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: if.else:
; CHECK-NEXT: call void @f2()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 2
; CHECK-NEXT: [[J_INC]] = add nsw i32 [[J]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
%j = phi i32 [ 4, %entry ], [ %j.inc, %for.inc ]
%cmp1 = icmp ult i32 %i.05, %j
br i1 %cmp1, label %if.then, label %if.else
if.then:
call void @f1()
br label %for.inc
if.else:
call void @f2()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 2
%j.inc = add nsw i32 %j, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
}
define void @test7(i32 %k) {
; FIXME: Could simplify loop body by peeling one additional iteration after
; i != 3 becomes false
; CHECK-LABEL: @test7(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[I_05]], 3
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp ne i32 %i.05, 3
br i1 %cmp1, label %if.then, label %for.inc
if.then:
call void @f1()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
}
define void @test8(i32 %k) {
; FIXME: Could simplify loop body by peeling one additional iteration after
; i == 3 becomes true.
; CHECK-LABEL: @test8(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[I_05]], 3
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp eq i32 %i.05, 3
br i1 %cmp1, label %if.then, label %for.inc
if.then:
call void @f1()
br label %for.inc
for.inc:
%inc = add nsw i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
}
; Comparison with non-monotonic predicate due to possible wrapping, loop
; body cannot be simplified.
define void @test9(i32 %k) {
; CHECK-LABEL: @test9(
; CHECK-NEXT: for.body.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[I_05]], 3
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
; CHECK: if.then:
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: [[INC]] = add i32 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
for.body.lr.ph:
br label %for.body
for.body:
%i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
%cmp1 = icmp slt i32 %i.05, 3
br i1 %cmp1, label %if.then, label %for.inc
if.then:
call void @f1()
br label %for.inc
for.inc:
%inc = add i32 %i.05, 1
%cmp = icmp slt i32 %inc, %k
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
}
; CHECK-NOT: llvm.loop.unroll.disable