Removing "case" with duplicate branches from Haskell's Core
Asked Answered
C

1

12

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

Cumae answered 30/10, 2012 at 13:18 Comment(2)
Unless i can acutally be legitimately negative, you should use quot instead of div. That should fix it.Picul
You're correct - this fixes my problem. Can you post that comment as an answer so I can accept it?Cumae
P
12

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.

Picul answered 30/10, 2012 at 14:16 Comment(1)
Thanks! I'm not sure whether this is a bug in GHC or my incorrect usage of compiler options. I'll try to reduce this problem to minimal working example and if it persists I'll fill a bug.Cumae

© 2022 - 2024 — McMap. All rights reserved.