[InlineCost] Remove skew when calculating call costs

When calculating the cost of a call instruction we were applying a heuristic penalty as well as the cost of the instruction itself.

However, when calculating the benefit from inlining we weren't discounting the equivalent penalty for the call instruction that would be removed! This caused skew in the calculation and meant we wouldn't inline in the following, trivial case:

  int g() {
    h();
  }
  int f() {
    g();
  }

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286814 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
James Molloy 2016-11-14 11:14:41 +00:00
parent c4d8c58337
commit a52fb282da
10 changed files with 41 additions and 12 deletions

View File

@ -1255,7 +1255,9 @@ bool CallAnalyzer::analyzeCall(CallSite CS) {
Cost -= InlineConstants::InstrCost; Cost -= InlineConstants::InstrCost;
} }
} }
// The call instruction also disappears after inlining.
Cost -= InlineConstants::InstrCost + InlineConstants::CallPenalty;
// If there is only one call of the function, and it has internal linkage, // If there is only one call of the function, and it has internal linkage,
// the cost of inlining it drops dramatically. // the cost of inlining it drops dramatically.
bool OnlyOneCallAndLocalLinkage = bool OnlyOneCallAndLocalLinkage =

View File

@ -22,6 +22,7 @@ define void @inner1(i32 *%ptr) {
%E = bitcast i32* %ptr to i8* %E = bitcast i32* %ptr to i8*
%F = select i1 false, i32* %ptr, i32* @glbl %F = select i1 false, i32* %ptr, i32* @glbl
call void @llvm.lifetime.start(i64 0, i8* %E) call void @llvm.lifetime.start(i64 0, i8* %E)
call void @extern()
ret void ret void
} }
@ -42,6 +43,7 @@ define void @inner2(i32 *%ptr) {
%E = bitcast i32* %ptr to i8* %E = bitcast i32* %ptr to i8*
%F = select i1 false, i32* %ptr, i32* @glbl %F = select i1 false, i32* %ptr, i32* @glbl
call void @llvm.lifetime.start(i64 0, i8* %E) call void @llvm.lifetime.start(i64 0, i8* %E)
call void @extern()
ret void ret void
} }
@ -56,6 +58,7 @@ define void @outer3() {
define void @inner3(i32 *%ptr, i1 %x) { define void @inner3(i32 *%ptr, i1 %x) {
%A = icmp eq i32* %ptr, null %A = icmp eq i32* %ptr, null
%B = and i1 %x, %A %B = and i1 %x, %A
call void @extern()
br i1 %A, label %bb.true, label %bb.false br i1 %A, label %bb.true, label %bb.false
bb.true: bb.true:
; This block musn't be counted in the inline cost. ; This block musn't be counted in the inline cost.
@ -97,6 +100,7 @@ define void @outer4(i32 %A) {
define void @inner4(i32 *%ptr, i32 %A) { define void @inner4(i32 *%ptr, i32 %A) {
%B = getelementptr inbounds i32, i32* %ptr, i32 %A %B = getelementptr inbounds i32, i32* %ptr, i32 %A
%C = icmp eq i32* %ptr, null %C = icmp eq i32* %ptr, null
call void @extern()
br i1 %C, label %bb.true, label %bb.false br i1 %C, label %bb.true, label %bb.false
bb.true: bb.true:
; This block musn't be counted in the inline cost. ; This block musn't be counted in the inline cost.
@ -139,6 +143,7 @@ define void @outer5() {
define void @inner5(i1 %flag, i32 *%ptr) { define void @inner5(i1 %flag, i32 *%ptr) {
%A = load i32, i32* %ptr %A = load i32, i32* %ptr
store i32 0, i32* %ptr store i32 0, i32* %ptr
call void @extern()
%C = getelementptr inbounds i32, i32* %ptr, i32 0 %C = getelementptr inbounds i32, i32* %ptr, i32 0
br i1 %flag, label %if.then, label %exit br i1 %flag, label %if.then, label %exit
@ -153,3 +158,4 @@ exit:
ret void ret void
} }
declare void @extern()

View File

@ -9,7 +9,7 @@ define i32 @callee1(i32 %x) !prof !21 {
%x1 = add i32 %x, 1 %x1 = add i32 %x, 1
%x2 = add i32 %x1, 1 %x2 = add i32 %x1, 1
%x3 = add i32 %x2, 1 %x3 = add i32 %x2, 1
call void @extern()
ret i32 %x3 ret i32 %x3
} }
@ -18,7 +18,7 @@ define i32 @callee2(i32 %x) !prof !22 {
%x1 = add i32 %x, 1 %x1 = add i32 %x, 1
%x2 = add i32 %x1, 1 %x2 = add i32 %x1, 1
%x3 = add i32 %x2, 1 %x3 = add i32 %x2, 1
call void @extern()
ret i32 %x3 ret i32 %x3
} }
@ -32,6 +32,8 @@ define i32 @caller2(i32 %y1) !prof !22 {
ret i32 %y3 ret i32 %y3
} }
declare void @extern()
!llvm.module.flags = !{!1} !llvm.module.flags = !{!1}
!21 = !{!"function_entry_count", i64 100} !21 = !{!"function_entry_count", i64 100}
!22 = !{!"function_entry_count", i64 1} !22 = !{!"function_entry_count", i64 1}

View File

@ -17,6 +17,7 @@
; Function Attrs: nounwind readnone uwtable ; Function Attrs: nounwind readnone uwtable
define i32 @simpleFunction(i32 %a) #0 { define i32 @simpleFunction(i32 %a) #0 {
entry: entry:
call void @extern()
%a1 = load volatile i32, i32* @a %a1 = load volatile i32, i32* @a
%x1 = add i32 %a1, %a1 %x1 = add i32 %a1, %a1
%a2 = load volatile i32, i32* @a %a2 = load volatile i32, i32* @a
@ -54,6 +55,7 @@ define i32 @ColdFunction(i32 %a) #1 {
; DEFAULT-LABEL: @ColdFunction ; DEFAULT-LABEL: @ColdFunction
; DEFAULT: ret ; DEFAULT: ret
entry: entry:
call void @extern()
%a1 = load volatile i32, i32* @a %a1 = load volatile i32, i32* @a
%x1 = add i32 %a1, %a1 %x1 = add i32 %a1, %a1
%a2 = load volatile i32, i32* @a %a2 = load volatile i32, i32* @a
@ -91,6 +93,7 @@ define i32 @ColdFunction2(i32 %a) #1 {
; DEFAULT-LABEL: @ColdFunction2 ; DEFAULT-LABEL: @ColdFunction2
; DEFAULT: ret ; DEFAULT: ret
entry: entry:
call void @extern()
%a1 = load volatile i32, i32* @a %a1 = load volatile i32, i32* @a
%x1 = add i32 %a1, %a1 %x1 = add i32 %a1, %a1
%a2 = load volatile i32, i32* @a %a2 = load volatile i32, i32* @a
@ -196,5 +199,6 @@ entry:
ret i32 %add ret i32 %add
} }
declare void @extern()
attributes #0 = { nounwind readnone uwtable } attributes #0 = { nounwind readnone uwtable }
attributes #1 = { nounwind cold readnone uwtable } attributes #1 = { nounwind cold readnone uwtable }

View File

@ -9,7 +9,7 @@ define i32 @callee1(i32 %x) !prof !21 {
%x1 = add i32 %x, 1 %x1 = add i32 %x, 1
%x2 = add i32 %x1, 1 %x2 = add i32 %x1, 1
%x3 = add i32 %x2, 1 %x3 = add i32 %x2, 1
call void @extern()
ret i32 %x3 ret i32 %x3
} }
@ -18,7 +18,7 @@ define i32 @callee2(i32 %x) !prof !22 {
%x1 = add i32 %x, 1 %x1 = add i32 %x, 1
%x2 = add i32 %x1, 1 %x2 = add i32 %x1, 1
%x3 = add i32 %x2, 1 %x3 = add i32 %x2, 1
call void @extern()
ret i32 %x3 ret i32 %x3
} }
@ -32,6 +32,8 @@ define i32 @caller2(i32 %y1) !prof !22 {
ret i32 %y3 ret i32 %y3
} }
declare void @extern()
!llvm.module.flags = !{!1} !llvm.module.flags = !{!1}
!21 = !{!"function_entry_count", i64 300} !21 = !{!"function_entry_count", i64 300}
!22 = !{!"function_entry_count", i64 1} !22 = !{!"function_entry_count", i64 1}

