Index: lib/CodeGen/XRayInstrumentation.cpp =================================================================== --- lib/CodeGen/XRayInstrumentation.cpp +++ lib/CodeGen/XRayInstrumentation.cpp @@ -43,7 +43,7 @@ // This is the approach to go on CPUs which have a single RET instruction, // like x86/x86_64. void replaceRetWithPatchableRet(MachineFunction &MF, - const TargetInstrInfo *TII); + const TargetInstrInfo *TII); // Prepend the original return instruction with the exit sled code ("patchable // function exit" pseudo-instruction), preserving the original return @@ -54,13 +54,12 @@ // have to call the trampoline and return from it to the original return // instruction of the function being instrumented. void prependRetWithPatchableExit(MachineFunction &MF, - const TargetInstrInfo *TII); + const TargetInstrInfo *TII); }; } // anonymous namespace -void XRayInstrumentation::replaceRetWithPatchableRet(MachineFunction &MF, - const TargetInstrInfo *TII) -{ +void XRayInstrumentation::replaceRetWithPatchableRet( + MachineFunction &MF, const TargetInstrInfo *TII) { // We look for *all* terminators and returns, then replace those with // PATCHABLE_RET instructions. SmallVector Terminators; @@ -91,9 +90,8 @@ I->eraseFromParent(); } -void XRayInstrumentation::prependRetWithPatchableExit(MachineFunction &MF, - const TargetInstrInfo *TII) -{ +void XRayInstrumentation::prependRetWithPatchableExit( + MachineFunction &MF, const TargetInstrInfo *TII) { for (auto &MBB : MF) { for (auto &T : MBB.terminators()) { unsigned Opc = 0; @@ -106,13 +104,16 @@ if (Opc != 0) { // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT or // PATCHABLE_TAIL_CALL . - BuildMI(MBB, T, T.getDebugLoc(),TII->get(Opc)); + BuildMI(MBB, T, T.getDebugLoc(), TII->get(Opc)); } } } } bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) { + if (MF.empty()) + return false; // The function is empty. + auto &F = *MF.getFunction(); auto InstrAttr = F.getFnAttribute("function-instrument"); bool AlwaysInstrument = !InstrAttr.hasAttribute(Attribute::None) && @@ -129,23 +130,24 @@ return false; // Function is too small. } - auto &FirstMBB = *MF.begin(); - auto &FirstMI = *FirstMBB.begin(); - - if (!MF.getSubtarget().isXRaySupported()) { - FirstMI.emitError("An attempt to perform XRay instrumentation for an" - " unsupported target."); - return false; + auto *TII = MF.getSubtarget().getInstrInfo(); + auto &FirstMBB = MF.front(); + if (FirstMBB.empty()) { + // It could be that the first MachineBasicBlock is empty, despite the + // function not being empty. So we insert the instruction in this basic + // block always. + BuildMI(FirstMBB, FirstMBB.begin(), DebugLoc(), + TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER)); + } else { + // Since the first basic block is not empty, we just add the entry + // instruction there. + auto &FirstMI = FirstMBB.instr_front(); + BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(), + TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER)); } // FIXME: Do the loop triviality analysis here or in an earlier pass. - // First, insert an PATCHABLE_FUNCTION_ENTER as the first instruction of the - // MachineFunction. - auto *TII = MF.getSubtarget().getInstrInfo(); - BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(), - TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER)); - switch (MF.getTarget().getTargetTriple().getArch()) { case Triple::ArchType::arm: case Triple::ArchType::thumb: Index: test/CodeGen/X86/xray-empty-firstmbb.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/xray-empty-firstmbb.mir @@ -0,0 +1,23 @@ +# RUN: llc -run-pass xray-instrumentation -mtriple=x86_64-unknown-linux-gnu -o - %s | FileCheck %s +# +# Make sure we can handle empty first basic blocks. + +--- | + + define i32 @foo() noinline uwtable "xray-instruction-threshold"="1" { + entry: + unreachable + } + +... + +--- +name: foo +tracksRegLiveness: true +liveins: + - { reg: '%edi'} +body: | + bb.0.entry: + liveins: %edi + ; CHECK: PATCHABLE_FUNCTION_ENTER +...