xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/PseudoProbe.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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"
181fd87a68SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
19e8d8bef9SDimitry Andric 
20e8d8bef9SDimitry Andric using namespace llvm;
21e8d8bef9SDimitry Andric 
22e8d8bef9SDimitry Andric namespace llvm {
23e8d8bef9SDimitry Andric 
24bdd1243dSDimitry Andric std::optional<PseudoProbe>
25*06c3fb27SDimitry Andric extractProbeFromDiscriminator(const DILocation *DIL) {
26*06c3fb27SDimitry Andric   if (DIL) {
27e8d8bef9SDimitry Andric     auto Discriminator = DIL->getDiscriminator();
28e8d8bef9SDimitry Andric     if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
29e8d8bef9SDimitry Andric       PseudoProbe Probe;
30e8d8bef9SDimitry Andric       Probe.Id =
31e8d8bef9SDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
32e8d8bef9SDimitry Andric       Probe.Type =
33e8d8bef9SDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeType(Discriminator);
34e8d8bef9SDimitry Andric       Probe.Attr =
35e8d8bef9SDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeAttributes(Discriminator);
36d409305fSDimitry Andric       Probe.Factor =
37d409305fSDimitry Andric           PseudoProbeDwarfDiscriminator::extractProbeFactor(Discriminator) /
38d409305fSDimitry Andric           (float)PseudoProbeDwarfDiscriminator::FullDistributionFactor;
39*06c3fb27SDimitry Andric       Probe.Discriminator = 0;
40e8d8bef9SDimitry Andric       return Probe;
41e8d8bef9SDimitry Andric     }
42e8d8bef9SDimitry Andric   }
43bdd1243dSDimitry Andric   return std::nullopt;
44e8d8bef9SDimitry Andric }
45e8d8bef9SDimitry Andric 
46*06c3fb27SDimitry Andric std::optional<PseudoProbe>
47*06c3fb27SDimitry Andric extractProbeFromDiscriminator(const Instruction &Inst) {
48*06c3fb27SDimitry Andric   assert(isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst) &&
49*06c3fb27SDimitry Andric          "Only call instructions should have pseudo probe encodes as their "
50*06c3fb27SDimitry Andric          "Dwarf discriminators");
51*06c3fb27SDimitry Andric   if (const DebugLoc &DLoc = Inst.getDebugLoc())
52*06c3fb27SDimitry Andric     return extractProbeFromDiscriminator(DLoc);
53*06c3fb27SDimitry Andric   return std::nullopt;
54*06c3fb27SDimitry Andric }
55*06c3fb27SDimitry Andric 
56bdd1243dSDimitry Andric std::optional<PseudoProbe> extractProbe(const Instruction &Inst) {
57e8d8bef9SDimitry Andric   if (const auto *II = dyn_cast<PseudoProbeInst>(&Inst)) {
58e8d8bef9SDimitry Andric     PseudoProbe Probe;
59e8d8bef9SDimitry Andric     Probe.Id = II->getIndex()->getZExtValue();
60e8d8bef9SDimitry Andric     Probe.Type = (uint32_t)PseudoProbeType::Block;
61e8d8bef9SDimitry Andric     Probe.Attr = II->getAttributes()->getZExtValue();
62d409305fSDimitry Andric     Probe.Factor = II->getFactor()->getZExtValue() /
63d409305fSDimitry Andric                    (float)PseudoProbeFullDistributionFactor;
64*06c3fb27SDimitry Andric     Probe.Discriminator = 0;
65*06c3fb27SDimitry Andric     if (const DebugLoc &DLoc = Inst.getDebugLoc())
66*06c3fb27SDimitry Andric       Probe.Discriminator = DLoc->getDiscriminator();
67e8d8bef9SDimitry Andric     return Probe;
68e8d8bef9SDimitry Andric   }
69e8d8bef9SDimitry Andric 
70e8d8bef9SDimitry Andric   if (isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst))
71e8d8bef9SDimitry Andric     return extractProbeFromDiscriminator(Inst);
72e8d8bef9SDimitry Andric 
73bdd1243dSDimitry Andric   return std::nullopt;
74e8d8bef9SDimitry Andric }
75d409305fSDimitry Andric 
76d409305fSDimitry Andric void setProbeDistributionFactor(Instruction &Inst, float Factor) {
77d409305fSDimitry Andric   assert(Factor >= 0 && Factor <= 1 &&
78d409305fSDimitry Andric          "Distribution factor must be in [0, 1.0]");
79d409305fSDimitry Andric   if (auto *II = dyn_cast<PseudoProbeInst>(&Inst)) {
80d409305fSDimitry Andric     IRBuilder<> Builder(&Inst);
81d409305fSDimitry Andric     uint64_t IntFactor = PseudoProbeFullDistributionFactor;
82d409305fSDimitry Andric     if (Factor < 1)
83d409305fSDimitry Andric       IntFactor *= Factor;
84d409305fSDimitry Andric     auto OrigFactor = II->getFactor()->getZExtValue();
85d409305fSDimitry Andric     if (IntFactor != OrigFactor)
86d409305fSDimitry Andric       II->replaceUsesOfWith(II->getFactor(), Builder.getInt64(IntFactor));
87d409305fSDimitry Andric   } else if (isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst)) {
88d409305fSDimitry Andric     if (const DebugLoc &DLoc = Inst.getDebugLoc()) {
89d409305fSDimitry Andric       const DILocation *DIL = DLoc;
90d409305fSDimitry Andric       auto Discriminator = DIL->getDiscriminator();
91d409305fSDimitry Andric       if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
92d409305fSDimitry Andric         auto Index =
93d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
94d409305fSDimitry Andric         auto Type =
95d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::extractProbeType(Discriminator);
96d409305fSDimitry Andric         auto Attr = PseudoProbeDwarfDiscriminator::extractProbeAttributes(
97d409305fSDimitry Andric             Discriminator);
98d409305fSDimitry Andric         // Round small factors to 0 to avoid over-counting.
99d409305fSDimitry Andric         uint32_t IntFactor =
100d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::FullDistributionFactor;
101d409305fSDimitry Andric         if (Factor < 1)
102d409305fSDimitry Andric           IntFactor *= Factor;
103d409305fSDimitry Andric         uint32_t V = PseudoProbeDwarfDiscriminator::packProbeData(
104d409305fSDimitry Andric             Index, Type, Attr, IntFactor);
105d409305fSDimitry Andric         DIL = DIL->cloneWithDiscriminator(V);
106d409305fSDimitry Andric         Inst.setDebugLoc(DIL);
107d409305fSDimitry Andric       }
108d409305fSDimitry Andric     }
109d409305fSDimitry Andric   }
110d409305fSDimitry Andric }
111fe6060f1SDimitry Andric 
112e8d8bef9SDimitry Andric } // namespace llvm
113