Commit 9fc058b7 authored by Simon Peyton Jones's avatar Simon Peyton Jones
Browse files

Add a new category of "eyeball" tests

These tests are hard to do automatically, but they record examples that 
provoked changes to the optimiser.  Each one has notes that says what you
should expect to see!
parent 4851699c
TOP=../../..
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
These tests are hard to test automatically, but
they are intended to let you eyeball the results.
Often they are referred to from comments in the
source code.
{-# OPTIONS -fglasgow-exts -O -ddump-stranal #-}
module Foo(foo) where
foo :: Int -> Int
foo n = baz (n+1) (bar1 n)
{-# NOINLINE bar1 #-}
bar1 n = 1 + bar n
bar :: Int -> Int
{-# NOINLINE bar #-}
{-# RULES
"bar/foo" forall n. bar (foo n) = n
#-}
bar n = n-1
baz :: Int -> Int -> Int
{-# INLINE [0] baz #-}
baz m n = m
{- Ronam writes (Feb08)
Note that bar becomes dead as soon as baz gets inlined. But strangely,
the simplifier only deletes it after full laziness and CSE. That is, it
is not deleted in the phase in which baz gets inlined. In fact, it is
still there after w/w and the subsequent simplifier run. It gets deleted
immediately if I comment out the rule.
I stumbled over this when I removed one simplifier run after SpecConstr
(at the moment, it runs twice at the end but I don't think that should
be necessary). With this change, the original version of a specialised
loop (the one with the rules) is not longer deleted even if it isn't
used any more. I'll reenable the second simplifier run for now but
should this really be necessary?
No, it should not be necessary. A refactoring in OccurAnal makes
this work right. Look at the simplifier output just before strictness
analysis; there should be a binding for 'foo', but for nothing else.
-}
{-# OPTIONS_GHC -fglasgow-exts -O -ddump-simpl #-}
module Roman where
import Control.Monad.ST
newtype T s a = T { unT :: Int -> ST s a }
instance Monad (T s) where
return = T . const . return
T p >>= f = T $ \i -> do { x <- p i
; unT (f x) i }
myIndex :: T s Int
{-# INLINE myIndex #-}
myIndex = T return
foo :: T s Int
foo = do { x <- myIndex
; return (x + 1) }
{- At one stage we got code looking like this:
U.a3 =
\ (@ s_a8E) (i_shA :: GHC.Base.Int) (eta_shB :: GHC.Prim.State# s_a8E) ->
case ((((U.myIndex @ s_a8E)
`cast` ...)
i_shA)
`cast` ...)
eta_shB
of wild_si5 { (# new_s_shF, r_shG #) -> ...
U.foo :: forall s_a5S. U.T s_a5S GHC.Base.Int
U.foo = U.a3 `cast` ...
The point is that myIndex should be inlined, else code is bad -}
\ No newline at end of file
{-# OPTIONS -fglasgow-exts -O -dshow-passes #-}
module Foo where
import GHC.Base
foo :: Int -> Int
foo (I# n#) = bar i i
where i# = n# +# 1#
i = I# i#
bar :: Int -> Int -> Int
{-# INLINE [0] bar #-}
bar _ n = n
{- The trouble here was
*** Simplify:
Result size = 25
Result size = 25
Result size = 25
Result size = 25
Result size = 25
*** Simplify:
Result size = 25
Result size = 25
Result size = 25
Result size = 25
Result size = 25
etc.
The reason was this:
x = n# +# 1#
i = I# x
Being an unboxed value, we were treating the argument context of x
as intersting, and hence inlining x in the arg of I#. But then we just
float it out again, giving an infinite loop.
-}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment