aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/BlockFrequency.cpp
blob: 84a993e3e5b6fd6a54dad76dc982b2c7ced36cf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//====--------------- lib/Support/BlockFrequency.cpp -----------*- C++ -*-====//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Block Frequency class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>

using namespace llvm;

namespace {

/// mult96bit - Multiply FREQ by N and store result in W array.
void mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]) {
  uint64_t u0 = freq & UINT32_MAX;
  uint64_t u1 = freq >> 32;

  // Represent 96-bit value as w[2]:w[1]:w[0];
  uint32_t w[3] = { 0, 0, 0 };

  uint64_t t = u0 * N;
  uint64_t k = t >> 32;
  w[0] = t;
  t = u1 * N + k;
  w[1] = t;
  w[2] = t >> 32;

  // W[1] - higher bits.
  // W[0] - lower bits.
  W[0] = w[0] + ((uint64_t) w[1] << 32);
  W[1] = w[2];
}


/// div96bit - Divide 96-bit value stored in W array by D. Return 64-bit frequency.
uint64_t div96bit(uint64_t W[2], uint32_t D) {
  uint64_t y = W[0];
  uint64_t x = W[1];
  int i;

  for (i = 1; i <= 64 && x; ++i) {
    uint32_t t = (int)x >> 31;
    x = (x << 1) | (y >> 63);
    y = y << 1;
    if ((x | t) >= D) {
      x -= D;
      ++y;
    }
  }

  return y << (64 - i + 1);
}

}


BlockFrequency &BlockFrequency::operator*=(const BranchProbability &Prob) {
  uint32_t n = Prob.getNumerator();
  uint32_t d = Prob.getDenominator();

  assert(n <= d && "Probability must be less or equal to 1.");

  // Calculate Frequency * n.
  uint64_t mulLo = (Frequency & UINT32_MAX) * n;
  uint64_t mulHi = (Frequency >> 32) * n;
  uint64_t mulRes = (mulHi << 32) + mulLo;

  // If there was overflow use 96-bit operations.
  if (mulHi > UINT32_MAX || mulRes < mulLo) {
    // 96-bit value represented as W[1]:W[0].
    uint64_t W[2];

    // Probability is less or equal to 1 which means that results must fit
    // 64-bit.
    mult96bit(Frequency, n, W);
    Frequency = div96bit(W, d);
    return *this;
  }

  Frequency = mulRes / d;
  return *this;
}

const BlockFrequency
BlockFrequency::operator*(const BranchProbability &Prob) const {
  BlockFrequency Freq(Frequency);
  Freq *= Prob;
  return Freq;
}

BlockFrequency &BlockFrequency::operator+=(const BlockFrequency &Freq) {
  uint64_t Before = Freq.Frequency;
  Frequency += Freq.Frequency;

  // If overflow, set frequency to the maximum value.
  if (Frequency < Before)
    Frequency = UINT64_MAX;

  return *this;
}

const BlockFrequency
BlockFrequency::operator+(const BlockFrequency &Prob) const {
  BlockFrequency Freq(Frequency);
  Freq += Prob;
  return Freq;
}

void BlockFrequency::print(raw_ostream &OS) const {
  OS << Frequency;
}

namespace llvm {

raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq) {
  Freq.print(OS);
  return OS;
}

}