13d4e64b0SAndrew Trick //===-------------- lib/Support/BranchProbability.cpp -----------*- C++ -*-===//
23d4e64b0SAndrew Trick //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63d4e64b0SAndrew Trick //
73d4e64b0SAndrew Trick //===----------------------------------------------------------------------===//
83d4e64b0SAndrew Trick //
93d4e64b0SAndrew Trick // This file implements Branch Probability class.
103d4e64b0SAndrew Trick //
113d4e64b0SAndrew Trick //===----------------------------------------------------------------------===//
123d4e64b0SAndrew Trick 
133d4e64b0SAndrew Trick #include "llvm/Support/BranchProbability.h"
14432a3883SNico Weber #include "llvm/Config/llvm-config.h"
153d4e64b0SAndrew Trick #include "llvm/Support/Debug.h"
16cc0ed6baSBenjamin Kramer #include "llvm/Support/Format.h"
173d4e64b0SAndrew Trick #include "llvm/Support/raw_ostream.h"
1815ea0163SCong Hou #include <cassert>
19*e8423dbfSSimon Pilgrim #include <cmath>
203d4e64b0SAndrew Trick 
213d4e64b0SAndrew Trick using namespace llvm;
223d4e64b0SAndrew Trick 
23b198f1f8SBenjamin Kramer constexpr uint32_t BranchProbability::D;
242a63631aSBenjamin Kramer 
print(raw_ostream & OS) const25bdc1e2abSDuncan P. N. Exon Smith raw_ostream &BranchProbability::print(raw_ostream &OS) const {
26d97c100dSCong Hou   if (isUnknown())
27d97c100dSCong Hou     return OS << "?%";
28d97c100dSCong Hou 
292a63631aSBenjamin Kramer   // Get a percentage rounded to two decimal digits. This avoids
302a63631aSBenjamin Kramer   // implementation-defined rounding inside printf.
312a63631aSBenjamin Kramer   double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0;
32d97c100dSCong Hou   return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D,
33d97c100dSCong Hou                       Percent);
343d4e64b0SAndrew Trick }
353d4e64b0SAndrew Trick 
36615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const37eb2a2546SYaron Keren LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }
388c209aa8SMatthias Braun #endif
393d4e64b0SAndrew Trick 
BranchProbability(uint32_t Numerator,uint32_t Denominator)4015ea0163SCong Hou BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {
4115ea0163SCong Hou   assert(Denominator > 0 && "Denominator cannot be 0!");
4215ea0163SCong Hou   assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
4315ea0163SCong Hou   if (Denominator == D)
4415ea0163SCong Hou     N = Numerator;
4515ea0163SCong Hou   else {
4615ea0163SCong Hou     uint64_t Prob64 =
4715ea0163SCong Hou         (Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator;
4815ea0163SCong Hou     N = static_cast<uint32_t>(Prob64);
4915ea0163SCong Hou   }
5015ea0163SCong Hou }
5115ea0163SCong Hou 
52d97c100dSCong Hou BranchProbability
getBranchProbability(uint64_t Numerator,uint64_t Denominator)53d97c100dSCong Hou BranchProbability::getBranchProbability(uint64_t Numerator,
54d97c100dSCong Hou                                         uint64_t Denominator) {
55d97c100dSCong Hou   assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
56d97c100dSCong Hou   // Scale down Denominator to fit in a 32-bit integer.
57d97c100dSCong Hou   int Scale = 0;
58d97c100dSCong Hou   while (Denominator > UINT32_MAX) {
59d97c100dSCong Hou     Denominator >>= 1;
60d97c100dSCong Hou     Scale++;
61d97c100dSCong Hou   }
62d97c100dSCong Hou   return BranchProbability(Numerator >> Scale, Denominator);
63d97c100dSCong Hou }
64d97c100dSCong Hou 
6515ea0163SCong Hou // If ConstD is not zero, then replace D by ConstD so that division and modulo
6615ea0163SCong Hou // operations by D can be optimized, in case this function is not inlined by the
6715ea0163SCong Hou // compiler.
6815ea0163SCong Hou template <uint32_t ConstD>
scale(uint64_t Num,uint32_t N,uint32_t D)692a63631aSBenjamin Kramer static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {
7015ea0163SCong Hou   if (ConstD > 0)
7115ea0163SCong Hou     D = ConstD;
7215ea0163SCong Hou 
73415e7656SDuncan P. N. Exon Smith   assert(D && "divide by 0");
74415e7656SDuncan P. N. Exon Smith 
75415e7656SDuncan P. N. Exon Smith   // Fast path for multiplying by 1.0.
76415e7656SDuncan P. N. Exon Smith   if (!Num || D == N)
77415e7656SDuncan P. N. Exon Smith     return Num;
78415e7656SDuncan P. N. Exon Smith 
79415e7656SDuncan P. N. Exon Smith   // Split Num into upper and lower parts to multiply, then recombine.
80415e7656SDuncan P. N. Exon Smith   uint64_t ProductHigh = (Num >> 32) * N;
81415e7656SDuncan P. N. Exon Smith   uint64_t ProductLow = (Num & UINT32_MAX) * N;
82415e7656SDuncan P. N. Exon Smith 
83415e7656SDuncan P. N. Exon Smith   // Split into 32-bit digits.
84415e7656SDuncan P. N. Exon Smith   uint32_t Upper32 = ProductHigh >> 32;
85415e7656SDuncan P. N. Exon Smith   uint32_t Lower32 = ProductLow & UINT32_MAX;
86415e7656SDuncan P. N. Exon Smith   uint32_t Mid32Partial = ProductHigh & UINT32_MAX;
87415e7656SDuncan P. N. Exon Smith   uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);
88415e7656SDuncan P. N. Exon Smith 
89415e7656SDuncan P. N. Exon Smith   // Carry.
90415e7656SDuncan P. N. Exon Smith   Upper32 += Mid32 < Mid32Partial;
91415e7656SDuncan P. N. Exon Smith 
92415e7656SDuncan P. N. Exon Smith   uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;
93415e7656SDuncan P. N. Exon Smith   uint64_t UpperQ = Rem / D;
94415e7656SDuncan P. N. Exon Smith 
95415e7656SDuncan P. N. Exon Smith   // Check for overflow.
96415e7656SDuncan P. N. Exon Smith   if (UpperQ > UINT32_MAX)
97415e7656SDuncan P. N. Exon Smith     return UINT64_MAX;
98415e7656SDuncan P. N. Exon Smith 
99415e7656SDuncan P. N. Exon Smith   Rem = ((Rem % D) << 32) | Lower32;
100415e7656SDuncan P. N. Exon Smith   uint64_t LowerQ = Rem / D;
101415e7656SDuncan P. N. Exon Smith   uint64_t Q = (UpperQ << 32) + LowerQ;
102415e7656SDuncan P. N. Exon Smith 
103415e7656SDuncan P. N. Exon Smith   // Check for overflow.
104415e7656SDuncan P. N. Exon Smith   return Q < LowerQ ? UINT64_MAX : Q;
105415e7656SDuncan P. N. Exon Smith }
106415e7656SDuncan P. N. Exon Smith 
scale(uint64_t Num) const107415e7656SDuncan P. N. Exon Smith uint64_t BranchProbability::scale(uint64_t Num) const {
10815ea0163SCong Hou   return ::scale<D>(Num, N, D);
109415e7656SDuncan P. N. Exon Smith }
110415e7656SDuncan P. N. Exon Smith 
scaleByInverse(uint64_t Num) const111415e7656SDuncan P. N. Exon Smith uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {
11215ea0163SCong Hou   return ::scale<0>(Num, D, N);
113415e7656SDuncan P. N. Exon Smith }
114