Skip to content

Commit 80f8cfb

Browse files
committed
Don't interfere with the __builtin_foo namespace under MSVC
This patch follows up on feedback received in the review for D32988. Specifically that libc++ should not mess with the __builtin namespace, and that libc++ should use __popcnt to implement __pop_count under MSVC. llvm-svn: 302731
1 parent 3c5e423 commit 80f8cfb

File tree

2 files changed

+103
-178
lines changed

2 files changed

+103
-178
lines changed

libcxx/include/algorithm

Lines changed: 103 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ template <class BidirectionalIterator, class Compare>
645645
#include "support/ibm/support.h"
646646
#endif
647647
#if defined(_LIBCPP_COMPILER_MSVC)
648-
#include "support/win32/msvc_builtin_support.h"
648+
#include <intrin.h>
649649
#endif
650650

651651
#include <__undef_min_max>
@@ -783,51 +783,132 @@ struct __debug_less
783783

784784
// Precondition: __x != 0
785785
inline _LIBCPP_INLINE_VISIBILITY
786-
unsigned
787-
__ctz(unsigned __x)
788-
{
786+
unsigned __ctz(unsigned __x) {
787+
#ifndef _LIBCPP_COMPILER_MSVC
789788
return static_cast<unsigned>(__builtin_ctz(__x));
789+
#else
790+
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
791+
static_assert(sizeof(unsigned long) == 4, "");
792+
unsigned long where;
793+
// Search from LSB to MSB for first set bit.
794+
// Returns zero if no set bit is found.
795+
if (_BitScanForward(&where, mask))
796+
return where;
797+
return 32;
798+
#endif
790799
}
791800

792801
inline _LIBCPP_INLINE_VISIBILITY
793-
unsigned long
794-
__ctz(unsigned long __x)
795-
{
802+
unsigned long __ctz(unsigned long __x) {
803+
#ifndef _LIBCPP_COMPILER_MSVC
796804
return static_cast<unsigned long>(__builtin_ctzl(__x));
805+
#else
806+
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
807+
return __ctz(static_cast<unsigned>(__x));
808+
#endif
797809
}
798810

799811
inline _LIBCPP_INLINE_VISIBILITY
800-
unsigned long long
801-
__ctz(unsigned long long __x)
802-
{
812+
unsigned long long __ctz(unsigned long long __x) {
813+
#ifndef _LIBCPP_COMPILER_MSVC
803814
return static_cast<unsigned long long>(__builtin_ctzll(__x));
815+
#else
816+
unsigned long where;
817+
// Search from LSB to MSB for first set bit.
818+
// Returns zero if no set bit is found.
819+
#if defined(_LIBCPP_HAS_BITSCAN64)
820+
(defined(_M_AMD64) || defined(__x86_64__))
821+
if (_BitScanForward64(&where, mask))
822+
return static_cast<int>(where);
823+
#else
824+
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
825+
// Scan the Low Word.
826+
if (_BitScanForward(&where, static_cast<unsigned long>(mask)))
827+
return where;
828+
// Scan the High Word.
829+
if (_BitScanForward(&where, static_cast<unsigned long>(mask >> 32)))
830+
return where + 32; // Create a bit offset from the LSB.
831+
#endif
832+
return 64;
833+
#endif // _LIBCPP_COMPILER_MSVC
804834
}
805835

806836
// Precondition: __x != 0
807837
inline _LIBCPP_INLINE_VISIBILITY
808-
unsigned
809-
__clz(unsigned __x)
810-
{
838+
unsigned __clz(unsigned __x) {
839+
#ifndef _LIBCPP_COMPILER_MSVC
811840
return static_cast<unsigned>(__builtin_clz(__x));
841+
#else
842+
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
843+
static_assert(sizeof(unsigned long) == 4, "");
844+
unsigned long where;
845+
// Search from LSB to MSB for first set bit.
846+
// Returns zero if no set bit is found.
847+
if (_BitScanReverse(&where, mask))
848+
return 31 - where;
849+
return 32; // Undefined Behavior.
850+
#endif
812851
}
813852

814853
inline _LIBCPP_INLINE_VISIBILITY
815-
unsigned long
816-
__clz(unsigned long __x)
817-
{
854+
unsigned long __clz(unsigned long __x) {
855+
#ifndef _LIBCPP_COMPILER_MSVC
818856
return static_cast<unsigned long>(__builtin_clzl (__x));
857+
#else
858+
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
859+
return __clz(static_cast<unsigned>(__x));
860+
#endif
819861
}
820862

821863
inline _LIBCPP_INLINE_VISIBILITY
822-
unsigned long long
823-
__clz(unsigned long long __x)
824-
{
864+
unsigned long long __clz(unsigned long long __x) {
865+
#ifndef _LIBCPP_COMPILER_MSVC
825866
return static_cast<unsigned long long>(__builtin_clzll(__x));
867+
#else
868+
unsigned long where;
869+
// BitScanReverse scans from MSB to LSB for first set bit.
870+
// Returns 0 if no set bit is found.
871+
#if defined(_LIBCPP_HAS_BITSCAN64)
872+
if (_BitScanReverse64(&where, mask))
873+
return static_cast<int>(63 - where);
874+
#else
875+
// Scan the high 32 bits.
876+
if (_BitScanReverse(&where, static_cast<unsigned long>(mask >> 32)))
877+
return 63 - (where + 32); // Create a bit offset from the MSB.
878+
// Scan the low 32 bits.
879+
if (_BitScanReverse(&where, static_cast<unsigned long>(mask)))
880+
return 63 - where;
881+
#endif
882+
return 64; // Undefined Behavior.
883+
#endif // _LIBCPP_COMPILER_MSVC
884+
}
885+
886+
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned __x) {
887+
#ifndef _LIBCPP_COMPILER_MSVC
888+
return __builtin_popcount (__x);
889+
#else
890+
static_assert(sizeof(unsigned) == 4, "");
891+
return __popcnt(__x);
892+
#endif
893+
}
894+
895+
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned long __x) {
896+
#ifndef _LIBCPP_COMPILER_MSVC
897+
return __builtin_popcountl (__x);
898+
#else
899+
static_assert(sizeof(unsigned long) == 4, "");
900+
return __popcnt(__x);
901+
#endif
826902
}
827903

828-
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned __x) {return __builtin_popcount (__x);}
829-
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned long __x) {return __builtin_popcountl (__x);}
830-
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned long long __x) {return __builtin_popcountll(__x);}
904+
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned long long __x) {
905+
#ifndef _LIBCPP_COMPILER_MSVC
906+
return __builtin_popcountll(__x);
907+
#else
908+
static_assert(sizeof(unsigned long long) == 8, "");
909+
return __popcnt64(__x);
910+
#endif
911+
}
831912

832913
// all_of
833914

libcxx/include/support/win32/msvc_builtin_support.h

Lines changed: 0 additions & 156 deletions
This file was deleted.

0 commit comments

Comments
 (0)