mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
11cd8b2ab1
Summary: MergeFunctions currently tries to process strong functions before weak functions, because weak functions can simply call strong functions, while a strong/weak function cannot call a weak function (a backing strong function is needed). This patch additionally tries to process external functions before local functions, because we definitely have to keep the external function, but may be able to drop the local one (and definitely can if it is also unnamed_addr). Unfortunately, this exposes an existing bug in the implementation: The FnTree and FNodesInTree structures can currently go out of sync in the case where two weak functions are merged, because the function in FnTree/FNodesInTree is RAUWed. This leaves it behind in FnTree (this is intended, as it is the strong backing function which should be used for further merges), while it is replaced in FNodesInTree (this is not intended). This is fixed by switching FNodesInTree from using a ValueMap to using a DenseMap of AssertingVH. This exposes another minor issue: Currently FNodesInTree is not cleared after MergeFunctions finishes running. Currently, this is potentially dangerous (e.g. if something else wants to RAUW a function with a non-function), but at the very least it is unnecessary/inefficient. After the change to use AssertingVH it becomes more problematic, because there are certainly passes that remove functions. This issue is fixed by clearing FNodesInTree at the end of the pass. Reviewers: jfb, whitequark Reviewed By: whitequark Subscribers: rkruppe, llvm-commits Differential Revision: https://reviews.llvm.org/D53271 llvm-svn: 346386
56 lines
1.2 KiB
LLVM
56 lines
1.2 KiB
LLVM
; RUN: opt -S -mergefunc < %s | FileCheck %s
|
|
|
|
; We should normalize to test2 rather than test1,
|
|
; because it allows us to drop test1 entirely
|
|
|
|
; CHECK-NOT: define internal void @test1() unnamed_addr
|
|
; CHECK: define void @test3() unnamed_addr
|
|
; CHECK-NEXT: call void @test2()
|
|
; CHECK-NEXT: call void @test2()
|
|
|
|
declare void @dummy()
|
|
|
|
define internal void @test1() unnamed_addr {
|
|
call void @dummy()
|
|
call void @dummy()
|
|
ret void
|
|
}
|
|
|
|
define void @test2() unnamed_addr {
|
|
call void @dummy()
|
|
call void @dummy()
|
|
ret void
|
|
}
|
|
|
|
define void @test3() unnamed_addr {
|
|
call void @test1()
|
|
call void @test2()
|
|
ret void
|
|
}
|
|
|
|
; We should normalize to the existing test6 rather than
|
|
; to a new anonymous strong backing function
|
|
|
|
; CHECK: define weak void @test5()
|
|
; CHECK-NEXT: tail call void @test6()
|
|
; CHECK: define weak void @test4()
|
|
; CHECK-NEXT: tail call void @test6()
|
|
|
|
declare void @dummy2()
|
|
|
|
define weak void @test4() {
|
|
call void @dummy2()
|
|
call void @dummy2()
|
|
ret void
|
|
}
|
|
define weak void @test5() {
|
|
call void @dummy2()
|
|
call void @dummy2()
|
|
ret void
|
|
}
|
|
define void @test6() {
|
|
call void @dummy2()
|
|
call void @dummy2()
|
|
ret void
|
|
}
|