<commit_before>%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section[SpecConstr]{Specialise over constructors}

\begin{code}
-- The above warning supression flag is a temporary kludge.
-- While working on this module you are encouraged to remove it and fix
-- any warnings in the module. See
--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
-- for details

module SpecConstr(
	specConstrProgram, SpecConstrAnnotation(..)
    ) where

#include "HsVersions.h"

import CoreSyn
import CoreSubst
import CoreUtils
import CoreUnfold	( couldBeSmallEnoughToInline )
import CoreFVs 		( exprsFreeVars )
import CoreMonad
import HscTypes         ( ModGuts(..) )
import WwLib		( mkWorkerArgs )
import DataCon		( dataConTyCon, dataConRepArity, dataConUnivTyVars )
import TyCon            ( TyCon )
import Literal          ( literalType )
import Coercion	
import Rules
import Type		hiding( substTy )
import Id
import MkId		( mkImpossibleExpr )
import Var
import VarEnv
import VarSet
import Name
import DynFlags		( DynFlags(..) )
import StaticFlags	( opt_PprStyle_Debug )
import StaticFlags	( opt_SpecInlineJoinPoints )
import BasicTypes	( Activation(..) )
import Maybes		( orElse, catMaybes, isJust, isNothing )
import NewDemand
import DmdAnal		( both )
import Serialized       ( deserializeWithData )
import Util
import UniqSupply
import Outputable
import FastString
import UniqFM
import qualified LazyUniqFM as L
import MonadUtils
import Control.Monad	( zipWithM )
import Data.List
import Data.Data        ( Data, Typeable )
\end{code}

-----------------------------------------------------
			Game plan
-----------------------------------------------------

Consider
	drop n []     = []
	drop 0 xs     = []
	drop n (x:xs) = drop (n-1) xs

After the first time round, we could pass n unboxed.  This happens in
numerical code too.  Here's what it looks like in Core:

	drop n xs = case xs of
		      []     -> []
		      (y:ys) -> case n of 
				  I# n# -> case n# of
					     0 -> []
					     _ -> drop (I# (n# -# 1#)) xs

Notice that the recursive call has an explicit constructor as argument.
Noticing this, we can make a specialised version of drop
	
	RULE: drop (I# n#) xs ==> drop' n# xs

	drop' n# xs = let n = I# n# in ...orig RHS...

Now the simplifier will apply the specialisation in the rhs of drop', giving
<commit_msg>Fix the build with GHC 6.8<commit_after>%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section[SpecConstr]{Specialise over constructors}

\begin{code}
-- The above warning supression flag is a temporary kludge.
-- While working on this module you are encouraged to remove it and fix
-- any warnings in the module. See
--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
-- for details

module SpecConstr(
	specConstrProgram, SpecConstrAnnotation(..)
    ) where

#include "HsVersions.h"

import CoreSyn
import CoreSubst
import CoreUtils
import CoreUnfold	( couldBeSmallEnoughToInline )
import CoreFVs 		( exprsFreeVars )
import CoreMonad
import HscTypes         ( ModGuts(..) )
import WwLib		( mkWorkerArgs )
import DataCon		( dataConTyCon, dataConRepArity, dataConUnivTyVars )
import TyCon            ( TyCon )
import Literal          ( literalType )
import Coercion	
import Rules
import Type		hiding( substTy )
import Id
import MkId		( mkImpossibleExpr )
import Var
import VarEnv
import VarSet
import Name
import DynFlags		( DynFlags(..) )
import StaticFlags	( opt_PprStyle_Debug )
import StaticFlags	( opt_SpecInlineJoinPoints )
import BasicTypes	( Activation(..) )
import Maybes		( orElse, catMaybes, isJust, isNothing )
import NewDemand
import DmdAnal		( both )
import Serialized       ( deserializeWithData )
import Util
import UniqSupply
import Outputable
import FastString
import UniqFM
import qualified LazyUniqFM as L
import MonadUtils
import Control.Monad	( zipWithM )
import Data.List
#if __GLASGOW_HASKELL__ > 609
import Data.Data        ( Data, Typeable )
#else
import Data.Generics    ( Data, Typeable )
#endif
\end{code}

-----------------------------------------------------
			Game plan
-----------------------------------------------------

Consider
	drop n []     = []
	drop 0 xs     = []
	drop n (x:xs) = drop (n-1) xs

After the first time round, we could pass n unboxed.  This happens in
numerical code too.  Here's what it looks like in Core:

	drop n xs = case xs of
		      []     -> []
		      (y:ys) -> case n of 
				  I# n# -> case n# of
					     0 -> []
					     _ -> drop (I# (n# -# 1#)) xs

Notice that the recursive call has an explicit constructor as argument.
Noticing this, we can make a specialised version of drop
	
	RULE: drop (I# n#) xs ==> drop' n# xs

	drop' n# xs = let n = I# n# in ...orig RHS...

Now the simplifier will apply the specialisation in the rhs of drop', giving

{'fraction_non_alphanumeric': 0.1250775273930122, 'fraction_numerical': 0.005995451726276618, 'mean_word_length': 2.776736924277908, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3932734', 'n_tokens_mistral': 1605, 'n_tokens_neox': 1500, 'n_words': 544}