llvm.org GIT mirror llvm / c71e199
Fix isShiftedInt and isShiftedUint for widths > 32. Summary: Previously we were doing 1 << S. "1" is an int, so this doesn't work when S >= 32. This patch also adds some static_asserts to these functions to ensure that we don't hit UB by shifting left too much. Reviewers: rnk Subscribers: llvm-commits, dylanmckay Differential Revision: https://reviews.llvm.org/D22441 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275719 91177308-0d34-0410-b5e6-96231b3b80d8 Justin Lebar 3 years ago
2 changed file(s) with 53 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
282282 /// left by S.
283283 template
284284 inline bool isShiftedInt(int64_t x) {
285 return isInt(x) && (x % (1<
285 static_assert(
286 N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
287 static_assert(N + S <= 64, "isShiftedInt with N + S > 64 is too wide.");
288 return isInt(x) && (x % (UINT64_C(1) << S) == 0);
286289 }
287290
288291 /// isUInt - Checks if an unsigned integer fits into the given bit width.
289292 template
290293 inline bool isUInt(uint64_t x) {
294 static_assert(N > 0, "isUInt<0> doesn't make sense.");
291295 return N >= 64 || x < (UINT64_C(1)<<(N));
292296 }
297
293298 // Template specializations to get better code for common cases.
294299 template<>
295300 inline bool isUInt<8>(uint64_t x) {
304309 return static_cast(x) == x;
305310 }
306311
307 /// isShiftedUInt - Checks if a unsigned integer is an N bit number shifted
308 /// left by S.
312 /// Checks if a unsigned integer is an N bit number shifted left by S.
309313 template
310314 inline bool isShiftedUInt(uint64_t x) {
311 return isUInt(x) && (x % (1<
315 static_assert(
316 N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
317 static_assert(N + S <= 64,
318 "isShiftedUInt with N + S > 64 is too wide.");
319 // Per the two static_asserts above, S must be strictly less than 64. So
320 // 1 << S is not undefined behavior.
321 return isUInt(x) && (x % (UINT64_C(1) << S) == 0);
312322 }
313323
314324 /// Gets the maximum value for a N-bit unsigned integer.
387387 SaturatingMultiplyAddTestHelper();
388388 }
389389
390 }
390 TEST(MathExtras, IsShiftedUInt) {
391 EXPECT_TRUE((isShiftedUInt<1, 0>(0)));
392 EXPECT_TRUE((isShiftedUInt<1, 0>(1)));
393 EXPECT_FALSE((isShiftedUInt<1, 0>(2)));
394 EXPECT_FALSE((isShiftedUInt<1, 0>(3)));
395 EXPECT_FALSE((isShiftedUInt<1, 0>(0x8000000000000000)));
396 EXPECT_TRUE((isShiftedUInt<1, 63>(0x8000000000000000)));
397 EXPECT_TRUE((isShiftedUInt<2, 62>(0xC000000000000000)));
398 EXPECT_FALSE((isShiftedUInt<2, 62>(0xE000000000000000)));
399
400 // 0x201 is ten bits long and has a 1 in the MSB and LSB.
401 EXPECT_TRUE((isShiftedUInt<10, 5>(uint64_t(0x201) << 5)));
402 EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 4)));
403 EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 6)));
404 }
405
406 TEST(MathExtras, IsShiftedInt) {
407 EXPECT_TRUE((isShiftedInt<1, 0>(0)));
408 EXPECT_TRUE((isShiftedInt<1, 0>(-1)));
409 EXPECT_FALSE((isShiftedInt<1, 0>(2)));
410 EXPECT_FALSE((isShiftedInt<1, 0>(3)));
411 EXPECT_FALSE((isShiftedInt<1, 0>(0x8000000000000000)));
412 EXPECT_TRUE((isShiftedInt<1, 63>(0x8000000000000000)));
413 EXPECT_TRUE((isShiftedInt<2, 62>(0xC000000000000000)));
414 EXPECT_FALSE((isShiftedInt<2, 62>(0xE000000000000000)));
415
416 // 0x201 is ten bits long and has a 1 in the MSB and LSB.
417 EXPECT_TRUE((isShiftedInt<11, 5>(int64_t(0x201) << 5)));
418 EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 3)));
419 EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 6)));
420 EXPECT_TRUE((isShiftedInt<11, 5>(-(int64_t(0x201) << 5))));
421 EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 3))));
422 EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 6))));
423
424 EXPECT_TRUE((isShiftedInt<6, 10>(-(int64_t(1) << 15))));
425 EXPECT_FALSE((isShiftedInt<6, 10>(int64_t(1) << 15)));
426 }
427
428 } // namespace