37 struct InstrumentationOptions {
43 bool HandleAllReturns;
71 InstrumentationOptions);
83 InstrumentationOptions);
88 void 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())
113 Terminators.push_back(&
T);
114 if (
T.shouldUpdateCallSiteInfo())
115 MF.eraseCallSiteInfo(&
T);
120 for (
auto &
I : Terminators)
121 I->eraseFromParent();
124 void 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 ThresholdAttr =
F.getFnAttribute(
"xray-instruction-threshold");
155 auto IgnoreLoopsAttr =
F.getFnAttribute(
"xray-ignore-loops");
156 unsigned int XRayThreshold = 0;
157 if (!AlwaysInstrument) {
158 if (!ThresholdAttr.isStringAttribute())
160 if (ThresholdAttr.getValueAsString().getAsInteger(10, XRayThreshold))
163 bool IgnoreLoops = IgnoreLoopsAttr.isValid();
167 for (
const auto &
MBB : MF)
170 bool TooFewInstrs = MICount < XRayThreshold;
174 auto *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
182 auto *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
185 ComputedMLI.
getBase().analyze(MDT->getBase());
192 if (MLI->empty() && TooFewInstrs)
194 }
else if (TooFewInstrs) {
207 auto *
TII = MF.getSubtarget().getInstrInfo();
208 auto &FirstMBB = *MBI;
209 auto &FirstMI = *FirstMBB.begin();
211 if (!MF.getSubtarget().isXRaySupported()) {
212 FirstMI.emitError(
"An attempt to perform XRay instrumentation for an"
213 " unsupported target.");
217 if (!
F.hasFnAttribute(
"xray-skip-entry")) {
220 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
221 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
224 if (!
F.hasFnAttribute(
"xray-skip-exit")) {
225 switch (MF.getTarget().getTargetTriple().getArch()) {
226 case Triple::ArchType::arm:
227 case Triple::ArchType::thumb:
228 case Triple::ArchType::aarch64:
229 case Triple::ArchType::hexagon:
230 case Triple::ArchType::mips:
231 case Triple::ArchType::mipsel:
232 case Triple::ArchType::mips64:
233 case Triple::ArchType::mips64el: {
235 InstrumentationOptions
op;
236 op.HandleTailcall =
false;
237 op.HandleAllReturns =
true;
238 prependRetWithPatchableExit(MF,
TII,
op);
241 case Triple::ArchType::ppc64le: {
243 InstrumentationOptions
op;
244 op.HandleTailcall =
false;
245 op.HandleAllReturns =
true;
246 replaceRetWithPatchableRet(MF,
TII,
op);
252 InstrumentationOptions
op;
253 op.HandleTailcall =
true;
254 op.HandleAllReturns =
false;
255 replaceRetWithPatchableRet(MF,
TII,
op);
266 "Insert XRay ops",
false,
false)