-
Notifications
You must be signed in to change notification settings - Fork 12
Open
Labels
Description
Currently we support the shifting of lanes both left and right, with the "logical" semantics.
For example, shiftRightLanes
:
Lines 144 to 171 in 4a13f5c
constexpr SWAR shiftLanesLeft(int laneCount) const noexcept { | |
return SWAR(value() << (NBits * laneCount)); | |
} | |
constexpr SWAR shiftLanesRight(int laneCount) const noexcept { | |
return SWAR(value() >> (NBits * laneCount)); | |
} | |
/// \brief as the name suggests | |
/// \param protectiveMask should clear the bits that would cross the lane. | |
/// The bits that will be cleared are directly related to the count of | |
/// shifts, it is natural to maintain the protective mask by the caller, | |
/// otherwise, the mask would have to be computed in all invocations. | |
/// We are not sure the optimizer would maintain this mask somewhere, if it | |
/// were to recalculate it, it would be disastrous for performance | |
/// \note the \c static_cast are necessary because of narrowing conversions | |
#define SHIFT_INTRALANE_OP_X_LIST X(Left, <<) X(Right, >>) | |
#define X(name, op) \ | |
constexpr SWAR \ | |
shiftIntraLane##name(int bitCount, SWAR protectiveMask) const noexcept { \ | |
T shiftC = static_cast<T>(bitCount); \ | |
auto V = (*this & protectiveMask).value(); \ | |
auto rv = static_cast<T>(V op shiftC); \ | |
return SWAR{rv}; \ | |
} | |
SHIFT_INTRALANE_OP_X_LIST | |
#undef X | |
#undef SHIFT_INTRALANE_OP_X_LIST |
There are many arithmetic operations that would like to have "arithmetic" shift right, shift right can be used as cheap division by two, then there are very clear use cases that we can anticipate enough for implementing this operation.