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

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 19 14:29:43 PDT 2017


This is the saner LLVM definition of UB. The C++ definition basically
means that as soon as UB is executed anything can happen.

On Wed, Apr 19, 2017 at 9:18 PM, Zachary Turner <zturner at google.com> wrote:
> I believe only the result of the expression is an undefined bit pattern, and
> it will be masked out by the fact the first argument will be all 0s. So it
> doesn't actually matter that the shift yields and undefined result
> On Wed, Apr 19, 2017 at 12:11 PM Benjamin Kramer <benny.kra at gmail.com>
> wrote:
>>
>> & 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