llvm.org GIT mirror
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).
 49 49 50 50 void dump() const; 51 51 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 52 76 bool operator==(BranchProbability RHS) const { 53 77 return (uint64_t)N * RHS.D == (uint64_t)D * RHS.N; 54 78 }
 25 25 dbgs() << *this << '\n'; 26 26 } 27 27 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 28 75 namespace llvm { 29 76 30 77 raw_ostream &operator<<(raw_ostream &OS, const BranchProbability &Prob) {
 86 86 EXPECT_EQ(BP::getOne(), BP(0, 7).getCompl()); 87 87 } 88 88 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)); 89 117 } 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 }