
In 4de3184f07fd8c548125d315dd306d4afa7c9698 we exposed BasicAA's cross-iteration mode for use in LAA, so we can handle selects with equal conditions correctly (where the select condition is not actually equal across iterations). However, if we replace the selects with equivalent phis, the issue still exists. In the phi case, we effectively still have an assumption that the condition(s) that control which phi arg is used will be the same across iterations. Fix this by disabling this phi handling in cross-iteration mode. (I'm not entirely sure whether this is also needed when BasicAA enables cross-iteration mode during internal phi recursion, but I wouldn't be surprised if that's the case.)
88 lines
3.2 KiB
LLVM
88 lines
3.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt -passes='print<access-info>' -disable-output 2>&1 < %s | FileCheck %s
|
|
|
|
define void @test(ptr noalias %x, ptr noalias %y, ptr noalias %z) {
|
|
; CHECK-LABEL: 'test'
|
|
; CHECK-NEXT: loop:
|
|
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
|
|
; CHECK-NEXT: Unsafe indirect dependence.
|
|
; CHECK-NEXT: Dependences:
|
|
; CHECK-NEXT: IndirectUnsafe:
|
|
; CHECK-NEXT: %load = load double, ptr %gep.sel, align 8 ->
|
|
; CHECK-NEXT: store double %load, ptr %gep.sel2, align 8
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: Run-time memory checks:
|
|
; CHECK-NEXT: Grouped accesses:
|
|
; 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:
|
|
%gep.y = getelementptr double, ptr %y, i64 -32
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%icmp = icmp ule i64 %iv, 32
|
|
%sel = select i1 %icmp, ptr %x, ptr %gep.y
|
|
%gep.sel = getelementptr inbounds double, ptr %sel, i64 %iv
|
|
%load = load double, ptr %gep.sel, align 8
|
|
%sel2 = select i1 %icmp, ptr %y, ptr %z
|
|
%gep.sel2 = getelementptr inbounds double, ptr %sel2, i64 %iv
|
|
store double %load, ptr %gep.sel2, align 8
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exit.cond = icmp eq i64 %iv, 94
|
|
br i1 %exit.cond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Same as previous test, but with selects replaced by phis in the same block.
|
|
define void @test_phi(ptr noalias %x, ptr noalias %y, ptr noalias %z) {
|
|
; CHECK-LABEL: 'test_phi'
|
|
; CHECK-NEXT: loop:
|
|
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
|
|
; CHECK-NEXT: Unsafe indirect dependence.
|
|
; CHECK-NEXT: Dependences:
|
|
; CHECK-NEXT: IndirectUnsafe:
|
|
; CHECK-NEXT: %load = load double, ptr %gep.sel, align 8 ->
|
|
; CHECK-NEXT: store double %load, ptr %gep.sel2, align 8
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: Run-time memory checks:
|
|
; CHECK-NEXT: Grouped accesses:
|
|
; 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:
|
|
%gep.y = getelementptr double, ptr %y, i64 -32
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ %iv.next, %latch ], [ 0, %entry ]
|
|
%icmp = icmp ule i64 %iv, 32
|
|
br i1 %icmp, label %if, label %latch
|
|
|
|
if:
|
|
br label %latch
|
|
|
|
latch:
|
|
%sel = phi ptr [ %x, %if ], [ %gep.y, %loop ]
|
|
%sel2 = phi ptr [ %y, %if ], [ %z, %loop ]
|
|
%gep.sel = getelementptr inbounds double, ptr %sel, i64 %iv
|
|
%load = load double, ptr %gep.sel, align 8
|
|
%gep.sel2 = getelementptr inbounds double, ptr %sel2, i64 %iv
|
|
store double %load, ptr %gep.sel2, align 8
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exit.cond = icmp eq i64 %iv, 94
|
|
br i1 %exit.cond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|