Use the more efficient unsafeShiftR instead of shiftR when base >= 4.5 #71

wants to merge 1 commit into


None yet
3 participants

basvandijk commented Mar 6, 2012

I may commit this myself when I have done some benchmarks. But I think this will improve performance a bit.

@ghost ghost assigned basvandijk Mar 6, 2012


bos commented Mar 6, 2012

In my experience with recent versions of GHC, the compiler usually spots shifts by small constants and does an unchecked shift. @tibbe, does this match what you've seen?

In any case, look at the generated Core before you worry about benchmarking. You may find that your change makes no difference at all.


tibbe commented Mar 6, 2012

Like @bos said, I'd start by looking at the core. IIRC if the shift amount is constant, GHC will generate good code. What shiftR does, and what is sometimes bad, is that it introduces a branch like so:

-- | Shift the argument right (signed) by the specified number of bits
-- (which must be non-negative).
iShiftRA# :: Int# -> Int# -> Int#
a `iShiftRA#` b | b >=# WORD_SIZE_IN_BITS# = if a <# 0# then (-1#) else 0#
                | otherwise                = a `uncheckedIShiftRA#` b

The reason it does so is that the underlying assembly instructions for shifts are undefined for shift amounts larger than the WORD_SIZE_IN_BITS and whoever designed shiftR thought safety was more important than speed. With inlining shiftR should be equivalent to unsafeShiftR, if the shift amount is known.

@bos bos closed this May 17, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment