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;
174 getAnalysisIfAvailable<MachineDominatorTreeWrapperPass>();
175 auto *MDT = MDTWrapper ? &MDTWrapper->getDomTree() :
nullptr;
183 auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
184 auto *MLI = MLIWrapper ? &MLIWrapper->getLI() :
nullptr;
187 ComputedMLI.
analyze(MDT->getBase());
194 if (MLI->empty() && TooFewInstrs)
196 }
else if (TooFewInstrs) {
209 auto *
TII = MF.getSubtarget().getInstrInfo();
210 auto &FirstMBB = *MBI;
211 auto &FirstMI = *FirstMBB.begin();
213 if (!MF.getSubtarget().isXRaySupported()) {
214 FirstMI.emitError(
"An attempt to perform XRay instrumentation for an"
215 " unsupported target.");
219 if (!
F.hasFnAttribute(
"xray-skip-entry")) {
222 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
223 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
226 if (!
F.hasFnAttribute(
"xray-skip-exit")) {
227 switch (MF.getTarget().getTargetTriple().getArch()) {
228 case Triple::ArchType::arm:
229 case Triple::ArchType::thumb:
230 case Triple::ArchType::aarch64:
231 case Triple::ArchType::hexagon:
232 case Triple::ArchType::loongarch64:
233 case Triple::ArchType::mips:
234 case Triple::ArchType::mipsel:
235 case Triple::ArchType::mips64:
236 case Triple::ArchType::mips64el: {
238 InstrumentationOptions
op;
239 op.HandleTailcall =
false;
240 op.HandleAllReturns =
true;
241 prependRetWithPatchableExit(MF,
TII,
op);
244 case Triple::ArchType::ppc64le: {
246 InstrumentationOptions
op;
247 op.HandleTailcall =
false;
248 op.HandleAllReturns =
true;
249 replaceRetWithPatchableRet(MF,
TII,
op);
255 InstrumentationOptions
op;
256 op.HandleTailcall =
true;
257 op.HandleAllReturns =
false;
258 replaceRetWithPatchableRet(MF,
TII,
op);
266char XRayInstrumentation::ID = 0;
269 "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
void analyze(const DominatorTreeBase< BlockT, false > &DomTree)
Create the loop forest using a stable algorithm.
iterator_range< iterator > terminators()
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineDominatorTree & 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
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.