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