mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
176c94be9c
This is an orthogonal and separated layer instead of being embedded inside the pass manager. While it adds a small amount of complexity, it is fairly minimal and the composability and control seems worth the cost. The logic for this ends up being nicely isolated and targeted. It should be easy to experiment with different iteration strategies wrapped around the CGSCC bottom-up walk using this kind of facility. The mechanism used to track devirtualization is the simplest one I came up with. I think it handles most of the cases the existing iteration machinery handles, but I haven't done a *very* in depth analysis. It does however match the basic intended semantics, and we can tweak or tune its exact behavior incrementally as necessary. One thing that we may want to revisit is freshly building the value handle set on each iteration. While I don't think this will be a significant cost (it is strictly fewer value handles but more churn of value handes than the old call graph), it is conceivable that we'll want a somewhat more clever tracking mechanism. My hope is to layer that on as a follow up patch with data supporting any implementation complexity it adds. This code also provides for a basic count heuristic: if the number of indirect calls decreases and the number of direct calls increases for a given function in the SCC, we assume devirtualization is responsible. This matches the heuristics currently used in the legacy pass manager. Differential Revision: https://reviews.llvm.org/D23114 llvm-svn: 290665
46 lines
814 B
LLVM
46 lines
814 B
LLVM
; RUN: opt < %s -inline -S | FileCheck %s
|
|
; RUN: opt < %s -passes='cgscc(devirt<4>(inline))' -S | FileCheck %s
|
|
; PR4834
|
|
|
|
define i32 @test1() {
|
|
%funcall1_ = call fastcc i32 ()* () @f1()
|
|
%executecommandptr1_ = call i32 %funcall1_()
|
|
ret i32 %executecommandptr1_
|
|
}
|
|
|
|
define internal fastcc i32 ()* @f1() nounwind readnone {
|
|
ret i32 ()* @f2
|
|
}
|
|
|
|
define internal i32 @f2() nounwind readnone {
|
|
ret i32 1
|
|
}
|
|
|
|
; CHECK: @test1()
|
|
; CHECK-NEXT: ret i32 1
|
|
|
|
|
|
|
|
|
|
|
|
declare i8* @f1a(i8*) ssp align 2
|
|
|
|
define internal i32 @f2a(i8* %t) inlinehint ssp {
|
|
entry:
|
|
ret i32 41
|
|
}
|
|
|
|
define internal i32 @f3a(i32 (i8*)* %__f) ssp {
|
|
entry:
|
|
%A = call i32 %__f(i8* undef)
|
|
ret i32 %A
|
|
}
|
|
|
|
define i32 @test2(i8* %this) ssp align 2 {
|
|
%X = call i32 @f3a(i32 (i8*)* @f2a) ssp
|
|
ret i32 %X
|
|
}
|
|
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: ret i32 41
|