[PATCH] D33616: [MS] Fix _bittest* intrinsics for values bigger than 31

Reid Kleckner via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri May 26 16:56:29 PDT 2017


rnk created this revision.

These intrinsics are supposed to select to BT, BTS, etc instructions.
Those instructions actually perform a bitwise array indexing memory
operation that LLVM doesn't currently expose.  This change implements
the shifting and array indexing in plain C.

Fixes PR33188

If we ever fix PR19164, then the array indexing should be pattern
matched to BT and BTS memory instructions as appropriate.


https://reviews.llvm.org/D33616

Files:
  clang/lib/Headers/intrin.h


Index: clang/lib/Headers/intrin.h
===================================================================
--- clang/lib/Headers/intrin.h
+++ clang/lib/Headers/intrin.h
@@ -342,68 +342,92 @@
 \*----------------------------------------------------------------------------*/
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittest(long const *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   return (*_BitBase >> _BitPos) & 1;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittestandcomplement(long *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   unsigned char _Res = (*_BitBase >> _BitPos) & 1;
   *_BitBase = *_BitBase ^ (1 << _BitPos);
   return _Res;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittestandreset(long *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   unsigned char _Res = (*_BitBase >> _BitPos) & 1;
   *_BitBase = *_BitBase & ~(1 << _BitPos);
   return _Res;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittestandset(long *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   unsigned char _Res = (*_BitBase >> _BitPos) & 1;
   *_BitBase = *_BitBase | (1 << _BitPos);
   return _Res;
 }
 #if defined(__arm__) || defined(__aarch64__)
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _interlockedbittestandset_acq(long volatile *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_ACQUIRE);
   return (_PrevVal >> _BitPos) & 1;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _interlockedbittestandset_nf(long volatile *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELAXED);
   return (_PrevVal >> _BitPos) & 1;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _interlockedbittestandset_rel(long volatile *_BitBase, long _BitPos) {
+  _BitBase += (_BitPos / 32);
+  _BitPos %= 32;
   long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELEASE);
   return (_PrevVal >> _BitPos) & 1;
 }
 #endif
 #ifdef __x86_64__
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittest64(__int64 const *_BitBase, __int64 _BitPos) {
+  _BitBase += (_BitPos / 64);
+  _BitPos %= 64;
   return (*_BitBase >> _BitPos) & 1;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittestandcomplement64(__int64 *_BitBase, __int64 _BitPos) {
+  _BitBase += (_BitPos / 64);
+  _BitPos %= 64;
   unsigned char _Res = (*_BitBase >> _BitPos) & 1;
   *_BitBase = *_BitBase ^ (1ll << _BitPos);
   return _Res;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittestandreset64(__int64 *_BitBase, __int64 _BitPos) {
+  _BitBase += (_BitPos / 64);
+  _BitPos %= 64;
   unsigned char _Res = (*_BitBase >> _BitPos) & 1;
   *_BitBase = *_BitBase & ~(1ll << _BitPos);
   return _Res;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _bittestandset64(__int64 *_BitBase, __int64 _BitPos) {
+  _BitBase += (_BitPos / 64);
+  _BitPos %= 64;
   unsigned char _Res = (*_BitBase >> _BitPos) & 1;
   *_BitBase = *_BitBase | (1ll << _BitPos);
   return _Res;
 }
 static __inline__ unsigned char __DEFAULT_FN_ATTRS
 _interlockedbittestandset64(__int64 volatile *_BitBase, __int64 _BitPos) {
+  _BitBase += (_BitPos / 64);
+  _BitPos %= 64;
   long long _PrevVal =
       __atomic_fetch_or(_BitBase, 1ll << _BitPos, __ATOMIC_SEQ_CST);
   return (_PrevVal >> _BitPos) & 1;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33616.100502.patch
Type: text/x-patch
Size: 3546 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170526/9876a676/attachment.bin>


More information about the cfe-commits mailing list