Skip to content

SpecConstr duplicating computations

In some (very rare) cases, SpecConstr can actually duplicate let bindings.

When SpecConstr sees something like

let tuple = (let x = expensive in x, simple)
case tuple of
  (a,b) -> a + a

it records the value of tuple, and replaces the case with

(let x = expensive in x) + (let x = expensive in x)

Usually we wouldn't notice this, because the Simplifier would let-float expensive out of the tuple before SpecConstr runs. In some cases though, the tuple constructor will only be exposed after specialisation happens.

To test, compile TSpecConstr_DoubleInline with

ghc TSpecConstr_DoubleInline.hs -O2 -fspec-constr -dverbose-core2core -fforce-recomp -dppr-case-as-let -dsuppress-all  | less

and search for the SpecConstr pass. The first specialisation is

$srecursive_sf3
$srecursive_sf3 =
  \ sc_seR sc_seS sc_seT sc_seU ->
    let {
      a'_sep
      a'_sep =
        (let { I# x_adP ~ _ <- expensive sc_seR } in I# (*# x_adP 2),
         sc_seR) } in
    let {
      ds_seq
      ds_seq =
        recursive
          (: sc_seR (: sc_seR (: sc_seS sc_seT)))
          (sc_seR,
           let { I# x_adP ~ _ <- expensive sc_seR } in I# (*# x_adP 2)) } in
    (let { (p_XdA, q_Xdu) ~ _ <- ds_seq } in
     let { I# x_ae7 ~ _ <- p_XdA } in
     let { I# y_aeb ~ _
     <- let { I# x_adP ~ _ <- expensive sc_seR } in I# (*# x_adP 2)
     } in
     I# (+# x_ae7 y_aeb),
     let { (p_adg, q_XdA) ~ _ <- ds_seq } in
     let { I# x_ae7 ~ _ <- q_XdA } in
     let { I# y_aeb ~ _ <- sc_seR } in I# (+# x_ae7 y_aeb))

With three calls to expensive. If you look at the -ddump-prep, one of the calls is simplified out, but there is still one too many at the end.

This is happening on at least 7.4.1 and head.

Trac metadata
Trac field Value
Version
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information