Files
clang-p2996/llvm/test/Transforms/Inline/cgscc-cycle-debug.ll
Wenlei He b559535a3a [NewPM] Avoid redundant CGSCC run for updated SCC
Summary:
When an SCC got split due to inlining, we have two mechanisms for reprocessing the updated SCC, first is UR.UpdatedC
that repeatedly rerun the new, current SCC; second is a worklist for all newly split SCCs. We can avoid rerun of
the same SCC when the SCC is set to be processed by both mechanisms *back to back*. In pathological cases, such redundant
rerun could cause exponential size growth due to inlining along cycles, even when there's no SCC mutation and hence
convergence is not a problem.

Note that it's ok to have SCC updated and rerun immediately, and also in the work list if we have actually moved an SCC
to be topologically "below" the current one due to merging. In that case, we will need to revisit the current SCC after
those moved SCCs. For that reason, the redundant avoidance here only targets back to back rerun of the same SCC - the
case described by the now removed FIXME comment.

Reviewers: chandlerc, wmi

Subscribers: llvm-commits, hoy

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D80589
2020-06-14 19:54:52 -07:00

45 lines
1.9 KiB
LLVM

; When an SCC got split due to inlining, we have two mechanisms for reprocessing the updated SCC, first is UR.UpdatedC
; that repeatedly rerun the new, current SCC; second is a worklist for all newly split SCCs. We need to avoid rerun of
; the same SCC when the SCC is set to be processed by both mechanisms back to back. In pathological cases, such extra,
; redundant rerun could cause exponential size growth due to inlining along cycles.
;
; The test cases here illustrates potential redundant rerun and how it's prevented, however there's no extra inlining
; even if we allow the redundant rerun. In real code, when inliner makes different decisions for different call sites
; of the same caller-callee edge, we could end up getting more recursive inlining without SCC mutation.
;
; REQUIRES: asserts
; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=500 -debug-only=cgscc -S 2>&1 | FileCheck %s
; CHECK: Running an SCC pass across the RefSCC: [(test1_c, test1_a, test1_b)]
; CHECK: Enqueuing the existing SCC in the worklist:(test1_b)
; CHECK: Enqueuing a newly formed SCC:(test1_c)
; CHECK: Enqueuing a new RefSCC in the update worklist: [(test1_b)]
; CHECK: Switch an internal ref edge to a call edge from 'test1_a' to 'test1_c'
; CHECK: Switch an internal ref edge to a call edge from 'test1_a' to 'test1_a'
; CHECK: Re-running SCC passes after a refinement of the current SCC: (test1_c, test1_a)
; CHECK: Skipping redundant run on SCC: (test1_c, test1_a)
; CHECK: Skipping an SCC that is now part of some other RefSCC...
declare void @external(i32 %seed)
define void @test1_a(i32 %num) {
entry:
call void @test1_b(i32 %num)
call void @external(i32 %num)
ret void
}
define void @test1_b(i32 %num) {
entry:
call void @test1_c(i32 %num)
call void @test1_a(i32 %num)
call void @external(i32 %num)
ret void
}
define void @test1_c(i32 %num) #0 {
call void @test1_a(i32 %num)
ret void
}
attributes #0 = { noinline nounwind optnone }