Rename CountingFunctionInserter and use for both mcount and cygprofile calls, before and after inlining

Clang implements the -finstrument-functions flag inherited from GCC, which
inserts calls to __cyg_profile_func_{enter,exit} on function entry and exit.

This is useful for getting a trace of how the functions in a program are
executed. Normally, the calls remain even if a function is inlined into another
function, but it is useful to be able to turn this off for users who are
interested in a lower-level trace, i.e. one that reflects what functions are
called post-inlining. (We use this to generate link order files for Chromium.)

LLVM already has a pass for inserting similar instrumentation calls to
mcount(), which it does after inlining. This patch renames and extends that
pass to handle calls both to mcount and the cygprofile functions, before and/or
after inlining as controlled by function attributes.

Differential Revision: https://reviews.llvm.org/D39287

llvm-svn: 318195
diff --git a/llvm/test/CodeGen/PowerPC/mcount-insertion.ll b/llvm/test/CodeGen/PowerPC/mcount-insertion.ll
index 04e8571..cbb7947 100644
--- a/llvm/test/CodeGen/PowerPC/mcount-insertion.ll
+++ b/llvm/test/CodeGen/PowerPC/mcount-insertion.ll
@@ -1,16 +1,46 @@
-; RUN: llc < %s | FileCheck %s
+; RUN: opt -ee-instrument < %s | opt -inline | llc | FileCheck %s
+
+; The run-line mimics how Clang might run the instrumentation passes.
+
 target datalayout = "E-m:e-i64:64-n32:64"
 target triple = "powerpc64-bgq-linux"
 
-define void @test1() #0 {
+
+define void @leaf_function() #0 {
 entry:
   ret void
 
-; CHECK-LABEL: @test1
+; CHECK-LABEL: leaf_function:
 ; CHECK: bl mcount
-; CHECK-NOT: mcount
+; CHECK-NOT: bl
+; CHECK: bl __cyg_profile_func_enter
+; CHECK-NOT: bl
+; CHECK: bl __cyg_profile_func_exit
+; CHECK-NOT: bl
 ; CHECK: blr
 }
 
-attributes #0 = { "counting-function"="mcount" }
 
+define void @root_function() #0 {
+entry:
+  call void @leaf_function()
+  ret void
+
+; CHECK-LABEL: root_function:
+; CHECK: bl mcount
+; CHECK-NOT: bl
+; CHECK: bl __cyg_profile_func_enter
+; CHECK-NOT: bl
+
+; Entry and exit calls, inlined from @leaf_function()
+; CHECK: bl __cyg_profile_func_enter
+; CHECK-NOT: bl
+; CHECK: bl __cyg_profile_func_exit
+; CHECK-NOT: bl
+
+; CHECK: bl __cyg_profile_func_exit
+; CHECK-NOT: bl
+; CHECK: blr
+}
+
+attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll
index 1f7415e..cb7dabe 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -22,7 +22,7 @@
 ; CHECK-NEXT:       Lower Garbage Collection Instructions
 ; CHECK-NEXT:       Shadow Stack GC Lowering
 ; CHECK-NEXT:       Remove unreachable blocks from the CFG
-; CHECK-NEXT:       Inserts calls to mcount-like functions
+; CHECK-NEXT:       Instrument function entry/exit with calls to e.g. mcount() (post inlining)
 ; CHECK-NEXT:       Scalarize Masked Memory Intrinsics
 ; CHECK-NEXT:       Expand reduction intrinsics
 ; CHECK-NEXT:     Rewrite Symbols
diff --git a/llvm/test/Transforms/CountingFunctionInserter/mcount.ll b/llvm/test/Transforms/CountingFunctionInserter/mcount.ll
index 88297c7..6d9aaab 100644
--- a/llvm/test/Transforms/CountingFunctionInserter/mcount.ll
+++ b/llvm/test/Transforms/CountingFunctionInserter/mcount.ll
@@ -1,27 +1,86 @@
-; RUN: opt -S -cfinserter < %s | FileCheck %s
+; RUN: opt -passes="function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument)" -S < %s | FileCheck %s
+
+; Running the passes twice should not result in more instrumentation.
+; RUN: opt -passes="function(ee-instrument),function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument),function(post-inline-ee-instrument)" -S < %s | FileCheck %s
+
 target datalayout = "E-m:e-i64:64-n32:64"
 target triple = "powerpc64-bgq-linux"
 
