[llvm] r300710 - [Support] Add some helpers to generate bitmasks.

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 19 11:12:55 PDT 2017


On Wed, Apr 19, 2017 at 5:45 PM, Zachary Turner via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: zturner
> Date: Wed Apr 19 10:45:31 2017
> New Revision: 300710
>
> URL: http://llvm.org/viewvc/llvm-project?rev=300710&view=rev
> Log:
> [Support] Add some helpers to generate bitmasks.
>
> Frequently you you want a bitmask consisting of a specified
> number of 1s, either at the beginning or end of a word.
>
> The naive way to do this is to write
>
> template<typename T>
> T leadingBitMask(unsigned N) {
>   return (T(1) << N) - 1;
> }
>
> but using this function you cannot produce a word with every
> bit set to 1 (i.e. leadingBitMask<uint8_t>(8)) because left
> shift is undefined when N is greater than or equal to the
> number of bits in the word.
>
> This patch provides an efficient, branch-free implementation
> that works for all values of N in [0, CHAR_BIT*sizeof(T)]
>
> Differential Revision: https://reviews.llvm.org/D32212
>
> Modified:
>     llvm/trunk/include/llvm/Support/MathExtras.h
>     llvm/trunk/unittests/Support/MathExtrasTest.cpp
>
> Modified: llvm/trunk/include/llvm/Support/MathExtras.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MathExtras.h?rev=300710&r1=300709&r2=300710&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/MathExtras.h (original)
> +++ llvm/trunk/include/llvm/Support/MathExtras.h Wed Apr 19 10:45:31 2017
> @@ -198,6 +198,21 @@ template <typename T> T findFirstSet(T V
>    return countTrailingZeros(Val, ZB_Undefined);
>  }
>
> +/// \brief Create a bitmask with the N right-most bits set to 1, and all other
> +/// bits set to 0.  Only unsigned types are allowed.
> +template <typename T> T maskTrailingOnes(unsigned N) {
> +  static_assert(std::is_unsigned<T>::value, "Invalid type!");
> +  const unsigned Bits = CHAR_BIT * sizeof(T);
> +  assert(N <= Bits && "Invalid bit index");
> +  return -T(N != 0) & (T(-1) >> (Bits - N));

This would be safe with LLVM's definition of UB, but not with C++'s.
Changed it to branchy in r300721.

> +}
> +
> +/// \brief Create a bitmask with the N left-most bits set to 1, and all other
> +/// bits set to 0.  Only unsigned types are allowed.
> +template <typename T> T maskLeadingOnes(unsigned N) {
> +  return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
> +}
> +
>  /// \brief Get the index of the last set bit starting from the least
>  ///   significant bit.
>  ///
>
> Modified: llvm/trunk/unittests/Support/MathExtrasTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MathExtrasTest.cpp?rev=300710&r1=300709&r2=300710&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/Support/MathExtrasTest.cpp (original)
> +++ llvm/trunk/unittests/Support/MathExtrasTest.cpp Wed Apr 19 10:45:31 2017
> @@ -66,6 +66,26 @@ TEST(MathExtras, countLeadingZeros) {
>    }
>  }
>
> +TEST(MathExtras, onesMask) {
> +  EXPECT_EQ(0U, maskLeadingOnes<uint8_t>(0));
> +  EXPECT_EQ(0U, maskTrailingOnes<uint8_t>(0));
> +  EXPECT_EQ(0U, maskLeadingOnes<uint16_t>(0));
> +  EXPECT_EQ(0U, maskTrailingOnes<uint16_t>(0));
> +  EXPECT_EQ(0U, maskLeadingOnes<uint32_t>(0));
> +  EXPECT_EQ(0U, maskTrailingOnes<uint32_t>(0));
> +  EXPECT_EQ(0U, maskLeadingOnes<uint64_t>(0));
> +  EXPECT_EQ(0U, maskTrailingOnes<uint64_t>(0));
> +
> +  EXPECT_EQ(0x00000003U, maskTrailingOnes<uint32_t>(2U));
> +  EXPECT_EQ(0xC0000000U, maskLeadingOnes<uint32_t>(2U));
> +
> +  EXPECT_EQ(0x000007FFU, maskTrailingOnes<uint32_t>(11U));
> +  EXPECT_EQ(0xFFE00000U, maskLeadingOnes<uint32_t>(11U));
> +
> +  EXPECT_EQ(0xFFFFFFFFU, maskTrailingOnes<uint32_t>(32U));
> +  EXPECT_EQ(0xFFFFFFFFU, maskLeadingOnes<uint32_t>(32U));
> +}
> +
>  TEST(MathExtras, findFirstSet) {
>    uint8_t Z8 = 0;
>    uint16_t Z16 = 0;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list