llvm.org GIT mirror llvm / 21314fb
[Support] Add saturating multiply-add support function Summary: Add SaturatingMultiplyAdd convenience function template since A + (X * Y) comes up frequently when doing weighted arithmetic. Reviewers: davidxl, silvas Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15385 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257532 91177308-0d34-0410-b5e6-96231b3b80d8 Nathan Slingerland 3 years ago
4 changed file(s) with 92 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
139139 /// around unsigned integers.
140140 sampleprof_error addSamples(uint64_t S, uint64_t Weight = 1) {
141141 bool Overflowed;
142 if (Weight > 1) {
143 S = SaturatingMultiply(S, Weight, &Overflowed);
144 if (Overflowed)
145 return sampleprof_error::counter_overflow;
146 }
147 NumSamples = SaturatingAdd(NumSamples, S, &Overflowed);
148 if (Overflowed)
149 return sampleprof_error::counter_overflow;
150
151 return sampleprof_error::success;
142 NumSamples = SaturatingMultiplyAdd(S, Weight, NumSamples, &Overflowed);
143 return Overflowed ? sampleprof_error::counter_overflow
144 : sampleprof_error::success;
152145 }
153146
154147 /// Add called function \p F with samples \p S.
160153 uint64_t Weight = 1) {
161154 uint64_t &TargetSamples = CallTargets[F];
162155 bool Overflowed;
163 if (Weight > 1) {
164 S = SaturatingMultiply(S, Weight, &Overflowed);
165 if (Overflowed)
166 return sampleprof_error::counter_overflow;
167 }
168 TargetSamples = SaturatingAdd(TargetSamples, S, &Overflowed);
169 if (Overflowed)
170 return sampleprof_error::counter_overflow;
171
172 return sampleprof_error::success;
156 TargetSamples =
157 SaturatingMultiplyAdd(S, Weight, TargetSamples, &Overflowed);
158 return Overflowed ? sampleprof_error::counter_overflow
159 : sampleprof_error::success;
173160 }
174161
175162 /// Return true if this sample record contains function calls.
214201 void dump() const;
215202 sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
216203 bool Overflowed;
217 if (Weight > 1) {
218 Num = SaturatingMultiply(Num, Weight, &Overflowed);
219 if (Overflowed)
220 return sampleprof_error::counter_overflow;
221 }
222 TotalSamples = SaturatingAdd(TotalSamples, Num, &Overflowed);
223 if (Overflowed)
224 return sampleprof_error::counter_overflow;
225
226 return sampleprof_error::success;
204 TotalSamples =
205 SaturatingMultiplyAdd(Num, Weight, TotalSamples, &Overflowed);
206 return Overflowed ? sampleprof_error::counter_overflow
207 : sampleprof_error::success;
227208 }
228209 sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
229210 bool Overflowed;
230 if (Weight > 1) {
231 Num = SaturatingMultiply(Num, Weight, &Overflowed);
232 if (Overflowed)
233 return sampleprof_error::counter_overflow;
234 }
235 TotalHeadSamples = SaturatingAdd(TotalHeadSamples, Num, &Overflowed);
236 if (Overflowed)
237 return sampleprof_error::counter_overflow;
238
239 return sampleprof_error::success;
211 TotalHeadSamples =
212 SaturatingMultiplyAdd(Num, Weight, TotalHeadSamples, &Overflowed);
213 return Overflowed ? sampleprof_error::counter_overflow
214 : sampleprof_error::success;
240215 }
241216 sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator,
242217 uint64_t Num, uint64_t Weight = 1) {
716716 return Z;
717717 }
718718
719 /// \brief Multiply two unsigned integers, X and Y, and add the unsigned
720 /// integer, A to the product. Clamp the result to the maximum representable
721 /// value of T on overflow. ResultOverflowed indicates if the result is larger
722 /// than the maximum representable value of type T.
723 /// Note that this is purely a convenience function as there is no distinction
724 /// where overflow occurred in a 'fused' multiply-add for unsigned numbers.
725 template
726 typename std::enable_if::value, T>::type
727 SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
728 bool Dummy;
729 bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
730
731 T Product = SaturatingMultiply(X, Y, &Overflowed);
732 if (Overflowed)
733 return Product;
734
735 return SaturatingAdd(A, Product, &Overflowed);
736 }
737
719738 extern const float huge_valf;
720739 } // End llvm namespace
721740
268268 while (I != IE && I->Value < J->Value)
269269 ++I;
270270 if (I != IE && I->Value == J->Value) {
271 uint64_t JCount = J->Count;
272271 bool Overflowed;
273 if (Weight > 1) {
274 JCount = SaturatingMultiply(JCount, Weight, &Overflowed);
275 if (Overflowed)
276 Result = instrprof_error::counter_overflow;
277 }
278 I->Count = SaturatingAdd(I->Count, JCount, &Overflowed);
272 I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed);
279273 if (Overflowed)
280274 Result = instrprof_error::counter_overflow;
281275 ++I;
327321
328322 for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
329323 bool Overflowed;
330 uint64_t OtherCount = Other.Counts[I];
331 if (Weight > 1) {
332 OtherCount = SaturatingMultiply(OtherCount, Weight, &Overflowed);
333 if (Overflowed)
334 Result = instrprof_error::counter_overflow;
335 }
336 Counts[I] = SaturatingAdd(Counts[I], OtherCount, &Overflowed);
324 Counts[I] =
325 SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
337326 if (Overflowed)
338327 Result = instrprof_error::counter_overflow;
339328 }
303303 SaturatingMultiplyTestHelper();
304304 }
305305
306 }
306 template
307 void SaturatingMultiplyAddTestHelper()
308 {
309 const T Max = std::numeric_limits::max();
310 bool ResultOverflowed;
311
312 // Test basic multiply-add.
313 EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10)));
314 EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10), &ResultOverflowed));
315 EXPECT_FALSE(ResultOverflowed);
316
317 // Test multiply overflows, add doesn't overflow
318 EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(0), &ResultOverflowed));
319 EXPECT_TRUE(ResultOverflowed);
320
321 // Test multiply doesn't overflow, add overflows
322 EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
323 EXPECT_TRUE(ResultOverflowed);
324
325 // Test multiply-add with Max as operand
326 EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
327 EXPECT_TRUE(ResultOverflowed);
328
329 EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), Max, T(1), &ResultOverflowed));
330 EXPECT_TRUE(ResultOverflowed);
331
332 EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(1), &ResultOverflowed));
333 EXPECT_TRUE(ResultOverflowed);
334
335 EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, Max, &ResultOverflowed));
336 EXPECT_TRUE(ResultOverflowed);
337
338 // Test multiply-add with 0 as operand
339 EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(1), T(0), &ResultOverflowed));
340 EXPECT_FALSE(ResultOverflowed);
341
342 EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(0), T(1), &ResultOverflowed));
343 EXPECT_FALSE(ResultOverflowed);
344
345 EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(0), T(0), T(1), &ResultOverflowed));
346 EXPECT_FALSE(ResultOverflowed);
347
348 EXPECT_EQ(T(0), SaturatingMultiplyAdd(T(0), T(0), T(0), &ResultOverflowed));
349 EXPECT_FALSE(ResultOverflowed);
350
351 }
352
353 TEST(MathExtras, SaturatingMultiplyAdd) {
354 SaturatingMultiplyAddTestHelper();
355 SaturatingMultiplyAddTestHelper();
356 SaturatingMultiplyAddTestHelper();
357 SaturatingMultiplyAddTestHelper();
358 }
359
360 }