View File

@ -9,7 +9,7 @@ define i32 @callee1(i32 %x) {
%x1 = add i32 %x, 1 %x1 = add i32 %x, 1
%x2 = add i32 %x1, 1 %x2 = add i32 %x1, 1
%x3 = add i32 %x2, 1 %x3 = add i32 %x2, 1
call void @extern()
ret i32 %x3 ret i32 %x3
} }
@ -18,7 +18,7 @@ define i32 @callee2(i32 %x) {
%x1 = add i32 %x, 1 %x1 = add i32 %x, 1
%x2 = add i32 %x1, 1 %x2 = add i32 %x1, 1
%x3 = add i32 %x2, 1 %x3 = add i32 %x2, 1
call void @extern()
ret i32 %x3 ret i32 %x3
} }
@ -32,6 +32,8 @@ define i32 @caller2(i32 %y1) {
ret i32 %y3 ret i32 %y3
} }
declare void @extern()
!llvm.module.flags = !{!1} !llvm.module.flags = !{!1}
!21 = !{!"branch_weights", i64 300} !21 = !{!"branch_weights", i64 300}
!22 = !{!"branch_weights", i64 1} !22 = !{!"branch_weights", i64 1}

View File

@ -12,6 +12,7 @@
; This function should be larger than the inline threshold for -Oz (25), but ; This function should be larger than the inline threshold for -Oz (25), but
; smaller than the inline threshold for optsize (75). ; smaller than the inline threshold for optsize (75).
define i32 @inner() { define i32 @inner() {
call void @extern()
%a1 = load volatile i32, i32* @a %a1 = load volatile i32, i32* @a
%x1 = add i32 %a1, %a1 %x1 = add i32 %a1, %a1
%a2 = load volatile i32, i32* @a %a2 = load volatile i32, i32* @a
@ -42,3 +43,5 @@ define i32 @outer2() minsize {
%r = call i32 @inner() %r = call i32 @inner()
ret i32 %r ret i32 %r
} }
declare void @extern()

View File

@ -8,6 +8,7 @@ define void @caller(i32 %a, i1 %b) #0 {
} }
define void @callee(i32 %a, i1 %b) { define void @callee(i32 %a, i1 %b) {
call void @extern()
call void asm sideeffect "", ""() call void asm sideeffect "", ""()
br i1 %b, label %bb1, label %bb2 br i1 %b, label %bb1, label %bb2
bb1: bb1:
@ -17,3 +18,5 @@ bb2:
call void asm sideeffect "", ""() call void asm sideeffect "", ""()
ret void ret void
} }
declare void @extern()

