332 lines · plain
1; RUN: opt -mtriple armv7-linux-gnueabihf -passes=loop-vectorize -S %s -debug-only=loop-vectorize --disable-output -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LINUX2; RUN: opt -mtriple armv8-linux-gnu -passes=loop-vectorize -S %s -debug-only=loop-vectorize --disable-output -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LINUX3; RUN: opt -mtriple armv8.1.m-none-eabi -mattr=+mve.fp -passes=loop-vectorize -S %s -debug-only=loop-vectorize --disable-output -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=MVE4; RUN: opt -mtriple armv7-unknwon-darwin -passes=loop-vectorize -S %s -debug-only=loop-vectorize --disable-output -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=DARWIN5; REQUIRES: asserts6 7target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"8 9; Testing the ability of the loop vectorizer to tell when SIMD is safe or not10; regarding IEEE 754 standard.11; On Linux, we only want the vectorizer to work when -ffast-math flag is set,12; because NEON is not IEEE compliant.13; Darwin, on the other hand, doesn't support subnormals, and all optimizations14; are allowed, even without -ffast-math.15 16; Integer loops are always vectorizeable17; CHECK: Checking a loop in 'sumi'18; CHECK: We can vectorize this loop!19define void @sumi(ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B, ptr noalias nocapture %C, i32 %N) {20entry:21 %cmp5 = icmp eq i32 %N, 022 br i1 %cmp5, label %for.end, label %for.body.preheader23 24for.body.preheader: ; preds = %entry25 br label %for.body26 27for.body: ; preds = %for.body.preheader, %for.body28 %i.06 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]29 %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.0630 %0 = load i32, ptr %arrayidx, align 431 %arrayidx1 = getelementptr inbounds i32, ptr %B, i32 %i.0632 %1 = load i32, ptr %arrayidx1, align 433 %mul = mul nsw i32 %1, %034 %arrayidx2 = getelementptr inbounds i32, ptr %C, i32 %i.0635 store i32 %mul, ptr %arrayidx2, align 436 %inc = add nuw nsw i32 %i.06, 137 %exitcond = icmp eq i32 %inc, %N38 br i1 %exitcond, label %for.end.loopexit, label %for.body39 40for.end.loopexit: ; preds = %for.body41 br label %for.end42 43for.end: ; preds = %for.end.loopexit, %entry44 ret void45}46 47; Floating-point loops need fast-math to be vectorizeable48; LINUX: Checking a loop in 'sumf'49; LINUX: Potentially unsafe FP op prevents vectorization50; MVE: Checking a loop in 'sumf'51; MVE: We can vectorize this loop!52; DARWIN: Checking a loop in 'sumf'53; DARWIN: We can vectorize this loop!54define void @sumf(ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B, ptr noalias nocapture %C, i32 %N) {55entry:56 %cmp5 = icmp eq i32 %N, 057 br i1 %cmp5, label %for.end, label %for.body.preheader58 59for.body.preheader: ; preds = %entry60 br label %for.body61 62for.body: ; preds = %for.body.preheader, %for.body63 %i.06 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]64 %arrayidx = getelementptr inbounds float, ptr %A, i32 %i.0665 %0 = load float, ptr %arrayidx, align 466 %arrayidx1 = getelementptr inbounds float, ptr %B, i32 %i.0667 %1 = load float, ptr %arrayidx1, align 468 %mul = fmul float %0, %169 %arrayidx2 = getelementptr inbounds float, ptr %C, i32 %i.0670 store float %mul, ptr %arrayidx2, align 471 %inc = add nuw nsw i32 %i.06, 172 %exitcond = icmp eq i32 %inc, %N73 br i1 %exitcond, label %for.end.loopexit, label %for.body74 75for.end.loopexit: ; preds = %for.body76 br label %for.end77 78for.end: ; preds = %for.end.loopexit, %entry79 ret void80}81 82; Integer loops are always vectorizeable83; CHECK: Checking a loop in 'redi'84; CHECK: We can vectorize this loop!85define i32 @redi(ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b, i32 %N) {86entry:87 br label %for.body.preheader88 89for.body.preheader: ; preds = %entry90 br label %for.body91 92for.body: ; preds = %for.body.preheader, %for.body93 %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]94 %Red.06 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]95 %arrayidx = getelementptr inbounds i32, ptr %a, i32 %i.0796 %0 = load i32, ptr %arrayidx, align 497 %arrayidx1 = getelementptr inbounds i32, ptr %b, i32 %i.0798 %1 = load i32, ptr %arrayidx1, align 499 %mul = mul nsw i32 %1, %0100 %add = add nsw i32 %mul, %Red.06101 %inc = add nuw nsw i32 %i.07, 1102 %exitcond = icmp eq i32 %inc, %N103 br i1 %exitcond, label %for.end.loopexit, label %for.body104 105for.end.loopexit: ; preds = %for.body106 %add.lcssa = phi i32 [ %add, %for.body ]107 br label %for.end108 109for.end: ; preds = %for.end.loopexit110 ret i32 %add.lcssa111}112 113; Floating-point loops need fast-math to be vectorizeable114; LINUX: Checking a loop in 'redf'115; LINUX: Potentially unsafe FP op prevents vectorization116; MVE: Checking a loop in 'redf'117; MVE: We can vectorize this loop!118; DARWIN: Checking a loop in 'redf'119; DARWIN: We can vectorize this loop!120define float @redf(ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b, i32 %N) {121entry:122 br label %for.body.preheader123 124for.body.preheader: ; preds = %entry125 br label %for.body126 127for.body: ; preds = %for.body.preheader, %for.body128 %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]129 %Red.06 = phi float [ %add, %for.body ], [ 0.0e+00, %for.body.preheader ]130 %arrayidx = getelementptr inbounds float, ptr %a, i32 %i.07131 %0 = load float, ptr %arrayidx, align 4132 %arrayidx1 = getelementptr inbounds float, ptr %b, i32 %i.07133 %1 = load float, ptr %arrayidx1, align 4134 %mul = fmul float %0, %1135 %add = fadd float %Red.06, %mul136 %inc = add nuw nsw i32 %i.07, 1137 %exitcond = icmp eq i32 %inc, %N138 br i1 %exitcond, label %for.end.loopexit, label %for.body139 140for.end.loopexit: ; preds = %for.body141 %add.lcssa = phi float [ %add, %for.body ]142 br label %for.end143 144for.end: ; preds = %for.end.loopexit145 ret float %add.lcssa146}147 148; Make sure calls that turn into builtins are also covered149; LINUX: Checking a loop in 'fabs'150; LINUX: Potentially unsafe FP op prevents vectorization151; DARWIN: Checking a loop in 'fabs'152; DARWIN: We can vectorize this loop!153define void @fabs(ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B, ptr noalias nocapture %C, i32 %N) {154entry:155 %cmp10 = icmp eq i32 %N, 0156 br i1 %cmp10, label %for.end, label %for.body157 158for.body: ; preds = %entry, %for.body159 %i.011 = phi i32 [ %inc, %for.body ], [ 0, %entry ]160 %arrayidx = getelementptr inbounds float, ptr %A, i32 %i.011161 %0 = load float, ptr %arrayidx, align 4162 %arrayidx1 = getelementptr inbounds float, ptr %B, i32 %i.011163 %1 = load float, ptr %arrayidx1, align 4164 %fabsf = tail call float @fabsf(float %1) #1165 %conv3 = fmul float %0, %fabsf166 %arrayidx4 = getelementptr inbounds float, ptr %C, i32 %i.011167 store float %conv3, ptr %arrayidx4, align 4168 %inc = add nuw nsw i32 %i.011, 1169 %exitcond = icmp eq i32 %inc, %N170 br i1 %exitcond, label %for.end, label %for.body171 172for.end: ; preds = %for.body, %entry173 ret void174}175 176; Integer loops are always vectorizeable177; CHECK: Checking a loop in 'sumi_fast'178; CHECK: We can vectorize this loop!179define void @sumi_fast(ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B, ptr noalias nocapture %C, i32 %N) {180entry:181 %cmp5 = icmp eq i32 %N, 0182 br i1 %cmp5, label %for.end, label %for.body.preheader183 184for.body.preheader: ; preds = %entry185 br label %for.body186 187for.body: ; preds = %for.body.preheader, %for.body188 %i.06 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]189 %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.06190 %0 = load i32, ptr %arrayidx, align 4191 %arrayidx1 = getelementptr inbounds i32, ptr %B, i32 %i.06192 %1 = load i32, ptr %arrayidx1, align 4193 %mul = mul nsw i32 %1, %0194 %arrayidx2 = getelementptr inbounds i32, ptr %C, i32 %i.06195 store i32 %mul, ptr %arrayidx2, align 4196 %inc = add nuw nsw i32 %i.06, 1197 %exitcond = icmp eq i32 %inc, %N198 br i1 %exitcond, label %for.end.loopexit, label %for.body199 200for.end.loopexit: ; preds = %for.body201 br label %for.end202 203for.end: ; preds = %for.end.loopexit, %entry204 ret void205}206 207; Floating-point loops can be vectorizeable with fast-math208; CHECK: Checking a loop in 'sumf_fast'209; CHECK: We can vectorize this loop!210define void @sumf_fast(ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B, ptr noalias nocapture %C, i32 %N) {211entry:212 %cmp5 = icmp eq i32 %N, 0213 br i1 %cmp5, label %for.end, label %for.body.preheader214 215for.body.preheader: ; preds = %entry216 br label %for.body217 218for.body: ; preds = %for.body.preheader, %for.body219 %i.06 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]220 %arrayidx = getelementptr inbounds float, ptr %A, i32 %i.06221 %0 = load float, ptr %arrayidx, align 4222 %arrayidx1 = getelementptr inbounds float, ptr %B, i32 %i.06223 %1 = load float, ptr %arrayidx1, align 4224 %mul = fmul fast float %1, %0225 %arrayidx2 = getelementptr inbounds float, ptr %C, i32 %i.06226 store float %mul, ptr %arrayidx2, align 4227 %inc = add nuw nsw i32 %i.06, 1228 %exitcond = icmp eq i32 %inc, %N229 br i1 %exitcond, label %for.end.loopexit, label %for.body230 231for.end.loopexit: ; preds = %for.body232 br label %for.end233 234for.end: ; preds = %for.end.loopexit, %entry235 ret void236}237 238; Integer loops are always vectorizeable239; CHECK: Checking a loop in 'redi_fast'240; CHECK: We can vectorize this loop!241define i32 @redi_fast(ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b, i32 %N) {242entry:243 %cmp5 = icmp eq i32 %N, 0244 br i1 %cmp5, label %for.end, label %for.body.preheader245 246for.body.preheader: ; preds = %entry247 br label %for.body248 249for.body: ; preds = %for.body.preheader, %for.body250 %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]251 %Red.06 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]252 %arrayidx = getelementptr inbounds i32, ptr %a, i32 %i.07253 %0 = load i32, ptr %arrayidx, align 4254 %arrayidx1 = getelementptr inbounds i32, ptr %b, i32 %i.07255 %1 = load i32, ptr %arrayidx1, align 4256 %mul = mul nsw i32 %1, %0257 %add = add nsw i32 %mul, %Red.06258 %inc = add nuw nsw i32 %i.07, 1259 %exitcond = icmp eq i32 %inc, %N260 br i1 %exitcond, label %for.end.loopexit, label %for.body261 262for.end.loopexit: ; preds = %for.body263 %add.lcssa = phi i32 [ %add, %for.body ]264 br label %for.end265 266for.end: ; preds = %for.end.loopexit, %entry267 %Red.0.lcssa = phi i32 [ 0, %entry ], [ %add.lcssa, %for.end.loopexit ]268 ret i32 %Red.0.lcssa269}270 271; Floating-point loops can be vectorizeable with fast-math272; CHECK: Checking a loop in 'redf_fast'273; CHECK: We can vectorize this loop!274define float @redf_fast(ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b, i32 %N) {275entry:276 br label %for.body.preheader277 278for.body.preheader: ; preds = %entry279 br label %for.body280 281for.body: ; preds = %for.body.preheader, %for.body282 %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]283 %Red.06 = phi float [ %add, %for.body ], [ 0.0e+00, %for.body.preheader ]284 %arrayidx = getelementptr inbounds float, ptr %a, i32 %i.07285 %0 = load float, ptr %arrayidx, align 4286 %arrayidx1 = getelementptr inbounds float, ptr %b, i32 %i.07287 %1 = load float, ptr %arrayidx1, align 4288 %mul = fmul fast float %1, %0289 %add = fadd fast float %mul, %Red.06290 %inc = add nuw nsw i32 %i.07, 1291 %exitcond = icmp eq i32 %inc, %N292 br i1 %exitcond, label %for.end.loopexit, label %for.body293 294for.end.loopexit: ; preds = %for.body295 %add.lcssa = phi float [ %add, %for.body ]296 br label %for.end297 298for.end: ; preds = %for.end.loopexit299 ret float %add.lcssa300}301 302; Make sure calls that turn into builtins are also covered303; CHECK: Checking a loop in 'fabs_fast'304; CHECK: We can vectorize this loop!305define void @fabs_fast(ptr noalias nocapture readonly %A, ptr noalias nocapture readonly %B, ptr noalias nocapture %C, i32 %N) {306entry:307 %cmp10 = icmp eq i32 %N, 0308 br i1 %cmp10, label %for.end, label %for.body309 310for.body: ; preds = %entry, %for.body311 %i.011 = phi i32 [ %inc, %for.body ], [ 0, %entry ]312 %arrayidx = getelementptr inbounds float, ptr %A, i32 %i.011313 %0 = load float, ptr %arrayidx, align 4314 %arrayidx1 = getelementptr inbounds float, ptr %B, i32 %i.011315 %1 = load float, ptr %arrayidx1, align 4316 %fabsf = tail call fast float @fabsf(float %1) #2317 %conv3 = fmul fast float %fabsf, %0318 %arrayidx4 = getelementptr inbounds float, ptr %C, i32 %i.011319 store float %conv3, ptr %arrayidx4, align 4320 %inc = add nuw nsw i32 %i.011, 1321 %exitcond = icmp eq i32 %inc, %N322 br i1 %exitcond, label %for.end, label %for.body323 324for.end: ; preds = %for.body, %entry325 ret void326}327 328declare float @fabsf(float)329 330attributes #1 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a8" "target-features"="+dsp,+neon,+vfp3" "use-soft-float"="false" }331attributes #2 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a8" "target-features"="+dsp,+neon,+vfp3" "use-soft-float"="false" }332