-define void @test1() #0 {
+define void @leaf_function() #0 {
 entry:
   ret void
 
-; CHECK-LABEL: define void @test1()
+; CHECK-LABEL: define void @leaf_function()
 ; CHECK: entry:
 ; CHECK-NEXT: call void @mcount()
-; CHECK: ret void
+; CHECK-NEXT: %0 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT: call void @__cyg_profile_func_enter(i8* bitcast (void ()* @leaf_function to i8*), i8* %0)
+; CHECK-NEXT: %1 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT: call void @__cyg_profile_func_exit(i8* bitcast (void ()* @leaf_function to i8*), i8* %1)
+; CHECK-NEXT: ret void
 }
 
-define void @test2() #1 {
+
+define void @root_function() #0 {
 entry:
+  call void @leaf_function()
   ret void
 
-; CHECK-LABEL: define void @test2()
+; CHECK-LABEL: define void @root_function()
 ; CHECK: entry:
-; CHECK-NEXT: call void @.mcount()
-; CHECK: ret void
+; CHECK-NEXT: call void @mcount()
+
+; CHECK-NEXT %0 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT call void @__cyg_profile_func_enter(i8* bitcast (void ()* @root_function to i8*), i8* %0)
+
+; Entry and exit calls, inlined from @leaf_function()
+; CHECK-NEXT %1 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT call void @__cyg_profile_func_enter(i8* bitcast (void ()* @leaf_function to i8*), i8* %1)
+; CHECK-NEXT %2 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT call void @__cyg_profile_func_exit(i8* bitcast (void ()* @leaf_function to i8*), i8* %2)
+; CHECK-NEXT %3 = call i8* @llvm.returnaddress(i32 0)
+
+; CHECK-NEXT call void @__cyg_profile_func_exit(i8* bitcast (void ()* @root_function to i8*), i8* %3)
+; CHECK-NEXT ret void
 }
 
-attributes #0 = { "counting-function"="mcount" }
-attributes #1 = { "counting-function"=".mcount" }
+attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
 
+
+; The mcount function has many different names.
+
+define void @f1() #1 { entry: ret void }
+; CHECK-LABEL: define void @f1
+; CHECK: call void @.mcount
+
+define void @f2() #2 { entry: ret void }
+; CHECK-LABEL: define void @f2
+; CHECK: call void @"\01__gnu_mcount_nc"
+
+define void @f3() #3 { entry: ret void }
+; CHECK-LABEL: define void @f3
+; CHECK: call void @"\01_mcount"
+
+define void @f4() #4 { entry: ret void }
+; CHECK-LABEL: define void @f4
+; CHECK: call void @"\01mcount"
+
+define void @f5() #5 { entry: ret void }
+; CHECK-LABEL: define void @f5
+; CHECK: call void @__mcount
+
+define void @f6() #6 { entry: ret void }
+; CHECK-LABEL: define void @f6
+; CHECK: call void @_mcount
+
+
+; The attributes are "consumed" when the instrumentation is inserted.
+; CHECK: attributes
+; CHECK-NOT: instrument-function
+
+attributes #1 = { "instrument-function-entry-inlined"=".mcount" }
+attributes #2 = { "instrument-function-entry-inlined"="\01__gnu_mcount_nc" }
+attributes #3 = { "instrument-function-entry-inlined"="\01_mcount" }
+attributes #4 = { "instrument-function-entry-inlined"="\01mcount" }
+attributes #5 = { "instrument-function-entry-inlined"="__mcount" }
+attributes #6 = { "instrument-function-entry-inlined"="_mcount" }