Fix a nasty continuation-duplication bug
authorsimonpj@microsoft.com <unknown>
Thu, 18 May 2006 16:36:17 +0000 (16:36 +0000)
committersimonpj@microsoft.com <unknown>
Thu, 18 May 2006 16:36:17 +0000 (16:36 +0000)
commitb812bfb914a0164f5ce3b206cb9769dc70253374
tree1d66ef039d8583da5297f9ecb242531b34b8ee67
parent647546977c3b6869c027b33c3de841ff13afc912
Fix a nasty continuation-duplication bug

For a long-time mkDupableCont has had a bug that allows it to duplicate
an arbitrary continuation, which it should not do, of course.

The bug was that in the Select case of mkDupableCont we were calling
prepareCaseCont, which did not duplicate the continuation if there is
but a single alternative.  This is quite right in the case of the call
in rebuildCase, but quite wrong in mkDupableCont.

The bug manifest as follows. In the expression
f (case ... of { ..several alts.. })
(when f is strict), we should transform to
f (...transformed arg...)
The application of f should not be pushed down (see notes with the
ArgOf case of mkDupableCont.  But that was not happening in an example
like this (see how the call to f is pushed inwards).

f (a `div` abs (b::Int))
--->
    case b_afT of wild_aHa { GHC.Base.I# x_aHc ->
    let {
      $j_sIe :: GHC.Prim.Int# -> GHC.Base.Int
      []
      $j_sIe =
\ (ds1_aHr [Nothing OneShot] :: GHC.Prim.Int#) ->
  Foo7.f
    (case ds1_aHr of ds2_aHq {
       __DEFAULT ->
 case a_afS of wild1_aHM { GHC.Base.I# x_aHO ->
 GHC.Base.I# (GHC.Base.divInt# x_aHO ds2_aHq)
 };
       0 -> GHC.Err.divZeroError @ GHC.Base.Int
     })
    } in
      case GHC.Prim.>=# x_aHc 0 of wild1_aHe [Dead Nothing] {
GHC.Base.False ->
  let {
    ds1_aHr :: GHC.Prim.Int#
    []
    ds1_aHr = GHC.Prim.negateInt# x_aHc
  } in  $j_sIe ds1_aHr;
GHC.Base.True -> $j_sIe x_aHc
      }
    }
compiler/simplCore/Simplify.lhs