LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 33188 - Clang's _bittest* MSVC intrinsics are incorrect for values outside [0, 31]
Summary: Clang's _bittest* MSVC intrinsics are incorrect for values outside [0, 31]
Status: RESOLVED FIXED
Alias: None
Product: clang
Classification: Unclassified
Component: Headers (show other bugs)
Version: unspecified
Hardware: PC Windows NT
: P enhancement
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-05-26 15:15 PDT by Reid Kleckner
Modified: 2018-06-05 18:48 PDT (History)
2 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Reid Kleckner 2017-05-26 15:15:28 PDT
I discovered this while staring at Microsoft's platform adaption layer code in ChakraCore: https://github.com/Microsoft/ChakraCore/blob/master/lib/Common/CommonPal.h#L647

    __forceinline unsigned char _BitTestAndSet(LONG *_BitBase, int _BitPos)
    {
#if defined(__clang__) && !defined(_ARM_)
        // Clang doesn't expand _bittestandset intrinic to bts, and it's implemention also doesn't work for _BitPos >= 32
        unsigned char retval = 0;
        asm(
            "bts %[_BitPos], %[_BitBase]\n\t"
            "setc %b[retval]\n\t"
            : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval)
            : [_BitPos] "ri" (_BitPos)
            : "cc" // clobber condition code
        );
        return retval;
#else
        return _bittestandset(_BitBase, _BitPos);
#endif
    }

It's a shame that nobody filed this bug upstream. :(

The Intel manual supports confirms this view:
"""
BT—Bit Test
...
Selects the bit in a bit string (specified with the first operand, called the bit base) at the bit-position designated by
the bit offset (specified by the second operand) and stores the value of the bit in the CF flag. The bit base operand
can be a register or a memory location; the bit offset operand can be a register or an immediate value:
• If the bit base operand specifies a register, the instruction takes the modulo 16, 32, or 64 of the bit offset
operand (modulo size depends on the mode and register size; 64-bit operands are available only in 64-bit
mode).
• If the bit base operand specifies a memory location, the operand represents the address of the byte in memory
that contains the bit base (bit 0 of the specified byte) of the bit string. The range of the bit position that can be
referenced by the offset operand depends on the operand size.
See also: Bit(BitBase, BitOffset) on page 3-11. 
"""

We either need to codegen this with an intrinsic or inline asm that will reliably select to bts, or we need to do an array indexing operation first.
Comment 1 Hans Wennborg 2017-08-08 14:29:56 PDT
There was a patch for this, but it got stuck: https://reviews.llvm.org/D33616
Comment 2 Reid Kleckner 2018-06-05 18:48:02 PDT
This should be fixed after r333978, r334059, and r334060.