View File

@ -12,7 +12,7 @@
; 4 return foo(); ; 4 return foo();
; 5 } ; 5 }
; CHECK: remark: /tmp/s.c:4:10: foo can be inlined into bar with cost={{[0-9]+}} (threshold={{[0-9]+}}) (hotness: 30) ; CHECK: remark: /tmp/s.c:4:10: foo can be inlined into bar with cost={{[0-9\-]+}} (threshold={{[0-9]+}}) (hotness: 30)
; CHECK-NEXT: remark: /tmp/s.c:4:10: foo inlined into bar (hotness: 30) ; CHECK-NEXT: remark: /tmp/s.c:4:10: foo inlined into bar (hotness: 30)
; YAML: --- !Analysis ; YAML: --- !Analysis
@ -28,7 +28,7 @@
; YAML-NEXT: - Caller: bar ; YAML-NEXT: - Caller: bar
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 0 } ; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 0 }
; YAML-NEXT: - String: ' with cost=' ; YAML-NEXT: - String: ' with cost='
; YAML-NEXT: - Cost: '{{[0-9]+}}' ; YAML-NEXT: - Cost: '{{[0-9\-]+}}'
; YAML-NEXT: - String: ' (threshold=' ; YAML-NEXT: - String: ' (threshold='
; YAML-NEXT: - Threshold: '{{[0-9]+}}' ; YAML-NEXT: - Threshold: '{{[0-9]+}}'
; YAML-NEXT: - String: ')' ; YAML-NEXT: - String: ')'

View File

