xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/PseudoProbe.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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>
2506c3fb27SDimitry Andric extractProbeFromDiscriminator(const DILocation *DIL) {
2606c3fb27SDimitry 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;
3906c3fb27SDimitry Andric       Probe.Discriminator = 0;
40e8d8bef9SDimitry Andric       return Probe;
41e8d8bef9SDimitry Andric     }
42e8d8bef9SDimitry Andric   }
43bdd1243dSDimitry Andric   return std::nullopt;
44e8d8bef9SDimitry Andric }
45e8d8bef9SDimitry Andric 
4606c3fb27SDimitry Andric std::optional<PseudoProbe>
4706c3fb27SDimitry Andric extractProbeFromDiscriminator(const Instruction &Inst) {
4806c3fb27SDimitry Andric   assert(isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst) &&
4906c3fb27SDimitry Andric          "Only call instructions should have pseudo probe encodes as their "
5006c3fb27SDimitry Andric          "Dwarf discriminators");
5106c3fb27SDimitry Andric   if (const DebugLoc &DLoc = Inst.getDebugLoc())
5206c3fb27SDimitry Andric     return extractProbeFromDiscriminator(DLoc);
5306c3fb27SDimitry Andric   return std::nullopt;
5406c3fb27SDimitry Andric }
5506c3fb27SDimitry 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;
6406c3fb27SDimitry Andric     Probe.Discriminator = 0;
6506c3fb27SDimitry Andric     if (const DebugLoc &DLoc = Inst.getDebugLoc())
6606c3fb27SDimitry 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);
98*0fca6ea1SDimitry Andric         auto DwarfBaseDiscriminator =
99*0fca6ea1SDimitry Andric             PseudoProbeDwarfDiscriminator::extractDwarfBaseDiscriminator(
100*0fca6ea1SDimitry Andric                 Discriminator);
101d409305fSDimitry Andric         // Round small factors to 0 to avoid over-counting.
102d409305fSDimitry Andric         uint32_t IntFactor =
103d409305fSDimitry Andric             PseudoProbeDwarfDiscriminator::FullDistributionFactor;
104d409305fSDimitry Andric         if (Factor < 1)
105d409305fSDimitry Andric           IntFactor *= Factor;
106d409305fSDimitry Andric         uint32_t V = PseudoProbeDwarfDiscriminator::packProbeData(
107*0fca6ea1SDimitry Andric             Index, Type, Attr, IntFactor, DwarfBaseDiscriminator);
108d409305fSDimitry Andric         DIL = DIL->cloneWithDiscriminator(V);
109d409305fSDimitry Andric         Inst.setDebugLoc(DIL);
110d409305fSDimitry Andric       }
111d409305fSDimitry Andric     }
112d409305fSDimitry Andric   }
113d409305fSDimitry Andric }
114fe6060f1SDimitry Andric 
115e8d8bef9SDimitry Andric } // namespace llvm
116