mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 18:42:46 +02:00
[xray] Allow instrumenting only function entry and/or only function exit
Extend -fxray-instrumentation-bundle to split function-entry and function-exit into two separate options, so that it is possible to instrument only function entry or only function exit. For use cases that only care about one or the other this will save significant overhead and code size. Differential Revision: https://reviews.llvm.org/D72890
This commit is contained in:
parent
d48e492a33
commit
16e0971625
@ -212,43 +212,47 @@ bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, insert an PATCHABLE_FUNCTION_ENTER as the first instruction of the
|
||||
// MachineFunction.
|
||||
BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
|
||||
TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
|
||||
if (!F.hasFnAttribute("xray-skip-entry")) {
|
||||
// First, insert an PATCHABLE_FUNCTION_ENTER as the first instruction of the
|
||||
// MachineFunction.
|
||||
BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
|
||||
TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
|
||||
}
|
||||
|
||||
switch (MF.getTarget().getTargetTriple().getArch()) {
|
||||
case Triple::ArchType::arm:
|
||||
case Triple::ArchType::thumb:
|
||||
case Triple::ArchType::aarch64:
|
||||
case Triple::ArchType::mips:
|
||||
case Triple::ArchType::mipsel:
|
||||
case Triple::ArchType::mips64:
|
||||
case Triple::ArchType::mips64el: {
|
||||
// For the architectures which don't have a single return instruction
|
||||
InstrumentationOptions op;
|
||||
op.HandleTailcall = false;
|
||||
op.HandleAllReturns = true;
|
||||
prependRetWithPatchableExit(MF, TII, op);
|
||||
break;
|
||||
}
|
||||
case Triple::ArchType::ppc64le: {
|
||||
// PPC has conditional returns. Turn them into branch and plain returns.
|
||||
InstrumentationOptions op;
|
||||
op.HandleTailcall = false;
|
||||
op.HandleAllReturns = true;
|
||||
replaceRetWithPatchableRet(MF, TII, op);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// For the architectures that have a single return instruction (such as
|
||||
// RETQ on x86_64).
|
||||
InstrumentationOptions op;
|
||||
op.HandleTailcall = true;
|
||||
op.HandleAllReturns = false;
|
||||
replaceRetWithPatchableRet(MF, TII, op);
|
||||
break;
|
||||
}
|
||||
if (!F.hasFnAttribute("xray-skip-exit")) {
|
||||
switch (MF.getTarget().getTargetTriple().getArch()) {
|
||||
case Triple::ArchType::arm:
|
||||
case Triple::ArchType::thumb:
|
||||
case Triple::ArchType::aarch64:
|
||||
case Triple::ArchType::mips:
|
||||
case Triple::ArchType::mipsel:
|
||||
case Triple::ArchType::mips64:
|
||||
case Triple::ArchType::mips64el: {
|
||||
// For the architectures which don't have a single return instruction
|
||||
InstrumentationOptions op;
|
||||
op.HandleTailcall = false;
|
||||
op.HandleAllReturns = true;
|
||||
prependRetWithPatchableExit(MF, TII, op);
|
||||
break;
|
||||
}
|
||||
case Triple::ArchType::ppc64le: {
|
||||
// PPC has conditional returns. Turn them into branch and plain returns.
|
||||
InstrumentationOptions op;
|
||||
op.HandleTailcall = false;
|
||||
op.HandleAllReturns = true;
|
||||
replaceRetWithPatchableRet(MF, TII, op);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// For the architectures that have a single return instruction (such as
|
||||
// RETQ on x86_64).
|
||||
InstrumentationOptions op;
|
||||
op.HandleTailcall = true;
|
||||
op.HandleAllReturns = false;
|
||||
replaceRetWithPatchableRet(MF, TII, op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
; RUN: llc -filetype=asm -o - -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
|
||||
|
||||
define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" "xray-skip-entry" {
|
||||
; CHECK-NOT: Lxray_sled_0:
|
||||
ret i32 0
|
||||
; CHECK-LABEL: Lxray_sled_0:
|
||||
; CHECK-NEXT: b #32
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-LABEL: Ltmp0:
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
; CHECK-LABEL: xray_instr_map
|
||||
; CHECK-LABEL: Lxray_sleds_start0
|
||||
; CHECK: .xword .Lxray_sled_0
|
||||
; CHECK-LABEL: Lxray_sleds_end0
|
@ -0,0 +1,21 @@
|
||||
; RUN: llc -filetype=asm -o - -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
|
||||
|
||||
define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" "xray-skip-exit" {
|
||||
; CHECK-LABEL: Lxray_sled_0:
|
||||
; CHECK-NEXT: b #32
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-LABEL: Ltmp0:
|
||||
ret i32 0
|
||||
; CHECK-NOT: Lxray_sled_1:
|
||||
; CHECK: ret
|
||||
}
|
||||
; CHECK-LABEL: xray_instr_map
|
||||
; CHECK-LABEL: Lxray_sleds_start0
|
||||
; CHECK: .xword .Lxray_sled_0
|
||||
; CHECK-LABEL: Lxray_sleds_end0
|
50
test/CodeGen/X86/xray-partial-instrumentation-skip-entry.ll
Normal file
50
test/CodeGen/X86/xray-partial-instrumentation-skip-entry.ll
Normal file
@ -0,0 +1,50 @@
|
||||
; RUN: llc -verify-machineinstrs -filetype=asm -o - -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
|
||||
; RUN: llc -verify-machineinstrs -filetype=asm -o - \
|
||||
; RUN: -mtriple=x86_64-unknown-linux-gnu -relocation-model=pic < %s | FileCheck %s
|
||||
; RUN: llc -verify-machineinstrs -filetype=asm -o - -mtriple=x86_64-darwin-unknown < %s | FileCheck %s
|
||||
|
||||
define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" "xray-skip-entry" {
|
||||
; CHECK-NOT: Lxray_sled_0:
|
||||
ret i32 0
|
||||
; CHECK: .p2align 1, 0x90
|
||||
; CHECK-LABEL: Lxray_sled_0:
|
||||
; CHECK: retq
|
||||
; CHECK-NEXT: nopw %cs:512(%rax,%rax)
|
||||
}
|
||||
; CHECK-LABEL: xray_instr_map
|
||||
; CHECK-LABEL: Lxray_sleds_start0:
|
||||
; CHECK: .quad {{.*}}xray_sled_0
|
||||
; CHECK-LABEL: Lxray_sleds_end0:
|
||||
; CHECK-LABEL: xray_fn_idx
|
||||
; CHECK: .quad {{.*}}xray_sleds_start0
|
||||
; CHECK-NEXT: .quad {{.*}}xray_sleds_end0
|
||||
|
||||
|
||||
; We test multiple returns in a single function to make sure we're getting all
|
||||
; of them with XRay instrumentation.
|
||||
define i32 @bar(i32 %i) nounwind noinline uwtable "function-instrument"="xray-always" "xray-skip-entry" {
|
||||
; CHECK-NOT: Lxray_sled_1:
|
||||
Test:
|
||||
%cond = icmp eq i32 %i, 0
|
||||
br i1 %cond, label %IsEqual, label %NotEqual
|
||||
IsEqual:
|
||||
ret i32 0
|
||||
; CHECK: .p2align 1, 0x90
|
||||
; CHECK-LABEL: Lxray_sled_1:
|
||||
; CHECK: retq
|
||||
; CHECK-NEXT: nopw %cs:512(%rax,%rax)
|
||||
NotEqual:
|
||||
ret i32 1
|
||||
; CHECK: .p2align 1, 0x90
|
||||
; CHECK-LABEL: Lxray_sled_2:
|
||||
; CHECK: retq
|
||||
; CHECK-NEXT: nopw %cs:512(%rax,%rax)
|
||||
}
|
||||
; CHECK-LABEL: xray_instr_map
|
||||
; CHECK-LABEL: Lxray_sleds_start1:
|
||||
; CHECK: .quad {{.*}}xray_sled_1
|
||||
; CHECK: .quad {{.*}}xray_sled_2
|
||||
; CHECK-LABEL: Lxray_sleds_end1:
|
||||
; CHECK-LABEL: xray_fn_idx
|
||||
; CHECK: .quad {{.*}}xray_sleds_start1
|
||||
; CHECK-NEXT: .quad {{.*}}xray_sleds_end1
|
49
test/CodeGen/X86/xray-partial-instrumentation-skip-exit.ll
Normal file
49
test/CodeGen/X86/xray-partial-instrumentation-skip-exit.ll
Normal file
@ -0,0 +1,49 @@
|
||||
; RUN: llc -verify-machineinstrs -filetype=asm -o - -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
|
||||
; RUN: llc -verify-machineinstrs -filetype=asm -o - \
|
||||
; RUN: -mtriple=x86_64-unknown-linux-gnu -relocation-model=pic < %s | FileCheck %s
|
||||
; RUN: llc -verify-machineinstrs -filetype=asm -o - -mtriple=x86_64-darwin-unknown < %s | FileCheck %s
|
||||
|
||||
define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" "xray-skip-exit" {
|
||||
; CHECK: .p2align 1, 0x90
|
||||
; CHECK-LABEL: Lxray_sled_0:
|
||||
; CHECK: .ascii "\353\t"
|
||||
; CHECK-NEXT: nopw 512(%rax,%rax)
|
||||
ret i32 0
|
||||
; CHECK-NOT: Lxray_sled_1:
|
||||
; CHECK: retq
|
||||
}
|
||||
; CHECK-LABEL: xray_instr_map
|
||||
; CHECK-LABEL: Lxray_sleds_start0:
|
||||
; CHECK: .quad {{.*}}xray_sled_0
|
||||
; CHECK-LABEL: Lxray_sleds_end0:
|
||||
; CHECK-LABEL: xray_fn_idx
|
||||
; CHECK: .quad {{.*}}xray_sleds_start0
|
||||
; CHECK-NEXT: .quad {{.*}}xray_sleds_end0
|
||||
|
||||
|
||||
; We test multiple returns in a single function to make sure we're skipping all
|
||||
; of them with XRay instrumentation.
|
||||
define i32 @bar(i32 %i) nounwind noinline uwtable "function-instrument"="xray-always" "xray-skip-exit" {
|
||||
; CHECK: .p2align 1, 0x90
|
||||
; CHECK-LABEL: Lxray_sled_1:
|
||||
; CHECK: .ascii "\353\t"
|
||||
; CHECK-NEXT: nopw 512(%rax,%rax)
|
||||
Test:
|
||||
%cond = icmp eq i32 %i, 0
|
||||
br i1 %cond, label %IsEqual, label %NotEqual
|
||||
IsEqual:
|
||||
ret i32 0
|
||||
; CHECK-NOT: Lxray_sled_{{.*}}:
|
||||
; CHECK: retq
|
||||
NotEqual:
|
||||
ret i32 1
|
||||
; CHECK-NOT: Lxray_sled_{{.*}}:
|
||||
; CHECK: retq
|
||||
}
|
||||
; CHECK-LABEL: xray_instr_map
|
||||
; CHECK-LABEL: Lxray_sleds_start1:
|
||||
; CHECK: .quad {{.*}}xray_sled_1
|
||||
; CHECK-LABEL: Lxray_sleds_end1:
|
||||
; CHECK-LABEL: xray_fn_idx
|
||||
; CHECK: .quad {{.*}}xray_sleds_start1
|
||||
; CHECK-NEXT: .quad {{.*}}xray_sleds_end1
|
Loading…
Reference in New Issue
Block a user