12

我有一段 Haskell 代码,如下所示:

fst . f $ (Z :. i `div` 2)

Z:.取自Repa库,定义如下:

data Z = Z deriving (Show, Read, Eq, Ord)
infixl 3 :. 
data tail :. head = !tail :. !head deriving (Show, Read, Eq, Ord)

表达式 right$定义了一个数组索引,而 whilef是一个接受该索引并返回一对的函数。这编译为以下核心:

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
}

对我来说,中间 case 语句(带有 as scrutinee 的语句)似乎很明显(也许是错误的># x_s32E 0)是多余的,因为两个分支是相同的。我能做些什么来摆脱它吗?我使用 Repa 文档中推荐的 GHC 选项编译我的代码:-O2 -Odph -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000

4

1 回答 1

12

事实上,这两个分支case ># x_s32E 0 of是相同的,因此这case是多余的。在两个分支变得相同之后,似乎case没有运行相同分支的 -elimination - 可能值得一个错误报告。这个可能是相关的,但由于为负除数生成的核心很好,我提交了一个新的错误

使用更简单的quot- 如果i不能合法地否定 - 直接映射到机器除法运算符使代码更简单,因此不需要为此生成分支。

于 2012-10-30T14:16:13.157 回答