Skip to content

Commit fded6f7

Browse files
committed
[LoopUnroll] Add multi-exit test which does not exit through latch.
This patch adds a new test for loop-unrolling with multiple exiting blocks, where the latch does not exit, but the header does. This can happen when the loop has not been rotated, e.g. due to minsize. Inspired by the following end-to-end test, using -Oz https://godbolt.org/z/fP6sna8qK bool foo(int *ptr, int limit) { #pragma clang loop unroll(full) for (unsigned int i = 0; i < 4; i++) { if (ptr[i] > limit) return false; ptr[i]++; } return true; }
1 parent f4c0fdc commit fded6f7

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -loop-unroll -S %s | FileCheck %s
3+
4+
; Loop with multiple exiting blocks, where the header exits but not the latch,
5+
; e.g. because it has not been rotated.
6+
define i16 @full_unroll_multiple_exiting_blocks(i16* %A, i16 %x, i16 %y) {
7+
; CHECK-LABEL: @full_unroll_multiple_exiting_blocks(
8+
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: br label [[HEADER:%.*]]
10+
; CHECK: header:
11+
; CHECK-NEXT: [[RES:%.*]] = phi i16 [ 123, [[ENTRY:%.*]] ], [ [[RES_NEXT:%.*]], [[LATCH:%.*]] ]
12+
; CHECK-NEXT: [[I_0:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INC9:%.*]], [[LATCH]] ]
13+
; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i64 [[I_0]]
14+
; CHECK-NEXT: [[LV:%.*]] = load i16, i16* [[PTR]], align 2
15+
; CHECK-NEXT: [[RES_NEXT]] = add i16 [[RES]], [[LV]]
16+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[I_0]], 3
17+
; CHECK-NEXT: br i1 [[CMP]], label [[EXITING_1:%.*]], label [[EXIT:%.*]]
18+
; CHECK: exiting.1:
19+
; CHECK-NEXT: [[EC_1:%.*]] = icmp eq i16 [[LV]], [[X:%.*]]
20+
; CHECK-NEXT: br i1 [[EC_1]], label [[EXIT]], label [[EXITING_2:%.*]]
21+
; CHECK: exiting.2:
22+
; CHECK-NEXT: [[EC_2:%.*]] = icmp eq i16 [[LV]], [[Y:%.*]]
23+
; CHECK-NEXT: br i1 [[EC_2]], label [[EXIT]], label [[LATCH]]
24+
; CHECK: latch:
25+
; CHECK-NEXT: [[INC9]] = add i64 [[I_0]], 1
26+
; CHECK-NEXT: br label [[HEADER]]
27+
; CHECK: exit:
28+
; CHECK-NEXT: [[RES_LCSSA:%.*]] = phi i16 [ [[RES_NEXT]], [[HEADER]] ], [ 0, [[EXITING_1]] ], [ 1, [[EXITING_2]] ]
29+
; CHECK-NEXT: ret i16 [[RES_LCSSA]]
30+
;
31+
entry:
32+
br label %header
33+
34+
header:
35+
%res = phi i16 [ 123, %entry ], [ %res.next, %latch ]
36+
%i.0 = phi i64 [ 0, %entry ], [ %inc9, %latch ]
37+
%ptr = getelementptr inbounds i16, i16* %A, i64 %i.0
38+
%lv = load i16, i16* %ptr
39+
%res.next = add i16 %res, %lv
40+
%cmp = icmp ult i64 %i.0, 3
41+
br i1 %cmp, label %exiting.1, label %exit
42+
43+
exiting.1:
44+
%ec.1 = icmp eq i16 %lv, %x
45+
br i1 %ec.1, label %exit, label %exiting.2
46+
47+
exiting.2:
48+
%ec.2 = icmp eq i16 %lv, %y
49+
br i1 %ec.2, label %exit, label %latch
50+
51+
latch:
52+
%inc9 = add i64 %i.0, 1
53+
br label %header
54+
55+
exit:
56+
%res.lcssa = phi i16 [ %res.next, %header ], [ 0, %exiting.1 ], [ 1, %exiting.2 ]
57+
ret i16 %res.lcssa
58+
}

0 commit comments

Comments
 (0)