41struct InstrumentationOptions {
47 bool HandleAllReturns;
67struct XRayInstrumentation {
69 : MDT(MDT), MLI(MLI) {}
75 static bool alwaysInstrument(
Function &
F) {
76 auto InstrAttr =
F.getFnAttribute(
"function-instrument");
77 return InstrAttr.isStringAttribute() &&
78 InstrAttr.getValueAsString() ==
"xray-always";
81 static bool needMDTAndMLIAnalyses(
Function &
F) {
82 auto IgnoreLoopsAttr =
F.getFnAttribute(
"xray-ignore-loops");
83 auto AlwaysInstrument = XRayInstrumentation::alwaysInstrument(
F);
84 return !AlwaysInstrument && !IgnoreLoopsAttr.isValid();
96 InstrumentationOptions);
108 InstrumentationOptions);
116void XRayInstrumentation::replaceRetWithPatchableRet(
118 InstrumentationOptions
op) {
122 for (
auto &
MBB : MF) {
126 (
op.HandleAllReturns ||
T.getOpcode() ==
TII->getReturnOpcode())) {
129 Opc = TargetOpcode::PATCHABLE_RET;
134 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
139 for (
auto &MO :
T.operands())
142 if (
T.shouldUpdateAdditionalCallInfo())
143 MF.eraseAdditionalCallInfo(&
T);
148 for (
auto &
I : Terminators)
149 I->eraseFromParent();
152void XRayInstrumentation::prependRetWithPatchableExit(
154 InstrumentationOptions
op) {
159 (
op.HandleAllReturns ||
T.getOpcode() ==
TII->getReturnOpcode())) {
160 Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
163 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
179 if (XRayInstrumentation::needMDTAndMLIAnalyses(MF.
getFunction())) {
184 if (!XRayInstrumentation(MDT, MLI).run(MF))
192bool XRayInstrumentationLegacy::runOnMachineFunction(
MachineFunction &MF) {
195 if (XRayInstrumentation::needMDTAndMLIAnalyses(MF.
getFunction())) {
197 getAnalysisIfAvailable<MachineDominatorTreeWrapperPass>();
198 MDT = MDTWrapper ? &MDTWrapper->getDomTree() :
nullptr;
199 auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
200 MLI = MLIWrapper ? &MLIWrapper->getLI() :
nullptr;
202 return XRayInstrumentation(MDT, MLI).run(MF);
207 auto InstrAttr =
F.getFnAttribute(
"function-instrument");
208 bool AlwaysInstrument = alwaysInstrument(
F);
209 bool NeverInstrument = InstrAttr.isStringAttribute() &&
210 InstrAttr.getValueAsString() ==
"xray-never";
211 if (NeverInstrument && !AlwaysInstrument)
213 auto IgnoreLoopsAttr =
F.getFnAttribute(
"xray-ignore-loops");
216 if (!AlwaysInstrument) {
217 bool IgnoreLoops = IgnoreLoopsAttr.isValid();
218 XRayThreshold =
F.getFnAttributeAsParsedInteger(
219 "xray-instruction-threshold", std::numeric_limits<uint64_t>::max());
220 if (XRayThreshold == std::numeric_limits<uint64_t>::max())
225 for (
const auto &
MBB : MF)
228 bool TooFewInstrs = MICount < XRayThreshold;
248 if (MLI->
empty() && TooFewInstrs)
250 }
else if (TooFewInstrs) {
263 auto *
TII = MF.getSubtarget().getInstrInfo();
264 auto &FirstMBB = *MBI;
265 auto &FirstMI = *FirstMBB.begin();
267 if (!MF.getSubtarget().isXRaySupported()) {
271 Fn,
"An attempt to perform XRay instrumentation for an"
272 " unsupported target."));
277 if (!
F.hasFnAttribute(
"xray-skip-entry")) {
280 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
281 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
284 if (!
F.hasFnAttribute(
"xray-skip-exit")) {
285 switch (MF.getTarget().getTargetTriple().getArch()) {
298 InstrumentationOptions
op;
300 op.HandleTailcall = MF.getTarget().getTargetTriple().isAArch64() ||
301 MF.getTarget().getTargetTriple().isRISCV();
302 op.HandleAllReturns =
true;
303 prependRetWithPatchableExit(MF,
TII,
op);
309 InstrumentationOptions
op;
310 op.HandleTailcall =
false;
311 op.HandleAllReturns =
true;
312 replaceRetWithPatchableRet(MF,
TII,
op);
318 InstrumentationOptions
op;
319 op.HandleTailcall =
true;
320 op.HandleAllReturns =
false;
321 replaceRetWithPatchableRet(MF,
TII,
op);
329char XRayInstrumentationLegacy::ID = 0;
332 "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.
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
Diagnostic information for unsupported feature in backend.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Module * getParent()
Get the module that this global value is contained inside of...
bool isTailCall(const MachineInstr &MI) const override
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
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.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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
Analysis pass that exposes the MachineLoopInfo for a machine function.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void initializeXRayInstrumentationLegacyPass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI 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.