Skip to content

Commit a1f2aa4

Browse files
fhahnJaddyen
authored andcommitted
[LoopPeel] Add tests for peeling from end with variable trip counts.
Add more test coverage for peeling the last iteration with variable trip counts. Separate test cases for constant and variable trip counts in different files.
1 parent e838bbf commit a1f2aa4

File tree

2 files changed

+199
-39
lines changed

2 files changed

+199
-39
lines changed

llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll renamed to llvm/test/Transforms/LoopUnroll/peel-last-iteration-with-constant-trip-count.ll

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -397,45 +397,6 @@ exit:
397397
ret i64 %iv
398398
}
399399

400-
define i64 @peel_single_block_loop_iv_step_1_may_execute_only_once(i64 %n) {
401-
; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_may_execute_only_once(
402-
; CHECK-SAME: i64 [[N:%.*]]) {
403-
; CHECK-NEXT: [[ENTRY:.*]]:
404-
; CHECK-NEXT: [[N_NOT_0:%.*]] = icmp ne i64 [[N]], 0
405-
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_0]])
406-
; CHECK-NEXT: [[SUB:%.*]] = add nsw i64 [[N]], 1
407-
; CHECK-NEXT: br label %[[LOOP:.*]]
408-
; CHECK: [[LOOP]]:
409-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
410-
; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], [[N]]
411-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 20
412-
; CHECK-NEXT: call void @foo(i32 [[COND]])
413-
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
414-
; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], [[N]]
415-
; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]
416-
; CHECK: [[EXIT]]:
417-
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]
418-
; CHECK-NEXT: ret i64 [[IV_LCSSA]]
419-
;
420-
entry:
421-
%n.not.0 = icmp ne i64 %n, 0
422-
call void @llvm.assume(i1 %n.not.0)
423-
%sub = add nsw i64 %n, 1
424-
br label %loop
425-
426-
loop:
427-
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
428-
%cmp = icmp eq i64 %iv, %n
429-
%cond = select i1 %cmp, i32 10, i32 20
430-
call void @foo(i32 %cond)
431-
%iv.next = add i64 %iv, 1
432-
%ec = icmp ne i64 %iv.next, %n
433-
br i1 %ec, label %loop, label %exit
434-
435-
exit:
436-
ret i64 %iv
437-
}
438-
439400
define i64 @peel_single_block_loop_iv_step_neg_1() {
440401
; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_neg_1() {
441402
; CHECK-NEXT: [[ENTRY:.*]]:
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -p loop-unroll -unroll-full-max-count=0 -S %s | FileCheck %s
3+
4+
5+
declare void @foo(i32)
6+
7+
define i32 @peel_last_with_trip_count_check_lcssa_phi(i32 %n) {
8+
; CHECK-LABEL: define i32 @peel_last_with_trip_count_check_lcssa_phi(
9+
; CHECK-SAME: i32 [[N:%.*]]) {
10+
; CHECK-NEXT: [[ENTRY:.*]]:
11+
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[N]], -1
12+
; CHECK-NEXT: br label %[[LOOP:.*]]
13+
; CHECK: [[LOOP]]:
14+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
15+
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[IV]], [[SUB]]
16+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 1, i32 2
17+
; CHECK-NEXT: call void @foo(i32 [[SEL]])
18+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
19+
; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[IV_NEXT]], [[N]]
20+
; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]
21+
; CHECK: [[EXIT]]:
22+
; CHECK-NEXT: [[SEL_LCSSA:%.*]] = phi i32 [ [[SEL]], %[[LOOP]] ]
23+
; CHECK-NEXT: ret i32 [[SEL_LCSSA]]
24+
;
25+
entry:
26+
%sub = add i32 %n, -1
27+
br label %loop
28+
29+
loop:
30+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
31+
%c = icmp eq i32 %iv, %sub
32+
%sel = select i1 %c, i32 1, i32 2
33+
call void @foo(i32 %sel)
34+
%iv.next = add i32 %iv, 1
35+
%ec = icmp ne i32 %iv.next, %n
36+
br i1 %ec, label %loop, label %exit
37+
38+
exit:
39+
%sel.lcssa = phi i32 [ %sel, %loop ]
40+
ret i32 %sel.lcssa
41+
}
42+
43+
define i32 @peel_last_with_trip_count_check_lcssa_phi_step_2(i32 %n) {
44+
; CHECK-LABEL: define i32 @peel_last_with_trip_count_check_lcssa_phi_step_2(
45+
; CHECK-SAME: i32 [[N:%.*]]) {
46+
; CHECK-NEXT: [[ENTRY:.*]]:
47+
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[N]], -2
48+
; CHECK-NEXT: br label %[[LOOP:.*]]
49+
; CHECK: [[LOOP]]:
50+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
51+
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[IV]], [[SUB]]
52+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 1, i32 2
53+
; CHECK-NEXT: call void @foo(i32 [[SEL]])
54+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 2
55+
; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[IV_NEXT]], [[N]]
56+
; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]
57+
; CHECK: [[EXIT]]:
58+
; CHECK-NEXT: [[SEL_LCSSA:%.*]] = phi i32 [ [[SEL]], %[[LOOP]] ]
59+
; CHECK-NEXT: ret i32 [[SEL_LCSSA]]
60+
;
61+
entry:
62+
%sub = add i32 %n, -2
63+
br label %loop
64+
65+
loop:
66+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
67+
%c = icmp eq i32 %iv, %sub
68+
%sel = select i1 %c, i32 1, i32 2
69+
call void @foo(i32 %sel)
70+
%iv.next = add i32 %iv, 2
71+
%ec = icmp ne i32 %iv.next, %n
72+
br i1 %ec, label %loop, label %exit
73+
74+
exit:
75+
%sel.lcssa = phi i32 [ %sel, %loop ]
76+
ret i32 %sel.lcssa
77+
}
78+
79+
define i64 @peel_single_block_loop_iv_step_1_may_execute_only_once(i64 %n) {
80+
; CHECK-LABEL: define i64 @peel_single_block_loop_iv_step_1_may_execute_only_once(
81+
; CHECK-SAME: i64 [[N:%.*]]) {
82+
; CHECK-NEXT: [[ENTRY:.*]]:
83+
; CHECK-NEXT: [[N_NOT_0:%.*]] = icmp ne i64 [[N]], 0
84+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_0]])
85+
; CHECK-NEXT: [[SUB:%.*]] = add nsw i64 [[N]], 1
86+
; CHECK-NEXT: br label %[[LOOP:.*]]
87+
; CHECK: [[LOOP]]:
88+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
89+
; CHECK-NEXT: [[CMP18_NOT:%.*]] = icmp eq i64 [[IV]], [[N]]
90+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP18_NOT]], i32 10, i32 20
91+
; CHECK-NEXT: call void @foo(i32 [[COND]])
92+
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
93+
; CHECK-NEXT: [[EC:%.*]] = icmp ne i64 [[IV_NEXT]], [[N]]
94+
; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]
95+
; CHECK: [[EXIT]]:
96+
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], %[[LOOP]] ]
97+
; CHECK-NEXT: ret i64 [[IV_LCSSA]]
98+
;
99+
entry:
100+
%n.not.0 = icmp ne i64 %n, 0
101+
call void @llvm.assume(i1 %n.not.0)
102+
%sub = add nsw i64 %n, 1
103+
br label %loop
104+
105+
loop:
106+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
107+
%cmp = icmp eq i64 %iv, %n
108+
%cond = select i1 %cmp, i32 10, i32 20
109+
call void @foo(i32 %cond)
110+
%iv.next = add i64 %iv, 1
111+
%ec = icmp ne i64 %iv.next, %n
112+
br i1 %ec, label %loop, label %exit
113+
114+
exit:
115+
ret i64 %iv
116+
}
117+
118+
119+
120+
define i32 @peel_last_with_trip_count_check_lcssa_phi_cmp_not_invar(i32 %n) {
121+
; CHECK-LABEL: define i32 @peel_last_with_trip_count_check_lcssa_phi_cmp_not_invar(
122+
; CHECK-SAME: i32 [[N:%.*]]) {
123+
; CHECK-NEXT: [[ENTRY:.*]]:
124+
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[N]], -2
125+
; CHECK-NEXT: br label %[[LOOP:.*]]
126+
; CHECK: [[LOOP]]:
127+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
128+
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[IV]], [[SUB]]
129+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 1, i32 2
130+
; CHECK-NEXT: call void @foo(i32 [[SEL]])
131+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
132+
; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[IV_NEXT]], [[N]]
133+
; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]]
134+
; CHECK: [[EXIT]]:
135+
; CHECK-NEXT: [[SEL_LCSSA:%.*]] = phi i32 [ [[SEL]], %[[LOOP]] ]
136+
; CHECK-NEXT: ret i32 [[SEL_LCSSA]]
137+
;
138+
entry:
139+
%sub = add i32 %n, -2
140+
br label %loop
141+
142+
loop:
143+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
144+
%c = icmp eq i32 %iv, %sub
145+
%sel = select i1 %c, i32 1, i32 2
146+
call void @foo(i32 %sel)
147+
%iv.next = add i32 %iv, 1
148+
%ec = icmp ne i32 %iv.next, %n
149+
br i1 %ec, label %loop, label %exit
150+
151+
exit:
152+
%sel.lcssa = phi i32 [ %sel, %loop ]
153+
ret i32 %sel.lcssa
154+
}
155+
156+
157+
define void @peel_last_with_trip_count_check_nested_loop(i32 %n) {
158+
; CHECK-LABEL: define void @peel_last_with_trip_count_check_nested_loop(
159+
; CHECK-SAME: i32 [[N:%.*]]) {
160+
; CHECK-NEXT: [[ENTRY:.*:]]
161+
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[N]], -1
162+
; CHECK-NEXT: br label %[[OUTER_HEADER:.*]]
163+
; CHECK: [[OUTER_HEADER_LOOPEXIT:.*]]:
164+
; CHECK-NEXT: br label %[[OUTER_HEADER]]
165+
; CHECK: [[OUTER_HEADER]]:
166+
; CHECK-NEXT: br label %[[INNER_HEADER:.*]]
167+
; CHECK: [[INNER_HEADER]]:
168+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[OUTER_HEADER]] ], [ [[IV_NEXT:%.*]], %[[INNER_LATCH:.*]] ]
169+
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[IV]], [[SUB]]
170+
; CHECK-NEXT: br i1 [[C]], label %[[INNER_LATCH]], label %[[THEN:.*]]
171+
; CHECK: [[THEN]]:
172+
; CHECK-NEXT: call void @foo(i32 1)
173+
; CHECK-NEXT: br label %[[INNER_LATCH]]
174+
; CHECK: [[INNER_LATCH]]:
175+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
176+
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV_NEXT]], [[N]]
177+
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[OUTER_HEADER_LOOPEXIT]], label %[[INNER_HEADER]]
178+
;
179+
entry:
180+
%sub = add i32 %n, -1
181+
br label %outer.header
182+
183+
outer.header:
184+
br label %inner.header
185+
186+
inner.header:
187+
%iv = phi i32 [ 0, %outer.header ], [ %iv.next, %inner.latch ]
188+
%c = icmp eq i32 %iv, %sub
189+
br i1 %c, label %inner.latch, label %then
190+
191+
then:
192+
call void @foo(i32 1)
193+
br label %inner.latch
194+
195+
inner.latch:
196+
%iv.next = add i32 %iv, 1
197+
%exitcond.not = icmp eq i32 %iv.next, %n
198+
br i1 %exitcond.not, label %outer.header, label %inner.header
199+
}

0 commit comments

Comments
 (0)