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