blob: 78aa3eda9d952f517df66ddefaa8e2f3b9945278 [file]
; REQUIRES: asserts
; DEFINE: %{cmd} = opt -S -p loop-vectorize -debug-only=loop-vectorize --disable-output \
; DEFINE: -epilogue-tail-folding-policy=prefer-fold-tail -pass-remarks-analysis=loop-vectorize
; RUN: %{cmd} -force-vector-width=16 -epilogue-vectorization-force-VF=8 < %s 2>&1 | FileCheck %s
; RUN: %{cmd} -force-vector-width=16 -epilogue-vectorization-force-VF=8 -enable-epilogue-vectorization=false \
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=CHECK-DISABLED-EPILOG
; RUN: %{cmd} -epilogue-vectorization-force-VF=8 < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-FORCED-MAIN-VF
; RUN: %{cmd} -force-vector-width=16 < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-FORCED-EPILOGUE-VF
; RUN: %{cmd} -force-vector-width=8 -epilogue-vectorization-force-VF=8 < %s 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID-VFs
; RUN: %{cmd} -force-vector-width=16 -epilogue-vectorization-force-VF=8 -enable-early-exit-vectorization-with-side-effects \
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=CHECK-DISABLED-EARLY-EXIT
; RUN: %{cmd} -force-vector-width=16 -epilogue-vectorization-force-VF=8 -enable-vplan-native-path \
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=CHECK-OUTER-LOOP
define void @test_epilogue_tf(ptr %A, i64 %n, i8 %val) {
; CHECK-LABEL: LV: Checking a loop in 'test_epilogue_tf'
; CHECK: LV: epilogue tail-folding is not supported yet
; CHECK: remark: <unknown>:0:0: The epilogue-tail-folding policy prefer-fold-tail is not supported yet, fall back to a normal epilogue
;
; CHECK-DISABLED-EPILOG-LABEL: LV: Checking a loop in 'test_epilogue_tf'
; CHECK-DISABLED-EPILOG: remark: <unknown>:0:0: Options conflict, epilogue vectorization is disallowed while epilogue tail-folding allowed!
;
; CHECK-NO-FORCED-MAIN-VF-LABEL: Checking a loop in 'test_epilogue_tf'
; CHECK-NO-FORCED-MAIN-VF: remark: <unknown>:0:0: For now, epilogue tail-folding can't be applied without forced main/epilogue loop VF
; CHECK-NO-FORCED-EPILOGUE-VF-LABEL: Checking a loop in 'test_epilogue_tf'
; CHECK-NO-FORCED-EPILOGUE-VF: remark: <unknown>:0:0: For now, epilogue tail-folding can't be applied without forced main/epilogue loop VF
;
; CHECK-INVALID-VFs-LABEL: Checking a loop in 'test_epilogue_tf'
; CHECK-INVALID-VFs: remark: <unknown>:0:0: For now, epilogue tail-folding can't be applied when VF of the main loop <= VF of the epilogue
;
entry:
br label %for.body
for.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
%arrayidx = getelementptr inbounds i8, ptr %A, i64 %iv
store i8 %val, ptr %arrayidx, align 1
%iv.next = add nuw nsw i64 %iv, 1
%exitcond = icmp ne i64 %iv.next, %n
br i1 %exitcond, label %for.body, label %exit
exit:
ret void
}
define i16 @require_scalar_epilogue(ptr %dst, i64 %x) {
; CHECK-LABEL: Checking a loop in 'require_scalar_epilogue'
; CHECK: remark: <unknown>:0:0: Epilogue tail-folding can't be applied because scalar epilogue is required. Fall back to a normal epilogue
;
entry:
br label %loop.header
loop.header:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%gep = getelementptr inbounds i32, ptr %dst, i64 %iv
store i64 0, ptr %gep
br label %loop.then
loop.then:
%cmp3 = icmp ne i64 %iv, %x
br i1 %cmp3, label %loop.latch, label %exit.1
loop.latch:
%iv.next = add i64 %iv, 1
br label %loop.header
exit.1:
ret i16 0
exit.2:
ret i16 1
}
define i32 @opt_for_size(ptr %p, i32 %n, i8 %val) optsize {
; CHECK-LABEL: Checking a loop in 'opt_for_size'
; CHECK: remark: <unknown>:0:0: Not applying tail-folding to the epilogue, since no epilogue is allowed
;
entry:
br label %for.body
for.body:
%iv = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%arrayidx = getelementptr inbounds i8, ptr %p, i32 %iv
store i8 %val, ptr %arrayidx, align 1
%inc = add nsw i32 %iv, 1
%exitcond = icmp eq i32 %inc, %n
br i1 %exitcond, label %for.end, label %for.body
for.end:
ret i32 0
}
define i32 @low_tc(ptr %p, i8 %val) {
; CHECK-LABEL: Checking a loop in 'low_tc'
; CHECK: remark: <unknown>:0:0: Not applying tail-folding to the epilogue, since no epilogue is allowed.
;
entry:
br label %for.body
for.body:
%iv = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%arrayidx = getelementptr inbounds i8, ptr %p, i32 %iv
store i8 %val, ptr %arrayidx, align 1
%inc = add nsw i32 %iv, 1
%exitcond = icmp eq i32 %inc, 8
br i1 %exitcond, label %for.end, label %for.body
for.end:
ret i32 0
}
define i1 @early_exit(ptr %A, i64 %n, i8 %find) {
; CHECK-DISABLED-EARLY-EXIT-LABEL: LV: Checking a loop in 'early_exit'
; CHECK-DISABLED-EARLY-EXIT: remark: <unknown>:0:0: Epilogue tail-folding is not supported yet for early-exit loops
;
entry:
br label %for.body
for.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %cont ]
%arrayidx = getelementptr inbounds i8, ptr %A, i64 %iv
%val = load i8, ptr %arrayidx, align 1
%exitcond = icmp eq i8 %val, %find
br i1 %exitcond, label %exit, label %cont
cont:
%iv.next = add nuw nsw i64 %iv, 1
%contcond = icmp ne i64 %iv.next, %n
br i1 %contcond, label %for.body, label %exit
exit:
ret i1 %exitcond
}
; For this function, the check line is not related to epilogue tail-folding, but when vectorizing this case gets supported,
; the check line should be changed to: Epilogue tail-folding is not supported yet for early-exit loops, same as the case above.
define void @combined_exit_conditions(ptr align 4 dereferenceable(80) readonly %src, ptr align 4 dereferenceable(80) noalias %dst, ptr align 4 dereferenceable(80) readonly %pred) {
; CHECK-DISABLED-EARLY-EXIT-LABEL: LV: Checking a loop in 'combined_exit_conditions'
; CHECK-DISABLED-EARLY-EXIT: remark: <unknown>:0:0: loop not vectorized: Cannot vectorize uncountable loop
;
entry:
br label %for.body
for.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
%src.ptr = getelementptr inbounds nuw [4 x i8], ptr %src, i64 %iv
%data = load i32, ptr %src.ptr, align 4
%add = add nsw i32 %data, 1
%dst.ptr = getelementptr inbounds nuw [4 x i8], ptr %dst, i64 %iv
store i32 %add, ptr %dst.ptr, align 4
%ee.ptr = getelementptr inbounds nuw [4 x i8], ptr %pred, i64 %iv
%ee.val = load i32, ptr %ee.ptr, align 4
%ee.cmp = icmp ne i32 %ee.val, 0
%iv.next = add nuw nsw i64 %iv, 1
%counted.cmp = icmp eq i64 %iv.next, 20
%combined.cond = select i1 %ee.cmp, i1 true, i1 %counted.cmp
br i1 %combined.cond, label %exit, label %for.body
exit:
ret void
}
define void @test_outer_loop(ptr %A, i64 %m) {
; CHECK-OUTER-LOOP-LABEL: Checking a loop in 'test_outer_loop'
; CHECK-OUTER-LOOP: remark: <unknown>:0:0: Epilogue tail-folding is not supported for outer loop
;
entry:
br label %outer.header
outer.header:
%iv.outer = phi i64 [ 0, %entry ], [ %iv.outer.next, %outer.latch ]
br label %inner
inner:
%iv.inner = phi i64 [ 0, %outer.header ], [ %iv.inner.next, %inner ]
%gep = getelementptr inbounds i8, ptr %A, i64 %iv.inner
store i8 0, ptr %gep, align 1
%iv.inner.next = add nuw nsw i64 %iv.inner, 1
%inner.ec = icmp eq i64 %iv.inner.next, 8
br i1 %inner.ec, label %outer.latch, label %inner
outer.latch:
%iv.outer.next = add nuw nsw i64 %iv.outer, 1
%outer.ec = icmp eq i64 %iv.outer.next, %m
br i1 %outer.ec, label %exit, label %outer.header, !llvm.loop !1
exit:
ret void
}
!1 = distinct !{!1, !2}
!2 = !{!"llvm.loop.vectorize.enable"}