In https://reviews.llvm.org/D129599, non-trivial switching was disabled for cold loops in the interest of code size. This added a dependency on BlockFrequencyInfo with PGO, but in loop passes this is only available on a lossy basis: see https://reviews.llvm.org/D86156 LICM moved away from BFI so as of today SimpleLoopUnswitch is the only remaining loop pass that uses BFI, for the sole reason to prevent code size increases in PGO builds. It doesn't use BFI if there's no profile summary available. After some investigation on llvm-test-suite it turns out that the lossy BFI causes very significant deviations in block frequency, since when new loops are deleted/created during the loop pass manager it can return frequencies for different loops altogether. This results in unswitchable loops being mistakenly skipped because they are thought to be cold. This patch removes the use of BFI from SimpleLoopUnswitch and thus the last remaining use of BFI in a loop pass. To recover the original intent of not unswitching cold code, PGOForceFunctionAttrs can be used to annotate functions which can be optimized for code size, since SimpleLoopUnswitch will respect OptSize: https://reviews.llvm.org/D94559 This isn't 100% the same behaviour since the previous behaviour checked for coldness at the loop level and this is now at the function level. We could expand PGOForceFunctionAttrs to be more granular at the loop level, https://github.com/llvm/llvm-project/issues/159595 tracks this idea.
74 lines
2.3 KiB
LLVM
74 lines
2.3 KiB
LLVM
; RUN: opt < %s -enable-loop-distribute -passes='loop-distribute,loop-mssa(simple-loop-unswitch<nontrivial>),loop-distribute' -o /dev/null -S -verify-analysis-invalidation=0 -debug-pass-manager=verbose 2>&1 | FileCheck %s
|
|
|
|
|
|
; Running loop-distribute will result in LoopAccessAnalysis being required and
|
|
; cached in the LoopAnalysisManagerFunctionProxy.
|
|
;
|
|
; CHECK: Running analysis: LoopAccessAnalysis on test6
|
|
|
|
|
|
; Then simple-loop-unswitch is removing/replacing some loops (resulting in
|
|
; Loop objects used as key in the analyses cache is destroyed). So here we
|
|
; want to see that any analysis results cached on the destroyed loop is
|
|
; cleared. A special case here is that loop_a_inner is destroyed when
|
|
; unswitching the parent loop.
|
|
;
|
|
; The bug solved and verified by this test case was related to the
|
|
; SimpleLoopUnswitch not marking the Loop as removed, so we missed clearing
|
|
; the analysis caches.
|
|
;
|
|
; CHECK: Running pass: SimpleLoopUnswitchPass on loop %loop_begin in function test6
|
|
; CHECK-NEXT: Clearing all analysis results for: loop_a_inner
|
|
|
|
|
|
; When running loop-distribute the second time we can see that loop_a_inner
|
|
; isn't analysed because the loop no longer exists (instead we find a new loop,
|
|
; loop_a_inner.us). This kind of verifies that it was correct to remove the
|
|
; loop_a_inner related analysis above.
|
|
;
|
|
; CHECK: Invalidating analysis: LoopAccessAnalysis on test6
|
|
; CHECK-NEXT: Running pass: LoopDistributePass on test6
|
|
; CHECK-NEXT: Running analysis: LoopAccessAnalysis on test6
|
|
|
|
|
|
define i32 @test6(ptr %ptr, i1 %cond1, ptr %a.ptr, ptr %b.ptr) {
|
|
entry:
|
|
br label %loop_begin
|
|
|
|
loop_begin:
|
|
%v = load i1, ptr %ptr
|
|
br i1 %cond1, label %loop_a, label %loop_b
|
|
|
|
loop_a:
|
|
br label %loop_a_inner
|
|
|
|
loop_a_inner:
|
|
%va = load i1, ptr %ptr
|
|
%a = load i32, ptr %a.ptr
|
|
br i1 %va, label %loop_a_inner, label %loop_a_inner_exit
|
|
|
|
loop_a_inner_exit:
|
|
%a.lcssa = phi i32 [ %a, %loop_a_inner ]
|
|
br label %latch
|
|
|
|
loop_b:
|
|
br label %loop_b_inner
|
|
|
|
loop_b_inner:
|
|
%vb = load i1, ptr %ptr
|
|
%b = load i32, ptr %b.ptr
|
|
br i1 %vb, label %loop_b_inner, label %loop_b_inner_exit
|
|
|
|
loop_b_inner_exit:
|
|
%b.lcssa = phi i32 [ %b, %loop_b_inner ]
|
|
br label %latch
|
|
|
|
latch:
|
|
%ab.phi = phi i32 [ %a.lcssa, %loop_a_inner_exit ], [ %b.lcssa, %loop_b_inner_exit ]
|
|
br i1 %v, label %loop_begin, label %loop_exit
|
|
|
|
loop_exit:
|
|
%ab.lcssa = phi i32 [ %ab.phi, %latch ]
|
|
ret i32 %ab.lcssa
|
|
}
|