@ -4,7 +4,7 @@ target datalayout = "p:32:32-p1:64:64-p2:16:16-n16:32:64"
define i32 @outer1() { define i32 @outer1() {
; CHECK-LABEL: @outer1( ; CHECK-LABEL: @outer1(
; CHECK-NOT: call ; CHECK-NOT: call i32
; CHECK: ret i32 ; CHECK: ret i32
%ptr = alloca i32 %ptr = alloca i32
@ -15,6 +15,7 @@ define i32 @outer1() {
} }
define i32 @inner1(i32* %begin, i32* %end) { define i32 @inner1(i32* %begin, i32* %end) {
call void @extern()
%begin.i = ptrtoint i32* %begin to i32 %begin.i = ptrtoint i32* %begin to i32
%end.i = ptrtoint i32* %end to i32 %end.i = ptrtoint i32* %end to i32
%distance = sub i32 %end.i, %begin.i %distance = sub i32 %end.i, %begin.i
@ -43,6 +44,7 @@ define i32 @outer2(i32* %ptr) {
} }
define i32 @inner2(i32* %begin, i32* %end) { define i32 @inner2(i32* %begin, i32* %end) {
call void @extern()
%begin.i = ptrtoint i32* %begin to i32 %begin.i = ptrtoint i32* %begin to i32
%end.i = ptrtoint i32* %end to i32 %end.i = ptrtoint i32* %end to i32
%distance = sub i32 %end.i, %begin.i %distance = sub i32 %end.i, %begin.i
@ -60,6 +62,7 @@ else:
; The inttoptrs are free since it is a smaller integer to a larger ; The inttoptrs are free since it is a smaller integer to a larger
; pointer size ; pointer size
define i32 @inttoptr_free_cost(i32 %a, i32 %b, i32 %c) { define i32 @inttoptr_free_cost(i32 %a, i32 %b, i32 %c) {
call void @extern()
%p1 = inttoptr i32 %a to i32 addrspace(1)* %p1 = inttoptr i32 %a to i32 addrspace(1)*
%p2 = inttoptr i32 %b to i32 addrspace(1)* %p2 = inttoptr i32 %b to i32 addrspace(1)*
%p3 = inttoptr i32 %c to i32 addrspace(1)* %p3 = inttoptr i32 %c to i32 addrspace(1)*
@ -73,7 +76,7 @@ define i32 @inttoptr_free_cost(i32 %a, i32 %b, i32 %c) {
define i32 @inttoptr_free_cost_user(i32 %begin, i32 %end) { define i32 @inttoptr_free_cost_user(i32 %begin, i32 %end) {
; CHECK-LABEL: @inttoptr_free_cost_user( ; CHECK-LABEL: @inttoptr_free_cost_user(
; CHECK-NOT: call ; CHECK-NOT: call i32
%x = call i32 @inttoptr_free_cost(i32 %begin, i32 %end, i32 9) %x = call i32 @inttoptr_free_cost(i32 %begin, i32 %end, i32 9)
ret i32 %x ret i32 %x
} }
@ -81,6 +84,7 @@ define i32 @inttoptr_free_cost_user(i32 %begin, i32 %end) {
; The inttoptrs have a cost since it is a larger integer to a smaller ; The inttoptrs have a cost since it is a larger integer to a smaller
; pointer size ; pointer size
define i32 @inttoptr_cost_smaller_ptr(i32 %a, i32 %b, i32 %c) { define i32 @inttoptr_cost_smaller_ptr(i32 %a, i32 %b, i32 %c) {
call void @extern()
%p1 = inttoptr i32 %a to i32 addrspace(2)* %p1 = inttoptr i32 %a to i32 addrspace(2)*
%p2 = inttoptr i32 %b to i32 addrspace(2)* %p2 = inttoptr i32 %b to i32 addrspace(2)*
%p3 = inttoptr i32 %c to i32 addrspace(2)* %p3 = inttoptr i32 %c to i32 addrspace(2)*
@ -94,8 +98,9 @@ define i32 @inttoptr_cost_smaller_ptr(i32 %a, i32 %b, i32 %c) {
define i32 @inttoptr_cost_smaller_ptr_user(i32 %begin, i32 %end) { define i32 @inttoptr_cost_smaller_ptr_user(i32 %begin, i32 %end) {
; CHECK-LABEL: @inttoptr_cost_smaller_ptr_user( ; CHECK-LABEL: @inttoptr_cost_smaller_ptr_user(
; CHECK: call ; CHECK: call i32
%x = call i32 @inttoptr_cost_smaller_ptr(i32 %begin, i32 %end, i32 9) %x = call i32 @inttoptr_cost_smaller_ptr(i32 %begin, i32 %end, i32 9)
ret i32 %x ret i32 %x
} }
declare void @extern()