【发布时间】:2011-05-07 09:24:20
【问题描述】:
给定程序:
import Debug.Trace
main = print $ trace "hit" 1 + trace "hit" 1
如果我使用ghc -O(7.0.1 或更高版本)编译,我会得到输出:
hit
2
即GHC 使用通用子表达式消除 (CSE) 将我的程序重写为:
main = print $ let x = trace "hit" 1 in x + x
如果我用-fno-cse 编译,那么我看到hit 出现了两次。
是否可以通过修改程序来避免 CSE?是否有任何子表达式 e 我可以保证 e + e 不会被 CSE 处理?我知道lazy,但找不到任何旨在抑制 CSE 的东西。
这个问题的背景是cmdargs库,CSE破库的地方(由于库中的杂质)。一种解决方案是让库的用户指定-fno-cse,但我更愿意修改库。
【问题讨论】:
-
嗯,长镜头,但这提醒我,我想尝试以某种方式使assert magic 用户可见。如果事实证明这是可能的,它也可以充当一个标签,防止 GHC 对特定的函数调用进行 CSE 处理。
-
@Peter:我确实尝试过 assert 的东西,但这需要
-fno-ignore-asserts才能工作。 -
(due to impurity in the library)。显然,由于这样做破坏了 Haskell 的语义,编译器会感到困惑。有没有办法以编译器可以理解的方式将代码重构为引用透明?例如。 ST monad 还是让它变得纯粹? -
你使用了 unsafePerformIO,你得到了你应得的。
-
@Don Stewart:这用于从用户代码中提取
opt "example"之类的注释(参见here)。由于用户代码几乎可以是任何东西,因此必须通过设计打破引用透明度。一个非常酷的 hack,但非常脆弱。
标签: optimization compiler-construction haskell ghc