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

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


& doesn't short-circuit, so the shift is still executed and invokes
undefined behavior if N == 0.

On Wed, Apr 19, 2017 at 8:52 PM, Zachary Turner <zturner at google.com> wrote:
> Can you elaborate?  What's UB about the branch-free version?
>
> On Wed, Apr 19, 2017 at 11:13 AM Benjamin Kramer <benny.kra at gmail.com>
> wrote:
>>
>> 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