1bd5abe19SDimitry Andric //===-------------- lib/Support/BranchProbability.cpp -----------*- C++ -*-===//
2bd5abe19SDimitry Andric //
3bd5abe19SDimitry Andric //                     The LLVM Compiler Infrastructure
4bd5abe19SDimitry Andric //
5bd5abe19SDimitry Andric // This file is distributed under the University of Illinois Open Source
6bd5abe19SDimitry Andric // License. See LICENSE.TXT for details.
7bd5abe19SDimitry Andric //
8bd5abe19SDimitry Andric //===----------------------------------------------------------------------===//
9bd5abe19SDimitry Andric //
10bd5abe19SDimitry Andric // This file implements Branch Probability class.
11bd5abe19SDimitry Andric //
12bd5abe19SDimitry Andric //===----------------------------------------------------------------------===//
13bd5abe19SDimitry Andric 
14bd5abe19SDimitry Andric #include "llvm/Support/BranchProbability.h"
15*4ba319b5SDimitry Andric #include "llvm/Config/llvm-config.h"
16bd5abe19SDimitry Andric #include "llvm/Support/Debug.h"
17dff0c46cSDimitry Andric #include "llvm/Support/Format.h"
18bd5abe19SDimitry Andric #include "llvm/Support/raw_ostream.h"
197d523365SDimitry Andric #include <cassert>
20bd5abe19SDimitry Andric 
21bd5abe19SDimitry Andric using namespace llvm;
22bd5abe19SDimitry Andric 
237d523365SDimitry Andric const uint32_t BranchProbability::D;
247d523365SDimitry Andric 
print(raw_ostream & OS) const2591bc56edSDimitry Andric raw_ostream &BranchProbability::print(raw_ostream &OS) const {
267d523365SDimitry Andric   if (isUnknown())
277d523365SDimitry Andric     return OS << "?%";
287d523365SDimitry Andric 
297d523365SDimitry Andric   // Get a percentage rounded to two decimal digits. This avoids
307d523365SDimitry Andric   // implementation-defined rounding inside printf.
317d523365SDimitry Andric   double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0;
327d523365SDimitry Andric   return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D,
337d523365SDimitry Andric                       Percent);
34bd5abe19SDimitry Andric }
35bd5abe19SDimitry Andric 
367a7e6055SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const373ca95b02SDimitry Andric LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }
387a7e6055SDimitry Andric #endif
3991bc56edSDimitry Andric 
BranchProbability(uint32_t Numerator,uint32_t Denominator)407d523365SDimitry Andric BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {
417d523365SDimitry Andric   assert(Denominator > 0 && "Denominator cannot be 0!");
427d523365SDimitry Andric   assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
437d523365SDimitry Andric   if (Denominator == D)
447d523365SDimitry Andric     N = Numerator;
457d523365SDimitry Andric   else {
467d523365SDimitry Andric     uint64_t Prob64 =
477d523365SDimitry Andric         (Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator;
487d523365SDimitry Andric     N = static_cast<uint32_t>(Prob64);
497d523365SDimitry Andric   }
507d523365SDimitry Andric }
517d523365SDimitry Andric 
527d523365SDimitry Andric BranchProbability
getBranchProbability(uint64_t Numerator,uint64_t Denominator)537d523365SDimitry Andric BranchProbability::getBranchProbability(uint64_t Numerator,
547d523365SDimitry Andric                                         uint64_t Denominator) {
557d523365SDimitry Andric   assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
567d523365SDimitry Andric   // Scale down Denominator to fit in a 32-bit integer.
577d523365SDimitry Andric   int Scale = 0;
587d523365SDimitry Andric   while (Denominator > UINT32_MAX) {
597d523365SDimitry Andric     Denominator >>= 1;
607d523365SDimitry Andric     Scale++;
617d523365SDimitry Andric   }
627d523365SDimitry Andric   return BranchProbability(Numerator >> Scale, Denominator);
637d523365SDimitry Andric }
647d523365SDimitry Andric 
657d523365SDimitry Andric // If ConstD is not zero, then replace D by ConstD so that division and modulo
667d523365SDimitry Andric // operations by D can be optimized, in case this function is not inlined by the
677d523365SDimitry Andric // compiler.
687d523365SDimitry Andric template <uint32_t ConstD>
scale(uint64_t Num,uint32_t N,uint32_t D)6991bc56edSDimitry Andric static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {
707d523365SDimitry Andric   if (ConstD > 0)
717d523365SDimitry Andric     D = ConstD;
727d523365SDimitry Andric 
7391bc56edSDimitry Andric   assert(D && "divide by 0");
7491bc56edSDimitry Andric 
7591bc56edSDimitry Andric   // Fast path for multiplying by 1.0.
7691bc56edSDimitry Andric   if (!Num || D == N)
7791bc56edSDimitry Andric     return Num;
7891bc56edSDimitry Andric 
7991bc56edSDimitry Andric   // Split Num into upper and lower parts to multiply, then recombine.
8091bc56edSDimitry Andric   uint64_t ProductHigh = (Num >> 32) * N;
8191bc56edSDimitry Andric   uint64_t ProductLow = (Num & UINT32_MAX) * N;
8291bc56edSDimitry Andric 
8391bc56edSDimitry Andric   // Split into 32-bit digits.
8491bc56edSDimitry Andric   uint32_t Upper32 = ProductHigh >> 32;
8591bc56edSDimitry Andric   uint32_t Lower32 = ProductLow & UINT32_MAX;
8691bc56edSDimitry Andric   uint32_t Mid32Partial = ProductHigh & UINT32_MAX;
8791bc56edSDimitry Andric   uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);
8891bc56edSDimitry Andric 
8991bc56edSDimitry Andric   // Carry.
9091bc56edSDimitry Andric   Upper32 += Mid32 < Mid32Partial;
9191bc56edSDimitry Andric 
9291bc56edSDimitry Andric   // Check for overflow.
9391bc56edSDimitry Andric   if (Upper32 >= D)
9491bc56edSDimitry Andric     return UINT64_MAX;
9591bc56edSDimitry Andric 
9691bc56edSDimitry Andric   uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;
9791bc56edSDimitry Andric   uint64_t UpperQ = Rem / D;
9891bc56edSDimitry Andric 
9991bc56edSDimitry Andric   // Check for overflow.
10091bc56edSDimitry Andric   if (UpperQ > UINT32_MAX)
10191bc56edSDimitry Andric     return UINT64_MAX;
10291bc56edSDimitry Andric 
10391bc56edSDimitry Andric   Rem = ((Rem % D) << 32) | Lower32;
10491bc56edSDimitry Andric   uint64_t LowerQ = Rem / D;
10591bc56edSDimitry Andric   uint64_t Q = (UpperQ << 32) + LowerQ;
10691bc56edSDimitry Andric 
10791bc56edSDimitry Andric   // Check for overflow.
10891bc56edSDimitry Andric   return Q < LowerQ ? UINT64_MAX : Q;
109bd5abe19SDimitry Andric }
110bd5abe19SDimitry Andric 
scale(uint64_t Num) const11191bc56edSDimitry Andric uint64_t BranchProbability::scale(uint64_t Num) const {
1127d523365SDimitry Andric   return ::scale<D>(Num, N, D);
113bd5abe19SDimitry Andric }
114bd5abe19SDimitry Andric 
scaleByInverse(uint64_t Num) const11591bc56edSDimitry Andric uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {
1167d523365SDimitry Andric   return ::scale<0>(Num, D, N);
117bd5abe19SDimitry Andric }
118