什么 GHC 优化负责复制 case 表达式?
What GHC optimization is responsible for duplicating case expressions?
给定以下代码:
{-# OPTIONS_GHC -funbox-strict-fields #-}
module Test where
data X = X !Int !Int
test (X a b) (X c d) = X (max a c) (max b d)
GHC 在优化编译时生成这个内核(重命名以便于阅读):
test
test =
\ u v ->
case u of x { X y z ->
case v of c { X d e ->
case tagToEnum# (<=# y d) of _ {
False ->
case tagToEnum# (<=# z e) of _ {
False -> x;
True -> X y e
};
True ->
case tagToEnum# (<=# z e) of _ {
False -> X d z;
True -> c
}
}
}
}
请注意 GHC 如何生成总共 4 个不同的代码路径。通常,代码路径的数量随着条件的数量呈指数增长。
什么 GHC 优化导致了这种行为?是否有控制此优化的标志?在我的例子中,这会产生巨大的代码膨胀,并且由于深层嵌套的 case 表达式使得核心转储非常难以阅读。
经过一些研究,我发现对此负责的优化是所谓的 "case-of-case" 转换,GHC 大概在简化器中执行此操作,因此无法将其停用(因为对于很多 GHC 所做的事情,简化器是 GHC 优化管道的一个组成部分。
以下 link 解释了 case of case 如何导致重复:http://lambda.jstolarek.com/2013/01/taking-magic-out-of-ghc-or-tracing-compilation-by-transformation/
具体来说,案例分析变成了这样:
case (
case C of
B1 -> F1
B2 -> F2
) of
A1 -> E1
A2 -> E2
进入以下:
case C of
B1 -> case F1 of
A1 -> E1
A2 -> E2
B2 -> case F2 of
A1 -> E1
A2 -> E2
外壳已被复制并推入分支。
给定以下代码:
{-# OPTIONS_GHC -funbox-strict-fields #-}
module Test where
data X = X !Int !Int
test (X a b) (X c d) = X (max a c) (max b d)
GHC 在优化编译时生成这个内核(重命名以便于阅读):
test
test =
\ u v ->
case u of x { X y z ->
case v of c { X d e ->
case tagToEnum# (<=# y d) of _ {
False ->
case tagToEnum# (<=# z e) of _ {
False -> x;
True -> X y e
};
True ->
case tagToEnum# (<=# z e) of _ {
False -> X d z;
True -> c
}
}
}
}
请注意 GHC 如何生成总共 4 个不同的代码路径。通常,代码路径的数量随着条件的数量呈指数增长。
什么 GHC 优化导致了这种行为?是否有控制此优化的标志?在我的例子中,这会产生巨大的代码膨胀,并且由于深层嵌套的 case 表达式使得核心转储非常难以阅读。
经过一些研究,我发现对此负责的优化是所谓的 "case-of-case" 转换,GHC 大概在简化器中执行此操作,因此无法将其停用(因为对于很多 GHC 所做的事情,简化器是 GHC 优化管道的一个组成部分。
以下 link 解释了 case of case 如何导致重复:http://lambda.jstolarek.com/2013/01/taking-magic-out-of-ghc-or-tracing-compilation-by-transformation/
具体来说,案例分析变成了这样:
case (
case C of
B1 -> F1
B2 -> F2
) of
A1 -> E1
A2 -> E2
进入以下:
case C of
B1 -> case F1 of
A1 -> E1
A2 -> E2
B2 -> case F2 of
A1 -> E1
A2 -> E2
外壳已被复制并推入分支。