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