
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.
259 lines
11 KiB
LLVM
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
|
|
}
|