Index: include/llvm/Target/TargetInstrInfo.h =================================================================== --- include/llvm/Target/TargetInstrInfo.h +++ include/llvm/Target/TargetInstrInfo.h @@ -152,6 +152,19 @@ unsigned getCatchReturnOpcode() const { return CatchRetOpcode; } + /// This returns true if the given instruction is a "normal return" as opposed + /// to special kinds of returns. On platforms where there may be multiple + /// OpCodes that signify 'normal' return instructions (like in X86), this + /// return true for those instructions. The default implementation excludes + /// known non-normal instructions. + virtual bool isNormalReturn(const MachineInstr *MI) const { + if (!MI->isReturn()) return false; + auto OpCode = MI->getOpcode(); + bool IsCatchReturn = OpCode == getCatchReturnOpcode(); + bool IsFrameDestroy = OpCode == getCallFrameDestroyOpcode(); + return !IsCatchReturn && !IsFrameDestroy; + } + /// Returns the actual stack pointer adjustment made by an instruction /// as part of a call sequence. By default, only call frame setup/destroy /// instructions adjust the stack, but targets may want to override this Index: lib/CodeGen/XRayInstrumentation.cpp =================================================================== --- lib/CodeGen/XRayInstrumentation.cpp +++ lib/CodeGen/XRayInstrumentation.cpp @@ -68,19 +68,18 @@ // PATCHABLE_RET instructions. SmallVector Terminators; for (auto &MBB : MF) { - for (auto &Terminator : MBB.terminators()) { + for (auto &T : MBB.terminators()) { // FIXME: Handle tail calls here too? - if (Terminator.isReturn() && (Terminator.getOpcode() != ISD::CATCHRET || - Terminator.getOpcode() != ISD::CLEANUPRET || - Terminator.getOpcode() != ISD::EH_RETURN)) { + if (T.isReturn() && TII->isNormalReturn(&T)) { // Replace return instructions with: // PATCHABLE_RET , ... - auto MIB = BuildMI(MBB, Terminator, Terminator.getDebugLoc(), + auto MIB = BuildMI(MBB, T, T.getDebugLoc(), TII->get(TargetOpcode::PATCHABLE_RET)) - .addImm(Terminator.getOpcode()); - for (auto &MO : Terminator.operands()) + .addImm(T.getOpcode()); + for (auto &MO : T.operands()) MIB.addOperand(MO); - Terminators.push_back(&Terminator); + Terminators.push_back(&T); + break; } } } Index: lib/Target/X86/X86InstrInfo.h =================================================================== --- lib/Target/X86/X86InstrInfo.h +++ lib/Target/X86/X86InstrInfo.h @@ -531,6 +531,8 @@ ArrayRef> getSerializableDirectMachineOperandTargetFlags() const override; + bool isNormalReturn(const MachineInstr *MI) const override; + protected: /// Commutes the operands in the given instruction by changing the operands /// order and/or changing the instruction's opcode and/or the immediate value Index: lib/Target/X86/X86InstrInfo.cpp =================================================================== --- lib/Target/X86/X86InstrInfo.cpp +++ lib/Target/X86/X86InstrInfo.cpp @@ -7312,6 +7312,32 @@ return makeArrayRef(TargetFlags); } +bool X86InstrInfo::isNormalReturn(const MachineInstr *MI) const { + // Inspect the actual op-code to see if it's a normal return instruction. + if (!MI->isReturn()) + return false; + auto OpCode = MI->getOpcode(); + // FIXME: Maybe handle IRET instructions too? + switch (OpCode) { + default: + break; + case X86::RETL: + case X86::RETQ: + case X86::RETW: + case X86::RETIL: + case X86::RETIQ: + case X86::RETIW: + case X86::LRETL: + case X86::LRETQ: + case X86::LRETW: + case X86::LRETIL: + case X86::LRETIQ: + case X86::LRETIW: + return true; + } + return false; +} + namespace { /// Create Global Base Reg pass. This initializes the PIC /// global base register for x86-32.