37struct InstrumentationOptions {
43 bool HandleAllReturns;
71 InstrumentationOptions);
83 InstrumentationOptions);
88void XRayInstrumentation::replaceRetWithPatchableRet(
90 InstrumentationOptions
op) {
94 for (
auto &
MBB : MF) {
98 (
op.HandleAllReturns ||
T.getOpcode() ==
TII->getReturnOpcode())) {
101 Opc = TargetOpcode::PATCHABLE_RET;
106 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
111 for (
auto &MO :
T.operands())
114 if (
T.shouldUpdateCallSiteInfo())
115 MF.eraseCallSiteInfo(&
T);
120 for (
auto &
I : Terminators)
121 I->eraseFromParent();
124void XRayInstrumentation::prependRetWithPatchableExit(
126 InstrumentationOptions
op) {
131 (
op.HandleAllReturns ||
T.getOpcode() ==
TII->getReturnOpcode())) {
132 Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
135 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
147 auto InstrAttr =
F.getFnAttribute(
"function-instrument");
148 bool AlwaysInstrument = InstrAttr.isStringAttribute() &&
149 InstrAttr.getValueAsString() ==
"xray-always";
150 bool NeverInstrument = InstrAttr.isStringAttribute() &&
151 InstrAttr.getValueAsString() ==
"xray-never";
152 if (NeverInstrument && !AlwaysInstrument)
154 auto IgnoreLoopsAttr =
F.getFnAttribute(
"xray-ignore-loops");
157 if (!AlwaysInstrument) {
158 bool IgnoreLoops = IgnoreLoopsAttr.isValid();
159 XRayThreshold =
F.getFnAttributeAsParsedInteger(
160 "xray-instruction-threshold", std::numeric_limits<uint64_t>::max());
161 if (XRayThreshold == std::numeric_limits<uint64_t>::max())
166 for (
const auto &
MBB : MF)
169 bool TooFewInstrs = MICount < XRayThreshold;
173 auto *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
181 auto *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
184 ComputedMLI.
getBase().analyze(MDT->getBase());
191 if (MLI->empty() && TooFewInstrs)
193 }
else if (TooFewInstrs) {
206 auto *
TII = MF.getSubtarget().getInstrInfo();
207 auto &FirstMBB = *MBI;
208 auto &FirstMI = *FirstMBB.begin();
210 if (!MF.getSubtarget().isXRaySupported()) {
211 FirstMI.emitError(
"An attempt to perform XRay instrumentation for an"
212 " unsupported target.");
216 if (!
F.hasFnAttribute(
"xray-skip-entry")) {
219 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
220 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
223 if (!
F.hasFnAttribute(
"xray-skip-exit")) {
224 switch (MF.getTarget().getTargetTriple().getArch()) {
225 case Triple::ArchType::arm:
226 case Triple::ArchType::thumb:
227 case Triple::ArchType::aarch64:
228 case Triple::ArchType::hexagon:
229 case Triple::ArchType::mips:
230 case Triple::ArchType::mipsel:
231 case Triple::ArchType::mips64:
232 case Triple::ArchType::mips64el: {
234 InstrumentationOptions
op;
235 op.HandleTailcall =
false;
236 op.HandleAllReturns =
true;
237 prependRetWithPatchableExit(MF,
TII,
op);
240 case Triple::ArchType::ppc64le: {
242 InstrumentationOptions
op;
243 op.HandleTailcall =
false;
244 op.HandleAllReturns =
true;
245 replaceRetWithPatchableRet(MF,
TII,
op);
251 InstrumentationOptions
op;
252 op.HandleTailcall =
true;
253 op.HandleAllReturns =
false;
254 replaceRetWithPatchableRet(MF,
TII,
op);
262char XRayInstrumentation::ID = 0;
265 "Insert XRay ops",
false,
false)
This file contains the simple types necessary to represent the attributes associated with functions a...
const HexagonInstrInfo * TII
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
bool isTailCall(const MachineInstr &MI) const override
iterator_range< iterator > terminators()
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineDomTree & getBase()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
LoopInfoBase< MachineBasicBlock, MachineLoop > & getBase()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void initializeXRayInstrumentationPass(PassRegistry &)
char & XRayInstrumentationID
This pass inserts the XRay instrumentation sleds if they are supported by the target platform.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.