1 ; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S < %s | FileCheck %s --check-prefix=CHECK
2 ; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=4 -S < %s | FileCheck %s --check-prefix=CHECK
3 ; RUN: opt -passes=loop-vectorize -force-vector-width=1 -force-vector-interleave=4 -S < %s | FileCheck %s --check-prefix=CHECK
5 define i64 @smax_idx(ptr nocapture readonly %a, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
6 ; CHECK-LABEL: @smax_idx(
7 ; CHECK-NOT: vector.body:
13 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
14 %max.09 = phi i64 [ %mm, %entry ], [ %1, %for.body ]
15 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
16 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
17 %0 = load i64, ptr %arrayidx
18 %1 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
19 %cmp1 = icmp slt i64 %max.09, %0
20 %spec.select7 = select i1 %cmp1, i64 %indvars.iv, i64 %idx.011
21 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
22 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
23 br i1 %exitcond.not, label %exit, label %for.body
26 store i64 %1, ptr %res_max
31 ; Check the different order of reduction phis.
33 define i64 @smax_idx_inverted_phi(ptr nocapture readonly %a, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
34 ; CHECK-LABEL: @smax_idx_inverted_phi(
35 ; CHECK-NOT: vector.body:
41 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
42 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
43 %max.09 = phi i64 [ %mm, %entry ], [ %1, %for.body ]
44 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
45 %0 = load i64, ptr %arrayidx
46 %1 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
47 %cmp1 = icmp slt i64 %max.09, %0
48 %spec.select7 = select i1 %cmp1, i64 %indvars.iv, i64 %idx.011
49 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
50 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
51 br i1 %exitcond.not, label %exit, label %for.body
54 store i64 %1, ptr %res_max
58 ; Check if it is a min/max with index (MMI) pattern when the
59 ; min/max value is not used outside the loop.
61 ; Currently, the vectorizer checks if smax value is used outside
62 ; the loop. However, even if only the index part has external users,
63 ; and smax itself does not have external users, it can still form a
66 define i64 @smax_idx_max_no_exit_user(ptr nocapture readonly %a, i64 %mm, i64 %ii, i64 %n) {
67 ; CHECK-LABEL: @smax_idx_max_no_exit_user(
68 ; CHECK-NOT: vector.body:
74 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
75 %max.09 = phi i64 [ %mm, %entry ], [ %1, %for.body ]
76 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
77 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
78 %0 = load i64, ptr %arrayidx
79 %1 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
80 %cmp1 = icmp slt i64 %max.09, %0
81 %spec.select7 = select i1 %cmp1, i64 %indvars.iv, i64 %idx.011
82 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
83 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
84 br i1 %exitcond.not, label %exit, label %for.body
87 ; %1 has no external users
91 ; Check smax implemented by select(cmp()).
93 ; Currently, MMI pattern does not support icmp with multiple users.
94 ; TODO: It may be possible to reuse some of the methods in instcombine pass to
95 ; check whether icmp can be duplicated.
97 define i64 @smax_idx_select_cmp(ptr nocapture readonly %a, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
98 ; CHECK-LABEL: @smax_idx_select_cmp(
99 ; CHECK-NOT: vector.body:
105 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
106 %max.09 = phi i64 [ %mm, %entry ], [ %spec.select, %for.body ]
107 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
108 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
109 %0 = load i64, ptr %arrayidx
110 %cmp1 = icmp slt i64 %max.09, %0
111 %spec.select = select i1 %cmp1, i64 %0, i64 %max.09
112 %spec.select7 = select i1 %cmp1, i64 %indvars.iv, i64 %idx.011
113 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
114 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
115 br i1 %exitcond.not, label %exit, label %for.body
118 store i64 %spec.select, ptr %res_max
119 ret i64 %spec.select7
125 define i64 @smax_idx_inverted_pred(ptr nocapture readonly %a, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
126 ; CHECK-LABEL: @smax_idx_inverted_pred(
127 ; CHECK-NOT: vector.body:
133 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
134 %max.09 = phi i64 [ %mm, %entry ], [ %1, %for.body ]
135 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
136 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
137 %0 = load i64, ptr %arrayidx
138 %1 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
139 %cmp1 = icmp sge i64 %0, %max.09
140 %spec.select7 = select i1 %cmp1, i64 %indvars.iv, i64 %idx.011
141 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
142 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
143 br i1 %exitcond.not, label %exit, label %for.body
146 store i64 %1, ptr %res_max
147 ret i64 %spec.select7
151 ; In such cases, the last index should be extracted.
153 define i64 @smax_idx_extract_last(ptr nocapture readonly %a, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
154 ; CHECK-LABEL: @smax_idx_extract_last(
155 ; CHECK-NOT: vector.body:
161 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
162 %max.09 = phi i64 [ %mm, %entry ], [ %1, %for.body ]
163 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
164 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
165 %0 = load i64, ptr %arrayidx
166 %1 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
167 %cmp1.not = icmp sgt i64 %max.09, %0
168 %spec.select7 = select i1 %cmp1.not, i64 %idx.011, i64 %indvars.iv
169 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
170 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
171 br i1 %exitcond.not, label %exit, label %for.body
174 store i64 %1, ptr %res_max
175 ret i64 %spec.select7
179 ; The operands of smax intrinsic and icmp are not the same to be recognized as MMI.
181 define i64 @smax_idx_not_vec_1(ptr nocapture readonly %a, ptr nocapture readonly %b, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
182 ; CHECK-LABEL: @smax_idx_not_vec_1(
183 ; CHECK-NOT: vector.body:
189 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
190 %max.09 = phi i64 [ %mm, %entry ], [ %2, %for.body ]
191 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
192 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
193 %0 = load i64, ptr %arrayidx
194 %arrayidx.01 = getelementptr inbounds i64, ptr %b, i64 %indvars.iv
195 %1 = load i64, ptr %arrayidx
196 %2 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
197 %cmp1 = icmp slt i64 %max.09, %1
198 %spec.select7 = select i1 %cmp1, i64 %indvars.iv, i64 %idx.011
199 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
200 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
201 br i1 %exitcond.not, label %exit, label %for.body
204 store i64 %2, ptr %res_max
205 ret i64 %spec.select7
209 ; It cannot be recognized as MMI when the operand of index select is not an induction variable.
211 define i64 @smax_idx_not_vec_2(ptr nocapture readonly %a, i64 %mm, i64 %ii, ptr nocapture writeonly %res_max, i64 %n) {
212 ; CHECK-LABEL: @smax_idx_not_vec_2(
213 ; CHECK-NOT: vector.body:
219 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
220 %max.09 = phi i64 [ %mm, %entry ], [ %1, %for.body ]
221 %idx.011 = phi i64 [ %ii, %entry ], [ %spec.select7, %for.body ]
222 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
223 %0 = load i64, ptr %arrayidx
224 %1 = tail call i64 @llvm.smax.i64(i64 %max.09, i64 %0)
225 %cmp1 = icmp slt i64 %max.09, %0
226 %spec.select7 = select i1 %cmp1, i64 123, i64 %idx.011
227 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
228 %exitcond.not = icmp eq i64 %indvars.iv.next, %n
229 br i1 %exitcond.not, label %exit, label %for.body
232 store i64 %1, ptr %res_max
233 ret i64 %spec.select7
236 declare i64 @llvm.smax.i64(i64, i64)