<div dir="ltr">Can you elaborate?  What's UB about the branch-free version?</div><br><div class="gmail_quote"><div dir="ltr">On Wed, Apr 19, 2017 at 11:13 AM Benjamin Kramer <<a href="mailto:benny.kra@gmail.com">benny.kra@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Wed, Apr 19, 2017 at 5:45 PM, Zachary Turner via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
> Author: zturner<br>
> Date: Wed Apr 19 10:45:31 2017<br>
> New Revision: 300710<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=300710&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=300710&view=rev</a><br>
> Log:<br>
> [Support] Add some helpers to generate bitmasks.<br>
><br>
> Frequently you you want a bitmask consisting of a specified<br>
> number of 1s, either at the beginning or end of a word.<br>
><br>
> The naive way to do this is to write<br>
><br>
> template<typename T><br>
> T leadingBitMask(unsigned N) {<br>
>   return (T(1) << N) - 1;<br>
> }<br>
><br>
> but using this function you cannot produce a word with every<br>
> bit set to 1 (i.e. leadingBitMask<uint8_t>(8)) because left<br>
> shift is undefined when N is greater than or equal to the<br>
> number of bits in the word.<br>
><br>
> This patch provides an efficient, branch-free implementation<br>
> that works for all values of N in [0, CHAR_BIT*sizeof(T)]<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D32212" rel="noreferrer" target="_blank">https://reviews.llvm.org/D32212</a><br>
><br>
> Modified:<br>
>     llvm/trunk/include/llvm/Support/MathExtras.h<br>
>     llvm/trunk/unittests/Support/MathExtrasTest.cpp<br>
><br>
> Modified: llvm/trunk/include/llvm/Support/MathExtras.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MathExtras.h?rev=300710&r1=300709&r2=300710&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MathExtras.h?rev=300710&r1=300709&r2=300710&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Support/MathExtras.h (original)<br>
> +++ llvm/trunk/include/llvm/Support/MathExtras.h Wed Apr 19 10:45:31 2017<br>
> @@ -198,6 +198,21 @@ template <typename T> T findFirstSet(T V<br>
>    return countTrailingZeros(Val, ZB_Undefined);<br>
>  }<br>
><br>
> +/// \brief Create a bitmask with the N right-most bits set to 1, and all other<br>
> +/// bits set to 0.  Only unsigned types are allowed.<br>
> +template <typename T> T maskTrailingOnes(unsigned N) {<br>
> +  static_assert(std::is_unsigned<T>::value, "Invalid type!");<br>
> +  const unsigned Bits = CHAR_BIT * sizeof(T);<br>
> +  assert(N <= Bits && "Invalid bit index");<br>
> +  return -T(N != 0) & (T(-1) >> (Bits - N));<br>
<br>
This would be safe with LLVM's definition of UB, but not with C++'s.<br>
Changed it to branchy in r300721.<br>
<br>
> +}<br>
> +<br>
> +/// \brief Create a bitmask with the N left-most bits set to 1, and all other<br>
> +/// bits set to 0.  Only unsigned types are allowed.<br>
> +template <typename T> T maskLeadingOnes(unsigned N) {<br>
> +  return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);<br>
> +}<br>
> +<br>
>  /// \brief Get the index of the last set bit starting from the least<br>
>  ///   significant bit.<br>
>  ///<br>
><br>
> Modified: llvm/trunk/unittests/Support/MathExtrasTest.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MathExtrasTest.cpp?rev=300710&r1=300709&r2=300710&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MathExtrasTest.cpp?rev=300710&r1=300709&r2=300710&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/unittests/Support/MathExtrasTest.cpp (original)<br>
> +++ llvm/trunk/unittests/Support/MathExtrasTest.cpp Wed Apr 19 10:45:31 2017<br>
> @@ -66,6 +66,26 @@ TEST(MathExtras, countLeadingZeros) {<br>
>    }<br>
>  }<br>
><br>
> +TEST(MathExtras, onesMask) {<br>
> +  EXPECT_EQ(0U, maskLeadingOnes<uint8_t>(0));<br>
> +  EXPECT_EQ(0U, maskTrailingOnes<uint8_t>(0));<br>
> +  EXPECT_EQ(0U, maskLeadingOnes<uint16_t>(0));<br>
> +  EXPECT_EQ(0U, maskTrailingOnes<uint16_t>(0));<br>
> +  EXPECT_EQ(0U, maskLeadingOnes<uint32_t>(0));<br>
> +  EXPECT_EQ(0U, maskTrailingOnes<uint32_t>(0));<br>
> +  EXPECT_EQ(0U, maskLeadingOnes<uint64_t>(0));<br>
> +  EXPECT_EQ(0U, maskTrailingOnes<uint64_t>(0));<br>
> +<br>
> +  EXPECT_EQ(0x00000003U, maskTrailingOnes<uint32_t>(2U));<br>
> +  EXPECT_EQ(0xC0000000U, maskLeadingOnes<uint32_t>(2U));<br>
> +<br>
> +  EXPECT_EQ(0x000007FFU, maskTrailingOnes<uint32_t>(11U));<br>
> +  EXPECT_EQ(0xFFE00000U, maskLeadingOnes<uint32_t>(11U));<br>
> +<br>
> +  EXPECT_EQ(0xFFFFFFFFU, maskTrailingOnes<uint32_t>(32U));<br>
> +  EXPECT_EQ(0xFFFFFFFFU, maskLeadingOnes<uint32_t>(32U));<br>
> +}<br>
> +<br>
>  TEST(MathExtras, findFirstSet) {<br>
>    uint8_t Z8 = 0;<br>
>    uint16_t Z16 = 0;<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>