[GHC] #5129: "evaluate" optimized away

GHC ghc-devs at haskell.org
Tue Mar 20 16:36:21 UTC 2018


#5129: "evaluate" optimized away
-------------------------------------+-------------------------------------
        Reporter:  dons              |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.4.2
       Component:  Compiler          |              Version:  7.0.3
      Resolution:                    |             Keywords:  seq, evaluate
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Incorrect result  |  Unknown/Multiple
  at runtime                         |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #13930            |  Differential Rev(s):  Phab:D615,
       Wiki Page:                    |  Phab:D4514
-------------------------------------+-------------------------------------

Comment (by simonpj):

 > One way to fix this if we want to keep seq# as effect-free is avoiding
 inlining evaluate with {-# NOINLINE evaluate #-}.

 I'm very unhappy with this.  It just sweeps the problem under the rug.
 What if the ''user'' wrote
 {{{
 ..(case (seq# (throwIfNegative (I# -1#)) s) of <alts>)...
 }}}
 We don't want to discard the case.

 Moreover we shouldn't.  The "plain-seq" transformation in `Simplify.hs`
 looks like
 {{{
   | is_plain_seq
   , exprOkForSideEffects scrut
   = ...
 }}}
 Well, should `exprOkForSideEffects` return False (as it does) for `seq#
 (throwIfNegative (I# -1#)) s`?  The comments in `CoreUtils` say
 {{{
 -- Precisely, exprOkForSpeculation returns @True@ iff:
 --  a) The expression guarantees to terminate,
 --  b) soon,
 --  c) without causing a write side effect (e.g. writing a mutable
 variable)
 --  d) without throwing a Haskell exception
 --  e) without risking an unchecked runtime exception (array out of
 bounds,
 --     divide by zero)
 --
 -- For @exprOkForSideEffects@ the list is the same, but omitting (e).
 }}}
 So clearly `exprOkForSideEffects` should return False!  That's the real
 bug!

 Why does it return True?  Because in `arg_ok` in `CoreUtils.app_ok` we see
 {{{
     arg_ok (Anon ty) arg        -- A term argument
        | isUnliftedType ty = expr_ok primop_ok arg
        | otherwise         = True  -- See Note [Primops with lifted
 arguments]
 }}}
 Uh oh!  It never even looks at the argument `throwIfNegative minus_one`!

 I think that `seq#` is exception to the reasoning in `Note [Primops with
 lifted arguments]`, which says that a primop doesn't evaluate a lifted
 argument.  In effect `seq#` does.

 So in the `PrimOpId` case of `app_ok` I think we want to add
 {{{
         | SeqOp <- op
         -> all (expr_ok primop_ok) args
 }}}
 And sure enough that fixes it.

 I'll make a patch.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/5129#comment:33>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list