如何判断 GHC 中是否发生公共子表达式消除?

How to tell that common subexpression elimination is happening or not in GHC?

假设我有一个像这样天真的实现的函数:

quadratic a b c = (ans1, ans2)
  where
    ans1 = ((-b) + sqrt (b * b - 4 * a * c)) / (2 * a)
    ans2 = ((-b) - sqrt (b * b - 4 * a * c)) / (2 * a)

有多个相同的子表达式。如果不阅读核心,我怎么能知道公共子表达式消除是否正在发生,以及它的哪些部分?

使用 trace 可能会告诉您如 this SO question 中所示。

import Debug.Trace

quadratic a b c = (ans1, ans2)
  where
    ans1 = ((-b) + tr1 (sqrt (b * b - 4 * a * c))) / (2 * a)
    ans2 = ((-b) - tr2 (sqrt (b * b - 4 * a * c))) / (2 * a)
    tr1 = trace "ans1"
    tr2 = trace "ans2"

main = print $ quadratic 1 10 3

-O2-O3 编译它会在跟踪输出中同时显示 ans1ans2,表明 GHC 没有执行 CSE。你得到相似的 如果你在两个地方都使用 tr1 结果。

Haskell Wiki 提到 GHC 仅在有限的范围内执行 CSE 情况 - (link) - 建议您执行 如果您想确保它发生,请自己动手。