{"id":26344,"date":"2020-09-03T16:39:27","date_gmt":"2020-09-03T16:39:27","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=26344"},"modified":"2020-09-03T16:40:39","modified_gmt":"2020-09-03T16:40:39","slug":"bit-in-visual-studio-2019-version-16-8-preview-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/bit-in-visual-studio-2019-version-16-8-preview-2\/","title":{"rendered":"&lt;bit&gt; in Visual Studio 2019 version 16.8 Preview 2"},"content":{"rendered":"<p>C++20 added two new library features for those of you that like bit twiddling: \u201cbit rotating and counting functions\u201d and \u201cintegral power of two operations\u201d. Most of the added function templates are simple numeric utility functions, and a handful map somewhat directly to common instructions on modern CPUs. We&#8217;ve implemented them in Visual Studio 2019 version 16.8 Preview 2. This post will tell you about our implementations and what processor-specific optimizations you can expect.<\/p>\n<p>All the functions are fully constexpr enabled, which should be quite handy for things like computing lookup tables. I know I\u2019ve seen these functions implemented in several numeric codebases, so hopefully having standard versions will be useful. The new functions are:<\/p>\n<p>&nbsp;<\/p>\n<h2>std::countl_zero, std::countr_zero<\/h2>\n<p>These count the number of zeros on the left (from most-significant-bit to least-significant-bit), or right (from least-significant-bit to most-significant-bit) respectively. On x86 and x64 platforms these emit the <code>LZCNT<\/code> and <code>TZCNT<\/code> instructions respectively. By default, the availability of the instructions is checked at runtime. The <code>BSF<\/code> and <code>BSR<\/code> instructions will be used if the runtime check fails. The runtime check is omitted when compiling with <code>\/arch:AVX2<\/code> or higher, since all CPUs that support AVX2 also support <code>LZCNT<\/code> and <code>TZCNT<\/code>. On ARM and ARM64 <code>countl_zero<\/code> emits the <code>CLZ<\/code> instruction; <code>countr_zero<\/code> does not emit any special instructions on <code>ARM<\/code> or <code>ARM64<\/code> at this time.<\/p>\n<p>Interestingly, <code>LZCNT<\/code> and <code>TZCNT<\/code> have a somewhat oddball instruction encoding on x86 and x64; they are encoded as <code>REP BSF<\/code> and <code>REP BSR<\/code>. The rep prefix is ignored on CPUs that don\u2019t support <code>LZCNT<\/code> or <code>TZCNT<\/code>. This means that running code with <code>LZCNT<\/code> or <code>TZCNT<\/code> on a CPU that doesn\u2019t support them will still run, but <code>TZCNT<\/code> won\u2019t have the correct output for zero and <code>LZCNT<\/code> will both have the wrong output for zero and return the index of the first set bit starting from the least significant bit, which is the opposite of what it does on CPUs that actually support the instruction. This isn\u2019t a very useful fallback, and while we tried to use it in <code>&lt;bit&gt;<\/code> to simplify some code, it ended up being more trouble than it was worth.<\/p>\n<p>Note that Visual Studio version 16.8 Preview 1 contains a bug related to <code>LZCNT<\/code> usage on CPUs that only support bsr. This will be fixed in Visual Studio version 16.8 Preview 3.<\/p>\n<p>&nbsp;<\/p>\n<h2>std::popcount<\/h2>\n<p><code>std::popcount<\/code> counts the number of set bits in its input. On x86 and x64 platforms <code>popcount<\/code> emits the <code>POPCNT<\/code> instruction, again checking the availability of <code>POPCNT<\/code> at runtime. If compiled with <code>\/arch:AVX<\/code> or higher no check is made as all CPUs that support AVX also support <code>POPCNT<\/code>. No special instructions are emitted on ARM or ARM64 at this time.<\/p>\n<p>&nbsp;<\/p>\n<h2>std::countl_one, std::countr_one<\/h2>\n<p>Counts the number of ones on the left or right of their input; these rely on <code>countl_zero<\/code> and <code>countr_zero<\/code> and thus will use the same intrinsics as those<\/p>\n<p>&nbsp;<\/p>\n<h2>std::has_single_bit<\/h2>\n<p>Functionally equivalent to <code>popcount(x) == 1<\/code>. <code>has_single_bit<\/code> does not use any special instructions.<\/p>\n<p>&nbsp;<\/p>\n<h2>std::bit_ceil, std::bit_floor<\/h2>\n<p>Finds the nearest power of two above or below the input. If the input is already a power of two it is returned unchanged. If the result would not be representable in the input\u2019s type, then the behavior is undefined (this occurs for example in <code>bit_ceil(static_cast&lt;unsigned char&gt;(0b11111111))<\/code>). <code>bit_ceil<\/code> is only allowed as a constant expression if this undefined behavior does not occur. <code>bit_floor<\/code> returns zero when the input is zero.<\/p>\n<p>&nbsp;<\/p>\n<h2>std::rotl, std::rotr<\/h2>\n<p>Bitwise rotates the input to the left or right. Currently this does not explicitly emit any special instructions.<\/p>\n<p>&nbsp;<\/p>\n<p>You can try all of these functions out today by downloading <a href=\"https:\/\/visualstudio.microsoft.com\/vs\/preview\/\">Visual Studio 2019 version 16.8 Preview 2<\/a>\u00a0 and compiling your code with <code>\/std:c++latest<\/code>. If you find any bugs in our library implementation report them by opening an issue at on our <a href=\"https:\/\/github.com\/microsoft\/stl\">GitHub page<\/a>. Please report any other Visual Studio issues on <a href=\"https:\/\/developercommunity.visualstudio.com\/\">Developer Community<\/a>. Don\u2019t hesitate to contact us with any questions or suggestions.<\/p>\n<p>You can also read find our <a href=\"https:\/\/docs.microsoft.com\/en-us\/cpp\/standard-library\/bit?view=vs-2019\">reference documentation<\/a> or the relevant C++ papers on <code>&lt;bit&gt;<\/code>: <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n3864.html\">P0553R4: Bit operations<\/a> and <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2018\/p0556r3.html\">P0556R3: Integral power-of-2 operations<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bit twiddling: \u201cbit rotating and counting functions\u201d and \u201cintegral power of two operations\u201d.<\/p>\n","protected":false},"author":4807,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-26344","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>Bit twiddling: \u201cbit rotating and counting functions\u201d and \u201cintegral power of two operations\u201d.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/26344","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/4807"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=26344"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/26344\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=26344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=26344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=26344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}