llvm-project/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
John Brawn 81d3189891
[LAA] Keep pointer checks on partial analysis (#139719)
Currently if there's any memory access that AccessAnalysis couldn't
analyze then all of the runtime pointer check results are discarded.
This patch makes this able to be controlled with the AllowPartial
option, which makes it so we generate the runtime check information
for those pointers that we could analyze, as transformations may still
be able to make use of the partial information.

Of the transformations that use LoopAccessAnalysis, only
LoopVersioningLICM changes behaviour as a result of this change. This is
because the others either:
* Check canVectorizeMemory, which will return false when we have partial
pointer information as analyzeLoop() will return false.
* Examine the dependencies returned by getDepChecker(), which will be
empty as we exit analyzeLoop if we have partial pointer information
before calling areDepsSafe(), which is what fills in the dependency
information.
2025-06-04 16:47:20 +01:00

259 lines
11 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes='print<access-info><allow-partial>' -disable-output %s 2>&1 | FileCheck %s
define void @dependency_check_and_runtime_checks_needed_select_of_invariant_ptrs(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_invariant_ptrs'
; CHECK-NEXT: loop:
; CHECK-NEXT: Memory dependences are safe with run-time checks
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP1:
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP3:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Check 3:
; CHECK-NEXT: Comparing group GRP1:
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
; CHECK-NEXT: Check 4:
; CHECK-NEXT: Comparing group GRP1:
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
; CHECK-NEXT: Against group GRP3:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Check 5:
; CHECK-NEXT: Comparing group GRP2:
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
; CHECK-NEXT: Against group GRP3:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Group GRP1:
; CHECK-NEXT: (Low: %b High: (4 + %b))
; CHECK-NEXT: Member: %b
; CHECK-NEXT: Group GRP2:
; CHECK-NEXT: (Low: %c High: (4 + %c))
; CHECK-NEXT: Member: %c
; CHECK-NEXT: Group GRP3:
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
%l1 = load float, ptr %gep.a.iv, align 4
%iv.offset = add i64 %iv, %offset
%gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
%l2 = load float, ptr %gep.a.iv.off, align 4
%ad = fadd fast float %l1, %l2
store float %ad, ptr %gep.a.iv, align 4
%cmp = fcmp ult float %l1, 10.0
%select = select i1 %cmp, ptr %b, ptr %c
store float 0.0, ptr %select
%iv.next = add nuw nsw i64 %iv, 1
%exitcond = icmp eq i64 %iv.next, %n
br i1 %exitcond, label %exit, label %loop
exit:
ret void
}
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs'
; CHECK-NEXT: loop:
; CHECK-NEXT: Memory dependences are safe with run-time checks
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP1:
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP3:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Check 3:
; CHECK-NEXT: Comparing group GRP1:
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
; CHECK-NEXT: Check 4:
; CHECK-NEXT: Comparing group GRP1:
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
; CHECK-NEXT: Against group GRP3:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Check 5:
; CHECK-NEXT: Comparing group GRP2:
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
; CHECK-NEXT: Against group GRP3:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Group GRP1:
; CHECK-NEXT: (Low: %b High: ((4 * %n) + %b))
; CHECK-NEXT: Member: {%b,+,4}<%loop>
; CHECK-NEXT: Group GRP2:
; CHECK-NEXT: (Low: %c High: ((4 * %n) + %c))
; CHECK-NEXT: Member: {%c,+,4}<%loop>
; CHECK-NEXT: Group GRP3:
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
%l1 = load float, ptr %gep.a.iv, align 4
%iv.offset = add i64 %iv, %offset
%gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
%l2 = load float, ptr %gep.a.iv.off, align 4
%ad = fadd fast float %l1, %l2
store float %ad, ptr %gep.a.iv, align 4
%gep.b = getelementptr inbounds float, ptr %b, i64 %iv
%gep.c = getelementptr inbounds float, ptr %c, i64 %iv
%cmp = fcmp ult float %l1, 10.0
%select = select i1 %cmp, ptr %gep.b, ptr %gep.c
store float 0.0, ptr %select
%iv.next = add nuw nsw i64 %iv, 1
%exitcond = icmp eq i64 %iv.next, %n
br i1 %exitcond, label %exit, label %loop
exit:
ret void
}
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_1(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_1'
; CHECK-NEXT: loop:
; CHECK-NEXT: Report: cannot identify array bounds
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
; CHECK-NEXT: Group GRP1:
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Generated run-time checks are incomplete
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv2 = phi i64 [ 0, %entry ], [ %iv2.next, %loop ]
%gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
%l1 = load float, ptr %gep.a.iv, align 4
%iv.offset = add i64 %iv, %offset
%gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
%l2 = load float, ptr %gep.a.iv.off, align 4
%ad = fadd fast float %l1, %l2
store float %ad, ptr %gep.a.iv, align 4
%gep.b = getelementptr float, ptr %b, i64 %iv2
%gep.c = getelementptr inbounds float, ptr %c, i64 %iv
%cmp = fcmp ult float %l1, 10.0
%select = select i1 %cmp, ptr %gep.b, ptr %gep.c
store float 0.0, ptr %select
%iv.next = add nuw nsw i64 %iv, 1
%iv2.next = add i64 %iv2, 2
%exitcond = icmp eq i64 %iv.next, %n
br i1 %exitcond, label %exit, label %loop
exit:
ret void
}
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_2(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_2'
; CHECK-NEXT: loop:
; CHECK-NEXT: Report: cannot identify array bounds
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
; CHECK-NEXT: Group GRP1:
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Generated run-time checks are incomplete
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv2 = phi i64 [ 0, %entry ], [ %iv2.next, %loop ]
%gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
%l1 = load float, ptr %gep.a.iv, align 4
%iv.offset = add i64 %iv, %offset
%gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
%l2 = load float, ptr %gep.a.iv.off, align 4
%ad = fadd fast float %l1, %l2
store float %ad, ptr %gep.a.iv, align 4
%gep.b = getelementptr inbounds float, ptr %b, i64 %iv
%gep.c = getelementptr inbounds float, ptr %c, i64 %iv2
%cmp = fcmp ult float %l1, 10.0
%select = select i1 %cmp, ptr %gep.b, ptr %gep.c
store float 0.0, ptr %select
%iv.next = add nuw nsw i64 %iv, 1
%iv2.next = add i64 %iv2, 2
%exitcond = icmp eq i64 %iv.next, %n
br i1 %exitcond, label %exit, label %loop
exit:
ret void
}