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

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 19 12:18:59 PDT 2017


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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170419/1174ed55/attachment.html>


More information about the llvm-commits mailing list