[Haskell-cafe] quotRem and divMod

Daniel Fischer daniel.is.fischer at googlemail.com
Tue Jan 29 12:39:37 CET 2013


On Tuesday 29 January 2013, 03:27:41, Artyom Kazak wrote:
> Hi!
> 
> I’ve always thought that `quotRem` is faster than `quot` + `rem`, since
> both `quot` and `rem` are just "wrappers" that compute both the quotient
> and the remainder and then just throw one out. However, today I looked
> into the implementation of `quotRem` for `Int32` and found out that it’s
> not true:
> 
>      quotRem x@(I32# x#) y@(I32# y#)
> 
>          | y == 0                     = divZeroError
>          | x == minBound && y == (-1) = overflowError
>          | otherwise                  = (I32# (narrow32Int# (x# `quotInt#`
> 
> y#)),
>                                          I32# (narrow32Int# (x# `remInt#`
> y#)))
> 
> Why? The `DIV` instruction computes both, doesn’t it? And yet it’s being
> performed twice here. Couldn’t one of the experts clarify this bit?

It's not necessarily performed twice.

func a b = case a `quotRem` b of
             (q, r) -> q+r

produces

    idivq 8(%rbp)
    movq %rax,%rbx
    movq $GHC.Int.I32#_con_info,-8(%r12)
    movslq %edx,%rax
    movslq %ebx,%rbx
    addq %rax,%rbx

as the relevant part of the assembly, with only one idivq instruction.

I don't know whether you can rely on the code generator emitting only one 
division instruction in all cases, but in simple cases, it does (on x86_64, at 
least).

Cheers,
Daniel



More information about the Haskell-Cafe mailing list