xref: /llvm-project/llvm/test/Transforms/LoopVectorize/multi_early_exit_live_outs.ll (revision 13107cb09441dfeab24fcbcae9f4d3ba4cfc2703)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S < %s -p loop-vectorize -enable-early-exit-vectorization | FileCheck %s
3
4declare void @init_mem(ptr, i64);
5
6; There are multiple exit blocks - two of them have an exact representation for the
7; exit-not-taken counts and the other is unknown, i.e. the "early exit".
8define i64 @one_uncountable_two_countable_same_exit() {
9; CHECK-LABEL: define i64 @one_uncountable_two_countable_same_exit() {
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
12; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
13; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
14; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
15; CHECK-NEXT:    br label [[LOOP:%.*]]
16; CHECK:       loop:
17; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
18; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[INDEX]], 64
19; CHECK-NEXT:    br i1 [[CMP1]], label [[SEARCH:%.*]], label [[LOOP_END:%.*]]
20; CHECK:       search:
21; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
22; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
23; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
24; CHECK-NEXT:    [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
25; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]
26; CHECK-NEXT:    br i1 [[CMP3]], label [[LOOP_END]], label [[LOOP_INC]]
27; CHECK:       loop.inc:
28; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
29; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 128
30; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
31; CHECK:       loop.end:
32; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ 64, [[LOOP]] ], [ [[INDEX]], [[SEARCH]] ], [ 128, [[LOOP_INC]] ]
33; CHECK-NEXT:    ret i64 [[RETVAL]]
34;
35entry:
36  %p1 = alloca [1024 x i8]
37  %p2 = alloca [1024 x i8]
38  call void @init_mem(ptr %p1, i64 1024)
39  call void @init_mem(ptr %p2, i64 1024)
40  br label %loop
41
42loop:
43  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
44  %cmp1 = icmp ne i64 %index, 64
45  br i1 %cmp1, label %search, label %loop.end
46
47search:
48  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
49  %ld1 = load i8, ptr %arrayidx, align 1
50  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
51  %ld2 = load i8, ptr %arrayidx1, align 1
52  %cmp3 = icmp eq i8 %ld1, %ld2
53  br i1 %cmp3, label %loop.end, label %loop.inc
54
55loop.inc:
56  %index.next = add i64 %index, 1
57  %exitcond = icmp ne i64 %index.next, 128
58  br i1 %exitcond, label %loop, label %loop.end
59
60loop.end:
61  %retval = phi i64 [ 64, %loop ], [ %index, %search ], [ 128, %loop.inc ]
62  ret i64 %retval
63}
64
65
66define i64 @one_uncountable_two_countable_diff_exit() {
67; CHECK-LABEL: define i64 @one_uncountable_two_countable_diff_exit() {
68; CHECK-NEXT:  entry:
69; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
70; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
71; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
72; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
73; CHECK-NEXT:    br label [[LOOP:%.*]]
74; CHECK:       loop:
75; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
76; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[INDEX]], 64
77; CHECK-NEXT:    br i1 [[CMP1]], label [[SEARCH:%.*]], label [[LOOP_END:%.*]]
78; CHECK:       search:
79; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
80; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
81; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
82; CHECK-NEXT:    [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
83; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]
84; CHECK-NEXT:    br i1 [[CMP3]], label [[LOOP_END_EARLY:%.*]], label [[LOOP_INC]]
85; CHECK:       loop.inc:
86; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
87; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 128
88; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
89; CHECK:       loop.end.early:
90; CHECK-NEXT:    [[RET_EARLY:%.*]] = phi i64 [ [[INDEX]], [[SEARCH]] ]
91; CHECK-NEXT:    ret i64 [[RET_EARLY]]
92; CHECK:       loop.end:
93; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ 64, [[LOOP]] ], [ 128, [[LOOP_INC]] ]
94; CHECK-NEXT:    ret i64 [[RETVAL]]
95;
96entry:
97  %p1 = alloca [1024 x i8]
98  %p2 = alloca [1024 x i8]
99  call void @init_mem(ptr %p1, i64 1024)
100  call void @init_mem(ptr %p2, i64 1024)
101  br label %loop
102
103loop:
104  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
105  %cmp1 = icmp ne i64 %index, 64
106  br i1 %cmp1, label %search, label %loop.end
107
108search:
109  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
110  %ld1 = load i8, ptr %arrayidx, align 1
111  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
112  %ld2 = load i8, ptr %arrayidx1, align 1
113  %cmp3 = icmp eq i8 %ld1, %ld2
114  br i1 %cmp3, label %loop.end.early, label %loop.inc
115
116loop.inc:
117  %index.next = add i64 %index, 1
118  %exitcond = icmp ne i64 %index.next, 128
119  br i1 %exitcond, label %loop, label %loop.end
120
121loop.end.early:
122  %ret.early = phi i64 [ %index, %search ]
123  ret i64 %ret.early
124
125loop.end:
126  %retval = phi i64 [ 64, %loop ], [ 128, %loop.inc ]
127  ret i64 %retval
128}
129