Files
clang-p2996/llvm/test/Transforms/SampleProfile/pseudo-probe-dangle.ll
Hongtao Yu c75da238b4 [CSSPGO] Deduplicating dangling pseudo probes.
Same dangling probes are redundant since they all have the same semantic that is to rely on the counts inference tool to get reasonable count for the same original block. Therefore, there's no need to keep multiple copies of them. I've seen jump threading created tons of redundant dangling probes that slowed down the compiler dramatically. Other optimization passes can also result in redundant probes though without an observed impact so far.

This change removes block-wise redundant dangling probes specifically introduced by jump threading. To support removing redundant dangling probes caused by all other passes, a final function-wise deduplication is also added.

An 18% size win of the .pseudo_probe section was seen for SPEC2017. No performance difference was observed.

Differential Revision: https://reviews.llvm.org/D97482
2021-03-03 22:44:42 -08:00

102 lines
3.0 KiB
LLVM

; REQUIRES: x86_64-linux
; RUN: opt < %s -passes='pseudo-probe,jump-threading' -S -o %t
; RUN: FileCheck %s < %t --check-prefix=JT
; RUN: llc -pseudo-probe-for-profiling -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
; RUN: opt < %s -passes='pseudo-probe' -S -o %t1
; RUN: llc -pseudo-probe-for-profiling -stop-after=tailduplication <%t1 | FileCheck %s --check-prefix=MIR-tail
; RUN: opt < %s -passes='pseudo-probe,simplifycfg' -S | FileCheck %s --check-prefix=SC
declare i32 @f1()
define i32 @foo(i1 %cond) {
; JT-LABEL: @foo(
; JT: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0, i64 -1)
; ASM: pseudoprobe 6699318081062747564 1 0 0
%call = call i32 @f1()
br i1 %cond, label %T, label %F
T:
br label %Merge
F:
br label %Merge
Merge:
;; Check branch T and F are gone, and their probes (probe 2 and 3) are dangling.
; JT-LABEL-NO: T
; JT-LABEL-NO: F
; JT-LABEL: Merge
; JT: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 3, i32 2, i64 -1)
; JT: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 2, i32 2, i64 -1)
; JT: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 4, i32 0, i64 -1)
; ASM: .pseudoprobe 6699318081062747564 3 0 2
; ASM: .pseudoprobe 6699318081062747564 2 0 2
; ASM: .pseudoprobe 6699318081062747564 4 0 0
ret i32 %call
}
;; Check block T and F are gone, and their probes (probe 2 and 3) are dangling.
; MIR-tail: bb.0
; MIR-tail: PSEUDO_PROBE [[#GUID:]], 1, 0, 0
; MIR-tail: PSEUDO_PROBE [[#GUID:]], 2, 0, 2
; MIR-tail: PSEUDO_PROBE [[#GUID:]], 3, 0, 2
; MIR-tail: PSEUDO_PROBE [[#GUID:]], 4, 0, 0
define void @foo2() {
bb:
%tmp = call i32 @f1()
%tmp1 = icmp eq i32 %tmp, 1
br i1 %tmp1, label %bb5, label %bb8
bb2:
%tmp4 = icmp ne i32 %tmp, 1
switch i1 %tmp4, label %bb2 [
i1 0, label %bb5
i1 1, label %bb8
]
bb5:
;; Check the pseudo probe with id 3 only has one copy.
; JT-COUNT-1: call void @llvm.pseudoprobe(i64 [[#GUID2:]], i64 3, i32 2, i64 -1)
; JT-NOT: call void @llvm.pseudoprobe(i64 [[#GUID2:]], i64 3, i32 2, i64 -1)
%tmp6 = phi i1 [ %tmp1, %bb ], [ false, %bb2 ]
br i1 %tmp6, label %bb8, label %bb7
bb7:
br label %bb8
bb8:
ret void
}
define i32 @test(i32 %a, i32 %b, i32 %c) {
;; Check block bb1 and bb2 are gone, and their probes (probe 2 and 3) are dangling.
; SC-LABEL: @test(
; SC-LABEL-NO: bb1
; SC-LABEL-NO: bb2
; SC: [[T1:%.*]] = icmp eq i32 [[B:%.*]], 0
; SC-DAG: call void @llvm.pseudoprobe(i64 [[#GUID3:]], i64 2, i32 2, i64 -1)
; SC-DAG: call void @llvm.pseudoprobe(i64 [[#GUID3]], i64 3, i32 2, i64 -1)
; SC: [[T2:%.*]] = icmp sgt i32 [[C:%.*]], 1
; SC: [[T3:%.*]] = add i32 [[A:%.*]], 1
; SC: [[SPEC_SELECT:%.*]] = select i1 [[T2]], i32 [[T3]], i32 [[A]]
; SC: [[T4:%.*]] = select i1 [[T1]], i32 [[SPEC_SELECT]], i32 [[B]]
; SC: [[T5:%.*]] = sub i32 [[T4]], 1
; SC: ret i32 [[T5]]
entry:
%t1 = icmp eq i32 %b, 0
br i1 %t1, label %bb1, label %bb3
bb1:
%t2 = icmp sgt i32 %c, 1
br i1 %t2, label %bb2, label %bb3
bb2:
%t3 = add i32 %a, 1
br label %bb3
bb3:
%t4 = phi i32 [ %b, %entry ], [ %a, %bb1 ], [ %t3, %bb2 ]
%t5 = sub i32 %t4, 1
ret i32 %t5
}