Index: lib/CodeGen/XRayInstrumentation.cpp =================================================================== --- lib/CodeGen/XRayInstrumentation.cpp +++ lib/CodeGen/XRayInstrumentation.cpp @@ -95,10 +95,17 @@ { for (auto &MBB : MF) { for (auto &T : MBB.terminators()) { + unsigned Opc = 0; if (T.isReturn()) { - // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT - BuildMI(MBB, T, T.getDebugLoc(), - TII->get(TargetOpcode::PATCHABLE_FUNCTION_EXIT)); + Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT; + } + if (TII->isTailCall(T)) { + Opc = TargetOpcode::PATCHABLE_TAIL_CALL; + } + if (Opc != 0) { + // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT or + // PATCHABLE_TAIL_CALL . + BuildMI(MBB, T, T.getDebugLoc(),TII->get(Opc)); } } } Index: lib/Target/ARM/ARMAsmPrinter.h =================================================================== --- lib/Target/ARM/ARMAsmPrinter.h +++ lib/Target/ARM/ARMAsmPrinter.h @@ -112,6 +112,7 @@ // XRay-specific lowering for ARM. void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); + void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); // Helper function that emits the XRay sleds we've collected for a particular // function. void EmitXRayTable(); Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -2050,6 +2050,9 @@ case ARM::PATCHABLE_FUNCTION_EXIT: LowerPATCHABLE_FUNCTION_EXIT(*MI); return; + case ARM::PATCHABLE_TAIL_CALL: + LowerPATCHABLE_TAIL_CALL(*MI); + return; } MCInst TmpInst; Index: lib/Target/ARM/ARMMCInstLower.cpp =================================================================== --- lib/Target/ARM/ARMMCInstLower.cpp +++ lib/Target/ARM/ARMMCInstLower.cpp @@ -219,6 +219,11 @@ EmitSled(MI, SledKind::FUNCTION_EXIT); } +void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) +{ + EmitSled(MI, SledKind::TAIL_CALL); +} + void ARMAsmPrinter::EmitXRayTable() { if (Sleds.empty()) Index: test/CodeGen/ARM/xray-tail-call-sled.ll =================================================================== --- test/CodeGen/ARM/xray-tail-call-sled.ll +++ test/CodeGen/ARM/xray-tail-call-sled.ll @@ -0,0 +1,53 @@ +; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s + +define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" { +; CHECK: .p2align 2 +; CHECK-LABEL: Lxray_sled_0: +; CHECK-NEXT: b #20 +; 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-NEXT: mov r0, #0 +; CHECK-NEXT: .p2align 2 +; CHECK-LABEL: Lxray_sled_1: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp1: +; CHECK-NEXT: bx lr +} + +define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" { +; CHECK: .p2align 2 +; CHECK-LABEL: Lxray_sled_2: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp2: +; CHECK: .p2align 2 +; CHECK-LABEL: Lxray_sled_3: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp3: + %retval = tail call i32 @callee() +; CHECK: b callee + ret i32 %retval +}