1 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve.fp -passes=loop-vectorize -tail-predication=enabled -S < %s | \
4 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
6 ; Test that ARMTTIImpl::preferPredicateOverEpilogue triggers tail-folding.
8 define dso_local void @f1(ptr noalias nocapture %A, ptr noalias nocapture readonly %B, ptr noalias nocapture readonly %C, i32 %N) {
11 ; CHECK: @llvm.get.active.lane.mask
14 %cmp8 = icmp sgt i32 %N, 0
15 br i1 %cmp8, label %for.body.preheader, label %for.cond.cleanup
17 for.body.preheader: ; preds = %entry
20 for.cond.cleanup.loopexit: ; preds = %for.body
21 br label %for.cond.cleanup
23 for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
26 for.body: ; preds = %for.body.preheader, %for.body
27 %i.09 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
28 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.09
29 %0 = load i32, ptr %arrayidx, align 4
30 %arrayidx1 = getelementptr inbounds i32, ptr %C, i32 %i.09
31 %1 = load i32, ptr %arrayidx1, align 4
32 %add = add nsw i32 %1, %0
33 %arrayidx2 = getelementptr inbounds i32, ptr %A, i32 %i.09
34 store i32 %add, ptr %arrayidx2, align 4
35 %inc = add nuw nsw i32 %i.09, 1
36 %exitcond.not = icmp eq i32 %inc, %N
37 br i1 %exitcond.not, label %for.cond.cleanup.loopexit, label %for.body
40 define dso_local void @f32_reduction(ptr nocapture readonly %Input, i32 %N, ptr nocapture %Output) {
41 ; CHECK-LABEL: f32_reduction(
43 ; CHECK: @llvm.masked.load
44 ; CHECK: br i1 %{{.*}}, label {{.*}}, label %vector.body
46 %cmp6 = icmp eq i32 %N, 0
47 br i1 %cmp6, label %while.end, label %while.body.preheader
49 while.body.preheader: ; preds = %entry
52 while.body: ; preds = %while.body.preheader, %while.body
53 %blkCnt.09 = phi i32 [ %dec, %while.body ], [ %N, %while.body.preheader ]
54 %sum.08 = phi float [ %add, %while.body ], [ 0.000000e+00, %while.body.preheader ]
55 %Input.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %Input, %while.body.preheader ]
56 %incdec.ptr = getelementptr inbounds float, ptr %Input.addr.07, i32 1
57 %0 = load float, ptr %Input.addr.07, align 4
58 %add = fadd fast float %0, %sum.08
59 %dec = add i32 %blkCnt.09, -1
60 %cmp = icmp eq i32 %dec, 0
61 br i1 %cmp, label %while.end.loopexit, label %while.body
63 while.end.loopexit: ; preds = %while.body
64 %add.lcssa = phi float [ %add, %while.body ]
67 while.end: ; preds = %while.end.loopexit, %entry
68 %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add.lcssa, %while.end.loopexit ]
69 %conv = uitofp i32 %N to float
70 %div = fdiv fast float %sum.0.lcssa, %conv
71 store float %div, ptr %Output, align 4
75 define dso_local void @f16_reduction(ptr nocapture readonly %Input, i32 %N, ptr nocapture %Output) {
76 ; CHECK-LABEL: f16_reduction(
78 ; CHECK: @llvm.masked.load
79 ; CHECK: br i1 %{{.*}}, label {{.*}}, label %vector.body
81 %cmp6 = icmp eq i32 %N, 0
82 br i1 %cmp6, label %while.end, label %while.body.preheader
84 while.body.preheader: ; preds = %entry
87 while.body: ; preds = %while.body.preheader, %while.body
88 %blkCnt.09 = phi i32 [ %dec, %while.body ], [ %N, %while.body.preheader ]
89 %sum.08 = phi half [ %add, %while.body ], [ 0.000000e+00, %while.body.preheader ]
90 %Input.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %Input, %while.body.preheader ]
91 %incdec.ptr = getelementptr inbounds half, ptr %Input.addr.07, i32 1
92 %0 = load half, ptr %Input.addr.07, align 2
93 %add = fadd fast half %0, %sum.08
94 %dec = add i32 %blkCnt.09, -1
95 %cmp = icmp eq i32 %dec, 0
96 br i1 %cmp, label %while.end.loopexit, label %while.body
98 while.end.loopexit: ; preds = %while.body
99 %add.lcssa = phi half [ %add, %while.body ]
102 while.end: ; preds = %while.end.loopexit, %entry
103 %sum.0.lcssa = phi half [ 0.000000e+00, %entry ], [ %add.lcssa, %while.end.loopexit ]
104 %conv = uitofp i32 %N to half
105 %div = fdiv fast half %sum.0.lcssa, %conv
106 store half %div, ptr %Output, align 2
110 define dso_local void @mixed_f32_i32_reduction(ptr nocapture readonly %fInput, ptr nocapture readonly %iInput, i32 %N, ptr nocapture %fOutput, ptr nocapture %iOutput) {
111 ; CHECK-LABEL: mixed_f32_i32_reduction(
112 ; CHECK: vector.body:
113 ; CHECK: @llvm.masked.load
114 ; CHECK: br i1 %{{.*}}, label {{.*}}, label %vector.body
116 %cmp15 = icmp eq i32 %N, 0
117 br i1 %cmp15, label %while.end, label %while.body.preheader
119 while.body.preheader:
123 %blkCnt.020 = phi i32 [ %dec, %while.body ], [ %N, %while.body.preheader ]
124 %isum.019 = phi i32 [ %add2, %while.body ], [ 0, %while.body.preheader ]
125 %fsum.018 = phi float [ %add, %while.body ], [ 0.000000e+00, %while.body.preheader ]
126 %fInput.addr.017 = phi ptr [ %incdec.ptr, %while.body ], [ %fInput, %while.body.preheader ]
127 %iInput.addr.016 = phi ptr [ %incdec.ptr1, %while.body ], [ %iInput, %while.body.preheader ]
128 %incdec.ptr = getelementptr inbounds float, ptr %fInput.addr.017, i32 1
129 %incdec.ptr1 = getelementptr inbounds i32, ptr %iInput.addr.016, i32 1
130 %0 = load i32, ptr %iInput.addr.016, align 4
131 %add2 = add nsw i32 %0, %isum.019
132 %1 = load float, ptr %fInput.addr.017, align 4
133 %add = fadd fast float %1, %fsum.018
134 %dec = add i32 %blkCnt.020, -1
135 %cmp = icmp eq i32 %dec, 0
136 br i1 %cmp, label %while.end.loopexit, label %while.body
139 %add.lcssa = phi float [ %add, %while.body ]
140 %add2.lcssa = phi i32 [ %add2, %while.body ]
141 %phitmp = sitofp i32 %add2.lcssa to float
145 %fsum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add.lcssa, %while.end.loopexit ]
146 %isum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %phitmp, %while.end.loopexit ]
147 %conv = uitofp i32 %N to float
148 %div = fdiv fast float %fsum.0.lcssa, %conv
149 store float %div, ptr %fOutput, align 4
150 %div5 = fdiv fast float %isum.0.lcssa, %conv
151 %conv6 = fptosi float %div5 to i32
152 store i32 %conv6, ptr %iOutput, align 4
156 define dso_local i32 @i32_mul_reduction(ptr noalias nocapture readonly %B, i32 %N) {
157 ; CHECK-LABEL: i32_mul_reduction(
158 ; CHECK: vector.body:
159 ; CHECK: @llvm.masked.load
160 ; CHECK: br i1 %{{.*}}, label {{.*}}, label %vector.body
162 %cmp6 = icmp sgt i32 %N, 0
163 br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup
168 for.cond.cleanup.loopexit:
169 %mul.lcssa = phi i32 [ %mul, %for.body ]
170 br label %for.cond.cleanup
173 %S.0.lcssa = phi i32 [ 1, %entry ], [ %mul.lcssa, %for.cond.cleanup.loopexit ]
177 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
178 %S.07 = phi i32 [ %mul, %for.body ], [ 1, %for.body.preheader ]
179 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.08
180 %0 = load i32, ptr %arrayidx, align 4
181 %mul = mul nsw i32 %0, %S.07
182 %inc = add nuw nsw i32 %i.08, 1
183 %exitcond = icmp eq i32 %inc, %N
184 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body
187 define dso_local i32 @i32_or_reduction(ptr noalias nocapture readonly %B, i32 %N) {
188 ; CHECK-LABEL: i32_or_reduction(
189 ; CHECK: vector.body:
190 ; CHECK: @llvm.masked.load
191 ; CHECK: br i1 %{{.*}}, label {{.*}}, label %vector.body
193 %cmp6 = icmp sgt i32 %N, 0
194 br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup
196 for.body.preheader: ; preds = %entry
199 for.cond.cleanup.loopexit: ; preds = %for.body
200 %or.lcssa = phi i32 [ %or, %for.body ]
201 br label %for.cond.cleanup
203 for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
204 %S.0.lcssa = phi i32 [ 1, %entry ], [ %or.lcssa, %for.cond.cleanup.loopexit ]
207 for.body: ; preds = %for.body.preheader, %for.body
208 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
209 %S.07 = phi i32 [ %or, %for.body ], [ 1, %for.body.preheader ]
210 %arrayidx = getelementptr inbounds i32, ptr %B, i32 %i.08
211 %0 = load i32, ptr %arrayidx, align 4
212 %or = or i32 %0, %S.07
213 %inc = add nuw nsw i32 %i.08, 1
214 %exitcond = icmp eq i32 %inc, %N
215 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body
218 define dso_local i32 @i32_and_reduction(ptr noalias nocapture readonly %A, i32 %N, i32 %S) {
219 ; CHECK-LABEL: i32_and_reduction(
220 ; CHECK: vector.body:
221 ; CHECK: @llvm.masked.load
222 ; CHECK: br i1 %{{.*}}, label {{.*}}, label %vector.body
224 %cmp5 = icmp sgt i32 %N, 0
225 br i1 %cmp5, label %for.body.preheader, label %for.cond.cleanup
227 for.body.preheader: ; preds = %entry
230 for.cond.cleanup.loopexit: ; preds = %for.body
231 %and.lcssa = phi i32 [ %and, %for.body ]
232 br label %for.cond.cleanup
234 for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
235 %S.addr.0.lcssa = phi i32 [ %S, %entry ], [ %and.lcssa, %for.cond.cleanup.loopexit ]
236 ret i32 %S.addr.0.lcssa
238 for.body: ; preds = %for.body.preheader, %for.body
239 %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
240 %S.addr.06 = phi i32 [ %and, %for.body ], [ %S, %for.body.preheader ]
241 %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.07
242 %0 = load i32, ptr %arrayidx, align 4
243 %and = and i32 %0, %S.addr.06
244 %inc = add nuw nsw i32 %i.07, 1
245 %exitcond = icmp eq i32 %inc, %N
246 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body