
The entry count of a function needs to be updated after a callsite is elided by TRE: before elision, the entry count accounted for the recursive call at that callsite. After TRE, we need to remove that callsite's contribution. This patch enables this for instrumented profiling cases because, there, we know the function entry count captured entries before TRE. We cannot currently address this for sample-based (because we don't know whether this function was TRE-ed in the binary that donated samples)
121 lines
4.9 KiB
LLVM
121 lines
4.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
|
|
; RUN: opt -passes=tailcallelim -S %s -o - | FileCheck %s --check-prefixes=CHECK,ENABLED
|
|
; RUN: opt -passes=tailcallelim -tre-disable-entrycount-recompute -S %s -o - | FileCheck %s --check-prefixes=CHECK,DISABLED
|
|
|
|
; Test that tail call elimination correctly adjusts function entry counts
|
|
; when eliminating tail recursive calls.
|
|
|
|
; Basic test: eliminate a tail call and adjust entry count
|
|
define i32 @test_basic_entry_count_adjustment(i32 %n) !prof !0 {
|
|
; CHECK-LABEL: @test_basic_entry_count_adjustment(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
|
|
; CHECK: tailrecurse:
|
|
; CHECK-NEXT: [[N_TR:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[IF_THEN:%.*]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N_TR]], 0
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[IF_ELSE:%.*]], !prof [[PROF1:![0-9]+]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[SUB]] = sub i32 [[N_TR]], 1
|
|
; CHECK-NEXT: br label [[TAILRECURSE]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
%cmp = icmp sgt i32 %n, 0
|
|
br i1 %cmp, label %if.then, label %if.else, !prof !1
|
|
|
|
if.then: ; preds = %entry
|
|
%sub = sub i32 %n, 1
|
|
%call = tail call i32 @test_basic_entry_count_adjustment(i32 %sub)
|
|
ret i32 %call
|
|
|
|
if.else: ; preds = %entry
|
|
ret i32 0
|
|
}
|
|
|
|
; Test multiple tail calls in different blocks with different frequencies
|
|
define i32 @test_multiple_blocks_entry_count(i32 %n, i32 %flag) !prof !2 {
|
|
; CHECK-LABEL: @test_multiple_blocks_entry_count(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
|
|
; CHECK: tailrecurse:
|
|
; CHECK-NEXT: [[N_TR:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[SUB1:%.*]], [[BLOCK1:%.*]] ], [ [[SUB2:%.*]], [[BLOCK2:%.*]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N_TR]], 0
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_FLAG:%.*]], label [[BASE_CASE:%.*]], !prof [[PROF3:![0-9]+]]
|
|
; CHECK: check.flag:
|
|
; CHECK-NEXT: [[CMP_FLAG:%.*]] = icmp eq i32 [[FLAG:%.*]], 1
|
|
; CHECK-NEXT: br i1 [[CMP_FLAG]], label [[BLOCK1]], label [[BLOCK2]], !prof [[PROF4:![0-9]+]]
|
|
; CHECK: block1:
|
|
; CHECK-NEXT: [[SUB1]] = sub i32 [[N_TR]], 1
|
|
; CHECK-NEXT: br label [[TAILRECURSE]]
|
|
; CHECK: block2:
|
|
; CHECK-NEXT: [[SUB2]] = sub i32 [[N_TR]], 2
|
|
; CHECK-NEXT: br label [[TAILRECURSE]]
|
|
; CHECK: base.case:
|
|
; CHECK-NEXT: ret i32 1
|
|
;
|
|
entry:
|
|
%cmp = icmp sgt i32 %n, 0
|
|
br i1 %cmp, label %check.flag, label %base.case, !prof !3
|
|
check.flag:
|
|
%cmp.flag = icmp eq i32 %flag, 1
|
|
br i1 %cmp.flag, label %block1, label %block2, !prof !4
|
|
block1: ; preds = %check.flag
|
|
%sub1 = sub i32 %n, 1
|
|
%call1 = tail call i32 @test_multiple_blocks_entry_count(i32 %sub1, i32 %flag)
|
|
ret i32 %call1
|
|
block2: ; preds = %check.flag
|
|
%sub2 = sub i32 %n, 2
|
|
%call2 = tail call i32 @test_multiple_blocks_entry_count(i32 %sub2, i32 %flag)
|
|
ret i32 %call2
|
|
base.case: ; preds = %entry
|
|
ret i32 1
|
|
}
|
|
|
|
define i32 @test_no_entry_count(i32 %n) {
|
|
; CHECK-LABEL: @test_no_entry_count(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
|
|
; CHECK: tailrecurse:
|
|
; CHECK-NEXT: [[N_TR:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[IF_THEN:%.*]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N_TR]], 0
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[IF_ELSE:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[SUB]] = sub i32 [[N_TR]], 1
|
|
; CHECK-NEXT: br label [[TAILRECURSE]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
%cmp = icmp sgt i32 %n, 0
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
if.then: ; preds = %entry
|
|
%sub = sub i32 %n, 1
|
|
%call = tail call i32 @test_no_entry_count(i32 %sub)
|
|
ret i32 %call
|
|
|
|
if.else: ; preds = %entry
|
|
ret i32 0
|
|
}
|
|
|
|
; Function entry count metadata
|
|
!0 = !{!"function_entry_count", i64 1000}
|
|
!1 = !{!"branch_weights", i32 800, i32 200}
|
|
!2 = !{!"function_entry_count", i64 2000}
|
|
!3 = !{!"branch_weights", i32 3, i32 1}
|
|
!4 = !{!"branch_weights", i32 100, i32 900}
|
|
;.
|
|
; ENABLED: [[META0:![0-9]+]] = !{!"function_entry_count", i64 200}
|
|
; ENABLED: [[PROF1]] = !{!"branch_weights", i32 800, i32 200}
|
|
; ENABLED: [[META2:![0-9]+]] = !{!"function_entry_count", i64 500}
|
|
; ENABLED: [[PROF3]] = !{!"branch_weights", i32 3, i32 1}
|
|
; ENABLED: [[PROF4]] = !{!"branch_weights", i32 100, i32 900}
|
|
;.
|
|
; DISABLED: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
|
|
; DISABLED: [[PROF1]] = !{!"branch_weights", i32 800, i32 200}
|
|
; DISABLED: [[META2:![0-9]+]] = !{!"function_entry_count", i64 2000}
|
|
; DISABLED: [[PROF3]] = !{!"branch_weights", i32 3, i32 1}
|
|
; DISABLED: [[PROF4]] = !{!"branch_weights", i32 100, i32 900}
|
|
;.
|