mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
c9829bfb08
``` // The legacy PM CGPassManager discovers SCCs this way: for function in the source order tarjanSCC(function) // While the new PM CGSCCPassManager does: for function in the reversed source order [1] discover a reference graph SCC build call graph SCCs inside the reference graph SCC ``` In the common cases, reference graph ~= call graph, the new PM order is undesired because for `a | b | c` (3 independent functions), the new PM will process them in the reversed order: c, b, a. If `a <-> b <-> c`, we can see that `-print-after-all` will report the sole SCC as `scc: (c, b, a)`. This patch corrects the iteration order. The discovered SCC order will match the legacy PM in the common cases. For some tests (`Transforms/Inline/cgscc-*.ll` and `unittests/Analysis/CGSCCPassManagerTest.cpp`), the behaviors are dependent on the SCC discovery order and there are too many check lines for the particular order. This patch simply reverses the function order to avoid changing too many check lines. Differential Revision: https://reviews.llvm.org/D90566
105 lines
2.9 KiB
LLVM
105 lines
2.9 KiB
LLVM
; This test tries to ensure that the inliner successfully invalidates function
|
|
; analyses after inlining into the function body.
|
|
;
|
|
; The strategy for these tests is to compute domtree over all the functions,
|
|
; then run the inliner, and then verify the domtree. Then we can arrange the
|
|
; inline to disturb the domtree (easy) and detect any stale cached entries in
|
|
; the verifier. We do the initial computation both *inside* the CGSCC walk and
|
|
; in a pre-step to make sure both work.
|
|
;
|
|
; RUN: opt < %s -passes='function(require<domtree>),cgscc(inline,function(verify<domtree>))' -S | FileCheck %s
|
|
; RUN: opt < %s -passes='cgscc(function(require<domtree>),inline,function(verify<domtree>))' -S | FileCheck %s
|
|
|
|
; An external function used to control branches.
|
|
declare i1 @flag()
|
|
; CHECK-LABEL: declare i1 @flag()
|
|
|
|
; The utility function with interesting control flow that gets inlined below to
|
|
; perturb the dominator tree.
|
|
define internal void @callee() {
|
|
; CHECK-LABEL: @callee
|
|
entry:
|
|
%ptr = alloca i8
|
|
%flag = call i1 @flag()
|
|
br i1 %flag, label %then, label %else
|
|
|
|
then:
|
|
store volatile i8 42, i8* %ptr
|
|
br label %return
|
|
|
|
else:
|
|
store volatile i8 -42, i8* %ptr
|
|
br label %return
|
|
|
|
return:
|
|
ret void
|
|
}
|
|
|
|
|
|
; The 'test1_' prefixed functions test the basic scenario of inlining
|
|
; destroying dominator tree.
|
|
|
|
define void @test1_caller() {
|
|
; CHECK-LABEL: define void @test1_caller()
|
|
entry:
|
|
call void @callee()
|
|
; CHECK-NOT: @callee
|
|
ret void
|
|
; CHECK: ret void
|
|
}
|
|
|
|
|
|
; The 'test2_' prefixed functions test the scenario of not inlining preserving
|
|
; dominators.
|
|
|
|
define void @test2_caller() {
|
|
; CHECK-LABEL: define void @test2_caller()
|
|
entry:
|
|
call void @callee() noinline
|
|
; CHECK: call void @callee
|
|
ret void
|
|
; CHECK: ret void
|
|
}
|
|
|
|
|
|
; The 'test3_' prefixed functions test the scenario of not inlining preserving
|
|
; dominators after splitting an SCC into two smaller SCCs.
|
|
|
|
; This function gets visited first and we end up inlining everything we
|
|
; can into this routine. That splits test3_g into a separate SCC that is enqued
|
|
; for later processing.
|
|
define void @test3_f() {
|
|
; CHECK-LABEL: define void @test3_f()
|
|
entry:
|
|
; Create the first edge in the SCC cycle.
|
|
call void @test3_g()
|
|
; CHECK-NOT: @test3_g()
|
|
; CHECK: call void @test3_f()
|
|
|
|
; Pull interesting CFG into this function.
|
|
call void @callee()
|
|
; CHECK-NOT: call void @callee()
|
|
|
|
ret void
|
|
; CHECK: ret void
|
|
}
|
|
|
|
; This function ends up split into a separate SCC, which can cause its analyses
|
|
; to become stale if the splitting doesn't properly invalidate things. Also, as
|
|
; a consequence of being split out, test3_f is too large to inline by the time
|
|
; we get here.
|
|
define void @test3_g() {
|
|
; CHECK-LABEL: define void @test3_g()
|
|
entry:
|
|
; Create the second edge in the SCC cycle.
|
|
call void @test3_f()
|
|
; CHECK: call void @test3_f()
|
|
|
|
; Pull interesting CFG into this function.
|
|
call void @callee()
|
|
; CHECK-NOT: call void @callee()
|
|
|
|
ret void
|
|
; CHECK: ret void
|
|
}
|