1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -passes="function(ee-instrument),cgscc(inline),function(ee-instrument<post-inline>)" -S < %s | FileCheck %s 3 4; Running the passes twice should not result in more instrumentation. 5; RUN: opt -passes="function(ee-instrument),function(ee-instrument),cgscc(inline),function(ee-instrument<post-inline>),function(ee-instrument<post-inline>)" -S < %s | FileCheck %s 6 7target datalayout = "E-m:e-i64:64-n32:64" 8target triple = "powerpc64le-unknown-linux" 9 10define void @leaf_function() #0 { 11; CHECK-LABEL: define void @leaf_function() { 12; CHECK-NEXT: call void @mcount() 13; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.returnaddress(i32 0) 14; CHECK-NEXT: call void @__cyg_profile_func_enter(ptr @leaf_function, ptr [[TMP1]]) 15; CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.returnaddress(i32 0) 16; CHECK-NEXT: call void @__cyg_profile_func_exit(ptr @leaf_function, ptr [[TMP2]]) 17; CHECK-NEXT: ret void 18; 19 ret void 20} 21 22 23define void @root_function() #0 { 24; CHECK-LABEL: define void @root_function() { 25; CHECK-NEXT: call void @mcount() 26; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.returnaddress(i32 0) 27; CHECK-NEXT: call void @__cyg_profile_func_enter(ptr @root_function, ptr [[TMP1]]) 28; CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.returnaddress(i32 0) 29; CHECK-NEXT: call void @__cyg_profile_func_enter(ptr @leaf_function, ptr [[TMP2]]) 30; CHECK-NEXT: [[TMP3:%.*]] = call ptr @llvm.returnaddress(i32 0) 31; CHECK-NEXT: call void @__cyg_profile_func_exit(ptr @leaf_function, ptr [[TMP3]]) 32; CHECK-NEXT: [[TMP4:%.*]] = call ptr @llvm.returnaddress(i32 0) 33; CHECK-NEXT: call void @__cyg_profile_func_exit(ptr @root_function, ptr [[TMP4]]) 34; CHECK-NEXT: ret void 35; 36 call void @leaf_function() 37 ret void 38} 39 40; The mcount function has many different names. 41 42define void @f1() #1 { 43; CHECK-LABEL: define void @f1() { 44; CHECK-NEXT: call void @.mcount() 45; CHECK-NEXT: ret void 46; 47 ret void 48} 49 50define void @f2() #2 { 51; CHECK-LABEL: define void @f2() { 52; CHECK-NEXT: call void @llvm.arm.gnu.eabi.mcount() 53; CHECK-NEXT: ret void 54; 55 ret void 56} 57 58define void @f3() #3 { 59; CHECK-LABEL: define void @f3() { 60; CHECK-NEXT: call void @"\01_mcount"() 61; CHECK-NEXT: ret void 62; 63 ret void 64} 65 66define void @f4() #4 { 67; CHECK-LABEL: define void @f4() { 68; CHECK-NEXT: call void @"\01mcount"() 69; CHECK-NEXT: ret void 70; 71 ret void 72} 73 74define void @f5() #5 { 75; CHECK-LABEL: define void @f5() { 76; CHECK-NEXT: call void @__mcount() 77; CHECK-NEXT: ret void 78; 79 ret void 80} 81 82define void @f6() #6 { 83; CHECK-LABEL: define void @f6() { 84; CHECK-NEXT: call void @_mcount() 85; CHECK-NEXT: ret void 86; 87 ret void 88} 89 90define void @f7() #7 { 91; CHECK-LABEL: define void @f7() { 92; CHECK-NEXT: call void @__cyg_profile_func_enter_bare() 93; CHECK-NEXT: ret void 94; 95 ret void 96} 97 98; Treat musttail calls as terminators; inserting between the musttail call and 99; ret is not allowed. 100declare ptr @tailcallee() 101define ptr @tailcaller() #8 { 102; CHECK-LABEL: define ptr @tailcaller() { 103; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.returnaddress(i32 0) 104; CHECK-NEXT: call void @__cyg_profile_func_exit(ptr @tailcaller, ptr [[TMP1]]) 105; CHECK-NEXT: [[TMP2:%.*]] = musttail call ptr @tailcallee() 106; CHECK-NEXT: ret ptr [[TMP2]] 107; 108 %1 = musttail call ptr @tailcallee() 109 ret ptr %1 110} 111define ptr @tailcaller2() #8 { 112; CHECK-LABEL: define ptr @tailcaller2() { 113; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.returnaddress(i32 0) 114; CHECK-NEXT: call void @__cyg_profile_func_exit(ptr @tailcaller2, ptr [[TMP1]]) 115; CHECK-NEXT: [[TMP2:%.*]] = musttail call ptr @tailcallee() 116; CHECK-NEXT: ret ptr [[TMP2]] 117; 118 %1 = musttail call ptr @tailcallee() 119 ret ptr %1 120} 121 122;; naked functions are not instrumented, otherwise the argument registers 123;; and the return address register (if present) would be clobbered. 124define void @naked() naked { 125; CHECK-LABEL: define void @naked( 126; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { 127; CHECK-NEXT: ret void 128; 129 ret void 130} 131 132define available_externally void @always_inline() { 133; CHECK-LABEL: define available_externally void @always_inline() { 134; CHECK-NEXT: ret void 135; 136 ret void 137} 138 139; The attributes are "consumed" when the instrumentation is inserted. 140; CHECK: attributes 141; CHECK-NOT: instrument-function 142 143attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" } 144attributes #1 = { "instrument-function-entry-inlined"=".mcount" } 145attributes #2 = { "instrument-function-entry-inlined"="llvm.arm.gnu.eabi.mcount" } 146attributes #3 = { "instrument-function-entry-inlined"="\01_mcount" } 147attributes #4 = { "instrument-function-entry-inlined"="\01mcount" } 148attributes #5 = { "instrument-function-entry-inlined"="__mcount" } 149attributes #6 = { "instrument-function-entry-inlined"="_mcount" } 150attributes #7 = { "instrument-function-entry-inlined"="__cyg_profile_func_enter_bare" } 151attributes #8 = { "instrument-function-exit"="__cyg_profile_func_exit" } 152