-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hint to GHC that indices are to be used strictly #485
Conversation
5de58ff
to
9f21834
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great find! I think slice
/unsafeSlice
would benefit from the same treatment as well.
P.S. Out of curiosity I looking into GHC's timing information. This change reduced allocation by simplifier by about 1e-3 when compiling unboxed vectors.
@@ -700,21 +700,25 @@ exchange v i x = checkIndex Bounds i (length v) $ unsafeExchange v i x | |||
-- | Yield the element at the given position. No bounds checks are performed. | |||
unsafeRead :: (PrimMonad m, MVector v a) => v (PrimState m) a -> Int -> m a | |||
{-# INLINE unsafeRead #-} | |||
unsafeRead v i = checkIndex Unsafe i (length v) | |||
unsafeRead v !i = checkIndex Unsafe i (length v) | |||
$ stToPrim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I 100% agree with this change, but unfortunately it means the following lines are no longer indented correctly with respect to the =
. Is that something that can be fixed as part of this PR?
|
||
-- | Replace the element at the given position. No bounds checks are performed. | ||
unsafeWrite :: (PrimMonad m, MVector v a) => v (PrimState m) a -> Int -> a -> m () | ||
{-# INLINE unsafeWrite #-} | ||
unsafeWrite v i x = checkIndex Unsafe i (length v) | ||
unsafeWrite v !i x = checkIndex Unsafe i (length v) | ||
$ stToPrim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
$ stToPrim | ||
$ basicUnsafeWrite v i x | ||
|
||
-- | Modify the element at the given position. No bounds checks are performed. | ||
unsafeModify :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> a) -> Int -> m () | ||
{-# INLINE unsafeModify #-} | ||
unsafeModify v f i = checkIndex Unsafe i (length v) | ||
unsafeModify v f !i = checkIndex Unsafe i (length v) | ||
$ stToPrim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
@@ -725,7 +729,7 @@ unsafeModify v f i = checkIndex Unsafe i (length v) | |||
-- @since 0.12.3.0 | |||
unsafeModifyM :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> m a) -> Int -> m () | |||
{-# INLINE unsafeModifyM #-} | |||
unsafeModifyM v f i = checkIndex Unsafe i (length v) | |||
unsafeModifyM v f !i = checkIndex Unsafe i (length v) | |||
$ stToPrim . basicUnsafeWrite v i =<< f =<< stToPrim (basicUnsafeRead v i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
@Bodigrim I extended same treatment to If you're fine with this I'd like to merge this PR |
@Shimuuar sure, go ahead. |
'basicUnsafe{Read/Write/IndexM}' are class members and, unless a call site was already specialised to a specific vector instance, GHC has no clue that the index is most certainly to be used eagerly. Bang before the index provides this vital for optimizer information.
We have longish comment which is referenced from multiple places in source code. GHC notes seems good option for that
96ee359
to
e13cb00
Compare
basicUnsafe{Read/Write/IndexM}
are class members and, unless a call site was already specialised to a specific vector instance, GHC has no clue that the index is most certainly to be used eagerly. Bang before the index provides this vital for optimizer information.I've been recently looking at Core for programs, where vectors did not specialise to a specific instance for one reason or another. It's really horrible: even if a specific instance remains unknown, we should tell GHC that passing boxed indices around is not OK.