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;
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;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits