I have a piece of Haskell code that looks like this:
fst . f $ (Z :. i `div` 2)
Z
and :.
are taken from Repa library and are defined like this:
data Z = Z deriving (Show, Read, Eq, Ord)
infixl 3 :.
data tail :. head = !tail :. !head deriving (Show, Read, Eq, Ord)
The expression right of $
defines an array index, while f
is a function that takes that index and returns a pair. This compiles to following Core:
case f_a2pC
(case ># x_s32E 0 of _ {
False ->
case <# x_s32E 0 of _ {
False -> :. Z (I# (quotInt# x_s32E 2));
True -> :. Z (I# (-# (quotInt# (+# x_s32E 1) 2) 1))
};
True ->
case <# x_s32E 0 of _ {
False -> :. Z (I# (quotInt# x_s32E 2));
True -> :. Z (I# (-# (quotInt# (+# x_s32E 1) 2) 1))
}
})
of _ { (x1_a2Cv, _) ->
x1_a2Cv
}
To me it seems obvious (perhaps incorrectly) that the middle case statement (the one with ># x_s32E 0
as scrutinee) is redundant, as both branches are identical. Is there anything I can do to get rid of it? I compile my code using GHC options recommended in Repa documentation: -O2 -Odph -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000
Indeed the two branches of the case ># x_s32E 0 of
are identical, and hence that case
is redundant. It seems that the case
-elimination for identical branches isn't run after both branches became identical - probably worth a bug report. This one may be pertinent, but since the core generated for negative divisors is good, I filed a new bug.
Using the simpler quot
- if i
cannot legitimately negative - that directly maps to the machine division operator makes the code simpler, so that no branches need to be generated for that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With