xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/PseudoProbe.cpp (revision d409305fa3838fb39b38c26fc085fb729b8766d5)
1e8d8bef9SDimitry Andric //===- PseudoProbe.cpp - Pseudo Probe Helpers -----------------------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // This file implements the helpers to manipulate pseudo probe IR intrinsic
10e8d8bef9SDimitry Andric // calls.
11e8d8bef9SDimitry Andric //
12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
13e8d8bef9SDimitry Andric 
14e8d8bef9SDimitry Andric #include "llvm/IR/PseudoProbe.h"
15e8d8bef9SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
16e8d8bef9SDimitry Andric #include "llvm/IR/IRBuilder.h"
17e8d8bef9SDimitry Andric #include "llvm/IR/Instruction.h"
18e8d8bef9SDimitry Andric 
19e8d8bef9SDimitry Andric using namespace llvm;
20e8d8bef9SDimitry Andric 
21e8d8bef9SDimitry Andric namespace llvm {
22e8d8bef9SDimitry Andric 
23e8d8bef9SDimitry Andric Optional<PseudoProbe> extractProbeFromDiscriminator(const Instruction &Inst) {
24e8d8bef9SDimitry Andric   assert(isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst) &&
25e8d8bef9SDimitry Andric          "Only call instructions should have pseudo probe encodes as their "
26e8d8bef9SDimitry Andric          "Dwarf discriminators");
27e8d8bef9SDimitry Andric   if (const DebugLoc &DLoc = Inst.getDebugLoc()) {
28e8d8bef9SDimitry Andric     const DILocation *DIL = DLoc;
29e8d8bef9SDimitry Andric     auto Discriminator = DIL->getDiscriminator();
30e8d8bef9SDimitry Andric     if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
31e8d8bef9SDimitry Andric       PseudoProbe Probe;
32e8d8bef9SDimitry Andric       Probe.Id =
33e8d8bef9SDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
34e8d8bef9SDimitry Andric       Probe.Type =
35e8d8bef9SDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeType(Discriminator);
36e8d8bef9SDimitry Andric       Probe.Attr =
37e8d8bef9SDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeAttributes(Discriminator);
38*d409305fSDimitry Andric       Probe.Factor =
39*d409305fSDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeFactor(Discriminator) /
40*d409305fSDimitry Andric           (float)PseudoProbeDwarfDiscriminator::FullDistributionFactor;
41e8d8bef9SDimitry Andric       return Probe;
42e8d8bef9SDimitry Andric     }
43e8d8bef9SDimitry Andric   }
44e8d8bef9SDimitry Andric   return None;
45e8d8bef9SDimitry Andric }
46e8d8bef9SDimitry Andric 
47e8d8bef9SDimitry Andric Optional<PseudoProbe> extractProbe(const Instruction &Inst) {
48e8d8bef9SDimitry Andric   if (const auto *II = dyn_cast<PseudoProbeInst>(&Inst)) {
49e8d8bef9SDimitry Andric     PseudoProbe Probe;
50e8d8bef9SDimitry Andric     Probe.Id = II->getIndex()->getZExtValue();
51e8d8bef9SDimitry Andric     Probe.Type = (uint32_t)PseudoProbeType::Block;
52e8d8bef9SDimitry Andric     Probe.Attr = II->getAttributes()->getZExtValue();
53*d409305fSDimitry Andric     Probe.Factor = II->getFactor()->getZExtValue() /
54*d409305fSDimitry Andric                    (float)PseudoProbeFullDistributionFactor;
55e8d8bef9SDimitry Andric     return Probe;
56e8d8bef9SDimitry Andric   }
57e8d8bef9SDimitry Andric 
58e8d8bef9SDimitry Andric   if (isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst))
59e8d8bef9SDimitry Andric     return extractProbeFromDiscriminator(Inst);
60e8d8bef9SDimitry Andric 
61e8d8bef9SDimitry Andric   return None;
62e8d8bef9SDimitry Andric }
63*d409305fSDimitry Andric 
64*d409305fSDimitry Andric void setProbeDistributionFactor(Instruction &Inst, float Factor) {
65*d409305fSDimitry Andric   assert(Factor >= 0 && Factor <= 1 &&
66*d409305fSDimitry Andric          "Distribution factor must be in [0, 1.0]");
67*d409305fSDimitry Andric   if (auto *II = dyn_cast<PseudoProbeInst>(&Inst)) {
68*d409305fSDimitry Andric     IRBuilder<> Builder(&Inst);
69*d409305fSDimitry Andric     uint64_t IntFactor = PseudoProbeFullDistributionFactor;
70*d409305fSDimitry Andric     if (Factor < 1)
71*d409305fSDimitry Andric       IntFactor *= Factor;
72*d409305fSDimitry Andric     auto OrigFactor = II->getFactor()->getZExtValue();
73*d409305fSDimitry Andric     if (IntFactor != OrigFactor)
74*d409305fSDimitry Andric       II->replaceUsesOfWith(II->getFactor(), Builder.getInt64(IntFactor));
75*d409305fSDimitry Andric   } else if (isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst)) {
76*d409305fSDimitry Andric     if (const DebugLoc &DLoc = Inst.getDebugLoc()) {
77*d409305fSDimitry Andric       const DILocation *DIL = DLoc;
78*d409305fSDimitry Andric       auto Discriminator = DIL->getDiscriminator();
79*d409305fSDimitry Andric       if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
80*d409305fSDimitry Andric         auto Index =
81*d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
82*d409305fSDimitry Andric         auto Type =
83*d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::extractProbeType(Discriminator);
84*d409305fSDimitry Andric         auto Attr = PseudoProbeDwarfDiscriminator::extractProbeAttributes(
85*d409305fSDimitry Andric             Discriminator);
86*d409305fSDimitry Andric         // Round small factors to 0 to avoid over-counting.
87*d409305fSDimitry Andric         uint32_t IntFactor =
88*d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::FullDistributionFactor;
89*d409305fSDimitry Andric         if (Factor < 1)
90*d409305fSDimitry Andric           IntFactor *= Factor;
91*d409305fSDimitry Andric         uint32_t V = PseudoProbeDwarfDiscriminator::packProbeData(
92*d409305fSDimitry Andric             Index, Type, Attr, IntFactor);
93*d409305fSDimitry Andric         DIL = DIL->cloneWithDiscriminator(V);
94*d409305fSDimitry Andric         Inst.setDebugLoc(DIL);
95*d409305fSDimitry Andric       }
96*d409305fSDimitry Andric     }
97*d409305fSDimitry Andric   }
98*d409305fSDimitry Andric }
99e8d8bef9SDimitry Andric } // namespace llvm
100