xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Support/BlockFrequency.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-------- BlockFrequency.h - Block Frequency Wrapper --------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements Block Frequency class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_SUPPORT_BLOCKFREQUENCY_H
14 #define LLVM_SUPPORT_BLOCKFREQUENCY_H
15 
16 #include <cassert>
17 #include <cstdint>
18 #include <optional>
19 
20 namespace llvm {
21 
22 class raw_ostream;
23 class BranchProbability;
24 
25 // This class represents Block Frequency as a 64-bit value.
26 class BlockFrequency {
27   uint64_t Frequency;
28 
29 public:
BlockFrequency()30   BlockFrequency() : Frequency(0) {}
BlockFrequency(uint64_t Freq)31   explicit BlockFrequency(uint64_t Freq) : Frequency(Freq) {}
32 
33   /// Returns the maximum possible frequency, the saturation value.
max()34   static BlockFrequency max() { return BlockFrequency(UINT64_MAX); }
35 
36   /// Returns the frequency as a fixpoint number scaled by the entry
37   /// frequency.
getFrequency()38   uint64_t getFrequency() const { return Frequency; }
39 
40   /// Multiplies with a branch probability. The computation will never
41   /// overflow.
42   BlockFrequency &operator*=(BranchProbability Prob);
43   BlockFrequency operator*(BranchProbability Prob) const;
44 
45   /// Divide by a non-zero branch probability using saturating
46   /// arithmetic.
47   BlockFrequency &operator/=(BranchProbability Prob);
48   BlockFrequency operator/(BranchProbability Prob) const;
49 
50   /// Adds another block frequency using saturating arithmetic.
51   BlockFrequency &operator+=(BlockFrequency Freq) {
52     uint64_t Before = Freq.Frequency;
53     Frequency += Freq.Frequency;
54 
55     // If overflow, set frequency to the maximum value.
56     if (Frequency < Before)
57       Frequency = UINT64_MAX;
58 
59     return *this;
60   }
61   BlockFrequency operator+(BlockFrequency Freq) const {
62     BlockFrequency NewFreq(Frequency);
63     NewFreq += Freq;
64     return NewFreq;
65   }
66 
67   /// Subtracts another block frequency using saturating arithmetic.
68   BlockFrequency &operator-=(BlockFrequency Freq) {
69     // If underflow, set frequency to 0.
70     if (Frequency <= Freq.Frequency)
71       Frequency = 0;
72     else
73       Frequency -= Freq.Frequency;
74     return *this;
75   }
76   BlockFrequency operator-(BlockFrequency Freq) const {
77     BlockFrequency NewFreq(Frequency);
78     NewFreq -= Freq;
79     return NewFreq;
80   }
81 
82   /// Multiplies frequency with `Factor`. Returns `nullopt` in case of overflow.
83   std::optional<BlockFrequency> mul(uint64_t Factor) const;
84 
85   /// Shift block frequency to the right by count digits saturating to 1.
86   BlockFrequency &operator>>=(const unsigned count) {
87     // Frequency can never be 0 by design.
88     assert(Frequency != 0);
89 
90     // Shift right by count.
91     Frequency >>= count;
92 
93     // Saturate to 1 if we are 0.
94     Frequency |= Frequency == 0;
95     return *this;
96   }
97 
98   bool operator<(BlockFrequency RHS) const {
99     return Frequency < RHS.Frequency;
100   }
101 
102   bool operator<=(BlockFrequency RHS) const {
103     return Frequency <= RHS.Frequency;
104   }
105 
106   bool operator>(BlockFrequency RHS) const {
107     return Frequency > RHS.Frequency;
108   }
109 
110   bool operator>=(BlockFrequency RHS) const {
111     return Frequency >= RHS.Frequency;
112   }
113 
114   bool operator==(BlockFrequency RHS) const {
115     return Frequency == RHS.Frequency;
116   }
117 
118   bool operator!=(BlockFrequency RHS) const {
119     return Frequency != RHS.Frequency;
120   }
121 };
122 
123 void printRelativeBlockFreq(raw_ostream &OS, BlockFrequency EntryFreq,
124                             BlockFrequency Freq);
125 
126 } // namespace llvm
127 
128 #endif
129