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