llvm.org GIT mirror llvm / 048f520
Support: Add BranchProbability::scale() and ::scaleByInverse() Add API to `BranchProbability` for scaling big integers. Next job is to rip the logic out of `BlockMass` and `BlockFrequency`. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207544 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 6 years ago
3 changed file(s) with 139 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
4949
5050 void dump() const;
5151
52 /// \brief Scale a large integer.
53 ///
54 /// Scales \c Num. Guarantees full precision. Returns the floor of the
55 /// result.
56 ///
57 /// \return \c Num times \c this.
58 ///
59 /// \note This code should be shared with (or replaced by) the implementation
60 /// of \a BlockFrequency::scale(), which seems to be calculating something
61 /// similar.
62 uint64_t scale(uint64_t Num) const;
63
64 /// \brief Scale a large integer by the inverse.
65 ///
66 /// Scales \c Num by the inverse of \c this. Guarantees full precision.
67 /// Returns the floor of the result.
68 ///
69 /// \return \c Num divided by \c this.
70 ///
71 /// \note This code should be shared with (or replaced by) the implementation
72 /// of \a BlockFrequency::scale(), which seems to be calculating something
73 /// similar.
74 uint64_t scaleByInverse(uint64_t Num) const;
75
5276 bool operator==(BranchProbability RHS) const {
5377 return (uint64_t)N * RHS.D == (uint64_t)D * RHS.N;
5478 }
2525 dbgs() << *this << '\n';
2626 }
2727
28 static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {
29 assert(D && "divide by 0");
30
31 // Fast path for multiplying by 1.0.
32 if (!Num || D == N)
33 return Num;
34
35 // Split Num into upper and lower parts to multiply, then recombine.
36 uint64_t ProductHigh = (Num >> 32) * N;
37 uint64_t ProductLow = (Num & UINT32_MAX) * N;
38
39 // Split into 32-bit digits.
40 uint32_t Upper32 = ProductHigh >> 32;
41 uint32_t Lower32 = ProductLow & UINT32_MAX;
42 uint32_t Mid32Partial = ProductHigh & UINT32_MAX;
43 uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);
44
45 // Carry.
46 Upper32 += Mid32 < Mid32Partial;
47
48 // Check for overflow.
49 if (Upper32 >= D)
50 return UINT64_MAX;
51
52 uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;
53 uint64_t UpperQ = Rem / D;
54
55 // Check for overflow.
56 if (UpperQ > UINT32_MAX)
57 return UINT64_MAX;
58
59 Rem = ((Rem % D) << 32) | Lower32;
60 uint64_t LowerQ = Rem / D;
61 uint64_t Q = (UpperQ << 32) + LowerQ;
62
63 // Check for overflow.
64 return Q < LowerQ ? UINT64_MAX : Q;
65 }
66
67 uint64_t BranchProbability::scale(uint64_t Num) const {
68 return ::scale(Num, N, D);
69 }
70
71 uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {
72 return ::scale(Num, D, N);
73 }
74
2875 namespace llvm {
2976
3077 raw_ostream &operator<<(raw_ostream &OS, const BranchProbability &Prob) {
8686 EXPECT_EQ(BP::getOne(), BP(0, 7).getCompl());
8787 }
8888
89 TEST(BranchProbabilityTest, scale) {
90 // Multiply by 1.0.
91 EXPECT_EQ(UINT64_MAX, BP(1, 1).scale(UINT64_MAX));
92 EXPECT_EQ(UINT64_MAX, BP(7, 7).scale(UINT64_MAX));
93 EXPECT_EQ(UINT32_MAX, BP(1, 1).scale(UINT32_MAX));
94 EXPECT_EQ(UINT32_MAX, BP(7, 7).scale(UINT32_MAX));
95 EXPECT_EQ(0u, BP(1, 1).scale(0));
96 EXPECT_EQ(0u, BP(7, 7).scale(0));
97
98 // Multiply by 0.0.
99 EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX));
100 EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX));
101 EXPECT_EQ(0u, BP(0, 1).scale(0));
102
103 auto Two63 = UINT64_C(1) << 63;
104 auto Two31 = UINT64_C(1) << 31;
105
106 // Multiply by 0.5.
107 EXPECT_EQ(Two63 - 1, BP(1, 2).scale(UINT64_MAX));
108
109 // Big fractions.
110 EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scale(2));
111 EXPECT_EQ(Two31, BP(Two31, UINT32_MAX).scale(Two31 * 2));
112 EXPECT_EQ(Two63 + Two31, BP(Two31, UINT32_MAX).scale(UINT64_MAX));
113
114 // High precision.
115 EXPECT_EQ(UINT64_C(9223372047592194055),
116 BP(Two31 + 1, UINT32_MAX - 2).scale(UINT64_MAX));
89117 }
118
119 TEST(BranchProbabilityTest, scaleByInverse) {
120 // Divide by 1.0.
121 EXPECT_EQ(UINT64_MAX, BP(1, 1).scaleByInverse(UINT64_MAX));
122 EXPECT_EQ(UINT64_MAX, BP(7, 7).scaleByInverse(UINT64_MAX));
123 EXPECT_EQ(UINT32_MAX, BP(1, 1).scaleByInverse(UINT32_MAX));
124 EXPECT_EQ(UINT32_MAX, BP(7, 7).scaleByInverse(UINT32_MAX));
125 EXPECT_EQ(0u, BP(1, 1).scaleByInverse(0));
126 EXPECT_EQ(0u, BP(7, 7).scaleByInverse(0));
127
128 // Divide by something very small.
129 EXPECT_EQ(UINT64_MAX, BP(1, UINT32_MAX).scaleByInverse(UINT64_MAX));
130 EXPECT_EQ(uint64_t(UINT32_MAX) * UINT32_MAX,
131 BP(1, UINT32_MAX).scaleByInverse(UINT32_MAX));
132 EXPECT_EQ(UINT32_MAX, BP(1, UINT32_MAX).scaleByInverse(1));
133
134 auto Two63 = UINT64_C(1) << 63;
135 auto Two31 = UINT64_C(1) << 31;
136
137 // Divide by 0.5.
138 EXPECT_EQ(UINT64_MAX - 1, BP(1, 2).scaleByInverse(Two63 - 1));
139 EXPECT_EQ(UINT64_MAX, BP(1, 2).scaleByInverse(Two63));
140
141 // Big fractions.
142 EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scaleByInverse(1));
143 EXPECT_EQ(2u, BP(Two31 - 1, UINT32_MAX).scaleByInverse(1));
144 EXPECT_EQ(Two31 * 2 - 1, BP(Two31, UINT32_MAX).scaleByInverse(Two31));
145 EXPECT_EQ(Two31 * 2 + 1, BP(Two31 - 1, UINT32_MAX).scaleByInverse(Two31));
146 EXPECT_EQ(UINT64_MAX, BP(Two31, UINT32_MAX).scaleByInverse(Two63 + Two31));
147
148 // High precision. The exact answers to these are close to the successors of
149 // the floor. If we were rounding, these would round up.
150 EXPECT_EQ(UINT64_C(18446744065119617030),
151 BP(Two31 + 2, UINT32_MAX - 2)
152 .scaleByInverse(UINT64_C(9223372047592194055)));
153 EXPECT_EQ(UINT64_C(18446744065119617026),
154 BP(Two31 + 1, UINT32_MAX).scaleByInverse(Two63 + Two31));
155 }
156
157 }