Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / AArch64 / scalable-call.ll
blob333bb20fd0d9aa4304088f281f5e99ca8e2b2ab6
1 ; RUN: opt -S -passes=loop-vectorize,instcombine -force-vector-interleave=1 -mattr=+sve -mtriple aarch64-unknown-linux-gnu \
2 ; RUN:     -prefer-predicate-over-epilogue=scalar-epilogue -pass-remarks-missed=loop-vectorize < %s 2>%t | FileCheck %s
3 ; RUN: cat %t | FileCheck %s --check-prefix=CHECK-REMARKS
4 ; RUN: opt -S -passes=loop-vectorize,instcombine -force-vector-interleave=1 -force-target-instruction-cost=1 -mattr=+sve -mtriple aarch64-unknown-linux-gnu \
5 ; RUN:     -prefer-predicate-over-epilogue=scalar-epilogue -pass-remarks-missed=loop-vectorize < %s 2>%t | FileCheck %s
6 ; RUN: cat %t | FileCheck %s --check-prefix=CHECK-REMARKS
8 define void @vec_load(i64 %N, ptr nocapture %a, ptr nocapture readonly %b) {
9 ; CHECK-LABEL: @vec_load
10 ; CHECK: vector.body:
11 ; CHECK: %[[LOAD:.*]] = load <vscale x 2 x double>, ptr
12 ; CHECK: call <vscale x 2 x double> @foo_vec(<vscale x 2 x double> %[[LOAD]])
13 entry:
14   %cmp7 = icmp sgt i64 %N, 0
15   br i1 %cmp7, label %for.body, label %for.end
17 for.body:                                         ; preds = %for.body.preheader, %for.body
18   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
19   %arrayidx = getelementptr inbounds double, ptr %b, i64 %iv
20   %0 = load double, ptr %arrayidx, align 8
21   %1 = call double @foo(double %0) #0
22   %add = fadd double %1, 1.000000e+00
23   %arrayidx2 = getelementptr inbounds double, ptr %a, i64 %iv
24   store double %add, ptr %arrayidx2, align 8
25   %iv.next = add nuw nsw i64 %iv, 1
26   %exitcond.not = icmp eq i64 %iv.next, %N
27   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !1
29 for.end:                                 ; preds = %for.body, %entry
30   ret void
33 define void @vec_scalar(i64 %N, ptr nocapture %a) {
34 ; CHECK-LABEL: @vec_scalar
35 ; CHECK: vector.body:
36 ; CHECK: call <vscale x 2 x double> @foo_vec(<vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double 1.000000e+01, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer))
37 entry:
38   %cmp7 = icmp sgt i64 %N, 0
39   br i1 %cmp7, label %for.body, label %for.end
41 for.body:                                         ; preds = %for.body.preheader, %for.body
42   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
43   %0 = call double @foo(double 10.0) #0
44   %sub = fsub double %0, 1.000000e+00
45   %arrayidx = getelementptr inbounds double, ptr %a, i64 %iv
46   store double %sub, ptr %arrayidx, align 8
47   %iv.next = add nuw nsw i64 %iv, 1
48   %exitcond.not = icmp eq i64 %iv.next, %N
49   br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !1
51 for.end:                                 ; preds = %for.body, %entry
52   ret void
55 define void @vec_ptr(i64 %N, ptr noalias %a, ptr readnone %b) {
56 ; CHECK-LABEL: @vec_ptr
57 ; CHECK: vector.body:
58 ; CHECK: %[[LOAD:.*]] = load <vscale x 2 x ptr>, ptr
59 ; CHECK: call <vscale x 2 x i64> @bar_vec(<vscale x 2 x ptr> %[[LOAD]])
60 entry:
61   %cmp7 = icmp sgt i64 %N, 0
62   br i1 %cmp7, label %for.body, label %for.end
64 for.body:
65   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
66   %gep = getelementptr ptr, ptr %b, i64 %iv
67   %load = load ptr, ptr %gep
68   %call = call i64 @bar(ptr %load) #1
69   %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv
70   store i64 %call, ptr %arrayidx
71   %iv.next = add nuw nsw i64 %iv, 1
72   %exitcond = icmp eq i64 %iv.next, 1024
73   br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !1
75 for.end:
76   ret void
79 define void @vec_intrinsic(i64 %N, ptr nocapture readonly %a) {
80 ; CHECK-LABEL: @vec_intrinsic
81 ; CHECK: vector.body:
82 ; CHECK: %[[LOAD:.*]] = load <vscale x 2 x double>, ptr
83 ; CHECK: call fast <vscale x 2 x double> @sin_vec_nxv2f64(<vscale x 2 x double> %[[LOAD]])
84 entry:
85   %cmp7 = icmp sgt i64 %N, 0
86   br i1 %cmp7, label %for.body, label %for.end
88 for.body:
89   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
90   %arrayidx = getelementptr inbounds double, ptr %a, i64 %iv
91   %0 = load double, ptr %arrayidx, align 8
92   %1 = call fast double @llvm.sin.f64(double %0) #2
93   %add = fadd fast double %1, 1.000000e+00
94   store double %add, ptr %arrayidx, align 8
95   %iv.next = add nuw nsw i64 %iv, 1
96   %exitcond = icmp eq i64 %iv.next, %N
97   br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !1
99 for.end:
100   ret void
103 ; CHECK-REMARKS: UserVF ignored because of invalid costs.
104 ; CHECK-REMARKS-NEXT: t.c:3:10: Instruction with invalid costs prevented vectorization at VF=(vscale x 1): load
105 ; CHECK-REMARKS-NEXT: t.c:3:20: Instruction with invalid costs prevented vectorization at VF=(vscale x 1, vscale x 2): call to llvm.sin.f32
106 ; CHECK-REMARKS-NEXT: t.c:3:30: Instruction with invalid costs prevented vectorization at VF=(vscale x 1): store
107 define void @vec_sin_no_mapping(ptr noalias nocapture %dst, ptr noalias nocapture readonly %src, i64 %n) {
108 ; CHECK: @vec_sin_no_mapping
109 ; CHECK: call fast <2 x float> @llvm.sin.v2f32
110 ; CHECK-NOT: <vscale x
111 entry:
112   br label %for.body
114 for.body:                                         ; preds = %entry, %for.body
115   %i.07 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
116   %arrayidx = getelementptr inbounds float, ptr %src, i64 %i.07
117   %0 = load float, ptr %arrayidx, align 4, !dbg !11
118   %1 = tail call fast float @llvm.sin.f32(float %0), !dbg !12
119   %arrayidx1 = getelementptr inbounds float, ptr %dst, i64 %i.07
120   store float %1, ptr %arrayidx1, align 4, !dbg !13
121   %inc = add nuw nsw i64 %i.07, 1
122   %exitcond.not = icmp eq i64 %inc, %n
123   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !1
125 for.cond.cleanup:                                 ; preds = %for.body
126   ret void
129 ; CHECK-REMARKS: UserVF ignored because of invalid costs.
130 ; CHECK-REMARKS-NEXT: t.c:3:10: Instruction with invalid costs prevented vectorization at VF=(vscale x 1): load
131 ; CHECK-REMARKS-NEXT: t.c:3:30: Instruction with invalid costs prevented vectorization at VF=(vscale x 1, vscale x 2): call to llvm.sin.f32
132 ; CHECK-REMARKS-NEXT: t.c:3:20: Instruction with invalid costs prevented vectorization at VF=(vscale x 1, vscale x 2): call to llvm.sin.f32
133 ; CHECK-REMARKS-NEXT: t.c:3:40: Instruction with invalid costs prevented vectorization at VF=(vscale x 1): store
134 define void @vec_sin_no_mapping_ite(ptr noalias nocapture %dst, ptr noalias nocapture readonly %src, i64 %n) {
135 ; CHECK: @vec_sin_no_mapping_ite
136 ; CHECK-NOT: <vscale x
137 ; CHECK: ret
138 entry:
139   br label %for.body
141 for.body:                                         ; preds = %entry, %if.end
142   %i.07 = phi i64 [ %inc, %if.end ], [ 0, %entry ]
143   %arrayidx = getelementptr inbounds float, ptr %src, i64 %i.07
144   %0 = load float, ptr %arrayidx, align 4, !dbg !11
145   %cmp = fcmp ugt float %0, 0.0000
146   br i1 %cmp, label %if.then, label %if.else
147 if.then:
148   %1 = tail call fast float @llvm.sin.f32(float %0), !dbg !12
149   br label %if.end
150 if.else:
151   %2 = tail call fast float @llvm.sin.f32(float 0.0), !dbg !13
152   br label %if.end
153 if.end:
154   %3 = phi float [%1, %if.then], [%2, %if.else]
155   %arrayidx1 = getelementptr inbounds float, ptr %dst, i64 %i.07
156   store float %3, ptr %arrayidx1, align 4, !dbg !14
157   %inc = add nuw nsw i64 %i.07, 1
158   %exitcond.not = icmp eq i64 %inc, %n
159   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !1
161 for.cond.cleanup:                                 ; preds = %for.body
162   ret void
165 ; CHECK-REMARKS: UserVF ignored because of invalid costs.
166 ; CHECK-REMARKS-NEXT: t.c:3:10: Instruction with invalid costs prevented vectorization at VF=(vscale x 1): load
167 ; CHECK-REMARKS-NEXT: t.c:3:20: Instruction with invalid costs prevented vectorization at VF=(vscale x 1, vscale x 2): call to llvm.sin.f32
168 ; CHECK-REMARKS-NEXT: t.c:3:30: Instruction with invalid costs prevented vectorization at VF=(vscale x 1): store
169 define void @vec_sin_fixed_mapping(ptr noalias nocapture %dst, ptr noalias nocapture readonly %src, i64 %n) {
170 ; CHECK: @vec_sin_fixed_mapping
171 ; CHECK: call fast <2 x float> @llvm.sin.v2f32
172 ; CHECK-NOT: <vscale x
173 entry:
174   br label %for.body
176 for.body:                                         ; preds = %entry, %for.body
177   %i.07 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
178   %arrayidx = getelementptr inbounds float, ptr %src, i64 %i.07
179   %0 = load float, ptr %arrayidx, align 4, !dbg !11
180   %1 = tail call fast float @llvm.sin.f32(float %0) #3, !dbg !12
181   %arrayidx1 = getelementptr inbounds float, ptr %dst, i64 %i.07
182   store float %1, ptr %arrayidx1, align 4, !dbg !13
183   %inc = add nuw nsw i64 %i.07, 1
184   %exitcond.not = icmp eq i64 %inc, %n
185   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !1
187 for.cond.cleanup:                                 ; preds = %for.body
188   ret void
191 ; Even though there are no function mappings attached to the call
192 ; in the loop below we can still vectorize the loop because SVE has
193 ; hardware support in the form of the 'fqsrt' instruction.
194 define void @vec_sqrt_no_mapping(ptr noalias nocapture %dst, ptr noalias nocapture readonly %src, i64 %n) {
195 ; CHECK: @vec_sqrt_no_mapping
196 ; CHECK: call fast <vscale x 2 x float> @llvm.sqrt.nxv2f32
197 entry:
198   br label %for.body
200 for.body:                                         ; preds = %entry, %for.body
201   %i.07 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
202   %arrayidx = getelementptr inbounds float, ptr %src, i64 %i.07
203   %0 = load float, ptr %arrayidx, align 4
204   %1 = tail call fast float @llvm.sqrt.f32(float %0)
205   %arrayidx1 = getelementptr inbounds float, ptr %dst, i64 %i.07
206   store float %1, ptr %arrayidx1, align 4
207   %inc = add nuw nsw i64 %i.07, 1
208   %exitcond.not = icmp eq i64 %inc, %n
209   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !1
211 for.cond.cleanup:                                 ; preds = %for.body
212   ret void
216 declare double @foo(double)
217 declare i64 @bar(ptr)
218 declare double @llvm.sin.f64(double)
219 declare float @llvm.sin.f32(float)
220 declare float @llvm.sqrt.f32(float)
222 declare <vscale x 2 x double> @foo_vec(<vscale x 2 x double>)
223 declare <vscale x 2 x i64> @bar_vec(<vscale x 2 x ptr>)
224 declare <vscale x 2 x double> @sin_vec_nxv2f64(<vscale x 2 x double>)
225 declare <2 x double> @sin_vec_v2f64(<2 x double>)
227 attributes #0 = { "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vec)" }
228 attributes #1 = { "vector-function-abi-variant"="_ZGVsNxv_bar(bar_vec)" }
229 attributes #2 = { "vector-function-abi-variant"="_ZGVsNxv_llvm.sin.f64(sin_vec_nxv2f64)" }
230 attributes #3 = { "vector-function-abi-variant"="_ZGV_LLVM_N2v_llvm.sin.f64(sin_vec_v2f64)" }
232 !1 = distinct !{!1, !2, !3}
233 !2 = !{!"llvm.loop.vectorize.width", i32 2}
234 !3 = !{!"llvm.loop.vectorize.scalable.enable", i1 true}
236 !llvm.dbg.cu = !{!4}
237 !llvm.module.flags = !{!7}
238 !llvm.ident = !{!8}
240 !4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !5, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !6, splitDebugInlining: false, nameTableKind: None)
241 !5 = !DIFile(filename: "t.c", directory: "somedir")
242 !6 = !{}
243 !7 = !{i32 2, !"Debug Info Version", i32 3}
244 !8 = !{!"clang"}
245 !9 = distinct !DISubprogram(name: "foo", scope: !5, file: !5, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !4, retainedNodes: !6)
246 !10 = !DISubroutineType(types: !6)
247 !11 = !DILocation(line: 3, column: 10, scope: !9)
248 !12 = !DILocation(line: 3, column: 20, scope: !9)
249 !13 = !DILocation(line: 3, column: 30, scope: !9)
250 !14 = !DILocation(line: 3, column: 40, scope: !9)