42struct InstrumentationOptions {
48 bool HandleAllReturns;
54 XRayInstrumentationLegacy() : MachineFunctionPass(ID) {}
56 void getAnalysisUsage(AnalysisUsage &AU)
const override {
61 bool runOnMachineFunction(MachineFunction &MF)
override;
64struct XRayInstrumentation {
65 XRayInstrumentation(MachineDominatorTree *MDT, MachineLoopInfo *MLI)
66 : MDT(MDT), MLI(MLI) {}
68 bool run(MachineFunction &MF);
72 static bool alwaysInstrument(Function &
F) {
73 auto InstrAttr =
F.getFnAttribute(
"function-instrument");
74 return InstrAttr.isStringAttribute() &&
75 InstrAttr.getValueAsString() ==
"xray-always";
78 static bool needMDTAndMLIAnalyses(Function &
F) {
79 auto IgnoreLoopsAttr =
F.getFnAttribute(
"xray-ignore-loops");
80 auto AlwaysInstrument = XRayInstrumentation::alwaysInstrument(
F);
81 return !AlwaysInstrument && !IgnoreLoopsAttr.isValid();
91 void replaceRetWithPatchableRet(MachineFunction &MF,
92 const TargetInstrInfo *
TII,
93 InstrumentationOptions);
103 void prependRetWithPatchableExit(MachineFunction &MF,
104 const TargetInstrInfo *
TII,
105 InstrumentationOptions);
107 MachineDominatorTree *MDT;
108 MachineLoopInfo *MLI;
113void XRayInstrumentation::replaceRetWithPatchableRet(
115 InstrumentationOptions
op) {
118 SmallVector<MachineInstr *, 4> Terminators;
119 for (
auto &
MBB : MF) {
123 (
op.HandleAllReturns ||
T.getOpcode() ==
TII->getReturnOpcode())) {
126 Opc = TargetOpcode::PATCHABLE_RET;
131 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
136 for (
auto &MO :
T.operands())
139 if (
T.shouldUpdateAdditionalCallInfo())
140 MF.eraseAdditionalCallInfo(&
T);
145 for (
auto &
I : Terminators)
146 I->eraseFromParent();
149void XRayInstrumentation::prependRetWithPatchableExit(
150 MachineFunction &MF,
const TargetInstrInfo *
TII,
151 InstrumentationOptions
op) {
156 (
op.HandleAllReturns ||
T.getOpcode() ==
TII->getReturnOpcode())) {
157 Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
160 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
176 if (XRayInstrumentation::needMDTAndMLIAnalyses(MF.
getFunction())) {
181 if (!XRayInstrumentation(MDT, MLI).
run(MF))
189bool XRayInstrumentationLegacy::runOnMachineFunction(
MachineFunction &MF) {
192 if (XRayInstrumentation::needMDTAndMLIAnalyses(MF.
getFunction())) {
194 getAnalysisIfAvailable<MachineDominatorTreeWrapperPass>();
195 MDT = MDTWrapper ? &MDTWrapper->getDomTree() :
nullptr;
196 auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
197 MLI = MLIWrapper ? &MLIWrapper->getLI() :
nullptr;
199 return XRayInstrumentation(MDT, MLI).run(MF);
202bool XRayInstrumentation::run(MachineFunction &MF) {
205 bool AlwaysInstrument = alwaysInstrument(
F);
206 bool NeverInstrument = InstrAttr.isStringAttribute() &&
207 InstrAttr.getValueAsString() ==
"xray-never";
208 if (NeverInstrument && !AlwaysInstrument)
210 auto IgnoreLoopsAttr =
F.getFnAttribute(
"xray-ignore-loops");
212 uint64_t XRayThreshold = 0;
213 if (!AlwaysInstrument) {
214 bool IgnoreLoops = IgnoreLoopsAttr.isValid();
215 XRayThreshold =
F.getFnAttributeAsParsedInteger(
216 "xray-instruction-threshold", std::numeric_limits<uint64_t>::max());
217 if (XRayThreshold == std::numeric_limits<uint64_t>::max())
221 uint64_t MICount = 0;
222 for (
const auto &
MBB : MF)
225 bool TooFewInstrs = MICount < XRayThreshold;
230 MachineDominatorTree ComputedMDT;
231 MachineLoopInfo ComputedMLI;
233 ComputedMLI.
calculate(MF, [&]() ->
const MachineDominatorTree & {
246 if (MLI->
empty() && TooFewInstrs)
248 }
else if (TooFewInstrs) {
257 MF, [&](
const MachineBasicBlock &
MBB) {
return !
MBB.
empty(); });
261 auto *
TII = MF.getSubtarget().getInstrInfo();
262 auto &FirstMBB = *MBI;
263 auto &FirstMI = *FirstMBB.begin();
265 if (!MF.getSubtarget().isXRaySupported()) {
267 const Function &Fn = FirstMBB.getParent()->getFunction();
269 Fn,
"An attempt to perform XRay instrumentation for an"
270 " unsupported target."));
275 if (!
F.hasFnAttribute(
"xray-skip-entry")) {
278 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
279 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
282 if (!
F.hasFnAttribute(
"xray-skip-exit")) {
283 switch (MF.getTarget().getTargetTriple().getArch()) {
284 case Triple::ArchType::arm:
285 case Triple::ArchType::thumb:
286 case Triple::ArchType::aarch64:
287 case Triple::ArchType::hexagon:
288 case Triple::ArchType::loongarch64:
289 case Triple::ArchType::mips:
290 case Triple::ArchType::mipsel:
291 case Triple::ArchType::mips64:
292 case Triple::ArchType::mips64el:
293 case Triple::ArchType::riscv32:
294 case Triple::ArchType::riscv64: {
296 InstrumentationOptions
op;
298 op.HandleTailcall = MF.getTarget().getTargetTriple().isAArch64() ||
299 MF.getTarget().getTargetTriple().isRISCV();
300 op.HandleAllReturns =
true;
301 prependRetWithPatchableExit(MF,
TII,
op);
304 case Triple::ArchType::ppc64le:
305 case Triple::ArchType::systemz: {
307 InstrumentationOptions
op;
308 op.HandleTailcall =
false;
309 op.HandleAllReturns =
true;
310 replaceRetWithPatchableRet(MF,
TII,
op);
316 InstrumentationOptions
op;
317 op.HandleTailcall =
true;
318 op.HandleAllReturns =
false;
319 replaceRetWithPatchableRet(MF,
TII,
op);
327char XRayInstrumentationLegacy::ID = 0;
330 "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.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
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.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isTailCall(const MachineInstr &MI) const override
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
iterator_range< iterator > terminators()
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.
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.
LLVM_ABI void calculate(MachineDominatorTree &MDT)
Calculate the natural loop information.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
TargetInstrInfo - Interface to description of machine instruction set.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
DXILDebugInfoMap run(Module &M)
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.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
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.